diff options
author | 2015-08-24 19:22:04 +0000 | |
---|---|---|
committer | 2015-08-24 19:22:04 +0000 | |
commit | a42cf680a57e73eb4ed874bb78b7f47c6d5d76d3 (patch) | |
tree | 039f696d15f2606051438d98045d18128fb99ae9 | |
parent | 21490522523c24c2873d4b3b89caa7d243982490 (diff) | |
parent | 2e3215c9f6ac210a4ff3bdbb08a499b26042e212 (diff) |
Merge "Camera: Add support for notifying NFC stack when camera is active" into mnc-dr-dev
-rw-r--r-- | core/java/android/hardware/ICameraServiceProxy.aidl | 7 | ||||
-rw-r--r-- | services/core/java/com/android/server/camera/CameraService.java | 136 |
2 files changed, 132 insertions, 11 deletions
diff --git a/core/java/android/hardware/ICameraServiceProxy.aidl b/core/java/android/hardware/ICameraServiceProxy.aidl index 0bb24bc2b04e..0e654d5083b6 100644 --- a/core/java/android/hardware/ICameraServiceProxy.aidl +++ b/core/java/android/hardware/ICameraServiceProxy.aidl @@ -19,6 +19,8 @@ package android.hardware; /** * Binder interface for the camera service proxy running in system_server. * + * Keep in sync with frameworks/av/include/camera/ICameraServiceProxy.h + * * @hide */ interface ICameraServiceProxy @@ -27,4 +29,9 @@ interface ICameraServiceProxy * Ping the service proxy to update the valid users for the camera service. */ oneway void pingForUserUpdate(); + + /** + * Update the status of a camera device + */ + oneway void notifyCameraState(String cameraId, int newCameraState); } diff --git a/services/core/java/com/android/server/camera/CameraService.java b/services/core/java/com/android/server/camera/CameraService.java index 0be24f4c10ea..f82454a1d9f8 100644 --- a/services/core/java/com/android/server/camera/CameraService.java +++ b/services/core/java/com/android/server/camera/CameraService.java @@ -23,13 +23,17 @@ import android.content.IntentFilter; import android.content.pm.UserInfo; import android.hardware.ICameraService; import android.hardware.ICameraServiceProxy; +import android.nfc.INfcAdapter; import android.os.Handler; import android.os.IBinder; +import android.os.Binder; import android.os.Message; import android.os.Process; import android.os.RemoteException; import android.os.UserManager; +import android.os.SystemProperties; import android.util.Slog; +import android.util.ArraySet; import com.android.server.ServiceThread; import com.android.server.SystemService; @@ -44,8 +48,10 @@ import java.util.Set; * * @hide */ -public class CameraService extends SystemService implements Handler.Callback { +public class CameraService extends SystemService + implements Handler.Callback, IBinder.DeathRecipient { private static final String TAG = "CameraService_proxy"; + private static final boolean DEBUG = false; /** * This must match the ICameraService.aidl definition @@ -58,6 +64,16 @@ public class CameraService extends SystemService implements Handler.Callback { public static final int NO_EVENT = 0; // NOOP public static final int USER_SWITCHED = 1; // User changed, argument is the new user handle + // State arguments to use with the notifyCameraState call from camera service: + public static final int CAMERA_STATE_OPEN = 0; + public static final int CAMERA_STATE_ACTIVE = 1; + public static final int CAMERA_STATE_IDLE = 2; + public static final int CAMERA_STATE_CLOSED = 3; + + // Flags arguments to NFC adapter to enable/disable NFC + public static final int DISABLE_POLLING_FLAGS = 0x1000; + public static final int ENABLE_POLLING_FLAGS = 0x0000; + // Handler message codes private static final int MSG_SWITCH_USER = 1; @@ -72,6 +88,17 @@ public class CameraService extends SystemService implements Handler.Callback { private Set<Integer> mEnabledCameraUsers; private int mLastUser; + private ICameraService mCameraServiceRaw; + + private final ArraySet<String> mActiveCameraIds = new ArraySet<>(); + + private static final String NFC_NOTIFICATION_PROP = "ro.camera.notify_nfc"; + private static final String NFC_SERVICE_BINDER_NAME = "nfc"; + private static final IBinder nfcInterfaceToken = new Binder(); + + private final boolean mNotifyNfc; + private int mActiveCameraCount = 0; + private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -102,6 +129,14 @@ public class CameraService extends SystemService implements Handler.Callback { public void pingForUserUpdate() { notifySwitchWithRetries(30); } + + @Override + public void notifyCameraState(String cameraId, int newCameraState) { + String state = cameraStateToString(newCameraState); + if (DEBUG) Slog.v(TAG, "Camera " + cameraId + " state now " + state); + + updateActivityCount(cameraId, newCameraState); + } }; public CameraService(Context context) { @@ -110,6 +145,9 @@ public class CameraService extends SystemService implements Handler.Callback { mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_DISPLAY, /*allowTo*/false); mHandlerThread.start(); mHandler = new Handler(mHandlerThread.getLooper(), this); + + mNotifyNfc = SystemProperties.getInt(NFC_NOTIFICATION_PROP, 0) > 0; + if (DEBUG) Slog.v(TAG, "Notify NFC behavior is " + (mNotifyNfc ? "active" : "disabled")); } @Override @@ -161,13 +199,32 @@ public class CameraService extends SystemService implements Handler.Callback { } } + /** + * Handle the death of the native camera service + */ + @Override + public void binderDied() { + if (DEBUG) Slog.w(TAG, "Native camera service has died"); + synchronized(mLock) { + mCameraServiceRaw = null; + + // All cameras reset to idle on camera service death + boolean wasEmpty = mActiveCameraIds.isEmpty(); + mActiveCameraIds.clear(); + + if ( mNotifyNfc && !wasEmpty ) { + notifyNfcService(/*enablePolling*/ true); + } + } + } + private void switchUserLocked(int userHandle) { Set<Integer> currentUserHandles = getEnabledUserHandles(userHandle); mLastUser = userHandle; if (mEnabledCameraUsers == null || !mEnabledCameraUsers.equals(currentUserHandles)) { // Some user handles have been added or removed, update mediaserver. mEnabledCameraUsers = currentUserHandles; - notifyMediaserver(USER_SWITCHED, currentUserHandles); + notifyMediaserverLocked(USER_SWITCHED, currentUserHandles); } } @@ -187,7 +244,7 @@ public class CameraService extends SystemService implements Handler.Callback { if (mEnabledCameraUsers == null) { return; } - if (notifyMediaserver(USER_SWITCHED, mEnabledCameraUsers)) { + if (notifyMediaserverLocked(USER_SWITCHED, mEnabledCameraUsers)) { retries = 0; } } @@ -199,19 +256,27 @@ public class CameraService extends SystemService implements Handler.Callback { RETRY_DELAY_TIME); } - private boolean notifyMediaserver(int eventType, Set<Integer> updatedUserHandles) { + private boolean notifyMediaserverLocked(int eventType, Set<Integer> updatedUserHandles) { // Forward the user switch event to the native camera service running in the mediaserver // process. - IBinder cameraServiceBinder = getBinderService(CAMERA_SERVICE_BINDER_NAME); - if (cameraServiceBinder == null) { - Slog.w(TAG, "Could not notify mediaserver, camera service not available."); - return false; // Camera service not active, cannot evict user clients. - } + if (mCameraServiceRaw == null) { + IBinder cameraServiceBinder = getBinderService(CAMERA_SERVICE_BINDER_NAME); + if (cameraServiceBinder == null) { + Slog.w(TAG, "Could not notify mediaserver, camera service not available."); + return false; // Camera service not active, cannot evict user clients. + } + try { + cameraServiceBinder.linkToDeath(this, /*flags*/ 0); + } catch (RemoteException e) { + Slog.w(TAG, "Could not link to death of native camera service"); + return false; + } - ICameraService cameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder); + mCameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder); + } try { - cameraServiceRaw.notifySystemEvent(eventType, toArray(updatedUserHandles)); + mCameraServiceRaw.notifySystemEvent(eventType, toArray(updatedUserHandles)); } catch (RemoteException e) { Slog.w(TAG, "Could not notify mediaserver, remote exception: " + e); // Not much we can do if camera service is dead. @@ -220,6 +285,44 @@ public class CameraService extends SystemService implements Handler.Callback { return true; } + private void updateActivityCount(String cameraId, int newCameraState) { + synchronized(mLock) { + boolean wasEmpty = mActiveCameraIds.isEmpty(); + switch (newCameraState) { + case CAMERA_STATE_OPEN: + break; + case CAMERA_STATE_ACTIVE: + mActiveCameraIds.add(cameraId); + break; + case CAMERA_STATE_IDLE: + case CAMERA_STATE_CLOSED: + mActiveCameraIds.remove(cameraId); + break; + } + boolean isEmpty = mActiveCameraIds.isEmpty(); + if ( mNotifyNfc && (wasEmpty != isEmpty) ) { + notifyNfcService(isEmpty); + } + } + } + + private void notifyNfcService(boolean enablePolling) { + + IBinder nfcServiceBinder = getBinderService(NFC_SERVICE_BINDER_NAME); + if (nfcServiceBinder == null) { + Slog.w(TAG, "Could not connect to NFC service to notify it of camera state"); + return; + } + INfcAdapter nfcAdapterRaw = INfcAdapter.Stub.asInterface(nfcServiceBinder); + int flags = enablePolling ? ENABLE_POLLING_FLAGS : DISABLE_POLLING_FLAGS; + if (DEBUG) Slog.v(TAG, "Setting NFC reader mode to flags " + flags); + try { + nfcAdapterRaw.setReaderMode(nfcInterfaceToken, null, flags, null); + } catch (RemoteException e) { + Slog.w(TAG, "Could not notify NFC service, remote exception: " + e); + } + } + private static int[] toArray(Collection<Integer> c) { int len = c.size(); int[] ret = new int[len]; @@ -229,4 +332,15 @@ public class CameraService extends SystemService implements Handler.Callback { } return ret; } + + private static String cameraStateToString(int newCameraState) { + switch (newCameraState) { + case CAMERA_STATE_OPEN: return "CAMERA_STATE_OPEN"; + case CAMERA_STATE_ACTIVE: return "CAMERA_STATE_ACTIVE"; + case CAMERA_STATE_IDLE: return "CAMERA_STATE_IDLE"; + case CAMERA_STATE_CLOSED: return "CAMERA_STATE_CLOSED"; + default: break; + } + return "CAMERA_STATE_UNKNOWN"; + } } |