Merge "Update mic/cam quicksetting toggles when user changes" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
4e09234999
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user