From 9bf45ccf6cd5a3b317306bcef1c687c1f3c8cad2 Mon Sep 17 00:00:00 2001 From: Kweku Adams Date: Sat, 13 Aug 2022 14:47:33 +0000 Subject: [PATCH] Add shell command so tests aren't hindered. Add a shell command that allows tests to temporarily exempt themselves from all TARE policy. Bug: 242294488 Test: set battery level to 10%, unplug, then: Test: atest --rerun-until-failure 100 CtsOsTestCases:AppHibernationIntegrationTest Test: atest --rerun-until-failure 100 CtsOsTestCases:AutoRevokeTest Test: atest --rerun-until-failure 100 CtsPermissionTestCases:NotificationListenerCheckTest Test: atest --rerun-until-failure 100 CtsPermissionTestCases:LocationAccessCheckTest Test: atest frameworks/base/services/tests/mockingservicestests/src/com/android/server/tare Test: atest frameworks/base/services/tests/servicestests/src/com/android/server/tare Change-Id: I95f3c2ad27c603c94784d13d5c75db4e58ade974 --- .../java/com/android/server/tare/Agent.java | 79 ++++++++++-- .../tare/AlarmManagerEconomicPolicy.java | 6 +- .../android/server/tare/EconomicPolicy.java | 4 +- .../server/tare/InternalResourceService.java | 100 +++++++++++++++- .../tare/JobSchedulerEconomicPolicy.java | 6 +- .../android/server/tare/TareShellCommand.java | 112 ++++++++++++++++++ .../server/tare/AgentTrendCalculatorTest.java | 9 +- 7 files changed, 292 insertions(+), 24 deletions(-) create mode 100644 apex/jobscheduler/service/java/com/android/server/tare/TareShellCommand.java rename services/tests/{servicestests => mockingservicestests}/src/com/android/server/tare/AgentTrendCalculatorTest.java (98%) diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java index 66dc08dd7a46a..e23860c1eca37 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java @@ -44,6 +44,7 @@ import android.util.IndentingPrintWriter; import android.util.Log; import android.util.Slog; import android.util.SparseArrayMap; +import android.util.SparseSetArray; import android.util.TimeUtils; import com.android.internal.annotations.GuardedBy; @@ -282,6 +283,7 @@ class Agent { for (int i = 0; i < pkgNames.size(); ++i) { final String pkgName = pkgNames.valueAt(i); + final boolean isVip = mIrs.isVip(userId, pkgName); SparseArrayMap ongoingEvents = mCurrentOngoingEvents.get(userId, pkgName); if (ongoingEvents != null) { @@ -296,8 +298,8 @@ class Agent { for (int n = 0; n < size; ++n) { final ActionAffordabilityNote note = actionAffordabilityNotes.valueAt(n); note.recalculateCosts(economicPolicy, userId, pkgName); - final boolean isAffordable = - isAffordableLocked(newBalance, + final boolean isAffordable = isVip + || isAffordableLocked(newBalance, note.getCachedModifiedPrice(), note.getCtp()); if (note.isCurrentlyAffordable() != isAffordable) { note.setNewAffordability(isAffordable); @@ -310,6 +312,51 @@ class Agent { } } + @GuardedBy("mLock") + void onVipStatusChangedLocked(final int userId, @NonNull String pkgName) { + final long now = getCurrentTimeMillis(); + final long nowElapsed = SystemClock.elapsedRealtime(); + final CompleteEconomicPolicy economicPolicy = mIrs.getCompleteEconomicPolicyLocked(); + + final boolean isVip = mIrs.isVip(userId, pkgName); + SparseArrayMap ongoingEvents = + mCurrentOngoingEvents.get(userId, pkgName); + if (ongoingEvents != null) { + mOngoingEventUpdater.reset(userId, pkgName, now, nowElapsed); + ongoingEvents.forEach(mOngoingEventUpdater); + } + final ArraySet actionAffordabilityNotes = + mActionAffordabilityNotes.get(userId, pkgName); + if (actionAffordabilityNotes != null) { + final int size = actionAffordabilityNotes.size(); + final long newBalance = + mScribe.getLedgerLocked(userId, pkgName).getCurrentBalance(); + for (int n = 0; n < size; ++n) { + final ActionAffordabilityNote note = actionAffordabilityNotes.valueAt(n); + note.recalculateCosts(economicPolicy, userId, pkgName); + final boolean isAffordable = isVip + || isAffordableLocked(newBalance, + note.getCachedModifiedPrice(), note.getCtp()); + if (note.isCurrentlyAffordable() != isAffordable) { + note.setNewAffordability(isAffordable); + mIrs.postAffordabilityChanged(userId, pkgName, note); + } + } + } + scheduleBalanceCheckLocked(userId, pkgName); + } + + @GuardedBy("mLock") + void onVipStatusChangedLocked(@NonNull SparseSetArray pkgs) { + for (int u = pkgs.size() - 1; u >= 0; --u) { + final int userId = pkgs.keyAt(u); + + for (int p = pkgs.sizeAt(u) - 1; p >= 0; --p) { + onVipStatusChangedLocked(userId, pkgs.valueAt(u, p)); + } + } + } + @GuardedBy("mLock") private void onAnythingChangedLocked(final boolean updateOngoingEvents) { final long now = getCurrentTimeMillis(); @@ -347,11 +394,12 @@ class Agent { if (actionAffordabilityNotes != null) { final int size = actionAffordabilityNotes.size(); final long newBalance = getBalanceLocked(userId, pkgName); + final boolean isVip = mIrs.isVip(userId, pkgName); for (int n = 0; n < size; ++n) { final ActionAffordabilityNote note = actionAffordabilityNotes.valueAt(n); note.recalculateCosts(economicPolicy, userId, pkgName); - final boolean isAffordable = - isAffordableLocked(newBalance, + final boolean isAffordable = isVip + || isAffordableLocked(newBalance, note.getCachedModifiedPrice(), note.getCtp()); if (note.isCurrentlyAffordable() != isAffordable) { note.setNewAffordability(isAffordable); @@ -452,6 +500,14 @@ class Agent { "Tried to adjust system balance for " + appToString(userId, pkgName)); return; } + if (mIrs.isVip(userId, pkgName)) { + // This could happen if the app was made a VIP after it started performing actions. + // Continue recording the transaction for debugging purposes, but don't let it change + // any numbers. + transaction = new Ledger.Transaction( + transaction.startTimeMs, transaction.endTimeMs, + transaction.eventId, transaction.tag, 0 /* delta */, transaction.ctp); + } final CompleteEconomicPolicy economicPolicy = mIrs.getCompleteEconomicPolicyLocked(); final long originalBalance = ledger.getCurrentBalance(); if (transaction.delta > 0 @@ -477,10 +533,11 @@ class Agent { mActionAffordabilityNotes.get(userId, pkgName); if (actionAffordabilityNotes != null) { final long newBalance = ledger.getCurrentBalance(); + final boolean isVip = mIrs.isVip(userId, pkgName); for (int i = 0; i < actionAffordabilityNotes.size(); ++i) { final ActionAffordabilityNote note = actionAffordabilityNotes.valueAt(i); - final boolean isAffordable = - isAffordableLocked(newBalance, + final boolean isAffordable = isVip + || isAffordableLocked(newBalance, note.getCachedModifiedPrice(), note.getCtp()); if (note.isCurrentlyAffordable() != isAffordable) { note.setNewAffordability(isAffordable); @@ -866,7 +923,7 @@ class Agent { private void scheduleBalanceCheckLocked(final int userId, @NonNull final String pkgName) { SparseArrayMap ongoingEvents = mCurrentOngoingEvents.get(userId, pkgName); - if (ongoingEvents == null) { + if (ongoingEvents == null || mIrs.isVip(userId, pkgName)) { // No ongoing transactions. No reason to schedule mBalanceThresholdAlarmQueue.removeAlarmForKey(new Package(userId, pkgName)); return; @@ -1059,9 +1116,10 @@ class Agent { note.setNewAffordability(true); return; } + final boolean isVip = mIrs.isVip(userId, pkgName); note.recalculateCosts(economicPolicy, userId, pkgName); - note.setNewAffordability( - isAffordableLocked(getBalanceLocked(userId, pkgName), + note.setNewAffordability(isVip + || isAffordableLocked(getBalanceLocked(userId, pkgName), note.getCachedModifiedPrice(), note.getCtp())); mIrs.postAffordabilityChanged(userId, pkgName, note); // Update ongoing alarm @@ -1200,11 +1258,12 @@ class Agent { if (actionAffordabilityNotes != null && actionAffordabilityNotes.size() > 0) { final long newBalance = getBalanceLocked(userId, pkgName); + final boolean isVip = mIrs.isVip(userId, pkgName); for (int i = 0; i < actionAffordabilityNotes.size(); ++i) { final ActionAffordabilityNote note = actionAffordabilityNotes.valueAt(i); - final boolean isAffordable = isAffordableLocked( + final boolean isAffordable = isVip || isAffordableLocked( newBalance, note.getCachedModifiedPrice(), note.getCtp()); if (note.isCurrentlyAffordable() != isAffordable) { note.setNewAffordability(isAffordable); diff --git a/apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java b/apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java index a46430feb688b..aa66e92a091f8 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java @@ -149,7 +149,6 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy { private long mHardSatiatedConsumptionLimit; private final KeyValueListParser mParser = new KeyValueListParser(','); - private final InternalResourceService mInternalResourceService; private final Injector mInjector; private final SparseArray mActions = new SparseArray<>(); @@ -157,7 +156,6 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy { AlarmManagerEconomicPolicy(InternalResourceService irs, Injector injector) { super(irs); - mInternalResourceService = irs; mInjector = injector; loadConstants("", null); } @@ -165,14 +163,14 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy { @Override void setup(@NonNull DeviceConfig.Properties properties) { super.setup(properties); - ContentResolver resolver = mInternalResourceService.getContext().getContentResolver(); + ContentResolver resolver = mIrs.getContext().getContentResolver(); loadConstants(mInjector.getSettingsGlobalString(resolver, TARE_ALARM_MANAGER_CONSTANTS), properties); } @Override long getMinSatiatedBalance(final int userId, @NonNull final String pkgName) { - if (mInternalResourceService.isPackageExempted(userId, pkgName)) { + if (mIrs.isPackageExempted(userId, pkgName)) { return mMinSatiatedBalanceExempted; } // TODO: take other exemptions into account diff --git a/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java b/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java index 0937e7ba4055c..564ffb9c41696 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java @@ -169,9 +169,11 @@ public abstract class EconomicPolicy { } } + protected final InternalResourceService mIrs; private static final Modifier[] COST_MODIFIER_BY_INDEX = new Modifier[NUM_COST_MODIFIERS]; EconomicPolicy(@NonNull InternalResourceService irs) { + mIrs = irs; for (int mId : getCostModifiers()) { initModifier(mId, irs); } @@ -240,7 +242,7 @@ public abstract class EconomicPolicy { @NonNull final Cost getCostOfAction(int actionId, int userId, @NonNull String pkgName) { final Action action = getAction(actionId); - if (action == null) { + if (action == null || mIrs.isVip(userId, pkgName)) { return new Cost(0, 0); } long ctp = action.costToProduce; diff --git a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java index e9270bffec65b..7a7d669ae2293 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java @@ -48,6 +48,7 @@ import android.os.Handler; import android.os.IDeviceIdleController; import android.os.Looper; import android.os.Message; +import android.os.ParcelFileDescriptor; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; @@ -149,6 +150,9 @@ public class InternalResourceService extends SystemService { @GuardedBy("mLock") private ArraySet mExemptedApps = new ArraySet<>(); + @GuardedBy("mLock") + private final SparseArrayMap mVipOverrides = new SparseArrayMap<>(); + private volatile boolean mIsEnabled; private volatile int mBootPhase; private volatile boolean mExemptListLoaded; @@ -368,6 +372,21 @@ public class InternalResourceService extends SystemService { return UserHandle.isCore(getUid(userId, pkgName)); } + boolean isVip(final int userId, @NonNull String pkgName) { + synchronized (mLock) { + final Boolean override = mVipOverrides.get(userId, pkgName); + if (override != null) { + return override; + } + } + if (isSystem(userId, pkgName)) { + // The government, I mean the system, can create ARCs as it needs to in order to + // operate. + return true; + } + return false; + } + void onBatteryLevelChanged() { synchronized (mLock) { final int newBatteryLevel = getCurrentBatteryLevel(); @@ -470,6 +489,7 @@ public class InternalResourceService extends SystemService { } synchronized (mLock) { mUidToPackageCache.remove(uid, pkgName); + mVipOverrides.delete(userId, pkgName); for (int i = 0; i < mPkgCache.size(); ++i) { final InstalledPackageInfo pkgInfo = mPkgCache.get(i); if (UserHandle.getUserId(pkgInfo.uid) == userId @@ -506,6 +526,7 @@ public class InternalResourceService extends SystemService { void onUserRemoved(final int userId) { synchronized (mLock) { + mVipOverrides.delete(userId); ArrayList removedPkgs = new ArrayList<>(); for (int i = mPkgCache.size() - 1; i >= 0; --i) { final InstalledPackageInfo pkgInfo = mPkgCache.get(i); @@ -886,6 +907,15 @@ public class InternalResourceService extends SystemService { Binder.restoreCallingIdentity(identityToken); } } + + @Override + public int handleShellCommand(@NonNull ParcelFileDescriptor in, + @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, + @NonNull String[] args) { + return (new TareShellCommand(InternalResourceService.this)).exec( + this, in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(), + args); + } } private final class LocalService implements EconomyManagerInternal { @@ -937,9 +967,9 @@ public class InternalResourceService extends SystemService { if (!mIsEnabled) { return true; } - if (isSystem(userId, pkgName)) { + if (isVip(userId, pkgName)) { // The government, I mean the system, can create ARCs as it needs to in order to - // operate. + // allow VIPs to operate. return true; } // TODO: take temp-allowlist into consideration @@ -965,7 +995,7 @@ public class InternalResourceService extends SystemService { if (!mIsEnabled) { return FOREVER_MS; } - if (isSystem(userId, pkgName)) { + if (isVip(userId, pkgName)) { return FOREVER_MS; } long totalCostPerSecond = 0; @@ -1136,6 +1166,47 @@ public class InternalResourceService extends SystemService { } } + // Shell command infrastructure + int executeClearVip(@NonNull PrintWriter pw) { + synchronized (mLock) { + final SparseSetArray changedPkgs = new SparseSetArray<>(); + for (int u = mVipOverrides.numMaps() - 1; u >= 0; --u) { + final int userId = mVipOverrides.keyAt(u); + + for (int p = mVipOverrides.numElementsForKeyAt(u) - 1; p >= 0; --p) { + changedPkgs.add(userId, mVipOverrides.keyAt(u, p)); + } + } + mVipOverrides.clear(); + if (mIsEnabled) { + mAgent.onVipStatusChangedLocked(changedPkgs); + } + } + pw.println("Cleared all VIP statuses"); + return TareShellCommand.COMMAND_SUCCESS; + } + + int executeSetVip(@NonNull PrintWriter pw, + int userId, @NonNull String pkgName, @Nullable Boolean newVipState) { + final boolean changed; + synchronized (mLock) { + final boolean wasVip = isVip(userId, pkgName); + if (newVipState == null) { + mVipOverrides.delete(userId, pkgName); + } else { + mVipOverrides.add(userId, pkgName, newVipState); + } + changed = isVip(userId, pkgName) != wasVip; + if (mIsEnabled && changed) { + mAgent.onVipStatusChangedLocked(userId, pkgName); + } + } + pw.println(appToString(userId, pkgName) + " VIP status set to " + newVipState + "." + + " Final VIP state changed? " + changed); + return TareShellCommand.COMMAND_SUCCESS; + } + + // Dump infrastructure private static void dumpHelp(PrintWriter pw) { pw.println("Resource Economy (economy) dump options:"); pw.println(" [-h|--help] [package] ..."); @@ -1173,6 +1244,29 @@ public class InternalResourceService extends SystemService { pw.print("Exempted apps", mExemptedApps); pw.println(); + boolean printedVips = false; + pw.println(); + pw.print("VIPs:"); + for (int u = 0; u < mVipOverrides.numMaps(); ++u) { + final int userId = mVipOverrides.keyAt(u); + + for (int p = 0; p < mVipOverrides.numElementsForKeyAt(u); ++p) { + final String pkgName = mVipOverrides.keyAt(u, p); + + printedVips = true; + pw.println(); + pw.print(appToString(userId, pkgName)); + pw.print("="); + pw.print(mVipOverrides.valueAt(u, p)); + } + } + if (printedVips) { + pw.println(); + } else { + pw.print(" None"); + } + pw.println(); + pw.println(); mCompleteEconomicPolicy.dump(pw); diff --git a/apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java b/apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java index e7db1adc859e5..03c5fdd632507 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java @@ -151,7 +151,6 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy { private long mHardSatiatedConsumptionLimit; private final KeyValueListParser mParser = new KeyValueListParser(','); - private final InternalResourceService mInternalResourceService; private final Injector mInjector; private final SparseArray mActions = new SparseArray<>(); @@ -159,7 +158,6 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy { JobSchedulerEconomicPolicy(InternalResourceService irs, Injector injector) { super(irs); - mInternalResourceService = irs; mInjector = injector; loadConstants("", null); } @@ -167,14 +165,14 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy { @Override void setup(@NonNull DeviceConfig.Properties properties) { super.setup(properties); - ContentResolver resolver = mInternalResourceService.getContext().getContentResolver(); + final ContentResolver resolver = mIrs.getContext().getContentResolver(); loadConstants(mInjector.getSettingsGlobalString(resolver, TARE_JOB_SCHEDULER_CONSTANTS), properties); } @Override long getMinSatiatedBalance(final int userId, @NonNull final String pkgName) { - if (mInternalResourceService.isPackageExempted(userId, pkgName)) { + if (mIrs.isPackageExempted(userId, pkgName)) { return mMinSatiatedBalanceExempted; } // TODO: take other exemptions into account diff --git a/apex/jobscheduler/service/java/com/android/server/tare/TareShellCommand.java b/apex/jobscheduler/service/java/com/android/server/tare/TareShellCommand.java new file mode 100644 index 0000000000000..5e380b408d013 --- /dev/null +++ b/apex/jobscheduler/service/java/com/android/server/tare/TareShellCommand.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.tare; + +import android.Manifest; +import android.annotation.NonNull; +import android.content.pm.PackageManager; +import android.os.Binder; + +import com.android.modules.utils.BasicShellCommandHandler; + +import java.io.PrintWriter; + +/** + * Shell command handler for TARE. + */ +public class TareShellCommand extends BasicShellCommandHandler { + static final int COMMAND_ERROR = -1; + static final int COMMAND_SUCCESS = 0; + + private final InternalResourceService mIrs; + + public TareShellCommand(@NonNull InternalResourceService irs) { + mIrs = irs; + } + + @Override + public int onCommand(String cmd) { + final PrintWriter pw = getOutPrintWriter(); + try { + switch (cmd != null ? cmd : "") { + case "clear-vip": + return runClearVip(pw); + case "set-vip": + return runSetVip(pw); + default: + return handleDefaultCommands(cmd); + } + } catch (Exception e) { + pw.println("Exception: " + e); + } + return COMMAND_ERROR; + } + + @Override + public void onHelp() { + final PrintWriter pw = getOutPrintWriter(); + + pw.println("TARE commands:"); + pw.println(" help"); + pw.println(" Print this help text."); + pw.println(" clear-vip"); + pw.println(" Clears all VIP settings resulting from previous calls using `set-vip` and"); + pw.println(" resets them all to default."); + pw.println(" set-vip "); + pw.println(" Designate the app as a Very Important Package or not. A VIP is allowed to"); + pw.println(" do as much work as it wants, regardless of TARE state."); + pw.println(" The user ID must be an explicit user ID. USER_ALL, CURRENT, etc. are not"); + pw.println(" supported."); + pw.println(); + } + + private void checkPermission(@NonNull String operation) throws Exception { + final int perm = mIrs.getContext() + .checkCallingOrSelfPermission(Manifest.permission.CHANGE_APP_IDLE_STATE); + if (perm != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Uid " + Binder.getCallingUid() + + " not permitted to " + operation); + } + } + + private int runClearVip(@NonNull PrintWriter pw) throws Exception { + checkPermission("clear vip"); + + final long ident = Binder.clearCallingIdentity(); + try { + return mIrs.executeClearVip(pw); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + private int runSetVip(@NonNull PrintWriter pw) throws Exception { + checkPermission("modify vip"); + + final int userId = Integer.parseInt(getNextArgRequired()); + final String pkgName = getNextArgRequired(); + final String vipState = getNextArgRequired(); + final Boolean isVip = "default".equals(vipState) ? null : Boolean.valueOf(vipState); + + final long ident = Binder.clearCallingIdentity(); + try { + return mIrs.executeSetVip(pw, userId, pkgName, isVip); + } finally { + Binder.restoreCallingIdentity(ident); + } + } +} diff --git a/services/tests/servicestests/src/com/android/server/tare/AgentTrendCalculatorTest.java b/services/tests/mockingservicestests/src/com/android/server/tare/AgentTrendCalculatorTest.java similarity index 98% rename from services/tests/servicestests/src/com/android/server/tare/AgentTrendCalculatorTest.java rename to services/tests/mockingservicestests/src/com/android/server/tare/AgentTrendCalculatorTest.java index 9e986be99e953..da7664b822944 100644 --- a/services/tests/servicestests/src/com/android/server/tare/AgentTrendCalculatorTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/tare/AgentTrendCalculatorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 The Android Open Source Project + * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,10 @@ package com.android.server.tare; 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 static org.mockito.Mockito.when; import android.util.ArraySet; import android.util.SparseLongArray; @@ -99,7 +102,9 @@ public class AgentTrendCalculatorTest { @Before public void setUp() { - mEconomicPolicy = new MockEconomicPolicy(mock(InternalResourceService.class)); + final InternalResourceService irs = mock(InternalResourceService.class); + when(irs.isVip(anyInt(), anyString())).thenReturn(false); + mEconomicPolicy = new MockEconomicPolicy(irs); } @Test