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

This commit is contained in:
TreeHugger Robot
2018-05-17 02:56:42 +00:00
committed by Android (Google) Code Review
5 changed files with 99 additions and 8 deletions

View File

@@ -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";
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------

View File

@@ -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 -->
<!-- ====================================================================== -->

View File

@@ -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++) {

View File

@@ -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();
}

View File

@@ -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());
}