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
This commit is contained in:
Makoto Onuki
2018-02-07 10:49:01 -08:00
parent bcaeb104c2
commit 3f7be62d31
9 changed files with 192 additions and 119 deletions

View File

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

View File

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

View File

@@ -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());
@@ -474,6 +466,11 @@ public class ForceAppStandbyTracker {
return ActivityManager.getService();
}
@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)) {
@@ -1104,6 +1101,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.
*

View File

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

View File

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

View File

@@ -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;
}
}
}
/**

View File

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

View File

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

View File

@@ -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());
}
@@ -111,6 +112,11 @@ public class ForceAppStandbyTrackerTest {
return mMockIActivityManager;
}
@Override
ActivityManagerInternal injectActivityManagerInternal() {
return mMockIActivityManagerInternal;
}
@Override
PowerManagerInternal injectPowerManagerInternal() {
return mMockPowerManagerInternal;
@@ -151,6 +157,9 @@ public class ForceAppStandbyTrackerTest {
@Mock
private IActivityManager mMockIActivityManager;
@Mock
private ActivityManagerInternal mMockIActivityManagerInternal;
@Mock
private AppOpsManager mMockAppOpsManager;
@@ -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);