summaryrefslogtreecommitdiffstats
path: root/src/com/android/camera/one/OneCameraManager.java
blob: 13f7dfe0b93d7f7329b74f0179e342d5bbc57fbf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.camera.one;

import android.content.Context;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
import android.util.DisplayMetrics;
import android.view.WindowManager;

import com.android.camera.CameraActivity;
import com.android.camera.debug.Log;
import com.android.camera.debug.Log.Tag;
import com.android.camera.one.OneCamera.Facing;
import com.android.camera.one.OneCamera.OpenCallback;
import com.android.camera.util.Size;

/**
 * The camera manager is responsible for instantiating {@link OneCamera}
 * instances.
 */
public abstract class OneCameraManager {
    private static Tag TAG = new Tag("OneCameraManager");

    /**
     * Attempts to open the camera facing the given direction with the given
     * capture size.
     *
     * @param facing which camera to open. The first camera found in the given
     *            direction will be opened.
     * @param enableHdr if an HDR feature exists, open a camera that supports it
     * @param captureSize the capture size. This must be one of the supported
     *            sizes.
     * @param callback this listener is called when the camera was opened or
     *            when it failed to open.
     */
    public abstract void open(Facing facing, boolean enableHdr, Size captureSize,
            OpenCallback callback);

    /**
     * Returns whether the device has a camera facing the given direction.
     */
    public abstract boolean hasCameraFacing(Facing facing);

    /**
     * Singleton camera manager to be used throughout the app.
     */
    private static OneCameraManager sCameraManager;

    /**
     * Returns a camera manager that is based on Camera2 API, if available, or
     * otherwise uses the portability layer API.
     * <p>
     * The instance is created the first time this method is called and cached
     * in a singleton thereafter, so successive calls are cheap.
     */
    public static OneCameraManager get(CameraActivity activity) {
        if (sCameraManager == null) {
            sCameraManager = create(activity);
        }
        return sCameraManager;
    }

    /**
     * Creates a new camera manager that is based on Camera2 API, if available,
     * or otherwise uses the portability API.
     */
    private static OneCameraManager create(CameraActivity activity) {
        DisplayMetrics displayMetrics = getDisplayMetrics(activity);
        CameraManager cameraManager = (CameraManager) activity
                .getSystemService(Context.CAMERA_SERVICE);
        int maxMemoryMB = activity.getServices().getMemoryManager()
                .getMaxAllowedNativeMemoryAllocation();
        if (cameraManager != null && isCamera2Supported(cameraManager)) {
            return new com.android.camera.one.v2.OneCameraManagerImpl(
                    activity.getApplicationContext(), cameraManager, maxMemoryMB,
                    displayMetrics, activity.getSoundPlayer());
        } else {
            return new com.android.camera.one.v1.OneCameraManagerImpl();
        }
    }

    /**
     * Returns whether the device fully supports API2
     *
     * @param cameraManager the Camera2 API manager.
     * @return If this device is only emulating Camera2 API on top of an older
     *         HAL (such as the Nexus 4, 7 or 10), this method returns false. It
     *         only returns true, if Camera2 is fully supported through newer
     *         HALs.
     */
    private static boolean isCamera2Supported(CameraManager cameraManager) {
        try {
            final String id = cameraManager.getCameraIdList()[0];
            // TODO: We should check for all the flags we need to ensure the
            // device is capable of taking Camera2 API shots. For now, let's
            // accept all device that are either 'partial' or 'full' devices
            // (but not legacy).
            return cameraManager.getCameraCharacteristics(id).get(
                    CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL)
                != CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY;
        } catch (CameraAccessException ex) {
            Log.e(TAG, "Could not access camera to determine hardware-level API support.");
            return false;
        }
    }

    private static DisplayMetrics getDisplayMetrics(Context context) {
        DisplayMetrics displayMetrics = new DisplayMetrics();
        WindowManager wm = (WindowManager)
                context.getSystemService(Context.WINDOW_SERVICE);
        if (wm != null) {
            displayMetrics = new DisplayMetrics();
            wm.getDefaultDisplay().getMetrics(displayMetrics);
        }
        return displayMetrics;
    }
}