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

Commit 86b2581c authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "[IdleController] Support dock scenario on idle or active judgement" into pi-dev

parents 3a7fc6e5 318abc93
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -3986,6 +3986,26 @@ public class Intent implements Parcelable, Cloneable {
     */
    public static final int EXTRA_THERMAL_STATE_EXCEEDED = 2;

    /**
     * Broadcast Action: Indicates the dock in idle state while device is docked.
     *
     * <p class="note">This is a protected intent that can only be sent
     * by the system.
     *
     * @hide
     */
    public static final String ACTION_DOCK_IDLE = "android.intent.action.DOCK_IDLE";

    /**
     * Broadcast Action: Indicates the dock in active state while device is docked.
     *
     * <p class="note">This is a protected intent that can only be sent
     * by the system.
     *
     * @hide
     */
    public static final String ACTION_DOCK_ACTIVE = "android.intent.action.DOCK_ACTIVE";


    // ---------------------------------------------------------------------
    // ---------------------------------------------------------------------
+4 −0
Original line number Diff line number Diff line
@@ -599,6 +599,10 @@
    <protected-broadcast android:name="android.app.action.DATA_SHARING_RESTRICTION_CHANGED" />
    <protected-broadcast android:name="android.app.action.STATSD_STARTED" />

    <!-- For IdleController -->
    <protected-broadcast android:name="android.intent.action.DOCK_IDLE" />
    <protected-broadcast android:name="android.intent.action.DOCK_ACTIVE" />

    <!-- ====================================================================== -->
    <!--                          RUNTIME PERMISSIONS                           -->
    <!-- ====================================================================== -->
+12 −0
Original line number Diff line number Diff line
@@ -2961,6 +2961,18 @@ public class JobSchedulerService extends com.android.server.SystemService
        return 0;
    }

    void triggerDockState(boolean idleState) {
        final Intent dockIntent;
        if (idleState) {
            dockIntent = new Intent(Intent.ACTION_DOCK_IDLE);
        } else {
            dockIntent = new Intent(Intent.ACTION_DOCK_ACTIVE);
        }
        dockIntent.setPackage("android");
        dockIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
        getContext().sendBroadcastAsUser(dockIntent, UserHandle.ALL);
    }

    private String printContextIdToJobMap(JobStatus[] map, String initial) {
        StringBuilder s = new StringBuilder(initial + ": ");
        for (int i=0; i<map.length; i++) {
+27 −0
Original line number Diff line number Diff line
@@ -66,6 +66,8 @@ public final class JobSchedulerShellCommand extends ShellCommand {
                    return getJobState(pw);
                case "heartbeat":
                    return doHeartbeat(pw);
                case "trigger-dock-state":
                    return triggerDockState(pw);
                default:
                    return handleDefaultCommands(cmd);
            }
@@ -349,6 +351,29 @@ public final class JobSchedulerShellCommand extends ShellCommand {
        }
    }

    private int triggerDockState(PrintWriter pw) throws Exception {
        checkPermission("trigger wireless charging dock state");

        final String opt = getNextArgRequired();
        boolean idleState;
        if ("idle".equals(opt)) {
            idleState = true;
        } else if ("active".equals(opt)) {
            idleState = false;
        } else {
            getErrPrintWriter().println("Error: unknown option " + opt);
            return 1;
        }

        final long ident = Binder.clearCallingIdentity();
        try {
            mInternal.triggerDockState(idleState);
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
        return 0;
    }

    @Override
    public void onHelp() {
        final PrintWriter pw = getOutPrintWriter();
@@ -403,6 +428,8 @@ public final class JobSchedulerShellCommand extends ShellCommand {
        pw.println("    Options:");
        pw.println("      -u or --user: specify which user's job is to be run; the default is");
        pw.println("         the primary or system user");
        pw.println("  trigger-dock-state [idle|active]");
        pw.println("    Trigger wireless charging dock state.  Active by default.");
        pw.println();
    }

+36 −8
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ public final class IdleController extends StateController {
            || Log.isLoggable(TAG, Log.DEBUG);

    // Policy: we decide that we're "idle" if the device has been unused /
    // screen off or dreaming for at least this long
    // screen off or dreaming or wireless charging dock idle for at least this long
    private long mInactivityIdleThreshold;
    private long mIdleWindowSlop;
    final ArraySet<JobStatus> mTrackedTasks = new ArraySet<>();
@@ -105,6 +105,7 @@ public final class IdleController extends StateController {
        // on the main looper thread, either in onReceive() or in an alarm callback.
        private boolean mIdle;
        private boolean mScreenOn;
        private boolean mDockIdle;

        private AlarmManager.OnAlarmListener mIdleAlarmListener = () -> {
            handleIdleTrigger();
@@ -117,6 +118,7 @@ public final class IdleController extends StateController {
            // device in some meaningful way.
            mIdle = false;
            mScreenOn = true;
            mDockIdle = false;
        }

        public boolean isIdle() {
@@ -137,6 +139,10 @@ public final class IdleController extends StateController {
            // Debugging/instrumentation
            filter.addAction(ActivityManagerService.ACTION_TRIGGER_IDLE);

            // Wireless charging dock state
            filter.addAction(Intent.ACTION_DOCK_IDLE);
            filter.addAction(Intent.ACTION_DOCK_ACTIVE);

            mContext.registerReceiver(this, filter);
        }

@@ -144,11 +150,22 @@ public final class IdleController extends StateController {
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (action.equals(Intent.ACTION_SCREEN_ON)
                    || action.equals(Intent.ACTION_DREAMING_STOPPED)) {
                    || action.equals(Intent.ACTION_DREAMING_STOPPED)
                    || action.equals(Intent.ACTION_DOCK_ACTIVE)) {
                if (action.equals(Intent.ACTION_DOCK_ACTIVE)) {
                    if (!mScreenOn) {
                        // Ignore this intent during screen off
                        return;
                    } else {
                        mDockIdle = false;
                    }
                } else {
                    mScreenOn = true;
                    mDockIdle = false;
                }
                if (DEBUG) {
                    Slog.v(TAG,"exiting idle : " + action);
                }
                mScreenOn = true;
                //cancel the alarm
                mAlarm.cancel(mIdleAlarmListener);
                if (mIdle) {
@@ -157,17 +174,28 @@ public final class IdleController extends StateController {
                    reportNewIdleState(mIdle);
                }
            } else if (action.equals(Intent.ACTION_SCREEN_OFF)
                    || action.equals(Intent.ACTION_DREAMING_STARTED)) {
                // when the screen goes off or dreaming starts, we schedule the
                // alarm that will tell us when we have decided the device is
                    || action.equals(Intent.ACTION_DREAMING_STARTED)
                    || action.equals(Intent.ACTION_DOCK_IDLE)) {
                // when the screen goes off or dreaming starts or wireless charging dock in idle,
                // we schedule the alarm that will tell us when we have decided the device is
                // truly idle.
                if (action.equals(Intent.ACTION_DOCK_IDLE)) {
                    if (!mScreenOn) {
                        // Ignore this intent during screen off
                        return;
                    } else {
                        mDockIdle = true;
                    }
                } else {
                    mScreenOn = false;
                    mDockIdle = false;
                }
                final long nowElapsed = sElapsedRealtimeClock.millis();
                final long when = nowElapsed + mInactivityIdleThreshold;
                if (DEBUG) {
                    Slog.v(TAG, "Scheduling idle : " + action + " now:" + nowElapsed + " when="
                            + when);
                }
                mScreenOn = false;
                mAlarm.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                        when, mIdleWindowSlop, "JS idleness", mIdleAlarmListener, null);
            } else if (action.equals(ActivityManagerService.ACTION_TRIGGER_IDLE)) {
@@ -177,7 +205,7 @@ public final class IdleController extends StateController {

        private void handleIdleTrigger() {
            // idle time starts now. Do not set mIdle if screen is on.
            if (!mIdle && !mScreenOn) {
            if (!mIdle && (!mScreenOn || mDockIdle)) {
                if (DEBUG) {
                    Slog.v(TAG, "Idle trigger fired @ " + sElapsedRealtimeClock.millis());
                }