Merge "Fix permissions update for VrListenerService on user changes." into nyc-dev
This commit is contained in:
@@ -1340,9 +1340,14 @@ public class AppOpsManager {
|
|||||||
/** @hide */
|
/** @hide */
|
||||||
public void setUserRestriction(int code, boolean restricted, IBinder token,
|
public void setUserRestriction(int code, boolean restricted, IBinder token,
|
||||||
String[] exceptionPackages) {
|
String[] exceptionPackages) {
|
||||||
|
setUserRestrictionForUser(code, restricted, token, exceptionPackages, mContext.getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public void setUserRestrictionForUser(int code, boolean restricted, IBinder token,
|
||||||
|
String[] exceptionPackages, int userId) {
|
||||||
try {
|
try {
|
||||||
mService.setUserRestriction(code, restricted, token, mContext.getUserId(),
|
mService.setUserRestriction(code, restricted, token, userId, exceptionPackages);
|
||||||
exceptionPackages);
|
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
throw e.rethrowFromSystemServer();
|
throw e.rethrowFromSystemServer();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,11 +46,12 @@ import android.service.vr.IVrListener;
|
|||||||
import android.service.vr.IVrManager;
|
import android.service.vr.IVrManager;
|
||||||
import android.service.vr.IVrStateCallbacks;
|
import android.service.vr.IVrStateCallbacks;
|
||||||
import android.service.vr.VrListenerService;
|
import android.service.vr.VrListenerService;
|
||||||
|
import android.util.ArrayMap;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
|
|
||||||
import com.android.internal.R;
|
import com.android.internal.R;
|
||||||
|
import com.android.server.LocalServices;
|
||||||
import com.android.server.SystemConfig;
|
import com.android.server.SystemConfig;
|
||||||
import com.android.server.SystemService;
|
import com.android.server.SystemService;
|
||||||
import com.android.server.utils.ManagedApplicationService.PendingEvent;
|
import com.android.server.utils.ManagedApplicationService.PendingEvent;
|
||||||
@@ -67,6 +68,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -197,29 +199,44 @@ public class VrManagerService extends SystemService implements EnabledComponentC
|
|||||||
|
|
||||||
private final class NotificationAccessManager {
|
private final class NotificationAccessManager {
|
||||||
private final SparseArray<ArraySet<String>> mAllowedPackages = new SparseArray<>();
|
private final SparseArray<ArraySet<String>> mAllowedPackages = new SparseArray<>();
|
||||||
|
private final ArrayMap<String, Integer> mNotificationAccessPackageToUserId =
|
||||||
|
new ArrayMap<>();
|
||||||
|
|
||||||
public void update(Collection<String> packageNames) {
|
public void update(Collection<String> packageNames) {
|
||||||
int currentUserId = ActivityManager.getCurrentUser();
|
int currentUserId = ActivityManager.getCurrentUser();
|
||||||
|
|
||||||
UserHandle currentUserHandle = new UserHandle(currentUserId);
|
|
||||||
|
|
||||||
ArraySet<String> allowed = mAllowedPackages.get(currentUserId);
|
ArraySet<String> allowed = mAllowedPackages.get(currentUserId);
|
||||||
if (allowed == null) {
|
if (allowed == null) {
|
||||||
allowed = new ArraySet<>();
|
allowed = new ArraySet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure we revoke notification access for listeners in other users
|
||||||
|
final int listenerCount = mNotificationAccessPackageToUserId.size();
|
||||||
|
for (int i = listenerCount - 1; i >= 0; i--) {
|
||||||
|
final int grantUserId = mNotificationAccessPackageToUserId.valueAt(i);
|
||||||
|
if (grantUserId != currentUserId) {
|
||||||
|
String packageName = mNotificationAccessPackageToUserId.keyAt(i);
|
||||||
|
revokeNotificationListenerAccess(packageName, grantUserId);
|
||||||
|
revokeNotificationPolicyAccess(packageName);
|
||||||
|
revokeCoarseLocationPermissionIfNeeded(packageName, grantUserId);
|
||||||
|
mNotificationAccessPackageToUserId.removeAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (String pkg : allowed) {
|
for (String pkg : allowed) {
|
||||||
if (!packageNames.contains(pkg)) {
|
if (!packageNames.contains(pkg)) {
|
||||||
revokeNotificationListenerAccess(pkg);
|
revokeNotificationListenerAccess(pkg, currentUserId);
|
||||||
revokeNotificationPolicyAccess(pkg);
|
revokeNotificationPolicyAccess(pkg);
|
||||||
revokeCoarseLocationAccess(pkg, currentUserHandle);
|
revokeCoarseLocationPermissionIfNeeded(pkg, currentUserId);
|
||||||
|
mNotificationAccessPackageToUserId.remove(pkg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (String pkg : packageNames) {
|
for (String pkg : packageNames) {
|
||||||
if (!allowed.contains(pkg)) {
|
if (!allowed.contains(pkg)) {
|
||||||
grantNotificationPolicyAccess(pkg);
|
grantNotificationPolicyAccess(pkg);
|
||||||
grantNotificationListenerAccess(pkg, currentUserHandle);
|
grantNotificationListenerAccess(pkg, currentUserId);
|
||||||
grantCoarseLocationAccess(pkg, currentUserHandle);
|
grantCoarseLocationPermissionIfNeeded(pkg, currentUserId);
|
||||||
|
mNotificationAccessPackageToUserId.put(pkg, currentUserId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,7 +246,6 @@ public class VrManagerService extends SystemService implements EnabledComponentC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a user, package, or setting changes that could affect whether or not the
|
* Called when a user, package, or setting changes that could affect whether or not the
|
||||||
* currently bound VrListenerService is changed.
|
* currently bound VrListenerService is changed.
|
||||||
@@ -535,17 +551,33 @@ public class VrManagerService extends SystemService implements EnabledComponentC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateOverlayStateLocked(ComponentName exemptedComponent) {
|
private void updateOverlayStateLocked(String exemptedPackage, int newUserId, int oldUserId) {
|
||||||
|
AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
|
||||||
|
|
||||||
|
// If user changed drop restrictions for the old user.
|
||||||
|
if (oldUserId != newUserId) {
|
||||||
|
appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
|
||||||
|
false, mOverlayToken, null, oldUserId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the restrictions for the current user based on vr state
|
||||||
|
String[] exemptions = (exemptedPackage == null) ? new String[0] :
|
||||||
|
new String[] { exemptedPackage };
|
||||||
|
|
||||||
|
appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
|
||||||
|
mVrModeEnabled, mOverlayToken, exemptions, newUserId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateDependentAppOpsLocked(String newVrServicePackage, int newUserId,
|
||||||
|
String oldVrServicePackage, int oldUserId) {
|
||||||
|
// If VR state changed and we also have a VR service change.
|
||||||
|
if (Objects.equals(newVrServicePackage, oldVrServicePackage)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
final long identity = Binder.clearCallingIdentity();
|
final long identity = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
|
// Set overlay exception state based on VR enabled and current service
|
||||||
if (appOpsManager != null) {
|
updateOverlayStateLocked(newVrServicePackage, newUserId, oldUserId);
|
||||||
String[] exemptions = (exemptedComponent == null) ? new String[0] :
|
|
||||||
new String[] { exemptedComponent.getPackageName() };
|
|
||||||
|
|
||||||
appOpsManager.setUserRestriction(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
|
|
||||||
mVrModeEnabled, mOverlayToken, exemptions);
|
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(identity);
|
Binder.restoreCallingIdentity(identity);
|
||||||
}
|
}
|
||||||
@@ -578,8 +610,12 @@ public class VrManagerService extends SystemService implements EnabledComponentC
|
|||||||
return validUserComponent; // Disabled -> Disabled transition does nothing.
|
return validUserComponent; // Disabled -> Disabled transition does nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String oldVrServicePackage = mCurrentVrService != null
|
||||||
|
? mCurrentVrService.getComponent().getPackageName() : null;
|
||||||
|
final int oldUserId = mCurrentVrModeUser;
|
||||||
|
|
||||||
// Always send mode change events.
|
// Always send mode change events.
|
||||||
changeVrModeLocked(enabled, (enabled && validUserComponent) ? component : null);
|
changeVrModeLocked(enabled);
|
||||||
|
|
||||||
if (!enabled || !validUserComponent) {
|
if (!enabled || !validUserComponent) {
|
||||||
// Unbind whatever is running
|
// Unbind whatever is running
|
||||||
@@ -608,10 +644,23 @@ public class VrManagerService extends SystemService implements EnabledComponentC
|
|||||||
|
|
||||||
if (calling != null && !Objects.equals(calling, mCurrentVrModeComponent)) {
|
if (calling != null && !Objects.equals(calling, mCurrentVrModeComponent)) {
|
||||||
mCurrentVrModeComponent = calling;
|
mCurrentVrModeComponent = calling;
|
||||||
|
sendUpdatedCaller = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCurrentVrModeUser != userId) {
|
||||||
mCurrentVrModeUser = userId;
|
mCurrentVrModeUser = userId;
|
||||||
sendUpdatedCaller = true;
|
sendUpdatedCaller = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String newVrServicePackage = mCurrentVrService != null
|
||||||
|
? mCurrentVrService.getComponent().getPackageName() : null;
|
||||||
|
final int newUserId = mCurrentVrModeUser;
|
||||||
|
|
||||||
|
// Update AppOps settings that change state when entering/exiting VR mode, or changing
|
||||||
|
// the current VrListenerService.
|
||||||
|
updateDependentAppOpsLocked(newVrServicePackage, newUserId,
|
||||||
|
oldVrServicePackage, oldUserId);
|
||||||
|
|
||||||
if (mCurrentVrService != null && sendUpdatedCaller) {
|
if (mCurrentVrService != null && sendUpdatedCaller) {
|
||||||
final ComponentName c = mCurrentVrModeComponent;
|
final ComponentName c = mCurrentVrModeComponent;
|
||||||
mCurrentVrService.sendEvent(new PendingEvent() {
|
mCurrentVrService.sendEvent(new PendingEvent() {
|
||||||
@@ -645,18 +694,6 @@ public class VrManagerService extends SystemService implements EnabledComponentC
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void grantCoarseLocationAccess(String pkg, UserHandle userId) {
|
|
||||||
PackageManager pm = mContext.getPackageManager();
|
|
||||||
pm.grantRuntimePermission(pkg, android.Manifest.permission.ACCESS_COARSE_LOCATION,
|
|
||||||
userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void revokeCoarseLocationAccess(String pkg, UserHandle userId) {
|
|
||||||
PackageManager pm = mContext.getPackageManager();
|
|
||||||
pm.revokeRuntimePermission(pkg,
|
|
||||||
android.Manifest.permission.ACCESS_COARSE_LOCATION, userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void grantNotificationPolicyAccess(String pkg) {
|
private void grantNotificationPolicyAccess(String pkg) {
|
||||||
NotificationManager nm = mContext.getSystemService(NotificationManager.class);
|
NotificationManager nm = mContext.getSystemService(NotificationManager.class);
|
||||||
nm.setNotificationPolicyAccessGranted(pkg, true);
|
nm.setNotificationPolicyAccessGranted(pkg, true);
|
||||||
@@ -670,14 +707,14 @@ public class VrManagerService extends SystemService implements EnabledComponentC
|
|||||||
nm.setNotificationPolicyAccessGranted(pkg, false);
|
nm.setNotificationPolicyAccessGranted(pkg, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void grantNotificationListenerAccess(String pkg, UserHandle userId) {
|
private void grantNotificationListenerAccess(String pkg, int userId) {
|
||||||
PackageManager pm = mContext.getPackageManager();
|
PackageManager pm = mContext.getPackageManager();
|
||||||
ArraySet<ComponentName> possibleServices = EnabledComponentsObserver.loadComponentNames(pm,
|
ArraySet<ComponentName> possibleServices = EnabledComponentsObserver.loadComponentNames(pm,
|
||||||
userId.getIdentifier(), NotificationListenerService.SERVICE_INTERFACE,
|
userId, NotificationListenerService.SERVICE_INTERFACE,
|
||||||
android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE);
|
android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE);
|
||||||
ContentResolver resolver = mContext.getContentResolver();
|
ContentResolver resolver = mContext.getContentResolver();
|
||||||
|
|
||||||
ArraySet<String> current = getCurrentNotifListeners(resolver);
|
ArraySet<String> current = getNotificationListeners(resolver, userId);
|
||||||
|
|
||||||
for (ComponentName c : possibleServices) {
|
for (ComponentName c : possibleServices) {
|
||||||
String flatName = c.flattenToString();
|
String flatName = c.flattenToString();
|
||||||
@@ -689,14 +726,16 @@ public class VrManagerService extends SystemService implements EnabledComponentC
|
|||||||
|
|
||||||
if (current.size() > 0) {
|
if (current.size() > 0) {
|
||||||
String flatSettings = formatSettings(current);
|
String flatSettings = formatSettings(current);
|
||||||
Settings.Secure.putString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
|
Settings.Secure.putStringForUser(resolver,
|
||||||
flatSettings);
|
Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
|
||||||
|
flatSettings, userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void revokeNotificationListenerAccess(String pkg) {
|
private void revokeNotificationListenerAccess(String pkg, int userId) {
|
||||||
ContentResolver resolver = mContext.getContentResolver();
|
ContentResolver resolver = mContext.getContentResolver();
|
||||||
ArraySet<String> current = getCurrentNotifListeners(resolver);
|
|
||||||
|
ArraySet<String> current = getNotificationListeners(resolver, userId);
|
||||||
|
|
||||||
ArrayList<String> toRemove = new ArrayList<>();
|
ArrayList<String> toRemove = new ArrayList<>();
|
||||||
|
|
||||||
@@ -710,14 +749,37 @@ public class VrManagerService extends SystemService implements EnabledComponentC
|
|||||||
current.removeAll(toRemove);
|
current.removeAll(toRemove);
|
||||||
|
|
||||||
String flatSettings = formatSettings(current);
|
String flatSettings = formatSettings(current);
|
||||||
Settings.Secure.putString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
|
Settings.Secure.putStringForUser(resolver,
|
||||||
flatSettings);
|
Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
|
||||||
|
flatSettings, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArraySet<String> getCurrentNotifListeners(ContentResolver resolver) {
|
private void grantCoarseLocationPermissionIfNeeded(String pkg, int userId) {
|
||||||
String flat = Settings.Secure.getString(resolver,
|
// Don't clobber the user if permission set in current state explicitly
|
||||||
Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
|
if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
|
||||||
|
mContext.getPackageManager().grantRuntimePermission(pkg,
|
||||||
|
Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void revokeCoarseLocationPermissionIfNeeded(String pkg, int userId) {
|
||||||
|
// Don't clobber the user if permission set in current state explicitly
|
||||||
|
if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
|
||||||
|
mContext.getPackageManager().revokeRuntimePermission(pkg,
|
||||||
|
Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isPermissionUserUpdated(String permission, String pkg, int userId) {
|
||||||
|
final int flags = mContext.getPackageManager().getPermissionFlags(
|
||||||
|
permission, pkg, new UserHandle(userId));
|
||||||
|
return (flags & (PackageManager.FLAG_PERMISSION_USER_SET
|
||||||
|
| PackageManager.FLAG_PERMISSION_USER_FIXED)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArraySet<String> getNotificationListeners(ContentResolver resolver, int userId) {
|
||||||
|
String flat = Settings.Secure.getStringForUser(resolver,
|
||||||
|
Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, userId);
|
||||||
|
|
||||||
ArraySet<String> current = new ArraySet<>();
|
ArraySet<String> current = new ArraySet<>();
|
||||||
if (flat != null) {
|
if (flat != null) {
|
||||||
@@ -763,9 +825,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC
|
|||||||
* Note: Must be called while holding {@code mLock}.
|
* Note: Must be called while holding {@code mLock}.
|
||||||
*
|
*
|
||||||
* @param enabled new state of the VR mode.
|
* @param enabled new state of the VR mode.
|
||||||
* @param exemptedComponent a component to exempt from AppOps restrictions for overlays.
|
|
||||||
*/
|
*/
|
||||||
private void changeVrModeLocked(boolean enabled, ComponentName exemptedComponent) {
|
private void changeVrModeLocked(boolean enabled) {
|
||||||
if (mVrModeEnabled != enabled) {
|
if (mVrModeEnabled != enabled) {
|
||||||
mVrModeEnabled = enabled;
|
mVrModeEnabled = enabled;
|
||||||
|
|
||||||
@@ -773,7 +834,6 @@ public class VrManagerService extends SystemService implements EnabledComponentC
|
|||||||
Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
|
Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
|
||||||
setVrModeNative(mVrModeEnabled);
|
setVrModeNative(mVrModeEnabled);
|
||||||
|
|
||||||
updateOverlayStateLocked(exemptedComponent);
|
|
||||||
onVrModeChangedLocked();
|
onVrModeChangedLocked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user