Merge "Add shell command so tests aren't hindered."
This commit is contained in:
committed by
Android (Google) Code Review
commit
63979bd540
@@ -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<String, OngoingEvent> 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<String, OngoingEvent> ongoingEvents =
|
||||
mCurrentOngoingEvents.get(userId, pkgName);
|
||||
if (ongoingEvents != null) {
|
||||
mOngoingEventUpdater.reset(userId, pkgName, now, nowElapsed);
|
||||
ongoingEvents.forEach(mOngoingEventUpdater);
|
||||
}
|
||||
final ArraySet<ActionAffordabilityNote> 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<String> 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<String, OngoingEvent> 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);
|
||||
|
||||
@@ -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<Action> 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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<String> mExemptedApps = new ArraySet<>();
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private final SparseArrayMap<String, Boolean> 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<String> 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<String> 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);
|
||||
|
||||
|
||||
@@ -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<Action> 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
|
||||
|
||||
@@ -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 <USER_ID> <PACKAGE> <true|false|default>");
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user