Merge "Add global app op restrictions" into sc-dev

This commit is contained in:
TreeHugger Robot
2021-06-29 19:53:50 +00:00
committed by Android (Google) Code Review
4 changed files with 164 additions and 36 deletions

View File

@@ -209,4 +209,10 @@ public abstract class AppOpsManagerInternal {
*/ */
public abstract void setModeFromPermissionPolicy(int code, int uid, @NonNull String packageName, public abstract void setModeFromPermissionPolicy(int code, int uid, @NonNull String packageName,
int mode, @Nullable IAppOpsCallback callback); int mode, @Nullable IAppOpsCallback callback);
/**
* Sets a global restriction on an op code.
*/
public abstract void setGlobalRestriction(int code, boolean restricted, IBinder token);
} }

View File

@@ -97,6 +97,7 @@ interface IAppOpsService {
void setUserRestrictions(in Bundle restrictions, IBinder token, int userHandle); void setUserRestrictions(in Bundle restrictions, IBinder token, int userHandle);
void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle, in PackageTagsList excludedPackageTags); void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle, in PackageTagsList excludedPackageTags);
void removeUser(int userHandle); void removeUser(int userHandle);
void startWatchingActive(in int[] ops, IAppOpsActiveCallback callback); void startWatchingActive(in int[] ops, IAppOpsActiveCallback callback);

View File

@@ -28,7 +28,6 @@ import static android.app.AppOpsManager.OP_CAMERA;
import static android.app.AppOpsManager.OP_PHONE_CALL_CAMERA; import static android.app.AppOpsManager.OP_PHONE_CALL_CAMERA;
import static android.app.AppOpsManager.OP_PHONE_CALL_MICROPHONE; import static android.app.AppOpsManager.OP_PHONE_CALL_MICROPHONE;
import static android.app.AppOpsManager.OP_RECORD_AUDIO; import static android.app.AppOpsManager.OP_RECORD_AUDIO;
import static android.app.AppOpsManager.OP_RECORD_AUDIO_HOTWORD;
import static android.content.Intent.EXTRA_PACKAGE_NAME; import static android.content.Intent.EXTRA_PACKAGE_NAME;
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -47,6 +46,7 @@ import android.app.ActivityManagerInternal;
import android.app.ActivityOptions; import android.app.ActivityOptions;
import android.app.ActivityTaskManager; import android.app.ActivityTaskManager;
import android.app.AppOpsManager; import android.app.AppOpsManager;
import android.app.AppOpsManagerInternal;
import android.app.KeyguardManager; import android.app.KeyguardManager;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationChannel; import android.app.NotificationChannel;
@@ -163,6 +163,7 @@ public final class SensorPrivacyService extends SystemService {
private final ActivityManagerInternal mActivityManagerInternal; private final ActivityManagerInternal mActivityManagerInternal;
private final ActivityTaskManager mActivityTaskManager; private final ActivityTaskManager mActivityTaskManager;
private final AppOpsManager mAppOpsManager; private final AppOpsManager mAppOpsManager;
private final AppOpsManagerInternal mAppOpsManagerInternal;
private final TelephonyManager mTelephonyManager; private final TelephonyManager mTelephonyManager;
private final IBinder mAppOpsRestrictionToken = new Binder(); private final IBinder mAppOpsRestrictionToken = new Binder();
@@ -172,16 +173,18 @@ public final class SensorPrivacyService extends SystemService {
private EmergencyCallHelper mEmergencyCallHelper; private EmergencyCallHelper mEmergencyCallHelper;
private KeyguardManager mKeyguardManager; private KeyguardManager mKeyguardManager;
private int mCurrentUser = -1;
public SensorPrivacyService(Context context) { public SensorPrivacyService(Context context) {
super(context); super(context);
mContext = context; mContext = context;
mAppOpsManager = context.getSystemService(AppOpsManager.class); mAppOpsManager = context.getSystemService(AppOpsManager.class);
mAppOpsManagerInternal = getLocalService(AppOpsManagerInternal.class);
mUserManagerInternal = getLocalService(UserManagerInternal.class); mUserManagerInternal = getLocalService(UserManagerInternal.class);
mActivityManager = context.getSystemService(ActivityManager.class); mActivityManager = context.getSystemService(ActivityManager.class);
mActivityManagerInternal = getLocalService(ActivityManagerInternal.class); mActivityManagerInternal = getLocalService(ActivityManagerInternal.class);
mActivityTaskManager = context.getSystemService(ActivityTaskManager.class); mActivityTaskManager = context.getSystemService(ActivityTaskManager.class);
mTelephonyManager = context.getSystemService(TelephonyManager.class); mTelephonyManager = context.getSystemService(TelephonyManager.class);
mSensorPrivacyServiceImpl = new SensorPrivacyServiceImpl(); mSensorPrivacyServiceImpl = new SensorPrivacyServiceImpl();
} }
@@ -201,6 +204,20 @@ public final class SensorPrivacyService extends SystemService {
} }
} }
@Override
public void onUserStarting(TargetUser user) {
if (mCurrentUser == -1) {
mCurrentUser = user.getUserIdentifier();
setGlobalRestriction();
}
}
@Override
public void onUserSwitching(TargetUser from, TargetUser to) {
mCurrentUser = to.getUserIdentifier();
setGlobalRestriction();
}
class SensorPrivacyServiceImpl extends ISensorPrivacyManager.Stub implements class SensorPrivacyServiceImpl extends ISensorPrivacyManager.Stub implements
AppOpsManager.OnOpNotedListener, AppOpsManager.OnOpStartedListener, AppOpsManager.OnOpNotedListener, AppOpsManager.OnOpStartedListener,
IBinder.DeathRecipient, UserManagerInternal.UserRestrictionsListener { IBinder.DeathRecipient, UserManagerInternal.UserRestrictionsListener {
@@ -262,17 +279,6 @@ public final class SensorPrivacyService extends SystemService {
if (readPersistedSensorPrivacyStateLocked()) { if (readPersistedSensorPrivacyStateLocked()) {
persistSensorPrivacyStateLocked(); persistSensorPrivacyStateLocked();
} }
for (int i = 0; i < mIndividualEnabled.size(); i++) {
int userId = mIndividualEnabled.keyAt(i);
SparseBooleanArray userIndividualEnabled =
mIndividualEnabled.valueAt(i);
for (int j = 0; j < userIndividualEnabled.size(); j++) {
int sensor = userIndividualEnabled.keyAt(j);
boolean enabled = userIndividualEnabled.valueAt(j);
setUserRestriction(userId, sensor, enabled);
}
}
} }
int[] micAndCameraOps = new int[]{OP_RECORD_AUDIO, OP_PHONE_CALL_MICROPHONE, int[] micAndCameraOps = new int[]{OP_RECORD_AUDIO, OP_PHONE_CALL_MICROPHONE,
@@ -1379,7 +1385,10 @@ public final class SensorPrivacyService extends SystemService {
SparseArray<RemoteCallbackList<ISensorPrivacyListener>> listenersForUser = SparseArray<RemoteCallbackList<ISensorPrivacyListener>> listenersForUser =
mIndividualSensorListeners.get(userId); mIndividualSensorListeners.get(userId);
setUserRestriction(userId, sensor, enabled); setGlobalRestriction();
if (userId == mCurrentUser) {
setGlobalRestriction();
}
if (listenersForUser == null) { if (listenersForUser == null) {
return; return;
@@ -1408,16 +1417,18 @@ public final class SensorPrivacyService extends SystemService {
} }
} }
private void setUserRestriction(int userId, int sensor, boolean enabled) { private void setGlobalRestriction() {
if (sensor == CAMERA) { boolean camState =
mAppOpsManager.setUserRestrictionForUser(OP_CAMERA, enabled, mSensorPrivacyServiceImpl
mAppOpsRestrictionToken, null, userId); .isIndividualSensorPrivacyEnabled(mCurrentUser, CAMERA);
} else if (sensor == MICROPHONE) { boolean micState =
mAppOpsManager.setUserRestrictionForUser(OP_RECORD_AUDIO, enabled, mSensorPrivacyServiceImpl
mAppOpsRestrictionToken, null, userId); .isIndividualSensorPrivacyEnabled(mCurrentUser, MICROPHONE);
mAppOpsManager.setUserRestrictionForUser(OP_RECORD_AUDIO_HOTWORD, enabled,
mAppOpsRestrictionToken, null, userId); mAppOpsManagerInternal
} .setGlobalRestriction(OP_CAMERA, camState, mAppOpsRestrictionToken);
mAppOpsManagerInternal
.setGlobalRestriction(OP_RECORD_AUDIO, micState, mAppOpsRestrictionToken);
} }
private final class DeathRecipient implements IBinder.DeathRecipient { private final class DeathRecipient implements IBinder.DeathRecipient {
@@ -1535,7 +1546,7 @@ public final class SensorPrivacyService extends SystemService {
} }
private class EmergencyCallHelper { private class EmergencyCallHelper {
private OutogingEmergencyStateCallback mEmergencyStateCallback; private OutgoingEmergencyStateCallback mEmergencyStateCallback;
private CallStateCallback mCallStateCallback; private CallStateCallback mCallStateCallback;
private boolean mIsInEmergencyCall; private boolean mIsInEmergencyCall;
@@ -1544,7 +1555,7 @@ public final class SensorPrivacyService extends SystemService {
private Object mEmergencyStateLock = new Object(); private Object mEmergencyStateLock = new Object();
EmergencyCallHelper() { EmergencyCallHelper() {
mEmergencyStateCallback = new OutogingEmergencyStateCallback(); mEmergencyStateCallback = new OutgoingEmergencyStateCallback();
mCallStateCallback = new CallStateCallback(); mCallStateCallback = new CallStateCallback();
mTelephonyManager.registerTelephonyCallback(FgThread.getExecutor(), mTelephonyManager.registerTelephonyCallback(FgThread.getExecutor(),
@@ -1559,7 +1570,7 @@ public final class SensorPrivacyService extends SystemService {
} }
} }
private class OutogingEmergencyStateCallback extends TelephonyCallback implements private class OutgoingEmergencyStateCallback extends TelephonyCallback implements
TelephonyCallback.OutgoingEmergencyCallListener { TelephonyCallback.OutgoingEmergencyCallListener {
@Override @Override
public void onOutgoingEmergencyCall(EmergencyNumber placedEmergencyNumber, public void onOutgoingEmergencyCall(EmergencyNumber placedEmergencyNumber,

View File

@@ -338,7 +338,14 @@ public class AppOpsService extends IAppOpsService.Stub {
/* /*
* These are app op restrictions imposed per user from various parties. * These are app op restrictions imposed per user from various parties.
*/ */
private final ArrayMap<IBinder, ClientRestrictionState> mOpUserRestrictions = new ArrayMap<>(); private final ArrayMap<IBinder, ClientUserRestrictionState> mOpUserRestrictions =
new ArrayMap<>();
/*
* These are app op restrictions imposed globally from various parties within the system.
*/
private final ArrayMap<IBinder, ClientGlobalRestrictionState> mOpGlobalRestrictions =
new ArrayMap<>();
SparseIntArray mProfileOwners; SparseIntArray mProfileOwners;
@@ -4722,13 +4729,22 @@ public class AppOpsService extends IAppOpsService.Stub {
private boolean isOpRestrictedLocked(int uid, int code, String packageName, private boolean isOpRestrictedLocked(int uid, int code, String packageName,
String attributionTag, @Nullable RestrictionBypass appBypass) { String attributionTag, @Nullable RestrictionBypass appBypass) {
int restrictionSetCount = mOpGlobalRestrictions.size();
for (int i = 0; i < restrictionSetCount; i++) {
ClientGlobalRestrictionState restrictionState = mOpGlobalRestrictions.valueAt(i);
if (restrictionState.hasRestriction(code)) {
return true;
}
}
int userHandle = UserHandle.getUserId(uid); int userHandle = UserHandle.getUserId(uid);
final int restrictionSetCount = mOpUserRestrictions.size(); restrictionSetCount = mOpUserRestrictions.size();
for (int i = 0; i < restrictionSetCount; i++) { for (int i = 0; i < restrictionSetCount; i++) {
// For each client, check that the given op is not restricted, or that the given // For each client, check that the given op is not restricted, or that the given
// package is exempt from the restriction. // package is exempt from the restriction.
ClientRestrictionState restrictionState = mOpUserRestrictions.valueAt(i); ClientUserRestrictionState restrictionState = mOpUserRestrictions.valueAt(i);
if (restrictionState.hasRestriction(code, packageName, attributionTag, userHandle)) { if (restrictionState.hasRestriction(code, packageName, attributionTag, userHandle)) {
RestrictionBypass opBypass = opAllowSystemBypassRestriction(code); RestrictionBypass opBypass = opAllowSystemBypassRestriction(code);
if (opBypass != null) { if (opBypass != null) {
@@ -6295,10 +6311,31 @@ public class AppOpsService extends IAppOpsService.Stub {
pw.println(); pw.println();
} }
final int globalRestrictionCount = mOpGlobalRestrictions.size();
for (int i = 0; i < globalRestrictionCount; i++) {
IBinder token = mOpGlobalRestrictions.keyAt(i);
ClientGlobalRestrictionState restrictionState = mOpGlobalRestrictions.valueAt(i);
ArraySet<Integer> restrictedOps = restrictionState.mRestrictedOps;
pw.println(" Global restrictions for token " + token + ":");
StringBuilder restrictedOpsValue = new StringBuilder();
restrictedOpsValue.append("[");
final int restrictedOpCount = restrictedOps.size();
for (int j = 0; j < restrictedOpCount; j++) {
if (restrictedOpsValue.length() > 1) {
restrictedOpsValue.append(", ");
}
restrictedOpsValue.append(AppOpsManager.opToName(restrictedOps.valueAt(j)));
}
restrictedOpsValue.append("]");
pw.println(" Restricted ops: " + restrictedOpsValue);
}
final int userRestrictionCount = mOpUserRestrictions.size(); final int userRestrictionCount = mOpUserRestrictions.size();
for (int i = 0; i < userRestrictionCount; i++) { for (int i = 0; i < userRestrictionCount; i++) {
IBinder token = mOpUserRestrictions.keyAt(i); IBinder token = mOpUserRestrictions.keyAt(i);
ClientRestrictionState restrictionState = mOpUserRestrictions.valueAt(i); ClientUserRestrictionState restrictionState = mOpUserRestrictions.valueAt(i);
boolean printedTokenHeader = false; boolean printedTokenHeader = false;
if (dumpMode >= 0 || dumpWatchers || dumpHistory) { if (dumpMode >= 0 || dumpWatchers || dumpHistory) {
@@ -6444,11 +6481,11 @@ public class AppOpsService extends IAppOpsService.Stub {
private void setUserRestrictionNoCheck(int code, boolean restricted, IBinder token, private void setUserRestrictionNoCheck(int code, boolean restricted, IBinder token,
int userHandle, PackageTagsList excludedPackageTags) { int userHandle, PackageTagsList excludedPackageTags) {
synchronized (AppOpsService.this) { synchronized (AppOpsService.this) {
ClientRestrictionState restrictionState = mOpUserRestrictions.get(token); ClientUserRestrictionState restrictionState = mOpUserRestrictions.get(token);
if (restrictionState == null) { if (restrictionState == null) {
try { try {
restrictionState = new ClientRestrictionState(token); restrictionState = new ClientUserRestrictionState(token);
} catch (RemoteException e) { } catch (RemoteException e) {
return; return;
} }
@@ -6528,7 +6565,7 @@ public class AppOpsService extends IAppOpsService.Stub {
synchronized (AppOpsService.this) { synchronized (AppOpsService.this) {
final int tokenCount = mOpUserRestrictions.size(); final int tokenCount = mOpUserRestrictions.size();
for (int i = tokenCount - 1; i >= 0; i--) { for (int i = tokenCount - 1; i >= 0; i--) {
ClientRestrictionState opRestrictions = mOpUserRestrictions.valueAt(i); ClientUserRestrictionState opRestrictions = mOpUserRestrictions.valueAt(i);
opRestrictions.removeUser(userHandle); opRestrictions.removeUser(userHandle);
} }
removeUidsForUserLocked(userHandle); removeUidsForUserLocked(userHandle);
@@ -6986,12 +7023,12 @@ public class AppOpsService extends IAppOpsService.Stub {
return packageNames; return packageNames;
} }
private final class ClientRestrictionState implements DeathRecipient { private final class ClientUserRestrictionState implements DeathRecipient {
private final IBinder token; private final IBinder token;
SparseArray<boolean[]> perUserRestrictions; SparseArray<boolean[]> perUserRestrictions;
SparseArray<PackageTagsList> perUserExcludedPackageTags; SparseArray<PackageTagsList> perUserExcludedPackageTags;
public ClientRestrictionState(IBinder token) ClientUserRestrictionState(IBinder token)
throws RemoteException { throws RemoteException {
token.linkToDeath(this, 0); token.linkToDeath(this, 0);
this.token = token; this.token = token;
@@ -7082,6 +7119,7 @@ public class AppOpsService extends IAppOpsService.Stub {
if (perUserExclusions == null) { if (perUserExclusions == null) {
return true; return true;
} }
return !perUserExclusions.contains(packageName, attributionTag); return !perUserExclusions.contains(packageName, attributionTag);
} }
@@ -7143,6 +7181,42 @@ public class AppOpsService extends IAppOpsService.Stub {
} }
} }
private final class ClientGlobalRestrictionState implements DeathRecipient {
final IBinder mToken;
final ArraySet<Integer> mRestrictedOps = new ArraySet<>();
ClientGlobalRestrictionState(IBinder token)
throws RemoteException {
token.linkToDeath(this, 0);
this.mToken = token;
}
boolean setRestriction(int code, boolean restricted) {
if (restricted) {
return mRestrictedOps.add(code);
} else {
return mRestrictedOps.remove(code);
}
}
boolean hasRestriction(int code) {
return mRestrictedOps.contains(code);
}
boolean isDefault() {
return mRestrictedOps.isEmpty();
}
@Override
public void binderDied() {
destroy();
}
void destroy() {
mToken.unlinkToDeath(this, 0);
}
}
private final class AppOpsManagerInternalImpl extends AppOpsManagerInternal { private final class AppOpsManagerInternalImpl extends AppOpsManagerInternal {
@Override public void setDeviceAndProfileOwners(SparseIntArray owners) { @Override public void setDeviceAndProfileOwners(SparseIntArray owners) {
synchronized (AppOpsService.this) { synchronized (AppOpsService.this) {
@@ -7167,6 +7241,42 @@ public class AppOpsService extends IAppOpsService.Stub {
int mode, @Nullable IAppOpsCallback callback) { int mode, @Nullable IAppOpsCallback callback) {
setMode(code, uid, packageName, mode, callback); setMode(code, uid, packageName, mode, callback);
} }
@Override
public void setGlobalRestriction(int code, boolean restricted, IBinder token) {
if (Binder.getCallingPid() != Process.myPid()) {
// TODO instead of this enforcement put in AppOpsManagerInternal
throw new SecurityException("Only the system can set global restrictions");
}
synchronized (AppOpsService.this) {
ClientGlobalRestrictionState restrictionState = mOpGlobalRestrictions.get(token);
if (restrictionState == null) {
try {
restrictionState = new ClientGlobalRestrictionState(token);
} catch (RemoteException e) {
return;
}
mOpGlobalRestrictions.put(token, restrictionState);
}
if (restrictionState.setRestriction(code, restricted)) {
mHandler.sendMessage(PooledLambda.obtainMessage(
AppOpsService::notifyWatchersOfChange, AppOpsService.this, code,
UID_ANY));
mHandler.sendMessage(PooledLambda.obtainMessage(
AppOpsService::updateStartedOpModeForUser, AppOpsService.this,
code, restricted, UserHandle.USER_ALL));
}
if (restrictionState.isDefault()) {
mOpGlobalRestrictions.remove(token);
restrictionState.destroy();
}
}
}
} }
/** /**