Merge "Handle Background Restricted apps."

This commit is contained in:
Kweku Adams
2022-08-17 15:02:47 +00:00
committed by Android (Google) Code Review
11 changed files with 170 additions and 29 deletions

View File

@@ -19,6 +19,8 @@ package com.android.server.tare;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static com.android.server.tare.EconomicPolicy.REGULATION_BASIC_INCOME;
import static com.android.server.tare.EconomicPolicy.REGULATION_BG_RESTRICTED;
import static com.android.server.tare.EconomicPolicy.REGULATION_BG_UNRESTRICTED;
import static com.android.server.tare.EconomicPolicy.REGULATION_BIRTHRIGHT;
import static com.android.server.tare.EconomicPolicy.REGULATION_DEMOTION;
import static com.android.server.tare.EconomicPolicy.REGULATION_PROMOTION;
@@ -510,12 +512,12 @@ class Agent {
}
final CompleteEconomicPolicy economicPolicy = mIrs.getCompleteEconomicPolicyLocked();
final long originalBalance = ledger.getCurrentBalance();
final long maxBalance = economicPolicy.getMaxSatiatedBalance(userId, pkgName);
if (transaction.delta > 0
&& originalBalance + transaction.delta > economicPolicy.getMaxSatiatedBalance()) {
&& originalBalance + transaction.delta > maxBalance) {
// Set lower bound at 0 so we don't accidentally take away credits when we were trying
// to _give_ the app credits.
final long newDelta =
Math.max(0, economicPolicy.getMaxSatiatedBalance() - originalBalance);
final long newDelta = Math.max(0, maxBalance - originalBalance);
Slog.i(TAG, "Would result in becoming too rich. Decreasing transaction "
+ eventToString(transaction.eventId)
+ (transaction.tag == null ? "" : ":" + transaction.tag)
@@ -660,6 +662,47 @@ class Agent {
}
}
/**
* Reclaim all ARCs from an app that was just restricted.
*/
@GuardedBy("mLock")
void onAppRestrictedLocked(final int userId, @NonNull final String pkgName) {
final long curBalance = getBalanceLocked(userId, pkgName);
final long minBalance = mIrs.getMinBalanceLocked(userId, pkgName);
if (curBalance <= minBalance) {
return;
}
if (DEBUG) {
Slog.i(TAG, "App restricted! Taking " + curBalance
+ " from " + appToString(userId, pkgName));
}
final long now = getCurrentTimeMillis();
final Ledger ledger = mScribe.getLedgerLocked(userId, pkgName);
recordTransactionLocked(userId, pkgName, ledger,
new Ledger.Transaction(now, now, REGULATION_BG_RESTRICTED, null, -curBalance, 0),
true);
}
/**
* Give an app that was just unrestricted some ARCs.
*/
@GuardedBy("mLock")
void onAppUnrestrictedLocked(final int userId, @NonNull final String pkgName) {
final Ledger ledger = mScribe.getLedgerLocked(userId, pkgName);
if (ledger.getCurrentBalance() > 0) {
Slog.wtf(TAG, "App " + pkgName + " had credits while it was restricted");
// App already got credits somehow. Move along.
return;
}
final long now = getCurrentTimeMillis();
recordTransactionLocked(userId, pkgName, ledger,
new Ledger.Transaction(now, now, REGULATION_BG_UNRESTRICTED, null,
mIrs.getMinBalanceLocked(userId, pkgName), 0), true);
}
/** Returns true if an app should be given credits in the general distributions. */
private boolean shouldGiveCredits(@NonNull InstalledPackageInfo packageInfo) {
// Skip apps that wouldn't be doing any work. Giving them ARCs would be wasteful.
@@ -668,7 +711,8 @@ class Agent {
}
final int userId = UserHandle.getUserId(packageInfo.uid);
// No point allocating ARCs to the system. It can do whatever it wants.
return !mIrs.isSystem(userId, packageInfo.packageName);
return !mIrs.isSystem(userId, packageInfo.packageName)
&& !mIrs.isPackageRestricted(userId, packageInfo.packageName);
}
void onCreditSupplyChanged() {

View File

@@ -170,6 +170,9 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy {
@Override
long getMinSatiatedBalance(final int userId, @NonNull final String pkgName) {
if (mIrs.isPackageRestricted(userId, pkgName)) {
return 0;
}
if (mIrs.isPackageExempted(userId, pkgName)) {
return mMinSatiatedBalanceExempted;
}
@@ -178,7 +181,10 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy {
}
@Override
long getMaxSatiatedBalance() {
long getMaxSatiatedBalance(int userId, @NonNull String pkgName) {
if (mIrs.isPackageRestricted(userId, pkgName)) {
return 0;
}
// TODO(230501287): adjust balance based on whether the app has the SCHEDULE_EXACT_ALARM
// permission granted. Apps without the permission granted shouldn't need a high balance
// since they won't be able to use exact alarms. Apps with the permission granted could

View File

@@ -36,7 +36,6 @@ public class CompleteEconomicPolicy extends EconomicPolicy {
/** Lazily populated set of rewards covered by this policy. */
private final SparseArray<Reward> mRewards = new SparseArray<>();
private final int[] mCostModifiers;
private long mMaxSatiatedBalance;
private long mInitialConsumptionLimit;
private long mHardConsumptionLimit;
@@ -80,16 +79,13 @@ public class CompleteEconomicPolicy extends EconomicPolicy {
}
private void updateLimits() {
long maxSatiatedBalance = 0;
long initialConsumptionLimit = 0;
long hardConsumptionLimit = 0;
for (int i = 0; i < mEnabledEconomicPolicies.size(); ++i) {
final EconomicPolicy economicPolicy = mEnabledEconomicPolicies.valueAt(i);
maxSatiatedBalance += economicPolicy.getMaxSatiatedBalance();
initialConsumptionLimit += economicPolicy.getInitialSatiatedConsumptionLimit();
hardConsumptionLimit += economicPolicy.getHardSatiatedConsumptionLimit();
}
mMaxSatiatedBalance = maxSatiatedBalance;
mInitialConsumptionLimit = initialConsumptionLimit;
mHardConsumptionLimit = hardConsumptionLimit;
}
@@ -104,8 +100,12 @@ public class CompleteEconomicPolicy extends EconomicPolicy {
}
@Override
long getMaxSatiatedBalance() {
return mMaxSatiatedBalance;
long getMaxSatiatedBalance(int userId, @NonNull String pkgName) {
long max = 0;
for (int i = 0; i < mEnabledEconomicPolicies.size(); ++i) {
max += mEnabledEconomicPolicies.valueAt(i).getMaxSatiatedBalance(userId, pkgName);
}
return max;
}
@Override

View File

@@ -67,6 +67,9 @@ public abstract class EconomicPolicy {
static final int REGULATION_WEALTH_RECLAMATION = TYPE_REGULATION | 2;
static final int REGULATION_PROMOTION = TYPE_REGULATION | 3;
static final int REGULATION_DEMOTION = TYPE_REGULATION | 4;
/** App is fully restricted from running in the background. */
static final int REGULATION_BG_RESTRICTED = TYPE_REGULATION | 5;
static final int REGULATION_BG_UNRESTRICTED = TYPE_REGULATION | 6;
static final int REWARD_NOTIFICATION_SEEN = TYPE_REWARD | 0;
static final int REWARD_NOTIFICATION_INTERACTION = TYPE_REWARD | 1;
@@ -210,7 +213,7 @@ public abstract class EconomicPolicy {
* exists to ensure that no single app accumulate all available resources and increases fairness
* for all apps.
*/
abstract long getMaxSatiatedBalance();
abstract long getMaxSatiatedBalance(int userId, @NonNull String pkgName);
/**
* Returns the maximum number of cakes that should be consumed during a full 100% discharge

View File

@@ -29,6 +29,7 @@ import static com.android.server.tare.TareUtils.getCurrentTimeMillis;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AlarmManager;
import android.app.AppOpsManager;
import android.app.tare.IEconomyManager;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManagerInternal;
@@ -64,6 +65,8 @@ import android.util.SparseArrayMap;
import android.util.SparseSetArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
@@ -119,6 +122,7 @@ public class InternalResourceService extends SystemService {
private final PackageManager mPackageManager;
private final PackageManagerInternal mPackageManagerInternal;
private IAppOpsService mAppOpsService;
private IDeviceIdleController mDeviceIdleController;
private final Agent mAgent;
@@ -145,6 +149,12 @@ public class InternalResourceService extends SystemService {
private final CopyOnWriteArraySet<TareStateChangeListener> mStateChangeListeners =
new CopyOnWriteArraySet<>();
/**
* List of packages that are fully restricted and shouldn't be allowed to run in the background.
*/
@GuardedBy("mLock")
private final SparseSetArray<String> mRestrictedApps = new SparseSetArray<>();
/** List of packages that are "exempted" from battery restrictions. */
// TODO(144864180): include userID
@GuardedBy("mLock")
@@ -160,6 +170,30 @@ public class InternalResourceService extends SystemService {
@GuardedBy("mLock")
private int mCurrentBatteryLevel;
private final IAppOpsCallback mApbListener = new IAppOpsCallback.Stub() {
@Override
public void opChanged(int op, int uid, String packageName) {
boolean restricted = false;
try {
restricted = mAppOpsService.checkOperation(
AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uid, packageName)
!= AppOpsManager.MODE_ALLOWED;
} catch (RemoteException e) {
// Shouldn't happen
}
final int userId = UserHandle.getUserId(uid);
synchronized (mLock) {
if (restricted) {
if (mRestrictedApps.add(userId, packageName)) {
mAgent.onAppRestrictedLocked(userId, packageName);
}
} else if (mRestrictedApps.remove(UserHandle.getUserId(uid), packageName)) {
mAgent.onAppUnrestrictedLocked(userId, packageName);
}
}
}
};
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Nullable
private String getPackageName(Intent intent) {
@@ -280,9 +314,11 @@ public class InternalResourceService extends SystemService {
switch (phase) {
case PHASE_SYSTEM_SERVICES_READY:
mConfigObserver.start();
mAppOpsService = IAppOpsService.Stub.asInterface(
ServiceManager.getService(Context.APP_OPS_SERVICE));
mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
mConfigObserver.start();
onBootPhaseSystemServicesReady();
break;
case PHASE_THIRD_PARTY_APPS_CAN_START:
@@ -365,6 +401,12 @@ public class InternalResourceService extends SystemService {
}
}
boolean isPackageRestricted(final int userId, @NonNull String pkgName) {
synchronized (mLock) {
return mRestrictedApps.contains(userId, pkgName);
}
}
boolean isSystem(final int userId, @NonNull String pkgName) {
if ("android".equals(pkgName)) {
return true;
@@ -711,6 +753,13 @@ public class InternalResourceService extends SystemService {
UsageStatsManagerInternal usmi = LocalServices.getService(UsageStatsManagerInternal.class);
usmi.registerListener(mSurveillanceAgent);
try {
mAppOpsService
.startWatchingMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, null, mApbListener);
} catch (RemoteException e) {
// shouldn't happen.
}
}
/** Perform long-running and/or heavy setup work. This should be called off the main thread. */
@@ -815,6 +864,11 @@ public class InternalResourceService extends SystemService {
UsageStatsManagerInternal usmi =
LocalServices.getService(UsageStatsManagerInternal.class);
usmi.unregisterListener(mSurveillanceAgent);
try {
mAppOpsService.stopWatchingMode(mApbListener);
} catch (RemoteException e) {
// shouldn't happen.
}
}
synchronized (mPackageToUidCache) {
mPackageToUidCache.clear();

View File

@@ -172,6 +172,9 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy {
@Override
long getMinSatiatedBalance(final int userId, @NonNull final String pkgName) {
if (mIrs.isPackageRestricted(userId, pkgName)) {
return 0;
}
if (mIrs.isPackageExempted(userId, pkgName)) {
return mMinSatiatedBalanceExempted;
}
@@ -180,7 +183,10 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy {
}
@Override
long getMaxSatiatedBalance() {
long getMaxSatiatedBalance(int userId, @NonNull String pkgName) {
if (mIrs.isPackageRestricted(userId, pkgName)) {
return 0;
}
return mMaxSatiatedBalance;
}

View File

@@ -20,6 +20,8 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import android.app.AlarmManager;
@@ -92,7 +94,7 @@ public class AgentTest {
Ledger ledger = new Ledger();
doReturn(1_000_000L).when(mIrs).getConsumptionLimitLocked();
doReturn(1_000_000L).when(mEconomicPolicy).getMaxSatiatedBalance();
doReturn(1_000_000L).when(mEconomicPolicy).getMaxSatiatedBalance(anyInt(), anyString());
Ledger.Transaction transaction = new Ledger.Transaction(0, 0, 0, null, 5, 0);
agent.recordTransactionLocked(0, "com.test", ledger, transaction, false);
@@ -121,7 +123,7 @@ public class AgentTest {
Ledger ledger = new Ledger();
doReturn(1000L).when(mIrs).getConsumptionLimitLocked();
doReturn(1_000_000L).when(mEconomicPolicy).getMaxSatiatedBalance();
doReturn(1_000_000L).when(mEconomicPolicy).getMaxSatiatedBalance(anyInt(), anyString());
Ledger.Transaction transaction = new Ledger.Transaction(0, 0, 0, null, 5, 0);
agent.recordTransactionLocked(0, "com.test", ledger, transaction, false);
@@ -168,7 +170,7 @@ public class AgentTest {
Ledger ledger = new Ledger();
doReturn(1_000_000L).when(mIrs).getConsumptionLimitLocked();
doReturn(1000L).when(mEconomicPolicy).getMaxSatiatedBalance();
doReturn(1000L).when(mEconomicPolicy).getMaxSatiatedBalance(anyInt(), anyString());
Ledger.Transaction transaction = new Ledger.Transaction(0, 0, 0, null, 5, 0);
agent.recordTransactionLocked(0, "com.test", ledger, transaction, false);
@@ -187,7 +189,7 @@ public class AgentTest {
assertEquals(1_000, ledger.getCurrentBalance());
// Shouldn't change in normal operation, but adding test case in case it does.
doReturn(900L).when(mEconomicPolicy).getMaxSatiatedBalance();
doReturn(900L).when(mEconomicPolicy).getMaxSatiatedBalance(anyInt(), anyString());
transaction = new Ledger.Transaction(0, 0, 0, null, 500, 0);
agent.recordTransactionLocked(0, "com.test", ledger, transaction, false);

View File

@@ -63,7 +63,7 @@ public class AgentTrendCalculatorTest {
}
@Override
long getMaxSatiatedBalance() {
long getMaxSatiatedBalance(int userId, String pkgName) {
return 0;
}

View File

@@ -134,8 +134,11 @@ public class AlarmManagerEconomicPolicyTest {
mEconomicPolicy.getInitialSatiatedConsumptionLimit());
assertEquals(EconomyManager.DEFAULT_AM_HARD_CONSUMPTION_LIMIT_CAKES,
mEconomicPolicy.getHardSatiatedConsumptionLimit());
final String pkgRestricted = "com.pkg.restricted";
when(mIrs.isPackageRestricted(anyInt(), eq(pkgRestricted))).thenReturn(true);
assertEquals(0, mEconomicPolicy.getMaxSatiatedBalance(0, pkgRestricted));
assertEquals(EconomyManager.DEFAULT_AM_MAX_SATIATED_BALANCE_CAKES,
mEconomicPolicy.getMaxSatiatedBalance());
mEconomicPolicy.getMaxSatiatedBalance(0, "com.any.other.app"));
final String pkgExempted = "com.pkg.exempted";
when(mIrs.isPackageExempted(anyInt(), eq(pkgExempted))).thenReturn(true);
assertEquals(EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_EXEMPTED_CAKES,
@@ -154,7 +157,10 @@ public class AlarmManagerEconomicPolicyTest {
assertEquals(arcToCake(5), mEconomicPolicy.getInitialSatiatedConsumptionLimit());
assertEquals(arcToCake(25), mEconomicPolicy.getHardSatiatedConsumptionLimit());
assertEquals(arcToCake(10), mEconomicPolicy.getMaxSatiatedBalance());
final String pkgRestricted = "com.pkg.restricted";
when(mIrs.isPackageRestricted(anyInt(), eq(pkgRestricted))).thenReturn(true);
assertEquals(arcToCake(0), mEconomicPolicy.getMaxSatiatedBalance(0, pkgRestricted));
assertEquals(arcToCake(10), mEconomicPolicy.getMaxSatiatedBalance(0, "com.any.other.app"));
final String pkgExempted = "com.pkg.exempted";
when(mIrs.isPackageExempted(anyInt(), eq(pkgExempted))).thenReturn(true);
assertEquals(arcToCake(9), mEconomicPolicy.getMinSatiatedBalance(0, pkgExempted));
@@ -172,7 +178,10 @@ public class AlarmManagerEconomicPolicyTest {
assertEquals(arcToCake(1), mEconomicPolicy.getInitialSatiatedConsumptionLimit());
assertEquals(arcToCake(1), mEconomicPolicy.getHardSatiatedConsumptionLimit());
assertEquals(arcToCake(1), mEconomicPolicy.getMaxSatiatedBalance());
final String pkgRestricted = "com.pkg.restricted";
when(mIrs.isPackageRestricted(anyInt(), eq(pkgRestricted))).thenReturn(true);
assertEquals(arcToCake(0), mEconomicPolicy.getMaxSatiatedBalance(0, pkgRestricted));
assertEquals(arcToCake(1), mEconomicPolicy.getMaxSatiatedBalance(0, "com.any.other.app"));
final String pkgExempted = "com.pkg.exempted";
when(mIrs.isPackageExempted(anyInt(), eq(pkgExempted))).thenReturn(true);
assertEquals(arcToCake(0), mEconomicPolicy.getMinSatiatedBalance(0, pkgExempted));
@@ -187,7 +196,8 @@ public class AlarmManagerEconomicPolicyTest {
assertEquals(arcToCake(5), mEconomicPolicy.getInitialSatiatedConsumptionLimit());
assertEquals(arcToCake(5), mEconomicPolicy.getHardSatiatedConsumptionLimit());
assertEquals(arcToCake(13), mEconomicPolicy.getMaxSatiatedBalance());
assertEquals(arcToCake(0), mEconomicPolicy.getMaxSatiatedBalance(0, pkgRestricted));
assertEquals(arcToCake(13), mEconomicPolicy.getMaxSatiatedBalance(0, "com.any.other.app"));
assertEquals(arcToCake(13), mEconomicPolicy.getMinSatiatedBalance(0, pkgExempted));
assertEquals(arcToCake(13), mEconomicPolicy.getMinSatiatedBalance(0, "com.any.other.app"));
}

View File

@@ -142,9 +142,12 @@ public class CompleteEconomicPolicyTest {
assertEquals(EconomyManager.DEFAULT_JS_HARD_CONSUMPTION_LIMIT_CAKES
+ EconomyManager.DEFAULT_AM_HARD_CONSUMPTION_LIMIT_CAKES,
mEconomicPolicy.getHardSatiatedConsumptionLimit());
final String pkgRestricted = "com.pkg.restricted";
when(mIrs.isPackageRestricted(anyInt(), eq(pkgRestricted))).thenReturn(true);
assertEquals(0, mEconomicPolicy.getMaxSatiatedBalance(0, pkgRestricted));
assertEquals(EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES
+ EconomyManager.DEFAULT_AM_MAX_SATIATED_BALANCE_CAKES,
mEconomicPolicy.getMaxSatiatedBalance());
mEconomicPolicy.getMaxSatiatedBalance(0, "com.any.other.app"));
final String pkgExempted = "com.pkg.exempted";
when(mIrs.isPackageExempted(anyInt(), eq(pkgExempted))).thenReturn(true);
assertEquals(EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED_CAKES
@@ -170,7 +173,10 @@ public class CompleteEconomicPolicyTest {
assertEquals(arcToCake(10), mEconomicPolicy.getInitialSatiatedConsumptionLimit());
assertEquals(arcToCake(50), mEconomicPolicy.getHardSatiatedConsumptionLimit());
assertEquals(arcToCake(20), mEconomicPolicy.getMaxSatiatedBalance());
final String pkgRestricted = "com.pkg.restricted";
when(mIrs.isPackageRestricted(anyInt(), eq(pkgRestricted))).thenReturn(true);
assertEquals(arcToCake(0), mEconomicPolicy.getMaxSatiatedBalance(0, pkgRestricted));
assertEquals(arcToCake(20), mEconomicPolicy.getMaxSatiatedBalance(0, "com.any.other.app"));
final String pkgExempted = "com.pkg.exempted";
when(mIrs.isPackageExempted(anyInt(), eq(pkgExempted))).thenReturn(true);
assertEquals(arcToCake(13), mEconomicPolicy.getMinSatiatedBalance(0, pkgExempted));

View File

@@ -134,8 +134,11 @@ public class JobSchedulerEconomicPolicyTest {
mEconomicPolicy.getInitialSatiatedConsumptionLimit());
assertEquals(EconomyManager.DEFAULT_JS_HARD_CONSUMPTION_LIMIT_CAKES,
mEconomicPolicy.getHardSatiatedConsumptionLimit());
final String pkgRestricted = "com.pkg.restricted";
when(mIrs.isPackageRestricted(anyInt(), eq(pkgRestricted))).thenReturn(true);
assertEquals(0, mEconomicPolicy.getMaxSatiatedBalance(0, pkgRestricted));
assertEquals(EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES,
mEconomicPolicy.getMaxSatiatedBalance());
mEconomicPolicy.getMaxSatiatedBalance(0, "com.any.other.app"));
final String pkgExempted = "com.pkg.exempted";
when(mIrs.isPackageExempted(anyInt(), eq(pkgExempted))).thenReturn(true);
assertEquals(EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED_CAKES,
@@ -154,7 +157,10 @@ public class JobSchedulerEconomicPolicyTest {
assertEquals(arcToCake(5), mEconomicPolicy.getInitialSatiatedConsumptionLimit());
assertEquals(arcToCake(25), mEconomicPolicy.getHardSatiatedConsumptionLimit());
assertEquals(arcToCake(10), mEconomicPolicy.getMaxSatiatedBalance());
final String pkgRestricted = "com.pkg.restricted";
when(mIrs.isPackageRestricted(anyInt(), eq(pkgRestricted))).thenReturn(true);
assertEquals(arcToCake(0), mEconomicPolicy.getMaxSatiatedBalance(0, pkgRestricted));
assertEquals(arcToCake(10), mEconomicPolicy.getMaxSatiatedBalance(0, "com.any.other.app"));
final String pkgExempted = "com.pkg.exempted";
when(mIrs.isPackageExempted(anyInt(), eq(pkgExempted))).thenReturn(true);
assertEquals(arcToCake(9), mEconomicPolicy.getMinSatiatedBalance(0, pkgExempted));
@@ -172,7 +178,10 @@ public class JobSchedulerEconomicPolicyTest {
assertEquals(arcToCake(1), mEconomicPolicy.getInitialSatiatedConsumptionLimit());
assertEquals(arcToCake(1), mEconomicPolicy.getHardSatiatedConsumptionLimit());
assertEquals(arcToCake(1), mEconomicPolicy.getMaxSatiatedBalance());
final String pkgRestricted = "com.pkg.restricted";
when(mIrs.isPackageRestricted(anyInt(), eq(pkgRestricted))).thenReturn(true);
assertEquals(arcToCake(0), mEconomicPolicy.getMaxSatiatedBalance(0, pkgRestricted));
assertEquals(arcToCake(1), mEconomicPolicy.getMaxSatiatedBalance(0, "com.any.other.app"));
final String pkgExempted = "com.pkg.exempted";
when(mIrs.isPackageExempted(anyInt(), eq(pkgExempted))).thenReturn(true);
assertEquals(arcToCake(0), mEconomicPolicy.getMinSatiatedBalance(0, pkgExempted));
@@ -187,7 +196,8 @@ public class JobSchedulerEconomicPolicyTest {
assertEquals(arcToCake(5), mEconomicPolicy.getInitialSatiatedConsumptionLimit());
assertEquals(arcToCake(5), mEconomicPolicy.getHardSatiatedConsumptionLimit());
assertEquals(arcToCake(13), mEconomicPolicy.getMaxSatiatedBalance());
assertEquals(arcToCake(0), mEconomicPolicy.getMaxSatiatedBalance(0, pkgRestricted));
assertEquals(arcToCake(13), mEconomicPolicy.getMaxSatiatedBalance(0, "com.any.other.app"));
assertEquals(arcToCake(13), mEconomicPolicy.getMinSatiatedBalance(0, pkgExempted));
assertEquals(arcToCake(13), mEconomicPolicy.getMinSatiatedBalance(0, "com.any.other.app"));
}