Merge "Set notification listener defaults for system VrListeners." into nyc-dev
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
package com.android.server.vr;
|
package com.android.server.vr;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
|
import android.app.ActivityManager;
|
||||||
import android.app.AppOpsManager;
|
import android.app.AppOpsManager;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
@@ -47,6 +48,7 @@ import android.service.vr.IVrStateCallbacks;
|
|||||||
import android.service.vr.VrListenerService;
|
import android.service.vr.VrListenerService;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
|
||||||
import com.android.internal.R;
|
import com.android.internal.R;
|
||||||
import com.android.server.SystemConfig;
|
import com.android.server.SystemConfig;
|
||||||
@@ -95,6 +97,7 @@ public class VrManagerService extends SystemService implements EnabledComponentC
|
|||||||
|
|
||||||
private static final int PENDING_STATE_DELAY_MS = 300;
|
private static final int PENDING_STATE_DELAY_MS = 300;
|
||||||
private static final int EVENT_LOG_SIZE = 32;
|
private static final int EVENT_LOG_SIZE = 32;
|
||||||
|
private static final int INVALID_APPOPS_MODE = -1;
|
||||||
|
|
||||||
private static native void initializeNative();
|
private static native void initializeNative();
|
||||||
private static native void setVrModeNative(boolean enabled);
|
private static native void setVrModeNative(boolean enabled);
|
||||||
@@ -114,12 +117,11 @@ public class VrManagerService extends SystemService implements EnabledComponentC
|
|||||||
private boolean mGuard;
|
private boolean mGuard;
|
||||||
private final RemoteCallbackList<IVrStateCallbacks> mRemoteCallbacks =
|
private final RemoteCallbackList<IVrStateCallbacks> mRemoteCallbacks =
|
||||||
new RemoteCallbackList<>();
|
new RemoteCallbackList<>();
|
||||||
private final ArraySet<String> mPreviousToggledListenerSettings = new ArraySet<>();
|
private int mPreviousCoarseLocationMode = INVALID_APPOPS_MODE;
|
||||||
private String mPreviousNotificationPolicyAccessPackage;
|
private int mPreviousManageOverlayMode = INVALID_APPOPS_MODE;
|
||||||
private String mPreviousCoarseLocationPackage;
|
|
||||||
private String mPreviousManageOverlayPackage;
|
|
||||||
private VrState mPendingState;
|
private VrState mPendingState;
|
||||||
private final ArrayDeque<VrState> mLoggingDeque = new ArrayDeque<>(EVENT_LOG_SIZE);
|
private final ArrayDeque<VrState> mLoggingDeque = new ArrayDeque<>(EVENT_LOG_SIZE);
|
||||||
|
private final NotificationAccessManager mNotifAccessManager = new NotificationAccessManager();
|
||||||
|
|
||||||
private static final int MSG_VR_STATE_CHANGE = 0;
|
private static final int MSG_VR_STATE_CHANGE = 0;
|
||||||
private static final int MSG_PENDING_VR_STATE_CHANGE = 1;
|
private static final int MSG_PENDING_VR_STATE_CHANGE = 1;
|
||||||
@@ -193,6 +195,39 @@ public class VrManagerService extends SystemService implements EnabledComponentC
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private final class NotificationAccessManager {
|
||||||
|
private final SparseArray<ArraySet<String>> mAllowedPackages = new SparseArray<>();
|
||||||
|
|
||||||
|
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<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String pkg : allowed) {
|
||||||
|
if (!packageNames.contains(pkg)) {
|
||||||
|
revokeNotificationListenerAccess(pkg);
|
||||||
|
revokeNotificationPolicyAccess(pkg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (String pkg : packageNames) {
|
||||||
|
if (!allowed.contains(pkg)) {
|
||||||
|
grantNotificationPolicyAccess(pkg);
|
||||||
|
grantNotificationListenerAccess(pkg, currentUserHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allowed.clear();
|
||||||
|
allowed.addAll(packageNames);
|
||||||
|
mAllowedPackages.put(currentUserId, allowed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
@@ -200,6 +235,20 @@ public class VrManagerService extends SystemService implements EnabledComponentC
|
|||||||
@Override
|
@Override
|
||||||
public void onEnabledComponentChanged() {
|
public void onEnabledComponentChanged() {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
|
int currentUser = ActivityManager.getCurrentUser();
|
||||||
|
|
||||||
|
// Update listeners
|
||||||
|
ArraySet<ComponentName> enabledListeners = mComponentObserver.getEnabled(currentUser);
|
||||||
|
|
||||||
|
ArraySet<String> enabledPackages = new ArraySet<>();
|
||||||
|
for (ComponentName n : enabledListeners) {
|
||||||
|
String pkg = n.getPackageName();
|
||||||
|
if (isDefaultAllowed(pkg)) {
|
||||||
|
enabledPackages.add(n.getPackageName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mNotifAccessManager.update(enabledPackages);
|
||||||
|
|
||||||
if (mCurrentVrService == null) {
|
if (mCurrentVrService == null) {
|
||||||
return; // No active services
|
return; // No active services
|
||||||
}
|
}
|
||||||
@@ -616,21 +665,18 @@ public class VrManagerService extends SystemService implements EnabledComponentC
|
|||||||
} catch (NameNotFoundException e) {
|
} catch (NameNotFoundException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info == null) {
|
if (info == null || !(info.isSystemApp() || info.isUpdatedSystemApp())) {
|
||||||
Slog.e(TAG, "Couldn't set implied permissions for " + pName + ", no such package.");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(info.isSystemApp() || info.isUpdatedSystemApp())) {
|
|
||||||
return; // Application is not pre-installed, avoid setting implied permissions
|
|
||||||
}
|
|
||||||
|
|
||||||
mWasDefaultGranted = true;
|
mWasDefaultGranted = true;
|
||||||
|
AppOpsManager mgr = mContext.getSystemService(AppOpsManager.class);
|
||||||
grantCoarseLocationAccess(pName, userId);
|
if (mgr == null) {
|
||||||
grantOverlayAccess(pName, userId);
|
Slog.e(TAG, "No AppOpsManager, failed to set permissions for: " + pName);
|
||||||
grantNotificationPolicyAccess(pName);
|
return;
|
||||||
grantNotificationListenerAccess(pName, userId);
|
}
|
||||||
|
grantCoarseLocationAccess(mgr, pName, info.uid);
|
||||||
|
grantOverlayAccess(mgr, pName, info.uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -657,80 +703,89 @@ public class VrManagerService extends SystemService implements EnabledComponentC
|
|||||||
|
|
||||||
String pName = component.getPackageName();
|
String pName = component.getPackageName();
|
||||||
if (mWasDefaultGranted) {
|
if (mWasDefaultGranted) {
|
||||||
revokeCoarseLocationAccess(userId);
|
ApplicationInfo info = null;
|
||||||
revokeOverlayAccess(userId);
|
try {
|
||||||
revokeNotificationPolicyAccess(pName);
|
info = pm.getApplicationInfo(pName, PackageManager.GET_META_DATA);
|
||||||
revokeNotificiationListenerAccess();
|
} catch (NameNotFoundException e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info != null) {
|
||||||
|
AppOpsManager mgr = mContext.getSystemService(AppOpsManager.class);
|
||||||
|
if (mgr == null) {
|
||||||
|
Slog.e(TAG, "No AppOpsManager, failed to set permissions for: " + pName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
revokeCoarseLocationAccess(mgr, pName, info.uid);
|
||||||
|
revokeOverlayAccess(mgr, pName, info.uid);
|
||||||
|
}
|
||||||
mWasDefaultGranted = false;
|
mWasDefaultGranted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void grantCoarseLocationAccess(String pkg, UserHandle userId) {
|
private boolean isDefaultAllowed(String packageName) {
|
||||||
PackageManager pm = mContext.getPackageManager();
|
PackageManager pm = mContext.getPackageManager();
|
||||||
boolean prev = (PackageManager.PERMISSION_GRANTED ==
|
|
||||||
pm.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION, pkg));
|
ApplicationInfo info = null;
|
||||||
mPreviousCoarseLocationPackage = null;
|
try {
|
||||||
if (!prev) {
|
info = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
|
||||||
pm.grantRuntimePermission(pkg, android.Manifest.permission.ACCESS_COARSE_LOCATION,
|
} catch (NameNotFoundException e) {
|
||||||
userId);
|
}
|
||||||
mPreviousCoarseLocationPackage = pkg;
|
|
||||||
|
if (info == null || !(info.isSystemApp() || info.isUpdatedSystemApp())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void grantCoarseLocationAccess(AppOpsManager mgr, String packageName, int uid) {
|
||||||
|
mPreviousCoarseLocationMode = mgr.checkOpNoThrow(AppOpsManager.OP_COARSE_LOCATION, uid,
|
||||||
|
packageName);
|
||||||
|
|
||||||
|
if (mPreviousCoarseLocationMode != AppOpsManager.MODE_ALLOWED) {
|
||||||
|
mgr.setMode(AppOpsManager.OP_COARSE_LOCATION, uid, packageName,
|
||||||
|
AppOpsManager.MODE_ALLOWED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void revokeCoarseLocationAccess(UserHandle userId) {
|
private void revokeCoarseLocationAccess(AppOpsManager mgr, String packageName, int uid) {
|
||||||
PackageManager pm = mContext.getPackageManager();
|
if (mPreviousCoarseLocationMode != AppOpsManager.MODE_ALLOWED) {
|
||||||
if (mPreviousCoarseLocationPackage != null) {
|
mgr.setMode(AppOpsManager.OP_COARSE_LOCATION, uid, packageName,
|
||||||
pm.revokeRuntimePermission(mPreviousCoarseLocationPackage,
|
mPreviousCoarseLocationMode);
|
||||||
android.Manifest.permission.ACCESS_COARSE_LOCATION, userId);
|
mPreviousCoarseLocationMode = INVALID_APPOPS_MODE;
|
||||||
mPreviousCoarseLocationPackage = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void grantOverlayAccess(String pkg, UserHandle userId) {
|
private void grantOverlayAccess(AppOpsManager mgr, String packageName, int uid) {
|
||||||
PackageManager pm = mContext.getPackageManager();
|
|
||||||
boolean prev = (PackageManager.PERMISSION_GRANTED ==
|
mPreviousManageOverlayMode = mgr.checkOpNoThrow(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, uid,
|
||||||
pm.checkPermission(android.Manifest.permission.SYSTEM_ALERT_WINDOW, pkg));
|
packageName);
|
||||||
mPreviousManageOverlayPackage = null;
|
|
||||||
if (!prev) {
|
if (mPreviousManageOverlayMode != AppOpsManager.MODE_ALLOWED) {
|
||||||
pm.grantRuntimePermission(pkg, android.Manifest.permission.SYSTEM_ALERT_WINDOW,
|
mgr.setMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, uid, packageName,
|
||||||
userId);
|
AppOpsManager.MODE_ALLOWED);
|
||||||
mPreviousManageOverlayPackage = pkg;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void revokeOverlayAccess(UserHandle userId) {
|
private void revokeOverlayAccess(AppOpsManager mgr, String packageName, int uid) {
|
||||||
PackageManager pm = mContext.getPackageManager();
|
if (mPreviousManageOverlayMode != AppOpsManager.MODE_ALLOWED) {
|
||||||
if (mPreviousManageOverlayPackage != null) {
|
mgr.setMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, uid, packageName,
|
||||||
pm.revokeRuntimePermission(mPreviousManageOverlayPackage,
|
mPreviousManageOverlayMode);
|
||||||
android.Manifest.permission.SYSTEM_ALERT_WINDOW, userId);
|
mPreviousManageOverlayMode = INVALID_APPOPS_MODE;
|
||||||
mPreviousManageOverlayPackage = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void grantNotificationPolicyAccess(String pkg) {
|
private void grantNotificationPolicyAccess(String pkg) {
|
||||||
NotificationManager nm = mContext.getSystemService(NotificationManager.class);
|
NotificationManager nm = mContext.getSystemService(NotificationManager.class);
|
||||||
boolean prev = nm.isNotificationPolicyAccessGrantedForPackage(pkg);
|
nm.setNotificationPolicyAccessGranted(pkg, true);
|
||||||
mPreviousNotificationPolicyAccessPackage = null;
|
|
||||||
if (!prev) {
|
|
||||||
mPreviousNotificationPolicyAccessPackage = pkg;
|
|
||||||
nm.setNotificationPolicyAccessGranted(pkg, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void revokeNotificationPolicyAccess(String pkg) {
|
private void revokeNotificationPolicyAccess(String pkg) {
|
||||||
NotificationManager nm = mContext.getSystemService(NotificationManager.class);
|
NotificationManager nm = mContext.getSystemService(NotificationManager.class);
|
||||||
if (mPreviousNotificationPolicyAccessPackage != null) {
|
// Remove any DND zen rules possibly created by the package.
|
||||||
if (mPreviousNotificationPolicyAccessPackage.equals(pkg)) {
|
nm.removeAutomaticZenRules(pkg);
|
||||||
// Remove any DND zen rules possibly created by the package.
|
// Remove Notification Policy Access.
|
||||||
nm.removeAutomaticZenRules(mPreviousNotificationPolicyAccessPackage);
|
nm.setNotificationPolicyAccessGranted(pkg, false);
|
||||||
// Remove Notification Policy Access.
|
|
||||||
nm.setNotificationPolicyAccessGranted(mPreviousNotificationPolicyAccessPackage, false);
|
|
||||||
mPreviousNotificationPolicyAccessPackage = null;
|
|
||||||
} else {
|
|
||||||
Slog.e(TAG, "Couldn't remove Notification Policy Access for package: " + pkg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void grantNotificationListenerAccess(String pkg, UserHandle userId) {
|
private void grantNotificationListenerAccess(String pkg, UserHandle userId) {
|
||||||
@@ -742,13 +797,10 @@ public class VrManagerService extends SystemService implements EnabledComponentC
|
|||||||
|
|
||||||
ArraySet<String> current = getCurrentNotifListeners(resolver);
|
ArraySet<String> current = getCurrentNotifListeners(resolver);
|
||||||
|
|
||||||
mPreviousToggledListenerSettings.clear();
|
|
||||||
|
|
||||||
for (ComponentName c : possibleServices) {
|
for (ComponentName c : possibleServices) {
|
||||||
String flatName = c.flattenToString();
|
String flatName = c.flattenToString();
|
||||||
if (Objects.equals(c.getPackageName(), pkg)
|
if (Objects.equals(c.getPackageName(), pkg)
|
||||||
&& !current.contains(flatName)) {
|
&& !current.contains(flatName)) {
|
||||||
mPreviousToggledListenerSettings.add(flatName);
|
|
||||||
current.add(flatName);
|
current.add(flatName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -760,20 +812,25 @@ public class VrManagerService extends SystemService implements EnabledComponentC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void revokeNotificiationListenerAccess() {
|
private void revokeNotificationListenerAccess(String pkg) {
|
||||||
if (mPreviousToggledListenerSettings.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ContentResolver resolver = mContext.getContentResolver();
|
ContentResolver resolver = mContext.getContentResolver();
|
||||||
ArraySet<String> current = getCurrentNotifListeners(resolver);
|
ArraySet<String> current = getCurrentNotifListeners(resolver);
|
||||||
|
|
||||||
current.removeAll(mPreviousToggledListenerSettings);
|
ArrayList<String> toRemove = new ArrayList<>();
|
||||||
mPreviousToggledListenerSettings.clear();
|
|
||||||
|
for (String c : current) {
|
||||||
|
ComponentName component = ComponentName.unflattenFromString(c);
|
||||||
|
if (component.getPackageName().equals(pkg)) {
|
||||||
|
toRemove.add(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
current.removeAll(toRemove);
|
||||||
|
|
||||||
String flatSettings = formatSettings(current);
|
String flatSettings = formatSettings(current);
|
||||||
Settings.Secure.putString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
|
Settings.Secure.putString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
|
||||||
flatSettings);
|
flatSettings);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArraySet<String> getCurrentNotifListeners(ContentResolver resolver) {
|
private ArraySet<String> getCurrentNotifListeners(ContentResolver resolver) {
|
||||||
|
|||||||
Reference in New Issue
Block a user