summaryrefslogtreecommitdiffstats
path: root/core/java/android/hardware
diff options
context:
space:
mode:
authorChien-Yu Chen <cychen@google.com>2015-02-11 11:23:28 -0800
committerChien-Yu Chen <cychen@google.com>2015-03-03 13:55:07 -0800
commitafa91399fd32ede17d440ec1c3321eee0426123c (patch)
tree2a57bbef2d75c79620a1dc80eed67bc5af9e3834 /core/java/android/hardware
parent1b4b87c2aec1ea5487e7279e92114bb1dca013b6 (diff)
downloadframeworks_base-afa91399fd32ede17d440ec1c3321eee0426123c.zip
frameworks_base-afa91399fd32ede17d440ec1c3321eee0426123c.tar.gz
frameworks_base-afa91399fd32ede17d440ec1c3321eee0426123c.tar.bz2
CameraManager: implement flashlight controls
Implement the flashlight controls and callbacks and update the torch mode states. Bug: 2682206 Change-Id: I59025f34f9ece75dd535166a25c428b8d68c6e4b
Diffstat (limited to 'core/java/android/hardware')
-rw-r--r--core/java/android/hardware/ICameraService.aidl2
-rw-r--r--core/java/android/hardware/ICameraServiceListener.aidl2
-rw-r--r--core/java/android/hardware/camera2/CameraManager.java239
3 files changed, 205 insertions, 38 deletions
diff --git a/core/java/android/hardware/ICameraService.aidl b/core/java/android/hardware/ICameraService.aidl
index 2bc3dd4..9aede01 100644
--- a/core/java/android/hardware/ICameraService.aidl
+++ b/core/java/android/hardware/ICameraService.aidl
@@ -81,4 +81,6 @@ interface ICameraService
int clientUid,
// Container for an ICamera object
out BinderHolder device);
+
+ int setTorchMode(String CameraId, boolean enabled, IBinder clientBinder);
}
diff --git a/core/java/android/hardware/ICameraServiceListener.aidl b/core/java/android/hardware/ICameraServiceListener.aidl
index c548496..49278b6 100644
--- a/core/java/android/hardware/ICameraServiceListener.aidl
+++ b/core/java/android/hardware/ICameraServiceListener.aidl
@@ -23,4 +23,6 @@ interface ICameraServiceListener
* Keep up-to-date with frameworks/av/include/camera/ICameraServiceListener.h
*/
void onStatusChanged(int status, int cameraId);
+
+ void onTorchStatusChanged(int status, String cameraId);
}
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 8af3c15..faa782a 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -27,6 +27,7 @@ import android.hardware.camera2.utils.CameraServiceBinderDecorator;
import android.hardware.camera2.utils.CameraRuntimeException;
import android.hardware.camera2.utils.BinderHolder;
import android.os.IBinder;
+import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
@@ -163,6 +164,15 @@ public final class CameraManager {
* no looper.
*/
public void registerTorchCallback(TorchCallback callback, Handler handler) {
+ if (handler == null) {
+ Looper looper = Looper.myLooper();
+ if (looper == null) {
+ throw new IllegalArgumentException(
+ "No handler given, and current thread has no looper!");
+ }
+ handler = new Handler(looper);
+ }
+ CameraManagerGlobal.get().registerTorchCallback(callback, handler);
}
/**
@@ -174,6 +184,7 @@ public final class CameraManager {
* @param callback The callback to remove from the notification list
*/
public void unregisterTorchCallback(TorchCallback callback) {
+ CameraManagerGlobal.get().unregisterTorchCallback(callback);
}
/**
@@ -437,11 +448,11 @@ public final class CameraManager {
* However, even if turning on the torch mode is successful, the application does not have the
* exclusive ownership of the flash unit or the camera device. The torch mode will be turned
* off and becomes unavailable when the camera device that the flash unit belongs to becomes
- * unavailable ({@link CameraManager.TorchCallback#onTorchModeAvailable} will be
- * invoked) or when other camera resources to keep the torch on become unavailable (
+ * unavailable or when other camera resources to keep the torch on become unavailable (
* {@link CameraManager.TorchCallback#onTorchModeUnavailable} will be invoked). Also,
* other applications are free to call {@link #setTorchMode} to turn off the torch mode (
- * {@link CameraManager.TorchCallback#onTorchModeChanged} will be invoked).
+ * {@link CameraManager.TorchCallback#onTorchModeChanged} will be invoked). If the latest
+ * application that turned on the torch mode exits, the torch mode will be turned off.
*
* @param cameraId
* The unique identifier of the camera device that the flash unit belongs to.
@@ -454,13 +465,15 @@ public final class CameraManager {
* {@link CameraAccessException#CAMERA_IN_USE} will be thrown if the camera device
* is in use. {@link CameraAccessException#MAX_CAMERAS_IN_USE} will be thrown if
* other camera resources needed to turn on the torch mode are in use.
+ * {@link CameraAccessException#CAMERA_DISCONNECTED} will be thrown if camera
+ * service is not available.
*
* @throws IllegalArgumentException if cameraId was null, cameraId doesn't match any currently
* or previously available camera device, or the camera device doesn't have a
* flash unit.
*/
public void setTorchMode(String cameraId, boolean enabled) throws CameraAccessException {
-
+ CameraManagerGlobal.get().setTorchMode(cameraId, enabled);
}
/**
@@ -508,14 +521,19 @@ public final class CameraManager {
}
/**
- * A callback for camera flash torch modes becoming available, unavailable, enabled, or
- * disabled.
+ * A callback for camera flash torch modes becoming unavailable, disabled, or enabled.
*
- * <p>The torch mode becomes available when the camera device it belongs to is no longer in use
- * and other camera resources it needs are no longer busy. It becomes unavailable when the
- * camera device it belongs to becomes unavailable or other camera resouces it needs become
- * busy due to other higher priority camera activities. The torch mode changes when an
- * application calls {@link #setTorchMode} successfully.
+ * <p>The torch mode becomes unavailable when the camera device it belongs to becomes
+ * unavailable or other camera resouces it needs become busy due to other higher priority
+ * camera activities. The torch mode becomes disabled when it was turned off or when the camera
+ * device it belongs to is no longer in use and other camera resources it needs are no longer
+ * busy. A camera's torch mode is turned off when an application calls {@link #setTorchMode} to
+ * turn off the camera's torch mode, or when an application turns on another camera's torch mode
+ * if keeping multiple torch modes on simultaneously is not supported. The torch mode becomes
+ * enabled when it is turned on via {@link #setTorchMode}.</p>
+ *
+ * <p>The torch mode is available to set via {@link #setTorchMode} only when it's in a disabled
+ * or enabled state.</p>
*
* <p>Extend this callback and pass an instance of the subclass to
* {@link CameraManager#registerTorchCallback} to be notified of such status changes.
@@ -525,24 +543,12 @@ public final class CameraManager {
*/
public static abstract class TorchCallback {
/**
- * The torch mode of a camera has become available to use.
- *
- * <p>The default implementation of this method does nothing.</p>
- *
- * @param cameraId The unique identifier of the camera whose torch mode has become
- * available.
- */
- public void onTorchModeAvailable(String cameraId) {
- // default empty implementation
- }
-
- /**
- * A previously-available torch mode of a camera has become unavailable.
+ * A camera's torch mode has become unavailable to set via {@link #setTorchMode}.
*
* <p>If torch mode was previously turned on by calling {@link #setTorchMode}, it will be
* turned off before {@link CameraManager.TorchCallback#onTorchModeUnavailable} is
- * invoked. {@link #setTorchMode} will fail until the flash unit becomes available again.
- * </p>
+ * invoked. {@link #setTorchMode} will fail until the torch mode has entered a disabled or
+ * enabled state again.</p>
*
* <p>The default implementation of this method does nothing.</p>
*
@@ -554,15 +560,17 @@ public final class CameraManager {
}
/**
- * Torch mode of a camera has been turned on or off through {@link #setTorchMode}.
+ * A camera's torch mode has become enabled or disabled and can be changed via
+ * {@link #setTorchMode}.
*
* <p>The default implementation of this method does nothing.</p>
*
* @param cameraId The unique identifier of the camera whose torch mode has been changed.
*
* @param enabled The state that the torch mode of the camera has been changed to.
- * {@code true} when the torch mode has been turned on. {@code false} when
- * the torch mode has been turned off.
+ * {@code true} when the torch mode has become on and available to be turned
+ * off. {@code false} when the torch mode has becomes off and available to
+ * be turned on.
*/
public void onTorchModeChanged(String cameraId, boolean enabled) {
// default empty implementation
@@ -725,6 +733,27 @@ public final class CameraManager {
private final ArrayMap<AvailabilityCallback, Handler> mCallbackMap =
new ArrayMap<AvailabilityCallback, Handler>();
+ // Keep up-to-date with ICameraServiceListener.h
+
+ // torch mode has become not available to set via setTorchMode().
+ public static final int TORCH_STATUS_NOT_AVAILABLE = 0;
+ // torch mode is off and available to be turned on via setTorchMode().
+ public static final int TORCH_STATUS_AVAILABLE_OFF = 1;
+ // torch mode is on and available to be turned off via setTorchMode().
+ public static final int TORCH_STATUS_AVAILABLE_ON = 2;
+
+ // End enums shared with ICameraServiceListener.h
+
+ // torch client binder to set the torch mode with.
+ private Binder mTorchClientBinder = new Binder();
+
+ // Camera ID -> Torch status map
+ private final ArrayMap<String, Integer> mTorchStatus = new ArrayMap<String, Integer>();
+
+ // Registered torch callbacks and their handlers
+ private final ArrayMap<TorchCallback, Handler> mTorchCallbackMap =
+ new ArrayMap<TorchCallback, Handler>();
+
private final Object mLock = new Object();
// Access only through getCameraService to deal with binder death
@@ -810,15 +839,46 @@ public final class CameraManager {
}
}
+ public void setTorchMode(String cameraId, boolean enabled) throws CameraAccessException {
+ synchronized(mLock) {
+
+ if (cameraId == null) {
+ throw new IllegalArgumentException("cameraId was null");
+ }
+
+ ICameraService cameraService = getCameraService();
+ if (cameraService == null) {
+ throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
+ "Camera service is currently unavailable");
+ }
+
+ try {
+ int status = cameraService.setTorchMode(cameraId, enabled, mTorchClientBinder);
+ } catch(CameraRuntimeException e) {
+ int problem = e.getReason();
+ switch (problem) {
+ case CameraAccessException.CAMERA_ERROR:
+ throw new IllegalArgumentException(
+ "the camera device doesn't have a flash unit.");
+ default:
+ throw e.asChecked();
+ }
+ } catch (RemoteException e) {
+ throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
+ "Camera service is currently unavailable");
+ }
+ }
+ }
+
private void handleRecoverableSetupErrors(CameraRuntimeException e, String msg) {
int problem = e.getReason();
switch (problem) {
- case CameraAccessException.CAMERA_DISCONNECTED:
- String errorMsg = CameraAccessException.getDefaultMessage(problem);
- Log.w(TAG, msg + ": " + errorMsg);
- break;
- default:
- throw new IllegalStateException(msg, e.asChecked());
+ case CameraAccessException.CAMERA_DISCONNECTED:
+ String errorMsg = CameraAccessException.getDefaultMessage(problem);
+ Log.w(TAG, msg + ": " + errorMsg);
+ break;
+ default:
+ throw new IllegalStateException(msg, e.asChecked());
}
}
@@ -843,6 +903,17 @@ public final class CameraManager {
}
}
+ private boolean validTorchStatus(int status) {
+ switch (status) {
+ case TORCH_STATUS_NOT_AVAILABLE:
+ case TORCH_STATUS_AVAILABLE_ON:
+ case TORCH_STATUS_AVAILABLE_OFF:
+ return true;
+ default:
+ return false;
+ }
+ }
+
private void postSingleUpdate(final AvailabilityCallback callback, final Handler handler,
final String id, final int status) {
if (isAvailable(status)) {
@@ -864,6 +935,32 @@ public final class CameraManager {
}
}
+ private void postSingleTorchUpdate(final TorchCallback callback, final Handler handler,
+ final String id, final int status) {
+ switch(status) {
+ case TORCH_STATUS_AVAILABLE_ON:
+ case TORCH_STATUS_AVAILABLE_OFF:
+ handler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ callback.onTorchModeChanged(id, status ==
+ TORCH_STATUS_AVAILABLE_ON);
+ }
+ });
+ break;
+ default:
+ handler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ callback.onTorchModeUnavailable(id);
+ }
+ });
+ break;
+ }
+ }
+
/**
* Send the state of all known cameras to the provided listener, to initialize
* the listener's knowledge of camera state.
@@ -933,6 +1030,44 @@ public final class CameraManager {
}
} // onStatusChangedLocked
+ private void updateTorchCallbackLocked(TorchCallback callback, Handler handler) {
+ for (int i = 0; i < mTorchStatus.size(); i++) {
+ String id = mTorchStatus.keyAt(i);
+ Integer status = mTorchStatus.valueAt(i);
+ postSingleTorchUpdate(callback, handler, id, status);
+ }
+ }
+
+ private void onTorchStatusChangedLocked(int status, String id) {
+ if (DEBUG) {
+ Log.v(TAG,
+ String.format("Camera id %s has torch status changed to 0x%x", id, status));
+ }
+
+ if (!validTorchStatus(status)) {
+ Log.e(TAG, String.format("Ignoring invalid device %s torch status 0x%x", id,
+ status));
+ return;
+ }
+
+ Integer oldStatus = mTorchStatus.put(id, status);
+ if (oldStatus != null && oldStatus == status) {
+ if (DEBUG) {
+ Log.v(TAG, String.format(
+ "Torch status changed to 0x%x, which is what it already was",
+ status));
+ }
+ return;
+ }
+
+ final int callbackCount = mTorchCallbackMap.size();
+ for (int i = 0; i < callbackCount; i++) {
+ final Handler handler = mTorchCallbackMap.valueAt(i);
+ final TorchCallback callback = mTorchCallbackMap.keyAt(i);
+ postSingleTorchUpdate(callback, handler, id, status);
+ }
+ } // onTorchStatusChangedLocked
+
/**
* Register a callback to be notified about camera device availability with the
* global listener singleton.
@@ -962,6 +1097,22 @@ public final class CameraManager {
}
}
+ public void registerTorchCallback(TorchCallback callback, Handler handler) {
+ synchronized(mLock) {
+ Handler oldHandler = mTorchCallbackMap.put(callback, handler);
+ // For new callbacks, provide initial torch information
+ if (oldHandler == null) {
+ updateTorchCallbackLocked(callback, handler);
+ }
+ }
+ }
+
+ public void unregisterTorchCallback(TorchCallback callback) {
+ synchronized(mLock) {
+ mTorchCallbackMap.remove(callback);
+ }
+ }
+
/**
* Callback from camera service notifying the process about camera availability changes
*/
@@ -972,6 +1123,13 @@ public final class CameraManager {
}
}
+ @Override
+ public void onTorchStatusChanged(int status, String cameraId) throws RemoteException {
+ synchronized (mLock) {
+ onTorchStatusChangedLocked(status, cameraId);
+ }
+ }
+
/**
* Listener for camera service death.
*
@@ -986,9 +1144,9 @@ public final class CameraManager {
mCameraService = null;
- // Tell listeners that the cameras are _available_, because any existing clients
- // will have gotten disconnected. This is optimistic under the assumption that
- // the service will be back shortly.
+ // Tell listeners that the cameras and torch modes are _available_, because any
+ // existing clients will have gotten disconnected. This is optimistic under the
+ // assumption that the service will be back shortly.
//
// Without this, a camera service crash while a camera is open will never signal
// to listeners that previously in-use cameras are now available.
@@ -996,6 +1154,11 @@ public final class CameraManager {
String cameraId = mDeviceStatus.keyAt(i);
onStatusChangedLocked(STATUS_PRESENT, cameraId);
}
+ for (int i = 0; i < mTorchStatus.size(); i++) {
+ String cameraId = mTorchStatus.keyAt(i);
+ onTorchStatusChangedLocked(TORCH_STATUS_AVAILABLE_OFF, cameraId);
+ }
+
}
}