diff --git a/core/java/android/hardware/ISensorPrivacyManager.aidl b/core/java/android/hardware/ISensorPrivacyManager.aidl index 46682adcb147e..a54e88f2d4931 100644 --- a/core/java/android/hardware/ISensorPrivacyManager.aidl +++ b/core/java/android/hardware/ISensorPrivacyManager.aidl @@ -26,19 +26,19 @@ interface ISensorPrivacyManager { // =============== Beginning of transactions used on native side as well ====================== void addSensorPrivacyListener(in ISensorPrivacyListener listener); + void addIndividualSensorPrivacyListener(int userId, int sensor, + in ISensorPrivacyListener listener); + void removeSensorPrivacyListener(in ISensorPrivacyListener listener); boolean isSensorPrivacyEnabled(); - void setSensorPrivacy(boolean enable); - // =============== End of transactions used on native side as well ============================ - - // TODO(evanseverson) add to native interface boolean isIndividualSensorPrivacyEnabled(int userId, int sensor); - // TODO(evanseverson) add to native interface - void setIndividualSensorPrivacy(int userId, int sensor, boolean enable); - void setIndividualSensorPrivacyForProfileGroup(int userId, int sensor, boolean enable); + void setSensorPrivacy(boolean enable); - // TODO(evanseverson) listeners + void setIndividualSensorPrivacy(int userId, int sensor, boolean enable); + + void setIndividualSensorPrivacyForProfileGroup(int userId, int sensor, boolean enable); + // =============== End of transactions used on native side as well ============================ } \ No newline at end of file diff --git a/core/java/android/hardware/SensorPrivacyManager.java b/core/java/android/hardware/SensorPrivacyManager.java index 4d488715b2c51..b3b2dd85a8d8b 100644 --- a/core/java/android/hardware/SensorPrivacyManager.java +++ b/core/java/android/hardware/SensorPrivacyManager.java @@ -160,6 +160,37 @@ public final class SensorPrivacyManager { } } + /** + * Registers a new listener to receive notification when the state of sensor privacy + * changes. + * + * @param userId the user's id + * @param sensor the sensor to listen to changes to + * @param listener the OnSensorPrivacyChangedListener to be notified when the state of sensor + * privacy changes. + */ + public void addSensorPrivacyListener(@UserIdInt int userId, @IndividualSensor int sensor, + final OnSensorPrivacyChangedListener listener) { + synchronized (mListeners) { + ISensorPrivacyListener iListener = mListeners.get(listener); + if (iListener == null) { + iListener = new ISensorPrivacyListener.Stub() { + @Override + public void onSensorPrivacyChanged(boolean enabled) { + listener.onSensorPrivacyChanged(enabled); + } + }; + mListeners.put(listener, iListener); + } + + try { + mService.addIndividualSensorPrivacyListener(userId, sensor, iListener); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } + /** * Unregisters the specified listener from receiving notifications when the state of sensor * privacy changes. diff --git a/services/core/java/com/android/server/SensorPrivacyService.java b/services/core/java/com/android/server/SensorPrivacyService.java index 2b705f5ffb3e5..9ba71dc5f4f7b 100644 --- a/services/core/java/com/android/server/SensorPrivacyService.java +++ b/services/core/java/com/android/server/SensorPrivacyService.java @@ -291,6 +291,7 @@ public final class SensorPrivacyService extends SystemService { } persistSensorPrivacyState(); } + mHandler.onSensorPrivacyChanged(userId, sensor, enable); } @Override @@ -557,6 +558,18 @@ public final class SensorPrivacyService extends SystemService { mHandler.addListener(listener); } + /** + * Registers a listener to be notified when the sensor privacy state changes. + */ + @Override + public void addIndividualSensorPrivacyListener(int userId, int sensor, + ISensorPrivacyListener listener) { + if (listener == null) { + throw new NullPointerException("listener cannot be null"); + } + mHandler.addListener(userId, sensor, listener); + } + /** * Unregisters a listener from sensor privacy state change notifications. */ @@ -760,6 +773,9 @@ public final class SensorPrivacyService extends SystemService { @GuardedBy("mListenerLock") private final RemoteCallbackList mListeners = new RemoteCallbackList<>(); + @GuardedBy("mListenerLock") + private final SparseArray>> + mIndividualSensorListeners = new SparseArray<>(); private final ArrayMap mDeathRecipients; private final Context mContext; @@ -777,6 +793,14 @@ public final class SensorPrivacyService extends SystemService { mSensorPrivacyServiceImpl)); } + public void onSensorPrivacyChanged(int userId, int sensor, boolean enabled) { + sendMessage(PooledLambda.obtainMessage(SensorPrivacyHandler::handleSensorPrivacyChanged, + this, userId, sensor, enabled)); + sendMessage( + PooledLambda.obtainMessage(SensorPrivacyServiceImpl::persistSensorPrivacyState, + mSensorPrivacyServiceImpl)); + } + public void addListener(ISensorPrivacyListener listener) { synchronized (mListenerLock) { DeathRecipient deathRecipient = new DeathRecipient(listener); @@ -785,6 +809,25 @@ public final class SensorPrivacyService extends SystemService { } } + public void addListener(int userId, int sensor, ISensorPrivacyListener listener) { + synchronized (mListenerLock) { + DeathRecipient deathRecipient = new DeathRecipient(listener); + mDeathRecipients.put(listener, deathRecipient); + SparseArray> listenersForUser = + mIndividualSensorListeners.get(userId); + if (listenersForUser == null) { + listenersForUser = new SparseArray<>(); + mIndividualSensorListeners.put(userId, listenersForUser); + } + RemoteCallbackList listeners = listenersForUser.get(sensor); + if (listeners == null) { + listeners = new RemoteCallbackList<>(); + listenersForUser.put(sensor, listeners); + } + listeners.register(listener); + } + } + public void removeListener(ISensorPrivacyListener listener) { synchronized (mListenerLock) { DeathRecipient deathRecipient = mDeathRecipients.remove(listener); @@ -792,6 +835,12 @@ public final class SensorPrivacyService extends SystemService { deathRecipient.destroy(); } mListeners.unregister(listener); + for (int i = 0, numUsers = mIndividualSensorListeners.size(); i < numUsers; i++) { + for (int j = 0, numListeners = mIndividualSensorListeners.valueAt(i).size(); + j < numListeners; j++) { + mIndividualSensorListeners.valueAt(i).valueAt(j).unregister(listener); + } + } } } @@ -807,6 +856,28 @@ public final class SensorPrivacyService extends SystemService { } mListeners.finishBroadcast(); } + + public void handleSensorPrivacyChanged(int userId, int sensor, boolean enabled) { + SparseArray> listenersForUser = + mIndividualSensorListeners.get(userId); + if (listenersForUser == null) { + return; + } + RemoteCallbackList listeners = listenersForUser.get(sensor); + if (listeners == null) { + return; + } + final int count = listeners.beginBroadcast(); + for (int i = 0; i < count; i++) { + ISensorPrivacyListener listener = listeners.getBroadcastItem(i); + try { + listener.onSensorPrivacyChanged(enabled); + } catch (RemoteException e) { + Log.e(TAG, "Caught an exception notifying listener " + listener + ": ", e); + } + } + listeners.finishBroadcast(); + } } private final class DeathRecipient implements IBinder.DeathRecipient {