blob: b85aefbe1ca8343807edd20120c6a8cb7b54bf33 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
package com.android.camera;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import java.io.IOException;
import static com.android.camera.Util.Assert;
//
// CameraHolder is used to hold an android.hardware.Camera instance.
//
// The open() and release() calls are similar to the ones in
// android.hardware.Camera. The difference is if keep() is called before
// release(), CameraHolder will try to hold the android.hardware.Camera
// instance for a while, so if open() call called soon after, we can avoid
// the cost of open() in android.hardware.Camera.
//
// This is used in switching between Camera and VideoCamera activities.
//
public class CameraHolder {
private static final String TAG = "CameraHolder";
private android.hardware.Camera mCameraDevice;
private long keepBeforeTime = 0; // Keep the Camera before this time.
private Handler mHandler;
private int users = 0; // number of open() - number of release()
// Use a singleton.
private static CameraHolder sHolder;
public static synchronized CameraHolder instance() {
if (sHolder == null) {
sHolder = new CameraHolder();
}
return sHolder;
}
private static final int RELEASE_CAMERA = 1;
private class MyHandler extends Handler {
MyHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
switch(msg.what) {
case RELEASE_CAMERA:
releaseCamera();
break;
}
}
}
private CameraHolder() {
HandlerThread ht = new HandlerThread("CameraHolder");
ht.start();
mHandler = new MyHandler(ht.getLooper());
}
public synchronized android.hardware.Camera open() {
Assert(users == 0);
if (mCameraDevice == null) {
mCameraDevice = android.hardware.Camera.open();
} else {
try {
mCameraDevice.reconnect();
} catch (IOException e) {
Log.e(TAG, "reconnect failed.");
}
}
++users;
mHandler.removeMessages(RELEASE_CAMERA);
keepBeforeTime = 0;
return mCameraDevice;
}
public synchronized void release() {
Assert(users == 1);
--users;
mCameraDevice.stopPreview();
releaseCamera();
}
private synchronized void releaseCamera() {
Assert(users == 0);
Assert(mCameraDevice != null);
long now = System.currentTimeMillis();
if (now < keepBeforeTime) {
mHandler.sendEmptyMessageDelayed(RELEASE_CAMERA,
keepBeforeTime - now);
return;
}
mCameraDevice.release();
mCameraDevice = null;
}
public synchronized void keep() {
// We allow (users == 0) for the convenience of the calling activity.
// The activity may not have a chance to call open() before the user
// choose the menu item to switch to another activity.
Assert(users == 1 || users == 0);
// Keep the camera instance for 3 seconds.
keepBeforeTime = System.currentTimeMillis() + 3000;
}
}
|