Changes in DeviceIdlecontroller and JobScheduler to support Auto GarageMode.

Changes made in the cl:
1. Let DeviceIdleController take listeners on whether background
maintanence services are active. This currently includes JobScheduler,
SyncManager, DownloadService. Note this is the last known
states reported by these services.

2. In JobScheduler, make the idle threshold and alarm window configurable.
So in the car case, we don't need to wait 71 mins after screen off
to kick off any jobs that require device idle.

-------------------------------------------------------------------

* We are not going to suppress JobScheduler, DownloadService, SyncManager
entirely while user is driving. Because apps may not be working properly if
these services are suspended.

* The jobs that we don't allow to run while driving are the
jobs submitted to JobScheduler that require device idle.
And this is already taken care of, because
screen is ON and JobScheduler will not consider the device to be idle
while driving (unless user turns off the head unit).

* We will need to give the JobScheduler a chance to run the device idle
jobs when car is turned off. This is the scope of GarageMode. If
DownloadService and SyncManager want to run, we will allow them to run
too.

* The headunit is treated as wall power device, so it's always charging.
The charging state will not toggle.

Change-Id: I55b92cf92efd61c48dd6c9b8197c2b68078a4439
This commit is contained in:
Yao Chen
2016-01-13 14:44:36 -08:00
parent 8e25f731d3
commit ca5edbb6b5
7 changed files with 105 additions and 7 deletions

View File

@@ -209,6 +209,7 @@ LOCAL_SRC_FILES += \
core/java/android/os/IBatteryPropertiesRegistrar.aidl \
core/java/android/os/ICancellationSignal.aidl \
core/java/android/os/IDeviceIdleController.aidl \
core/java/android/os/IMaintenanceActivityListener.aidl \
core/java/android/os/IMessenger.aidl \
core/java/android/os/INetworkActivityListener.aidl \
core/java/android/os/INetworkManagementService.aidl \

View File

@@ -16,6 +16,7 @@
package android.os;
import android.os.IMaintenanceActivityListener;
import android.os.UserHandle;
/** @hide */
@@ -37,4 +38,6 @@ interface IDeviceIdleController {
void exitIdle(String reason);
void downloadServiceActive(IBinder token);
void downloadServiceInactive();
boolean registerMaintenanceActivityListener(IMaintenanceActivityListener listener);
void unregisterMaintenanceActivityListener(IMaintenanceActivityListener listener);
}

View File

@@ -0,0 +1,22 @@
/**
* Copyright (c) 2016, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.os;
/** @hide */
oneway interface IMaintenanceActivityListener {
void onMaintenanceActivityChanged(boolean active);
}

View File

@@ -2421,4 +2421,10 @@
<!-- List of comma separated package names for which we the system will not show crash, ANR,
etc. dialogs. -->
<string translatable="false" name="config_appsNotReportingCrashes"></string>
<!-- Inactivity threshold (in milliseconds) used in JobScheduler. JobScheduler will consider
the device to be "idle" after being inactive for this long. -->
<integer name="config_jobSchedulerInactivityIdleThreshold">4260000</integer>
<!-- The alarm window (in milliseconds) that JobScheduler uses to enter the idle state -->
<integer name="config_jobSchedulerIdleWindowSlop">300000</integer>
</resources>

View File

@@ -2250,6 +2250,9 @@
<java-symbol type="integer" name="config_defaultNightMode" />
<java-symbol type="integer" name="config_jobSchedulerInactivityIdleThreshold" />
<java-symbol type="integer" name="config_jobSchedulerIdleWindowSlop" />
<java-symbol type="style" name="Animation.ImmersiveModeConfirmation" />
<java-symbol type="integer" name="config_screen_magnification_multi_tap_adjustment" />

View File

@@ -50,11 +50,13 @@ import android.os.FileUtils;
import android.os.Handler;
import android.os.IBinder;
import android.os.IDeviceIdleController;
import android.os.IMaintenanceActivityListener;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
@@ -206,9 +208,13 @@ public class DeviceIdleController extends SystemService
private boolean mSyncActive;
private boolean mJobsActive;
private boolean mAlarmsActive;
private boolean mReportedMaintenanceActivity;
public final AtomicFile mConfigFile;
private final RemoteCallbackList<IMaintenanceActivityListener> mMaintenanceActivityListeners =
new RemoteCallbackList<IMaintenanceActivityListener>();
/**
* Package names the system has white-listed to opt out of power save restrictions,
* except for device idle mode.
@@ -813,6 +819,7 @@ public class DeviceIdleController extends SystemService
static final int MSG_REPORT_IDLE_OFF = 4;
static final int MSG_REPORT_ACTIVE = 5;
static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 6;
static final int MSG_REPORT_MAINTENANCE_ACTIVITY = 7;
final class MyHandler extends Handler {
MyHandler(Looper looper) {
@@ -902,6 +909,21 @@ public class DeviceIdleController extends SystemService
int uid = msg.arg1;
checkTempAppWhitelistTimeout(uid);
} break;
case MSG_REPORT_MAINTENANCE_ACTIVITY: {
boolean active = (msg.arg1 == 1);
final int size = mMaintenanceActivityListeners.beginBroadcast();
try {
for (int i = 0; i < size; i++) {
try {
mMaintenanceActivityListeners.getBroadcastItem(i)
.onMaintenanceActivityChanged(active);
} catch (RemoteException ignored) {
}
}
} finally {
mMaintenanceActivityListeners.finishBroadcast();
}
} break;
}
}
}
@@ -996,6 +1018,16 @@ public class DeviceIdleController extends SystemService
DeviceIdleController.this.downloadServiceInactive();
}
@Override public boolean registerMaintenanceActivityListener(
IMaintenanceActivityListener listener) {
return DeviceIdleController.this.registerMaintenanceActivityListener(listener);
}
@Override public void unregisterMaintenanceActivityListener(
IMaintenanceActivityListener listener) {
DeviceIdleController.this.unregisterMaintenanceActivityListener(listener);
}
@Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
DeviceIdleController.this.dump(fd, pw, args);
}
@@ -1708,6 +1740,7 @@ public class DeviceIdleController extends SystemService
void downloadServiceActive(IBinder token) {
synchronized (this) {
mDownloadServiceActive = token;
reportMaintenanceActivityIfNeededLocked();
try {
token.linkToDeath(new IBinder.DeathRecipient() {
@Override public void binderDied() {
@@ -1723,6 +1756,7 @@ public class DeviceIdleController extends SystemService
void downloadServiceInactive() {
synchronized (this) {
mDownloadServiceActive = null;
reportMaintenanceActivityIfNeededLocked();
exitMaintenanceEarlyIfNeededLocked();
}
}
@@ -1730,6 +1764,7 @@ public class DeviceIdleController extends SystemService
void setSyncActive(boolean active) {
synchronized (this) {
mSyncActive = active;
reportMaintenanceActivityIfNeededLocked();
if (!active) {
exitMaintenanceEarlyIfNeededLocked();
}
@@ -1739,6 +1774,7 @@ public class DeviceIdleController extends SystemService
void setJobsActive(boolean active) {
synchronized (this) {
mJobsActive = active;
reportMaintenanceActivityIfNeededLocked();
if (!active) {
exitMaintenanceEarlyIfNeededLocked();
}
@@ -1754,6 +1790,30 @@ public class DeviceIdleController extends SystemService
}
}
boolean registerMaintenanceActivityListener(IMaintenanceActivityListener listener) {
synchronized (this) {
mMaintenanceActivityListeners.register(listener);
return mReportedMaintenanceActivity;
}
}
void unregisterMaintenanceActivityListener(IMaintenanceActivityListener listener) {
synchronized (this) {
mMaintenanceActivityListeners.unregister(listener);
}
}
void reportMaintenanceActivityIfNeededLocked() {
boolean active = mJobsActive | mSyncActive | (mDownloadServiceActive != null);
if (active == mReportedMaintenanceActivity) {
return;
}
mReportedMaintenanceActivity = active;
Message msg = mHandler.obtainMessage(MSG_REPORT_MAINTENANCE_ACTIVITY,
mReportedMaintenanceActivity ? 1 : 0, 0);
mHandler.sendMessage(msg);
}
void exitMaintenanceEarlyIfNeededLocked() {
if (mState == STATE_IDLE_MAINTENANCE || mLightState == LIGHT_STATE_IDLE_MAINTENANCE) {
if (mActiveIdleOpCount <= 0 && mDownloadServiceActive == null

View File

@@ -34,14 +34,13 @@ import com.android.server.job.StateChangedListener;
public class IdleController extends StateController {
private static final String TAG = "IdleController";
// Policy: we decide that we're "idle" if the device has been unused /
// screen off or dreaming for at least this long
private static final long INACTIVITY_IDLE_THRESHOLD = 71 * 60 * 1000; // millis; 71 min
private static final long IDLE_WINDOW_SLOP = 5 * 60 * 1000; // 5 minute window, to be nice
private static final String ACTION_TRIGGER_IDLE =
"com.android.server.task.controllers.IdleController.ACTION_TRIGGER_IDLE";
// Policy: we decide that we're "idle" if the device has been unused /
// screen off or dreaming for at least this long
private long mInactivityIdleThreshold;
private long mIdleWindowSlop;
final ArrayList<JobStatus> mTrackedTasks = new ArrayList<JobStatus>();
IdlenessTracker mIdleTracker;
@@ -100,6 +99,10 @@ public class IdleController extends StateController {
* significant state changes occur
*/
private void initIdleStateTracking() {
mInactivityIdleThreshold = mContext.getResources().getInteger(
com.android.internal.R.integer.config_jobSchedulerInactivityIdleThreshold);
mIdleWindowSlop = mContext.getResources().getInteger(
com.android.internal.R.integer.config_jobSchedulerIdleWindowSlop);
mIdleTracker = new IdlenessTracker();
mIdleTracker.startTracking();
}
@@ -168,14 +171,14 @@ public class IdleController extends StateController {
// alarm that will tell us when we have decided the device is
// truly idle.
final long nowElapsed = SystemClock.elapsedRealtime();
final long when = nowElapsed + INACTIVITY_IDLE_THRESHOLD;
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, IDLE_WINDOW_SLOP, mIdleTriggerIntent);
when, mIdleWindowSlop, mIdleTriggerIntent);
} else if (action.equals(ACTION_TRIGGER_IDLE)) {
// idle time starts now. Do not set mIdle if screen is on.
if (!mIdle && !mScreenOn) {