Home | History | Annotate | Download | only in camera
      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.hardware.Camera.Parameters;
     23 import android.hardware.Camera.Size;
     24 import android.media.CamcorderProfile;
     25 import android.preference.PreferenceManager;
     26 import android.util.Log;
     27 
     28 import java.util.ArrayList;
     29 import java.util.List;
     30 
     31 /**
     32  *  Provides utilities and keys for Camera settings.
     33  */
     34 public class CameraSettings {
     35     private static final int NOT_FOUND = -1;
     36 
     37     public static final String KEY_VERSION = "pref_version_key";
     38     public static final String KEY_RECORD_LOCATION = RecordLocationPreference.KEY;
     39     public static final String KEY_VIDEO_QUALITY = "pref_video_quality_key";
     40     public static final String KEY_PICTURE_SIZE = "pref_camera_picturesize_key";
     41     public static final String KEY_JPEG_QUALITY = "pref_camera_jpegquality_key";
     42     public static final String KEY_FOCUS_MODE = "pref_camera_focusmode_key";
     43     public static final String KEY_FLASH_MODE = "pref_camera_flashmode_key";
     44     public static final String KEY_VIDEOCAMERA_FLASH_MODE = "pref_camera_video_flashmode_key";
     45     public static final String KEY_COLOR_EFFECT = "pref_camera_coloreffect_key";
     46     public static final String KEY_WHITE_BALANCE = "pref_camera_whitebalance_key";
     47     public static final String KEY_SCENE_MODE = "pref_camera_scenemode_key";
     48     public static final String KEY_QUICK_CAPTURE = "pref_camera_quickcapture_key";
     49     public static final String KEY_EXPOSURE = "pref_camera_exposure_key";
     50 
     51     public static final String QUICK_CAPTURE_ON = "on";
     52     public static final String QUICK_CAPTURE_OFF = "off";
     53 
     54     private static final String VIDEO_QUALITY_HIGH = "high";
     55     private static final String VIDEO_QUALITY_MMS = "mms";
     56     private static final String VIDEO_QUALITY_YOUTUBE = "youtube";
     57 
     58     public static final String EXPOSURE_DEFAULT_VALUE = "0";
     59 
     60     public static final int CURRENT_VERSION = 4;
     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 
     78     public CameraSettings(Activity activity, Parameters parameters) {
     79         mContext = activity;
     80         mParameters = parameters;
     81     }
     82 
     83     public PreferenceGroup getPreferenceGroup(int preferenceRes) {
     84         PreferenceInflater inflater = new PreferenceInflater(mContext);
     85         PreferenceGroup group =
     86                 (PreferenceGroup) inflater.inflate(preferenceRes);
     87         initPreference(group);
     88         return group;
     89     }
     90 
     91     public static void initialCameraPictureSize(
     92             Context context, Parameters parameters) {
     93         // When launching the camera app first time, we will set the picture
     94         // size to the first one in the list defined in "arrays.xml" and is also
     95         // supported by the driver.
     96         List<Size> supported = parameters.getSupportedPictureSizes();
     97         if (supported == null) return;
     98         for (String candidate : context.getResources().getStringArray(
     99                 R.array.pref_camera_picturesize_entryvalues)) {
    100             if (setCameraPictureSize(candidate, supported, parameters)) {
    101                 SharedPreferences.Editor editor = PreferenceManager
    102                         .getDefaultSharedPreferences(context).edit();
    103                 editor.putString(KEY_PICTURE_SIZE, candidate);
    104                 editor.commit();
    105                 return;
    106             }
    107         }
    108         Log.e(TAG, "No supported picture size found");
    109     }
    110 
    111     public static void removePreferenceFromScreen(
    112             PreferenceGroup group, String key) {
    113         removePreference(group, key);
    114     }
    115 
    116     public static boolean setCameraPictureSize(
    117             String candidate, List<Size> supported, Parameters parameters) {
    118         int index = candidate.indexOf('x');
    119         if (index == NOT_FOUND) return false;
    120         int width = Integer.parseInt(candidate.substring(0, index));
    121         int height = Integer.parseInt(candidate.substring(index + 1));
    122         for (Size size: supported) {
    123             if (size.width == width && size.height == height) {
    124                 parameters.setPictureSize(width, height);
    125                 return true;
    126             }
    127         }
    128         return false;
    129     }
    130 
    131     private void initPreference(PreferenceGroup group) {
    132         ListPreference videoQuality = group.findPreference(KEY_VIDEO_QUALITY);
    133         ListPreference pictureSize = group.findPreference(KEY_PICTURE_SIZE);
    134         ListPreference whiteBalance =  group.findPreference(KEY_WHITE_BALANCE);
    135         ListPreference colorEffect = group.findPreference(KEY_COLOR_EFFECT);
    136         ListPreference sceneMode = group.findPreference(KEY_SCENE_MODE);
    137         ListPreference flashMode = group.findPreference(KEY_FLASH_MODE);
    138         ListPreference focusMode = group.findPreference(KEY_FOCUS_MODE);
    139         ListPreference exposure = group.findPreference(KEY_EXPOSURE);
    140         ListPreference videoFlashMode =
    141                 group.findPreference(KEY_VIDEOCAMERA_FLASH_MODE);
    142 
    143         // Since the screen could be loaded from different resources, we need
    144         // to check if the preference is available here
    145         if (videoQuality != null) {
    146             // Modify video duration settings.
    147             // The first entry is for MMS video duration, and we need to fill
    148             // in the device-dependent value (in seconds).
    149             CharSequence[] entries = videoQuality.getEntries();
    150             CharSequence[] values = videoQuality.getEntryValues();
    151             for (int i = 0; i < entries.length; ++i) {
    152                 if (VIDEO_QUALITY_MMS.equals(values[i])) {
    153                     entries[i] = entries[i].toString().replace(
    154                             "30", Integer.toString(MMS_VIDEO_DURATION));
    155                     break;
    156                 }
    157             }
    158         }
    159 
    160         // Filter out unsupported settings / options
    161         if (pictureSize != null) {
    162             filterUnsupportedOptions(group, pictureSize, sizeListToStringList(
    163                     mParameters.getSupportedPictureSizes()));
    164         }
    165         if (whiteBalance != null) {
    166             filterUnsupportedOptions(group,
    167                     whiteBalance, mParameters.getSupportedWhiteBalance());
    168         }
    169         if (colorEffect != null) {
    170             filterUnsupportedOptions(group,
    171                     colorEffect, mParameters.getSupportedColorEffects());
    172         }
    173         if (sceneMode != null) {
    174             filterUnsupportedOptions(group,
    175                     sceneMode, mParameters.getSupportedSceneModes());
    176         }
    177         if (flashMode != null) {
    178             filterUnsupportedOptions(group,
    179                     flashMode, mParameters.getSupportedFlashModes());
    180         }
    181         if (focusMode != null) {
    182             filterUnsupportedOptions(group,
    183                     focusMode, mParameters.getSupportedFocusModes());
    184         }
    185         if (videoFlashMode != null) {
    186             filterUnsupportedOptions(group,
    187                     videoFlashMode, mParameters.getSupportedFlashModes());
    188         }
    189 
    190         if (exposure != null) {
    191             buildExposureCompensation(group, exposure);
    192         }
    193     }
    194 
    195     private void buildExposureCompensation(
    196             PreferenceGroup group, ListPreference exposure) {
    197         int max = mParameters.getMaxExposureCompensation();
    198         int min = mParameters.getMinExposureCompensation();
    199         if (max == 0 && min == 0) {
    200             removePreference(group, exposure.getKey());
    201             return;
    202         }
    203         float step = mParameters.getExposureCompensationStep();
    204 
    205         // show only integer values for exposure compensation
    206         int maxValue = (int) Math.floor(max * step);
    207         int minValue = (int) Math.ceil(min * step);
    208         CharSequence entries[] = new CharSequence[maxValue - minValue + 1];
    209         CharSequence entryValues[] = new CharSequence[maxValue - minValue + 1];
    210         for (int i = minValue; i <= maxValue; ++i) {
    211             entryValues[maxValue - i] = Integer.toString(Math.round(i / step));
    212             StringBuilder builder = new StringBuilder();
    213             if (i > 0) builder.append('+');
    214             entries[maxValue - i] = builder.append(i).toString();
    215         }
    216         exposure.setEntries(entries);
    217         exposure.setEntryValues(entryValues);
    218     }
    219 
    220     private static boolean removePreference(PreferenceGroup group, String key) {
    221         for (int i = 0, n = group.size(); i < n; i++) {
    222             CameraPreference child = group.get(i);
    223             if (child instanceof PreferenceGroup) {
    224                 if (removePreference((PreferenceGroup) child, key)) {
    225                     return true;
    226                 }
    227             }
    228             if (child instanceof ListPreference &&
    229                     ((ListPreference) child).getKey().equals(key)) {
    230                 group.removePreference(i);
    231                 return true;
    232             }
    233         }
    234         return false;
    235     }
    236 
    237     private void filterUnsupportedOptions(PreferenceGroup group,
    238             ListPreference pref, List<String> supported) {
    239 
    240         CharSequence[] allEntries = pref.getEntries();
    241 
    242         // Remove the preference if the parameter is not supported or there is
    243         // only one options for the settings.
    244         if (supported == null || supported.size() <= 1) {
    245             removePreference(group, pref.getKey());
    246             return;
    247         }
    248 
    249         pref.filterUnsupported(supported);
    250 
    251         // Set the value to the first entry if it is invalid.
    252         String value = pref.getValue();
    253         if (pref.findIndexOfValue(value) == NOT_FOUND) {
    254             pref.setValueIndex(0);
    255         }
    256     }
    257 
    258     private static List<String> sizeListToStringList(List<Size> sizes) {
    259         ArrayList<String> list = new ArrayList<String>();
    260         for (Size size : sizes) {
    261             list.add(String.format("%dx%d", size.width, size.height));
    262         }
    263         return list;
    264     }
    265 
    266     public static void upgradePreferences(SharedPreferences pref) {
    267         int version;
    268         try {
    269             version = pref.getInt(KEY_VERSION, 0);
    270         } catch (Exception ex) {
    271             version = 0;
    272         }
    273         if (version == CURRENT_VERSION) return;
    274 
    275         SharedPreferences.Editor editor = pref.edit();
    276         if (version == 0) {
    277             // We won't use the preference which change in version 1.
    278             // So, just upgrade to version 1 directly
    279             version = 1;
    280         }
    281         if (version == 1) {
    282             // Change jpeg quality {65,75,85} to {normal,fine,superfine}
    283             String quality = pref.getString(KEY_JPEG_QUALITY, "85");
    284             if (quality.equals("65")) {
    285                 quality = "normal";
    286             } else if (quality.equals("75")) {
    287                 quality = "fine";
    288             } else {
    289                 quality = "superfine";
    290             }
    291             editor.putString(KEY_JPEG_QUALITY, quality);
    292             version = 2;
    293         }
    294         if (version == 2) {
    295             editor.putString(KEY_RECORD_LOCATION,
    296                     pref.getBoolean(KEY_RECORD_LOCATION, false)
    297                     ? RecordLocationPreference.VALUE_ON
    298                     : RecordLocationPreference.VALUE_NONE);
    299             version = 3;
    300         }
    301         if (version == 3) {
    302             // Just use video quality to replace it and
    303             // ignore the current settings.
    304             editor.remove("pref_camera_videoquality_key");
    305             editor.remove("pref_camera_video_duration_key");
    306         }
    307         editor.putInt(KEY_VERSION, CURRENT_VERSION);
    308         editor.commit();
    309     }
    310 
    311     public static boolean getVideoQuality(String quality) {
    312         return VIDEO_QUALITY_YOUTUBE.equals(
    313                 quality) || VIDEO_QUALITY_HIGH.equals(quality);
    314     }
    315 
    316     public static int getVidoeDurationInMillis(String quality) {
    317         if (VIDEO_QUALITY_MMS.equals(quality)) {
    318             return MMS_VIDEO_DURATION * 1000;
    319         } else if (VIDEO_QUALITY_YOUTUBE.equals(quality)) {
    320             return YOUTUBE_VIDEO_DURATION * 1000;
    321         }
    322         return DEFAULT_VIDEO_DURATION * 1000;
    323     }
    324 }
    325