Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b4088dd1 authored by Adnan Begovic's avatar Adnan Begovic Committed by Gerrit Code Review
Browse files

appops: Implement concept of delayedcount.

 High frequency request ops will be delayed until their ignore count
 ceiling is met. This is to mitigate the overloading the main activity
 manager service handler and having watchdog kill our service.

 Google play services likes to share its uid with numerous packages to avoid
 having to grant permissions from the users perspective and thus is the worst
 example of overloading this queue -- so, to not encourage bad behavior,
 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.

Change-Id: I5c3e88807abc80f9700dd68dcecd87dac4626de7
TICKET: CYNGNOS-2869
parent 8e897a5c
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -60,6 +60,11 @@ public class AppOpsPolicy {

    public static final int CONTROL_UNKNOWN = 2;

    // Rate limiting thresholds for ask operations
    public static final int RATE_LIMIT_OP_COUNT = 3;
    public static final int RATE_LIMIT_OPS_TOTAL_PKG_COUNT = 4;
    public static final int RATE_LIMIT_OP_DELAY_CEILING = 10;

    public static int stringToControl(String show) {
        if ("true".equalsIgnoreCase(show)) {
            return CONTROL_SHOW;
+40 −2
Original line number Diff line number Diff line
@@ -184,6 +184,7 @@ public class AppOpsService extends IAppOpsService.Stub {
        final ArrayList<IBinder> clientTokens;
        public int allowedCount;
        public int ignoredCount;
        public int delayedCount;

        public Op(int _uid, String _packageName, int _op, int _mode) {
            uid = _uid;
@@ -1058,8 +1059,45 @@ public class AppOpsService extends IAppOpsService.Stub {
                                    + packageName + ")");
                    return switchOp.mode;
                }

                if (DEBUG) {
                        Log.d(TAG, "Package " + op.packageName + " has " + op.noteOpCount
                                + " requests and " + op.startOpCount + " start requests with "
                                + op.ignoredCount + " ignored at " + op.time +
                                " with a duration of "
                                + op.duration + " while being delayed " + op.delayedCount +
                                " times");
                        Log.d(TAG, "Total pkops for " + ops.packageName + " "
                                + ops.uidState.pkgOps.size());
                }

                // First 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.
                // Google play services likes to share its uid with numerous packages to avoid
                // having to grant permissions from the users perspective and thus is the worst
                // example of overloading this queue -- so, to not encourage bad behavior,
                // 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
                        && op.noteOpCount < AppOpsPolicy.RATE_LIMIT_OP_COUNT
                        || op.delayedCount > AppOpsPolicy.RATE_LIMIT_OP_DELAY_CEILING) {

                    // Reset delayed count, most ops will never need this
                    if (op.delayedCount > 0) {
                        if (DEBUG) Log.d(TAG, "Resetting delayed count for " + op.packageName);
                        op.delayedCount = 0;
                    }

                    op.noteOpCount++;
                    req = askOperationLocked(code, uid, packageName, switchOp);
                } else {
                    op.delayedCount++;
                    op.ignoredCount++;
                    return AppOpsManager.MODE_IGNORED;
                }
            }
        }