Loading core/java/android/app/AppOpsManager.java +7 −2 Original line number Diff line number Diff line Loading @@ -1340,9 +1340,14 @@ public class AppOpsManager { /** @hide */ public void setUserRestriction(int code, boolean restricted, IBinder token, String[] exceptionPackages) { setUserRestrictionForUser(code, restricted, token, exceptionPackages, mContext.getUserId()); } /** @hide */ public void setUserRestrictionForUser(int code, boolean restricted, IBinder token, String[] exceptionPackages, int userId) { try { mService.setUserRestriction(code, restricted, token, mContext.getUserId(), exceptionPackages); mService.setUserRestriction(code, restricted, token, userId, exceptionPackages); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading services/core/java/com/android/server/vr/VrManagerService.java +106 −46 Original line number Diff line number Diff line Loading @@ -46,11 +46,12 @@ import android.service.vr.IVrListener; import android.service.vr.IVrManager; import android.service.vr.IVrStateCallbacks; import android.service.vr.VrListenerService; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Slog; import android.util.SparseArray; import com.android.internal.R; import com.android.server.LocalServices; import com.android.server.SystemConfig; import com.android.server.SystemService; import com.android.server.utils.ManagedApplicationService.PendingEvent; Loading @@ -67,6 +68,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Objects; /** Loading Loading @@ -197,29 +199,44 @@ public class VrManagerService extends SystemService implements EnabledComponentC private final class NotificationAccessManager { private final SparseArray<ArraySet<String>> mAllowedPackages = new SparseArray<>(); private final ArrayMap<String, Integer> mNotificationAccessPackageToUserId = new ArrayMap<>(); public void update(Collection<String> packageNames) { int currentUserId = ActivityManager.getCurrentUser(); UserHandle currentUserHandle = new UserHandle(currentUserId); ArraySet<String> allowed = mAllowedPackages.get(currentUserId); if (allowed == null) { 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) { if (!packageNames.contains(pkg)) { revokeNotificationListenerAccess(pkg); revokeNotificationListenerAccess(pkg, currentUserId); revokeNotificationPolicyAccess(pkg); revokeCoarseLocationAccess(pkg, currentUserHandle); revokeCoarseLocationPermissionIfNeeded(pkg, currentUserId); mNotificationAccessPackageToUserId.remove(pkg); } } for (String pkg : packageNames) { if (!allowed.contains(pkg)) { grantNotificationPolicyAccess(pkg); grantNotificationListenerAccess(pkg, currentUserHandle); grantCoarseLocationAccess(pkg, currentUserHandle); grantNotificationListenerAccess(pkg, currentUserId); grantCoarseLocationPermissionIfNeeded(pkg, currentUserId); mNotificationAccessPackageToUserId.put(pkg, currentUserId); } } Loading @@ -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 * currently bound VrListenerService is changed. Loading Loading @@ -535,17 +551,33 @@ public class VrManagerService extends SystemService implements EnabledComponentC } } private void updateOverlayStateLocked(ComponentName exemptedComponent) { final long identity = Binder.clearCallingIdentity(); try { private void updateOverlayStateLocked(String exemptedPackage, int newUserId, int oldUserId) { AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class); if (appOpsManager != null) { String[] exemptions = (exemptedComponent == null) ? new String[0] : new String[] { exemptedComponent.getPackageName() }; appOpsManager.setUserRestriction(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, mVrModeEnabled, mOverlayToken, exemptions); // 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(); try { // Set overlay exception state based on VR enabled and current service updateOverlayStateLocked(newVrServicePackage, newUserId, oldUserId); } finally { Binder.restoreCallingIdentity(identity); } Loading Loading @@ -578,8 +610,12 @@ public class VrManagerService extends SystemService implements EnabledComponentC return validUserComponent; // Disabled -> Disabled transition does nothing. } String oldVrServicePackage = mCurrentVrService != null ? mCurrentVrService.getComponent().getPackageName() : null; final int oldUserId = mCurrentVrModeUser; // Always send mode change events. changeVrModeLocked(enabled, (enabled && validUserComponent) ? component : null); changeVrModeLocked(enabled); if (!enabled || !validUserComponent) { // Unbind whatever is running Loading Loading @@ -608,10 +644,23 @@ public class VrManagerService extends SystemService implements EnabledComponentC if (calling != null && !Objects.equals(calling, mCurrentVrModeComponent)) { mCurrentVrModeComponent = calling; sendUpdatedCaller = true; } if (mCurrentVrModeUser != userId) { mCurrentVrModeUser = userId; 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) { final ComponentName c = mCurrentVrModeComponent; mCurrentVrService.sendEvent(new PendingEvent() { Loading Loading @@ -645,18 +694,6 @@ public class VrManagerService extends SystemService implements EnabledComponentC 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) { NotificationManager nm = mContext.getSystemService(NotificationManager.class); nm.setNotificationPolicyAccessGranted(pkg, true); Loading @@ -670,14 +707,14 @@ public class VrManagerService extends SystemService implements EnabledComponentC nm.setNotificationPolicyAccessGranted(pkg, false); } private void grantNotificationListenerAccess(String pkg, UserHandle userId) { private void grantNotificationListenerAccess(String pkg, int userId) { PackageManager pm = mContext.getPackageManager(); ArraySet<ComponentName> possibleServices = EnabledComponentsObserver.loadComponentNames(pm, userId.getIdentifier(), NotificationListenerService.SERVICE_INTERFACE, userId, NotificationListenerService.SERVICE_INTERFACE, android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE); ContentResolver resolver = mContext.getContentResolver(); ArraySet<String> current = getCurrentNotifListeners(resolver); ArraySet<String> current = getNotificationListeners(resolver, userId); for (ComponentName c : possibleServices) { String flatName = c.flattenToString(); Loading @@ -689,14 +726,16 @@ public class VrManagerService extends SystemService implements EnabledComponentC if (current.size() > 0) { String flatSettings = formatSettings(current); Settings.Secure.putString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, flatSettings); Settings.Secure.putStringForUser(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, flatSettings, userId); } } private void revokeNotificationListenerAccess(String pkg) { private void revokeNotificationListenerAccess(String pkg, int userId) { ContentResolver resolver = mContext.getContentResolver(); ArraySet<String> current = getCurrentNotifListeners(resolver); ArraySet<String> current = getNotificationListeners(resolver, userId); ArrayList<String> toRemove = new ArrayList<>(); Loading @@ -710,14 +749,37 @@ public class VrManagerService extends SystemService implements EnabledComponentC current.removeAll(toRemove); String flatSettings = formatSettings(current); Settings.Secure.putString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, flatSettings); Settings.Secure.putStringForUser(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, flatSettings, userId); } private void grantCoarseLocationPermissionIfNeeded(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().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> getCurrentNotifListeners(ContentResolver resolver) { String flat = Settings.Secure.getString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS); 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<>(); if (flat != null) { Loading Loading @@ -763,9 +825,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC * Note: Must be called while holding {@code mLock}. * * @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) { mVrModeEnabled = enabled; Loading @@ -773,7 +834,6 @@ public class VrManagerService extends SystemService implements EnabledComponentC Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled")); setVrModeNative(mVrModeEnabled); updateOverlayStateLocked(exemptedComponent); onVrModeChangedLocked(); } } Loading Loading
core/java/android/app/AppOpsManager.java +7 −2 Original line number Diff line number Diff line Loading @@ -1340,9 +1340,14 @@ public class AppOpsManager { /** @hide */ public void setUserRestriction(int code, boolean restricted, IBinder token, String[] exceptionPackages) { setUserRestrictionForUser(code, restricted, token, exceptionPackages, mContext.getUserId()); } /** @hide */ public void setUserRestrictionForUser(int code, boolean restricted, IBinder token, String[] exceptionPackages, int userId) { try { mService.setUserRestriction(code, restricted, token, mContext.getUserId(), exceptionPackages); mService.setUserRestriction(code, restricted, token, userId, exceptionPackages); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading
services/core/java/com/android/server/vr/VrManagerService.java +106 −46 Original line number Diff line number Diff line Loading @@ -46,11 +46,12 @@ import android.service.vr.IVrListener; import android.service.vr.IVrManager; import android.service.vr.IVrStateCallbacks; import android.service.vr.VrListenerService; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Slog; import android.util.SparseArray; import com.android.internal.R; import com.android.server.LocalServices; import com.android.server.SystemConfig; import com.android.server.SystemService; import com.android.server.utils.ManagedApplicationService.PendingEvent; Loading @@ -67,6 +68,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Objects; /** Loading Loading @@ -197,29 +199,44 @@ public class VrManagerService extends SystemService implements EnabledComponentC private final class NotificationAccessManager { private final SparseArray<ArraySet<String>> mAllowedPackages = new SparseArray<>(); private final ArrayMap<String, Integer> mNotificationAccessPackageToUserId = new ArrayMap<>(); public void update(Collection<String> packageNames) { int currentUserId = ActivityManager.getCurrentUser(); UserHandle currentUserHandle = new UserHandle(currentUserId); ArraySet<String> allowed = mAllowedPackages.get(currentUserId); if (allowed == null) { 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) { if (!packageNames.contains(pkg)) { revokeNotificationListenerAccess(pkg); revokeNotificationListenerAccess(pkg, currentUserId); revokeNotificationPolicyAccess(pkg); revokeCoarseLocationAccess(pkg, currentUserHandle); revokeCoarseLocationPermissionIfNeeded(pkg, currentUserId); mNotificationAccessPackageToUserId.remove(pkg); } } for (String pkg : packageNames) { if (!allowed.contains(pkg)) { grantNotificationPolicyAccess(pkg); grantNotificationListenerAccess(pkg, currentUserHandle); grantCoarseLocationAccess(pkg, currentUserHandle); grantNotificationListenerAccess(pkg, currentUserId); grantCoarseLocationPermissionIfNeeded(pkg, currentUserId); mNotificationAccessPackageToUserId.put(pkg, currentUserId); } } Loading @@ -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 * currently bound VrListenerService is changed. Loading Loading @@ -535,17 +551,33 @@ public class VrManagerService extends SystemService implements EnabledComponentC } } private void updateOverlayStateLocked(ComponentName exemptedComponent) { final long identity = Binder.clearCallingIdentity(); try { private void updateOverlayStateLocked(String exemptedPackage, int newUserId, int oldUserId) { AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class); if (appOpsManager != null) { String[] exemptions = (exemptedComponent == null) ? new String[0] : new String[] { exemptedComponent.getPackageName() }; appOpsManager.setUserRestriction(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, mVrModeEnabled, mOverlayToken, exemptions); // 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(); try { // Set overlay exception state based on VR enabled and current service updateOverlayStateLocked(newVrServicePackage, newUserId, oldUserId); } finally { Binder.restoreCallingIdentity(identity); } Loading Loading @@ -578,8 +610,12 @@ public class VrManagerService extends SystemService implements EnabledComponentC return validUserComponent; // Disabled -> Disabled transition does nothing. } String oldVrServicePackage = mCurrentVrService != null ? mCurrentVrService.getComponent().getPackageName() : null; final int oldUserId = mCurrentVrModeUser; // Always send mode change events. changeVrModeLocked(enabled, (enabled && validUserComponent) ? component : null); changeVrModeLocked(enabled); if (!enabled || !validUserComponent) { // Unbind whatever is running Loading Loading @@ -608,10 +644,23 @@ public class VrManagerService extends SystemService implements EnabledComponentC if (calling != null && !Objects.equals(calling, mCurrentVrModeComponent)) { mCurrentVrModeComponent = calling; sendUpdatedCaller = true; } if (mCurrentVrModeUser != userId) { mCurrentVrModeUser = userId; 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) { final ComponentName c = mCurrentVrModeComponent; mCurrentVrService.sendEvent(new PendingEvent() { Loading Loading @@ -645,18 +694,6 @@ public class VrManagerService extends SystemService implements EnabledComponentC 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) { NotificationManager nm = mContext.getSystemService(NotificationManager.class); nm.setNotificationPolicyAccessGranted(pkg, true); Loading @@ -670,14 +707,14 @@ public class VrManagerService extends SystemService implements EnabledComponentC nm.setNotificationPolicyAccessGranted(pkg, false); } private void grantNotificationListenerAccess(String pkg, UserHandle userId) { private void grantNotificationListenerAccess(String pkg, int userId) { PackageManager pm = mContext.getPackageManager(); ArraySet<ComponentName> possibleServices = EnabledComponentsObserver.loadComponentNames(pm, userId.getIdentifier(), NotificationListenerService.SERVICE_INTERFACE, userId, NotificationListenerService.SERVICE_INTERFACE, android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE); ContentResolver resolver = mContext.getContentResolver(); ArraySet<String> current = getCurrentNotifListeners(resolver); ArraySet<String> current = getNotificationListeners(resolver, userId); for (ComponentName c : possibleServices) { String flatName = c.flattenToString(); Loading @@ -689,14 +726,16 @@ public class VrManagerService extends SystemService implements EnabledComponentC if (current.size() > 0) { String flatSettings = formatSettings(current); Settings.Secure.putString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, flatSettings); Settings.Secure.putStringForUser(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, flatSettings, userId); } } private void revokeNotificationListenerAccess(String pkg) { private void revokeNotificationListenerAccess(String pkg, int userId) { ContentResolver resolver = mContext.getContentResolver(); ArraySet<String> current = getCurrentNotifListeners(resolver); ArraySet<String> current = getNotificationListeners(resolver, userId); ArrayList<String> toRemove = new ArrayList<>(); Loading @@ -710,14 +749,37 @@ public class VrManagerService extends SystemService implements EnabledComponentC current.removeAll(toRemove); String flatSettings = formatSettings(current); Settings.Secure.putString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, flatSettings); Settings.Secure.putStringForUser(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, flatSettings, userId); } private void grantCoarseLocationPermissionIfNeeded(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().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> getCurrentNotifListeners(ContentResolver resolver) { String flat = Settings.Secure.getString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS); 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<>(); if (flat != null) { Loading Loading @@ -763,9 +825,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC * Note: Must be called while holding {@code mLock}. * * @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) { mVrModeEnabled = enabled; Loading @@ -773,7 +834,6 @@ public class VrManagerService extends SystemService implements EnabledComponentC Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled")); setVrModeNative(mVrModeEnabled); updateOverlayStateLocked(exemptedComponent); onVrModeChangedLocked(); } } Loading