summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Yao Chen <yaochen@google.com> 2016-01-13 14:44:36 -0800
committer Yao Chen <yaochen@google.com> 2016-01-15 12:06:30 -0800
commitca5edbb6b5300e07a5f7bfbec36f08df65d8f6e7 (patch)
treef546e49f84095fc56ee48349d9f397c3fd6eca96
parent8e25f731d32c8623b5518be1b1529faeebffa1e8 (diff)
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
-rw-r--r--Android.mk1
-rw-r--r--core/java/android/os/IDeviceIdleController.aidl3
-rw-r--r--core/java/android/os/IMaintenanceActivityListener.aidl22
-rw-r--r--core/res/res/values/config.xml6
-rw-r--r--core/res/res/values/symbols.xml3
-rw-r--r--services/core/java/com/android/server/DeviceIdleController.java60
-rw-r--r--services/core/java/com/android/server/job/controllers/IdleController.java17
7 files changed, 105 insertions, 7 deletions
diff --git a/Android.mk b/Android.mk
index c1c74ea04e55..ea7a12e3051e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -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 \
diff --git a/core/java/android/os/IDeviceIdleController.aidl b/core/java/android/os/IDeviceIdleController.aidl
index 7a1a6a29ad12..838279bf38f9 100644
--- a/core/java/android/os/IDeviceIdleController.aidl
+++ b/core/java/android/os/IDeviceIdleController.aidl
@@ -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);
}
diff --git a/core/java/android/os/IMaintenanceActivityListener.aidl b/core/java/android/os/IMaintenanceActivityListener.aidl
new file mode 100644
index 000000000000..6a2581faaa58
--- /dev/null
+++ b/core/java/android/os/IMaintenanceActivityListener.aidl
@@ -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);
+}
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 58c4046dde82..b863f394a13b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -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>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index a4654e8a710f..d5f7519eaa93 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -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" />
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 8d707d610ae0..3fb957c2964e 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -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
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 92df851bb687..fe5e8c94bc3e 100644
--- a/services/core/java/com/android/server/job/controllers/IdleController.java
+++ b/services/core/java/com/android/server/job/controllers/IdleController.java
@@ -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) {