diff options
author | Adnan Begovic <adnan@cyngn.com> | 2016-05-24 18:17:03 -0700 |
---|---|---|
committer | Adnan Begovic <adnan@cyngn.com> | 2016-05-27 10:22:22 -0700 |
commit | 1c1efe46d095646111db415983005a96b8bee244 (patch) | |
tree | 2bfe0ec2afbb3da44701f32c36cd3fb481498d8a | |
parent | b4088dd11909e3b19519520a8838251902446f9a (diff) | |
download | frameworks_base-1c1efe46d095646111db415983005a96b8bee244.zip frameworks_base-1c1efe46d095646111db415983005a96b8bee244.tar.gz frameworks_base-1c1efe46d095646111db415983005a96b8bee244.tar.bz2 |
appops: Respect screen interactivity before creating dialogs.
If the device's screen is currently off, do not queue ask
runnables who cannot be interacted with. Since these events
are gating mechanisms for closing an IPC loop, they need to
happen when the user is interacting with the device.
Likewise, on screen off, clear the queue of every op as they
become unnecessary.
Change-Id: Ie930d200839c9408e882510c6bc3ede37ea889ef
TICKET: CYNGNOS-2869
3 files changed, 60 insertions, 4 deletions
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java index b99e4db..3b12ed6 100644 --- a/services/core/java/com/android/server/AppOpsService.java +++ b/services/core/java/com/android/server/AppOpsService.java @@ -39,8 +39,10 @@ import android.app.ActivityThread; import android.app.AppGlobals; import android.app.AppOpsManager; import android.app.Dialog; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; @@ -51,6 +53,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Looper; +import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; @@ -96,6 +99,7 @@ public class AppOpsService extends IAppOpsService.Stub { final Looper mLooper; final boolean mStrictEnable; AppOpsPolicy mPolicy; + private PowerManager mPowerManager; private static final int[] PRIVACY_GUARD_OP_STATES = new int[] { AppOpsManager.OP_COARSE_LOCATION, @@ -361,8 +365,45 @@ public class AppOpsService extends IAppOpsService.Stub { || mountMode == Zygote.MOUNT_EXTERNAL_WRITE; } }); + + mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_SCREEN_OFF); + mContext.registerReceiver(mIntentReceiver, filter); } + private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action.equals(Intent.ACTION_SCREEN_OFF)) { + synchronized (this) { + for (int i = mUidStates.size() - 1; i >= 0; i--) { + UidState uidState = mUidStates.valueAt(i); + + ArrayMap<String, Ops> packages = uidState.pkgOps; + if (packages == null) { + continue; + } + + Iterator<Map.Entry<String, Ops>> it = packages.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry<String, Ops> ent = it.next(); + Ops pkgOps = ent.getValue(); + for (int j = pkgOps.size() - 1; j >= 0; j--) { + Op curOp = pkgOps.valueAt(j); + if (DEBUG) + Log.d(TAG, "Ignoring " + curOp.packageName + " request " + + curOp.op); + curOp.dialogReqQueue.ignore(); + } + } + } + } + } + } + }; + public void packageRemoved(int uid, String packageName) { synchronized (this) { UidState uidState = mUidStates.get(uid); @@ -1071,7 +1112,8 @@ public class AppOpsService extends IAppOpsService.Stub { + ops.uidState.pkgOps.size()); } - // First check what the global pkg ops count for the package, + // First drop all request events if the device is not interactive, next + // check what the global pkg ops count for the package, // then check op scoped count. High frequency request ops will be delayed until // their delay count ceiling is met. This is to mitigate the overloading the // main activity manager service handler and having watchdog kill our service. @@ -1081,9 +1123,11 @@ public class AppOpsService extends IAppOpsService.Stub { // we move them to the back of the line. NOTE: these values are magic, and may need // tuning. Ideally we'd want a ringbuffer or token bucket here to do proper rate // limiting. - if (ops.uidState.pkgOps.size() < AppOpsPolicy.RATE_LIMIT_OPS_TOTAL_PKG_COUNT + final boolean isInteractive = mPowerManager.isInteractive(); + if (isInteractive && + (ops.uidState.pkgOps.size() < AppOpsPolicy.RATE_LIMIT_OPS_TOTAL_PKG_COUNT && op.noteOpCount < AppOpsPolicy.RATE_LIMIT_OP_COUNT - || op.delayedCount > AppOpsPolicy.RATE_LIMIT_OP_DELAY_CEILING) { + || op.delayedCount > AppOpsPolicy.RATE_LIMIT_OP_DELAY_CEILING)) { // Reset delayed count, most ops will never need this if (op.delayedCount > 0) { @@ -1094,7 +1138,9 @@ public class AppOpsService extends IAppOpsService.Stub { op.noteOpCount++; req = askOperationLocked(code, uid, packageName, switchOp); } else { - op.delayedCount++; + if (isInteractive) { + op.delayedCount++; + } op.ignoredCount++; return AppOpsManager.MODE_IGNORED; } diff --git a/services/core/java/com/android/server/PermissionDialog.java b/services/core/java/com/android/server/PermissionDialog.java index 0f337b8..fd676b5 100644 --- a/services/core/java/com/android/server/PermissionDialog.java +++ b/services/core/java/com/android/server/PermissionDialog.java @@ -102,6 +102,10 @@ public class PermissionDialog extends BasePermissionDialog { mHandler.obtainMessage(ACTION_IGNORED_TIMEOUT), DISMISS_TIMEOUT); } + public void ignore() { + mHandler.sendMessage(mHandler.obtainMessage(ACTION_IGNORED_TIMEOUT)); + } + private String getAppName(String packageName) { ApplicationInfo appInfo = null; PackageManager pm = mContext.getPackageManager(); diff --git a/services/core/java/com/android/server/PermissionDialogReqQueue.java b/services/core/java/com/android/server/PermissionDialogReqQueue.java index ee94427..5b602e3 100644 --- a/services/core/java/com/android/server/PermissionDialogReqQueue.java +++ b/services/core/java/com/android/server/PermissionDialogReqQueue.java @@ -79,4 +79,10 @@ public class PermissionDialogReqQueue { } } } + + public void ignore() { + if (mDialog != null) { + mDialog.ignore(); + } + } } |