191acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang/* 291acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang * Copyright (C) 2009 The Android Open Source Project 391acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang * 491acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang * Licensed under the Apache License, Version 2.0 (the "License"); 591acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang * you may not use this file except in compliance with the License. 691acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang * You may obtain a copy of the License at 791acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang * 891acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang * http://www.apache.org/licenses/LICENSE-2.0 991acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang * 1091acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang * Unless required by applicable law or agreed to in writing, software 1191acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang * distributed under the License is distributed on an "AS IS" BASIS, 1291acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1391acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang * See the License for the specific language governing permissions and 1491acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang * limitations under the License. 1591acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang */ 1691acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang 17cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Changpackage com.android.camera; 18cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 193f3c857e3f34650c15d764810335024654b0fcc3Owen Linimport static com.android.camera.Util.Assert; 203f3c857e3f34650c15d764810335024654b0fcc3Owen Lin 217add00693c1ec910bc8700fe046ee18cbe4e1148Wu-cheng Liimport android.hardware.Camera.CameraInfo; 224c9266ef8f43c6b057b6f560645475272c66ff8aChih-Chung Changimport android.hardware.Camera.Parameters; 23f6ef7b960f610d557f0bab924b9f7928b46f6f0aOwen Linimport android.os.Build; 24cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Changimport android.os.Handler; 25cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Changimport android.os.HandlerThread; 26cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Changimport android.os.Looper; 27cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Changimport android.os.Message; 28cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Changimport android.util.Log; 29cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 30475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Tingimport com.android.camera.CameraManager.CameraProxy; 31475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting 32cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Changimport java.io.IOException; 33f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Changimport java.text.SimpleDateFormat; 34f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Changimport java.util.ArrayList; 35f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Changimport java.util.Date; 36cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 37271b3095b9f763421c0547109da9de774795072dChih-Chung Chang/** 38271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * The class is used to hold an {@code android.hardware.Camera} instance. 39271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * 40271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * <p>The {@code open()} and {@code release()} calls are similar to the ones 41271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * in {@code android.hardware.Camera}. The difference is if {@code keep()} is 42271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * called before {@code release()}, CameraHolder will try to hold the {@code 43271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * android.hardware.Camera} instance for a while, so if {@code open()} is 44271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * called soon after, we can avoid the cost of {@code open()} in {@code 45271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * android.hardware.Camera}. 46271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * 47ed19156e705efb982b351653a3ea9b15f5a08df7Wu-cheng Li * <p>This is used in switching between different modules. 48271b3095b9f763421c0547109da9de774795072dChih-Chung Chang */ 49cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Changpublic class CameraHolder { 50cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang private static final String TAG = "CameraHolder"; 517717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li private static final int KEEP_CAMERA_TIMEOUT = 3000; // 3 seconds 52475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting private CameraProxy mCameraDevice; 531df224649e0663c4bc6366f299e060d5967f526dPin Ting private long mKeepBeforeTime; // Keep the Camera before this time. 543f3c857e3f34650c15d764810335024654b0fcc3Owen Lin private final Handler mHandler; 551df224649e0663c4bc6366f299e060d5967f526dPin Ting private boolean mCameraOpened; // true if camera is opened 561df224649e0663c4bc6366f299e060d5967f526dPin Ting private final int mNumberOfCameras; 57003dd5a52457c024a0f99a2bb222bfc6ad70bbe5Wu-cheng Li private int mCameraId = -1; // current camera id 581df224649e0663c4bc6366f299e060d5967f526dPin Ting private int mBackCameraId = -1; 591df224649e0663c4bc6366f299e060d5967f526dPin Ting private int mFrontCameraId = -1; 601df224649e0663c4bc6366f299e060d5967f526dPin Ting private final CameraInfo[] mInfo; 61475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting private static CameraProxy mMockCamera[]; 6219c0b7882d14679bc0fe5d25c4e1ea34350d0b8dWu-cheng Li private static CameraInfo mMockCameraInfo[]; 63cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 64f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang /* Debug double-open issue */ 65f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang private static final boolean DEBUG_OPEN_RELEASE = true; 66f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang private static class OpenReleaseState { 67f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang long time; 68f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang int id; 69f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang String device; 70f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang String[] stack; 71f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang } 72f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang private static ArrayList<OpenReleaseState> sOpenReleaseStates = 73f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang new ArrayList<OpenReleaseState>(); 74f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang private static SimpleDateFormat sDateFormat = new SimpleDateFormat( 75f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang "yyyy-MM-dd HH:mm:ss.SSS"); 76f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang 77f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang private static synchronized void collectState(int id, CameraProxy device) { 78f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang OpenReleaseState s = new OpenReleaseState(); 79f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang s.time = System.currentTimeMillis(); 80f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang s.id = id; 81f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang if (device == null) { 82f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang s.device = "(null)"; 83f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang } else { 84f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang s.device = device.toString(); 85f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang } 86f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang 87f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang StackTraceElement[] stack = Thread.currentThread().getStackTrace(); 88f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang String[] lines = new String[stack.length]; 89f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang for (int i = 0; i < stack.length; i++) { 90f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang lines[i] = stack[i].toString(); 91f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang } 92f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang s.stack = lines; 93f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang 94f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang if (sOpenReleaseStates.size() > 10) { 95f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang sOpenReleaseStates.remove(0); 96f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang } 97f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang sOpenReleaseStates.add(s); 98f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang } 99f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang 100f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang private static synchronized void dumpStates() { 101f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang for (int i = sOpenReleaseStates.size() - 1; i >= 0; i--) { 102f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang OpenReleaseState s = sOpenReleaseStates.get(i); 103f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang String date = sDateFormat.format(new Date(s.time)); 104f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang Log.d(TAG, "State " + i + " at " + date); 105f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang Log.d(TAG, "mCameraId = " + s.id + ", mCameraDevice = " + s.device); 106f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang Log.d(TAG, "Stack:"); 107f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang for (int j = 0; j < s.stack.length; j++) { 108f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang Log.d(TAG, " " + s.stack[j]); 109f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang } 110f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang } 111f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang } 112f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang 1134c9266ef8f43c6b057b6f560645475272c66ff8aChih-Chung Chang // We store the camera parameters when we actually open the device, 1144c9266ef8f43c6b057b6f560645475272c66ff8aChih-Chung Chang // so we can restore them in the subsequent open() requests by the user. 115ed19156e705efb982b351653a3ea9b15f5a08df7Wu-cheng Li // This prevents the parameters set by PhotoModule used by VideoModule 116ed19156e705efb982b351653a3ea9b15f5a08df7Wu-cheng Li // inadvertently. 1174c9266ef8f43c6b057b6f560645475272c66ff8aChih-Chung Chang private Parameters mParameters; 1184c9266ef8f43c6b057b6f560645475272c66ff8aChih-Chung Chang 119cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang // Use a singleton. 120cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang private static CameraHolder sHolder; 121cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang public static synchronized CameraHolder instance() { 122cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang if (sHolder == null) { 123cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang sHolder = new CameraHolder(); 124cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 125cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang return sHolder; 126cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 127cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 128cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang private static final int RELEASE_CAMERA = 1; 129cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang private class MyHandler extends Handler { 130cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang MyHandler(Looper looper) { 131cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang super(looper); 132cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 133cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 134cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang @Override 135cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang public void handleMessage(Message msg) { 136cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang switch(msg.what) { 137cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang case RELEASE_CAMERA: 138dd6600e7f0adf322e5a8fcb0ed5389b14655106eOwen Lin synchronized (CameraHolder.this) { 139dd6600e7f0adf322e5a8fcb0ed5389b14655106eOwen Lin // In 'CameraHolder.open', the 'RELEASE_CAMERA' message 140dd6600e7f0adf322e5a8fcb0ed5389b14655106eOwen Lin // will be removed if it is found in the queue. However, 141dd6600e7f0adf322e5a8fcb0ed5389b14655106eOwen Lin // there is a chance that this message has been handled 142dd6600e7f0adf322e5a8fcb0ed5389b14655106eOwen Lin // before being removed. So, we need to add a check 143dd6600e7f0adf322e5a8fcb0ed5389b14655106eOwen Lin // here: 1448147561670f166bc090e60cbb271555cde86a9c9Wu-cheng Li if (!mCameraOpened) release(); 145dd6600e7f0adf322e5a8fcb0ed5389b14655106eOwen Lin } 146cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang break; 147cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 148cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 149cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 150cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 151475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting public static void injectMockCamera(CameraInfo[] info, CameraProxy[] camera) { 15219c0b7882d14679bc0fe5d25c4e1ea34350d0b8dWu-cheng Li mMockCameraInfo = info; 15319c0b7882d14679bc0fe5d25c4e1ea34350d0b8dWu-cheng Li mMockCamera = camera; 15475aa8e0970c88c1ffbe30ea5cf50a3e1ad80c5f5Wu-cheng Li sHolder = new CameraHolder(); 15519c0b7882d14679bc0fe5d25c4e1ea34350d0b8dWu-cheng Li } 15619c0b7882d14679bc0fe5d25c4e1ea34350d0b8dWu-cheng Li 157cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang private CameraHolder() { 158cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang HandlerThread ht = new HandlerThread("CameraHolder"); 159cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang ht.start(); 160cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang mHandler = new MyHandler(ht.getLooper()); 16119c0b7882d14679bc0fe5d25c4e1ea34350d0b8dWu-cheng Li if (mMockCameraInfo != null) { 16219c0b7882d14679bc0fe5d25c4e1ea34350d0b8dWu-cheng Li mNumberOfCameras = mMockCameraInfo.length; 16319c0b7882d14679bc0fe5d25c4e1ea34350d0b8dWu-cheng Li mInfo = mMockCameraInfo; 16475aa8e0970c88c1ffbe30ea5cf50a3e1ad80c5f5Wu-cheng Li } else { 16575aa8e0970c88c1ffbe30ea5cf50a3e1ad80c5f5Wu-cheng Li mNumberOfCameras = android.hardware.Camera.getNumberOfCameras(); 16675aa8e0970c88c1ffbe30ea5cf50a3e1ad80c5f5Wu-cheng Li mInfo = new CameraInfo[mNumberOfCameras]; 16775aa8e0970c88c1ffbe30ea5cf50a3e1ad80c5f5Wu-cheng Li for (int i = 0; i < mNumberOfCameras; i++) { 16875aa8e0970c88c1ffbe30ea5cf50a3e1ad80c5f5Wu-cheng Li mInfo[i] = new CameraInfo(); 16975aa8e0970c88c1ffbe30ea5cf50a3e1ad80c5f5Wu-cheng Li android.hardware.Camera.getCameraInfo(i, mInfo[i]); 17075aa8e0970c88c1ffbe30ea5cf50a3e1ad80c5f5Wu-cheng Li } 17119c0b7882d14679bc0fe5d25c4e1ea34350d0b8dWu-cheng Li } 1721df224649e0663c4bc6366f299e060d5967f526dPin Ting 1731df224649e0663c4bc6366f299e060d5967f526dPin Ting // get the first (smallest) back and first front camera id 174ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang for (int i = 0; i < mNumberOfCameras; i++) { 175003dd5a52457c024a0f99a2bb222bfc6ad70bbe5Wu-cheng Li if (mBackCameraId == -1 && mInfo[i].facing == CameraInfo.CAMERA_FACING_BACK) { 176003dd5a52457c024a0f99a2bb222bfc6ad70bbe5Wu-cheng Li mBackCameraId = i; 1771df224649e0663c4bc6366f299e060d5967f526dPin Ting } else if (mFrontCameraId == -1 && mInfo[i].facing == CameraInfo.CAMERA_FACING_FRONT) { 178003dd5a52457c024a0f99a2bb222bfc6ad70bbe5Wu-cheng Li mFrontCameraId = i; 179003dd5a52457c024a0f99a2bb222bfc6ad70bbe5Wu-cheng Li } 180ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang } 181ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang } 182ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang 183ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang public int getNumberOfCameras() { 184ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang return mNumberOfCameras; 185cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 186cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 1877add00693c1ec910bc8700fe046ee18cbe4e1148Wu-cheng Li public CameraInfo[] getCameraInfo() { 1887add00693c1ec910bc8700fe046ee18cbe4e1148Wu-cheng Li return mInfo; 1897add00693c1ec910bc8700fe046ee18cbe4e1148Wu-cheng Li } 1907add00693c1ec910bc8700fe046ee18cbe4e1148Wu-cheng Li 191475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting public synchronized CameraProxy open(int cameraId) 1923f3c857e3f34650c15d764810335024654b0fcc3Owen Lin throws CameraHardwareException { 193f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang if (DEBUG_OPEN_RELEASE) { 194f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang collectState(cameraId, mCameraDevice); 195f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang if (mCameraOpened) { 196f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang Log.e(TAG, "double open"); 197f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang dumpStates(); 198f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang } 199f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang } 2001df224649e0663c4bc6366f299e060d5967f526dPin Ting Assert(!mCameraOpened); 20143b6525b4aedc5e177163cab7b6f26698a19097fWu-cheng Li if (mCameraDevice != null && mCameraId != cameraId) { 20243b6525b4aedc5e177163cab7b6f26698a19097fWu-cheng Li mCameraDevice.release(); 20343b6525b4aedc5e177163cab7b6f26698a19097fWu-cheng Li mCameraDevice = null; 20443b6525b4aedc5e177163cab7b6f26698a19097fWu-cheng Li mCameraId = -1; 20543b6525b4aedc5e177163cab7b6f26698a19097fWu-cheng Li } 206cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang if (mCameraDevice == null) { 2073f3c857e3f34650c15d764810335024654b0fcc3Owen Lin try { 208ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang Log.v(TAG, "open camera " + cameraId); 20919c0b7882d14679bc0fe5d25c4e1ea34350d0b8dWu-cheng Li if (mMockCameraInfo == null) { 210475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting mCameraDevice = CameraManager.instance().cameraOpen(cameraId); 21119c0b7882d14679bc0fe5d25c4e1ea34350d0b8dWu-cheng Li } else { 21219c0b7882d14679bc0fe5d25c4e1ea34350d0b8dWu-cheng Li if (mMockCamera == null) 21319c0b7882d14679bc0fe5d25c4e1ea34350d0b8dWu-cheng Li throw new RuntimeException(); 21419c0b7882d14679bc0fe5d25c4e1ea34350d0b8dWu-cheng Li mCameraDevice = mMockCamera[cameraId]; 21519c0b7882d14679bc0fe5d25c4e1ea34350d0b8dWu-cheng Li } 21643b6525b4aedc5e177163cab7b6f26698a19097fWu-cheng Li mCameraId = cameraId; 2173f3c857e3f34650c15d764810335024654b0fcc3Owen Lin } catch (RuntimeException e) { 2183f3c857e3f34650c15d764810335024654b0fcc3Owen Lin Log.e(TAG, "fail to connect Camera", e); 219f6ef7b960f610d557f0bab924b9f7928b46f6f0aOwen Lin throw new CameraHardwareException(e); 2203f3c857e3f34650c15d764810335024654b0fcc3Owen Lin } 2214c9266ef8f43c6b057b6f560645475272c66ff8aChih-Chung Chang mParameters = mCameraDevice.getParameters(); 222cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } else { 223cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang try { 224cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang mCameraDevice.reconnect(); 225cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } catch (IOException e) { 226cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang Log.e(TAG, "reconnect failed."); 227f6ef7b960f610d557f0bab924b9f7928b46f6f0aOwen Lin throw new CameraHardwareException(e); 228cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 2294c9266ef8f43c6b057b6f560645475272c66ff8aChih-Chung Chang mCameraDevice.setParameters(mParameters); 230cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 2311df224649e0663c4bc6366f299e060d5967f526dPin Ting mCameraOpened = true; 232cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang mHandler.removeMessages(RELEASE_CAMERA); 23391acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang mKeepBeforeTime = 0; 234cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang return mCameraDevice; 235cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 236cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 237d9e32402bbc5ebaac40ccd2c4b734f8e5743343eOwen Lin /** 238d9e32402bbc5ebaac40ccd2c4b734f8e5743343eOwen Lin * Tries to open the hardware camera. If the camera is being used or 239d9e32402bbc5ebaac40ccd2c4b734f8e5743343eOwen Lin * unavailable then return {@code null}. 240d9e32402bbc5ebaac40ccd2c4b734f8e5743343eOwen Lin */ 241475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687Pin Ting public synchronized CameraProxy tryOpen(int cameraId) { 242d9e32402bbc5ebaac40ccd2c4b734f8e5743343eOwen Lin try { 2431df224649e0663c4bc6366f299e060d5967f526dPin Ting return !mCameraOpened ? open(cameraId) : null; 244d9e32402bbc5ebaac40ccd2c4b734f8e5743343eOwen Lin } catch (CameraHardwareException e) { 245f6ef7b960f610d557f0bab924b9f7928b46f6f0aOwen Lin // In eng build, we throw the exception so that test tool 246f6ef7b960f610d557f0bab924b9f7928b46f6f0aOwen Lin // can detect it and report it 247f6ef7b960f610d557f0bab924b9f7928b46f6f0aOwen Lin if ("eng".equals(Build.TYPE)) { 248f6ef7b960f610d557f0bab924b9f7928b46f6f0aOwen Lin throw new RuntimeException(e); 249f6ef7b960f610d557f0bab924b9f7928b46f6f0aOwen Lin } 250d9e32402bbc5ebaac40ccd2c4b734f8e5743343eOwen Lin return null; 251d9e32402bbc5ebaac40ccd2c4b734f8e5743343eOwen Lin } 252d9e32402bbc5ebaac40ccd2c4b734f8e5743343eOwen Lin } 253d9e32402bbc5ebaac40ccd2c4b734f8e5743343eOwen Lin 254cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang public synchronized void release() { 255f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang if (DEBUG_OPEN_RELEASE) { 256f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang collectState(mCameraId, mCameraDevice); 257f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang } 258f33fc45cc2aa5c7888e7a8aa8a9e49bc960237d7Chih-Chung Chang 259c0ef4802f17a76045b1d32586b963fe90bb5460fBobby Georgescu if (mCameraDevice == null) return; 2608147561670f166bc090e60cbb271555cde86a9c9Wu-cheng Li 261cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang long now = System.currentTimeMillis(); 26291acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang if (now < mKeepBeforeTime) { 2638147561670f166bc090e60cbb271555cde86a9c9Wu-cheng Li if (mCameraOpened) { 2648147561670f166bc090e60cbb271555cde86a9c9Wu-cheng Li mCameraOpened = false; 2658147561670f166bc090e60cbb271555cde86a9c9Wu-cheng Li mCameraDevice.stopPreview(); 2668147561670f166bc090e60cbb271555cde86a9c9Wu-cheng Li } 267cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang mHandler.sendEmptyMessageDelayed(RELEASE_CAMERA, 26891acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang mKeepBeforeTime - now); 269cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang return; 270cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 2718147561670f166bc090e60cbb271555cde86a9c9Wu-cheng Li mCameraOpened = false; 272cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang mCameraDevice.release(); 273cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang mCameraDevice = null; 274788aad96ea4abcda2469867464139daa8087af65Wu-cheng Li // We must set this to null because it has a reference to Camera. 275788aad96ea4abcda2469867464139daa8087af65Wu-cheng Li // Camera has references to the listeners. 276788aad96ea4abcda2469867464139daa8087af65Wu-cheng Li mParameters = null; 27743b6525b4aedc5e177163cab7b6f26698a19097fWu-cheng Li mCameraId = -1; 278cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 279cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 2807717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li public void keep() { 2817717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li keep(KEEP_CAMERA_TIMEOUT); 2827717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li } 2837717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li 2847717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li public synchronized void keep(int time) { 28524e4e6cc25b7628ef15eff703f70b2872575a4ccWu-cheng Li // We allow mCameraOpened in either state for the convenience of the 28624e4e6cc25b7628ef15eff703f70b2872575a4ccWu-cheng Li // calling activity. The activity may not have a chance to call open() 28724e4e6cc25b7628ef15eff703f70b2872575a4ccWu-cheng Li // before the user switches to another activity. 2887717d2f0fc0e1393971cab44b3bba8a0f1297835Wu-cheng Li mKeepBeforeTime = System.currentTimeMillis() + time; 289cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 290003dd5a52457c024a0f99a2bb222bfc6ad70bbe5Wu-cheng Li 291003dd5a52457c024a0f99a2bb222bfc6ad70bbe5Wu-cheng Li public int getBackCameraId() { 292003dd5a52457c024a0f99a2bb222bfc6ad70bbe5Wu-cheng Li return mBackCameraId; 293003dd5a52457c024a0f99a2bb222bfc6ad70bbe5Wu-cheng Li } 294003dd5a52457c024a0f99a2bb222bfc6ad70bbe5Wu-cheng Li 295003dd5a52457c024a0f99a2bb222bfc6ad70bbe5Wu-cheng Li public int getFrontCameraId() { 296003dd5a52457c024a0f99a2bb222bfc6ad70bbe5Wu-cheng Li return mFrontCameraId; 297003dd5a52457c024a0f99a2bb222bfc6ad70bbe5Wu-cheng Li } 298cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang} 299