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

Commit 485d0b06 authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android Git Automerger
Browse files

am 9c8600e1: Merge "Implement device idle in power manager." into mnc-dev

* commit '9c8600e1':
  Implement device idle in power manager.
parents c090a6d4 9c8600e1
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