Merge "Update mic/cam quicksetting toggles when user changes" into sc-dev am: 4e09234999

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15365189

Change-Id: I41fc267659a241f7a1cce0268cfa4d719aef3f09
This commit is contained in:
Evan Severson
2021-07-24 02:56:11 +00:00
committed by Automerger Merge Worker
3 changed files with 228 additions and 59 deletions

View File

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

View File

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

View File

@@ -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
@@ -897,18 +897,22 @@ public final class SensorPrivacyService extends SystemService {
public boolean isIndividualSensorPrivacyEnabled(@UserIdInt int userId, int sensor) {
enforceObserveSensorPrivacyPermission();
synchronized (mLock) {
SparseArray<SensorState> states = mIndividualEnabled.get(userId);
if (states == null) {
return false;
}
SensorState state = states.get(sensor);
if (state == null) {
return false;
}
return state.mEnabled;
return isIndividualSensorPrivacyEnabledLocked(userId, sensor);
}
}
private boolean isIndividualSensorPrivacyEnabledLocked(int userId, int sensor) {
SparseArray<SensorState> states = mIndividualEnabled.get(userId);
if (states == null) {
return false;
}
SensorState state = states.get(sensor);
if (state == null) {
return false;
}
return state.mEnabled;
}
/**
* Returns the state of sensor privacy from persistent storage.
*/
@@ -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.
*/
@@ -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) {
@@ -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.
*
@@ -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) {
@@ -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) {
@@ -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 addUserGlobalListener(int sensor, ISensorPrivacyListener listener) {
synchronized (mListenerLock) {
RemoteCallbackList<ISensorPrivacyListener> listeners =
mUserGlobalIndividualSensorListeners.get(sensor);
if (listeners == null) {
listeners = new RemoteCallbackList<>();
mUserGlobalIndividualSensorListeners.put(sensor, listeners);
}
if (listeners.register(listener)) {
addDeathRecipient(listener);
}
}
}
public void removeListener(ISensorPrivacyListener listener) {
synchronized (mListenerLock) {
DeathRecipient deathRecipient = mDeathRecipients.remove(listener);
if (deathRecipient != null) {
deathRecipient.destroy();
if (mListeners.unregister(listener)) {
removeDeathRecipient(listener);
}
mListeners.unregister(listener);
}
}
public void removeListener(int sensor, ISensorPrivacyListener listener) {
synchronized (mListenerLock) {
DeathRecipient deathRecipient = mDeathRecipients.remove(listener);
if (deathRecipient != null) {
deathRecipient.destroy();
}
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);
}
}
}
@@ -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) {
@@ -1563,16 +1662,42 @@ public final class SensorPrivacyService extends SystemService {
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);
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 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();
}
listeners.finishBroadcast();
}
public void removeSuppressPackageReminderToken(Pair<Integer, UserHandle> key,
@@ -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 {