package com.android.camera.settings;
+import android.content.ContentResolver;
+import android.graphics.ImageFormat;
+
import com.android.camera.debug.Log;
+import com.android.camera.device.CameraId;
import com.android.camera.exif.Rational;
import com.android.camera.one.OneCamera;
+import com.android.camera.one.OneCamera.Facing;
import com.android.camera.one.OneCameraAccessException;
import com.android.camera.one.OneCameraCharacteristics;
import com.android.camera.one.OneCameraManager;
+import com.android.camera.util.GservicesHelper;
import com.android.camera.util.Size;
-import android.graphics.ImageFormat;
+import com.google.common.base.Preconditions;
import java.util.List;
private static final Log.Tag TAG = new Log.Tag("ResolutionSettings");
private final SettingsManager mSettingsManager;
-
private final OneCameraManager mOneCameraManager;
+ private final String mResolutionBlackListBack;
+ private final String mResolutionBlackListFront;
- public ResolutionSetting(SettingsManager settingsManager, OneCameraManager oneCameraManager) {
+ public ResolutionSetting(SettingsManager settingsManager,
+ OneCameraManager oneCameraManager,
+ ContentResolver contentResolver) {
mSettingsManager = settingsManager;
mOneCameraManager = oneCameraManager;
+
+ mResolutionBlackListBack = GservicesHelper.getBlacklistedResolutionsBack(contentResolver);
+ mResolutionBlackListFront = GservicesHelper.getBlacklistedResolutionsFront(contentResolver);
}
/**
* Changes the picture size settings for the cameras with specified facing.
* Pick the largest picture size with the specified aspect ratio.
*
- * @param cameraFacing The specified direction that the camera is facing.
+ * @param cameraId The specific camera device.
* @param aspectRatio The chosen aspect ratio.
*/
- public void setPictureAspectRatio(OneCamera.Facing cameraFacing, Rational aspectRatio)
+ public void setPictureAspectRatio(CameraId cameraId, Rational aspectRatio)
throws OneCameraAccessException {
OneCameraCharacteristics cameraCharacteristics =
- mOneCameraManager.getCameraCharacteristics(cameraFacing);
+ mOneCameraManager.getOneCameraCharacteristics(cameraId);
+
+ Facing cameraFacing = cameraCharacteristics.getCameraDirection();
- // Pick the largest picture size with the selected aspect ratio and save the choice for front camera.
+ // Pick the largest picture size with the selected aspect ratio and save
+ // the choice for front camera.
final String pictureSizeSettingKey = cameraFacing == OneCamera.Facing.FRONT ?
Keys.KEY_PICTURE_SIZE_FRONT : Keys.KEY_PICTURE_SIZE_BACK;
- final List<Size> supportedPictureSizes =
- cameraCharacteristics.getSupportedPictureSizes(ImageFormat.JPEG);
+ final String blacklist = cameraFacing == OneCamera.Facing.FRONT ? mResolutionBlackListFront
+ : mResolutionBlackListBack;
+
+ // All resolutions supported by the camera.
+ List<Size> supportedPictureSizes = cameraCharacteristics
+ .getSupportedPictureSizes(ImageFormat.JPEG);
+
+ // Filter sizes which we are showing to the user in settings.
+ // This might also add some new resolution we support on some devices
+ // non-natively.
+ supportedPictureSizes = ResolutionUtil.getDisplayableSizesFromSupported(
+ supportedPictureSizes, cameraFacing == OneCamera.Facing.BACK);
+
+ // Filter the remaining sizes through our backlist.
+ supportedPictureSizes = ResolutionUtil.filterBlackListedSizes(supportedPictureSizes,
+ blacklist);
+
final Size chosenPictureSize =
ResolutionUtil.getLargestPictureSize(aspectRatio, supportedPictureSizes);
mSettingsManager.set(
/**
* Reads the picture size setting for the cameras with specified facing.
- *
- * @param cameraFacing The specified direction that the camera is facing.
- * @return The preferred picture size.
+ * This specifically avoids reading camera characteristics unless the size
+ * is blacklisted or is not cached to prevent a crash.
*/
- public Size getPictureSize(OneCamera.Facing cameraFacing) throws OneCameraAccessException {
+ public Size getPictureSize(CameraId cameraId, Facing cameraFacing)
+ throws OneCameraAccessException {
final String pictureSizeSettingKey = cameraFacing == OneCamera.Facing.FRONT ?
Keys.KEY_PICTURE_SIZE_FRONT : Keys.KEY_PICTURE_SIZE_BACK;
- /**
- * If there is no saved reference, pick a largest size with 4:3 aspect
- * ratio as a fallback.
- */
- final boolean isPictureSizeSettingSet =
+ Size pictureSize = null;
+
+ String blacklist = "";
+ if (cameraFacing == OneCamera.Facing.BACK) {
+ blacklist = mResolutionBlackListBack;
+ } else if (cameraFacing == OneCamera.Facing.FRONT) {
+ blacklist = mResolutionBlackListFront;
+ }
+
+ // If there is no saved picture size preference or the saved on is
+ // blacklisted., pick a largest size with 4:3 aspect
+ boolean isPictureSizeSettingSet =
mSettingsManager.isSet(SettingsManager.SCOPE_GLOBAL, pictureSizeSettingKey);
- if (!isPictureSizeSettingSet) {
+ boolean isPictureSizeBlacklisted = false;
+
+ // If a picture size is set, check whether it's blacklisted.
+ if (isPictureSizeSettingSet) {
+ pictureSize = SettingsUtil.sizeFromSettingString(
+ mSettingsManager.getString(SettingsManager.SCOPE_GLOBAL,
+ pictureSizeSettingKey));
+ isPictureSizeBlacklisted = pictureSize == null ||
+ ResolutionUtil.isBlackListed(pictureSize, blacklist);
+ }
+
+ // Due to b/21758681, it is possible that an invalid picture size has
+ // been saved to the settings. Therefore, picture size is set AND is not
+ // blacklisted, but completely invalid. In these cases, need to take the
+ // fallback, instead of the saved value. This logic should now save a
+ // valid picture size to the settings and self-correct the state of the
+ // settings.
+ final boolean isPictureSizeFromSettingsValid = pictureSize != null &&
+ pictureSize.width() > 0 && pictureSize.height() > 0;
+
+ if (!isPictureSizeSettingSet || isPictureSizeBlacklisted || !isPictureSizeFromSettingsValid) {
final Rational aspectRatio = ResolutionUtil.ASPECT_RATIO_4x3;
- final OneCameraCharacteristics cameraCharacteristics =
- mOneCameraManager.getCameraCharacteristics(cameraFacing);
+ OneCameraCharacteristics cameraCharacteristics =
+ mOneCameraManager.getOneCameraCharacteristics(cameraId);
+
final List<Size> supportedPictureSizes =
- cameraCharacteristics.getSupportedPictureSizes(ImageFormat.JPEG);
+ ResolutionUtil.filterBlackListedSizes(
+ cameraCharacteristics.getSupportedPictureSizes(ImageFormat.JPEG),
+ blacklist);
final Size fallbackPictureSize =
ResolutionUtil.getLargestPictureSize(aspectRatio, supportedPictureSizes);
mSettingsManager.set(
SettingsManager.SCOPE_GLOBAL,
pictureSizeSettingKey,
SettingsUtil.sizeToSettingString(fallbackPictureSize));
+ pictureSize = fallbackPictureSize;
Log.e(TAG, "Picture size setting is not set. Choose " + fallbackPictureSize);
+ // Crash here if invariants are violated
+ Preconditions.checkNotNull(fallbackPictureSize);
+ Preconditions.checkState(fallbackPictureSize.width() > 0
+ && fallbackPictureSize.height() > 0);
}
+ return pictureSize;
+ }
- /** Reads picture size setting from SettingsManager. */
- return SettingsUtil.sizeFromSettingString(
- mSettingsManager.getString(SettingsManager.SCOPE_GLOBAL, pictureSizeSettingKey));
+ /**
+ * Obtains the preferred picture aspect ratio in terms of the picture size
+ * setting.
+ *
+ * @param cameraId The specific camera device.
+ * @return The preferred picture aspect ratio.
+ * @throws OneCameraAccessException
+ */
+ public Rational getPictureAspectRatio(CameraId cameraId, Facing facing)
+ throws OneCameraAccessException {
+ Size pictureSize = getPictureSize(cameraId, facing);
+ return new Rational(pictureSize.getWidth(), pictureSize.getHeight());
}
-}
\ No newline at end of file
+}