CameraHolder.java revision 4c9266ef8f43c6b057b6f560645475272c66ff8a
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 214c9266ef8f43c6b057b6f560645475272c66ff8aChih-Chung Changimport android.hardware.Camera.Parameters; 22f6ef7b960f610d557f0bab924b9f7928b46f6f0aOwen Linimport android.os.Build; 23cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Changimport android.os.Handler; 24cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Changimport android.os.HandlerThread; 25cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Changimport android.os.Looper; 26cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Changimport android.os.Message; 27cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Changimport android.util.Log; 28cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 29cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Changimport java.io.IOException; 30cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 31cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang// 32cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang// CameraHolder is used to hold an android.hardware.Camera instance. 33cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang// 34cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang// The open() and release() calls are similar to the ones in 35cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang// android.hardware.Camera. The difference is if keep() is called before 36cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang// release(), CameraHolder will try to hold the android.hardware.Camera 37cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang// instance for a while, so if open() call called soon after, we can avoid 38cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang// the cost of open() in android.hardware.Camera. 39cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang// 40cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang// This is used in switching between Camera and VideoCamera activities. 41cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang// 42cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Changpublic class CameraHolder { 43cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang private static final String TAG = "CameraHolder"; 44cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang private android.hardware.Camera mCameraDevice; 4591acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang private long mKeepBeforeTime = 0; // Keep the Camera before this time. 463f3c857e3f34650c15d764810335024654b0fcc3Owen Lin private final Handler mHandler; 4791acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang private int mUsers = 0; // number of open() - number of release() 48cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 494c9266ef8f43c6b057b6f560645475272c66ff8aChih-Chung Chang // We store the camera parameters when we actually open the device, 504c9266ef8f43c6b057b6f560645475272c66ff8aChih-Chung Chang // so we can restore them in the subsequent open() requests by the user. 514c9266ef8f43c6b057b6f560645475272c66ff8aChih-Chung Chang // This prevents the parameters set by the Camera activity used by 524c9266ef8f43c6b057b6f560645475272c66ff8aChih-Chung Chang // the VideoCamera activity inadvertently. 534c9266ef8f43c6b057b6f560645475272c66ff8aChih-Chung Chang private Parameters mParameters; 544c9266ef8f43c6b057b6f560645475272c66ff8aChih-Chung Chang 55cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang // Use a singleton. 56cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang private static CameraHolder sHolder; 57cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang public static synchronized CameraHolder instance() { 58cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang if (sHolder == null) { 59cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang sHolder = new CameraHolder(); 60cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 61cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang return sHolder; 62cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 63cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 64cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang private static final int RELEASE_CAMERA = 1; 65cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang private class MyHandler extends Handler { 66cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang MyHandler(Looper looper) { 67cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang super(looper); 68cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 69cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 70cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang @Override 71cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang public void handleMessage(Message msg) { 72cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang switch(msg.what) { 73cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang case RELEASE_CAMERA: 74cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang releaseCamera(); 75cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang break; 76cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 77cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 78cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 79cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 80cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang private CameraHolder() { 81cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang HandlerThread ht = new HandlerThread("CameraHolder"); 82cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang ht.start(); 83cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang mHandler = new MyHandler(ht.getLooper()); 84cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 85cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 863f3c857e3f34650c15d764810335024654b0fcc3Owen Lin public synchronized android.hardware.Camera open() 873f3c857e3f34650c15d764810335024654b0fcc3Owen Lin throws CameraHardwareException { 8891acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang Assert(mUsers == 0); 89cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang if (mCameraDevice == null) { 903f3c857e3f34650c15d764810335024654b0fcc3Owen Lin try { 913f3c857e3f34650c15d764810335024654b0fcc3Owen Lin mCameraDevice = android.hardware.Camera.open(); 923f3c857e3f34650c15d764810335024654b0fcc3Owen Lin } catch (RuntimeException e) { 933f3c857e3f34650c15d764810335024654b0fcc3Owen Lin Log.e(TAG, "fail to connect Camera", e); 94f6ef7b960f610d557f0bab924b9f7928b46f6f0aOwen Lin throw new CameraHardwareException(e); 953f3c857e3f34650c15d764810335024654b0fcc3Owen Lin } 964c9266ef8f43c6b057b6f560645475272c66ff8aChih-Chung Chang mParameters = mCameraDevice.getParameters(); 97cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } else { 98cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang try { 99cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang mCameraDevice.reconnect(); 100cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } catch (IOException e) { 101cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang Log.e(TAG, "reconnect failed."); 102f6ef7b960f610d557f0bab924b9f7928b46f6f0aOwen Lin throw new CameraHardwareException(e); 103cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 1044c9266ef8f43c6b057b6f560645475272c66ff8aChih-Chung Chang mCameraDevice.setParameters(mParameters); 105cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 10691acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang ++mUsers; 107cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang mHandler.removeMessages(RELEASE_CAMERA); 10891acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang mKeepBeforeTime = 0; 109cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang return mCameraDevice; 110cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 111cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 112d9e32402bbc5ebaac40ccd2c4b734f8e5743343eOwen Lin /** 113d9e32402bbc5ebaac40ccd2c4b734f8e5743343eOwen Lin * Tries to open the hardware camera. If the camera is being used or 114d9e32402bbc5ebaac40ccd2c4b734f8e5743343eOwen Lin * unavailable then return {@code null}. 115d9e32402bbc5ebaac40ccd2c4b734f8e5743343eOwen Lin */ 116d9e32402bbc5ebaac40ccd2c4b734f8e5743343eOwen Lin public synchronized android.hardware.Camera tryOpen() { 117d9e32402bbc5ebaac40ccd2c4b734f8e5743343eOwen Lin try { 118d9e32402bbc5ebaac40ccd2c4b734f8e5743343eOwen Lin return mUsers == 0 ? open() : null; 119d9e32402bbc5ebaac40ccd2c4b734f8e5743343eOwen Lin } catch (CameraHardwareException e) { 120f6ef7b960f610d557f0bab924b9f7928b46f6f0aOwen Lin // In eng build, we throw the exception so that test tool 121f6ef7b960f610d557f0bab924b9f7928b46f6f0aOwen Lin // can detect it and report it 122f6ef7b960f610d557f0bab924b9f7928b46f6f0aOwen Lin if ("eng".equals(Build.TYPE)) { 123f6ef7b960f610d557f0bab924b9f7928b46f6f0aOwen Lin throw new RuntimeException(e); 124f6ef7b960f610d557f0bab924b9f7928b46f6f0aOwen Lin } 125d9e32402bbc5ebaac40ccd2c4b734f8e5743343eOwen Lin return null; 126d9e32402bbc5ebaac40ccd2c4b734f8e5743343eOwen Lin } 127d9e32402bbc5ebaac40ccd2c4b734f8e5743343eOwen Lin } 128d9e32402bbc5ebaac40ccd2c4b734f8e5743343eOwen Lin 129cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang public synchronized void release() { 13091acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang Assert(mUsers == 1); 13191acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang --mUsers; 132cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang mCameraDevice.stopPreview(); 133cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang releaseCamera(); 134cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 135cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 136cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang private synchronized void releaseCamera() { 13791acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang Assert(mUsers == 0); 138cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang Assert(mCameraDevice != null); 139cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang long now = System.currentTimeMillis(); 14091acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang if (now < mKeepBeforeTime) { 141cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang mHandler.sendEmptyMessageDelayed(RELEASE_CAMERA, 14291acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang mKeepBeforeTime - now); 143cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang return; 144cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 145cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang mCameraDevice.release(); 146cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang mCameraDevice = null; 147cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 148cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang 149cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang public synchronized void keep() { 15091acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang // We allow (mUsers == 0) for the convenience of the calling activity. 1515075f53df86f3dcb0a46fd6353057260ad480f43Chih-Chung Chang // The activity may not have a chance to call open() before the user 1525075f53df86f3dcb0a46fd6353057260ad480f43Chih-Chung Chang // choose the menu item to switch to another activity. 15391acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang Assert(mUsers == 1 || mUsers == 0); 154cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang // Keep the camera instance for 3 seconds. 15591acfc99279d5ece7ac9cb2d7a2980eb0d3b50daChih-Chung Chang mKeepBeforeTime = System.currentTimeMillis() + 3000; 156cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang } 157cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang} 158