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

Commit f5d1f1a5 authored by Suprabh Shukla's avatar Suprabh Shukla Committed by Automerger Merge Worker
Browse files

Merge "Add a metrics reason code for USE_EXACT_ALARM" into tm-dev am: 7fc26f8e am: 80bcc90a

parents 0cf8519d 80bcc90a
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -88,6 +88,10 @@ class Alarm {
     * Change wasn't enable for the caller due to compat reasons.
     * Change wasn't enable for the caller due to compat reasons.
     */
     */
    static final int EXACT_ALLOW_REASON_COMPAT = 2;
    static final int EXACT_ALLOW_REASON_COMPAT = 2;
    /**
     * Caller had USE_EXACT_ALARM permission.
     */
    static final int EXACT_ALLOW_REASON_POLICY_PERMISSION = 3;


    public final int type;
    public final int type;
    /**
    /**
@@ -275,6 +279,8 @@ class Alarm {
                return "compat";
                return "compat";
            case EXACT_ALLOW_REASON_PERMISSION:
            case EXACT_ALLOW_REASON_PERMISSION:
                return "permission";
                return "permission";
            case EXACT_ALLOW_REASON_POLICY_PERMISSION:
                return "policy_permission";
            case EXACT_ALLOW_REASON_NOT_APPLICABLE:
            case EXACT_ALLOW_REASON_NOT_APPLICABLE:
                return "N/A";
                return "N/A";
            default:
            default:
+35 −36
Original line number Original line Diff line number Diff line
@@ -46,6 +46,7 @@ import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_ALLOW_LIST;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_COMPAT;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_COMPAT;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_NOT_APPLICABLE;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_NOT_APPLICABLE;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_PERMISSION;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_PERMISSION;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_POLICY_PERMISSION;
import static com.android.server.alarm.Alarm.REQUESTER_POLICY_INDEX;
import static com.android.server.alarm.Alarm.REQUESTER_POLICY_INDEX;
import static com.android.server.alarm.Alarm.TARE_POLICY_INDEX;
import static com.android.server.alarm.Alarm.TARE_POLICY_INDEX;
import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_ALARM_CANCELLED;
import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_ALARM_CANCELLED;
@@ -2698,8 +2699,7 @@ public class AlarmManagerService extends SystemService {


            // Make sure the caller is allowed to use the requested kind of alarm, and also
            // Make sure the caller is allowed to use the requested kind of alarm, and also
            // decide what quota and broadcast options to use.
            // decide what quota and broadcast options to use.
            boolean allowListed = false;    // For logging the reason.
            int exactAllowReason = EXACT_ALLOW_REASON_NOT_APPLICABLE;
            boolean changeDisabled = false; // For logging the reason.
            Bundle idleOptions = null;
            Bundle idleOptions = null;
            if ((flags & FLAG_PRIORITIZE) != 0) {
            if ((flags & FLAG_PRIORITIZE) != 0) {
                getContext().enforcePermission(
                getContext().enforcePermission(
@@ -2721,57 +2721,56 @@ public class AlarmManagerService extends SystemService {
                        idleOptions = mOptsWithoutFgs.toBundle();
                        idleOptions = mOptsWithoutFgs.toBundle();
                    }
                    }
                } else {
                } else {
                    changeDisabled = true;
                    needsPermission = false;
                    needsPermission = false;
                    lowerQuota = allowWhileIdle;
                    lowerQuota = allowWhileIdle;
                    idleOptions = allowWhileIdle ? mOptsWithFgs.toBundle() : null;
                    idleOptions = allowWhileIdle ? mOptsWithFgs.toBundle() : null;
                    if (exact) {
                        exactAllowReason = EXACT_ALLOW_REASON_COMPAT;
                    }
                    }
                if (needsPermission && !hasScheduleExactAlarmInternal(callingPackage, callingUid)
                }
                        && !hasUseExactAlarmInternal(callingPackage, callingUid)) {
                if (needsPermission) {
                    if (!isExemptFromExactAlarmPermissionNoLock(callingUid)) {
                    if (hasUseExactAlarmInternal(callingPackage, callingUid)) {
                        final String errorMessage = "Caller " + callingPackage + " needs to hold "
                        exactAllowReason = EXACT_ALLOW_REASON_POLICY_PERMISSION;
                                + Manifest.permission.SCHEDULE_EXACT_ALARM + " to set "
                    } else if (hasScheduleExactAlarmInternal(callingPackage, callingUid)) {
                        exactAllowReason = EXACT_ALLOW_REASON_PERMISSION;
                    } else {
                        if (isExemptFromExactAlarmPermissionNoLock(callingUid)) {
                            exactAllowReason = EXACT_ALLOW_REASON_ALLOW_LIST;
                        } else {
                            final String errorMessage =
                                    "Caller " + callingPackage + " needs to hold "
                                            + Manifest.permission.SCHEDULE_EXACT_ALARM + " or "
                                            + Manifest.permission.USE_EXACT_ALARM + " to set "
                                            + "exact alarms.";
                                            + "exact alarms.";
                            if (mConstants.CRASH_NON_CLOCK_APPS) {
                            if (mConstants.CRASH_NON_CLOCK_APPS) {
                                throw new SecurityException(errorMessage);
                                throw new SecurityException(errorMessage);
                            } else {
                            } else {
                                Slog.wtf(TAG, errorMessage);
                                Slog.wtf(TAG, errorMessage);
                            }
                            }
                    } else {
                        allowListed = true;
                        }
                        }
                    // If the app is on the full system power allow-list (not except-idle), or the
                        // If the app is on the full system power allow-list (not except-idle),
                    // user-elected allow-list, or we're in a soft failure mode, we still allow the
                        // or the user-elected allow-list, or we're in a soft failure mode, we still
                    // alarms.
                        // allow the alarms.
                    // In both cases, ALLOW_WHILE_IDLE alarms get a lower quota equivalent to what
                        // In both cases, ALLOW_WHILE_IDLE alarms get a lower quota equivalent to
                    // pre-S apps got. Note that user-allow-listed apps don't use the flag
                        // what pre-S apps got. Note that user-allow-listed apps don't use the flag
                        // ALLOW_WHILE_IDLE.
                        // ALLOW_WHILE_IDLE.
                        // We grant temporary allow-list to allow-while-idle alarms but without FGS
                        // We grant temporary allow-list to allow-while-idle alarms but without FGS
                    // capability. AlarmClock alarms do not get the temporary allow-list. This is
                        // capability. AlarmClock alarms do not get the temporary allow-list.
                    // consistent with pre-S behavior. Note that apps that are in either of the
                        // This is consistent with pre-S behavior. Note that apps that are in
                    // power-save allow-lists do not need it.
                        // either of the power-save allow-lists do not need it.
                        idleOptions = allowWhileIdle ? mOptsWithoutFgs.toBundle() : null;
                        idleOptions = allowWhileIdle ? mOptsWithoutFgs.toBundle() : null;
                        lowerQuota = allowWhileIdle;
                        lowerQuota = allowWhileIdle;
                    }
                    }
                }
                if (lowerQuota) {
                if (lowerQuota) {
                    flags &= ~FLAG_ALLOW_WHILE_IDLE;
                    flags &= ~FLAG_ALLOW_WHILE_IDLE;
                    flags |= FLAG_ALLOW_WHILE_IDLE_COMPAT;
                    flags |= FLAG_ALLOW_WHILE_IDLE_COMPAT;
                }
                }
            }
            }
            final int exactAllowReason;
            if (exact) {
            if (exact) {
                // If this is an exact time alarm, then it can't be batched with other alarms.
                // If this is an exact time alarm, then it can't be batched with other alarms.
                flags |= AlarmManager.FLAG_STANDALONE;
                flags |= AlarmManager.FLAG_STANDALONE;


                if (changeDisabled) {
                    exactAllowReason = EXACT_ALLOW_REASON_COMPAT;
                } else if (allowListed) {
                    exactAllowReason = EXACT_ALLOW_REASON_ALLOW_LIST;
                } else {
                    exactAllowReason = EXACT_ALLOW_REASON_PERMISSION;
                }
            } else {
                exactAllowReason = EXACT_ALLOW_REASON_NOT_APPLICABLE;
            }
            }


            setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver,
            setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver,
+3 −0
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT
import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__CHANGE_DISABLED;
import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__CHANGE_DISABLED;
import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__NOT_APPLICABLE;
import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__NOT_APPLICABLE;
import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__PERMISSION;
import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__PERMISSION;
import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__POLICY_PERMISSION;
import static com.android.server.alarm.AlarmManagerService.INDEFINITE_DELAY;
import static com.android.server.alarm.AlarmManagerService.INDEFINITE_DELAY;


import android.app.ActivityManager;
import android.app.ActivityManager;
@@ -89,6 +90,8 @@ class MetricsHelper {
                return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__PERMISSION;
                return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__PERMISSION;
            case Alarm.EXACT_ALLOW_REASON_COMPAT:
            case Alarm.EXACT_ALLOW_REASON_COMPAT:
                return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__CHANGE_DISABLED;
                return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__CHANGE_DISABLED;
            case Alarm.EXACT_ALLOW_REASON_POLICY_PERMISSION:
                return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__POLICY_PERMISSION;
            default:
            default:
                return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__NOT_APPLICABLE;
                return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__NOT_APPLICABLE;
        }
        }
+85 −3
Original line number Original line Diff line number Diff line
@@ -56,6 +56,7 @@ import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_ALLOW_LIST;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_COMPAT;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_COMPAT;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_NOT_APPLICABLE;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_NOT_APPLICABLE;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_PERMISSION;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_PERMISSION;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_POLICY_PERMISSION;
import static com.android.server.alarm.AlarmManagerService.ACTIVE_INDEX;
import static com.android.server.alarm.AlarmManagerService.ACTIVE_INDEX;
import static com.android.server.alarm.AlarmManagerService.AlarmHandler.APP_STANDBY_BUCKET_CHANGED;
import static com.android.server.alarm.AlarmManagerService.AlarmHandler.APP_STANDBY_BUCKET_CHANGED;
import static com.android.server.alarm.AlarmManagerService.AlarmHandler.CHARGING_STATUS_CHANGED;
import static com.android.server.alarm.AlarmManagerService.AlarmHandler.CHARGING_STATUS_CHANGED;
@@ -2337,7 +2338,7 @@ public class AlarmManagerServiceTest {
    }
    }


    @Test
    @Test
    public void alarmClockBinderCall() throws RemoteException {
    public void alarmClockBinderCallWithSEAPermission() throws RemoteException {
        mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
        mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);


        mockScheduleExactAlarmState(true, false, MODE_ALLOWED);
        mockScheduleExactAlarmState(true, false, MODE_ALLOWED);
@@ -2362,6 +2363,34 @@ public class AlarmManagerServiceTest {
        assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type);
        assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type);
    }
    }


    @Test
    public void alarmClockBinderCallWithUEAPermission() throws RemoteException {
        mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
        mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true);

        mockUseExactAlarmState(true);
        mockScheduleExactAlarmState(false, false, MODE_ERRORED);

        final PendingIntent alarmPi = getNewMockPendingIntent();
        final AlarmManager.AlarmClockInfo alarmClock = mock(AlarmManager.AlarmClockInfo.class);
        mBinder.set(TEST_CALLING_PACKAGE, RTC_WAKEUP, 1234, WINDOW_EXACT, 0, 0,
                alarmPi, null, null, null, alarmClock);

        // Correct permission checks are invoked.
        verify(mService).hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID);
        verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt());

        final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
        verify(mService).setImpl(eq(RTC_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L),
                eq(alarmPi), isNull(), isNull(), eq(FLAG_STANDALONE | FLAG_WAKE_FROM_IDLE),
                isNull(), eq(alarmClock), eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE),
                bundleCaptor.capture(), eq(EXACT_ALLOW_REASON_POLICY_PERMISSION));

        final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue());
        final int type = idleOptions.getTemporaryAppAllowlistType();
        assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type);
    }

    private void mockScheduleExactAlarmState(boolean declared, boolean denyList, int mode) {
    private void mockScheduleExactAlarmState(boolean declared, boolean denyList, int mode) {
        String[] requesters = declared ? new String[]{TEST_CALLING_PACKAGE} : EmptyArray.STRING;
        String[] requesters = declared ? new String[]{TEST_CALLING_PACKAGE} : EmptyArray.STRING;
        when(mPermissionManagerInternal.getAppOpPermissionPackages(SCHEDULE_EXACT_ALARM))
        when(mPermissionManagerInternal.getAppOpPermissionPackages(SCHEDULE_EXACT_ALARM))
@@ -2410,7 +2439,7 @@ public class AlarmManagerServiceTest {
    }
    }


    @Test
    @Test
    public void exactBinderCallWithPermission() throws RemoteException {
    public void exactBinderCallWithSEAPermission() throws RemoteException {
        mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
        mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);


        mockScheduleExactAlarmState(true, false, MODE_ALLOWED);
        mockScheduleExactAlarmState(true, false, MODE_ALLOWED);
@@ -2433,6 +2462,32 @@ public class AlarmManagerServiceTest {
        assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type);
        assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type);
    }
    }


    @Test
    public void exactBinderCallWithUEAPermission() throws RemoteException {
        mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
        mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true);

        mockUseExactAlarmState(true);
        mockScheduleExactAlarmState(false, false, MODE_ERRORED);
        final PendingIntent alarmPi = getNewMockPendingIntent();
        mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0,
                0, alarmPi, null, null, null, null);

        verify(mService).hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID);
        verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt());

        final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
        verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L),
                eq(alarmPi), isNull(), isNull(),
                eq(FLAG_STANDALONE), isNull(), isNull(),
                eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture(),
                eq(EXACT_ALLOW_REASON_POLICY_PERMISSION));

        final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue());
        final int type = idleOptions.getTemporaryAppAllowlistType();
        assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type);
    }

    @Test
    @Test
    public void exactBinderCallWithAllowlist() throws RemoteException {
    public void exactBinderCallWithAllowlist() throws RemoteException {
        mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
        mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
@@ -2454,7 +2509,7 @@ public class AlarmManagerServiceTest {
    }
    }


    @Test
    @Test
    public void exactAllowWhileIdleBinderCallWithPermission() throws RemoteException {
    public void exactAllowWhileIdleBinderCallWithSEAPermission() throws RemoteException {
        mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
        mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);


        mockScheduleExactAlarmState(true, false, MODE_ALLOWED);
        mockScheduleExactAlarmState(true, false, MODE_ALLOWED);
@@ -2462,6 +2517,7 @@ public class AlarmManagerServiceTest {
        mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0,
        mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0,
                FLAG_ALLOW_WHILE_IDLE, alarmPi, null, null, null, null);
                FLAG_ALLOW_WHILE_IDLE, alarmPi, null, null, null, null);


        verify(mService).hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID);
        verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt());
        verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt());


        final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
        final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -2476,6 +2532,32 @@ public class AlarmManagerServiceTest {
        assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type);
        assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type);
    }
    }


    @Test
    public void exactAllowWhileIdleBinderCallWithUEAPermission() throws RemoteException {
        mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
        mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true);

        mockUseExactAlarmState(true);
        mockScheduleExactAlarmState(false, false, MODE_ERRORED);
        final PendingIntent alarmPi = getNewMockPendingIntent();
        mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0,
                FLAG_ALLOW_WHILE_IDLE, alarmPi, null, null, null, null);

        verify(mService).hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID);
        verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt());

        final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
        verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L),
                eq(alarmPi), isNull(), isNull(),
                eq(FLAG_ALLOW_WHILE_IDLE | FLAG_STANDALONE), isNull(), isNull(),
                eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture(),
                eq(EXACT_ALLOW_REASON_POLICY_PERMISSION));

        final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue());
        final int type = idleOptions.getTemporaryAppAllowlistType();
        assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type);
    }

    @Test
    @Test
    public void exactAllowWhileIdleBinderCallWithAllowlist() throws RemoteException {
    public void exactAllowWhileIdleBinderCallWithAllowlist() throws RemoteException {
        mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
        mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);