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.annotation.TargetApi;
     20 import android.app.Activity;
     21 import android.content.Context;
     22 import android.content.SharedPreferences;
     23 import android.content.SharedPreferences.Editor;
     24 import android.content.res.Resources;
     25 import android.content.res.TypedArray;
     26 import android.hardware.Camera.CameraInfo;
     27 import android.hardware.Camera.Parameters;
     28 import android.hardware.Camera.Size;
     29 import android.media.CamcorderProfile;
     30 import android.util.FloatMath;
     31 import android.util.Log;
     32 
     33 import com.android.gallery3d.common.ApiHelper;
     34 
     35 import java.util.ArrayList;
     36 import java.util.List;
     37 import java.util.Locale;
     38 
     39 /**
     40  *  Provides utilities and keys for Camera settings.
     41  */
     42 public class CameraSettings {
     43     private static final int NOT_FOUND = -1;
     44 
     45     public static final String KEY_VERSION = "pref_version_key";
     46     public static final String KEY_LOCAL_VERSION = "pref_local_version_key";
     47     public static final String KEY_RECORD_LOCATION = "pref_camera_recordlocation_key";
     48     public static final String KEY_VIDEO_QUALITY = "pref_video_quality_key";
     49     public static final String KEY_VIDEO_TIME_LAPSE_FRAME_INTERVAL = "pref_video_time_lapse_frame_interval_key";
     50     public static final String KEY_PICTURE_SIZE = "pref_camera_picturesize_key";
     51     public static final String KEY_JPEG_QUALITY = "pref_camera_jpegquality_key";
     52     public static final String KEY_FOCUS_MODE = "pref_camera_focusmode_key";
     53     public static final String KEY_FLASH_MODE = "pref_camera_flashmode_key";
     54     public static final String KEY_VIDEOCAMERA_FLASH_MODE = "pref_camera_video_flashmode_key";
     55     public static final String KEY_WHITE_BALANCE = "pref_camera_whitebalance_key";
     56     public static final String KEY_SCENE_MODE = "pref_camera_scenemode_key";
     57     public static final String KEY_EXPOSURE = "pref_camera_exposure_key";
     58     public static final String KEY_TIMER = "pref_camera_timer_key";
     59     public static final String KEY_TIMER_SOUND_EFFECTS = "pref_camera_timer_sound_key";
     60     public static final String KEY_VIDEO_EFFECT = "pref_video_effect_key";
     61     public static final String KEY_CAMERA_ID = "pref_camera_id_key";
     62     public static final String KEY_CAMERA_HDR = "pref_camera_hdr_key";
     63     public static final String KEY_CAMERA_FIRST_USE_HINT_SHOWN = "pref_camera_first_use_hint_shown_key";
     64     public static final String KEY_VIDEO_FIRST_USE_HINT_SHOWN = "pref_video_first_use_hint_shown_key";
     65 
     66     public static final String EXPOSURE_DEFAULT_VALUE = "0";
     67 
     68     public static final int CURRENT_VERSION = 5;
     69     public static final int CURRENT_LOCAL_VERSION = 2;
     70 
     71     private static final String TAG = "CameraSettings";
     72 
     73     private final Context mContext;
     74     private final Parameters mParameters;
     75     private final CameraInfo[] mCameraInfo;
     76     private final int mCameraId;
     77 
     78     public CameraSettings(Activity activity, Parameters parameters,
     79                           int cameraId, CameraInfo[] cameraInfo) {
     80         mContext = activity;
     81         mParameters = parameters;
     82         mCameraId = cameraId;
     83         mCameraInfo = cameraInfo;
     84     }
     85 
     86     public PreferenceGroup getPreferenceGroup(int preferenceRes) {
     87         PreferenceInflater inflater = new PreferenceInflater(mContext);
     88         PreferenceGroup group =
     89                 (PreferenceGroup) inflater.inflate(preferenceRes);
     90         if (mParameters != null) initPreference(group);
     91         return group;
     92     }
     93 
     94     @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB)
     95     public static String getDefaultVideoQuality(int cameraId,
     96             String defaultQuality) {
     97         if (ApiHelper.HAS_FINE_RESOLUTION_QUALITY_LEVELS) {
     98             if (CamcorderProfile.hasProfile(
     99                     cameraId, Integer.valueOf(defaultQuality))) {
    100                 return defaultQuality;
    101             }
    102         }
    103         return Integer.toString(CamcorderProfile.QUALITY_HIGH);
    104     }
    105 
    106     public static void initialCameraPictureSize(
    107             Context context, Parameters parameters) {
    108         // When launching the camera app first time, we will set the picture
    109         // size to the first one in the list defined in "arrays.xml" and is also
    110         // supported by the driver.
    111         List<Size> supported = parameters.getSupportedPictureSizes();
    112         if (supported == null) return;
    113         for (String candidate : context.getResources().getStringArray(
    114                 R.array.pref_camera_picturesize_entryvalues)) {
    115             if (setCameraPictureSize(candidate, supported, parameters)) {
    116                 SharedPreferences.Editor editor = ComboPreferences
    117                         .get(context).edit();
    118                 editor.putString(KEY_PICTURE_SIZE, candidate);
    119                 editor.apply();
    120                 return;
    121             }
    122         }
    123         Log.e(TAG, "No supported picture size found");
    124     }
    125 
    126     public static void removePreferenceFromScreen(
    127             PreferenceGroup group, String key) {
    128         removePreference(group, key);
    129     }
    130 
    131     public static boolean setCameraPictureSize(
    132             String candidate, List<Size> supported, Parameters parameters) {
    133         int index = candidate.indexOf('x');
    134         if (index == NOT_FOUND) return false;
    135         int width = Integer.parseInt(candidate.substring(0, index));
    136         int height = Integer.parseInt(candidate.substring(index + 1));
    137         for (Size size : supported) {
    138             if (size.width == width && size.height == height) {
    139                 parameters.setPictureSize(width, height);
    140                 return true;
    141             }
    142         }
    143         return false;
    144     }
    145 
    146     public static int getMaxVideoDuration(Context context) {
    147         int duration = 0;  // in milliseconds, 0 means unlimited.
    148         try {
    149             duration = context.getResources().getInteger(R.integer.max_video_recording_length);
    150         } catch (Resources.NotFoundException ex) {
    151         }
    152         return duration;
    153     }
    154 
    155     private void initPreference(PreferenceGroup group) {
    156         ListPreference videoQuality = group.findPreference(KEY_VIDEO_QUALITY);
    157         ListPreference timeLapseInterval = group.findPreference(KEY_VIDEO_TIME_LAPSE_FRAME_INTERVAL);
    158         ListPreference pictureSize = group.findPreference(KEY_PICTURE_SIZE);
    159         ListPreference whiteBalance =  group.findPreference(KEY_WHITE_BALANCE);
    160         ListPreference sceneMode = group.findPreference(KEY_SCENE_MODE);
    161         ListPreference flashMode = group.findPreference(KEY_FLASH_MODE);
    162         ListPreference focusMode = group.findPreference(KEY_FOCUS_MODE);
    163         IconListPreference exposure =
    164                 (IconListPreference) group.findPreference(KEY_EXPOSURE);
    165         CountDownTimerPreference timer =
    166                 (CountDownTimerPreference) group.findPreference(KEY_TIMER);
    167         ListPreference countDownSoundEffects = group.findPreference(KEY_TIMER_SOUND_EFFECTS);
    168         IconListPreference cameraIdPref =
    169                 (IconListPreference) group.findPreference(KEY_CAMERA_ID);
    170         ListPreference videoFlashMode =
    171                 group.findPreference(KEY_VIDEOCAMERA_FLASH_MODE);
    172         ListPreference videoEffect = group.findPreference(KEY_VIDEO_EFFECT);
    173         ListPreference cameraHdr = group.findPreference(KEY_CAMERA_HDR);
    174 
    175         // Since the screen could be loaded from different resources, we need
    176         // to check if the preference is available here
    177         if (videoQuality != null) {
    178             filterUnsupportedOptions(group, videoQuality, getSupportedVideoQuality());
    179         }
    180 
    181         if (pictureSize != null) {
    182             filterUnsupportedOptions(group, pictureSize, sizeListToStringList(
    183                     mParameters.getSupportedPictureSizes()));
    184             filterSimilarPictureSize(group, pictureSize);
    185         }
    186         if (whiteBalance != null) {
    187             filterUnsupportedOptions(group,
    188                     whiteBalance, mParameters.getSupportedWhiteBalance());
    189         }
    190         if (sceneMode != null) {
    191             filterUnsupportedOptions(group,
    192                     sceneMode, mParameters.getSupportedSceneModes());
    193         }
    194         if (flashMode != null) {
    195             filterUnsupportedOptions(group,
    196                     flashMode, mParameters.getSupportedFlashModes());
    197         }
    198         if (focusMode != null) {
    199             if (!Util.isFocusAreaSupported(mParameters)) {
    200                 filterUnsupportedOptions(group,
    201                         focusMode, mParameters.getSupportedFocusModes());
    202             } else {
    203                 // Remove the focus mode if we can use tap-to-focus.
    204                 removePreference(group, focusMode.getKey());
    205             }
    206         }
    207         if (videoFlashMode != null) {
    208             filterUnsupportedOptions(group,
    209                     videoFlashMode, mParameters.getSupportedFlashModes());
    210         }
    211         if (exposure != null) buildExposureCompensation(group, exposure);
    212         if (cameraIdPref != null) buildCameraId(group, cameraIdPref);
    213 
    214         if (timeLapseInterval != null) {
    215             if (ApiHelper.HAS_TIME_LAPSE_RECORDING) {
    216                 resetIfInvalid(timeLapseInterval);
    217             } else {
    218                 removePreference(group, timeLapseInterval.getKey());
    219             }
    220         }
    221         if (videoEffect != null) {
    222             if (ApiHelper.HAS_EFFECTS_RECORDING) {
    223                 initVideoEffect(group, videoEffect);
    224                 resetIfInvalid(videoEffect);
    225             } else {
    226                 filterUnsupportedOptions(group, videoEffect, null);
    227             }
    228         }
    229         if (cameraHdr != null && (!ApiHelper.HAS_CAMERA_HDR
    230                     || !Util.isCameraHdrSupported(mParameters))) {
    231             removePreference(group, cameraHdr.getKey());
    232         }
    233     }
    234 
    235     private void buildExposureCompensation(
    236             PreferenceGroup group, IconListPreference exposure) {
    237         int max = mParameters.getMaxExposureCompensation();
    238         int min = mParameters.getMinExposureCompensation();
    239         if (max == 0 && min == 0) {
    240             removePreference(group, exposure.getKey());
    241             return;
    242         }
    243         float step = mParameters.getExposureCompensationStep();
    244 
    245         // show only integer values for exposure compensation
    246         int maxValue = (int) FloatMath.floor(max * step);
    247         int minValue = (int) FloatMath.ceil(min * step);
    248         CharSequence entries[] = new CharSequence[maxValue - minValue + 1];
    249         CharSequence entryValues[] = new CharSequence[maxValue - minValue + 1];
    250         int[] icons = new int[maxValue - minValue + 1];
    251         TypedArray iconIds = mContext.getResources().obtainTypedArray(
    252                 R.array.pref_camera_exposure_icons);
    253         for (int i = minValue; i <= maxValue; ++i) {
    254             entryValues[maxValue - i] = Integer.toString(Math.round(i / step));
    255             StringBuilder builder = new StringBuilder();
    256             if (i > 0) builder.append('+');
    257             entries[maxValue - i] = builder.append(i).toString();
    258             icons[maxValue - i] = iconIds.getResourceId(3 + i, 0);
    259         }
    260         exposure.setUseSingleIcon(true);
    261         exposure.setEntries(entries);
    262         exposure.setEntryValues(entryValues);
    263         exposure.setLargeIconIds(icons);
    264     }
    265 
    266     private void buildCameraId(
    267             PreferenceGroup group, IconListPreference preference) {
    268         int numOfCameras = mCameraInfo.length;
    269         if (numOfCameras < 2) {
    270             removePreference(group, preference.getKey());
    271             return;
    272         }
    273 
    274         CharSequence[] entryValues = new CharSequence[numOfCameras];
    275         for (int i = 0; i < numOfCameras; ++i) {
    276             entryValues[i] = "" + i;
    277         }
    278         preference.setEntryValues(entryValues);
    279     }
    280 
    281     private static boolean removePreference(PreferenceGroup group, String key) {
    282         for (int i = 0, n = group.size(); i < n; i++) {
    283             CameraPreference child = group.get(i);
    284             if (child instanceof PreferenceGroup) {
    285                 if (removePreference((PreferenceGroup) child, key)) {
    286                     return true;
    287                 }
    288             }
    289             if (child instanceof ListPreference &&
    290                     ((ListPreference) child).getKey().equals(key)) {
    291                 group.removePreference(i);
    292                 return true;
    293             }
    294         }
    295         return false;
    296     }
    297 
    298     private void filterUnsupportedOptions(PreferenceGroup group,
    299             ListPreference pref, List<String> supported) {
    300 
    301         // Remove the preference if the parameter is not supported or there is
    302         // only one options for the settings.
    303         if (supported == null || supported.size() <= 1) {
    304             removePreference(group, pref.getKey());
    305             return;
    306         }
    307 
    308         pref.filterUnsupported(supported);
    309         if (pref.getEntries().length <= 1) {
    310             removePreference(group, pref.getKey());
    311             return;
    312         }
    313 
    314         resetIfInvalid(pref);
    315     }
    316 
    317     private void filterSimilarPictureSize(PreferenceGroup group,
    318             ListPreference pref) {
    319         pref.filterDuplicated();
    320         if (pref.getEntries().length <= 1) {
    321             removePreference(group, pref.getKey());
    322             return;
    323         }
    324         resetIfInvalid(pref);
    325     }
    326 
    327     private void resetIfInvalid(ListPreference pref) {
    328         // Set the value to the first entry if it is invalid.
    329         String value = pref.getValue();
    330         if (pref.findIndexOfValue(value) == NOT_FOUND) {
    331             pref.setValueIndex(0);
    332         }
    333     }
    334 
    335     private static List<String> sizeListToStringList(List<Size> sizes) {
    336         ArrayList<String> list = new ArrayList<String>();
    337         for (Size size : sizes) {
    338             list.add(String.format(Locale.ENGLISH, "%dx%d", size.width, size.height));
    339         }
    340         return list;
    341     }
    342 
    343     public static void upgradeLocalPreferences(SharedPreferences pref) {
    344         int version;
    345         try {
    346             version = pref.getInt(KEY_LOCAL_VERSION, 0);
    347         } catch (Exception ex) {
    348             version = 0;
    349         }
    350         if (version == CURRENT_LOCAL_VERSION) return;
    351 
    352         SharedPreferences.Editor editor = pref.edit();
    353         if (version == 1) {
    354             // We use numbers to represent the quality now. The quality definition is identical to
    355             // that of CamcorderProfile.java.
    356             editor.remove("pref_video_quality_key");
    357         }
    358         editor.putInt(KEY_LOCAL_VERSION, CURRENT_LOCAL_VERSION);
    359         editor.apply();
    360     }
    361 
    362     public static void upgradeGlobalPreferences(SharedPreferences pref) {
    363         upgradeOldVersion(pref);
    364         upgradeCameraId(pref);
    365     }
    366 
    367     private static void upgradeOldVersion(SharedPreferences pref) {
    368         int version;
    369         try {
    370             version = pref.getInt(KEY_VERSION, 0);
    371         } catch (Exception ex) {
    372             version = 0;
    373         }
    374         if (version == CURRENT_VERSION) return;
    375 
    376         SharedPreferences.Editor editor = pref.edit();
    377         if (version == 0) {
    378             // We won't use the preference which change in version 1.
    379             // So, just upgrade to version 1 directly
    380             version = 1;
    381         }
    382         if (version == 1) {
    383             // Change jpeg quality {65,75,85} to {normal,fine,superfine}
    384             String quality = pref.getString(KEY_JPEG_QUALITY, "85");
    385             if (quality.equals("65")) {
    386                 quality = "normal";
    387             } else if (quality.equals("75")) {
    388                 quality = "fine";
    389             } else {
    390                 quality = "superfine";
    391             }
    392             editor.putString(KEY_JPEG_QUALITY, quality);
    393             version = 2;
    394         }
    395         if (version == 2) {
    396             editor.putString(KEY_RECORD_LOCATION,
    397                     pref.getBoolean(KEY_RECORD_LOCATION, false)
    398                     ? RecordLocationPreference.VALUE_ON
    399                     : RecordLocationPreference.VALUE_NONE);
    400             version = 3;
    401         }
    402         if (version == 3) {
    403             // Just use video quality to replace it and
    404             // ignore the current settings.
    405             editor.remove("pref_camera_videoquality_key");
    406             editor.remove("pref_camera_video_duration_key");
    407         }
    408 
    409         editor.putInt(KEY_VERSION, CURRENT_VERSION);
    410         editor.apply();
    411     }
    412 
    413     private static void upgradeCameraId(SharedPreferences pref) {
    414         // The id stored in the preference may be out of range if we are running
    415         // inside the emulator and a webcam is removed.
    416         // Note: This method accesses the global preferences directly, not the
    417         // combo preferences.
    418         int cameraId = readPreferredCameraId(pref);
    419         if (cameraId == 0) return;  // fast path
    420 
    421         int n = CameraHolder.instance().getNumberOfCameras();
    422         if (cameraId < 0 || cameraId >= n) {
    423             writePreferredCameraId(pref, 0);
    424         }
    425     }
    426 
    427     public static int readPreferredCameraId(SharedPreferences pref) {
    428         return Integer.parseInt(pref.getString(KEY_CAMERA_ID, "0"));
    429     }
    430 
    431     public static void writePreferredCameraId(SharedPreferences pref,
    432             int cameraId) {
    433         Editor editor = pref.edit();
    434         editor.putString(KEY_CAMERA_ID, Integer.toString(cameraId));
    435         editor.apply();
    436     }
    437 
    438     public static int readExposure(ComboPreferences preferences) {
    439         String exposure = preferences.getString(
    440                 CameraSettings.KEY_EXPOSURE,
    441                 EXPOSURE_DEFAULT_VALUE);
    442         try {
    443             return Integer.parseInt(exposure);
    444         } catch (Exception ex) {
    445             Log.e(TAG, "Invalid exposure: " + exposure);
    446         }
    447         return 0;
    448     }
    449 
    450     public static int readEffectType(SharedPreferences pref) {
    451         String effectSelection = pref.getString(KEY_VIDEO_EFFECT, "none");
    452         if (effectSelection.equals("none")) {
    453             return EffectsRecorder.EFFECT_NONE;
    454         } else if (effectSelection.startsWith("goofy_face")) {
    455             return EffectsRecorder.EFFECT_GOOFY_FACE;
    456         } else if (effectSelection.startsWith("backdropper")) {
    457             return EffectsRecorder.EFFECT_BACKDROPPER;
    458         }
    459         Log.e(TAG, "Invalid effect selection: " + effectSelection);
    460         return EffectsRecorder.EFFECT_NONE;
    461     }
    462 
    463     public static Object readEffectParameter(SharedPreferences pref) {
    464         String effectSelection = pref.getString(KEY_VIDEO_EFFECT, "none");
    465         if (effectSelection.equals("none")) {
    466             return null;
    467         }
    468         int separatorIndex = effectSelection.indexOf('/');
    469         String effectParameter =
    470                 effectSelection.substring(separatorIndex + 1);
    471         if (effectSelection.startsWith("goofy_face")) {
    472             if (effectParameter.equals("squeeze")) {
    473                 return EffectsRecorder.EFFECT_GF_SQUEEZE;
    474             } else if (effectParameter.equals("big_eyes")) {
    475                 return EffectsRecorder.EFFECT_GF_BIG_EYES;
    476             } else if (effectParameter.equals("big_mouth")) {
    477                 return EffectsRecorder.EFFECT_GF_BIG_MOUTH;
    478             } else if (effectParameter.equals("small_mouth")) {
    479                 return EffectsRecorder.EFFECT_GF_SMALL_MOUTH;
    480             } else if (effectParameter.equals("big_nose")) {
    481                 return EffectsRecorder.EFFECT_GF_BIG_NOSE;
    482             } else if (effectParameter.equals("small_eyes")) {
    483                 return EffectsRecorder.EFFECT_GF_SMALL_EYES;
    484             }
    485         } else if (effectSelection.startsWith("backdropper")) {
    486             // Parameter is a string that either encodes the URI to use,
    487             // or specifies 'gallery'.
    488             return effectParameter;
    489         }
    490 
    491         Log.e(TAG, "Invalid effect selection: " + effectSelection);
    492         return null;
    493     }
    494 
    495     public static void restorePreferences(Context context,
    496             ComboPreferences preferences, Parameters parameters) {
    497         int currentCameraId = readPreferredCameraId(preferences);
    498 
    499         // Clear the preferences of both cameras.
    500         int backCameraId = CameraHolder.instance().getBackCameraId();
    501         if (backCameraId != -1) {
    502             preferences.setLocalId(context, backCameraId);
    503             Editor editor = preferences.edit();
    504             editor.clear();
    505             editor.apply();
    506         }
    507         int frontCameraId = CameraHolder.instance().getFrontCameraId();
    508         if (frontCameraId != -1) {
    509             preferences.setLocalId(context, frontCameraId);
    510             Editor editor = preferences.edit();
    511             editor.clear();
    512             editor.apply();
    513         }
    514 
    515         // Switch back to the preferences of the current camera. Otherwise,
    516         // we may write the preference to wrong camera later.
    517         preferences.setLocalId(context, currentCameraId);
    518 
    519         upgradeGlobalPreferences(preferences.getGlobal());
    520         upgradeLocalPreferences(preferences.getLocal());
    521 
    522         // Write back the current camera id because parameters are related to
    523         // the camera. Otherwise, we may switch to the front camera but the
    524         // initial picture size is that of the back camera.
    525         initialCameraPictureSize(context, parameters);
    526         writePreferredCameraId(preferences, currentCameraId);
    527     }
    528 
    529     private ArrayList<String> getSupportedVideoQuality() {
    530         ArrayList<String> supported = new ArrayList<String>();
    531         // Check for supported quality
    532         if (ApiHelper.HAS_FINE_RESOLUTION_QUALITY_LEVELS) {
    533             getFineResolutionQuality(supported);
    534         } else {
    535             supported.add(Integer.toString(CamcorderProfile.QUALITY_HIGH));
    536             CamcorderProfile high = CamcorderProfile.get(
    537                     mCameraId, CamcorderProfile.QUALITY_HIGH);
    538             CamcorderProfile low = CamcorderProfile.get(
    539                     mCameraId, CamcorderProfile.QUALITY_LOW);
    540             if (high.videoFrameHeight * high.videoFrameWidth >
    541                     low.videoFrameHeight * low.videoFrameWidth) {
    542                 supported.add(Integer.toString(CamcorderProfile.QUALITY_LOW));
    543             }
    544         }
    545 
    546         return supported;
    547     }
    548 
    549     @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB)
    550     private void getFineResolutionQuality(ArrayList<String> supported) {
    551         if (CamcorderProfile.hasProfile(mCameraId, CamcorderProfile.QUALITY_1080P)) {
    552             supported.add(Integer.toString(CamcorderProfile.QUALITY_1080P));
    553         }
    554         if (CamcorderProfile.hasProfile(mCameraId, CamcorderProfile.QUALITY_720P)) {
    555             supported.add(Integer.toString(CamcorderProfile.QUALITY_720P));
    556         }
    557         if (CamcorderProfile.hasProfile(mCameraId, CamcorderProfile.QUALITY_480P)) {
    558             supported.add(Integer.toString(CamcorderProfile.QUALITY_480P));
    559         }
    560     }
    561 
    562     private void initVideoEffect(PreferenceGroup group, ListPreference videoEffect) {
    563         CharSequence[] values = videoEffect.getEntryValues();
    564 
    565         boolean goofyFaceSupported =
    566                 EffectsRecorder.isEffectSupported(EffectsRecorder.EFFECT_GOOFY_FACE);
    567         boolean backdropperSupported =
    568                 EffectsRecorder.isEffectSupported(EffectsRecorder.EFFECT_BACKDROPPER) &&
    569                 Util.isAutoExposureLockSupported(mParameters) &&
    570                 Util.isAutoWhiteBalanceLockSupported(mParameters);
    571 
    572         ArrayList<String> supported = new ArrayList<String>();
    573         for (CharSequence value : values) {
    574             String effectSelection = value.toString();
    575             if (!goofyFaceSupported && effectSelection.startsWith("goofy_face")) continue;
    576             if (!backdropperSupported && effectSelection.startsWith("backdropper")) continue;
    577             supported.add(effectSelection);
    578         }
    579 
    580         filterUnsupportedOptions(group, videoEffect, supported);
    581     }
    582 }
    583