Skip to content

Commit 8d3c318

Browse files
Wu-cheng LiAndroid (Google) Code Review
authored andcommitted
Merge "Add a new camera open API that allows taking the ownership."
2 parents 0c26976 + a1c41e1 commit 8d3c318

File tree

9 files changed

+240
-54
lines changed

9 files changed

+240
-54
lines changed

core/java/android/hardware/Camera.java

Lines changed: 76 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,50 @@ public static class CameraInfo {
236236
/**
237237
* Creates a new Camera object to access a particular hardware camera.
238238
*
239+
* <p>When <code>force</code> is set to false, this will throw an exception
240+
* if the same camera is already opened by other clients. If true, the other
241+
* client will be disconnected from the camera they opened. If the device
242+
* can only support one camera running at a time, all camera-using clients
243+
* will be disconnected from their cameras.
244+
*
245+
* <p>A camera being held by an application can be taken away by other
246+
* applications at any time. Before the camera is taken, applications will
247+
* get {@link #CAMERA_ERROR_RELEASED} and have some time to clean up. Apps
248+
* receiving this callback must immediately stop video recording and then
249+
* call {@link #release()} on their camera object. Otherwise, it will be
250+
* released by the frameworks in a short time. After receiving
251+
* CAMERA_ERROR_RELEASED, apps should not call any method except <code>
252+
* release</code> and {@link #isReleased()}. After a camera is taken away,
253+
* all methods will throw exceptions except <code>isReleased</code> and
254+
* <code>release</code>. Apps can use <code>isReleased</code> to see if the
255+
* camera has been taken away. If the camera is taken away, the apps can
256+
* silently finish themselves or show a dialog.
257+
*
258+
* <p>Applications with android.permission.KEEP_CAMERA can request to keep
259+
* the camera. That is, the camera will not be taken by other applications
260+
* while it is opened. The permission can only be obtained by trusted
261+
* platform applications, such as those implementing lock screen security
262+
* features.
263+
*
264+
* @param cameraId the hardware camera to access, between 0 and
265+
* {@link #getNumberOfCameras()}-1.
266+
* @param force true to take the ownership from the existing client if the
267+
* camera has been opened by other clients.
268+
* @param keep true if the applications do not want other apps to take the
269+
* camera. Only the apps with android.permission.KEEP_CAMERA can keep
270+
* the camera.
271+
* @return a new Camera object, connected, locked and ready for use.
272+
* @hide
273+
*/
274+
public static Camera open(int cameraId, boolean force, boolean keep) {
275+
return new Camera(cameraId, force, keep);
276+
}
277+
278+
/**
279+
* Creates a new Camera object to access a particular hardware camera. If
280+
* the same camera is opened by other applications, this will throw a
281+
* RuntimeException.
282+
*
239283
* <p>You must call {@link #release()} when you are done using the camera,
240284
* otherwise it will remain locked and be unavailable to other applications.
241285
*
@@ -255,13 +299,13 @@ public static class CameraInfo {
255299
* @param cameraId the hardware camera to access, between 0 and
256300
* {@link #getNumberOfCameras()}-1.
257301
* @return a new Camera object, connected, locked and ready for use.
258-
* @throws RuntimeException if connection to the camera service fails (for
259-
* example, if the camera is in use by another process or device policy
260-
* manager has disabled the camera).
302+
* @throws RuntimeException if opening the camera fails (for example, if the
303+
* camera is in use by another process or device policy manager has
304+
* disabled the camera).
261305
* @see android.app.admin.DevicePolicyManager#getCameraDisabled(android.content.ComponentName)
262306
*/
263307
public static Camera open(int cameraId) {
264-
return new Camera(cameraId);
308+
return new Camera(cameraId, false, false);
265309
}
266310

267311
/**
@@ -276,13 +320,13 @@ public static Camera open() {
276320
for (int i = 0; i < numberOfCameras; i++) {
277321
getCameraInfo(i, cameraInfo);
278322
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
279-
return new Camera(i);
323+
return new Camera(i, false, false);
280324
}
281325
}
282326
return null;
283327
}
284328

285-
Camera(int cameraId) {
329+
Camera(int cameraId, boolean force, boolean keep) {
286330
mShutterCallback = null;
287331
mRawImageCallback = null;
288332
mJpegCallback = null;
@@ -299,7 +343,7 @@ public static Camera open() {
299343
mEventHandler = null;
300344
}
301345

302-
native_setup(new WeakReference<Camera>(this), cameraId);
346+
native_setup(new WeakReference<Camera>(this), cameraId, force, keep);
303347
}
304348

305349
/**
@@ -312,7 +356,8 @@ protected void finalize() {
312356
release();
313357
}
314358

315-
private native final void native_setup(Object camera_this, int cameraId);
359+
private native final void native_setup(Object camera_this, int cameraId,
360+
boolean force, boolean keep);
316361
private native final void native_release();
317362

318363

@@ -326,6 +371,18 @@ public final void release() {
326371
mFaceDetectionRunning = false;
327372
}
328373

374+
/**
375+
* Whether the camera is released. When any camera method throws an
376+
* exception, applications can use this to check whether the camera has been
377+
* taken by other clients. If true, it means other clients have taken the
378+
* camera. The applications can silently finish themselves or show a dialog.
379+
*
380+
* @return whether the camera is released.
381+
* @see #open(int, boolean, boolean)
382+
* @hide
383+
*/
384+
public native final boolean isReleased();
385+
329386
/**
330387
* Unlocks the camera to allow another process to access it.
331388
* Normally, the camera is locked to the process with an active Camera
@@ -1321,6 +1378,17 @@ public Face() {
13211378
*/
13221379
public static final int CAMERA_ERROR_UNKNOWN = 1;
13231380

1381+
/**
1382+
* Camera was released because another client has opened the camera. The
1383+
* application should call {@link #release()} after getting this. The apps
1384+
* should not call any method except <code>release</code> and {@link #isReleased()}
1385+
* after this.
1386+
*
1387+
* @see Camera.ErrorCallback
1388+
* @hide
1389+
*/
1390+
public static final int CAMERA_ERROR_RELEASED = 2;
1391+
13241392
/**
13251393
* Media server died. In this case, the application must release the
13261394
* Camera object and instantiate a new one.

core/jni/android_hardware_Camera.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -457,9 +457,9 @@ static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz,
457457

458458
// connect to camera service
459459
static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
460-
jobject weak_this, jint cameraId)
460+
jobject weak_this, jint cameraId, jboolean force, jboolean keep)
461461
{
462-
sp<Camera> camera = Camera::connect(cameraId);
462+
sp<Camera> camera = Camera::connect(cameraId, force, keep);
463463

464464
if (camera == NULL) {
465465
jniThrowRuntimeException(env, "Fail to connect to camera service");
@@ -700,7 +700,12 @@ static jstring android_hardware_Camera_getParameters(JNIEnv *env, jobject thiz)
700700
sp<Camera> camera = get_native_camera(env, thiz, NULL);
701701
if (camera == 0) return 0;
702702

703-
return env->NewStringUTF(camera->getParameters().string());
703+
String8 params8 = camera->getParameters();
704+
if (params8.isEmpty()) {
705+
jniThrowRuntimeException(env, "getParameters failed (empty parameters)");
706+
return 0;
707+
}
708+
return env->NewStringUTF(params8.string());
704709
}
705710

706711
static void android_hardware_Camera_reconnect(JNIEnv *env, jobject thiz)
@@ -816,6 +821,15 @@ static void android_hardware_Camera_enableFocusMoveCallback(JNIEnv *env, jobject
816821
}
817822
}
818823

824+
static bool android_hardware_Camera_isReleased(JNIEnv *env, jobject thiz)
825+
{
826+
ALOGV("isReleased");
827+
sp<Camera> camera = get_native_camera(env, thiz, NULL);
828+
if (camera == 0) return true;
829+
830+
return (camera->sendCommand(CAMERA_CMD_PING, 0, 0) != NO_ERROR);
831+
}
832+
819833
//-------------------------------------------------
820834

821835
static JNINativeMethod camMethods[] = {
@@ -826,7 +840,7 @@ static JNINativeMethod camMethods[] = {
826840
"(ILandroid/hardware/Camera$CameraInfo;)V",
827841
(void*)android_hardware_Camera_getCameraInfo },
828842
{ "native_setup",
829-
"(Ljava/lang/Object;I)V",
843+
"(Ljava/lang/Object;IZZ)V",
830844
(void*)android_hardware_Camera_native_setup },
831845
{ "native_release",
832846
"()V",
@@ -894,6 +908,9 @@ static JNINativeMethod camMethods[] = {
894908
{ "enableFocusMoveCallback",
895909
"(I)V",
896910
(void *)android_hardware_Camera_enableFocusMoveCallback},
911+
{ "isReleased",
912+
"()Z",
913+
(void *)android_hardware_Camera_isReleased},
897914
};
898915

899916
struct field {

include/camera/Camera.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class Camera : public BnCameraClient, public IBinder::DeathRecipient
7272
static int32_t getNumberOfCameras();
7373
static status_t getCameraInfo(int cameraId,
7474
struct CameraInfo* cameraInfo);
75-
static sp<Camera> connect(int cameraId);
75+
static sp<Camera> connect(int cameraId, bool force, bool keep);
7676
virtual ~Camera();
7777
void init();
7878

include/camera/ICameraService.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class ICameraService : public IInterface
4242
virtual status_t getCameraInfo(int cameraId,
4343
struct CameraInfo* cameraInfo) = 0;
4444
virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient,
45-
int cameraId) = 0;
45+
int cameraId, bool force, bool keep) = 0;
4646
};
4747

4848
// ----------------------------------------------------------------------------

libs/camera/Camera.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,13 +116,13 @@ status_t Camera::getCameraInfo(int cameraId,
116116
return cs->getCameraInfo(cameraId, cameraInfo);
117117
}
118118

119-
sp<Camera> Camera::connect(int cameraId)
119+
sp<Camera> Camera::connect(int cameraId, bool force, bool keep)
120120
{
121121
ALOGV("connect");
122122
sp<Camera> c = new Camera();
123123
const sp<ICameraService>& cs = getCameraService();
124124
if (cs != 0) {
125-
c->mCamera = cs->connect(c, cameraId);
125+
c->mCamera = cs->connect(c, cameraId, force, keep);
126126
}
127127
if (c->mCamera != 0) {
128128
c->mCamera->asBinder()->linkToDeath(c);

libs/camera/ICameraService.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,15 @@ class BpCameraService: public BpInterface<ICameraService>
5656
}
5757

5858
// connect to camera service
59-
virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId)
59+
virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId,
60+
bool force, bool keep)
6061
{
6162
Parcel data, reply;
6263
data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
6364
data.writeStrongBinder(cameraClient->asBinder());
6465
data.writeInt32(cameraId);
66+
data.writeInt32(force);
67+
data.writeInt32(keep);
6568
remote()->transact(BnCameraService::CONNECT, data, &reply);
6669
return interface_cast<ICamera>(reply.readStrongBinder());
6770
}
@@ -93,7 +96,10 @@ status_t BnCameraService::onTransact(
9396
case CONNECT: {
9497
CHECK_INTERFACE(ICameraService, data, reply);
9598
sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder());
96-
sp<ICamera> camera = connect(cameraClient, data.readInt32());
99+
const int cameraId = data.readInt32();
100+
const int force = data.readInt32();
101+
const int keep = data.readInt32();
102+
sp<ICamera> camera = connect(cameraClient, cameraId, force, keep);
97103
reply->writeStrongBinder(camera->asBinder());
98104
return NO_ERROR;
99105
} break;
@@ -105,4 +111,3 @@ status_t BnCameraService::onTransact(
105111
// ----------------------------------------------------------------------------
106112

107113
}; // namespace android
108-

media/libstagefright/CameraSource.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ status_t CameraSource::isCameraAvailable(
182182
int32_t cameraId) {
183183

184184
if (camera == 0) {
185-
mCamera = Camera::connect(cameraId);
185+
mCamera = Camera::connect(cameraId, false, false);
186186
if (mCamera == 0) return -EBUSY;
187187
mCameraFlags &= ~FLAGS_HOT_CAMERA;
188188
} else {

0 commit comments

Comments
 (0)