am 93826c7e: am f2c5ce5d: am a42cf680: Merge "Camera: Add support for notifying NFC stack when camera is active" into mnc-dr-dev

* commit '93826c7ebd3d5c6d6372a8bc6050d276727f7464':
  Camera: Add support for notifying NFC stack when camera is active
This commit is contained in:
Eino-Ville Talvala
2015-08-24 19:42:49 +00:00
committed by Android Git Automerger
2 changed files with 132 additions and 11 deletions

View File

@@ -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);
}

View File

@@ -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;
}
mCameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder);
}
ICameraService cameraServiceRaw = 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";
}
}