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

Commit c32088c1 authored by Serik Beketayev's avatar Serik Beketayev Committed by Suprabh Shukla
Browse files

Disable a wakeup alarm in car.

- Car in power off or suspend state should not wake up from alarm.

Test: run added unit test.
Bug: 123430582
Change-Id: I5cdf93fc816cd3e8a5d2a6d93616ff6040840613
parent 442a4e7b
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -1697,6 +1697,8 @@ class AlarmManagerService extends SystemService {
            return;
        }

        type = fixTypeIfAuto(type);

        // Sanity check the window length.  This will catch people mistakenly
        // trying to pass an end-of-window timestamp rather than a duration.
        if (windowLength > AlarmManager.INTERVAL_HALF_DAY) {
@@ -1811,6 +1813,21 @@ class AlarmManagerService extends SystemService {
        return mConstants.APP_STANDBY_QUOTAS[index];
    }

    /**
     * In case of cars, we need to avoid scheduling wakeup alarms, since we don't want the system
     * to wake up from suspend arbitrarily to perform app work.
     */
    private int fixTypeIfAuto(int type) {
        if (mInjector.isAutomotive()) {
            if (type == AlarmManager.ELAPSED_REALTIME_WAKEUP) {
                type = AlarmManager.ELAPSED_REALTIME;
            } else if (type == AlarmManager.RTC_WAKEUP) {
                type = AlarmManager.RTC;
            }
        }
        return type;
    }

    /**
     * Return the minimum time that should elapse before an app in the specified bucket
     * can receive alarms again
@@ -2214,6 +2231,7 @@ class AlarmManagerService extends SystemService {
            pw.print("  mLastTickSet="); pw.println(sdf.format(new Date(mLastTickSet)));
            pw.print("  mLastTickAdded="); pw.println(sdf.format(new Date(mLastTickAdded)));
            pw.print("  mLastTickRemoved="); pw.println(sdf.format(new Date(mLastTickRemoved)));
            pw.print("  mIsAutomotive="); pw.println(mInjector.isAutomotive());

            if (RECORD_ALARMS_IN_HISTORY) {
                pw.println();
@@ -3838,9 +3856,12 @@ class AlarmManagerService extends SystemService {
    static class Injector {
        private long mNativeData;
        private Context mContext;
        private final boolean mIsAutomotive;

        Injector(Context context) {
            mContext = context;
            mIsAutomotive = context.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_AUTOMOTIVE);
        }

        void init() {
@@ -3929,6 +3950,10 @@ class AlarmManagerService extends SystemService {
        ClockReceiver getClockReceiver(AlarmManagerService service) {
            return service.new ClockReceiver();
        }

        boolean isAutomotive() {
            return mIsAutomotive;
        }
    }

    private class AlarmThread extends Thread
+51 −2
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ import android.app.usage.UsageStatsManagerInternal;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -118,6 +119,8 @@ public class AlarmManagerServiceTest {
    private AlarmManagerService.ClockReceiver mClockReceiver;
    @Mock
    private PowerManager.WakeLock mWakeLock;
    @Mock
    private PackageManager mMockPackageManager;

    private MockitoSession mMockingSession;
    private Injector mInjector;
@@ -128,15 +131,21 @@ public class AlarmManagerServiceTest {
    static class TestTimer {
        private long mElapsed;
        boolean mExpired;
        int mType;

        synchronized long getElapsed() {
            return mElapsed;
        }

        synchronized void set(long millisElapsed) {
        synchronized void set(int type, long millisElapsed) {
            mType = type;
            mElapsed = millisElapsed;
        }

        synchronized int getType() {
            return mType;
        }

        synchronized void expire() throws InterruptedException {
            mExpired = true;
            notifyAll();
@@ -146,6 +155,8 @@ public class AlarmManagerServiceTest {
    }

    public class Injector extends AlarmManagerService.Injector {
        boolean mIsAutomotiveOverride;

        Injector(Context context) {
            super(context);
        }
@@ -179,7 +190,7 @@ public class AlarmManagerServiceTest {

        @Override
        void setAlarm(int type, long millis) {
            mTestTimer.set(millis);
            mTestTimer.set(type, millis);
        }

        @Override
@@ -211,6 +222,11 @@ public class AlarmManagerServiceTest {
        PowerManager.WakeLock getAlarmWakeLock() {
            return mWakeLock;
        }

        @Override
        boolean isAutomotive() {
            return mIsAutomotiveOverride;
        }
    }

    @Before
@@ -237,6 +253,8 @@ public class AlarmManagerServiceTest {
        when(mMockContext.getContentResolver()).thenReturn(mMockResolver);
        doReturn("min_futurity=0,min_interval=0").when(() ->
                Settings.Global.getString(mMockResolver, Settings.Global.ALARM_MANAGER_CONSTANTS));
        when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);

        mInjector = new Injector(mMockContext);
        mService = new AlarmManagerService(mMockContext, mInjector);
        spyOn(mService);
@@ -932,6 +950,37 @@ public class AlarmManagerServiceTest {
        }
    }

    @Test
    public void alarmTypes() throws Exception {
        final int[] typesToSet = {ELAPSED_REALTIME_WAKEUP, ELAPSED_REALTIME, RTC_WAKEUP, RTC};
        final int[] typesExpected = {ELAPSED_REALTIME_WAKEUP, ELAPSED_REALTIME,
                ELAPSED_REALTIME_WAKEUP, ELAPSED_REALTIME};
        assertAlarmTypeConversion(typesToSet, typesExpected);
    }

    /**
     * Confirm that wakeup alarms are never set for automotive.
     */
    @Test
    public void alarmTypesForAuto() throws Exception {
        mInjector.mIsAutomotiveOverride = true;
        final int[] typesToSet = {ELAPSED_REALTIME_WAKEUP, ELAPSED_REALTIME, RTC_WAKEUP, RTC};
        final int[] typesExpected = {ELAPSED_REALTIME, ELAPSED_REALTIME, ELAPSED_REALTIME,
                ELAPSED_REALTIME};
        assertAlarmTypeConversion(typesToSet, typesExpected);
    }

    private void assertAlarmTypeConversion(int[] typesToSet, int[] typesExpected) throws Exception {
        for (int i = 0; i < typesToSet.length; i++) {
            setTestAlarm(typesToSet[i], 1234, getNewMockPendingIntent());
            final int typeSet = mTestTimer.getType();
            assertEquals("Alarm of type " + typesToSet[i] + " was set to type " + typeSet,
                    typesExpected[i], typeSet);
            mNowElapsedTest = mTestTimer.getElapsed();
            mTestTimer.expire();
        }
    }

    @Test
    public void alarmCountOnInvalidSet() {
        setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + 12345, null);