Loading core/java/android/hardware/ISensorPrivacyManager.aidl +4 −0 Original line number Diff line number Diff line Loading @@ -48,4 +48,8 @@ interface ISensorPrivacyManager { void suppressIndividualSensorPrivacyReminders(int userId, int sensor, IBinder token, boolean suppress); void addUserGlobalIndividualSensorPrivacyListener(int sensor, in ISensorPrivacyListener listener); void removeUserGlobalIndividualSensorPrivacyListener(int sensor, in ISensorPrivacyListener listener); } No newline at end of file core/java/android/hardware/SensorPrivacyManager.java +34 −7 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.content.Context; import android.os.Binder; import android.os.IBinder; Loading Loading @@ -247,8 +248,7 @@ public final class SensorPrivacyManager { @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(@Sensors.Sensor int sensor, @NonNull OnSensorPrivacyChangedListener listener) { addSensorPrivacyListener(sensor, mContext.getUserId(), mContext.getMainExecutor(), listener); addSensorPrivacyListener(sensor, mContext.getMainExecutor(), listener); } /** Loading Loading @@ -283,7 +283,25 @@ public final class SensorPrivacyManager { @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(@Sensors.Sensor int sensor, @NonNull Executor executor, @NonNull OnSensorPrivacyChangedListener listener) { addSensorPrivacyListener(sensor, mContext.getUserId(), executor, listener); Pair<OnSensorPrivacyChangedListener, Integer> key = new Pair<>(listener, sensor); synchronized (mIndividualListeners) { ISensorPrivacyListener iListener = mIndividualListeners.get(key); if (iListener == null) { iListener = new ISensorPrivacyListener.Stub() { @Override public void onSensorPrivacyChanged(boolean enabled) { executor.execute(() -> listener.onSensorPrivacyChanged(sensor, enabled)); } }; mIndividualListeners.put(key, iListener); } try { mService.addUserGlobalIndividualSensorPrivacyListener(sensor, iListener); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } /** Loading Loading @@ -361,7 +379,7 @@ public final class SensorPrivacyManager { @SystemApi @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY) public boolean isSensorPrivacyEnabled(@Sensors.Sensor int sensor) { return isSensorPrivacyEnabled(sensor, mContext.getUserId()); return isSensorPrivacyEnabled(sensor, getCurrentUserId()); } /** Loading Loading @@ -392,7 +410,7 @@ public final class SensorPrivacyManager { @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setSensorPrivacy(@Sources.Source int source, @Sensors.Sensor int sensor, boolean enable) { setSensorPrivacy(source, sensor, enable, mContext.getUserId()); setSensorPrivacy(source, sensor, enable, getCurrentUserId()); } /** Loading Loading @@ -428,7 +446,7 @@ public final class SensorPrivacyManager { @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setSensorPrivacyForProfileGroup(@Sources.Source int source, @Sensors.Sensor int sensor, boolean enable) { setSensorPrivacyForProfileGroup(source , sensor, enable, mContext.getUserId()); setSensorPrivacyForProfileGroup(source , sensor, enable, getCurrentUserId()); } /** Loading Loading @@ -463,7 +481,7 @@ public final class SensorPrivacyManager { @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY) public void suppressSensorPrivacyReminders(int sensor, boolean suppress) { suppressSensorPrivacyReminders(sensor, suppress, mContext.getUserId()); suppressSensorPrivacyReminders(sensor, suppress, getCurrentUserId()); } /** Loading Loading @@ -590,4 +608,13 @@ public final class SensorPrivacyManager { throw e.rethrowFromSystemServer(); } } private int getCurrentUserId() { try { return ActivityManager.getService().getCurrentUserId(); } catch (RemoteException e) { e.rethrowFromSystemServer(); } return 0; } } services/core/java/com/android/server/SensorPrivacyService.java +191 −53 Original line number Diff line number Diff line Loading @@ -232,14 +232,14 @@ public final class SensorPrivacyService extends SystemService { public void onUserStarting(TargetUser user) { if (mCurrentUser == -1) { mCurrentUser = user.getUserIdentifier(); setGlobalRestriction(); mSensorPrivacyServiceImpl.userSwitching(-1, user.getUserIdentifier()); } } @Override public void onUserSwitching(TargetUser from, TargetUser to) { mCurrentUser = to.getUserIdentifier(); setGlobalRestriction(); mSensorPrivacyServiceImpl.userSwitching(from.getUserIdentifier(), to.getUserIdentifier()); } class SensorPrivacyServiceImpl extends ISensorPrivacyManager.Stub implements Loading Loading @@ -897,6 +897,11 @@ public final class SensorPrivacyService extends SystemService { public boolean isIndividualSensorPrivacyEnabled(@UserIdInt int userId, int sensor) { enforceObserveSensorPrivacyPermission(); synchronized (mLock) { return isIndividualSensorPrivacyEnabledLocked(userId, sensor); } } private boolean isIndividualSensorPrivacyEnabledLocked(int userId, int sensor) { SparseArray<SensorState> states = mIndividualEnabled.get(userId); if (states == null) { return false; Loading @@ -907,7 +912,6 @@ public final class SensorPrivacyService extends SystemService { } return state.mEnabled; } } /** * Returns the state of sensor privacy from persistent storage. Loading Loading @@ -1149,11 +1153,27 @@ public final class SensorPrivacyService extends SystemService { ISensorPrivacyListener listener) { enforceObserveSensorPrivacyPermission(); if (listener == null) { throw new NullPointerException("listener cannot be null"); throw new IllegalArgumentException("listener cannot be null"); } mHandler.addListener(userId, sensor, listener); } /** * Registers a listener to be notified when the sensor privacy state changes. The callback * can be called if the user changes and the setting is different between the transitioning * users. */ @Override public void addUserGlobalIndividualSensorPrivacyListener(int sensor, ISensorPrivacyListener listener) { enforceObserveSensorPrivacyPermission(); if (listener == null) { throw new IllegalArgumentException("listener cannot be null"); } mHandler.addUserGlobalListener(sensor, listener); } /** * Unregisters a listener from sensor privacy state change notifications. */ Loading @@ -1174,11 +1194,21 @@ public final class SensorPrivacyService extends SystemService { ISensorPrivacyListener listener) { enforceObserveSensorPrivacyPermission(); if (listener == null) { throw new NullPointerException("listener cannot be null"); throw new IllegalArgumentException("listener cannot be null"); } mHandler.removeListener(sensor, listener); } @Override public void removeUserGlobalIndividualSensorPrivacyListener(int sensor, ISensorPrivacyListener listener) { enforceObserveSensorPrivacyPermission(); if (listener == null) { throw new IllegalArgumentException("listener cannot be null"); } mHandler.removeUserGlobalListener(sensor, listener); } @Override public void suppressIndividualSensorPrivacyReminders(int userId, int sensor, IBinder token, boolean suppress) { Loading Loading @@ -1209,6 +1239,40 @@ public final class SensorPrivacyService extends SystemService { } } private void userSwitching(int from, int to) { boolean micState; boolean camState; boolean prevMicState; boolean prevCamState; synchronized (mLock) { prevMicState = isIndividualSensorPrivacyEnabledLocked(from, MICROPHONE); prevCamState = isIndividualSensorPrivacyEnabledLocked(from, CAMERA); micState = isIndividualSensorPrivacyEnabledLocked(to, MICROPHONE); camState = isIndividualSensorPrivacyEnabledLocked(to, CAMERA); } if (prevMicState != micState) { mHandler.onUserGlobalSensorPrivacyChanged(MICROPHONE, micState); setGlobalRestriction(MICROPHONE, micState); } if (prevCamState != camState) { mHandler.onUserGlobalSensorPrivacyChanged(CAMERA, camState); setGlobalRestriction(CAMERA, micState); } } private void setGlobalRestriction(int sensor, boolean enabled) { switch(sensor) { case MICROPHONE: mAppOpsManagerInternal.setGlobalRestriction(OP_RECORD_AUDIO, enabled, mAppOpsRestrictionToken); break; case CAMERA: mAppOpsManagerInternal.setGlobalRestriction(OP_CAMERA, enabled, mAppOpsRestrictionToken); break; } } /** * Remove a sensor use reminder suppression token. * Loading Loading @@ -1454,7 +1518,12 @@ public final class SensorPrivacyService extends SystemService { @GuardedBy("mListenerLock") private final SparseArray<SparseArray<RemoteCallbackList<ISensorPrivacyListener>>> mIndividualSensorListeners = new SparseArray<>(); private final ArrayMap<ISensorPrivacyListener, DeathRecipient> mDeathRecipients; @GuardedBy("mListenerLock") private final SparseArray<RemoteCallbackList<ISensorPrivacyListener>> mUserGlobalIndividualSensorListeners = new SparseArray<>(); @GuardedBy("mListenerLock") private final ArrayMap<ISensorPrivacyListener, Pair<DeathRecipient, Integer>> mDeathRecipients; private final Context mContext; SensorPrivacyHandler(Looper looper, Context context) { Loading @@ -1479,18 +1548,22 @@ public final class SensorPrivacyService extends SystemService { mSensorPrivacyServiceImpl)); } public void onUserGlobalSensorPrivacyChanged(int sensor, boolean enabled) { sendMessage(PooledLambda.obtainMessage( SensorPrivacyHandler::handleUserGlobalSensorPrivacyChanged, this, sensor, enabled)); } public void addListener(ISensorPrivacyListener listener) { synchronized (mListenerLock) { DeathRecipient deathRecipient = new DeathRecipient(listener); mDeathRecipients.put(listener, deathRecipient); mListeners.register(listener); if (mListeners.register(listener)) { addDeathRecipient(listener); } } } public void addListener(int userId, int sensor, ISensorPrivacyListener listener) { synchronized (mListenerLock) { DeathRecipient deathRecipient = new DeathRecipient(listener); mDeathRecipients.put(listener, deathRecipient); SparseArray<RemoteCallbackList<ISensorPrivacyListener>> listenersForUser = mIndividualSensorListeners.get(userId); if (listenersForUser == null) { Loading @@ -1502,32 +1575,55 @@ public final class SensorPrivacyService extends SystemService { listeners = new RemoteCallbackList<>(); listenersForUser.put(sensor, listeners); } listeners.register(listener); if (listeners.register(listener)) { addDeathRecipient(listener); } } } public void removeListener(ISensorPrivacyListener listener) { public void addUserGlobalListener(int sensor, ISensorPrivacyListener listener) { synchronized (mListenerLock) { DeathRecipient deathRecipient = mDeathRecipients.remove(listener); if (deathRecipient != null) { deathRecipient.destroy(); RemoteCallbackList<ISensorPrivacyListener> listeners = mUserGlobalIndividualSensorListeners.get(sensor); if (listeners == null) { listeners = new RemoteCallbackList<>(); mUserGlobalIndividualSensorListeners.put(sensor, listeners); } if (listeners.register(listener)) { addDeathRecipient(listener); } mListeners.unregister(listener); } } public void removeListener(int sensor, ISensorPrivacyListener listener) { public void removeListener(ISensorPrivacyListener listener) { synchronized (mListenerLock) { DeathRecipient deathRecipient = mDeathRecipients.remove(listener); if (deathRecipient != null) { deathRecipient.destroy(); if (mListeners.unregister(listener)) { removeDeathRecipient(listener); } } } public void removeListener(int sensor, ISensorPrivacyListener listener) { synchronized (mListenerLock) { for (int i = 0, numUsers = mIndividualSensorListeners.size(); i < numUsers; i++) { RemoteCallbackList callbacks = mIndividualSensorListeners.valueAt(i).get(sensor); if (callbacks != null) { callbacks.unregister(listener); if (callbacks.unregister(listener)) { removeDeathRecipient(listener); } } } } } public void removeUserGlobalListener(int sensor, ISensorPrivacyListener listener) { synchronized (mListenerLock) { RemoteCallbackList callbacks = mUserGlobalIndividualSensorListeners.get(sensor); if (callbacks != null) { if (callbacks.unregister(listener)) { removeDeathRecipient(listener); } } } Loading @@ -1551,9 +1647,12 @@ public final class SensorPrivacyService extends SystemService { SparseArray<RemoteCallbackList<ISensorPrivacyListener>> listenersForUser = mIndividualSensorListeners.get(userId); setGlobalRestriction(); if (userId == mCurrentUser) { setGlobalRestriction(); mSensorPrivacyServiceImpl.setGlobalRestriction(sensor, enabled); } if (userId == mCurrentUser) { onUserGlobalSensorPrivacyChanged(sensor, enabled); } if (listenersForUser == null) { Loading @@ -1563,6 +1662,7 @@ public final class SensorPrivacyService extends SystemService { if (listeners == null) { return; } try { final int count = listeners.beginBroadcast(); for (int i = 0; i < count; i++) { ISensorPrivacyListener listener = listeners.getBroadcastItem(i); Loading @@ -1572,8 +1672,33 @@ public final class SensorPrivacyService extends SystemService { Log.e(TAG, "Caught an exception notifying listener " + listener + ": ", e); } } } finally { listeners.finishBroadcast(); } } public void handleUserGlobalSensorPrivacyChanged(int sensor, boolean enabled) { RemoteCallbackList<ISensorPrivacyListener> listeners = mUserGlobalIndividualSensorListeners.get(sensor); if (listeners == null) { return; } try { 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); } } } finally { listeners.finishBroadcast(); } } public void removeSuppressPackageReminderToken(Pair<Integer, UserHandle> key, IBinder token) { Loading @@ -1581,20 +1706,33 @@ public final class SensorPrivacyService extends SystemService { SensorPrivacyServiceImpl::removeSuppressPackageReminderToken, mSensorPrivacyServiceImpl, key, token)); } } private void setGlobalRestriction() { boolean camState = mSensorPrivacyServiceImpl .isIndividualSensorPrivacyEnabled(mCurrentUser, CAMERA); boolean micState = mSensorPrivacyServiceImpl .isIndividualSensorPrivacyEnabled(mCurrentUser, MICROPHONE); private void addDeathRecipient(ISensorPrivacyListener listener) { Pair<DeathRecipient, Integer> deathRecipient = mDeathRecipients.get(listener); if (deathRecipient == null) { deathRecipient = new Pair<>(new DeathRecipient(listener), 1); } else { int newRefCount = deathRecipient.second + 1; deathRecipient = new Pair<>(deathRecipient.first, newRefCount); } mDeathRecipients.put(listener, deathRecipient); } mAppOpsManagerInternal .setGlobalRestriction(OP_CAMERA, camState, mAppOpsRestrictionToken); mAppOpsManagerInternal .setGlobalRestriction(OP_RECORD_AUDIO, micState, mAppOpsRestrictionToken); private void removeDeathRecipient(ISensorPrivacyListener listener) { Pair<DeathRecipient, Integer> deathRecipient = mDeathRecipients.get(listener); if (deathRecipient == null) { return; } else { int newRefCount = deathRecipient.second - 1; if (newRefCount == 0) { mDeathRecipients.remove(listener); deathRecipient.first.destroy(); return; } deathRecipient = new Pair<>(deathRecipient.first, newRefCount); } mDeathRecipients.put(listener, deathRecipient); } } private final class DeathRecipient implements IBinder.DeathRecipient { Loading Loading
core/java/android/hardware/ISensorPrivacyManager.aidl +4 −0 Original line number Diff line number Diff line Loading @@ -48,4 +48,8 @@ interface ISensorPrivacyManager { void suppressIndividualSensorPrivacyReminders(int userId, int sensor, IBinder token, boolean suppress); void addUserGlobalIndividualSensorPrivacyListener(int sensor, in ISensorPrivacyListener listener); void removeUserGlobalIndividualSensorPrivacyListener(int sensor, in ISensorPrivacyListener listener); } No newline at end of file
core/java/android/hardware/SensorPrivacyManager.java +34 −7 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.content.Context; import android.os.Binder; import android.os.IBinder; Loading Loading @@ -247,8 +248,7 @@ public final class SensorPrivacyManager { @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(@Sensors.Sensor int sensor, @NonNull OnSensorPrivacyChangedListener listener) { addSensorPrivacyListener(sensor, mContext.getUserId(), mContext.getMainExecutor(), listener); addSensorPrivacyListener(sensor, mContext.getMainExecutor(), listener); } /** Loading Loading @@ -283,7 +283,25 @@ public final class SensorPrivacyManager { @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(@Sensors.Sensor int sensor, @NonNull Executor executor, @NonNull OnSensorPrivacyChangedListener listener) { addSensorPrivacyListener(sensor, mContext.getUserId(), executor, listener); Pair<OnSensorPrivacyChangedListener, Integer> key = new Pair<>(listener, sensor); synchronized (mIndividualListeners) { ISensorPrivacyListener iListener = mIndividualListeners.get(key); if (iListener == null) { iListener = new ISensorPrivacyListener.Stub() { @Override public void onSensorPrivacyChanged(boolean enabled) { executor.execute(() -> listener.onSensorPrivacyChanged(sensor, enabled)); } }; mIndividualListeners.put(key, iListener); } try { mService.addUserGlobalIndividualSensorPrivacyListener(sensor, iListener); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } /** Loading Loading @@ -361,7 +379,7 @@ public final class SensorPrivacyManager { @SystemApi @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY) public boolean isSensorPrivacyEnabled(@Sensors.Sensor int sensor) { return isSensorPrivacyEnabled(sensor, mContext.getUserId()); return isSensorPrivacyEnabled(sensor, getCurrentUserId()); } /** Loading Loading @@ -392,7 +410,7 @@ public final class SensorPrivacyManager { @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setSensorPrivacy(@Sources.Source int source, @Sensors.Sensor int sensor, boolean enable) { setSensorPrivacy(source, sensor, enable, mContext.getUserId()); setSensorPrivacy(source, sensor, enable, getCurrentUserId()); } /** Loading Loading @@ -428,7 +446,7 @@ public final class SensorPrivacyManager { @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setSensorPrivacyForProfileGroup(@Sources.Source int source, @Sensors.Sensor int sensor, boolean enable) { setSensorPrivacyForProfileGroup(source , sensor, enable, mContext.getUserId()); setSensorPrivacyForProfileGroup(source , sensor, enable, getCurrentUserId()); } /** Loading Loading @@ -463,7 +481,7 @@ public final class SensorPrivacyManager { @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY) public void suppressSensorPrivacyReminders(int sensor, boolean suppress) { suppressSensorPrivacyReminders(sensor, suppress, mContext.getUserId()); suppressSensorPrivacyReminders(sensor, suppress, getCurrentUserId()); } /** Loading Loading @@ -590,4 +608,13 @@ public final class SensorPrivacyManager { throw e.rethrowFromSystemServer(); } } private int getCurrentUserId() { try { return ActivityManager.getService().getCurrentUserId(); } catch (RemoteException e) { e.rethrowFromSystemServer(); } return 0; } }
services/core/java/com/android/server/SensorPrivacyService.java +191 −53 Original line number Diff line number Diff line Loading @@ -232,14 +232,14 @@ public final class SensorPrivacyService extends SystemService { public void onUserStarting(TargetUser user) { if (mCurrentUser == -1) { mCurrentUser = user.getUserIdentifier(); setGlobalRestriction(); mSensorPrivacyServiceImpl.userSwitching(-1, user.getUserIdentifier()); } } @Override public void onUserSwitching(TargetUser from, TargetUser to) { mCurrentUser = to.getUserIdentifier(); setGlobalRestriction(); mSensorPrivacyServiceImpl.userSwitching(from.getUserIdentifier(), to.getUserIdentifier()); } class SensorPrivacyServiceImpl extends ISensorPrivacyManager.Stub implements Loading Loading @@ -897,6 +897,11 @@ public final class SensorPrivacyService extends SystemService { public boolean isIndividualSensorPrivacyEnabled(@UserIdInt int userId, int sensor) { enforceObserveSensorPrivacyPermission(); synchronized (mLock) { return isIndividualSensorPrivacyEnabledLocked(userId, sensor); } } private boolean isIndividualSensorPrivacyEnabledLocked(int userId, int sensor) { SparseArray<SensorState> states = mIndividualEnabled.get(userId); if (states == null) { return false; Loading @@ -907,7 +912,6 @@ public final class SensorPrivacyService extends SystemService { } return state.mEnabled; } } /** * Returns the state of sensor privacy from persistent storage. Loading Loading @@ -1149,11 +1153,27 @@ public final class SensorPrivacyService extends SystemService { ISensorPrivacyListener listener) { enforceObserveSensorPrivacyPermission(); if (listener == null) { throw new NullPointerException("listener cannot be null"); throw new IllegalArgumentException("listener cannot be null"); } mHandler.addListener(userId, sensor, listener); } /** * Registers a listener to be notified when the sensor privacy state changes. The callback * can be called if the user changes and the setting is different between the transitioning * users. */ @Override public void addUserGlobalIndividualSensorPrivacyListener(int sensor, ISensorPrivacyListener listener) { enforceObserveSensorPrivacyPermission(); if (listener == null) { throw new IllegalArgumentException("listener cannot be null"); } mHandler.addUserGlobalListener(sensor, listener); } /** * Unregisters a listener from sensor privacy state change notifications. */ Loading @@ -1174,11 +1194,21 @@ public final class SensorPrivacyService extends SystemService { ISensorPrivacyListener listener) { enforceObserveSensorPrivacyPermission(); if (listener == null) { throw new NullPointerException("listener cannot be null"); throw new IllegalArgumentException("listener cannot be null"); } mHandler.removeListener(sensor, listener); } @Override public void removeUserGlobalIndividualSensorPrivacyListener(int sensor, ISensorPrivacyListener listener) { enforceObserveSensorPrivacyPermission(); if (listener == null) { throw new IllegalArgumentException("listener cannot be null"); } mHandler.removeUserGlobalListener(sensor, listener); } @Override public void suppressIndividualSensorPrivacyReminders(int userId, int sensor, IBinder token, boolean suppress) { Loading Loading @@ -1209,6 +1239,40 @@ public final class SensorPrivacyService extends SystemService { } } private void userSwitching(int from, int to) { boolean micState; boolean camState; boolean prevMicState; boolean prevCamState; synchronized (mLock) { prevMicState = isIndividualSensorPrivacyEnabledLocked(from, MICROPHONE); prevCamState = isIndividualSensorPrivacyEnabledLocked(from, CAMERA); micState = isIndividualSensorPrivacyEnabledLocked(to, MICROPHONE); camState = isIndividualSensorPrivacyEnabledLocked(to, CAMERA); } if (prevMicState != micState) { mHandler.onUserGlobalSensorPrivacyChanged(MICROPHONE, micState); setGlobalRestriction(MICROPHONE, micState); } if (prevCamState != camState) { mHandler.onUserGlobalSensorPrivacyChanged(CAMERA, camState); setGlobalRestriction(CAMERA, micState); } } private void setGlobalRestriction(int sensor, boolean enabled) { switch(sensor) { case MICROPHONE: mAppOpsManagerInternal.setGlobalRestriction(OP_RECORD_AUDIO, enabled, mAppOpsRestrictionToken); break; case CAMERA: mAppOpsManagerInternal.setGlobalRestriction(OP_CAMERA, enabled, mAppOpsRestrictionToken); break; } } /** * Remove a sensor use reminder suppression token. * Loading Loading @@ -1454,7 +1518,12 @@ public final class SensorPrivacyService extends SystemService { @GuardedBy("mListenerLock") private final SparseArray<SparseArray<RemoteCallbackList<ISensorPrivacyListener>>> mIndividualSensorListeners = new SparseArray<>(); private final ArrayMap<ISensorPrivacyListener, DeathRecipient> mDeathRecipients; @GuardedBy("mListenerLock") private final SparseArray<RemoteCallbackList<ISensorPrivacyListener>> mUserGlobalIndividualSensorListeners = new SparseArray<>(); @GuardedBy("mListenerLock") private final ArrayMap<ISensorPrivacyListener, Pair<DeathRecipient, Integer>> mDeathRecipients; private final Context mContext; SensorPrivacyHandler(Looper looper, Context context) { Loading @@ -1479,18 +1548,22 @@ public final class SensorPrivacyService extends SystemService { mSensorPrivacyServiceImpl)); } public void onUserGlobalSensorPrivacyChanged(int sensor, boolean enabled) { sendMessage(PooledLambda.obtainMessage( SensorPrivacyHandler::handleUserGlobalSensorPrivacyChanged, this, sensor, enabled)); } public void addListener(ISensorPrivacyListener listener) { synchronized (mListenerLock) { DeathRecipient deathRecipient = new DeathRecipient(listener); mDeathRecipients.put(listener, deathRecipient); mListeners.register(listener); if (mListeners.register(listener)) { addDeathRecipient(listener); } } } public void addListener(int userId, int sensor, ISensorPrivacyListener listener) { synchronized (mListenerLock) { DeathRecipient deathRecipient = new DeathRecipient(listener); mDeathRecipients.put(listener, deathRecipient); SparseArray<RemoteCallbackList<ISensorPrivacyListener>> listenersForUser = mIndividualSensorListeners.get(userId); if (listenersForUser == null) { Loading @@ -1502,32 +1575,55 @@ public final class SensorPrivacyService extends SystemService { listeners = new RemoteCallbackList<>(); listenersForUser.put(sensor, listeners); } listeners.register(listener); if (listeners.register(listener)) { addDeathRecipient(listener); } } } public void removeListener(ISensorPrivacyListener listener) { public void addUserGlobalListener(int sensor, ISensorPrivacyListener listener) { synchronized (mListenerLock) { DeathRecipient deathRecipient = mDeathRecipients.remove(listener); if (deathRecipient != null) { deathRecipient.destroy(); RemoteCallbackList<ISensorPrivacyListener> listeners = mUserGlobalIndividualSensorListeners.get(sensor); if (listeners == null) { listeners = new RemoteCallbackList<>(); mUserGlobalIndividualSensorListeners.put(sensor, listeners); } if (listeners.register(listener)) { addDeathRecipient(listener); } mListeners.unregister(listener); } } public void removeListener(int sensor, ISensorPrivacyListener listener) { public void removeListener(ISensorPrivacyListener listener) { synchronized (mListenerLock) { DeathRecipient deathRecipient = mDeathRecipients.remove(listener); if (deathRecipient != null) { deathRecipient.destroy(); if (mListeners.unregister(listener)) { removeDeathRecipient(listener); } } } public void removeListener(int sensor, ISensorPrivacyListener listener) { synchronized (mListenerLock) { for (int i = 0, numUsers = mIndividualSensorListeners.size(); i < numUsers; i++) { RemoteCallbackList callbacks = mIndividualSensorListeners.valueAt(i).get(sensor); if (callbacks != null) { callbacks.unregister(listener); if (callbacks.unregister(listener)) { removeDeathRecipient(listener); } } } } } public void removeUserGlobalListener(int sensor, ISensorPrivacyListener listener) { synchronized (mListenerLock) { RemoteCallbackList callbacks = mUserGlobalIndividualSensorListeners.get(sensor); if (callbacks != null) { if (callbacks.unregister(listener)) { removeDeathRecipient(listener); } } } Loading @@ -1551,9 +1647,12 @@ public final class SensorPrivacyService extends SystemService { SparseArray<RemoteCallbackList<ISensorPrivacyListener>> listenersForUser = mIndividualSensorListeners.get(userId); setGlobalRestriction(); if (userId == mCurrentUser) { setGlobalRestriction(); mSensorPrivacyServiceImpl.setGlobalRestriction(sensor, enabled); } if (userId == mCurrentUser) { onUserGlobalSensorPrivacyChanged(sensor, enabled); } if (listenersForUser == null) { Loading @@ -1563,6 +1662,7 @@ public final class SensorPrivacyService extends SystemService { if (listeners == null) { return; } try { final int count = listeners.beginBroadcast(); for (int i = 0; i < count; i++) { ISensorPrivacyListener listener = listeners.getBroadcastItem(i); Loading @@ -1572,8 +1672,33 @@ public final class SensorPrivacyService extends SystemService { Log.e(TAG, "Caught an exception notifying listener " + listener + ": ", e); } } } finally { listeners.finishBroadcast(); } } public void handleUserGlobalSensorPrivacyChanged(int sensor, boolean enabled) { RemoteCallbackList<ISensorPrivacyListener> listeners = mUserGlobalIndividualSensorListeners.get(sensor); if (listeners == null) { return; } try { 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); } } } finally { listeners.finishBroadcast(); } } public void removeSuppressPackageReminderToken(Pair<Integer, UserHandle> key, IBinder token) { Loading @@ -1581,20 +1706,33 @@ public final class SensorPrivacyService extends SystemService { SensorPrivacyServiceImpl::removeSuppressPackageReminderToken, mSensorPrivacyServiceImpl, key, token)); } } private void setGlobalRestriction() { boolean camState = mSensorPrivacyServiceImpl .isIndividualSensorPrivacyEnabled(mCurrentUser, CAMERA); boolean micState = mSensorPrivacyServiceImpl .isIndividualSensorPrivacyEnabled(mCurrentUser, MICROPHONE); private void addDeathRecipient(ISensorPrivacyListener listener) { Pair<DeathRecipient, Integer> deathRecipient = mDeathRecipients.get(listener); if (deathRecipient == null) { deathRecipient = new Pair<>(new DeathRecipient(listener), 1); } else { int newRefCount = deathRecipient.second + 1; deathRecipient = new Pair<>(deathRecipient.first, newRefCount); } mDeathRecipients.put(listener, deathRecipient); } mAppOpsManagerInternal .setGlobalRestriction(OP_CAMERA, camState, mAppOpsRestrictionToken); mAppOpsManagerInternal .setGlobalRestriction(OP_RECORD_AUDIO, micState, mAppOpsRestrictionToken); private void removeDeathRecipient(ISensorPrivacyListener listener) { Pair<DeathRecipient, Integer> deathRecipient = mDeathRecipients.get(listener); if (deathRecipient == null) { return; } else { int newRefCount = deathRecipient.second - 1; if (newRefCount == 0) { mDeathRecipients.remove(listener); deathRecipient.first.destroy(); return; } deathRecipient = new Pair<>(deathRecipient.first, newRefCount); } mDeathRecipients.put(listener, deathRecipient); } } private final class DeathRecipient implements IBinder.DeathRecipient { Loading