From 318abc932467485e191578a923baba2ed40834f0 Mon Sep 17 00:00:00 2001 From: lpeter <@google.com> Date: Fri, 4 May 2018 16:13:14 +0800 Subject: [IdleController] Support dock scenario on idle or active judgement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the current design, IdleController of Job service considers devices as ‘idle’ after 71 minutes of screen off. But under docking use scenario, devices screen might remain on for a very long time and it’s not necessary implying the device being interactive with users. So create a mechanism for device to enter the ‘idle’ state that JobScheduler can kick off idle tasks. Bug: 79183658 Test: atest DeviceStatesTest Change-Id: I5b307ca51e28ffca63f79a9c43984c3b76e51629 --- core/java/android/content/Intent.java | 20 ++++++++++ core/res/AndroidManifest.xml | 4 ++ .../android/server/job/JobSchedulerService.java | 12 ++++++ .../server/job/JobSchedulerShellCommand.java | 27 +++++++++++++ .../server/job/controllers/IdleController.java | 44 ++++++++++++++++++---- 5 files changed, 99 insertions(+), 8 deletions(-) diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index ea0811086d52..1bc3bc9732eb 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -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. + * + *

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. + * + *

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"; + // --------------------------------------------------------------------- // --------------------------------------------------------------------- diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 87d891539a02..e35b63113f59 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -599,6 +599,10 @@ + + + + diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index b441bafe975e..0b7c5b943e5e 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -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 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()); } -- cgit v1.2.3-59-g8ed1b