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.content.Context;
21 
22 import com.android.camera.settings.SettingsUtil.CameraDeviceSelector;
23 import com.android.camera.settings.SettingsUtil.SelectedVideoQualities;
24 import com.android.camera.util.GservicesHelper;
25 import com.android.camera.util.Size;
26 import com.android.ex.camera2.portability.CameraAgentFactory;
27 import com.android.ex.camera2.portability.CameraDeviceInfo;
28 import com.google.common.base.Optional;
29 
30 import java.util.ArrayList;
31 import java.util.List;
32 
33 import javax.annotation.Nonnull;
34 import javax.annotation.ParametersAreNonnullByDefault;
35 
36 /**
37  * Loads the camera picture sizes that can be set by the user.
38  * <p>
39  * This class is compatible with pre-Lollipop since it uses the compatibility
40  * layer to access the camera metadata.
41  */
42 @ParametersAreNonnullByDefault
43 public class PictureSizeLoader {
44     /**
45      * Holds the sizes for the back- and front cameras which will be available
46      * to the user for selection form settings.
47      */
48     @ParametersAreNonnullByDefault
49     public static class PictureSizes {
50         public final List<Size> backCameraSizes;
51         public final List<Size> frontCameraSizes;
52         public final Optional<SelectedVideoQualities> videoQualitiesBack;
53         public final Optional<SelectedVideoQualities> videoQualitiesFront;
54 
PictureSizes(List<Size> backCameraSizes, List<Size> frontCameraSizes, Optional<SelectedVideoQualities> videoQualitiesBack, Optional<SelectedVideoQualities> videoQualitiesFront)55         PictureSizes(List<Size> backCameraSizes,
56                 List<Size> frontCameraSizes,
57                 Optional<SelectedVideoQualities> videoQualitiesBack,
58                 Optional<SelectedVideoQualities> videoQualitiesFront) {
59             this.backCameraSizes = backCameraSizes;
60             this.frontCameraSizes = frontCameraSizes;
61             this.videoQualitiesBack = videoQualitiesBack;
62             this.videoQualitiesFront = videoQualitiesFront;
63         }
64     }
65 
66     private final Context mContext;
67     private final ContentResolver mContentResolver;
68     private final CameraDeviceInfo mCameraDeviceInfo;
69     private final boolean mCachedOnly;
70 
71     /**
72      * Initializes a new picture size loader.
73      * <p>
74      * This constructor will default to using the camera devices if the size
75      * values were not found in cache.
76      *
77      * @param context used to load caches sizes from preferences.
78      */
PictureSizeLoader(Context context)79     public PictureSizeLoader(Context context) {
80         this(context, false);
81     }
82 
83     /**
84      * Initializes a new picture size loader.
85      *
86      * @param context used to load caches sizes from preferences.
87      * @param cachedOnly if set to true, this will only check the cache for
88      *            sizes. If the cache is empty, this will NOT attempt to open
89      *            the camera devices in order to obtain the sizes.
90      */
PictureSizeLoader(Context context, boolean cachedOnly)91     public PictureSizeLoader(Context context, boolean cachedOnly) {
92         mContext = context;
93         mContentResolver = context.getContentResolver();
94         mCameraDeviceInfo = CameraAgentFactory
95                 .getAndroidCameraAgent(context, CameraAgentFactory.CameraApi.API_1)
96                 .getCameraDeviceInfo();
97         mCachedOnly = cachedOnly;
98     }
99 
100     /**
101      * Computes the list of picture sizes that should be displayed by settings.
102      * <p>
103      * For this it will open the camera devices to determine the available
104      * sizes, if the sizes are not already cached. This is to be compatible with
105      * devices running Camera API 1.
106      * <p>
107      * We then calculate the resolutions that should be available and in the end
108      * filter it in case a resolution is on the blacklist for this device.
109      */
computePictureSizes()110     public PictureSizes computePictureSizes() {
111         List<Size> backCameraSizes = computeSizesForCamera(SettingsUtil.CAMERA_FACING_BACK);
112         List<Size> frontCameraSizes = computeSizesForCamera(SettingsUtil.CAMERA_FACING_FRONT);
113         Optional<SelectedVideoQualities> videoQualitiesBack =
114                 computeQualitiesForCamera(SettingsUtil.CAMERA_FACING_BACK);
115         Optional<SelectedVideoQualities> videoQualitiesFront =
116                 computeQualitiesForCamera(SettingsUtil.CAMERA_FACING_FRONT);
117         return new PictureSizes(backCameraSizes, frontCameraSizes, videoQualitiesBack,
118                 videoQualitiesFront);
119     }
120 
computeSizesForCamera(CameraDeviceSelector facingSelector)121     private List<Size> computeSizesForCamera(CameraDeviceSelector facingSelector) {
122         List<Size> sizes;
123         int cameraId = SettingsUtil.getCameraId(mCameraDeviceInfo, facingSelector);
124         if (cameraId >= 0) {
125             if (mCachedOnly) {
126                 sizes = CameraPictureSizesCacher.getCachedSizesForCamera(cameraId, mContext)
127                         .orNull();
128             } else {
129                 sizes = CameraPictureSizesCacher.getSizesForCamera(cameraId, mContext);
130             }
131 
132             if (sizes != null) {
133                 sizes = ResolutionUtil
134                         .getDisplayableSizesFromSupported(sizes,
135                                 facingSelector == SettingsUtil.CAMERA_FACING_BACK);
136                 String blacklisted = GservicesHelper
137                         .getBlacklistedResolutionsBack(mContentResolver);
138                 sizes = ResolutionUtil.filterBlackListedSizes(sizes, blacklisted);
139                 return sizes;
140             }
141         }
142         return new ArrayList<>(0);
143     }
144 
computeQualitiesForCamera( CameraDeviceSelector facingSelector)145     private Optional<SelectedVideoQualities> computeQualitiesForCamera(
146             CameraDeviceSelector facingSelector) {
147         int cameraId = SettingsUtil.getCameraId(mCameraDeviceInfo, facingSelector);
148         if (cameraId >= 0) {
149             // This is guaranteed not to be null/absent.
150             return Optional.of(SettingsUtil.getSelectedVideoQualities(cameraId));
151         }
152         return Optional.absent();
153     }
154 }
155