diff options
| author | 2018-03-01 01:11:25 +0000 | |
|---|---|---|
| committer | 2018-03-01 01:11:25 +0000 | |
| commit | 06b1df657a9fcc93a2541fca4495559dc950798e (patch) | |
| tree | 7bd3a30056f3a3c758c9fbe233c6da6010fc4fc6 | |
| parent | 364eb306471fcdd4130b5899ddeb7978d8050b8c (diff) | |
| parent | f7b4725375dfb5f6b65433f1679c44501c2478e3 (diff) | |
Merge "Use start/finish app ops in window manager"
11 files changed, 201 insertions, 137 deletions
diff --git a/api/test-current.txt b/api/test-current.txt index 21d12c357164..a2fead2b6a9d 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -48,7 +48,10 @@ package android.app { public class AppOpsManager { method public static java.lang.String[] getOpStrs(); + method public boolean isOperationActive(int, int, java.lang.String); method public void setMode(int, int, java.lang.String, int); + method public void startWatchingActive(int[], android.app.AppOpsManager.OnOpActiveChangedListener); + method public void stopWatchingActive(android.app.AppOpsManager.OnOpActiveChangedListener); field public static final java.lang.String OPSTR_ACCEPT_HANDOVER = "android:accept_handover"; field public static final java.lang.String OPSTR_ACCESS_NOTIFICATIONS = "android:access_notifications"; field public static final java.lang.String OPSTR_ACTIVATE_VPN = "android:activate_vpn"; @@ -90,6 +93,11 @@ package android.app { field public static final java.lang.String OPSTR_WRITE_ICC_SMS = "android:write_icc_sms"; field public static final java.lang.String OPSTR_WRITE_SMS = "android:write_sms"; field public static final java.lang.String OPSTR_WRITE_WALLPAPER = "android:write_wallpaper"; + field public static final int OP_SYSTEM_ALERT_WINDOW = 24; // 0x18 + } + + public static abstract interface AppOpsManager.OnOpActiveChangedListener { + method public abstract void onOpActiveChanged(int, int, java.lang.String, boolean); } public final class NotificationChannelGroup implements android.os.Parcelable { diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index d76a4f9ff10e..0e126a3a02d4 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -31,7 +31,6 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.Process; import android.os.RemoteException; -import android.os.UserHandle; import android.os.UserManager; import android.util.ArrayMap; @@ -168,6 +167,7 @@ public class AppOpsManager { /** @hide */ public static final int OP_WRITE_SETTINGS = 23; /** @hide Required to draw on top of other apps. */ + @TestApi public static final int OP_SYSTEM_ALERT_WINDOW = 24; /** @hide */ public static final int OP_ACCESS_NOTIFICATIONS = 25; @@ -1540,6 +1540,7 @@ public class AppOpsManager { * * @hide */ + @TestApi public interface OnOpActiveChangedListener { /** * Called when the active state of an app op changes. @@ -1731,7 +1732,7 @@ public class AppOpsManager { * Monitor for changes to the operating mode for the given op in the given app package. * * <p> If you don't hold the {@link android.Manifest.permission#WATCH_APPOPS} permission - * to watch changes only for your UID. + * you can watch changes only for your UID. * * @param op The operation to monitor, one of OP_*. * @param packageName The name of the application to monitor. @@ -1787,6 +1788,9 @@ public class AppOpsManager { * watched ops for a registered callback you need to unregister and register it * again. * + * <p> If you don't hold the {@link android.Manifest.permission#WATCH_APPOPS} permission + * you can watch changes only for your UID. + * * @param ops The ops to watch. * @param callback Where to report changes. * @@ -1797,7 +1801,9 @@ public class AppOpsManager { * * @hide */ - @RequiresPermission(Manifest.permission.WATCH_APPOPS) + @TestApi + // TODO: Uncomment below annotation once b/73559440 is fixed + // @RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true) public void startWatchingActive(@NonNull int[] ops, @NonNull OnOpActiveChangedListener callback) { Preconditions.checkNotNull(ops, "ops cannot be null"); @@ -1835,6 +1841,7 @@ public class AppOpsManager { * * @hide */ + @TestApi public void stopWatchingActive(@NonNull OnOpActiveChangedListener callback) { synchronized (mActiveWatchers) { final IAppOpsActiveCallback cb = mActiveWatchers.get(callback); @@ -2086,15 +2093,11 @@ public class AppOpsManager { * @hide */ public int noteOp(int op, int uid, String packageName) { - try { - int mode = mService.noteOperation(op, uid, packageName); - if (mode == MODE_ERRORED) { - throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName)); - } - return mode; - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + final int mode = noteOpNoThrow(op, uid, packageName); + if (mode == MODE_ERRORED) { + throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName)); } + return mode; } /** @@ -2173,6 +2176,11 @@ public class AppOpsManager { } } + /** @hide */ + public int startOp(int op) { + return startOp(op, Process.myUid(), mContext.getOpPackageName()); + } + /** * Report that an application has started executing a long-running operation. Note that you * must pass in both the uid and name of the application to be checked; this function will @@ -2181,6 +2189,7 @@ public class AppOpsManager { * the current time and the operation will be marked as "running". In this case you must * later call {@link #finishOp(int, int, String)} to report when the application is no * longer performing the operation. + * * @param op The operation to start. One of the OP_* constants. * @param uid The user id of the application attempting to perform the operation. * @param packageName The name of the application attempting to perform the operation. @@ -2191,15 +2200,34 @@ public class AppOpsManager { * @hide */ public int startOp(int op, int uid, String packageName) { - try { - int mode = mService.startOperation(getToken(mService), op, uid, packageName); - if (mode == MODE_ERRORED) { - throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName)); - } - return mode; - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + return startOp(op, uid, packageName, false); + } + + /** + * Report that an application has started executing a long-running operation. Similar + * to {@link #startOp(String, int, String) except that if the mode is {@link #MODE_DEFAULT} + * the operation should succeed since the caller has performed its standard permission + * checks which passed and would perform the protected operation for this mode. + * + * @param op The operation to start. One of the OP_* constants. + * @param uid The user id of the application attempting to perform the operation. + * @param packageName The name of the application attempting to perform the operation. + * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or + * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without + * causing the app to crash). + * @param startIfModeDefault Whether to start if mode is {@link #MODE_DEFAULT}. + * + * @throws SecurityException If the app has been configured to crash on this op or + * the package is not in the passed in UID. + * + * @hide + */ + public int startOp(int op, int uid, String packageName, boolean startIfModeDefault) { + final int mode = startOpNoThrow(op, uid, packageName, startIfModeDefault); + if (mode == MODE_ERRORED) { + throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName)); } + return mode; } /** @@ -2208,18 +2236,32 @@ public class AppOpsManager { * @hide */ public int startOpNoThrow(int op, int uid, String packageName) { + return startOpNoThrow(op, uid, packageName, false); + } + + /** + * Like {@link #startOp(int, int, String, boolean)} but instead of throwing a + * {@link SecurityException} it returns {@link #MODE_ERRORED}. + * + * @param op The operation to start. One of the OP_* constants. + * @param uid The user id of the application attempting to perform the operation. + * @param packageName The name of the application attempting to perform the operation. + * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or + * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without + * causing the app to crash). + * @param startIfModeDefault Whether to start if mode is {@link #MODE_DEFAULT}. + * + * @hide + */ + public int startOpNoThrow(int op, int uid, String packageName, boolean startIfModeDefault) { try { - return mService.startOperation(getToken(mService), op, uid, packageName); + return mService.startOperation(getToken(mService), op, uid, packageName, + startIfModeDefault); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } - /** @hide */ - public int startOp(int op) { - return startOp(op, Process.myUid(), mContext.getOpPackageName()); - } - /** * Report that an application is no longer performing an operation that had previously * been started with {@link #startOp(int, int, String)}. There is no validation of input @@ -2240,8 +2282,21 @@ public class AppOpsManager { finishOp(op, Process.myUid(), mContext.getOpPackageName()); } - /** @hide */ - @RequiresPermission(Manifest.permission.WATCH_APPOPS) + /** + * Checks whether the given op for a UID and package is active. + * + * <p> If you don't hold the {@link android.Manifest.permission#WATCH_APPOPS} permission + * you can query only for your UID. + * + * @see #startWatchingActive(int[], OnOpActiveChangedListener) + * @see #stopWatchingMode(OnOpChangedListener) + * @see #finishOp(int) + * @see #startOp(int) + * + * @hide */ + @TestApi + // TODO: Uncomment below annotation once b/73559440 is fixed + // @RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true) public boolean isOperationActive(int code, int uid, String packageName) { try { return mService.isOperationActive(code, uid, packageName); diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl index fabda4a5c15e..2505ea5d448b 100644 --- a/core/java/com/android/internal/app/IAppOpsService.aidl +++ b/core/java/com/android/internal/app/IAppOpsService.aidl @@ -26,7 +26,8 @@ interface IAppOpsService { // be kept in sync with frameworks/native/libs/binder/include/binder/IAppOpsService.h int checkOperation(int code, int uid, String packageName); int noteOperation(int code, int uid, String packageName); - int startOperation(IBinder token, int code, int uid, String packageName); + int startOperation(IBinder token, int code, int uid, String packageName, + boolean startIfModeDefault); void finishOperation(IBinder token, int code, int uid, String packageName); void startWatchingMode(int op, String packageName, IAppOpsCallback callback); void stopWatchingMode(IAppOpsCallback callback); diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java index ca67a34101d5..692b12f660d1 100644 --- a/services/core/java/com/android/server/AppOpsService.java +++ b/services/core/java/com/android/server/AppOpsService.java @@ -211,9 +211,11 @@ public class AppOpsService extends IAppOpsService.Stub { public final class ActiveCallback implements DeathRecipient { final IAppOpsActiveCallback mCallback; + final int mUid; - public ActiveCallback(IAppOpsActiveCallback callback) { + public ActiveCallback(IAppOpsActiveCallback callback, int uid) { mCallback = callback; + mUid = uid; try { mCallback.asBinder().linkToDeath(this, 0); } catch (RemoteException e) { @@ -233,21 +235,19 @@ public class AppOpsService extends IAppOpsService.Stub { final ArrayMap<IBinder, ClientState> mClients = new ArrayMap<IBinder, ClientState>(); public final class ClientState extends Binder implements DeathRecipient { + final ArrayList<Op> mStartedOps = new ArrayList<>(); final IBinder mAppToken; final int mPid; - final ArrayList<Op> mStartedOps; public ClientState(IBinder appToken) { mAppToken = appToken; mPid = Binder.getCallingPid(); - if (appToken instanceof Binder) { - // For local clients, there is no reason to track them. - mStartedOps = null; - } else { - mStartedOps = new ArrayList<Op>(); + // Watch only for remote processes dying + if (!(appToken instanceof Binder)) { try { mAppToken.linkToDeath(this, 0); } catch (RemoteException e) { + /* do nothing */ } } } @@ -256,7 +256,7 @@ public class AppOpsService extends IAppOpsService.Stub { public String toString() { return "ClientState{" + "mAppToken=" + mAppToken + - ", " + (mStartedOps != null ? ("pid=" + mPid) : "local") + + ", " + "pid=" + mPid + '}'; } @@ -1195,8 +1195,11 @@ public class AppOpsService extends IAppOpsService.Stub { @Override public void startWatchingActive(int[] ops, IAppOpsActiveCallback callback) { - mContext.enforceCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS, - "startWatchingActive"); + int watchedUid = -1; + if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS) + != PackageManager.PERMISSION_GRANTED) { + watchedUid = Binder.getCallingUid(); + } if (ops != null) { Preconditions.checkArrayElementsInRange(ops, 0, AppOpsManager._NUM_OP - 1, "Invalid op code in: " + Arrays.toString(ops)); @@ -1210,7 +1213,7 @@ public class AppOpsService extends IAppOpsService.Stub { callbacks = new SparseArray<>(); mActiveWatchers.put(callback.asBinder(), callbacks); } - final ActiveCallback activeCallback = new ActiveCallback(callback); + final ActiveCallback activeCallback = new ActiveCallback(callback, watchedUid); for (int op : ops) { callbacks.put(op, activeCallback); } @@ -1239,7 +1242,8 @@ public class AppOpsService extends IAppOpsService.Stub { } @Override - public int startOperation(IBinder token, int code, int uid, String packageName) { + public int startOperation(IBinder token, int code, int uid, String packageName, + boolean startIfModeDefault) { verifyIncomingUid(uid); verifyIncomingOp(code); String resolvedPackageName = resolvePackageName(uid, packageName); @@ -1265,7 +1269,8 @@ public class AppOpsService extends IAppOpsService.Stub { // non-default) it takes over, otherwise use the per package policy. if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) { final int uidMode = uidState.opModes.get(switchCode); - if (uidMode != AppOpsManager.MODE_ALLOWED) { + if (uidMode != AppOpsManager.MODE_ALLOWED + && (!startIfModeDefault || uidMode != AppOpsManager.MODE_DEFAULT)) { if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + op.mode + " for code " + switchCode + " (" + code + ") uid " + uid + " package " + resolvedPackageName); @@ -1274,7 +1279,8 @@ public class AppOpsService extends IAppOpsService.Stub { } } else { final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op; - if (switchOp.mode != AppOpsManager.MODE_ALLOWED) { + if (switchOp.mode != AppOpsManager.MODE_ALLOWED + && (!startIfModeDefault || switchOp.mode != AppOpsManager.MODE_DEFAULT)) { if (DEBUG) Slog.d(TAG, "startOperation: reject #" + op.mode + " for code " + switchCode + " (" + code + ") uid " + uid + " package " + resolvedPackageName); @@ -1316,11 +1322,9 @@ public class AppOpsService extends IAppOpsService.Stub { if (op == null) { return; } - if (client.mStartedOps != null) { - if (!client.mStartedOps.remove(op)) { - throw new IllegalStateException("Operation not started: uid" + op.uid - + " pkg=" + op.packageName + " op=" + op.op); - } + if (!client.mStartedOps.remove(op)) { + throw new IllegalStateException("Operation not started: uid" + op.uid + + " pkg=" + op.packageName + " op=" + op.op); } finishOperationLocked(op); if (op.nesting <= 0) { @@ -1337,6 +1341,9 @@ public class AppOpsService extends IAppOpsService.Stub { final SparseArray<ActiveCallback> callbacks = mActiveWatchers.valueAt(i); ActiveCallback callback = callbacks.get(code); if (callback != null) { + if (callback.mUid >= 0 && callback.mUid != uid) { + continue; + } if (dispatchedCallbacks == null) { dispatchedCallbacks = new ArraySet<>(); } @@ -2420,7 +2427,7 @@ public class AppOpsService extends IAppOpsService.Stub { pw.print(" "); pw.print(mClients.keyAt(i)); pw.println(":"); ClientState cs = mClients.valueAt(i); pw.print(" "); pw.println(cs); - if (cs.mStartedOps != null && cs.mStartedOps.size() > 0) { + if (cs.mStartedOps.size() > 0) { pw.println(" Started ops:"); for (int j=0; j<cs.mStartedOps.size(); j++) { Op op = cs.mStartedOps.get(j); @@ -2651,8 +2658,12 @@ public class AppOpsService extends IAppOpsService.Stub { @Override public boolean isOperationActive(int code, int uid, String packageName) { - mContext.enforceCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS, - "isOperationActive"); + if (Binder.getCallingUid() != uid) { + if (mContext.checkCallingOrSelfPermission(Manifest.permission.WATCH_APPOPS) + != PackageManager.PERMISSION_GRANTED) { + return false; + } + } verifyIncomingOp(code); final String resolvedPackageName = resolvePackageName(uid, packageName); if (resolvedPackageName == null) { @@ -2661,8 +2672,6 @@ public class AppOpsService extends IAppOpsService.Stub { synchronized (AppOpsService.this) { for (int i = mClients.size() - 1; i >= 0; i--) { final ClientState client = mClients.valueAt(i); - if (client.mStartedOps == null) continue; - for (int j = client.mStartedOps.size() - 1; j >= 0; j--) { final Op op = client.mStartedOps.get(j); if (op.op == code && op.uid == uid) return true; diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java index 14c99b229962..752c44a6f59b 100644 --- a/services/core/java/com/android/server/VibratorService.java +++ b/services/core/java/com/android/server/VibratorService.java @@ -98,7 +98,7 @@ public class VibratorService extends IVibratorService.Stub private final Context mContext; private final PowerManager.WakeLock mWakeLock; - private final IAppOpsService mAppOpsService; + private final AppOpsManager mAppOps; private final IBatteryStats mBatteryStatsService; private PowerManagerInternal mPowerManagerInternal; private InputManager mIm; @@ -265,8 +265,7 @@ public class VibratorService extends IVibratorService.Stub mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*"); mWakeLock.setReferenceCounted(true); - mAppOpsService = - IAppOpsService.Stub.asInterface(ServiceManager.getService(Context.APP_OPS_SERVICE)); + mAppOps = mContext.getSystemService(AppOpsManager.class); mBatteryStatsService = IBatteryStats.Stub.asInterface(ServiceManager.getService( BatteryStats.SERVICE_NAME)); @@ -721,17 +720,10 @@ public class VibratorService extends IVibratorService.Stub } private int getAppOpMode(Vibration vib) { - int mode; - try { - mode = mAppOpsService.checkAudioOperation(AppOpsManager.OP_VIBRATE, - vib.usageHint, vib.uid, vib.opPkg); - if (mode == AppOpsManager.MODE_ALLOWED) { - mode = mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService), - AppOpsManager.OP_VIBRATE, vib.uid, vib.opPkg); - } - } catch (RemoteException e) { - Slog.e(TAG, "Failed to get appop mode for vibration!", e); - mode = AppOpsManager.MODE_IGNORED; + int mode = mAppOps.checkAudioOpNoThrow(AppOpsManager.OP_VIBRATE, + vib.usageHint, vib.uid, vib.opPkg); + if (mode == AppOpsManager.MODE_ALLOWED) { + mode = mAppOps.startOpNoThrow(AppOpsManager.OP_VIBRATE, vib.uid, vib.opPkg); } return mode; } @@ -741,11 +733,8 @@ public class VibratorService extends IVibratorService.Stub Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "reportFinishVibrationLocked"); try { if (mCurrentVibration != null) { - try { - mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService), - AppOpsManager.OP_VIBRATE, mCurrentVibration.uid, - mCurrentVibration.opPkg); - } catch (RemoteException e) { } + mAppOps.finishOp(AppOpsManager.OP_VIBRATE, mCurrentVibration.uid, + mCurrentVibration.opPkg); unlinkVibration(mCurrentVibration); mCurrentVibration = null; } diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java index 5267f54b9cd5..729ac0c68662 100644 --- a/services/core/java/com/android/server/location/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/GnssLocationProvider.java @@ -459,7 +459,7 @@ public class GnssLocationProvider implements LocationProviderInterface { private final PendingIntent mWakeupIntent; private final PendingIntent mTimeoutIntent; - private final IAppOpsService mAppOpsService; + private final AppOpsManager mAppOps; private final IBatteryStats mBatteryStats; // Current list of underlying location clients. @@ -782,8 +782,7 @@ public class GnssLocationProvider implements LocationProviderInterface { mConnMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); // App ops service to keep track of who is accessing the GPS - mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService( - Context.APP_OPS_SERVICE)); + mAppOps = mContext.getSystemService(AppOpsManager.class); // Battery statistics service to be notified when GPS turns on or off mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService( @@ -1490,26 +1489,16 @@ public class GnssLocationProvider implements LocationProviderInterface { if (newChains != null) { for (int i = 0; i < newChains.size(); ++i) { final WorkChain newChain = newChains.get(i); - try { - mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService), - AppOpsManager.OP_GPS, newChain.getAttributionUid(), - newChain.getAttributionTag()); - } catch (RemoteException e) { - Log.w(TAG, "RemoteException", e); - } + mAppOps.startOpNoThrow(AppOpsManager.OP_GPS, newChain.getAttributionUid(), + newChain.getAttributionTag()); } } if (goneChains != null) { for (int i = 0; i < goneChains.size(); i++) { final WorkChain goneChain = goneChains.get(i); - try { - mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService), - AppOpsManager.OP_GPS, goneChain.getAttributionUid(), - goneChain.getAttributionTag()); - } catch (RemoteException e) { - Log.w(TAG, "RemoteException", e); - } + mAppOps.finishOp(AppOpsManager.OP_GPS, goneChain.getAttributionUid(), + goneChain.getAttributionTag()); } } @@ -1525,24 +1514,15 @@ public class GnssLocationProvider implements LocationProviderInterface { // Update sources that were not previously tracked. if (newWork != null) { for (int i = 0; i < newWork.size(); i++) { - try { - mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService), - AppOpsManager.OP_GPS, newWork.get(i), newWork.getName(i)); - } catch (RemoteException e) { - Log.w(TAG, "RemoteException", e); - } + mAppOps.startOpNoThrow(AppOpsManager.OP_GPS, + newWork.get(i), newWork.getName(i)); } } // Update sources that are no longer tracked. if (goneWork != null) { for (int i = 0; i < goneWork.size(); i++) { - try { - mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService), - AppOpsManager.OP_GPS, goneWork.get(i), goneWork.getName(i)); - } catch (RemoteException e) { - Log.w(TAG, "RemoteException", e); - } + mAppOps.finishOp(AppOpsManager.OP_GPS, goneWork.get(i), goneWork.getName(i)); } } } diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java index 3072f212d7c1..b729b6a0f47f 100644 --- a/services/core/java/com/android/server/power/Notifier.java +++ b/services/core/java/com/android/server/power/Notifier.java @@ -91,7 +91,7 @@ final class Notifier { private final Context mContext; private final IBatteryStats mBatteryStats; - private final IAppOpsService mAppOps; + private final AppOpsManager mAppOps; private final SuspendBlocker mSuspendBlocker; private final WindowManagerPolicy mPolicy; private final ActivityManagerInternal mActivityManagerInternal; @@ -134,11 +134,10 @@ final class Notifier { private boolean mUserActivityPending; public Notifier(Looper looper, Context context, IBatteryStats batteryStats, - IAppOpsService appOps, SuspendBlocker suspendBlocker, - WindowManagerPolicy policy) { + SuspendBlocker suspendBlocker, WindowManagerPolicy policy) { mContext = context; mBatteryStats = batteryStats; - mAppOps = appOps; + mAppOps = mContext.getSystemService(AppOpsManager.class); mSuspendBlocker = suspendBlocker; mPolicy = policy; mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); @@ -194,8 +193,7 @@ final class Notifier { mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, historyTag, monitorType, unimportantForLogging); // XXX need to deal with disabled operations. - mAppOps.startOperation(AppOpsManager.getToken(mAppOps), - AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName); + mAppOps.startOpNoThrow(AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName); } } catch (RemoteException ex) { // Ignore @@ -295,8 +293,7 @@ final class Notifier { } else { mBatteryStats.noteStopWakelock(ownerUid, ownerPid, tag, historyTag, monitorType); - mAppOps.finishOperation(AppOpsManager.getToken(mAppOps), - AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName); + mAppOps.finishOp(AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName); } } catch (RemoteException ex) { // Ignore @@ -539,12 +536,11 @@ final class Notifier { try { mBatteryStats.noteWakeUp(reason, reasonUid); if (opPackageName != null) { - mAppOps.noteOperation(AppOpsManager.OP_TURN_SCREEN_ON, opUid, opPackageName); + mAppOps.noteOpNoThrow(AppOpsManager.OP_TURN_SCREEN_ON, opUid, opPackageName); } } catch (RemoteException ex) { // Ignore } - } /** diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index d67acc481acf..f77b0ee59249 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -759,8 +759,7 @@ public final class PowerManagerService extends SystemService // with the animations and other critical functions of the power manager. mBatteryStats = BatteryStatsService.getService(); mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats, - mAppOps, createSuspendBlockerLocked("PowerManagerService.Broadcasts"), - mPolicy); + createSuspendBlockerLocked("PowerManagerService.Broadcasts"), mPolicy); mWirelessChargerDetector = new WirelessChargerDetector(sensorManager, createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"), diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 6356a3512e65..36d331da19e4 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -29,9 +29,7 @@ import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.PowerManager; import android.os.RemoteException; -import android.os.SystemClock; import android.os.UserHandle; -import android.provider.Settings; import android.util.ArraySet; import android.util.EventLog; import android.util.Slog; @@ -50,9 +48,6 @@ import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; -import static android.app.AppOpsManager.MODE_ALLOWED; -import static android.app.AppOpsManager.MODE_DEFAULT; -import static android.app.AppOpsManager.OP_NONE; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; @@ -68,8 +63,6 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; -import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER; -import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE; import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS; @@ -427,12 +420,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { void updateAppOpsState() { forAllWindows((w) -> { - if (w.mAppOp == OP_NONE) { - return; - } - final int mode = mService.mAppOps.noteOpNoThrow(w.mAppOp, w.getOwningUid(), - w.getOwningPackage()); - w.setAppOpVisibilityLw(mode == MODE_ALLOWED || mode == MODE_DEFAULT); + w.updateAppOpsState(); }, false /* traverseTopToBottom */); } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index bab4399d76ad..696eef1ac6ca 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -1384,14 +1384,8 @@ public class WindowManagerService extends IWindowManager.Stub win.attach(); mWindowMap.put(client.asBinder(), win); - if (win.mAppOp != AppOpsManager.OP_NONE) { - int startOpResult = mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(), - win.getOwningPackage()); - if ((startOpResult != AppOpsManager.MODE_ALLOWED) && - (startOpResult != AppOpsManager.MODE_DEFAULT)) { - win.setAppOpVisibilityLw(false); - } - } + + win.initAppOpsState(); final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty(); win.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows); @@ -1656,9 +1650,8 @@ public class WindowManagerService extends IWindowManager.Stub void postWindowRemoveCleanupLocked(WindowState win) { if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "postWindowRemoveCleanupLocked: " + win); mWindowMap.remove(win.mClient.asBinder()); - if (win.mAppOp != AppOpsManager.OP_NONE) { - mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage()); - } + + win.resetAppOpsState(); if (mCurrentFocus == null) { mWinRemovedSinceNullFocus.add(win); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index b706096f3d0b..62664738a2c0 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -17,6 +17,9 @@ package com.android.server.wm; import static android.app.ActivityManager.StackId.INVALID_STACK_ID; +import static android.app.AppOpsManager.MODE_ALLOWED; +import static android.app.AppOpsManager.MODE_DEFAULT; +import static android.app.AppOpsManager.OP_NONE; import static android.os.PowerManager.DRAW_WAKE_LOCK; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.view.Display.DEFAULT_DISPLAY; @@ -2571,7 +2574,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } - public void setAppOpVisibilityLw(boolean state) { + private void setAppOpVisibilityLw(boolean state) { if (mAppOpVisibility != state) { mAppOpVisibility = state; if (state) { @@ -2588,6 +2591,49 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } + void initAppOpsState() { + if (mAppOp == OP_NONE || !mAppOpVisibility) { + return; + } + // If the app op was MODE_DEFAULT we would have checked the permission + // and add the window only if the permission was granted. Therefore, if + // the mode is MODE_DEFAULT we want the op to succeed as the window is + // shown. + final int mode = mService.mAppOps.startOpNoThrow(mAppOp, + getOwningUid(), getOwningPackage(), true); + if (mode != MODE_ALLOWED && mode != MODE_DEFAULT) { + setAppOpVisibilityLw(false); + } + } + + void resetAppOpsState() { + if (mAppOp != OP_NONE && mAppOpVisibility) { + mService.mAppOps.finishOp(mAppOp, getOwningUid(), getOwningPackage()); + } + } + + void updateAppOpsState() { + if (mAppOp == OP_NONE) { + return; + } + final int uid = getOwningUid(); + final String packageName = getOwningPackage(); + if (mAppOpVisibility) { + // There is a race between the check and the finish calls but this is fine + // as this would mean we will get another change callback and will reconcile. + int mode = mService.mAppOps.checkOpNoThrow(mAppOp, uid, packageName); + if (mode != MODE_ALLOWED && mode != MODE_DEFAULT) { + mService.mAppOps.finishOp(mAppOp, uid, packageName); + setAppOpVisibilityLw(false); + } + } else { + final int mode = mService.mAppOps.startOpNoThrow(mAppOp, uid, packageName); + if (mode == MODE_ALLOWED || mode == MODE_DEFAULT) { + setAppOpVisibilityLw(true); + } + } + } + public void hidePermanentlyLw() { if (!mPermanentlyHidden) { mPermanentlyHidden = true; |