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

Commit 2a099881 authored by Sam Mortimer's avatar Sam Mortimer Committed by Gerrit Code Review
Browse files

[2/2] AppOps: Add alarm wakeup op

When alarm wakeups are denied/ignored,
the alarm types are remapped as follows:

RTC_WAKEUP -> RTC
ELAPSED_REALTIME_WAKEUP -> ELAPSED_REALTIME

Change-Id: I3a5023e1f6260004319290e776bdb2daf73e9fdf
parent 543565f1
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -104,7 +104,8 @@ public class AppOpsManager {
    public static final int OP_WIFI_CHANGE = 31;
    public static final int OP_BLUETOOTH_CHANGE = 32;
    public static final int OP_DATA_CONNECT_CHANGE = 33;
    public static final int _NUM_OP = 34;
    public static final int OP_ALARM_WAKEUP = 34;
    public static final int _NUM_OP = 35;

    /**
     * Map to check if each operation is strict or not, to determine default
@@ -147,6 +148,7 @@ public class AppOpsManager {
        true,   //OP_WIFI_CHANGE
        true,   //OP_BLUETOOTH_CHANGE
        true,   //OP_DATA_CONNECT_CHANGE
        false,  //OP_ALARM_WAKEUP
    };

    /**
@@ -192,6 +194,7 @@ public class AppOpsManager {
            OP_WIFI_CHANGE,
            OP_BLUETOOTH_CHANGE,
            OP_DATA_CONNECT_CHANGE,
            OP_ALARM_WAKEUP,
    };

    /**
@@ -233,6 +236,7 @@ public class AppOpsManager {
            "WIFI_CHANGE",
            "BLUETOOTH_CHANGE",
            "DATA_CONNECT_CHANGE",
            "ALARM_WAKEUP",
    };

    /**
@@ -274,6 +278,7 @@ public class AppOpsManager {
            android.Manifest.permission.CHANGE_WIFI_STATE,
            android.Manifest.permission.BLUETOOTH,
            android.Manifest.permission.CHANGE_NETWORK_STATE,
            null, // no permission for alarm wakeups
    };

    /**
+1 −0
Original line number Diff line number Diff line
@@ -88,5 +88,6 @@
        <item>Trying to turn on/off Wifi</item>
        <item>Trying to turn on/off bluetooth</item>
        <item>Trying to turn on/off mobile data</item>
        <item>Trying to schedule device wakeup</item>
    </string-array>
</resources>
+55 −3
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server;
import android.app.Activity;
import android.app.ActivityManagerNative;
import android.app.AlarmManager;
import android.app.AppOpsManager;
import android.app.IAlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@@ -106,6 +107,8 @@ class AlarmManagerService extends IAlarmManager.Stub {
    private final PendingIntent mTimeTickSender;
    private final PendingIntent mDateChangeSender;

    private final AppOpsManager mAppOps;

    private static final class InFlight extends Intent {
        final PendingIntent mPendingIntent;
        final Pair<String, ComponentName> mTarget;
@@ -197,6 +200,8 @@ class AlarmManagerService extends IAlarmManager.Stub {
        } else {
            Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler.");
        }

        mAppOps = (AppOpsManager)mContext.getSystemService(Context.APP_OPS_SERVICE);
    }
    
    protected void finalize() throws Throwable {
@@ -217,6 +222,24 @@ class AlarmManagerService extends IAlarmManager.Stub {
            Slog.w(TAG, "set/setRepeating ignored because there is no intent");
            return;
        }

        boolean wakeupFiltered = false;
        if ((type == AlarmManager.RTC_WAKEUP
                        || type == AlarmManager.ELAPSED_REALTIME_WAKEUP)
                && mAppOps.checkOpNoThrow(AppOpsManager.OP_ALARM_WAKEUP,
                        operation.getCreatorUid(),
                        operation.getCreatorPackage())
                != AppOpsManager.MODE_ALLOWED) {

            if (type == AlarmManager.RTC_WAKEUP) {
                type = AlarmManager.RTC;
            } else {
                type = AlarmManager.ELAPSED_REALTIME;
            }

            wakeupFiltered = true;
        }

        synchronized (mLock) {
            Alarm alarm = new Alarm();
            alarm.type = type;
@@ -225,7 +248,16 @@ class AlarmManagerService extends IAlarmManager.Stub {
            alarm.operation = operation;

            // Remove this alarm if already scheduled.
            removeLocked(operation);
            removeNoWakeupLocked(operation);
            final boolean foundExistingWakeup = removeWakeupLocked(operation);

            // note AppOp for accounting purposes
            // skip if the alarm already existed
            if (!foundExistingWakeup && wakeupFiltered) {
                mAppOps.noteOpNoThrow(AppOpsManager.OP_ALARM_WAKEUP,
                        operation.getCreatorUid(),
                        operation.getCreatorPackage());
            }

            if (localLOGV) Slog.v(TAG, "set: " + alarm);

@@ -344,21 +376,37 @@ class AlarmManagerService extends IAlarmManager.Stub {
        removeLocked(mElapsedRealtimeAlarms, operation);
    }

    private void removeLocked(ArrayList<Alarm> alarmList,
    private boolean removeWakeupLocked(PendingIntent operation) {
        final boolean rtcwake = removeLocked(mRtcWakeupAlarms, operation);
        final boolean realtimewake = removeLocked(mElapsedRealtimeWakeupAlarms, operation);

        return rtcwake || realtimewake;
    }

    private void removeNoWakeupLocked(PendingIntent operation) {
        removeLocked(mRtcAlarms, operation);
        removeLocked(mElapsedRealtimeAlarms, operation);
    }

    private boolean removeLocked(ArrayList<Alarm> alarmList,
            PendingIntent operation) {
        if (alarmList.size() <= 0) {
            return;
            return false;
        }

        // iterator over the list removing any it where the intent match
        Iterator<Alarm> it = alarmList.iterator();
        
        boolean found = false;
        while (it.hasNext()) {
            Alarm alarm = it.next();
            if (alarm.operation.equals(operation)) {
                found = true;
                it.remove();
            }
        }

        return found;
    }

    public void removeLocked(String packageName) {
@@ -862,6 +910,10 @@ class AlarmManagerService extends IAlarmManager.Stub {
                                fs.numWakeup++;
                                ActivityManagerNative.noteWakeupAlarm(
                                        alarm.operation);
                                // AppOps accounting
                                mAppOps.noteOpNoThrow(AppOpsManager.OP_ALARM_WAKEUP,
                                        alarm.operation.getCreatorUid(),
                                        alarm.operation.getCreatorPackage());
                            }
                        } catch (PendingIntent.CanceledException e) {
                            if (alarm.repeatInterval > 0) {