summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Makoto Onuki <omakoto@google.com> 2018-02-07 10:49:01 -0800
committer Makoto Onuki <omakoto@google.com> 2018-02-07 11:38:11 -0800
commit3f7be62d316cf366fabca64b718f17982c8f436d (patch)
tree6d62753bd21aca14351e3f800714af5dba1545f9
parentbcaeb104c2d678a1d35aed925f6b9570223216b0 (diff)
Retry: JobScheduler to use UID active state for job exemption
This is a second try for I134ac3d84a26309dab56ab6cbb271de626acdf7d. Apparently alarms are firing even before PHASE_SYSTEM_SERVICES_READY, so add more null checks. Test: Boot on taimen. Test: atest CtsAlarmManagerTestCases Test: atest CtsJobSchedulerTestCases Test: atest CtsBatterySavingTestCases Test: atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java Change-Id: I4b2a5af04e4d78c996e73da0621047da7a7bff39
-rw-r--r--core/java/android/app/ActivityManagerInternal.java5
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java33
-rw-r--r--services/core/java/com/android/server/AppStateTracker.java (renamed from services/core/java/com/android/server/ForceAppStandbyTracker.java)80
-rw-r--r--services/core/java/com/android/server/DeviceIdleController.java8
-rw-r--r--services/core/java/com/android/server/StatLogger.java11
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java8
-rw-r--r--services/core/java/com/android/server/job/JobSchedulerService.java29
-rw-r--r--services/core/java/com/android/server/job/controllers/BackgroundJobsController.java38
-rw-r--r--services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java (renamed from services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java)99
9 files changed, 192 insertions, 119 deletions
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 5ee7edee9db7..4626cb274c0e 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -348,4 +348,9 @@ public abstract class ActivityManagerInternal {
* Returns is the caller has the same uid as the Recents component
*/
public abstract boolean isCallerRecents(int callingUid);
+
+ /**
+ * Whether an UID is active or idle.
+ */
+ public abstract boolean isUidActive(int uid);
}
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 17c617c095d8..355da2df87a9 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -98,7 +98,8 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.LocalLog;
-import com.android.server.ForceAppStandbyTracker.Listener;
+import com.android.internal.util.Preconditions;
+import com.android.server.AppStateTracker.Listener;
/**
* Alarm manager implementaion.
@@ -249,7 +250,7 @@ class AlarmManagerService extends SystemService {
private final SparseArray<AlarmManager.AlarmClockInfo> mHandlerSparseAlarmClockArray =
new SparseArray<>();
- private final ForceAppStandbyTracker mForceAppStandbyTracker;
+ private AppStateTracker mAppStateTracker;
private boolean mAppStandbyParole;
private ArrayMap<Pair<String, Integer>, Long> mLastAlarmDeliveredForPackage = new ArrayMap<>();
@@ -707,9 +708,6 @@ class AlarmManagerService extends SystemService {
super(context);
mConstants = new Constants(mHandler);
- mForceAppStandbyTracker = ForceAppStandbyTracker.getInstance(context);
- mForceAppStandbyTracker.addListener(mForceAppStandbyListener);
-
publishLocalService(AlarmManagerInternal.class, new LocalService());
}
@@ -1329,13 +1327,15 @@ class AlarmManagerService extends SystemService {
@Override
public void onBootPhase(int phase) {
if (phase == PHASE_SYSTEM_SERVICES_READY) {
- mForceAppStandbyTracker.start();
mConstants.start(getContext().getContentResolver());
mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
mLocalDeviceIdleController
= LocalServices.getService(DeviceIdleController.LocalService.class);
mUsageStatsManagerInternal = LocalServices.getService(UsageStatsManagerInternal.class);
mUsageStatsManagerInternal.addAppIdleStateChangeListener(new AppStandbyTracker());
+
+ mAppStateTracker = LocalServices.getService(AppStateTracker.class);
+ mAppStateTracker.addListener(mForceAppStandbyListener);
}
}
@@ -1729,7 +1729,8 @@ class AlarmManagerService extends SystemService {
// timing restrictions.
} else if (workSource == null && (callingUid < Process.FIRST_APPLICATION_UID
|| callingUid == mSystemUiUid
- || mForceAppStandbyTracker.isUidPowerSaveWhitelisted(callingUid))) {
+ || (mAppStateTracker != null
+ && mAppStateTracker.isUidPowerSaveWhitelisted(callingUid)))) {
flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
flags &= ~AlarmManager.FLAG_ALLOW_WHILE_IDLE;
}
@@ -1812,8 +1813,10 @@ class AlarmManagerService extends SystemService {
mConstants.dump(pw);
pw.println();
- mForceAppStandbyTracker.dump(pw, " ");
- pw.println();
+ if (mAppStateTracker != null) {
+ mAppStateTracker.dump(pw, " ");
+ pw.println();
+ }
pw.println(" App Standby Parole: " + mAppStandbyParole);
pw.println();
@@ -2161,8 +2164,10 @@ class AlarmManagerService extends SystemService {
mConstants.dumpProto(proto, AlarmManagerServiceProto.SETTINGS);
- mForceAppStandbyTracker.dumpProto(proto,
- AlarmManagerServiceProto.FORCE_APP_STANDBY_TRACKER);
+ if (mAppStateTracker != null) {
+ mAppStateTracker.dumpProto(proto,
+ AlarmManagerServiceProto.FORCE_APP_STANDBY_TRACKER);
+ }
proto.write(AlarmManagerServiceProto.IS_INTERACTIVE, mInteractive);
if (!mInteractive) {
@@ -2942,7 +2947,7 @@ class AlarmManagerService extends SystemService {
}
final String sourcePackage = alarm.sourcePackage;
final int sourceUid = alarm.creatorUid;
- return mForceAppStandbyTracker.areAlarmsRestricted(sourceUid, sourcePackage,
+ return mAppStateTracker.areAlarmsRestricted(sourceUid, sourcePackage,
allowWhileIdle);
}
@@ -2955,7 +2960,7 @@ class AlarmManagerService extends SystemService {
private long getWhileIdleMinIntervalLocked(int uid) {
final boolean dozing = mPendingIdleUntil != null;
- final boolean ebs = mForceAppStandbyTracker.isForceAllAppsStandbyEnabled();
+ final boolean ebs = mAppStateTracker.isForceAllAppsStandbyEnabled();
if (!dozing && !ebs) {
return mConstants.ALLOW_WHILE_IDLE_SHORT_TIME;
}
@@ -4133,7 +4138,7 @@ class AlarmManagerService extends SystemService {
if (allowWhileIdle) {
// Record the last time this uid handled an ALLOW_WHILE_IDLE alarm.
mLastAllowWhileIdleDispatch.put(alarm.creatorUid, nowELAPSED);
- if (mForceAppStandbyTracker.isUidInForeground(alarm.creatorUid)) {
+ if (mAppStateTracker.isUidInForeground(alarm.creatorUid)) {
mUseAllowWhileIdleShortTime.put(alarm.creatorUid, true);
} else {
mUseAllowWhileIdleShortTime.put(alarm.creatorUid, false);
diff --git a/services/core/java/com/android/server/ForceAppStandbyTracker.java b/services/core/java/com/android/server/AppStateTracker.java
index 100680df637d..51dff56d3c11 100644
--- a/services/core/java/com/android/server/ForceAppStandbyTracker.java
+++ b/services/core/java/com/android/server/AppStateTracker.java
@@ -54,7 +54,6 @@ import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
-import com.android.server.DeviceIdleController.LocalService;
import com.android.server.ForceAppStandbyTrackerProto.ExemptedPackage;
import com.android.server.ForceAppStandbyTrackerProto.RunAnyInBackgroundRestrictedPackages;
@@ -73,14 +72,14 @@ import java.util.List;
* TODO: Make it a LocalService.
*
* Test:
- atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
+ atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
*/
-public class ForceAppStandbyTracker {
+public class AppStateTracker {
private static final String TAG = "ForceAppStandbyTracker";
private static final boolean DEBUG = true;
- @GuardedBy("ForceAppStandbyTracker.class")
- private static ForceAppStandbyTracker sInstance;
+ @GuardedBy("AppStateTracker.class")
+ private static AppStateTracker sInstance;
private final Object mLock = new Object();
private final Context mContext;
@@ -89,6 +88,7 @@ public class ForceAppStandbyTracker {
static final int TARGET_OP = AppOpsManager.OP_RUN_ANY_IN_BACKGROUND;
IActivityManager mIActivityManager;
+ ActivityManagerInternal mActivityManagerInternal;
AppOpsManager mAppOpsManager;
IAppOpsService mAppOpsService;
PowerManagerInternal mPowerManagerInternal;
@@ -172,6 +172,9 @@ public class ForceAppStandbyTracker {
int EXEMPT_CHANGED = 6;
int FORCE_ALL_CHANGED = 7;
int FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 8;
+
+ int IS_UID_ACTIVE_CACHED = 9;
+ int IS_UID_ACTIVE_RAW = 10;
}
private final StatLogger mStatLogger = new StatLogger(new String[] {
@@ -184,6 +187,9 @@ public class ForceAppStandbyTracker {
"EXEMPT_CHANGED",
"FORCE_ALL_CHANGED",
"FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED",
+
+ "IS_UID_ACTIVE_CACHED",
+ "IS_UID_ACTIVE_RAW",
});
@VisibleForTesting
@@ -249,7 +255,7 @@ public class ForceAppStandbyTracker {
/**
* This is called when the OP_RUN_ANY_IN_BACKGROUND appops changed for a package.
*/
- private void onRunAnyAppOpsChanged(ForceAppStandbyTracker sender,
+ private void onRunAnyAppOpsChanged(AppStateTracker sender,
int uid, @NonNull String packageName) {
updateJobsForUidPackage(uid, packageName);
@@ -264,14 +270,14 @@ public class ForceAppStandbyTracker {
/**
* This is called when the foreground state changed for a UID.
*/
- private void onUidForegroundStateChanged(ForceAppStandbyTracker sender, int uid) {
+ private void onUidForegroundStateChanged(AppStateTracker sender, int uid) {
onUidForeground(uid, sender.isUidInForeground(uid));
}
/**
* This is called when the active/idle state changed for a UID.
*/
- private void onUidActiveStateChanged(ForceAppStandbyTracker sender, int uid) {
+ private void onUidActiveStateChanged(AppStateTracker sender, int uid) {
updateJobsForUid(uid);
if (sender.isUidActive(uid)) {
@@ -282,7 +288,7 @@ public class ForceAppStandbyTracker {
/**
* This is called when an app-id(s) is removed from the power save whitelist.
*/
- private void onPowerSaveUnwhitelisted(ForceAppStandbyTracker sender) {
+ private void onPowerSaveUnwhitelisted(AppStateTracker sender) {
updateAllJobs();
unblockAllUnrestrictedAlarms();
}
@@ -291,14 +297,14 @@ public class ForceAppStandbyTracker {
* This is called when the power save whitelist changes, excluding the
* {@link #onPowerSaveUnwhitelisted} case.
*/
- private void onPowerSaveWhitelistedChanged(ForceAppStandbyTracker sender) {
+ private void onPowerSaveWhitelistedChanged(AppStateTracker sender) {
updateAllJobs();
}
/**
* This is called when the temp whitelist changes.
*/
- private void onTempPowerSaveWhitelistChanged(ForceAppStandbyTracker sender) {
+ private void onTempPowerSaveWhitelistChanged(AppStateTracker sender) {
// TODO This case happens rather frequently; consider optimizing and update jobs
// only for affected app-ids.
@@ -311,7 +317,7 @@ public class ForceAppStandbyTracker {
/**
* This is called when the EXEMPT bucket is updated.
*/
- private void onExemptChanged(ForceAppStandbyTracker sender) {
+ private void onExemptChanged(AppStateTracker sender) {
// This doesn't happen very often, so just re-evaluate all jobs / alarms.
updateAllJobs();
unblockAllUnrestrictedAlarms();
@@ -320,7 +326,7 @@ public class ForceAppStandbyTracker {
/**
* This is called when the global "force all apps standby" flag changes.
*/
- private void onForceAllAppsStandbyChanged(ForceAppStandbyTracker sender) {
+ private void onForceAllAppsStandbyChanged(AppStateTracker sender) {
updateAllJobs();
if (!sender.isForceAllAppsStandbyEnabled()) {
@@ -377,30 +383,15 @@ public class ForceAppStandbyTracker {
}
}
- @VisibleForTesting
- ForceAppStandbyTracker(Context context, Looper looper) {
+ public AppStateTracker(Context context, Looper looper) {
mContext = context;
mHandler = new MyHandler(looper);
}
- private ForceAppStandbyTracker(Context context) {
- this(context, FgThread.get().getLooper());
- }
-
- /**
- * Get the singleton instance.
- */
- public static synchronized ForceAppStandbyTracker getInstance(Context context) {
- if (sInstance == null) {
- sInstance = new ForceAppStandbyTracker(context);
- }
- return sInstance;
- }
-
/**
* Call it when the system is ready.
*/
- public void start() {
+ public void onSystemServicesReady() {
synchronized (mLock) {
if (mStarted) {
return;
@@ -408,6 +399,7 @@ public class ForceAppStandbyTracker {
mStarted = true;
mIActivityManager = Preconditions.checkNotNull(injectIActivityManager());
+ mActivityManagerInternal = Preconditions.checkNotNull(injectActivityManagerInternal());
mAppOpsManager = Preconditions.checkNotNull(injectAppOpsManager());
mAppOpsService = Preconditions.checkNotNull(injectIAppOpsService());
mPowerManagerInternal = Preconditions.checkNotNull(injectPowerManagerInternal());
@@ -475,6 +467,11 @@ public class ForceAppStandbyTracker {
}
@VisibleForTesting
+ ActivityManagerInternal injectActivityManagerInternal() {
+ return LocalServices.getService(ActivityManagerInternal.class);
+ }
+
+ @VisibleForTesting
PowerManagerInternal injectPowerManagerInternal() {
return LocalServices.getService(PowerManagerInternal.class);
}
@@ -799,7 +796,7 @@ public class ForceAppStandbyTracker {
return;
}
}
- final ForceAppStandbyTracker sender = ForceAppStandbyTracker.this;
+ final AppStateTracker sender = AppStateTracker.this;
long start = mStatLogger.getTime();
switch (msg.what) {
@@ -1089,11 +1086,11 @@ public class ForceAppStandbyTracker {
}
/**
- * @return whether a UID is in active or not.
+ * @return whether a UID is in active or not *based on cached information.*
*
* Note this information is based on the UID proc state callback, meaning it's updated
* asynchronously and may subtly be stale. If the fresh data is needed, use
- * {@link ActivityManagerInternal#getUidProcessState} instead.
+ * {@link #isUidActiveSynced} instead.
*/
public boolean isUidActive(int uid) {
if (UserHandle.isCore(uid)) {
@@ -1105,6 +1102,23 @@ public class ForceAppStandbyTracker {
}
/**
+ * @return whether a UID is in active or not *right now.*
+ *
+ * This gives the fresh information, but may access the activity manager so is slower.
+ */
+ public boolean isUidActiveSynced(int uid) {
+ if (isUidActive(uid)) { // Use the cached one first.
+ return true;
+ }
+ final long start = mStatLogger.getTime();
+
+ final boolean ret = mActivityManagerInternal.isUidActive(uid);
+ mStatLogger.logDurationStat(Stats.IS_UID_ACTIVE_RAW, start);
+
+ return ret;
+ }
+
+ /**
* @return whether a UID is in the foreground or not.
*
* Note this information is based on the UID proc state callback, meaning it's updated
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 44974ffd3509..2b3c5852ac8b 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -82,6 +82,7 @@ import com.android.internal.os.AtomicFile;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.server.am.BatteryStatsService;
import com.android.server.net.NetworkPolicyManagerInternal;
@@ -128,6 +129,7 @@ public class DeviceIdleController extends SystemService
private Intent mIdleIntent;
private Intent mLightIdleIntent;
private AnyMotionDetector mAnyMotionDetector;
+ private final AppStateTracker mAppStateTracker;
private boolean mLightEnabled;
private boolean mDeepEnabled;
private boolean mForceIdle;
@@ -1371,6 +1373,8 @@ public class DeviceIdleController extends SystemService
super(context);
mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml"));
mHandler = new MyHandler(BackgroundThread.getHandler().getLooper());
+ mAppStateTracker = new AppStateTracker(context, FgThread.get().getLooper());
+ LocalServices.addService(AppStateTracker.class, mAppStateTracker);
}
boolean isAppOnWhitelistInternal(int appid) {
@@ -1501,6 +1505,8 @@ public class DeviceIdleController extends SystemService
(PowerManager) getContext().getSystemService(Context.POWER_SERVICE),
mHandler, mSensorManager, this, angleThreshold);
+ mAppStateTracker.onSystemServicesReady();
+
mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_FOREGROUND);
@@ -2615,7 +2621,7 @@ public class DeviceIdleController extends SystemService
}
private void passWhiteListToForceAppStandbyTrackerLocked() {
- ForceAppStandbyTracker.getInstance(getContext()).setPowerSaveWhitelistAppIds(
+ mAppStateTracker.setPowerSaveWhitelistAppIds(
mPowerSaveWhitelistExceptIdleAppIdArray,
mTempWhitelistAppIdArray);
}
diff --git a/services/core/java/com/android/server/StatLogger.java b/services/core/java/com/android/server/StatLogger.java
index f2117314df00..0e6f5e2338c7 100644
--- a/services/core/java/com/android/server/StatLogger.java
+++ b/services/core/java/com/android/server/StatLogger.java
@@ -17,6 +17,7 @@
package com.android.server;
import android.os.SystemClock;
+import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
@@ -33,6 +34,8 @@ import java.io.PrintWriter;
* @hide
*/
public class StatLogger {
+ private static final String TAG = "StatLogger";
+
private final Object mLock = new Object();
private final int SIZE;
@@ -66,8 +69,12 @@ public class StatLogger {
*/
public void logDurationStat(int eventId, long start) {
synchronized (mLock) {
- mCountStats[eventId]++;
- mDurationStats[eventId] += (getTime() - start);
+ if (eventId >= 0 && eventId < SIZE) {
+ mCountStats[eventId]++;
+ mDurationStats[eventId] += (getTime() - start);
+ } else {
+ Slog.wtf(TAG, "Invalid event ID: " + eventId);
+ }
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index a6c4fc952839..9db4e2b4e4c2 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -25863,6 +25863,14 @@ public class ActivityManagerService extends IActivityManager.Stub
public boolean isCallerRecents(int callingUid) {
return getRecentTasks().isCallerRecents(callingUid);
}
+
+ @Override
+ public boolean isUidActive(int uid) {
+ synchronized (ActivityManagerService.this) {
+ final UidRecord uidRec = mActiveUids.get(uid);
+ return (uidRec != null) && !uidRec.idle;
+ }
+ }
}
/**
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 401c05e80307..47a4fb24201c 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -40,7 +40,6 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.Intent.UriFlags;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
@@ -79,7 +78,7 @@ import com.android.internal.util.DumpUtils;
import com.android.internal.util.Preconditions;
import com.android.server.DeviceIdleController;
import com.android.server.FgThread;
-import com.android.server.ForceAppStandbyTracker;
+import com.android.server.AppStateTracker;
import com.android.server.LocalServices;
import com.android.server.job.JobSchedulerServiceDumpProto.ActiveJob;
import com.android.server.job.JobSchedulerServiceDumpProto.PendingJob;
@@ -184,7 +183,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
ActivityManagerInternal mActivityManagerInternal;
IBatteryStats mBatteryStats;
DeviceIdleController.LocalService mLocalDeviceIdleController;
- final ForceAppStandbyTracker mForceAppStandbyTracker;
+ AppStateTracker mAppStateTracker;
/**
* Set to true once we are allowed to run third party apps.
@@ -787,20 +786,13 @@ public final class JobSchedulerService extends com.android.server.SystemService
}
/**
- * Return whether an UID is in the foreground or not.
+ * Return whether an UID is active or idle.
*/
- private boolean isUidInForeground(int uid) {
- synchronized (mLock) {
- if (mUidPriorityOverride.get(uid, 0) > 0) {
- return true;
- }
- }
- // Note UID observer may not be called in time, so we always check with the AM.
- return mActivityManagerInternal.getUidProcessState(uid)
- <= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+ private boolean isUidActive(int uid) {
+ return mAppStateTracker.isUidActiveSynced(uid);
}
- private final Predicate<Integer> mIsUidInForegroundPredicate = this::isUidInForeground;
+ private final Predicate<Integer> mIsUidActivePredicate = this::isUidActive;
public int scheduleAsPackage(JobInfo job, JobWorkItem work, int uId, String packageName,
int userId, String tag) {
@@ -826,7 +818,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
// If any of work item is enqueued when the source is in the foreground,
// exempt the entire job.
- toCancel.maybeAddForegroundExemption(mIsUidInForegroundPredicate);
+ toCancel.maybeAddForegroundExemption(mIsUidActivePredicate);
return JobScheduler.RESULT_SUCCESS;
}
@@ -838,7 +830,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
// Note if it's a sync job, this method is called on the handler so it's not exactly
// the state when requestSync() was called, but that should be fine because of the
// 1 minute foreground grace period.
- jobStatus.maybeAddForegroundExemption(mIsUidInForegroundPredicate);
+ jobStatus.maybeAddForegroundExemption(mIsUidActivePredicate);
if (DEBUG) Slog.d(TAG, "SCHEDULE: " + jobStatus.toShortString());
// Jobs on behalf of others don't apply to the per-app job cap
@@ -1123,8 +1115,6 @@ public final class JobSchedulerService extends com.android.server.SystemService
mDeviceIdleJobsController = DeviceIdleJobsController.get(this);
mControllers.add(mDeviceIdleJobsController);
- mForceAppStandbyTracker = ForceAppStandbyTracker.getInstance(context);
-
// If the job store determined that it can't yet reschedule persisted jobs,
// we need to start watching the clock.
if (!mJobs.jobTimesInflatedValid()) {
@@ -1185,7 +1175,8 @@ public final class JobSchedulerService extends com.android.server.SystemService
if (PHASE_SYSTEM_SERVICES_READY == phase) {
mConstants.start(getContext().getContentResolver());
- mForceAppStandbyTracker.start();
+ mAppStateTracker = Preconditions.checkNotNull(
+ LocalServices.getService(AppStateTracker.class));
// Register br for package removals and user removals.
final IntentFilter filter = new IntentFilter();
diff --git a/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java b/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java
index 5eb77000a4f1..e8057fbd4150 100644
--- a/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java
+++ b/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java
@@ -22,8 +22,10 @@ import android.os.UserHandle;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
-import com.android.server.ForceAppStandbyTracker;
-import com.android.server.ForceAppStandbyTracker.Listener;
+import com.android.internal.util.Preconditions;
+import com.android.server.AppStateTracker;
+import com.android.server.AppStateTracker.Listener;
+import com.android.server.LocalServices;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.JobStore;
import com.android.server.job.StateControllerProto;
@@ -42,8 +44,7 @@ public final class BackgroundJobsController extends StateController {
private final JobSchedulerService mJobSchedulerService;
- private final ForceAppStandbyTracker mForceAppStandbyTracker;
-
+ private final AppStateTracker mAppStateTracker;
public static BackgroundJobsController get(JobSchedulerService service) {
synchronized (sCreationLock) {
@@ -59,10 +60,9 @@ public final class BackgroundJobsController extends StateController {
super(service, context, lock);
mJobSchedulerService = service;
- mForceAppStandbyTracker = ForceAppStandbyTracker.getInstance(context);
-
- mForceAppStandbyTracker.addListener(mForceAppStandbyListener);
- mForceAppStandbyTracker.start();
+ mAppStateTracker = Preconditions.checkNotNull(
+ LocalServices.getService(AppStateTracker.class));
+ mAppStateTracker.addListener(mForceAppStandbyListener);
}
@Override
@@ -79,7 +79,7 @@ public final class BackgroundJobsController extends StateController {
public void dumpControllerStateLocked(final PrintWriter pw, final int filterUid) {
pw.println("BackgroundJobsController");
- mForceAppStandbyTracker.dump(pw, "");
+ mAppStateTracker.dump(pw, "");
pw.println("Job state:");
mJobSchedulerService.getJobStore().forEachJob((jobStatus) -> {
@@ -92,16 +92,16 @@ public final class BackgroundJobsController extends StateController {
jobStatus.printUniqueId(pw);
pw.print(" from ");
UserHandle.formatUid(pw, uid);
- pw.print(mForceAppStandbyTracker.isUidActive(uid) ? " active" : " idle");
- if (mForceAppStandbyTracker.isUidPowerSaveWhitelisted(uid) ||
- mForceAppStandbyTracker.isUidTempPowerSaveWhitelisted(uid)) {
+ pw.print(mAppStateTracker.isUidActive(uid) ? " active" : " idle");
+ if (mAppStateTracker.isUidPowerSaveWhitelisted(uid) ||
+ mAppStateTracker.isUidTempPowerSaveWhitelisted(uid)) {
pw.print(", whitelisted");
}
pw.print(": ");
pw.print(sourcePkg);
pw.print(" [RUN_ANY_IN_BACKGROUND ");
- pw.print(mForceAppStandbyTracker.isRunAnyInBackgroundAppOpsAllowed(uid, sourcePkg)
+ pw.print(mAppStateTracker.isRunAnyInBackgroundAppOpsAllowed(uid, sourcePkg)
? "allowed]" : "disallowed]");
if ((jobStatus.satisfiedConstraints
@@ -118,7 +118,7 @@ public final class BackgroundJobsController extends StateController {
final long token = proto.start(fieldId);
final long mToken = proto.start(StateControllerProto.BACKGROUND);
- mForceAppStandbyTracker.dumpProto(proto,
+ mAppStateTracker.dumpProto(proto,
StateControllerProto.BackgroundJobsController.FORCE_APP_STANDBY_TRACKER);
mJobSchedulerService.getJobStore().forEachJob((jobStatus) -> {
@@ -136,14 +136,14 @@ public final class BackgroundJobsController extends StateController {
proto.write(TrackedJob.SOURCE_PACKAGE_NAME, sourcePkg);
proto.write(TrackedJob.IS_IN_FOREGROUND,
- mForceAppStandbyTracker.isUidActive(sourceUid));
+ mAppStateTracker.isUidActive(sourceUid));
proto.write(TrackedJob.IS_WHITELISTED,
- mForceAppStandbyTracker.isUidPowerSaveWhitelisted(sourceUid) ||
- mForceAppStandbyTracker.isUidTempPowerSaveWhitelisted(sourceUid));
+ mAppStateTracker.isUidPowerSaveWhitelisted(sourceUid) ||
+ mAppStateTracker.isUidTempPowerSaveWhitelisted(sourceUid));
proto.write(
TrackedJob.CAN_RUN_ANY_IN_BACKGROUND,
- mForceAppStandbyTracker.isRunAnyInBackgroundAppOpsAllowed(
+ mAppStateTracker.isRunAnyInBackgroundAppOpsAllowed(
sourceUid, sourcePkg));
proto.write(
@@ -197,7 +197,7 @@ public final class BackgroundJobsController extends StateController {
final int uid = jobStatus.getSourceUid();
final String packageName = jobStatus.getSourcePackageName();
- final boolean canRun = !mForceAppStandbyTracker.areJobsRestricted(uid, packageName,
+ final boolean canRun = !mAppStateTracker.areJobsRestricted(uid, packageName,
(jobStatus.getInternalFlags() & JobStatus.INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION)
!= 0);
diff --git a/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java b/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
index a499472d197f..90db2a328c6f 100644
--- a/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
@@ -15,7 +15,7 @@
*/
package com.android.server;
-import static com.android.server.ForceAppStandbyTracker.TARGET_OP;
+import static com.android.server.AppStateTracker.TARGET_OP;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -33,6 +33,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
import android.app.AppOpsManager.OpEntry;
import android.app.AppOpsManager.PackageOps;
@@ -63,7 +64,7 @@ import android.util.Pair;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
-import com.android.server.ForceAppStandbyTracker.Listener;
+import com.android.server.AppStateTracker.Listener;
import org.junit.Before;
import org.junit.Test;
@@ -82,17 +83,17 @@ import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
/**
- * Tests for {@link ForceAppStandbyTracker}
+ * Tests for {@link AppStateTracker}
*
* Run with:
- atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
+ atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
*/
@SmallTest
@RunWith(AndroidJUnit4.class)
-public class ForceAppStandbyTrackerTest {
+public class AppStateTrackerTest {
- private class ForceAppStandbyTrackerTestable extends ForceAppStandbyTracker {
- ForceAppStandbyTrackerTestable() {
+ private class AppStateTrackerTestable extends AppStateTracker {
+ AppStateTrackerTestable() {
super(mMockContext, Looper.getMainLooper());
}
@@ -112,6 +113,11 @@ public class ForceAppStandbyTrackerTest {
}
@Override
+ ActivityManagerInternal injectActivityManagerInternal() {
+ return mMockIActivityManagerInternal;
+ }
+
+ @Override
PowerManagerInternal injectPowerManagerInternal() {
return mMockPowerManagerInternal;
}
@@ -152,6 +158,9 @@ public class ForceAppStandbyTrackerTest {
private IActivityManager mMockIActivityManager;
@Mock
+ private ActivityManagerInternal mMockIActivityManagerInternal;
+
+ @Mock
private AppOpsManager mMockAppOpsManager;
@Mock
@@ -195,7 +204,7 @@ public class ForceAppStandbyTrackerTest {
return new PowerSaveState.Builder().setBatterySaverEnabled(mPowerSaveMode).build();
}
- private ForceAppStandbyTrackerTestable newInstance() throws Exception {
+ private AppStateTrackerTestable newInstance() throws Exception {
MockitoAnnotations.initMocks(this);
when(mMockIAppOpsService.checkOperation(eq(TARGET_OP), anyInt(), anyString()))
@@ -205,12 +214,12 @@ public class ForceAppStandbyTrackerTest {
AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED;
});
- final ForceAppStandbyTrackerTestable instance = new ForceAppStandbyTrackerTestable();
+ final AppStateTrackerTestable instance = new AppStateTrackerTestable();
return instance;
}
- private void callStart(ForceAppStandbyTrackerTestable instance) throws RemoteException {
+ private void callStart(AppStateTrackerTestable instance) throws RemoteException {
// Set up functions that start() calls.
when(mMockPowerManagerInternal.getLowPowerState(eq(ServiceType.FORCE_ALL_APPS_STANDBY)))
@@ -223,7 +232,7 @@ public class ForceAppStandbyTrackerTest {
when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver);
// Call start.
- instance.start();
+ instance.onSystemServicesReady();
// Capture the listeners.
ArgumentCaptor<IUidObserver> uidObserverArgumentCaptor =
@@ -287,7 +296,7 @@ public class ForceAppStandbyTrackerTest {
private static final int JOBS_ONLY = 1 << 1;
private static final int JOBS_AND_ALARMS = ALARMS_ONLY | JOBS_ONLY;
- private void areRestricted(ForceAppStandbyTrackerTestable instance, int uid, String packageName,
+ private void areRestricted(AppStateTrackerTestable instance, int uid, String packageName,
int restrictionTypes, boolean exemptFromBatterySaver) {
assertEquals(((restrictionTypes & JOBS_ONLY) != 0),
instance.areJobsRestricted(uid, packageName, exemptFromBatterySaver));
@@ -295,13 +304,13 @@ public class ForceAppStandbyTrackerTest {
instance.areAlarmsRestricted(uid, packageName, exemptFromBatterySaver));
}
- private void areRestricted(ForceAppStandbyTrackerTestable instance, int uid, String packageName,
+ private void areRestricted(AppStateTrackerTestable instance, int uid, String packageName,
int restrictionTypes) {
areRestricted(instance, uid, packageName, restrictionTypes,
/*exemptFromBatterySaver=*/ false);
}
- private void areRestrictedWithExemption(ForceAppStandbyTrackerTestable instance,
+ private void areRestrictedWithExemption(AppStateTrackerTestable instance,
int uid, String packageName, int restrictionTypes) {
areRestricted(instance, uid, packageName, restrictionTypes,
/*exemptFromBatterySaver=*/ true);
@@ -309,7 +318,7 @@ public class ForceAppStandbyTrackerTest {
@Test
public void testAll() throws Exception {
- final ForceAppStandbyTrackerTestable instance = newInstance();
+ final AppStateTrackerTestable instance = newInstance();
callStart(instance);
assertFalse(instance.isForceAllAppsStandbyEnabled());
@@ -466,7 +475,7 @@ public class ForceAppStandbyTrackerTest {
@Test
public void testUidStateForeground() throws Exception {
- final ForceAppStandbyTrackerTestable instance = newInstance();
+ final AppStateTrackerTestable instance = newInstance();
callStart(instance);
mIUidObserver.onUidActive(UID_1);
@@ -476,6 +485,10 @@ public class ForceAppStandbyTrackerTest {
assertFalse(instance.isUidActive(UID_2));
assertTrue(instance.isUidActive(Process.SYSTEM_UID));
+ assertTrue(instance.isUidActiveSynced(UID_1));
+ assertFalse(instance.isUidActiveSynced(UID_2));
+ assertTrue(instance.isUidActiveSynced(Process.SYSTEM_UID));
+
assertFalse(instance.isUidInForeground(UID_1));
assertFalse(instance.isUidInForeground(UID_2));
assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
@@ -489,6 +502,10 @@ public class ForceAppStandbyTrackerTest {
assertFalse(instance.isUidActive(UID_2));
assertTrue(instance.isUidActive(Process.SYSTEM_UID));
+ assertTrue(instance.isUidActiveSynced(UID_1));
+ assertFalse(instance.isUidActiveSynced(UID_2));
+ assertTrue(instance.isUidActiveSynced(Process.SYSTEM_UID));
+
assertFalse(instance.isUidInForeground(UID_1));
assertTrue(instance.isUidInForeground(UID_2));
assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
@@ -548,14 +565,34 @@ public class ForceAppStandbyTrackerTest {
assertFalse(instance.isUidActive(UID_2));
assertTrue(instance.isUidActive(Process.SYSTEM_UID));
+ assertFalse(instance.isUidActiveSynced(UID_1));
+ assertFalse(instance.isUidActiveSynced(UID_2));
+ assertTrue(instance.isUidActiveSynced(Process.SYSTEM_UID));
+
assertFalse(instance.isUidInForeground(UID_1));
assertFalse(instance.isUidInForeground(UID_2));
assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
+
+ // The result from AMI.isUidActive() only affects isUidActiveSynced().
+ when(mMockIActivityManagerInternal.isUidActive(anyInt())).thenReturn(true);
+
+ assertFalse(instance.isUidActive(UID_1));
+ assertFalse(instance.isUidActive(UID_2));
+ assertTrue(instance.isUidActive(Process.SYSTEM_UID));
+
+ assertTrue(instance.isUidActiveSynced(UID_1));
+ assertTrue(instance.isUidActiveSynced(UID_2));
+ assertTrue(instance.isUidActiveSynced(Process.SYSTEM_UID));
+
+ assertFalse(instance.isUidInForeground(UID_1));
+ assertFalse(instance.isUidInForeground(UID_2));
+ assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
+
}
@Test
public void testExempt() throws Exception {
- final ForceAppStandbyTrackerTestable instance = newInstance();
+ final AppStateTrackerTestable instance = newInstance();
callStart(instance);
assertFalse(instance.isForceAllAppsStandbyEnabled());
@@ -621,7 +658,7 @@ public class ForceAppStandbyTrackerTest {
}
public void loadPersistedAppOps() throws Exception {
- final ForceAppStandbyTrackerTestable instance = newInstance();
+ final AppStateTrackerTestable instance = newInstance();
final List<PackageOps> ops = new ArrayList<>();
@@ -631,7 +668,7 @@ public class ForceAppStandbyTrackerTest {
AppOpsManager.OP_ACCESS_NOTIFICATIONS,
AppOpsManager.MODE_IGNORED, 0, 0, 0, 0, null));
entries.add(new AppOpsManager.OpEntry(
- ForceAppStandbyTracker.TARGET_OP,
+ AppStateTracker.TARGET_OP,
AppOpsManager.MODE_IGNORED, 0, 0, 0, 0, null));
ops.add(new PackageOps(PACKAGE_1, UID_1, entries));
@@ -639,7 +676,7 @@ public class ForceAppStandbyTrackerTest {
//--------------------------------------------------
entries = new ArrayList<>();
entries.add(new AppOpsManager.OpEntry(
- ForceAppStandbyTracker.TARGET_OP,
+ AppStateTracker.TARGET_OP,
AppOpsManager.MODE_IGNORED, 0, 0, 0, 0, null));
ops.add(new PackageOps(PACKAGE_2, UID_2, entries));
@@ -647,7 +684,7 @@ public class ForceAppStandbyTrackerTest {
//--------------------------------------------------
entries = new ArrayList<>();
entries.add(new AppOpsManager.OpEntry(
- ForceAppStandbyTracker.TARGET_OP,
+ AppStateTracker.TARGET_OP,
AppOpsManager.MODE_ALLOWED, 0, 0, 0, 0, null));
ops.add(new PackageOps(PACKAGE_1, UID_10_1, entries));
@@ -655,7 +692,7 @@ public class ForceAppStandbyTrackerTest {
//--------------------------------------------------
entries = new ArrayList<>();
entries.add(new AppOpsManager.OpEntry(
- ForceAppStandbyTracker.TARGET_OP,
+ AppStateTracker.TARGET_OP,
AppOpsManager.MODE_IGNORED, 0, 0, 0, 0, null));
entries.add(new AppOpsManager.OpEntry(
AppOpsManager.OP_ACCESS_NOTIFICATIONS,
@@ -688,10 +725,10 @@ public class ForceAppStandbyTrackerTest {
@Test
public void testPowerSaveListener() throws Exception {
- final ForceAppStandbyTrackerTestable instance = newInstance();
+ final AppStateTrackerTestable instance = newInstance();
callStart(instance);
- ForceAppStandbyTracker.Listener l = mock(ForceAppStandbyTracker.Listener.class);
+ AppStateTracker.Listener l = mock(AppStateTracker.Listener.class);
instance.addListener(l);
// Power save on.
@@ -731,10 +768,10 @@ public class ForceAppStandbyTrackerTest {
@Test
public void testAllListeners() throws Exception {
- final ForceAppStandbyTrackerTestable instance = newInstance();
+ final AppStateTrackerTestable instance = newInstance();
callStart(instance);
- ForceAppStandbyTracker.Listener l = mock(ForceAppStandbyTracker.Listener.class);
+ AppStateTracker.Listener l = mock(AppStateTracker.Listener.class);
instance.addListener(l);
// -------------------------------------------------------------------------
@@ -1042,7 +1079,7 @@ public class ForceAppStandbyTrackerTest {
@Test
public void testUserRemoved() throws Exception {
- final ForceAppStandbyTrackerTestable instance = newInstance();
+ final AppStateTrackerTestable instance = newInstance();
callStart(instance);
mIUidObserver.onUidActive(UID_1);
@@ -1077,7 +1114,7 @@ public class ForceAppStandbyTrackerTest {
// This is a small battery device
mIsSmallBatteryDevice = true;
- final ForceAppStandbyTrackerTestable instance = newInstance();
+ final AppStateTrackerTestable instance = newInstance();
callStart(instance);
assertFalse(instance.isForceAllAppsStandbyEnabled());
@@ -1103,7 +1140,7 @@ public class ForceAppStandbyTrackerTest {
// Not a small battery device, so plugged in status should not affect forced app standby
mIsSmallBatteryDevice = false;
- final ForceAppStandbyTrackerTestable instance = newInstance();
+ final AppStateTrackerTestable instance = newInstance();
callStart(instance);
assertFalse(instance.isForceAllAppsStandbyEnabled());
@@ -1152,7 +1189,7 @@ public class ForceAppStandbyTrackerTest {
private void checkAnyAppIdUnwhitelisted(int[] prevArray, int[] newArray, boolean expected) {
assertEquals("Input: " + Arrays.toString(prevArray) + " " + Arrays.toString(newArray),
- expected, ForceAppStandbyTracker.isAnyAppIdUnwhitelisted(prevArray, newArray));
+ expected, AppStateTracker.isAnyAppIdUnwhitelisted(prevArray, newArray));
// Also test isAnyAppIdUnwhitelistedSlow.
assertEquals("Input: " + Arrays.toString(prevArray) + " " + Arrays.toString(newArray),
@@ -1184,7 +1221,7 @@ public class ForceAppStandbyTrackerTest {
final int[] array2 = makeRandomArray();
final boolean expected = isAnyAppIdUnwhitelistedSlow(array1, array2);
- final boolean actual = ForceAppStandbyTracker.isAnyAppIdUnwhitelisted(array1, array2);
+ final boolean actual = AppStateTracker.isAnyAppIdUnwhitelisted(array1, array2);
assertEquals("Input: " + Arrays.toString(array1) + " " + Arrays.toString(array2),
expected, actual);