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