Loading core/java/android/hardware/ICameraServiceProxy.aidl +7 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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); } services/core/java/com/android/server/camera/CameraService.java +125 −11 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading @@ -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; Loading @@ -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) { Loading Loading @@ -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) { Loading @@ -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 Loading Loading @@ -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); } } Loading @@ -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; } } Loading @@ -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. 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. Loading @@ -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]; Loading @@ -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"; } } Loading
core/java/android/hardware/ICameraServiceProxy.aidl +7 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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); }
services/core/java/com/android/server/camera/CameraService.java +125 −11 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading @@ -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; Loading @@ -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) { Loading Loading @@ -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) { Loading @@ -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 Loading Loading @@ -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); } } Loading @@ -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; } } Loading @@ -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. 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. Loading @@ -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]; Loading @@ -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"; } }