Merge "Give installers exemptions after first setup."

This commit is contained in:
TreeHugger Robot
2022-11-29 21:35:57 +00:00
committed by Android (Google) Code Review
7 changed files with 256 additions and 15 deletions

View File

@@ -286,7 +286,7 @@ class Agent {
for (int i = 0; i < pkgNames.size(); ++i) {
final String pkgName = pkgNames.valueAt(i);
final boolean isVip = mIrs.isVip(userId, pkgName);
final boolean isVip = mIrs.isVip(userId, pkgName, nowElapsed);
SparseArrayMap<String, OngoingEvent> ongoingEvents =
mCurrentOngoingEvents.get(userId, pkgName);
if (ongoingEvents != null) {
@@ -321,7 +321,7 @@ class Agent {
final long nowElapsed = SystemClock.elapsedRealtime();
final CompleteEconomicPolicy economicPolicy = mIrs.getCompleteEconomicPolicyLocked();
final boolean isVip = mIrs.isVip(userId, pkgName);
final boolean isVip = mIrs.isVip(userId, pkgName, nowElapsed);
SparseArrayMap<String, OngoingEvent> ongoingEvents =
mCurrentOngoingEvents.get(userId, pkgName);
if (ongoingEvents != null) {
@@ -397,7 +397,7 @@ class Agent {
if (actionAffordabilityNotes != null) {
final int size = actionAffordabilityNotes.size();
final long newBalance = getBalanceLocked(userId, pkgName);
final boolean isVip = mIrs.isVip(userId, pkgName);
final boolean isVip = mIrs.isVip(userId, pkgName, nowElapsed);
for (int n = 0; n < size; ++n) {
final ActionAffordabilityNote note = actionAffordabilityNotes.valueAt(n);
note.recalculateCosts(economicPolicy, userId, pkgName);
@@ -503,7 +503,8 @@ class Agent {
"Tried to adjust system balance for " + appToString(userId, pkgName));
return;
}
if (mIrs.isVip(userId, pkgName)) {
final boolean isVip = mIrs.isVip(userId, pkgName);
if (isVip) {
// 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.
@@ -536,7 +537,6 @@ 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 = isVip
@@ -830,7 +830,6 @@ class Agent {
@GuardedBy("mLock")
void onUserRemovedLocked(final int userId) {
mScribe.discardLedgersLocked(userId);
mCurrentOngoingEvents.delete(userId);
mBalanceThresholdAlarmQueue.removeAlarmsForUserId(userId);
}

View File

@@ -16,14 +16,20 @@
package com.android.server.tare;
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppGlobals;
import android.content.Context;
import android.content.PermissionChecker;
import android.content.pm.ApplicationInfo;
import android.content.pm.InstallSourceInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.RemoteException;
import com.android.internal.util.ArrayUtils;
/** POJO to cache only the information about installed packages that TARE cares about. */
class InstalledPackageInfo {
static final int NO_UID = -1;
@@ -31,14 +37,22 @@ class InstalledPackageInfo {
public final int uid;
public final String packageName;
public final boolean hasCode;
public final boolean isSystemInstaller;
@Nullable
public final String installerPackageName;
InstalledPackageInfo(@NonNull PackageInfo packageInfo) {
InstalledPackageInfo(@NonNull Context context, @NonNull PackageInfo packageInfo) {
final ApplicationInfo applicationInfo = packageInfo.applicationInfo;
uid = applicationInfo == null ? NO_UID : applicationInfo.uid;
packageName = packageInfo.packageName;
hasCode = applicationInfo != null && applicationInfo.hasCode();
isSystemInstaller = applicationInfo != null
&& ArrayUtils.indexOf(
packageInfo.requestedPermissions, Manifest.permission.INSTALL_PACKAGES) >= 0
&& PackageManager.PERMISSION_GRANTED
== PermissionChecker.checkPermissionForPreflight(context,
Manifest.permission.INSTALL_PACKAGES, PermissionChecker.PID_UNKNOWN,
applicationInfo.uid, packageName);
InstallSourceInfo installSourceInfo = null;
try {
installSourceInfo = AppGlobals.getPackageManager().getInstallSourceInfo(packageName);

View File

@@ -64,6 +64,7 @@ import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArrayMap;
import android.util.SparseLongArray;
import android.util.SparseSetArray;
import com.android.internal.annotations.GuardedBy;
@@ -107,6 +108,16 @@ public class InternalResourceService extends SystemService {
private static final long MIN_UNUSED_TIME_MS = 3 * DAY_IN_MILLIS;
/** The amount of time to delay reclamation by after boot. */
private static final long RECLAMATION_STARTUP_DELAY_MS = 30_000L;
/**
* The amount of time after TARE has first been set up that a system installer will be allowed
* expanded credit privileges.
*/
static final long INSTALLER_FIRST_SETUP_GRACE_PERIOD_MS = 7 * DAY_IN_MILLIS;
/**
* The amount of time to wait after TARE has first been set up before considering adjusting the
* stock/consumption limit.
*/
private static final long STOCK_ADJUSTMENT_FIRST_SETUP_GRACE_PERIOD_MS = 5 * DAY_IN_MILLIS;
/**
* The battery level above which we may consider quantitative easing (increasing the consumption
* limit).
@@ -127,7 +138,7 @@ public class InternalResourceService extends SystemService {
private static final long STOCK_RECALCULATION_MIN_DATA_DURATION_MS = 8 * HOUR_IN_MILLIS;
private static final int PACKAGE_QUERY_FLAGS =
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
| PackageManager.MATCH_APEX;
| PackageManager.MATCH_APEX | PackageManager.GET_PERMISSIONS;
/** Global lock for all resource economy state. */
private final Object mLock = new Object();
@@ -179,6 +190,13 @@ public class InternalResourceService extends SystemService {
@GuardedBy("mLock")
private final SparseArrayMap<String, Boolean> mVipOverrides = new SparseArrayMap<>();
/**
* Set of temporary Very Important Packages and when their VIP status ends, in the elapsed
* realtime ({@link android.annotation.ElapsedRealtimeLong}) timebase.
*/
@GuardedBy("mLock")
private final SparseArrayMap<String, Long> mTemporaryVips = new SparseArrayMap<>();
/** Set of apps each installer is responsible for installing. */
@GuardedBy("mLock")
private final SparseArrayMap<String, ArraySet<String>> mInstallers = new SparseArrayMap<>();
@@ -308,6 +326,7 @@ public class InternalResourceService extends SystemService {
private static final int MSG_PROCESS_USAGE_EVENT = 2;
private static final int MSG_NOTIFY_STATE_CHANGE_LISTENERS = 3;
private static final int MSG_NOTIFY_STATE_CHANGE_LISTENER = 4;
private static final int MSG_CLEAN_UP_TEMP_VIP_LIST = 5;
private static final String ALARM_TAG_WEALTH_RECLAMATION = "*tare.reclamation*";
/**
@@ -413,6 +432,13 @@ public class InternalResourceService extends SystemService {
return userPkgs;
}
@Nullable
InstalledPackageInfo getInstalledPackageInfo(final int userId, @NonNull final String pkgName) {
synchronized (mLock) {
return mPkgCache.get(userId, pkgName);
}
}
@GuardedBy("mLock")
long getConsumptionLimitLocked() {
return mCurrentBatteryLevel * mScribe.getSatiatedConsumptionLimitLocked() / 100;
@@ -429,6 +455,11 @@ public class InternalResourceService extends SystemService {
return mCompleteEconomicPolicy.getInitialSatiatedConsumptionLimit();
}
long getRealtimeSinceFirstSetupMs() {
return mScribe.getRealtimeSinceFirstSetupMs(SystemClock.elapsedRealtime());
}
int getUid(final int userId, @NonNull final String pkgName) {
synchronized (mPackageToUidCache) {
Integer uid = mPackageToUidCache.get(userId, pkgName);
@@ -470,6 +501,10 @@ public class InternalResourceService extends SystemService {
}
boolean isVip(final int userId, @NonNull String pkgName) {
return isVip(userId, pkgName, SystemClock.elapsedRealtime());
}
boolean isVip(final int userId, @NonNull String pkgName, final long nowElapsed) {
synchronized (mLock) {
final Boolean override = mVipOverrides.get(userId, pkgName);
if (override != null) {
@@ -481,6 +516,12 @@ public class InternalResourceService extends SystemService {
// operate.
return true;
}
synchronized (mLock) {
final Long expirationTimeElapsed = mTemporaryVips.get(userId, pkgName);
if (expirationTimeElapsed != null) {
return nowElapsed <= expirationTimeElapsed;
}
}
return false;
}
@@ -569,7 +610,7 @@ public class InternalResourceService extends SystemService {
mPackageToUidCache.add(userId, pkgName, uid);
}
synchronized (mLock) {
final InstalledPackageInfo ipo = new InstalledPackageInfo(packageInfo);
final InstalledPackageInfo ipo = new InstalledPackageInfo(getContext(), packageInfo);
final InstalledPackageInfo oldIpo = mPkgCache.add(userId, pkgName, ipo);
maybeUpdateInstallerStatusLocked(oldIpo, ipo);
mUidToPackageCache.add(uid, pkgName);
@@ -626,11 +667,16 @@ public class InternalResourceService extends SystemService {
final List<PackageInfo> pkgs =
mPackageManager.getInstalledPackagesAsUser(PACKAGE_QUERY_FLAGS, userId);
for (int i = pkgs.size() - 1; i >= 0; --i) {
final InstalledPackageInfo ipo = new InstalledPackageInfo(pkgs.get(i));
final InstalledPackageInfo ipo =
new InstalledPackageInfo(getContext(), pkgs.get(i));
final InstalledPackageInfo oldIpo = mPkgCache.add(userId, ipo.packageName, ipo);
maybeUpdateInstallerStatusLocked(oldIpo, ipo);
}
mAgent.grantBirthrightsLocked(userId);
final long nowElapsed = SystemClock.elapsedRealtime();
mScribe.setUserAddedTimeLocked(userId, nowElapsed);
grantInstallersTemporaryVipStatusLocked(userId,
nowElapsed, INSTALLER_FIRST_SETUP_GRACE_PERIOD_MS);
}
}
@@ -647,6 +693,7 @@ public class InternalResourceService extends SystemService {
mInstallers.delete(userId);
mPkgCache.delete(userId);
mAgent.onUserRemovedLocked(userId);
mScribe.onUserRemovedLocked(userId);
}
}
@@ -659,6 +706,10 @@ public class InternalResourceService extends SystemService {
maybeAdjustDesiredStockLevelLocked();
return;
}
if (getRealtimeSinceFirstSetupMs() < STOCK_ADJUSTMENT_FIRST_SETUP_GRACE_PERIOD_MS) {
// Things can be very tumultuous soon after first setup.
return;
}
// We don't need to increase the limit if the device runs out of consumable credits
// when the battery is low.
final long remainingConsumableCakes = mScribe.getRemainingConsumableCakesLocked();
@@ -687,6 +738,10 @@ public class InternalResourceService extends SystemService {
if (!mConfigObserver.ENABLE_TIP3) {
return;
}
if (getRealtimeSinceFirstSetupMs() < STOCK_ADJUSTMENT_FIRST_SETUP_GRACE_PERIOD_MS) {
// Things can be very tumultuous soon after first setup.
return;
}
// Don't adjust the limit too often or while the battery is low.
final long now = getCurrentTimeMillis();
if ((now - mScribe.getLastStockRecalculationTimeLocked()) < STOCK_RECALCULATION_DELAY_MS
@@ -775,6 +830,28 @@ public class InternalResourceService extends SystemService {
mAgent.onCreditSupplyChanged();
}
@GuardedBy("mLock")
private void grantInstallersTemporaryVipStatusLocked(int userId, long nowElapsed,
long grantDurationMs) {
final long grantEndTimeElapsed = nowElapsed + grantDurationMs;
final int uIdx = mPkgCache.indexOfKey(userId);
if (uIdx < 0) {
return;
}
for (int pIdx = mPkgCache.numElementsForKey(uIdx) - 1; pIdx >= 0; --pIdx) {
final InstalledPackageInfo ipo = mPkgCache.valueAt(uIdx, pIdx);
if (ipo.isSystemInstaller) {
final Long currentGrantEndTimeElapsed = mTemporaryVips.get(userId, ipo.packageName);
if (currentGrantEndTimeElapsed == null
|| currentGrantEndTimeElapsed < grantEndTimeElapsed) {
mTemporaryVips.add(userId, ipo.packageName, grantEndTimeElapsed);
}
}
}
mHandler.sendEmptyMessageDelayed(MSG_CLEAN_UP_TEMP_VIP_LIST, grantDurationMs);
}
@GuardedBy("mLock")
private void processUsageEventLocked(final int userId, @NonNull UsageEvents.Event event) {
if (!mIsEnabled) {
@@ -870,7 +947,8 @@ public class InternalResourceService extends SystemService {
final List<PackageInfo> pkgs =
mPackageManager.getInstalledPackagesAsUser(PACKAGE_QUERY_FLAGS, userId);
for (int i = pkgs.size() - 1; i >= 0; --i) {
final InstalledPackageInfo ipo = new InstalledPackageInfo(pkgs.get(i));
final InstalledPackageInfo ipo =
new InstalledPackageInfo(getContext(), pkgs.get(i));
final InstalledPackageInfo oldIpo = mPkgCache.add(userId, ipo.packageName, ipo);
maybeUpdateInstallerStatusLocked(oldIpo, ipo);
}
@@ -953,11 +1031,17 @@ public class InternalResourceService extends SystemService {
synchronized (mLock) {
mCompleteEconomicPolicy.setup(mConfigObserver.getAllDeviceConfigProperties());
loadInstalledPackageListLocked();
final SparseLongArray timeSinceUsersAdded;
final boolean isFirstSetup = !mScribe.recordExists();
final long nowElapsed = SystemClock.elapsedRealtime();
if (isFirstSetup) {
mAgent.grantBirthrightsLocked();
mScribe.setConsumptionLimitLocked(
mCompleteEconomicPolicy.getInitialSatiatedConsumptionLimit());
// Set the last reclamation time to now so we don't start reclaiming assets
// too early.
mScribe.setLastReclamationTimeLocked(getCurrentTimeMillis());
timeSinceUsersAdded = new SparseLongArray();
} else {
mScribe.loadFromDiskLocked();
if (mScribe.getSatiatedConsumptionLimitLocked()
@@ -971,6 +1055,21 @@ public class InternalResourceService extends SystemService {
// Adjust the supply in case battery level changed while the device was off.
adjustCreditSupplyLocked(true);
}
timeSinceUsersAdded = mScribe.getRealtimeSinceUsersAddedLocked(nowElapsed);
}
final int[] userIds = LocalServices.getService(UserManagerInternal.class).getUserIds();
for (int userId : userIds) {
final long timeSinceUserAddedMs = timeSinceUsersAdded.get(userId, 0);
// Temporarily mark installers as VIPs so they aren't subject to credit
// limits and policies on first boot.
if (timeSinceUserAddedMs < INSTALLER_FIRST_SETUP_GRACE_PERIOD_MS) {
final long remainingGraceDurationMs =
INSTALLER_FIRST_SETUP_GRACE_PERIOD_MS - timeSinceUserAddedMs;
grantInstallersTemporaryVipStatusLocked(userId, nowElapsed,
remainingGraceDurationMs);
}
}
scheduleUnusedWealthReclamationLocked();
}
@@ -1079,6 +1178,36 @@ public class InternalResourceService extends SystemService {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_CLEAN_UP_TEMP_VIP_LIST: {
removeMessages(MSG_CLEAN_UP_TEMP_VIP_LIST);
synchronized (mLock) {
final long nowElapsed = SystemClock.elapsedRealtime();
long earliestExpiration = Long.MAX_VALUE;
for (int u = 0; u < mTemporaryVips.numMaps(); ++u) {
final int userId = mTemporaryVips.keyAt(u);
for (int p = mTemporaryVips.numElementsForKeyAt(u) - 1; p >= 0; --p) {
final String pkgName = mTemporaryVips.keyAt(u, p);
final Long expiration = mTemporaryVips.valueAt(u, p);
if (expiration == null || expiration < nowElapsed) {
mTemporaryVips.delete(userId, pkgName);
} else {
earliestExpiration = Math.min(earliestExpiration, expiration);
}
}
}
if (earliestExpiration < Long.MAX_VALUE) {
sendEmptyMessageDelayed(MSG_CLEAN_UP_TEMP_VIP_LIST,
earliestExpiration - nowElapsed);
}
}
}
break;
case MSG_NOTIFY_AFFORDABILITY_CHANGE_LISTENER: {
final SomeArgs args = (SomeArgs) msg.obj;
final int userId = args.argi1;
@@ -1558,6 +1687,7 @@ public class InternalResourceService extends SystemService {
boolean printedVips = false;
pw.println();
pw.print("VIPs:");
pw.increaseIndent();
for (int u = 0; u < mVipOverrides.numMaps(); ++u) {
final int userId = mVipOverrides.keyAt(u);
@@ -1576,6 +1706,32 @@ public class InternalResourceService extends SystemService {
} else {
pw.print(" None");
}
pw.decreaseIndent();
pw.println();
boolean printedTempVips = false;
pw.println();
pw.print("Temp VIPs:");
pw.increaseIndent();
for (int u = 0; u < mTemporaryVips.numMaps(); ++u) {
final int userId = mTemporaryVips.keyAt(u);
for (int p = 0; p < mTemporaryVips.numElementsForKeyAt(u); ++p) {
final String pkgName = mTemporaryVips.keyAt(u, p);
printedTempVips = true;
pw.println();
pw.print(appToString(userId, pkgName));
pw.print("=");
pw.print(mTemporaryVips.valueAt(u, p));
}
}
if (printedTempVips) {
pw.println();
} else {
pw.print(" None");
}
pw.decreaseIndent();
pw.println();
pw.println();

View File

@@ -117,6 +117,7 @@ import static com.android.server.tare.Modifier.COST_MODIFIER_CHARGING;
import static com.android.server.tare.Modifier.COST_MODIFIER_DEVICE_IDLE;
import static com.android.server.tare.Modifier.COST_MODIFIER_POWER_SAVE_MODE;
import static com.android.server.tare.Modifier.COST_MODIFIER_PROCESS_STATE;
import static com.android.server.tare.TareUtils.appToString;
import static com.android.server.tare.TareUtils.cakeToString;
import android.annotation.NonNull;
@@ -210,6 +211,22 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy {
if (mIrs.isPackageRestricted(userId, pkgName)) {
return 0;
}
final InstalledPackageInfo ipo = mIrs.getInstalledPackageInfo(userId, pkgName);
if (ipo == null) {
Slog.wtfStack(TAG,
"Tried to get max balance of invalid app: " + appToString(userId, pkgName));
} else {
// A system installer's max balance is elevated for some time after first boot so
// they can use jobs to download and install apps.
if (ipo.isSystemInstaller) {
final long timeSinceFirstSetupMs = mIrs.getRealtimeSinceFirstSetupMs();
final boolean stillExempted = timeSinceFirstSetupMs
< InternalResourceService.INSTALLER_FIRST_SETUP_GRACE_PERIOD_MS;
if (stillExempted) {
return mMaxSatiatedConsumptionLimit;
}
}
}
return mMaxSatiatedBalance;
}

View File

@@ -24,6 +24,7 @@ import static com.android.server.tare.TareUtils.cakeToString;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Environment;
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.AtomicFile;
@@ -33,6 +34,7 @@ import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseArrayMap;
import android.util.SparseLongArray;
import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
@@ -88,6 +90,7 @@ public class Scribe {
"lastStockRecalculationTime";
private static final String XML_ATTR_REMAINING_CONSUMABLE_CAKES = "remainingConsumableCakes";
private static final String XML_ATTR_CONSUMPTION_LIMIT = "consumptionLimit";
private static final String XML_ATTR_TIME_SINCE_FIRST_SETUP_MS = "timeSinceFirstSetup";
private static final String XML_ATTR_PR_DISCHARGE = "discharge";
private static final String XML_ATTR_PR_BATTERY_LEVEL = "batteryLevel";
private static final String XML_ATTR_PR_PROFIT = "profit";
@@ -112,6 +115,11 @@ public class Scribe {
private final InternalResourceService mIrs;
private final Analyst mAnalyst;
/**
* The value of elapsed realtime since TARE was first setup that was read from disk.
* This will only be changed when the persisted file is read.
*/
private long mLoadedTimeSinceFirstSetup;
@GuardedBy("mIrs.getLock()")
private long mLastReclamationTime;
@GuardedBy("mIrs.getLock()")
@@ -122,6 +130,9 @@ public class Scribe {
private long mRemainingConsumableCakes;
@GuardedBy("mIrs.getLock()")
private final SparseArrayMap<String, Ledger> mLedgers = new SparseArrayMap<>();
/** Offsets used to calculate the total realtime since each user was added. */
@GuardedBy("mIrs.getLock()")
private final SparseLongArray mRealtimeSinceUsersAddedOffsets = new SparseLongArray();
private final Runnable mCleanRunnable = this::cleanupLedgers;
private final Runnable mWriteRunnable = this::writeState;
@@ -163,8 +174,9 @@ public class Scribe {
}
@GuardedBy("mIrs.getLock()")
void discardLedgersLocked(final int userId) {
void onUserRemovedLocked(final int userId) {
mLedgers.delete(userId);
mRealtimeSinceUsersAddedOffsets.delete(userId);
postWrite();
}
@@ -215,12 +227,27 @@ public class Scribe {
return sum;
}
/** Returns the cumulative elapsed realtime since TARE was first setup. */
long getRealtimeSinceFirstSetupMs(long nowElapsed) {
return mLoadedTimeSinceFirstSetup + nowElapsed;
}
/** Returns the total amount of cakes that remain to be consumed. */
@GuardedBy("mIrs.getLock()")
long getRemainingConsumableCakesLocked() {
return mRemainingConsumableCakes;
}
@GuardedBy("mIrs.getLock()")
SparseLongArray getRealtimeSinceUsersAddedLocked(long nowElapsed) {
final SparseLongArray realtimes = new SparseLongArray();
for (int i = mRealtimeSinceUsersAddedOffsets.size() - 1; i >= 0; --i) {
realtimes.put(mRealtimeSinceUsersAddedOffsets.keyAt(i),
mRealtimeSinceUsersAddedOffsets.valueAt(i) + nowElapsed);
}
return realtimes;
}
@GuardedBy("mIrs.getLock()")
void loadFromDiskLocked() {
mLedgers.clear();
@@ -276,7 +303,8 @@ public class Scribe {
}
}
final long endTimeCutoff = System.currentTimeMillis() - MAX_TRANSACTION_AGE_MS;
final long now = System.currentTimeMillis();
final long endTimeCutoff = now - MAX_TRANSACTION_AGE_MS;
long earliestEndTime = Long.MAX_VALUE;
for (eventType = parser.next(); eventType != XmlPullParser.END_DOCUMENT;
eventType = parser.next()) {
@@ -294,6 +322,12 @@ public class Scribe {
parser.getAttributeLong(null, XML_ATTR_LAST_RECLAMATION_TIME);
mLastStockRecalculationTime = parser.getAttributeLong(null,
XML_ATTR_LAST_STOCK_RECALCULATION_TIME, 0);
mLoadedTimeSinceFirstSetup =
parser.getAttributeLong(null, XML_ATTR_TIME_SINCE_FIRST_SETUP_MS,
// If there's no recorded time since first setup, then
// offset the current elapsed time so it doesn't shift the
// timing too much.
-SystemClock.elapsedRealtime());
mSatiatedConsumptionLimit =
parser.getAttributeLong(null, XML_ATTR_CONSUMPTION_LIMIT,
mIrs.getInitialSatiatedConsumptionLimitLocked());
@@ -355,6 +389,13 @@ public class Scribe {
postWrite();
}
@GuardedBy("mIrs.getLock()")
void setUserAddedTimeLocked(int userId, long timeElapsed) {
// Use the current time as an offset so that when we persist the time, it correctly persists
// as "time since now".
mRealtimeSinceUsersAddedOffsets.put(userId, -timeElapsed);
}
@GuardedBy("mIrs.getLock()")
void tearDownLocked() {
TareHandlerThread.getHandler().removeCallbacks(mCleanRunnable);
@@ -486,6 +527,14 @@ public class Scribe {
// Don't return early since we need to go through all the ledger tags and get to the end
// of the user tag.
}
if (curUser != UserHandle.USER_NULL) {
mRealtimeSinceUsersAddedOffsets.put(curUser,
parser.getAttributeLong(null, XML_ATTR_TIME_SINCE_FIRST_SETUP_MS,
// If there's no recorded time since first setup, then
// offset the current elapsed time so it doesn't shift the
// timing too much.
-SystemClock.elapsedRealtime()));
}
long earliestEndTime = Long.MAX_VALUE;
for (int eventType = parser.next(); eventType != XmlPullParser.END_DOCUMENT;
@@ -630,6 +679,8 @@ public class Scribe {
out.attributeLong(null, XML_ATTR_LAST_RECLAMATION_TIME, mLastReclamationTime);
out.attributeLong(null,
XML_ATTR_LAST_STOCK_RECALCULATION_TIME, mLastStockRecalculationTime);
out.attributeLong(null, XML_ATTR_TIME_SINCE_FIRST_SETUP_MS,
mLoadedTimeSinceFirstSetup + SystemClock.elapsedRealtime());
out.attributeLong(null, XML_ATTR_CONSUMPTION_LIMIT, mSatiatedConsumptionLimit);
out.attributeLong(null, XML_ATTR_REMAINING_CONSUMABLE_CAKES,
mRemainingConsumableCakes);
@@ -665,6 +716,9 @@ public class Scribe {
out.startTag(null, XML_TAG_USER);
out.attributeInt(null, XML_ATTR_USER_ID, userId);
out.attributeLong(null, XML_ATTR_TIME_SINCE_FIRST_SETUP_MS,
mRealtimeSinceUsersAddedOffsets.get(userId,
mLoadedTimeSinceFirstSetup + SystemClock.elapsedRealtime()));
for (int pIdx = mLedgers.numElementsForKey(userId) - 1; pIdx >= 0; --pIdx) {
final String pkgName = mLedgers.keyAt(uIdx, pIdx);
final Ledger ledger = mLedgers.get(userId, pkgName);

View File

@@ -18,6 +18,7 @@ package com.android.server.tare;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -108,7 +109,7 @@ public class AgentTrendCalculatorTest {
@Before
public void setUp() {
final InternalResourceService irs = mock(InternalResourceService.class);
when(irs.isVip(anyInt(), anyString())).thenReturn(false);
when(irs.isVip(anyInt(), anyString(), anyLong())).thenReturn(false);
mEconomicPolicy = new MockEconomicPolicy(irs);
}

View File

@@ -402,6 +402,6 @@ public class ScribeTest {
ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.uid = UserHandle.getUid(userId, Math.abs(pkgName.hashCode()));
pkgInfo.applicationInfo = applicationInfo;
mInstalledPackages.add(userId, pkgName, new InstalledPackageInfo(pkgInfo));
mInstalledPackages.add(userId, pkgName, new InstalledPackageInfo(getContext(), pkgInfo));
}
}