1/*
2 * Copyright (C) 2014 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
17package com.android.ex.camera2.portability;
18
19import com.android.ex.camera2.portability.debug.Log;
20
21import java.util.ArrayList;
22import java.util.EnumSet;
23import java.util.HashSet;
24import java.util.List;
25import java.util.Locale;
26import java.util.Set;
27import java.util.TreeSet;
28
29/**
30 * This class holds all the static information of a camera's capabilities.
31 * <p>
32 * The design of this class is thread-safe and can be passed around regardless
33 * of which thread using it.
34 * </p>
35 */
36public class CameraCapabilities {
37
38    private static Log.Tag TAG = new Log.Tag("CamCapabs");
39
40    /** Zoom ratio used for seeing sensor's full field of view. */
41    protected static final float ZOOM_RATIO_UNZOOMED = 1.0f;
42
43    /* All internal states are declared final and should be thread-safe. */
44
45    protected final ArrayList<int[]> mSupportedPreviewFpsRange = new ArrayList<int[]>();
46    protected final ArrayList<Size> mSupportedPreviewSizes = new ArrayList<Size>();
47    protected final TreeSet<Integer> mSupportedPreviewFormats = new TreeSet<Integer>();
48    protected final ArrayList<Size> mSupportedVideoSizes = new ArrayList<Size>();
49    protected final ArrayList<Size> mSupportedPhotoSizes = new ArrayList<Size>();
50    protected final TreeSet<Integer> mSupportedPhotoFormats = new TreeSet<Integer>();
51    protected final EnumSet<SceneMode> mSupportedSceneModes = EnumSet.noneOf(SceneMode.class);
52    protected final EnumSet<FlashMode> mSupportedFlashModes = EnumSet.noneOf(FlashMode.class);
53    protected final EnumSet<FocusMode> mSupportedFocusModes = EnumSet.noneOf(FocusMode.class);
54    protected final EnumSet<WhiteBalance> mSupportedWhiteBalances =
55            EnumSet.noneOf(WhiteBalance.class);
56    protected final EnumSet<Feature> mSupportedFeatures = EnumSet.noneOf(Feature.class);
57    protected Size mPreferredPreviewSizeForVideo;
58    protected int mMinExposureCompensation;
59    protected int mMaxExposureCompensation;
60    protected float mExposureCompensationStep;
61    protected int mMaxNumOfFacesSupported;
62    protected int mMaxNumOfFocusAreas;
63    protected int mMaxNumOfMeteringArea;
64    protected float mMaxZoomRatio;
65    protected float mHorizontalViewAngle;
66    protected float mVerticalViewAngle;
67    private final Stringifier mStringifier;
68
69    /**
70     * Focus modes.
71     */
72    public enum FocusMode {
73        /**
74         * Continuous auto focus mode intended for taking pictures.
75         * @see {@link android.hardware.Camera.Parameters#FOCUS_MODE_AUTO}.
76         */
77        AUTO,
78        /**
79         * Continuous auto focus mode intended for taking pictures.
80         * @see {@link android.hardware.Camera.Parameters#FOCUS_MODE_CONTINUOUS_PICTURE}.
81         */
82        CONTINUOUS_PICTURE,
83        /**
84         * Continuous auto focus mode intended for video recording.
85         * @see {@link android.hardware.Camera.Parameters#FOCUS_MODE_CONTINUOUS_VIDEO}.
86         */
87        CONTINUOUS_VIDEO,
88        /**
89         * Extended depth of field (EDOF).
90         * @see {@link android.hardware.Camera.Parameters#FOCUS_MODE_EDOF}.
91         */
92        EXTENDED_DOF,
93        /**
94         * Focus is fixed.
95         * @see {@link android.hardware.Camera.Parameters#FOCUS_MODE_FIXED}.
96         */
97        FIXED,
98        /**
99         * Focus is set at infinity.
100         * @see {@link android.hardware.Camera.Parameters#FOCUS_MODE_INFINITY}.
101         */
102        // TODO: Unsupported on API 2
103        INFINITY,
104        /**
105         * Macro (close-up) focus mode.
106         * @see {@link android.hardware.Camera.Parameters#FOCUS_MODE_MACRO}.
107         */
108        MACRO,
109    }
110
111    /**
112     * Flash modes.
113     */
114    public enum FlashMode {
115        /**
116         * No flash.
117         */
118        NO_FLASH,
119        /**
120         * Flash will be fired automatically when required.
121         * @see {@link android.hardware.Camera.Parameters#FLASH_MODE_OFF}.
122         */
123        AUTO,
124        /**
125         * Flash will not be fired.
126         * @see {@link android.hardware.Camera.Parameters#FLASH_MODE_OFF}.
127         */
128        OFF,
129        /**
130         * Flash will always be fired during snapshot.
131         * @see {@link android.hardware.Camera.Parameters#FLASH_MODE_ON}.
132         */
133        ON,
134        /**
135         * Constant emission of light during preview, auto-focus and snapshot.
136         * @see {@link android.hardware.Camera.Parameters#FLASH_MODE_TORCH}.
137         */
138        TORCH,
139        /**
140         * Flash will be fired in red-eye reduction mode.
141         * @see {@link android.hardware.Camera.Parameters#FLASH_MODE_RED_EYE}.
142         */
143        RED_EYE,
144    }
145
146    /**
147     * Scene modes.
148     */
149    public enum SceneMode {
150        /**
151         * No supported scene mode.
152         */
153        NO_SCENE_MODE,
154        /**
155         * Scene mode is off.
156         * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_AUTO}.
157         */
158        AUTO,
159        /**
160         * Take photos of fast moving objects.
161         * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_ACTION}.
162         */
163        ACTION,
164        /**
165         * Applications are looking for a barcode.
166         * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_BARCODE}.
167         */
168        BARCODE,
169        /**
170         * Take pictures on the beach.
171         * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_BEACH}.
172         */
173        BEACH,
174        /**
175         * Capture the naturally warm color of scenes lit by candles.
176         * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_CANDLELIGHT}.
177         */
178        CANDLELIGHT,
179        /**
180         * For shooting firework displays.
181         * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_FIREWORKS}.
182         */
183        FIREWORKS,
184        /**
185         * Capture a scene using high dynamic range imaging techniques.
186         * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_HDR}.
187         */
188        // Note: Supported as a vendor tag on the Camera2 API for some LEGACY devices.
189        HDR,
190        /**
191         * Take pictures on distant objects.
192         * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_LANDSCAPE}.
193         */
194        LANDSCAPE,
195        /**
196         * Take photos at night.
197         * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_NIGHT}.
198         */
199        NIGHT,
200        /**
201         * Take people pictures at night.
202         * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_NIGHT_PORTRAIT}.
203         */
204        // TODO: Unsupported on API 2
205        NIGHT_PORTRAIT,
206        /**
207         * Take indoor low-light shot.
208         * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_PARTY}.
209         */
210        PARTY,
211        /**
212         * Take people pictures.
213         * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_PORTRAIT}.
214         */
215        PORTRAIT,
216        /**
217         * Take pictures on the snow.
218         * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_SNOW}.
219         */
220        SNOW,
221        /**
222         * Take photos of fast moving objects.
223         * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_SPORTS}.
224         */
225        SPORTS,
226        /**
227         * Avoid blurry pictures (for example, due to hand shake).
228         * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_STEADYPHOTO}.
229         */
230        STEADYPHOTO,
231        /**
232         * Take sunset photos.
233         * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_SUNSET}.
234         */
235        SUNSET,
236        /**
237         * Take photos in a theater.
238         * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_THEATRE}.
239         */
240        THEATRE,
241    }
242
243    /**
244     * White blances.
245     */
246    public enum WhiteBalance {
247        /**
248         * @see {@link android.hardware.Camera.Parameters#WHITE_BALANCE_AUTO}.
249         */
250        AUTO,
251        /**
252         * @see {@link android.hardware.Camera.Parameters#WHITE_BALANCE_CLOUDY_DAYLIGHT}.
253         */
254        CLOUDY_DAYLIGHT,
255        /**
256         * @see {@link android.hardware.Camera.Parameters#WHITE_BALANCE_DAYLIGHT}.
257         */
258        DAYLIGHT,
259        /**
260         * @see {@link android.hardware.Camera.Parameters#WHITE_BALANCE_FLUORESCENT}.
261         */
262        FLUORESCENT,
263        /**
264         * @see {@link android.hardware.Camera.Parameters#WHITE_BALANCE_INCANDESCENT}.
265         */
266        INCANDESCENT,
267        /**
268         * @see {@link android.hardware.Camera.Parameters#WHITE_BALANCE_SHADE}.
269         */
270        SHADE,
271        /**
272         * @see {@link android.hardware.Camera.Parameters#WHITE_BALANCE_TWILIGHT}.
273         */
274        TWILIGHT,
275        /**
276         * @see {@link android.hardware.Camera.Parameters#WHITE_BALANCE_WARM_FLUORESCENT}.
277         */
278        WARM_FLUORESCENT,
279    }
280
281    /**
282     * Features.
283     */
284    public enum Feature {
285        /**
286         * Support zoom-related methods.
287         */
288        ZOOM,
289        /**
290         * Support for photo capturing during video recording.
291         */
292        VIDEO_SNAPSHOT,
293        /**
294         * Support for focus area settings.
295         */
296        FOCUS_AREA,
297        /**
298         * Support for metering area settings.
299         */
300        METERING_AREA,
301        /**
302         * Support for automatic exposure lock.
303         */
304        AUTO_EXPOSURE_LOCK,
305        /**
306         * Support for automatic white balance lock.
307         */
308        AUTO_WHITE_BALANCE_LOCK,
309        /**
310         * Support for video stabilization.
311         */
312        VIDEO_STABILIZATION,
313    }
314
315    /**
316     * A interface stringifier to convert abstract representations to API
317     * related string representation.
318     */
319    public static class Stringifier {
320        /**
321         * Converts the string to hyphen-delimited lowercase for compatibility with multiple APIs.
322         *
323         * @param enumCase The name of an enum constant.
324         * @return The converted string.
325         */
326        private static String toApiCase(String enumCase) {
327            return enumCase.toLowerCase(Locale.US).replaceAll("_", "-");
328        }
329
330        /**
331         * Converts the string to underscore-delimited uppercase to match the enum constant names.
332         *
333         * @param apiCase An API-related string representation.
334         * @return The converted string.
335         */
336        private static String toEnumCase(String apiCase) {
337            return apiCase.toUpperCase(Locale.US).replaceAll("-", "_");
338        }
339
340        /**
341         * Converts the focus mode to API-related string representation.
342         *
343         * @param focus The focus mode to convert.
344         * @return The string used by the camera framework API to represent the
345         *         focus mode.
346         */
347        public String stringify(FocusMode focus) {
348            return toApiCase(focus.name());
349        }
350
351        /**
352         * Converts the API-related string representation of the focus mode to the
353         * abstract representation.
354         *
355         * @param val The string representation.
356         * @return The focus mode represented by the input string, or the focus
357         *         mode with the lowest ordinal if it cannot be converted.
358         */
359        public FocusMode focusModeFromString(String val) {
360            if (val == null) {
361                return FocusMode.values()[0];
362            }
363            try {
364                return FocusMode.valueOf(toEnumCase(val));
365            } catch (IllegalArgumentException ex) {
366                return FocusMode.values()[0];
367            }
368        }
369
370        /**
371         * Converts the flash mode to API-related string representation.
372         *
373         * @param flash The focus mode to convert.
374         * @return The string used by the camera framework API to represent the
375         *         flash mode.
376         */
377        public String stringify(FlashMode flash) {
378            return toApiCase(flash.name());
379        }
380
381        /**
382         * Converts the API-related string representation of the flash mode to the
383         * abstract representation.
384         *
385         * @param val The string representation.
386         * @return The flash mode represented by the input string, or the flash
387         *         mode with the lowest ordinal if it cannot be converted.
388         */
389        public FlashMode flashModeFromString(String val) {
390            if (val == null) {
391                return FlashMode.values()[0];
392            }
393            try {
394                return FlashMode.valueOf(toEnumCase(val));
395            } catch (IllegalArgumentException ex) {
396                return FlashMode.values()[0];
397            }
398        }
399
400        /**
401         * Converts the scene mode to API-related string representation.
402         *
403         * @param scene The focus mode to convert.
404         * @return The string used by the camera framework API to represent the
405         *         scene mode.
406         */
407        public String stringify(SceneMode scene) {
408            return toApiCase(scene.name());
409        }
410
411        /**
412         * Converts the API-related string representation of the scene mode to the
413         * abstract representation.
414         *
415         * @param val The string representation.
416         * @return The scene mode represented by the input string, or the scene
417         *         mode with the lowest ordinal if it cannot be converted.
418         */
419        public SceneMode sceneModeFromString(String val) {
420            if (val == null) {
421                return SceneMode.values()[0];
422            }
423            try {
424                return SceneMode.valueOf(toEnumCase(val));
425            } catch (IllegalArgumentException ex) {
426                return SceneMode.values()[0];
427            }
428        }
429
430        /**
431         * Converts the white balance to API-related string representation.
432         *
433         * @param wb The focus mode to convert.
434         * @return The string used by the camera framework API to represent the
435         * white balance.
436         */
437        public String stringify(WhiteBalance wb) {
438            return toApiCase(wb.name());
439        }
440
441        /**
442         * Converts the API-related string representation of the white balance to
443         * the abstract representation.
444         *
445         * @param val The string representation.
446         * @return The white balance represented by the input string, or the
447         *         white balance with the lowest ordinal if it cannot be
448         *         converted.
449         */
450        public WhiteBalance whiteBalanceFromString(String val) {
451            if (val == null) {
452                return WhiteBalance.values()[0];
453            }
454            try {
455                return WhiteBalance.valueOf(toEnumCase(val));
456            } catch (IllegalArgumentException ex) {
457                return WhiteBalance.values()[0];
458            }
459        }
460    }
461
462    /**
463     * Constructor.
464     * @param stringifier The API-specific stringifier for this instance.
465     */
466    CameraCapabilities(Stringifier stringifier) {
467        mStringifier = stringifier;
468    }
469
470    /**
471     * Copy constructor.
472     * @param src The source instance.
473     */
474    public CameraCapabilities(CameraCapabilities src) {
475        mSupportedPreviewFpsRange.addAll(src.mSupportedPreviewFpsRange);
476        mSupportedPreviewSizes.addAll(src.mSupportedPreviewSizes);
477        mSupportedPreviewFormats.addAll(src.mSupportedPreviewFormats);
478        mSupportedVideoSizes.addAll(src.mSupportedVideoSizes);
479        mSupportedPhotoSizes.addAll(src.mSupportedPhotoSizes);
480        mSupportedPhotoFormats.addAll(src.mSupportedPhotoFormats);
481        mSupportedSceneModes.addAll(src.mSupportedSceneModes);
482        mSupportedFlashModes.addAll(src.mSupportedFlashModes);
483        mSupportedFocusModes.addAll(src.mSupportedFocusModes);
484        mSupportedWhiteBalances.addAll(src.mSupportedWhiteBalances);
485        mSupportedFeatures.addAll(src.mSupportedFeatures);
486        mPreferredPreviewSizeForVideo = src.mPreferredPreviewSizeForVideo;
487        mMaxExposureCompensation = src.mMaxExposureCompensation;
488        mMinExposureCompensation = src.mMinExposureCompensation;
489        mExposureCompensationStep = src.mExposureCompensationStep;
490        mMaxNumOfFacesSupported = src.mMaxNumOfFacesSupported;
491        mMaxNumOfFocusAreas = src.mMaxNumOfFocusAreas;
492        mMaxNumOfMeteringArea = src.mMaxNumOfMeteringArea;
493        mMaxZoomRatio = src.mMaxZoomRatio;
494        mHorizontalViewAngle = src.mHorizontalViewAngle;
495        mVerticalViewAngle = src.mVerticalViewAngle;
496        mStringifier = src.mStringifier;
497    }
498
499    public float getHorizontalViewAngle() {
500        return mHorizontalViewAngle;
501    }
502
503    public float getVerticalViewAngle() {
504        return mVerticalViewAngle;
505    }
506
507    /**
508     * @return the supported picture formats. See {@link android.graphics.ImageFormat}.
509     */
510    public Set<Integer> getSupportedPhotoFormats() {
511        return new TreeSet<Integer>(mSupportedPhotoFormats);
512    }
513
514    /**
515     * Gets the supported preview formats.
516     * @return The supported preview {@link android.graphics.ImageFormat}s.
517     */
518    public Set<Integer> getSupportedPreviewFormats() {
519        return new TreeSet<Integer>(mSupportedPreviewFormats);
520    }
521
522    /**
523     * Gets the supported picture sizes.
524     */
525    public List<Size> getSupportedPhotoSizes() {
526        return new ArrayList<Size>(mSupportedPhotoSizes);
527    }
528
529    /**
530     * @return The supported preview fps (frame-per-second) ranges. The returned
531     * list is sorted by maximum fps then minimum fps in a descending order.
532     * The values are multiplied by 1000.
533     */
534    public final List<int[]> getSupportedPreviewFpsRange() {
535        return new ArrayList<int[]>(mSupportedPreviewFpsRange);
536    }
537
538    /**
539     * @return The supported preview sizes. The list is sorted by width then
540     * height in a descending order.
541     */
542    public final List<Size> getSupportedPreviewSizes() {
543        return new ArrayList<Size>(mSupportedPreviewSizes);
544    }
545
546    public final Size getPreferredPreviewSizeForVideo() {
547        return new Size(mPreferredPreviewSizeForVideo);
548    }
549
550    /**
551     * @return The supported video frame sizes that can be used by MediaRecorder.
552     *         The list is sorted by width then height in a descending order.
553     */
554    public final List<Size> getSupportedVideoSizes() {
555        return new ArrayList<Size>(mSupportedVideoSizes);
556    }
557
558    /**
559     * @return The supported scene modes.
560     */
561    public final Set<SceneMode> getSupportedSceneModes() {
562        return new HashSet<SceneMode>(mSupportedSceneModes);
563    }
564
565    /**
566     * @return Whether the scene mode is supported.
567     */
568    public final boolean supports(SceneMode scene) {
569        return (scene != null && mSupportedSceneModes.contains(scene));
570    }
571
572    public boolean supports(final CameraSettings settings) {
573        if (zoomCheck(settings) && exposureCheck(settings) && focusCheck(settings) &&
574                flashCheck(settings) && photoSizeCheck(settings) && previewSizeCheck(settings) &&
575                videoStabilizationCheck(settings)) {
576            return true;
577        }
578        return false;
579    }
580
581    /**
582     * @return The supported flash modes.
583     */
584    public final Set<FlashMode> getSupportedFlashModes() {
585        return new HashSet<FlashMode>(mSupportedFlashModes);
586    }
587
588    /**
589     * @return Whether the flash mode is supported.
590     */
591    public final boolean supports(FlashMode flash) {
592        return (flash != null && mSupportedFlashModes.contains(flash));
593    }
594
595    /**
596     * @return The supported focus modes.
597     */
598    public final Set<FocusMode> getSupportedFocusModes() {
599        return new HashSet<FocusMode>(mSupportedFocusModes);
600    }
601
602    /**
603     * @return Whether the focus mode is supported.
604     */
605    public final boolean supports(FocusMode focus) {
606        return (focus != null && mSupportedFocusModes.contains(focus));
607    }
608
609    /**
610     * @return The supported white balanceas.
611     */
612    public final Set<WhiteBalance> getSupportedWhiteBalance() {
613        return new HashSet<WhiteBalance>(mSupportedWhiteBalances);
614    }
615
616    /**
617     * @return Whether the white balance is supported.
618     */
619    public boolean supports(WhiteBalance wb) {
620        return (wb != null && mSupportedWhiteBalances.contains(wb));
621    }
622
623    public final Set<Feature> getSupportedFeature() {
624        return new HashSet<Feature>(mSupportedFeatures);
625    }
626
627    public boolean supports(Feature ft) {
628        return (ft != null && mSupportedFeatures.contains(ft));
629    }
630
631    /**
632     * @return The maximal supported zoom ratio.
633     */
634    public float getMaxZoomRatio() {
635        return mMaxZoomRatio;
636    }
637
638    /**
639     * @return The min exposure compensation index. The EV is the compensation
640     * index multiplied by the step value. If unsupported, both this method and
641     * {@link #getMaxExposureCompensation()} return 0.
642     */
643    public final int getMinExposureCompensation() {
644        return mMinExposureCompensation;
645    }
646
647    /**
648     * @return The max exposure compensation index. The EV is the compensation
649     * index multiplied by the step value. If unsupported, both this method and
650     * {@link #getMinExposureCompensation()} return 0.
651     */
652    public final int getMaxExposureCompensation() {
653        return mMaxExposureCompensation;
654    }
655
656    /**
657     * @return The exposure compensation step. The EV is the compensation index
658     * multiplied by the step value.
659     */
660    public final float getExposureCompensationStep() {
661        return mExposureCompensationStep;
662    }
663
664    /**
665     * @return The max number of faces supported by the face detection. 0 if
666     * unsupported.
667     */
668    public final int getMaxNumOfFacesSupported() {
669        return mMaxNumOfFacesSupported;
670    }
671
672    /**
673     * @return The stringifier used by this instance.
674     */
675    public Stringifier getStringifier() {
676        return mStringifier;
677    }
678
679    private boolean zoomCheck(final CameraSettings settings) {
680        final float ratio = settings.getCurrentZoomRatio();
681        if (!supports(Feature.ZOOM)) {
682            if (ratio != ZOOM_RATIO_UNZOOMED) {
683                Log.v(TAG, "Zoom is not supported");
684                return false;
685            }
686        } else {
687            if (settings.getCurrentZoomRatio() > getMaxZoomRatio()) {
688                Log.v(TAG, "Zoom ratio is not supported: ratio = " +
689                        settings.getCurrentZoomRatio());
690                return false;
691            }
692        }
693        return true;
694    }
695
696    private boolean exposureCheck(final CameraSettings settings) {
697        final int index = settings.getExposureCompensationIndex();
698        if (index > getMaxExposureCompensation() || index < getMinExposureCompensation()) {
699            Log.v(TAG, "Exposure compensation index is not supported. Min = " +
700                    getMinExposureCompensation() + ", max = " + getMaxExposureCompensation() + "," +
701                    " setting = " + index);
702            return false;
703        }
704        return true;
705    }
706
707    private boolean focusCheck(final CameraSettings settings) {
708        FocusMode focusMode = settings.getCurrentFocusMode();
709        if (!supports(focusMode)) {
710            if (supports(FocusMode.FIXED)) {
711                // Workaround for devices whose templates define defaults they don't really support
712                // TODO: Remove workaround (b/17177436)
713                Log.w(TAG, "Focus mode not supported... trying FIXED");
714                settings.setFocusMode(FocusMode.FIXED);
715            } else {
716                Log.v(TAG, "Focus mode not supported:" +
717                        (focusMode != null ? focusMode.name() : "null"));
718                return false;
719            }
720        }
721        return true;
722    }
723
724    private boolean flashCheck(final CameraSettings settings) {
725        FlashMode flashMode = settings.getCurrentFlashMode();
726        if (!supports(flashMode)) {
727            Log.v(TAG,
728                    "Flash mode not supported:" + (flashMode != null ? flashMode.name() : "null"));
729            return false;
730        }
731        return true;
732    }
733
734    private boolean photoSizeCheck(final CameraSettings settings) {
735        Size photoSize = settings.getCurrentPhotoSize();
736        if (mSupportedPhotoSizes.contains(photoSize)) {
737            return true;
738        }
739        Log.v(TAG, "Unsupported photo size:" + photoSize);
740        return false;
741    }
742
743    private boolean previewSizeCheck(final CameraSettings settings) {
744        final Size previewSize = settings.getCurrentPreviewSize();
745        if (mSupportedPreviewSizes.contains(previewSize)) {
746            return true;
747        }
748        Log.v(TAG, "Unsupported preview size:" + previewSize);
749        return false;
750    }
751
752    private boolean videoStabilizationCheck(final CameraSettings settings) {
753        if (!settings.isVideoStabilizationEnabled() || supports(Feature.VIDEO_STABILIZATION)) {
754            return true;
755        }
756        Log.v(TAG, "Video stabilization is not supported");
757        return false;
758    }
759}
760