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

Commit 9c8600e1 authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android (Google) Code Review
Browse files

Merge "Implement device idle in power manager." into mnc-dev

parents b98e0712 8d66b3fb
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -3761,7 +3761,9 @@ package android.app {
    method public android.app.AlarmManager.AlarmClockInfo getNextAlarmClock();
    method public void set(int, long, android.app.PendingIntent);
    method public void setAlarmClock(android.app.AlarmManager.AlarmClockInfo, android.app.PendingIntent);
    method public void setAndAllowWhileIdle(int, long, android.app.PendingIntent);
    method public void setExact(int, long, android.app.PendingIntent);
    method public void setExactAndAllowWhileIdle(int, long, android.app.PendingIntent);
    method public void setInexactRepeating(int, long, long, android.app.PendingIntent);
    method public void setRepeating(int, long, long, android.app.PendingIntent);
    method public void setTime(long);
+2 −0
Original line number Diff line number Diff line
@@ -3851,7 +3851,9 @@ package android.app {
    method public void set(int, long, android.app.PendingIntent);
    method public void set(int, long, long, long, android.app.PendingIntent, android.os.WorkSource);
    method public void setAlarmClock(android.app.AlarmManager.AlarmClockInfo, android.app.PendingIntent);
    method public void setAndAllowWhileIdle(int, long, android.app.PendingIntent);
    method public void setExact(int, long, android.app.PendingIntent);
    method public void setExactAndAllowWhileIdle(int, long, android.app.PendingIntent);
    method public void setInexactRepeating(int, long, long, android.app.PendingIntent);
    method public void setRepeating(int, long, long, android.app.PendingIntent);
    method public void setTime(long);
+88 −5
Original line number Diff line number Diff line
@@ -71,10 +71,7 @@ import java.io.IOException;
 * {@link android.content.Context#getSystemService
 * Context.getSystemService(Context.ALARM_SERVICE)}.
 */
public class AlarmManager
{
    private static final String TAG = "AlarmManager";

public class AlarmManager {
    /**
     * Alarm time in {@link System#currentTimeMillis System.currentTimeMillis()}
     * (wall clock time in UTC), which will wake up the device when
@@ -559,6 +556,92 @@ public class AlarmManager
        setImpl(type, triggerAtMillis, WINDOW_HEURISTIC, intervalMillis, 0, operation, null, null);
    }

    /**
     * Like {@link #set(int, long, PendingIntent)}, but this alarm will be allowed to execute
     * even when the system is in low-power idle modes.  This type of alarm must <b>only</b>
     * be used for situations where it is actually required that the alarm go off while in
     * idle -- a reasonable example would be for a calendar notification that should make a
     * sound so the user is aware of it.  These alarms can significantly impact the power use
     * of the device when idle (and thus cause significant battery blame to the app scheduling
     * them), so they should be used with care.
     *
     * <p>Unlike other alarms, the system is free to reschedule this type of alarm to happen
     * out of order with any other alarms, even those from the same app.  This will clearly happen
     * when the device is idle (since this alarm can go off while idle, when any other alarms
     * from the app will be held until later), but may also happen even when not idle.</p>
     *
     * <p>Regardless of the app's target SDK version, this call always allows batching of the
     * alarm.</p>
     *
     * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP},
     *        {@link #RTC}, or {@link #RTC_WAKEUP}.
     * @param triggerAtMillis time in milliseconds that the alarm should go
     * off, using the appropriate clock (depending on the alarm type).
     * @param operation Action to perform when the alarm goes off;
     * typically comes from {@link PendingIntent#getBroadcast
     * IntentSender.getBroadcast()}.
     *
     * @see #set(int, long, PendingIntent)
     * @see #setExactAndAllowWhileIdle
     * @see #cancel
     * @see android.content.Context#sendBroadcast
     * @see android.content.Context#registerReceiver
     * @see android.content.Intent#filterEquals
     * @see #ELAPSED_REALTIME
     * @see #ELAPSED_REALTIME_WAKEUP
     * @see #RTC
     * @see #RTC_WAKEUP
     */
    public void setAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation) {
        setImpl(type, triggerAtMillis, WINDOW_HEURISTIC, 0, FLAG_ALLOW_WHILE_IDLE, operation,
                null, null);
    }

    /**
     * Like {@link #setExact(int, long, PendingIntent)}, but this alarm will be allowed to execute
     * even when the system is in low-power idle modes.  If you don't need exact scheduling of
     * the alarm but still need to execute while idle, consider using
     * {@link #setAndAllowWhileIdle}.  This type of alarm must <b>only</b>
     * be used for situations where it is actually required that the alarm go off while in
     * idle -- a reasonable example would be for a calendar notification that should make a
     * sound so the user is aware of it.  These alarms can significantly impact the power use
     * of the device when idle (and thus cause significant battery blame to the app scheduling
     * them), so they should be used with care.
     *
     * <p>Unlike other alarms, the system is free to reschedule this type of alarm to happen
     * out of order with any other alarms, even those from the same app.  This will clearly happen
     * when the device is idle (since this alarm can go off while idle, when any other alarms
     * from the app will be held until later), but may also happen even when not idle.
     * Note that the OS will allow itself more flexibility for scheduling these alarms than
     * regular exact alarms, since the application has opted into this behavior.  When the
     * device is idle it may take even more liberties with scheduling in order to optimize
     * for battery life.</p>
     *
     * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP},
     *        {@link #RTC}, or {@link #RTC_WAKEUP}.
     * @param triggerAtMillis time in milliseconds that the alarm should go
     *        off, using the appropriate clock (depending on the alarm type).
     * @param operation Action to perform when the alarm goes off;
     *        typically comes from {@link PendingIntent#getBroadcast
     *        IntentSender.getBroadcast()}.
     *
     * @see #set
     * @see #setRepeating
     * @see #setWindow
     * @see #cancel
     * @see android.content.Context#sendBroadcast
     * @see android.content.Context#registerReceiver
     * @see android.content.Intent#filterEquals
     * @see #ELAPSED_REALTIME
     * @see #ELAPSED_REALTIME_WAKEUP
     * @see #RTC
     * @see #RTC_WAKEUP
     */
    public void setExactAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation) {
        setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, FLAG_ALLOW_WHILE_IDLE, operation,
                null, null);
    }

    /**
     * Remove any alarms with a matching {@link Intent}.
     * Any alarm, of any type, whose Intent matches this one (as defined by
+2 −0
Original line number Diff line number Diff line
@@ -134,4 +134,6 @@ public abstract class PowerManagerInternal {
    }

    public abstract void setDeviceIdleMode(boolean enabled);

    public abstract void setDeviceIdleWhitelist(int[] appids);
}
+46 −8
Original line number Diff line number Diff line
@@ -142,6 +142,7 @@ public class DeviceIdleController extends SystemService {
    private PendingIntent mAlarmIntent;
    private Intent mIdleIntent;
    private Display mCurDisplay;
    private boolean mIdleDisabled;
    private boolean mScreenOn;
    private boolean mCharging;
    private boolean mSigMotionActive;
@@ -187,10 +188,16 @@ public class DeviceIdleController extends SystemService {
    private final ArrayMap<String, Integer> mPowerSaveWhitelistUserApps = new ArrayMap<>();

    /**
     * UIDs that have been white-listed to opt out of power save restrictions.
     * App IDs that have been white-listed to opt out of power save restrictions.
     */
    private final SparseBooleanArray mPowerSaveWhitelistAppIds = new SparseBooleanArray();

    /**
     * Current app IDs that are in the complete power save white list.  This array can
     * be shared with others because it will not be modified once set.
     */
    private int[] mPowerSaveWhitelistAppIdArray = new int[0];

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override public void onReceive(Context context, Intent intent) {
            if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
@@ -381,6 +388,8 @@ public class DeviceIdleController extends SystemService {
                filter.addAction(ACTION_STEP_IDLE_STATE);
                getContext().registerReceiver(mReceiver, filter);

                mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAppIdArray);

                mDisplayManager.registerDisplayListener(mDisplayListener, null);
                updateDisplayLocked();
            }
@@ -445,12 +454,7 @@ public class DeviceIdleController extends SystemService {

    public int[] getAppIdWhitelistInternal() {
        synchronized (this) {
            int size = mPowerSaveWhitelistAppIds.size();
            int[] appids = new int[size];
            for (int i = 0; i < size; i++) {
                appids[i] = mPowerSaveWhitelistAppIds.keyAt(i);
            }
            return appids;
            return mPowerSaveWhitelistAppIdArray;
        }
    }

@@ -499,7 +503,7 @@ public class DeviceIdleController extends SystemService {
    }

    void becomeInactiveIfAppropriateLocked() {
        if (!mScreenOn && !mCharging && mState == STATE_ACTIVE) {
        if (!mScreenOn && !mCharging && !mIdleDisabled && mState == STATE_ACTIVE) {
            // Screen has turned off; we are now going to become inactive and start
            // waiting to see if we will ultimately go idle.
            mState = STATE_INACTIVE;
@@ -625,6 +629,15 @@ public class DeviceIdleController extends SystemService {
        for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) {
            mPowerSaveWhitelistAppIds.put(mPowerSaveWhitelistUserApps.valueAt(i), true);
        }
        int size = mPowerSaveWhitelistAppIds.size();
        int[] appids = new int[size];
        for (int i = 0; i < size; i++) {
            appids[i] = mPowerSaveWhitelistAppIds.keyAt(i);
        }
        mPowerSaveWhitelistAppIdArray = appids;
        if (mLocalPowerManager != null) {
            mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAppIdArray);
        }
    }

    private void reportPowerSaveWhitelistChangedLocked() {
@@ -763,6 +776,10 @@ public class DeviceIdleController extends SystemService {
        pw.println("Commands:");
        pw.println("  step");
        pw.println("    Immediately step to next state, without waiting for alarm.");
        pw.println("  disable");
        pw.println("    Completely disable device idle mode.");
        pw.println("  enable");
        pw.println("    Re-enable device idle mode after it had previously been disabled.");
        pw.println("  whitelist");
        pw.println("    Add (prefix with +) or remove (prefix with -) packages.");
    }
@@ -782,12 +799,32 @@ public class DeviceIdleController extends SystemService {
                if ("-h".equals(arg)) {
                    dumpHelp(pw);
                    return;
                } else if ("-a".equals(arg)) {
                    // Ignore, we always dump all.
                } else if ("step".equals(arg)) {
                    synchronized (this) {
                        stepIdleStateLocked();
                        pw.print("Stepped to: "); pw.println(stateToString(mState));
                    }
                    return;
                } else if ("disable".equals(arg)) {
                    synchronized (this) {
                        if (!mIdleDisabled) {
                            mIdleDisabled = true;
                            becomeActiveLocked("disabled");
                            pw.println("Idle mode disabled");
                        }
                    }
                    return;
                } else if ("enable".equals(arg)) {
                    synchronized (this) {
                        if (mIdleDisabled) {
                            mIdleDisabled = false;
                            becomeInactiveIfAppropriateLocked();
                            pw.println("Idle mode enabled");
                        }
                    }
                    return;
                } else if ("whitelist".equals(arg)) {
                    i++;
                    while (i < args.length) {
@@ -853,6 +890,7 @@ public class DeviceIdleController extends SystemService {
            }
            pw.print("  mSigMotionSensor="); pw.println(mSigMotionSensor);
            pw.print("  mCurDisplay="); pw.println(mCurDisplay);
            pw.print("  mIdleDisabled="); pw.println(mIdleDisabled);
            pw.print("  mScreenOn="); pw.println(mScreenOn);
            pw.print("  mCharging="); pw.println(mCharging);
            pw.print("  mSigMotionActive="); pw.println(mSigMotionActive);
Loading