Home | History | Annotate | Download | only in settings
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.camera.settings;
     18 
     19 import android.content.ContentResolver;
     20 import android.graphics.ImageFormat;
     21 
     22 import com.android.camera.debug.Log;
     23 import com.android.camera.device.CameraId;
     24 import com.android.camera.exif.Rational;
     25 import com.android.camera.one.OneCamera;
     26 import com.android.camera.one.OneCamera.Facing;
     27 import com.android.camera.one.OneCameraAccessException;
     28 import com.android.camera.one.OneCameraCharacteristics;
     29 import com.android.camera.one.OneCameraManager;
     30 import com.android.camera.util.GservicesHelper;
     31 import com.android.camera.util.Size;
     32 
     33 import com.google.common.base.Preconditions;
     34 
     35 import java.util.List;
     36 
     37 /**
     38  * Handles the picture resolution setting stored in SharedPreferences keyed by
     39  * Keys.KEY_PICTURE_SIZE_BACK and Keys.KEY_PICTURE_SIZE_FRONT.
     40  */
     41 public class ResolutionSetting {
     42     private static final Log.Tag TAG = new Log.Tag("ResolutionSettings");
     43 
     44     private final SettingsManager mSettingsManager;
     45     private final OneCameraManager mOneCameraManager;
     46     private final String mResolutionBlackListBack;
     47     private final String mResolutionBlackListFront;
     48 
     49     public ResolutionSetting(SettingsManager settingsManager,
     50             OneCameraManager oneCameraManager,
     51             ContentResolver contentResolver) {
     52         mSettingsManager = settingsManager;
     53         mOneCameraManager = oneCameraManager;
     54 
     55         mResolutionBlackListBack = GservicesHelper.getBlacklistedResolutionsBack(contentResolver);
     56         mResolutionBlackListFront = GservicesHelper.getBlacklistedResolutionsFront(contentResolver);
     57     }
     58 
     59     /**
     60      * Changes the picture size settings for the cameras with specified facing.
     61      * Pick the largest picture size with the specified aspect ratio.
     62      *
     63      * @param cameraId The specific camera device.
     64      * @param aspectRatio The chosen aspect ratio.
     65      */
     66     public void setPictureAspectRatio(CameraId cameraId, Rational aspectRatio)
     67             throws OneCameraAccessException {
     68         OneCameraCharacteristics cameraCharacteristics =
     69                 mOneCameraManager.getOneCameraCharacteristics(cameraId);
     70 
     71         Facing cameraFacing = cameraCharacteristics.getCameraDirection();
     72 
     73         // Pick the largest picture size with the selected aspect ratio and save
     74         // the choice for front camera.
     75         final String pictureSizeSettingKey = cameraFacing == OneCamera.Facing.FRONT ?
     76                 Keys.KEY_PICTURE_SIZE_FRONT : Keys.KEY_PICTURE_SIZE_BACK;
     77         final String blacklist = cameraFacing == OneCamera.Facing.FRONT ? mResolutionBlackListFront
     78                 : mResolutionBlackListBack;
     79 
     80         // All resolutions supported by the camera.
     81         List<Size> supportedPictureSizes = cameraCharacteristics
     82                 .getSupportedPictureSizes(ImageFormat.JPEG);
     83 
     84         // Filter sizes which we are showing to the user in settings.
     85         // This might also add some new resolution we support on some devices
     86         // non-natively.
     87         supportedPictureSizes = ResolutionUtil.getDisplayableSizesFromSupported(
     88                 supportedPictureSizes, cameraFacing == OneCamera.Facing.BACK);
     89 
     90         // Filter the remaining sizes through our backlist.
     91         supportedPictureSizes = ResolutionUtil.filterBlackListedSizes(supportedPictureSizes,
     92                 blacklist);
     93 
     94         final Size chosenPictureSize =
     95                 ResolutionUtil.getLargestPictureSize(aspectRatio, supportedPictureSizes);
     96         mSettingsManager.set(
     97                 SettingsManager.SCOPE_GLOBAL,
     98                 pictureSizeSettingKey,
     99                 SettingsUtil.sizeToSettingString(chosenPictureSize));
    100     }
    101 
    102     /**
    103      * Reads the picture size setting for the cameras with specified facing.
    104      * This specifically avoids reading camera characteristics unless the size
    105      * is blacklisted or is not cached to prevent a crash.
    106      */
    107     public Size getPictureSize(CameraId cameraId, Facing cameraFacing)
    108             throws OneCameraAccessException {
    109         final String pictureSizeSettingKey = cameraFacing == OneCamera.Facing.FRONT ?
    110                 Keys.KEY_PICTURE_SIZE_FRONT : Keys.KEY_PICTURE_SIZE_BACK;
    111 
    112         Size pictureSize = null;
    113 
    114         String blacklist = "";
    115         if (cameraFacing == OneCamera.Facing.BACK) {
    116             blacklist = mResolutionBlackListBack;
    117         } else if (cameraFacing == OneCamera.Facing.FRONT) {
    118             blacklist = mResolutionBlackListFront;
    119         }
    120 
    121         // If there is no saved picture size preference or the saved on is
    122         // blacklisted., pick a largest size with 4:3 aspect
    123         boolean isPictureSizeSettingSet =
    124                 mSettingsManager.isSet(SettingsManager.SCOPE_GLOBAL, pictureSizeSettingKey);
    125         boolean isPictureSizeBlacklisted = false;
    126 
    127         // If a picture size is set, check whether it's blacklisted.
    128         if (isPictureSizeSettingSet) {
    129             pictureSize = SettingsUtil.sizeFromSettingString(
    130                     mSettingsManager.getString(SettingsManager.SCOPE_GLOBAL,
    131                             pictureSizeSettingKey));
    132             isPictureSizeBlacklisted = pictureSize == null ||
    133                     ResolutionUtil.isBlackListed(pictureSize, blacklist);
    134         }
    135 
    136         // Due to b/21758681, it is possible that an invalid picture size has
    137         // been saved to the settings. Therefore, picture size is set AND is not
    138         // blacklisted, but completely invalid. In these cases, need to take the
    139         // fallback, instead of the saved value. This logic should now save a
    140         // valid picture size to the settings and self-correct the state of the
    141         // settings.
    142         final boolean isPictureSizeFromSettingsValid = pictureSize != null &&
    143                 pictureSize.width() > 0 && pictureSize.height() > 0;
    144 
    145         if (!isPictureSizeSettingSet || isPictureSizeBlacklisted || !isPictureSizeFromSettingsValid) {
    146             final Rational aspectRatio = ResolutionUtil.ASPECT_RATIO_4x3;
    147 
    148             OneCameraCharacteristics cameraCharacteristics =
    149                     mOneCameraManager.getOneCameraCharacteristics(cameraId);
    150 
    151             final List<Size> supportedPictureSizes =
    152                     ResolutionUtil.filterBlackListedSizes(
    153                             cameraCharacteristics.getSupportedPictureSizes(ImageFormat.JPEG),
    154                             blacklist);
    155             final Size fallbackPictureSize =
    156                     ResolutionUtil.getLargestPictureSize(aspectRatio, supportedPictureSizes);
    157             mSettingsManager.set(
    158                     SettingsManager.SCOPE_GLOBAL,
    159                     pictureSizeSettingKey,
    160                     SettingsUtil.sizeToSettingString(fallbackPictureSize));
    161             pictureSize = fallbackPictureSize;
    162             Log.e(TAG, "Picture size setting is not set. Choose " + fallbackPictureSize);
    163             // Crash here if invariants are violated
    164             Preconditions.checkNotNull(fallbackPictureSize);
    165             Preconditions.checkState(fallbackPictureSize.width() > 0
    166                     && fallbackPictureSize.height() > 0);
    167         }
    168         return pictureSize;
    169     }
    170 
    171     /**
    172      * Obtains the preferred picture aspect ratio in terms of the picture size
    173      * setting.
    174      *
    175      * @param cameraId The specific camera device.
    176      * @return The preferred picture aspect ratio.
    177      * @throws OneCameraAccessException
    178      */
    179     public Rational getPictureAspectRatio(CameraId cameraId, Facing facing)
    180             throws OneCameraAccessException {
    181         Size pictureSize = getPictureSize(cameraId, facing);
    182         return new Rational(pictureSize.getWidth(), pictureSize.getHeight());
    183     }
    184 }
    185