CameraHolder.java revision 91acfc99279d5ece7ac9cb2d7a2980eb0d3b50da
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 19cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Changimport android.os.Handler; 20cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Changimport android.os.HandlerThread; 21cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Changimport android.os.Looper; 22cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Changimport android.os.Message; 23cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Changimport android.util.Log; 24cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 25cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Changimport java.io.IOException; 26cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 27cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Changimport static com.android.camera.Util.Assert; 28cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 29cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang// 30cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang// CameraHolder is used to hold an android.hardware.Camera instance. 31cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang// 32cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang// The open() and release() calls are similar to the ones in 33cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang// android.hardware.Camera. The difference is if keep() is called before 34cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang// release(), CameraHolder will try to hold the android.hardware.Camera 35cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang// instance for a while, so if open() call called soon after, we can avoid 36cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang// the cost of open() in android.hardware.Camera. 37cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang// 38cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang// This is used in switching between Camera and VideoCamera activities. 39cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang// 40cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Changpublic class CameraHolder { 41cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang private static final String TAG = "CameraHolder"; 42cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang private android.hardware.Camera mCameraDevice; 4391acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang private long mKeepBeforeTime = 0; // Keep the Camera before this time. 44cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang private Handler mHandler; 4591acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang private int mUsers = 0; // number of open() - number of release() 46cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 47cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang // Use a singleton. 48cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang private static CameraHolder sHolder; 49cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang public static synchronized CameraHolder instance() { 50cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang if (sHolder == null) { 51cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang sHolder = new CameraHolder(); 52cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 53cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang return sHolder; 54cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 55cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 56cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang private static final int RELEASE_CAMERA = 1; 57cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang private class MyHandler extends Handler { 58cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang MyHandler(Looper looper) { 59cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang super(looper); 60cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 61cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 62cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang @Override 63cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang public void handleMessage(Message msg) { 64cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang switch(msg.what) { 65cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang case RELEASE_CAMERA: 66cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang releaseCamera(); 67cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang break; 68cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 69cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 70cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 71cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 72cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang private CameraHolder() { 73cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang HandlerThread ht = new HandlerThread("CameraHolder"); 74cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang ht.start(); 75cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang mHandler = new MyHandler(ht.getLooper()); 76cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 77cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 78cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang public synchronized android.hardware.Camera open() { 7991acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang Assert(mUsers == 0); 80cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang if (mCameraDevice == null) { 81cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang mCameraDevice = android.hardware.Camera.open(); 82cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } else { 83cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang try { 84cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang mCameraDevice.reconnect(); 85cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } catch (IOException e) { 86cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang Log.e(TAG, "reconnect failed."); 87cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 88cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 8991acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang ++mUsers; 90cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang mHandler.removeMessages(RELEASE_CAMERA); 9191acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang mKeepBeforeTime = 0; 92cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang return mCameraDevice; 93cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 94cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 95cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang public synchronized void release() { 9691acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang Assert(mUsers == 1); 9791acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang --mUsers; 98cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang mCameraDevice.stopPreview(); 99cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang releaseCamera(); 100cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 101cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 102cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang private synchronized void releaseCamera() { 10391acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang Assert(mUsers == 0); 104cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang Assert(mCameraDevice != null); 105cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang long now = System.currentTimeMillis(); 10691acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang if (now < mKeepBeforeTime) { 107cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang mHandler.sendEmptyMessageDelayed(RELEASE_CAMERA, 10891acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang mKeepBeforeTime - now); 109cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang return; 110cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 111cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang mCameraDevice.release(); 112cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang mCameraDevice = null; 113cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 114cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 115cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang public synchronized void keep() { 11691acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang // We allow (mUsers == 0) for the convenience of the calling activity. 1175075f53df86f3dcb0a46fd6353057260ad480f43Chih-Chung Chang // The activity may not have a chance to call open() before the user 1185075f53df86f3dcb0a46fd6353057260ad480f43Chih-Chung Chang // choose the menu item to switch to another activity. 11991acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang Assert(mUsers == 1 || mUsers == 0); 120cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang // Keep the camera instance for 3 seconds. 12191acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang mKeepBeforeTime = System.currentTimeMillis() + 3000; 122cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 123cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang} 124