CameraController.java revision 6190c36db653e848f29d1caefc4fa1bb61e8a662
120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong/*
220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * Copyright (C) 2013 The Android Open Source Project
320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong *
420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * Licensed under the Apache License, Version 2.0 (the "License");
520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * you may not use this file except in compliance with the License.
620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * You may obtain a copy of the License at
720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong *
820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong *      http://www.apache.org/licenses/LICENSE-2.0
920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong *
1020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * Unless required by applicable law or agreed to in writing, software
1120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * distributed under the License is distributed on an "AS IS" BASIS,
1220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * See the License for the specific language governing permissions and
1420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * limitations under the License.
1520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong */
1620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
1720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kongpackage com.android.camera.app;
1820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
1920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kongimport android.content.Context;
2020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kongimport android.hardware.Camera;
2120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kongimport android.os.Handler;
2220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
2320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kongimport com.android.camera.CameraDisabledException;
245596b4c902dcb685928b43678f428746ca5ffd08Angus Kongimport com.android.camera.debug.Log;
2520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kongimport com.android.camera.util.CameraUtil;
265a344964cb003525727c31d295ca3a592c245606Sol Boucherimport com.android.ex.camera2.portability.CameraDeviceInfo;
275a344964cb003525727c31d295ca3a592c245606Sol Boucherimport com.android.ex.camera2.portability.CameraAgent;
285a344964cb003525727c31d295ca3a592c245606Sol Boucherimport com.android.ex.camera2.portability.CameraAgent.CameraExceptionCallback;
2920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
3020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong/**
3120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * A class which implements {@link com.android.camera.app.CameraProvider} used
3220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * by {@link com.android.camera.CameraActivity}.
3320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong * TODO: Make this class package private.
3420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong */
355a344964cb003525727c31d295ca3a592c245606Sol Boucherpublic class CameraController implements CameraAgent.CameraOpenCallback, CameraProvider {
365596b4c902dcb685928b43678f428746ca5ffd08Angus Kong    private static final Log.Tag TAG = new Log.Tag("CameraController");
37432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong    private static final int EMPTY_REQUEST = -1;
38846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling    private final Context mContext;
395a344964cb003525727c31d295ca3a592c245606Sol Boucher    private CameraAgent.CameraOpenCallback mCallbackReceiver;
40846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling    private final Handler mCallbackHandler;
415a344964cb003525727c31d295ca3a592c245606Sol Boucher    private final CameraAgent mCameraAgent;
42c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong    private CameraDeviceInfo mInfo;
4320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
445a344964cb003525727c31d295ca3a592c245606Sol Boucher    private CameraAgent.CameraProxy mCameraProxy;
45432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong    private int mRequestingCameraId = EMPTY_REQUEST;
4620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
4720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    /**
4820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong     * Constructor.
4920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong     *
5020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong     * @param context The {@link android.content.Context} used to check if the
5120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong     *                camera is disabled.
5220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong     * @param handler The {@link android.os.Handler} to post the camera
5320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong     *                callbacks to.
5420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong     * @param cameraManager Used for camera open/close.
5520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong     */
565a344964cb003525727c31d295ca3a592c245606Sol Boucher    public CameraController(Context context, CameraAgent.CameraOpenCallback callbackReceiver,
575a344964cb003525727c31d295ca3a592c245606Sol Boucher            Handler handler, CameraAgent cameraManager) {
5820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong        mContext = context;
5920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong        mCallbackReceiver = callbackReceiver;
6020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong        mCallbackHandler = handler;
615a344964cb003525727c31d295ca3a592c245606Sol Boucher        mCameraAgent = cameraManager;
625a344964cb003525727c31d295ca3a592c245606Sol Boucher        mInfo = mCameraAgent.getCameraDeviceInfo();
63c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        if (mInfo == null && mCallbackReceiver != null) {
64c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong            mCallbackReceiver.onDeviceOpenFailure(-1, "GETTING_CAMERA_INFO");
65c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        }
6620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    }
6720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
6820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    @Override
69630d55ba8111357730119899565026be503264c0Erin Dahlgren    public void setCameraDefaultExceptionCallback(CameraExceptionCallback callback,
70630d55ba8111357730119899565026be503264c0Erin Dahlgren            Handler handler) {
715a344964cb003525727c31d295ca3a592c245606Sol Boucher        mCameraAgent.setCameraDefaultExceptionCallback(callback, handler);
72630d55ba8111357730119899565026be503264c0Erin Dahlgren    }
73630d55ba8111357730119899565026be503264c0Erin Dahlgren
74630d55ba8111357730119899565026be503264c0Erin Dahlgren    @Override
7520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    public Camera.CameraInfo[] getCameraInfo() {
76c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        if (mInfo == null) {
77c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong            return null;
78c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        }
79c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        return mInfo.getCameraInfos();
8020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    }
8120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
8220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    @Override
836190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren    public int getCurrentCameraId() {
846190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren        if (mCameraProxy != null) {
856190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren            return mCameraProxy.getCameraId();
866190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren        } else {
876190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren            return -1;
886190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren        }
896190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren    }
906190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren
916190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren    @Override
9220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    public int getNumberOfCameras() {
93c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        if (mInfo == null) {
94c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong            return 0;
95c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        }
96c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        return mInfo.getNumberOfCameras();
9720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    }
9820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
9920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    @Override
10020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    public int getFirstBackCameraId() {
101c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        if (mInfo == null) {
102c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong            return -1;
103c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        }
104c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        return mInfo.getFirstBackCameraId();
10520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    }
10620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
10720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    @Override
10820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    public int getFirstFrontCameraId() {
109c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        if (mInfo == null) {
110c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong            return -1;
111c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        }
112c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        return mInfo.getFirstFrontCameraId();
11320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    }
11420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
11520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    @Override
11639b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong    public boolean isFrontFacingCamera(int id) {
117c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        if (mInfo == null) {
118c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong            return false;
119c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        }
120c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        if (id >= mInfo.getCameraInfos().length || mInfo.getCameraInfos()[id] == null) {
12139b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong            Log.e(TAG, "Camera info not available:" + id);
12239b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong            return false;
12339b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong        }
124c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        return (mInfo.getCameraInfos()[id].facing == Camera.CameraInfo.CAMERA_FACING_FRONT);
12539b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong    }
12639b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong
12739b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong    @Override
12839b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong    public boolean isBackFacingCamera(int id) {
129c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        if (mInfo == null) {
130c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong            return false;
131c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        }
132c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        if (id >= mInfo.getCameraInfos().length || mInfo.getCameraInfos()[id] == null) {
13339b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong            Log.e(TAG, "Camera info not available:" + id);
13439b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong            return false;
13539b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong        }
136c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        return (mInfo.getCameraInfos()[id].facing == Camera.CameraInfo.CAMERA_FACING_BACK);
13739b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong    }
13839b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong
13939b460b805adaa54f310d8637868b3a5c792b2f5Angus Kong    @Override
1405a344964cb003525727c31d295ca3a592c245606Sol Boucher    public void onCameraOpened(CameraAgent.CameraProxy camera) {
1410b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong        Log.v(TAG, "onCameraOpened");
1420b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong        if (mRequestingCameraId != camera.getCameraId()) {
1430b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong            // Not requesting any camera or not waiting for this one.
144f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong            return;
145f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong        }
1460b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong        mCameraProxy = camera;
147432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong        mRequestingCameraId = EMPTY_REQUEST;
1480fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling        if (mCallbackReceiver != null) {
1490fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling            mCallbackReceiver.onCameraOpened(camera);
1500fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling        }
15120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    }
15220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
15320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    @Override
15420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    public void onCameraDisabled(int cameraId) {
1550fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling        if (mCallbackReceiver != null) {
1560fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling            mCallbackReceiver.onCameraDisabled(cameraId);
1570fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling        }
15820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    }
15920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
16020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    @Override
1611b9d4fb6f649262e491c0fa743229b4930a87802Angus Kong    public void onDeviceOpenFailure(int cameraId, String info) {
1620fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling        if (mCallbackReceiver != null) {
1631b9d4fb6f649262e491c0fa743229b4930a87802Angus Kong            mCallbackReceiver.onDeviceOpenFailure(cameraId, info);
1640fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling        }
16520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    }
16620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
16720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    @Override
1680b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong    public void onDeviceOpenedAlready(int cameraId, String info) {
1690fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling        if (mCallbackReceiver != null) {
1700b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong            mCallbackReceiver.onDeviceOpenedAlready(cameraId, info);
1710fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling        }
17262753ae94be2ae7c08bf24ebcf1c462975af230fAngus Kong    }
17362753ae94be2ae7c08bf24ebcf1c462975af230fAngus Kong
17462753ae94be2ae7c08bf24ebcf1c462975af230fAngus Kong    @Override
1755a344964cb003525727c31d295ca3a592c245606Sol Boucher    public void onReconnectionFailure(CameraAgent mgr, String info) {
1760fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling        if (mCallbackReceiver != null) {
1770b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong            mCallbackReceiver.onReconnectionFailure(mgr, info);
1780fed7e62bfa0d8351b91d3531228a113637963a3Sascha Haeberling        }
17920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    }
18020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
18120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    @Override
18220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    public void requestCamera(int id) {
183432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong        // Based on
184432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong        // (mRequestingCameraId == id, mRequestingCameraId == EMPTY_REQUEST),
185432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong        // we have (T, T), (T, F), (F, T), (F, F).
186432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong        // (T, T): implies id == EMPTY_REQUEST. We don't allow this to happen
187432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong        //         here. Return.
188432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong        // (F, F): A previous request hasn't been fulfilled yet. Return.
189432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong        // (T, F): Already requested the same camera. No-op. Return.
190432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong        // (F, T): Nothing is going on. Continue.
191432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong        if (mRequestingCameraId != EMPTY_REQUEST || mRequestingCameraId == id) {
19220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong            return;
19320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong        }
194c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        if (mInfo == null) {
195c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong            return;
196c44c5d93a681d98719dfffdf7223c694e1cab715Angus Kong        }
19720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong        mRequestingCameraId = id;
19820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong        if (mCameraProxy == null) {
19920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong            // No camera yet.
2005a344964cb003525727c31d295ca3a592c245606Sol Boucher            checkAndOpenCamera(mContext, mCameraAgent, id, mCallbackHandler, this);
20120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong        } else if (mCameraProxy.getCameraId() != id) {
20220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong            // Already has another camera opened.
2035a344964cb003525727c31d295ca3a592c245606Sol Boucher            mCameraAgent.closeCamera(mCameraProxy, false);
2045a344964cb003525727c31d295ca3a592c245606Sol Boucher            checkAndOpenCamera(mContext, mCameraAgent, id, mCallbackHandler, this);
20520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong        } else {
20620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong            // The same camera, just do a reconnect.
2070b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong            Log.v(TAG, "reconnecting to use the existing camera");
20820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong            mCameraProxy.reconnect(mCallbackHandler, this);
20920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong            mCameraProxy = null;
21020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong        }
21120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    }
21220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
21320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    @Override
21497e282a3764215ac193726e0d259e55bf94369feAngus Kong    public boolean waitingForCamera() {
21597e282a3764215ac193726e0d259e55bf94369feAngus Kong        return mRequestingCameraId != EMPTY_REQUEST;
21697e282a3764215ac193726e0d259e55bf94369feAngus Kong    }
21797e282a3764215ac193726e0d259e55bf94369feAngus Kong
21897e282a3764215ac193726e0d259e55bf94369feAngus Kong    @Override
21920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    public void releaseCamera(int id) {
220f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong        if (mCameraProxy == null) {
221432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong            if (mRequestingCameraId == EMPTY_REQUEST) {
222f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong                // Camera not requested yet.
223f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong                Log.w(TAG, "Trying to release the camera before requesting");
224f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong            }
225f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong            // Camera requested but not available yet.
226432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong            mRequestingCameraId = EMPTY_REQUEST;
227f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong            return;
228f578829a0f9a298fd5e4fdd9081b768f25811599Angus Kong        }
22920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong        if (mCameraProxy.getCameraId() != id) {
23020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong            throw new IllegalStateException("Trying to release an unopened camera.");
23120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong        }
232432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong        mRequestingCameraId = EMPTY_REQUEST;
23320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    }
23420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
235846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling    public void removeCallbackReceiver() {
236846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling        mCallbackReceiver = null;
237846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling    }
238846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling
23920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    /**
24020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong     * Closes the opened camera device.
24120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong     * TODO: Make this method package private.
24220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong     */
2430b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong    public void closeCamera(boolean synced) {
24420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong        Log.v(TAG, "closing camera");
24520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong        mCameraProxy = null;
2465a344964cb003525727c31d295ca3a592c245606Sol Boucher        mCameraAgent.closeCamera(mCameraProxy, synced);
247432c964bb528a28600f19e18e81ff2b6407bb22dAngus Kong        mRequestingCameraId = EMPTY_REQUEST;
24820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    }
24920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
2505a344964cb003525727c31d295ca3a592c245606Sol Boucher    private static void checkAndOpenCamera(Context context, CameraAgent cameraManager,
2515a344964cb003525727c31d295ca3a592c245606Sol Boucher            final int cameraId, Handler handler, final CameraAgent.CameraOpenCallback cb) {
25220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong        try {
25320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong            CameraUtil.throwIfCameraDisabled(context);
2540b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong            cameraManager.openCamera(handler, cameraId, cb);
25520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong        } catch (CameraDisabledException ex) {
25620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong            handler.post(new Runnable() {
25720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong                @Override
25820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong                public void run() {
25920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong                    cb.onCameraDisabled(cameraId);
26020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong                }
26120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong            });
26220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong        }
26320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    }
2644d4a4bc8891bbfc5a7ca842f2981829ac3a716e8Doris Liu
2654d4a4bc8891bbfc5a7ca842f2981829ac3a716e8Doris Liu    public void setOneShotPreviewCallback(Handler handler,
2665a344964cb003525727c31d295ca3a592c245606Sol Boucher            CameraAgent.CameraPreviewDataCallback cb) {
2674d4a4bc8891bbfc5a7ca842f2981829ac3a716e8Doris Liu        mCameraProxy.setOneShotPreviewCallback(handler, cb);
2684d4a4bc8891bbfc5a7ca842f2981829ac3a716e8Doris Liu    }
26920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong}
270