diff options
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. + * + * <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"; + // --------------------------------------------------------------------- // --------------------------------------------------------------------- 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 @@ <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 --> <!-- ====================================================================== --> 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<map.length; i++) { diff --git a/services/core/java/com/android/server/job/JobSchedulerShellCommand.java b/services/core/java/com/android/server/job/JobSchedulerShellCommand.java index 63225f34234f..e3614413121a 100644 --- a/services/core/java/com/android/server/job/JobSchedulerShellCommand.java +++ b/services/core/java/com/android/server/job/JobSchedulerShellCommand.java @@ -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(); } diff --git a/services/core/java/com/android/server/job/controllers/IdleController.java b/services/core/java/com/android/server/job/controllers/IdleController.java index 40d2a3a4a094..644f2c4d6864 100644 --- a/services/core/java/com/android/server/job/controllers/IdleController.java +++ b/services/core/java/com/android/server/job/controllers/IdleController.java @@ -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()); } |