summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2015-03-23 13:29:14 -0700
committerDianne Hackborn <hackbod@google.com>2015-03-24 11:03:49 -0700
commit88e98dfa59e68a860d8c3b462ec03bc0b06d6b5c (patch)
tree10e846a1db4f2307eaa5a32c920e2e9ec0aee79b /services
parente7f931c4505a6bd62e01bef5193dd724571a672b (diff)
downloadframeworks_base-88e98dfa59e68a860d8c3b462ec03bc0b06d6b5c.zip
frameworks_base-88e98dfa59e68a860d8c3b462ec03bc0b06d6b5c.tar.gz
frameworks_base-88e98dfa59e68a860d8c3b462ec03bc0b06d6b5c.tar.bz2
More work on device idle mode.
- There is now an API for people to find out about its state. - Moved DeviceIdleController to be closer to the power manager implementation, since they are closely related. - Job scheduler now knows about idle state and doesn't run jobs while the device is idle. - Battery stats now keeps track of "idling" vs "idle mode". Idling is when we consider the device to be idle, independent of whether we are actually in deep idle mode. This allows us to keep track of longer-term changes independently of cycling in and out of idle mode. - Battery stats also now keeps track of package changes in its daily stats. - Small optimization to network policy manager service to not touch uids that do not have the NETWORK permission. Change-Id: I0b3304fb3722c78cdfdd0c1eada7369ece7cbcf9
Diffstat (limited to 'services')
-rw-r--r--services/core/java/com/android/server/job/JobSchedulerService.java59
-rw-r--r--services/core/java/com/android/server/job/controllers/StateController.java6
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java14
-rw-r--r--services/core/java/com/android/server/power/DeviceIdleController.java (renamed from services/core/java/com/android/server/DeviceIdleController.java)83
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java26
-rw-r--r--services/java/com/android/server/SystemServer.java2
6 files changed, 161 insertions, 29 deletions
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index fe1260d..53bdbea 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -41,6 +41,7 @@ import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -109,21 +110,22 @@ public class JobSchedulerService extends com.android.server.SystemService
* Track Services that have currently active or pending jobs. The index is provided by
* {@link JobStatus#getServiceToken()}
*/
- final List<JobServiceContext> mActiveServices = new ArrayList<JobServiceContext>();
+ final List<JobServiceContext> mActiveServices = new ArrayList<>();
/** List of controllers that will notify this service of updates to jobs. */
List<StateController> mControllers;
/**
* Queue of pending jobs. The JobServiceContext class will receive jobs from this list
* when ready to execute them.
*/
- final ArrayList<JobStatus> mPendingJobs = new ArrayList<JobStatus>();
+ final ArrayList<JobStatus> mPendingJobs = new ArrayList<>();
- final ArrayList<Integer> mStartedUsers = new ArrayList();
+ final ArrayList<Integer> mStartedUsers = new ArrayList<>();
final JobHandler mHandler;
final JobSchedulerStub mJobSchedulerStub;
IBatteryStats mBatteryStats;
+ PowerManager mPowerManager;
/**
* Set to true once we are allowed to run third party apps.
@@ -131,6 +133,11 @@ public class JobSchedulerService extends com.android.server.SystemService
boolean mReadyToRock;
/**
+ * True when in device idle mode, so we don't want to schedule any jobs.
+ */
+ boolean mDeviceIdleMode;
+
+ /**
* Cleans up outstanding jobs when a package is removed. Even if it's being replaced later we
* still clean up. On reinstall the package will have a new uid.
*/
@@ -154,6 +161,8 @@ public class JobSchedulerService extends com.android.server.SystemService
Slog.d(TAG, "Removing jobs for user: " + userId);
}
cancelJobsForUser(userId);
+ } else if (PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(intent.getAction())) {
+ updateIdleMode(mPowerManager != null ? mPowerManager.isDeviceIdleMode() : false);
}
}
};
@@ -199,7 +208,7 @@ public class JobSchedulerService extends com.android.server.SystemService
return outList;
}
- private void cancelJobsForUser(int userHandle) {
+ void cancelJobsForUser(int userHandle) {
List<JobStatus> jobsForUser;
synchronized (mJobs) {
jobsForUser = mJobs.getJobsByUser(userHandle);
@@ -257,6 +266,40 @@ public class JobSchedulerService extends com.android.server.SystemService
}
}
+ void updateIdleMode(boolean enabled) {
+ boolean changed = false;
+ boolean rocking;
+ synchronized (mJobs) {
+ if (mDeviceIdleMode != enabled) {
+ changed = true;
+ }
+ rocking = mReadyToRock;
+ }
+ if (changed) {
+ if (rocking) {
+ for (int i=0; i<mControllers.size(); i++) {
+ mControllers.get(i).deviceIdleModeChanged(enabled);
+ }
+ }
+ synchronized (mJobs) {
+ mDeviceIdleMode = enabled;
+ if (enabled) {
+ // When becoming idle, make sure no jobs are actively running.
+ for (int i=0; i<mActiveServices.size(); i++) {
+ JobServiceContext jsc = mActiveServices.get(i);
+ final JobStatus executing = jsc.getRunningJob();
+ if (executing != null) {
+ jsc.cancelExecutingJob();
+ }
+ }
+ } else {
+ // When coming out of idle, allow thing to start back up.
+ mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
+ }
+ }
+ }
+ }
+
/**
* Initializes the system service.
* <p>
@@ -294,8 +337,10 @@ public class JobSchedulerService extends com.android.server.SystemService
getContext().registerReceiverAsUser(
mBroadcastReceiver, UserHandle.ALL, filter, null, null);
final IntentFilter userFilter = new IntentFilter(Intent.ACTION_USER_REMOVED);
+ userFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
getContext().registerReceiverAsUser(
mBroadcastReceiver, UserHandle.ALL, userFilter, null, null);
+ mPowerManager = (PowerManager)getContext().getSystemService(Context.POWER_SERVICE);
} else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
synchronized (mJobs) {
// Let's go!
@@ -313,6 +358,7 @@ public class JobSchedulerService extends com.android.server.SystemService
for (int i=0; i<jobs.size(); i++) {
JobStatus job = jobs.valueAt(i);
for (int controller=0; controller<mControllers.size(); controller++) {
+ mControllers.get(i).deviceIdleModeChanged(mDeviceIdleMode);
mControllers.get(controller).maybeStartTrackingJob(job);
}
}
@@ -667,6 +713,10 @@ public class JobSchedulerService extends com.android.server.SystemService
*/
private void maybeRunPendingJobsH() {
synchronized (mJobs) {
+ if (mDeviceIdleMode) {
+ // If device is idle, we will not schedule jobs to run.
+ return;
+ }
Iterator<JobStatus> it = mPendingJobs.iterator();
if (DEBUG) {
Slog.d(TAG, "pending queue: " + mPendingJobs.size() + " jobs.");
@@ -878,6 +928,7 @@ public class JobSchedulerService extends com.android.server.SystemService
}
pw.println();
pw.print("mReadyToRock="); pw.println(mReadyToRock);
+ pw.print("mDeviceIdleMode="); pw.println(mDeviceIdleMode);
}
pw.println();
}
diff --git a/services/core/java/com/android/server/job/controllers/StateController.java b/services/core/java/com/android/server/job/controllers/StateController.java
index 7d76fc0..efd1928 100644
--- a/services/core/java/com/android/server/job/controllers/StateController.java
+++ b/services/core/java/com/android/server/job/controllers/StateController.java
@@ -31,12 +31,17 @@ public abstract class StateController {
protected static final boolean DEBUG = false;
protected Context mContext;
protected StateChangedListener mStateChangedListener;
+ protected boolean mDeviceIdleMode;
public StateController(StateChangedListener stateChangedListener, Context context) {
mStateChangedListener = stateChangedListener;
mContext = context;
}
+ public void deviceIdleModeChanged(boolean enabled) {
+ mDeviceIdleMode = enabled;
+ }
+
/**
* Implement the logic here to decide whether a job should be tracked by this controller.
* This logic is put here so the JobManger can be completely agnostic of Controller logic.
@@ -50,5 +55,4 @@ public abstract class StateController {
public abstract void maybeStopTrackingJob(JobStatus jobStatus);
public abstract void dumpControllerState(PrintWriter pw);
-
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 8d46775..5de7d42 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -71,7 +71,9 @@ import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UP
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
+import android.Manifest;
import android.app.ActivityManager;
+import android.app.AppGlobals;
import android.app.IActivityManager;
import android.app.INotificationManager;
import android.app.IProcessObserver;
@@ -83,6 +85,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.content.res.Resources;
@@ -2021,6 +2024,17 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
void updateRulesForUidLocked(int uid) {
if (!isUidValidForRules(uid)) return;
+ // quick check: if this uid doesn't have INTERNET permission, it doesn't have
+ // network access anyway, so it is a waste to mess with it here.
+ final IPackageManager ipm = AppGlobals.getPackageManager();
+ try {
+ if (ipm.checkUidPermission(Manifest.permission.INTERNET, uid)
+ != PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+ } catch (RemoteException e) {
+ }
+
final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
final boolean uidForeground = isUidForegroundLocked(uid);
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/power/DeviceIdleController.java
index 062992d..dd00446 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/power/DeviceIdleController.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.power;
import android.app.AlarmManager;
import android.app.PendingIntent;
@@ -30,12 +30,16 @@ import android.hardware.TriggerEventListener;
import android.hardware.display.DisplayManager;
import android.net.INetworkPolicyManager;
import android.os.Binder;
+import android.os.PowerManager;
+import android.os.PowerManagerInternal;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.util.TimeUtils;
import android.view.Display;
import com.android.internal.app.IBatteryStats;
+import com.android.server.SystemService;
import com.android.server.am.BatteryStatsService;
import java.io.FileDescriptor;
@@ -60,6 +64,11 @@ public class DeviceIdleController extends SystemService {
*/
private static final long DEFAULT_INACTIVE_TIMEOUT = 30*60*1000L;
/**
+ * This is the time, after seeing motion, that we wait after becoming inactive from
+ * that until we start looking for motion again.
+ */
+ private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT = 10*60*1000L;
+ /**
* This is the time, after the inactive timeout elapses, that we will wait looking
* for significant motion until we truly consider the device to be idle.
*/
@@ -94,11 +103,13 @@ public class DeviceIdleController extends SystemService {
private AlarmManager mAlarmManager;
private IBatteryStats mBatteryStats;
+ private PowerManagerInternal mLocalPowerManager;
private INetworkPolicyManager mNetworkPolicyManager;
private DisplayManager mDisplayManager;
private SensorManager mSensorManager;
private Sensor mSigMotionSensor;
private PendingIntent mAlarmIntent;
+ private Intent mIdleIntent;
private Display mCurDisplay;
private boolean mScreenOn;
private boolean mCharging;
@@ -124,6 +135,7 @@ public class DeviceIdleController extends SystemService {
private int mState;
+ private long mInactiveTimeout;
private long mNextAlarmTime;
private long mNextIdlePendingDelay;
private long mNextIdleDelay;
@@ -181,6 +193,7 @@ public class DeviceIdleController extends SystemService {
synchronized (this) {
mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
mBatteryStats = BatteryStatsService.getService();
+ mLocalPowerManager = getLocalService(PowerManagerInternal.class);
mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface(
ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
mDisplayManager = (DisplayManager) getContext().getSystemService(
@@ -193,6 +206,9 @@ public class DeviceIdleController extends SystemService {
.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0);
+ mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
+ mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
filter.addAction(ACTION_STEP_IDLE_STATE);
@@ -205,6 +221,7 @@ public class DeviceIdleController extends SystemService {
// a battery update the next time the level drops.
mCharging = true;
mState = STATE_ACTIVE;
+ mInactiveTimeout = DEFAULT_INACTIVE_TIMEOUT;
updateDisplayLocked();
}
@@ -238,12 +255,17 @@ public class DeviceIdleController extends SystemService {
void becomeActiveLocked() {
if (mState != STATE_ACTIVE) {
+ mLocalPowerManager.setDeviceIdleMode(false);
try {
mNetworkPolicyManager.setDeviceIdleMode(false);
mBatteryStats.noteDeviceIdleMode(false, true, false);
} catch (RemoteException e) {
}
+ if (mState == STATE_IDLE) {
+ getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
+ }
mState = STATE_ACTIVE;
+ mInactiveTimeout = DEFAULT_INACTIVE_TIMEOUT;
mNextIdlePendingDelay = 0;
mNextIdleDelay = 0;
cancelAlarmLocked();
@@ -256,7 +278,9 @@ public class DeviceIdleController extends SystemService {
// Screen has turned off; we are now going to become inactive and start
// waiting to see if we will ultimately go idle.
mState = STATE_INACTIVE;
- scheduleAlarmLocked(DEFAULT_INACTIVE_TIMEOUT, false);
+ mNextIdlePendingDelay = 0;
+ mNextIdleDelay = 0;
+ scheduleAlarmLocked(mInactiveTimeout, false);
}
}
@@ -283,11 +307,13 @@ public class DeviceIdleController extends SystemService {
mNextIdleDelay = DEFAULT_MAX_IDLE_TIMEOUT;
}
mState = STATE_IDLE;
+ mLocalPowerManager.setDeviceIdleMode(true);
try {
mNetworkPolicyManager.setDeviceIdleMode(true);
mBatteryStats.noteDeviceIdleMode(true, false, false);
} catch (RemoteException e) {
}
+ getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
break;
case STATE_IDLE:
// We have been idling long enough, now it is time to do some work.
@@ -297,11 +323,13 @@ public class DeviceIdleController extends SystemService {
mNextIdlePendingDelay = DEFAULT_MAX_IDLE_PENDING_TIMEOUT;
}
mState = STATE_IDLE_PENDING;
+ mLocalPowerManager.setDeviceIdleMode(false);
try {
mNetworkPolicyManager.setDeviceIdleMode(false);
mBatteryStats.noteDeviceIdleMode(false, false, false);
} catch (RemoteException e) {
}
+ getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
break;
}
}
@@ -313,13 +341,18 @@ public class DeviceIdleController extends SystemService {
// state to wait again for no motion. Note that we only monitor for significant
// motion after moving out of the inactive state, so no need to worry about that.
if (mState != STATE_ACTIVE) {
- mState = STATE_INACTIVE;
+ mLocalPowerManager.setDeviceIdleMode(false);
try {
mNetworkPolicyManager.setDeviceIdleMode(false);
mBatteryStats.noteDeviceIdleMode(false, false, true);
} catch (RemoteException e) {
}
- stepIdleStateLocked();
+ if (mState == STATE_IDLE) {
+ getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
+ }
+ mState = STATE_ACTIVE;
+ mInactiveTimeout = DEFAULT_MOTION_INACTIVE_TIMEOUT;
+ becomeInactiveIfAppropriateLocked();
}
}
@@ -399,26 +432,30 @@ public class DeviceIdleController extends SystemService {
}
}
- pw.print(" mSigMotionSensor="); pw.println(mSigMotionSensor);
- pw.print(" mCurDisplay="); pw.println(mCurDisplay);
- pw.print(" mScreenOn="); pw.println(mScreenOn);
- pw.print(" mCharging="); pw.println(mCharging);
- pw.print(" mSigMotionActive="); pw.println(mSigMotionActive);
- pw.print(" mState="); pw.println(stateToString(mState));
- if (mNextAlarmTime != 0) {
- pw.print(" mNextAlarmTime=");
- TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw);
- pw.println();
- }
- if (mNextIdlePendingDelay != 0) {
- pw.print(" mNextIdlePendingDelay=");
- TimeUtils.formatDuration(mNextIdlePendingDelay, pw);
- pw.println();
- }
- if (mNextIdleDelay != 0) {
- pw.print(" mNextIdleDelay=");
- TimeUtils.formatDuration(mNextIdleDelay, pw);
+ synchronized (this) {
+ pw.print(" mSigMotionSensor="); pw.println(mSigMotionSensor);
+ pw.print(" mCurDisplay="); pw.println(mCurDisplay);
+ pw.print(" mScreenOn="); pw.println(mScreenOn);
+ pw.print(" mCharging="); pw.println(mCharging);
+ pw.print(" mSigMotionActive="); pw.println(mSigMotionActive);
+ pw.print(" mState="); pw.println(stateToString(mState));
+ pw.print(" mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw);
pw.println();
+ if (mNextAlarmTime != 0) {
+ pw.print(" mNextAlarmTime=");
+ TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw);
+ pw.println();
+ }
+ if (mNextIdlePendingDelay != 0) {
+ pw.print(" mNextIdlePendingDelay=");
+ TimeUtils.formatDuration(mNextIdlePendingDelay, pw);
+ pw.println();
+ }
+ if (mNextIdleDelay != 0) {
+ pw.print(" mNextIdleDelay=");
+ TimeUtils.formatDuration(mNextIdleDelay, pw);
+ pw.println();
+ }
}
}
}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 9e373b7..33b451d 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -420,6 +420,9 @@ public final class PowerManagerService extends SystemService
// True if the battery level is currently considered low.
private boolean mBatteryLevelLow;
+ // True if we are currently in device idle mode.
+ private boolean mDeviceIdleMode;
+
// True if theater mode is enabled
private boolean mTheaterModeEnabled;
@@ -2178,6 +2181,12 @@ public final class PowerManagerService extends SystemService
}
}
+ private boolean isDeviceIdleModeInternal() {
+ synchronized (mLock) {
+ return mDeviceIdleMode;
+ }
+ }
+
private void handleBatteryStateChangedLocked() {
mDirty |= DIRTY_BATTERY_STATE;
updatePowerStateLocked();
@@ -3050,6 +3059,16 @@ public final class PowerManagerService extends SystemService
}
}
+ @Override // Binder call
+ public boolean isDeviceIdleMode() {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ return isDeviceIdleModeInternal();
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
/**
* Reboots the device.
*
@@ -3295,5 +3314,12 @@ public final class PowerManagerService extends SystemService
mLowPowerModeListeners.add(listener);
}
}
+
+ @Override
+ public void setDeviceIdleMode(boolean enabled) {
+ synchronized (mLock) {
+ mDeviceIdleMode = enabled;
+ }
+ }
}
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index ae2c54b..afce948 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -66,7 +66,6 @@ import com.android.server.lights.LightsService;
import com.android.server.media.MediaRouterService;
import com.android.server.media.MediaSessionService;
import com.android.server.media.projection.MediaProjectionManagerService;
-import com.android.server.MidiService;
import com.android.server.net.NetworkPolicyManagerService;
import com.android.server.net.NetworkStatsService;
import com.android.server.notification.NotificationManagerService;
@@ -76,6 +75,7 @@ import com.android.server.pm.Installer;
import com.android.server.pm.LauncherAppsService;
import com.android.server.pm.PackageManagerService;
import com.android.server.pm.UserManagerService;
+import com.android.server.power.DeviceIdleController;
import com.android.server.power.PowerManagerService;
import com.android.server.power.ShutdownThread;
import com.android.server.restrictions.RestrictionsManagerService;