• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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;
18 
19 import android.app.Activity;
20 import android.content.Context;
21 import android.content.SharedPreferences;
22 import android.content.SharedPreferences.Editor;
23 import android.hardware.Camera.CameraInfo;
24 import android.hardware.Camera.Parameters;
25 import android.hardware.Camera.Size;
26 import android.media.CamcorderProfile;
27 import android.util.Log;
28 
29 import java.util.ArrayList;
30 import java.util.List;
31 
32 /**
33  *  Provides utilities and keys for Camera settings.
34  */
35 public class CameraSettings {
36     private static final int NOT_FOUND = -1;
37 
38     public static final String KEY_VERSION = "pref_version_key";
39     public static final String KEY_LOCAL_VERSION = "pref_local_version_key";
40     public static final String KEY_RECORD_LOCATION = RecordLocationPreference.KEY;
41     public static final String KEY_VIDEO_QUALITY = "pref_video_quality_key";
42     public static final String KEY_PICTURE_SIZE = "pref_camera_picturesize_key";
43     public static final String KEY_JPEG_QUALITY = "pref_camera_jpegquality_key";
44     public static final String KEY_FOCUS_MODE = "pref_camera_focusmode_key";
45     public static final String KEY_FLASH_MODE = "pref_camera_flashmode_key";
46     public static final String KEY_VIDEOCAMERA_FLASH_MODE = "pref_camera_video_flashmode_key";
47     public static final String KEY_COLOR_EFFECT = "pref_camera_coloreffect_key";
48     public static final String KEY_WHITE_BALANCE = "pref_camera_whitebalance_key";
49     public static final String KEY_SCENE_MODE = "pref_camera_scenemode_key";
50     public static final String KEY_EXPOSURE = "pref_camera_exposure_key";
51     public static final String KEY_CAMERA_ID = "pref_camera_id_key";
52 
53     private static final String VIDEO_QUALITY_HIGH = "high";
54     private static final String VIDEO_QUALITY_MMS = "mms";
55     private static final String VIDEO_QUALITY_YOUTUBE = "youtube";
56 
57     public static final String EXPOSURE_DEFAULT_VALUE = "0";
58 
59     public static final int CURRENT_VERSION = 4;
60     public static final int CURRENT_LOCAL_VERSION = 1;
61 
62     // max video duration in seconds for mms and youtube.
63     private static final int MMS_VIDEO_DURATION = CamcorderProfile.get(CamcorderProfile.QUALITY_LOW).duration;
64     private static final int YOUTUBE_VIDEO_DURATION = 10 * 60; // 10 mins
65     private static final int DEFAULT_VIDEO_DURATION = 30 * 60; // 10 mins
66 
67     public static final String DEFAULT_VIDEO_QUALITY_VALUE = "high";
68 
69     // MMS video length
70     public static final int DEFAULT_VIDEO_DURATION_VALUE = -1;
71 
72     @SuppressWarnings("unused")
73     private static final String TAG = "CameraSettings";
74 
75     private final Context mContext;
76     private final Parameters mParameters;
77     private final CameraInfo[] mCameraInfo;
78 
CameraSettings(Activity activity, Parameters parameters, CameraInfo[] cameraInfo)79     public CameraSettings(Activity activity, Parameters parameters,
80                           CameraInfo[] cameraInfo) {
81         mContext = activity;
82         mParameters = parameters;
83         mCameraInfo = cameraInfo;
84     }
85 
getPreferenceGroup(int preferenceRes)86     public PreferenceGroup getPreferenceGroup(int preferenceRes) {
87         PreferenceInflater inflater = new PreferenceInflater(mContext);
88         PreferenceGroup group =
89                 (PreferenceGroup) inflater.inflate(preferenceRes);
90         initPreference(group);
91         return group;
92     }
93 
initialCameraPictureSize( Context context, Parameters parameters)94     public static void initialCameraPictureSize(
95             Context context, Parameters parameters) {
96         // When launching the camera app first time, we will set the picture
97         // size to the first one in the list defined in "arrays.xml" and is also
98         // supported by the driver.
99         List<Size> supported = parameters.getSupportedPictureSizes();
100         if (supported == null) return;
101         for (String candidate : context.getResources().getStringArray(
102                 R.array.pref_camera_picturesize_entryvalues)) {
103             if (setCameraPictureSize(candidate, supported, parameters)) {
104                 SharedPreferences.Editor editor = ComboPreferences
105                         .get(context).edit();
106                 editor.putString(KEY_PICTURE_SIZE, candidate);
107                 editor.apply();
108                 return;
109             }
110         }
111         Log.e(TAG, "No supported picture size found");
112     }
113 
removePreferenceFromScreen( PreferenceGroup group, String key)114     public static void removePreferenceFromScreen(
115             PreferenceGroup group, String key) {
116         removePreference(group, key);
117     }
118 
setCameraPictureSize( String candidate, List<Size> supported, Parameters parameters)119     public static boolean setCameraPictureSize(
120             String candidate, List<Size> supported, Parameters parameters) {
121         int index = candidate.indexOf('x');
122         if (index == NOT_FOUND) return false;
123         int width = Integer.parseInt(candidate.substring(0, index));
124         int height = Integer.parseInt(candidate.substring(index + 1));
125         for (Size size: supported) {
126             if (size.width == width && size.height == height) {
127                 parameters.setPictureSize(width, height);
128                 return true;
129             }
130         }
131         return false;
132     }
133 
initPreference(PreferenceGroup group)134     private void initPreference(PreferenceGroup group) {
135         ListPreference videoQuality = group.findPreference(KEY_VIDEO_QUALITY);
136         ListPreference pictureSize = group.findPreference(KEY_PICTURE_SIZE);
137         ListPreference whiteBalance =  group.findPreference(KEY_WHITE_BALANCE);
138         ListPreference colorEffect = group.findPreference(KEY_COLOR_EFFECT);
139         ListPreference sceneMode = group.findPreference(KEY_SCENE_MODE);
140         ListPreference flashMode = group.findPreference(KEY_FLASH_MODE);
141         ListPreference focusMode = group.findPreference(KEY_FOCUS_MODE);
142         ListPreference exposure = group.findPreference(KEY_EXPOSURE);
143         IconListPreference cameraId =
144                 (IconListPreference)group.findPreference(KEY_CAMERA_ID);
145         ListPreference videoFlashMode =
146                 group.findPreference(KEY_VIDEOCAMERA_FLASH_MODE);
147 
148         // Since the screen could be loaded from different resources, we need
149         // to check if the preference is available here
150         if (videoQuality != null) {
151             // Modify video duration settings.
152             // The first entry is for MMS video duration, and we need to fill
153             // in the device-dependent value (in seconds).
154             CharSequence[] entries = videoQuality.getEntries();
155             CharSequence[] values = videoQuality.getEntryValues();
156             for (int i = 0; i < entries.length; ++i) {
157                 if (VIDEO_QUALITY_MMS.equals(values[i])) {
158                     entries[i] = entries[i].toString().replace(
159                             "30", Integer.toString(MMS_VIDEO_DURATION));
160                     break;
161                 }
162             }
163         }
164 
165         // Filter out unsupported settings / options
166         if (pictureSize != null) {
167             filterUnsupportedOptions(group, pictureSize, sizeListToStringList(
168                     mParameters.getSupportedPictureSizes()));
169         }
170         if (whiteBalance != null) {
171             filterUnsupportedOptions(group,
172                     whiteBalance, mParameters.getSupportedWhiteBalance());
173         }
174         if (colorEffect != null) {
175             filterUnsupportedOptions(group,
176                     colorEffect, mParameters.getSupportedColorEffects());
177         }
178         if (sceneMode != null) {
179             filterUnsupportedOptions(group,
180                     sceneMode, mParameters.getSupportedSceneModes());
181         }
182         if (flashMode != null) {
183             filterUnsupportedOptions(group,
184                     flashMode, mParameters.getSupportedFlashModes());
185         }
186         if (focusMode != null) {
187             filterUnsupportedOptions(group,
188                     focusMode, mParameters.getSupportedFocusModes());
189         }
190         if (videoFlashMode != null) {
191             filterUnsupportedOptions(group,
192                     videoFlashMode, mParameters.getSupportedFlashModes());
193         }
194         if (exposure != null) buildExposureCompensation(group, exposure);
195         if (cameraId != null) buildCameraId(group, cameraId);
196     }
197 
buildExposureCompensation( PreferenceGroup group, ListPreference exposure)198     private void buildExposureCompensation(
199             PreferenceGroup group, ListPreference exposure) {
200         int max = mParameters.getMaxExposureCompensation();
201         int min = mParameters.getMinExposureCompensation();
202         if (max == 0 && min == 0) {
203             removePreference(group, exposure.getKey());
204             return;
205         }
206         float step = mParameters.getExposureCompensationStep();
207 
208         // show only integer values for exposure compensation
209         int maxValue = (int) Math.floor(max * step);
210         int minValue = (int) Math.ceil(min * step);
211         CharSequence entries[] = new CharSequence[maxValue - minValue + 1];
212         CharSequence entryValues[] = new CharSequence[maxValue - minValue + 1];
213         for (int i = minValue; i <= maxValue; ++i) {
214             entryValues[maxValue - i] = Integer.toString(Math.round(i / step));
215             StringBuilder builder = new StringBuilder();
216             if (i > 0) builder.append('+');
217             entries[maxValue - i] = builder.append(i).toString();
218         }
219         exposure.setEntries(entries);
220         exposure.setEntryValues(entryValues);
221     }
222 
buildCameraId( PreferenceGroup group, IconListPreference cameraId)223     private void buildCameraId(
224             PreferenceGroup group, IconListPreference cameraId) {
225         int numOfCameras = mCameraInfo.length;
226         if (numOfCameras < 2) {
227             removePreference(group, cameraId.getKey());
228             return;
229         }
230 
231         CharSequence entries[] = new CharSequence[numOfCameras];
232         CharSequence entryValues[] = new CharSequence[numOfCameras];
233         int[] iconIds = new int[numOfCameras];
234         int[] largeIconIds = new int[numOfCameras];
235         for (int i = 0; i < numOfCameras; i++) {
236             entryValues[i] = Integer.toString(i);
237             if (mCameraInfo[i].facing == CameraInfo.CAMERA_FACING_FRONT) {
238                 entries[i] = mContext.getString(
239                         R.string.pref_camera_id_entry_front);
240                 iconIds[i] = R.drawable.ic_menuselect_camera_facing_front;
241                 largeIconIds[i] = R.drawable.ic_viewfinder_camera_facing_front;
242             } else {
243                 entries[i] = mContext.getString(
244                         R.string.pref_camera_id_entry_back);
245                 iconIds[i] = R.drawable.ic_menuselect_camera_facing_back;
246                 largeIconIds[i] = R.drawable.ic_viewfinder_camera_facing_back;
247             }
248         }
249         cameraId.setEntries(entries);
250         cameraId.setEntryValues(entryValues);
251         cameraId.setIconIds(iconIds);
252         cameraId.setLargeIconIds(largeIconIds);
253     }
254 
removePreference(PreferenceGroup group, String key)255     private static boolean removePreference(PreferenceGroup group, String key) {
256         for (int i = 0, n = group.size(); i < n; i++) {
257             CameraPreference child = group.get(i);
258             if (child instanceof PreferenceGroup) {
259                 if (removePreference((PreferenceGroup) child, key)) {
260                     return true;
261                 }
262             }
263             if (child instanceof ListPreference &&
264                     ((ListPreference) child).getKey().equals(key)) {
265                 group.removePreference(i);
266                 return true;
267             }
268         }
269         return false;
270     }
271 
filterUnsupportedOptions(PreferenceGroup group, ListPreference pref, List<String> supported)272     private void filterUnsupportedOptions(PreferenceGroup group,
273             ListPreference pref, List<String> supported) {
274 
275         CharSequence[] allEntries = pref.getEntries();
276 
277         // Remove the preference if the parameter is not supported or there is
278         // only one options for the settings.
279         if (supported == null || supported.size() <= 1) {
280             removePreference(group, pref.getKey());
281             return;
282         }
283 
284         pref.filterUnsupported(supported);
285         if (pref.getEntries().length <= 1) {
286             removePreference(group, pref.getKey());
287             return;
288         }
289 
290         // Set the value to the first entry if it is invalid.
291         String value = pref.getValue();
292         if (pref.findIndexOfValue(value) == NOT_FOUND) {
293             pref.setValueIndex(0);
294         }
295     }
296 
sizeListToStringList(List<Size> sizes)297     private static List<String> sizeListToStringList(List<Size> sizes) {
298         ArrayList<String> list = new ArrayList<String>();
299         for (Size size : sizes) {
300             list.add(String.format("%dx%d", size.width, size.height));
301         }
302         return list;
303     }
304 
upgradeLocalPreferences(SharedPreferences pref)305     public static void upgradeLocalPreferences(SharedPreferences pref) {
306         int version;
307         try {
308             version = pref.getInt(KEY_LOCAL_VERSION, 0);
309         } catch (Exception ex) {
310             version = 0;
311         }
312         if (version == CURRENT_LOCAL_VERSION) return;
313         SharedPreferences.Editor editor = pref.edit();
314         editor.putInt(KEY_LOCAL_VERSION, CURRENT_LOCAL_VERSION);
315         editor.apply();
316     }
317 
upgradeGlobalPreferences(SharedPreferences pref)318     public static void upgradeGlobalPreferences(SharedPreferences pref) {
319         int version;
320         try {
321             version = pref.getInt(KEY_VERSION, 0);
322         } catch (Exception ex) {
323             version = 0;
324         }
325         if (version == CURRENT_VERSION) return;
326 
327         SharedPreferences.Editor editor = pref.edit();
328         if (version == 0) {
329             // We won't use the preference which change in version 1.
330             // So, just upgrade to version 1 directly
331             version = 1;
332         }
333         if (version == 1) {
334             // Change jpeg quality {65,75,85} to {normal,fine,superfine}
335             String quality = pref.getString(KEY_JPEG_QUALITY, "85");
336             if (quality.equals("65")) {
337                 quality = "normal";
338             } else if (quality.equals("75")) {
339                 quality = "fine";
340             } else {
341                 quality = "superfine";
342             }
343             editor.putString(KEY_JPEG_QUALITY, quality);
344             version = 2;
345         }
346         if (version == 2) {
347             editor.putString(KEY_RECORD_LOCATION,
348                     pref.getBoolean(KEY_RECORD_LOCATION, false)
349                     ? RecordLocationPreference.VALUE_ON
350                     : RecordLocationPreference.VALUE_NONE);
351             version = 3;
352         }
353         if (version == 3) {
354             // Just use video quality to replace it and
355             // ignore the current settings.
356             editor.remove("pref_camera_videoquality_key");
357             editor.remove("pref_camera_video_duration_key");
358         }
359         editor.putInt(KEY_VERSION, CURRENT_VERSION);
360         editor.apply();
361     }
362 
upgradeAllPreferences(ComboPreferences pref)363     public static void upgradeAllPreferences(ComboPreferences pref) {
364         upgradeGlobalPreferences(pref.getGlobal());
365         upgradeLocalPreferences(pref.getLocal());
366     }
367 
getVideoQuality(String quality)368     public static boolean getVideoQuality(String quality) {
369         return VIDEO_QUALITY_YOUTUBE.equals(
370                 quality) || VIDEO_QUALITY_HIGH.equals(quality);
371     }
372 
getVidoeDurationInMillis(String quality)373     public static int getVidoeDurationInMillis(String quality) {
374         if (VIDEO_QUALITY_MMS.equals(quality)) {
375             return MMS_VIDEO_DURATION * 1000;
376         } else if (VIDEO_QUALITY_YOUTUBE.equals(quality)) {
377             return YOUTUBE_VIDEO_DURATION * 1000;
378         }
379         return DEFAULT_VIDEO_DURATION * 1000;
380     }
381 
readPreferredCameraId(SharedPreferences pref)382     public static int readPreferredCameraId(SharedPreferences pref) {
383         return Integer.parseInt(pref.getString(KEY_CAMERA_ID, "0"));
384     }
385 
writePreferredCameraId(SharedPreferences pref, int cameraId)386     public static void writePreferredCameraId(SharedPreferences pref,
387             int cameraId) {
388         Editor editor = pref.edit();
389         editor.putString(KEY_CAMERA_ID, Integer.toString(cameraId));
390         editor.apply();
391     }
392 }
393