Merge "Give installers exemptions after first setup."
This commit is contained in:
committed by
Android (Google) Code Review
commit
2d8b2c396c
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user