Loading apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java +12 −0 Original line number Diff line number Diff line Loading @@ -227,6 +227,9 @@ public class EconomyManager { public static final String KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP = "js_min_satiated_balance_other_app"; /** @hide */ public static final String KEY_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER = "js_min_satiated_balance_increment_updater"; /** @hide */ public static final String KEY_JS_MAX_SATIATED_BALANCE = "js_max_satiated_balance"; /** @hide */ Loading Loading @@ -509,6 +512,15 @@ public class EconomyManager { public static final long DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_ONGOING_CAKES = arcToCake(0); /** @hide */ public static final long DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_MAX_CAKES = arcToCake(5000); /** * How many credits to increase the updating app's min satiated balance by for each app that it * is responsible for updating. * @hide */ public static final long DEFAULT_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER_CAKES = // Research indicates that the median time between popular app updates is 13-14 days, // so adjust by 14 to amortize over that time. DEFAULT_JS_REWARD_APP_INSTALL_INSTANT_CAKES / 14; /** @hide */ public static final long DEFAULT_JS_ACTION_JOB_MAX_START_CTP_CAKES = arcToCake(3); /** @hide */ Loading apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java +82 −4 Original line number Diff line number Diff line Loading @@ -81,6 +81,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.concurrent.CopyOnWriteArraySet; /** Loading Loading @@ -164,6 +165,10 @@ public class InternalResourceService extends SystemService { @GuardedBy("mLock") private final SparseArrayMap<String, Boolean> mVipOverrides = new SparseArrayMap<>(); /** Set of apps each installer is responsible for installing. */ @GuardedBy("mLock") private final SparseArrayMap<String, ArraySet<String>> mInstallers = new SparseArrayMap<>(); private volatile boolean mHasBattery = true; private volatile boolean mIsEnabled; private volatile int mBootPhase; Loading Loading @@ -353,6 +358,14 @@ public class InternalResourceService extends SystemService { return mCompleteEconomicPolicy; } /** Returns the number of apps that this app is expected to update at some point. */ int getAppUpdateResponsibilityCount(final int userId, @NonNull final String pkgName) { synchronized (mLock) { // TODO(248274798): return 0 if the app has lost the install permission return ArrayUtils.size(mInstallers.get(userId, pkgName)); } } @NonNull SparseArrayMap<String, InstalledPackageInfo> getInstalledPackages() { synchronized (mLock) { Loading Loading @@ -525,7 +538,8 @@ public class InternalResourceService extends SystemService { } synchronized (mLock) { final InstalledPackageInfo ipo = new InstalledPackageInfo(packageInfo); mPkgCache.add(userId, pkgName, ipo); final InstalledPackageInfo oldIpo = mPkgCache.add(userId, pkgName, ipo); maybeUpdateInstallerStatusLocked(oldIpo, ipo); mUidToPackageCache.add(uid, pkgName); // TODO: only do this when the user first launches the app (app leaves stopped state) mAgent.grantBirthrightLocked(userId, pkgName); Loading @@ -552,7 +566,14 @@ public class InternalResourceService extends SystemService { synchronized (mLock) { mUidToPackageCache.remove(uid, pkgName); mVipOverrides.delete(userId, pkgName); mPkgCache.delete(userId, pkgName); final InstalledPackageInfo ipo = mPkgCache.delete(userId, pkgName); mInstallers.delete(userId, pkgName); if (ipo != null && ipo.installerPackageName != null) { final ArraySet<String> list = mInstallers.get(userId, ipo.installerPackageName); if (list != null) { list.remove(pkgName); } } mAgent.onPackageRemovedLocked(userId, pkgName); } } Loading @@ -574,7 +595,8 @@ public class InternalResourceService extends SystemService { mPackageManager.getInstalledPackagesAsUser(PACKAGE_QUERY_FLAGS, userId); for (int i = pkgs.size() - 1; i >= 0; --i) { final InstalledPackageInfo ipo = new InstalledPackageInfo(pkgs.get(i)); mPkgCache.add(userId, ipo.packageName, ipo); final InstalledPackageInfo oldIpo = mPkgCache.add(userId, ipo.packageName, ipo); maybeUpdateInstallerStatusLocked(oldIpo, ipo); } mAgent.grantBirthrightsLocked(userId); } Loading @@ -590,6 +612,7 @@ public class InternalResourceService extends SystemService { mUidToPackageCache.remove(pkgInfo.uid); } } mInstallers.delete(userId); mPkgCache.delete(userId); mAgent.onUserRemovedLocked(userId); } Loading Loading @@ -746,11 +769,49 @@ public class InternalResourceService extends SystemService { mPackageManager.getInstalledPackagesAsUser(PACKAGE_QUERY_FLAGS, userId); for (int i = pkgs.size() - 1; i >= 0; --i) { final InstalledPackageInfo ipo = new InstalledPackageInfo(pkgs.get(i)); mPkgCache.add(userId, ipo.packageName, ipo); final InstalledPackageInfo oldIpo = mPkgCache.add(userId, ipo.packageName, ipo); maybeUpdateInstallerStatusLocked(oldIpo, ipo); } } } /** * Used to update the set of installed apps for each installer. This only has an effect if the * installer package name is different between {@code oldIpo} and {@code newIpo}. */ @GuardedBy("mLock") private void maybeUpdateInstallerStatusLocked(@Nullable InstalledPackageInfo oldIpo, @NonNull InstalledPackageInfo newIpo) { final boolean changed; if (oldIpo == null) { changed = newIpo.installerPackageName != null; } else { changed = !Objects.equals(oldIpo.installerPackageName, newIpo.installerPackageName); } if (!changed) { return; } // InstallSourceInfo doesn't track userId, so for now, assume the installer on the package's // user profile did the installation. // TODO(246640162): use the actual installer's user ID final int userId = UserHandle.getUserId(newIpo.uid); final String pkgName = newIpo.packageName; if (oldIpo != null) { final ArraySet<String> oldList = mInstallers.get(userId, oldIpo.installerPackageName); if (oldList != null) { oldList.remove(pkgName); } } if (newIpo.installerPackageName != null) { ArraySet<String> newList = mInstallers.get(userId, newIpo.installerPackageName); if (newList == null) { newList = new ArraySet<>(); mInstallers.add(userId, newIpo.installerPackageName, newList); } newList.add(pkgName); } } private void registerListeners() { final IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_BATTERY_CHANGED); Loading Loading @@ -1359,6 +1420,23 @@ public class InternalResourceService extends SystemService { } pw.println(); pw.println(); pw.println("Installers:"); pw.increaseIndent(); for (int u = 0; u < mInstallers.numMaps(); ++u) { final int userId = mInstallers.keyAt(u); for (int p = 0; p < mInstallers.numElementsForKeyAt(u); ++p) { final String pkgName = mInstallers.keyAt(u, p); pw.print(appToString(userId, pkgName)); pw.print(": "); pw.print(mInstallers.valueAt(u, p).size()); pw.println(" apps"); } } pw.decreaseIndent(); pw.println(); mCompleteEconomicPolicy.dump(pw); Loading apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java +20 −4 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import static android.app.tare.EconomyManager.DEFAULT_JS_HARD_CONSUMPTION_LIMIT_ import static android.app.tare.EconomyManager.DEFAULT_JS_INITIAL_CONSUMPTION_LIMIT_CAKES; import static android.app.tare.EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES; import static android.app.tare.EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED_CAKES; import static android.app.tare.EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER_CAKES; import static android.app.tare.EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_OTHER_APP_CAKES; import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_APP_INSTALL_INSTANT_CAKES; import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_APP_INSTALL_MAX_CAKES; Loading Loading @@ -87,6 +88,7 @@ import static android.app.tare.EconomyManager.KEY_JS_HARD_CONSUMPTION_LIMIT; import static android.app.tare.EconomyManager.KEY_JS_INITIAL_CONSUMPTION_LIMIT; import static android.app.tare.EconomyManager.KEY_JS_MAX_SATIATED_BALANCE; import static android.app.tare.EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED; import static android.app.tare.EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER; import static android.app.tare.EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP; import static android.app.tare.EconomyManager.KEY_JS_REWARD_APP_INSTALL_INSTANT; import static android.app.tare.EconomyManager.KEY_JS_REWARD_APP_INSTALL_MAX; Loading Loading @@ -154,6 +156,7 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy { private long mMinSatiatedBalanceExempted; private long mMinSatiatedBalanceOther; private long mMinSatiatedBalanceIncrementalAppUpdater; private long mMaxSatiatedBalance; private long mInitialSatiatedConsumptionLimit; private long mHardSatiatedConsumptionLimit; Loading Loading @@ -183,11 +186,20 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy { if (mIrs.isPackageRestricted(userId, pkgName)) { return 0; } final long baseBalance; if (mIrs.isPackageExempted(userId, pkgName)) { return mMinSatiatedBalanceExempted; baseBalance = mMinSatiatedBalanceExempted; } else { baseBalance = mMinSatiatedBalanceOther; } // TODO: take other exemptions into account return mMinSatiatedBalanceOther; long minBalance = baseBalance; final int updateResponsibilityCount = mIrs.getAppUpdateResponsibilityCount(userId, pkgName); minBalance += updateResponsibilityCount * mMinSatiatedBalanceIncrementalAppUpdater; return Math.min(minBalance, mMaxSatiatedBalance); } @Override Loading Loading @@ -242,6 +254,9 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy { mMinSatiatedBalanceExempted = getConstantAsCake(mParser, properties, KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED, DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED_CAKES, mMinSatiatedBalanceOther); mMinSatiatedBalanceIncrementalAppUpdater = getConstantAsCake(mParser, properties, KEY_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER, DEFAULT_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER_CAKES); mMaxSatiatedBalance = getConstantAsCake(mParser, properties, KEY_JS_MAX_SATIATED_BALANCE, DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES, Math.max(arcToCake(1), mMinSatiatedBalanceExempted)); Loading Loading @@ -397,10 +412,11 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy { @Override void dump(IndentingPrintWriter pw) { pw.println("Min satiated balances:"); pw.println("Min satiated balance:"); pw.increaseIndent(); pw.print("Exempted", cakeToString(mMinSatiatedBalanceExempted)).println(); pw.print("Other", cakeToString(mMinSatiatedBalanceOther)).println(); pw.print("+App Updater", cakeToString(mMinSatiatedBalanceIncrementalAppUpdater)).println(); pw.decreaseIndent(); pw.print("Max satiated balance", cakeToString(mMaxSatiatedBalance)).println(); pw.print("Consumption limits: ["); Loading apex/jobscheduler/service/java/com/android/server/tare/Ledger.java +1 −1 Original line number Diff line number Diff line Loading @@ -286,7 +286,7 @@ class Ledger { final int idx = (mRewardBucketIndex - b + NUM_REWARD_BUCKET_WINDOWS) % NUM_REWARD_BUCKET_WINDOWS; final RewardBucket rewardBucket = mRewardBuckets[idx]; if (rewardBucket == null) { if (rewardBucket == null || rewardBucket.startTimeMs == 0) { continue; } Loading services/tests/mockingservicestests/src/com/android/server/tare/JobSchedulerEconomicPolicyTest.java +39 −6 Original line number Diff line number Diff line Loading @@ -134,15 +134,36 @@ public class JobSchedulerEconomicPolicyTest { mEconomicPolicy.getInitialSatiatedConsumptionLimit()); assertEquals(EconomyManager.DEFAULT_JS_HARD_CONSUMPTION_LIMIT_CAKES, mEconomicPolicy.getHardSatiatedConsumptionLimit()); final String pkgRestricted = "com.pkg.restricted"; when(mIrs.isPackageRestricted(anyInt(), eq(pkgRestricted))).thenReturn(true); assertEquals(0, mEconomicPolicy.getMinSatiatedBalance(0, pkgRestricted)); assertEquals(0, mEconomicPolicy.getMaxSatiatedBalance(0, pkgRestricted)); assertEquals(EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES, mEconomicPolicy.getMaxSatiatedBalance(0, "com.any.other.app")); final String pkgExempted = "com.pkg.exempted"; when(mIrs.isPackageExempted(anyInt(), eq(pkgExempted))).thenReturn(true); assertEquals(EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED_CAKES, mEconomicPolicy.getMinSatiatedBalance(0, pkgExempted)); assertEquals(EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES, mEconomicPolicy.getMaxSatiatedBalance(0, pkgExempted)); final String pkgUpdater = "com.pkg.updater"; when(mIrs.getAppUpdateResponsibilityCount(anyInt(), eq(pkgUpdater))).thenReturn(5); assertEquals(5 * EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER_CAKES + EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_OTHER_APP_CAKES, mEconomicPolicy.getMinSatiatedBalance(0, pkgUpdater)); assertEquals(EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES, mEconomicPolicy.getMaxSatiatedBalance(0, pkgUpdater)); // Make sure it doesn't suggest a min balance greater than max. final int updateCount = (int) (EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES / EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER_CAKES); when(mIrs.getAppUpdateResponsibilityCount(anyInt(), eq(pkgUpdater))) .thenReturn(updateCount); assertEquals(EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES, mEconomicPolicy.getMinSatiatedBalance(0, pkgUpdater)); assertEquals(EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES, mEconomicPolicy.getMaxSatiatedBalance(0, "com.any.other.app")); assertEquals(EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_OTHER_APP_CAKES, mEconomicPolicy.getMinSatiatedBalance(0, "com.any.other.app")); } Loading @@ -152,8 +173,10 @@ public class JobSchedulerEconomicPolicyTest { setDeviceConfigCakes(EconomyManager.KEY_JS_INITIAL_CONSUMPTION_LIMIT, arcToCake(5)); setDeviceConfigCakes(EconomyManager.KEY_JS_HARD_CONSUMPTION_LIMIT, arcToCake(25)); setDeviceConfigCakes(EconomyManager.KEY_JS_MAX_SATIATED_BALANCE, arcToCake(10)); setDeviceConfigCakes(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED, arcToCake(9)); setDeviceConfigCakes(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP, arcToCake(7)); setDeviceConfigCakes(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED, arcToCake(6)); setDeviceConfigCakes(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP, arcToCake(4)); setDeviceConfigCakes(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER, arcToCake(1)); assertEquals(arcToCake(5), mEconomicPolicy.getInitialSatiatedConsumptionLimit()); assertEquals(arcToCake(25), mEconomicPolicy.getHardSatiatedConsumptionLimit()); Loading @@ -163,8 +186,12 @@ public class JobSchedulerEconomicPolicyTest { assertEquals(arcToCake(10), mEconomicPolicy.getMaxSatiatedBalance(0, "com.any.other.app")); final String pkgExempted = "com.pkg.exempted"; when(mIrs.isPackageExempted(anyInt(), eq(pkgExempted))).thenReturn(true); assertEquals(arcToCake(9), mEconomicPolicy.getMinSatiatedBalance(0, pkgExempted)); assertEquals(arcToCake(7), mEconomicPolicy.getMinSatiatedBalance(0, "com.any.other.app")); assertEquals(arcToCake(6), mEconomicPolicy.getMinSatiatedBalance(0, pkgExempted)); assertEquals(arcToCake(4), mEconomicPolicy.getMinSatiatedBalance(0, "com.any.other.app")); final String pkgUpdater = "com.pkg.updater"; when(mIrs.getAppUpdateResponsibilityCount(anyInt(), eq(pkgUpdater))).thenReturn(3); assertEquals(arcToCake(4) + 3 * arcToCake(1), mEconomicPolicy.getMinSatiatedBalance(0, pkgUpdater)); } @Test Loading @@ -175,6 +202,8 @@ public class JobSchedulerEconomicPolicyTest { setDeviceConfigCakes(EconomyManager.KEY_JS_MAX_SATIATED_BALANCE, arcToCake(-1)); setDeviceConfigCakes(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED, arcToCake(-2)); setDeviceConfigCakes(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP, arcToCake(-3)); setDeviceConfigCakes(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER, arcToCake(-4)); assertEquals(arcToCake(1), mEconomicPolicy.getInitialSatiatedConsumptionLimit()); assertEquals(arcToCake(1), mEconomicPolicy.getHardSatiatedConsumptionLimit()); Loading @@ -186,6 +215,10 @@ public class JobSchedulerEconomicPolicyTest { when(mIrs.isPackageExempted(anyInt(), eq(pkgExempted))).thenReturn(true); assertEquals(arcToCake(0), mEconomicPolicy.getMinSatiatedBalance(0, pkgExempted)); assertEquals(arcToCake(0), mEconomicPolicy.getMinSatiatedBalance(0, "com.any.other.app")); final String pkgUpdater = "com.pkg.updater"; when(mIrs.getAppUpdateResponsibilityCount(anyInt(), eq(pkgUpdater))).thenReturn(5); assertEquals(arcToCake(0) + 5 * arcToCake(0), mEconomicPolicy.getMinSatiatedBalance(0, pkgUpdater)); // Test min+max reversed. setDeviceConfigCakes(EconomyManager.KEY_JS_INITIAL_CONSUMPTION_LIMIT, arcToCake(5)); Loading Loading
apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java +12 −0 Original line number Diff line number Diff line Loading @@ -227,6 +227,9 @@ public class EconomyManager { public static final String KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP = "js_min_satiated_balance_other_app"; /** @hide */ public static final String KEY_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER = "js_min_satiated_balance_increment_updater"; /** @hide */ public static final String KEY_JS_MAX_SATIATED_BALANCE = "js_max_satiated_balance"; /** @hide */ Loading Loading @@ -509,6 +512,15 @@ public class EconomyManager { public static final long DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_ONGOING_CAKES = arcToCake(0); /** @hide */ public static final long DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_MAX_CAKES = arcToCake(5000); /** * How many credits to increase the updating app's min satiated balance by for each app that it * is responsible for updating. * @hide */ public static final long DEFAULT_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER_CAKES = // Research indicates that the median time between popular app updates is 13-14 days, // so adjust by 14 to amortize over that time. DEFAULT_JS_REWARD_APP_INSTALL_INSTANT_CAKES / 14; /** @hide */ public static final long DEFAULT_JS_ACTION_JOB_MAX_START_CTP_CAKES = arcToCake(3); /** @hide */ Loading
apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java +82 −4 Original line number Diff line number Diff line Loading @@ -81,6 +81,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.concurrent.CopyOnWriteArraySet; /** Loading Loading @@ -164,6 +165,10 @@ public class InternalResourceService extends SystemService { @GuardedBy("mLock") private final SparseArrayMap<String, Boolean> mVipOverrides = new SparseArrayMap<>(); /** Set of apps each installer is responsible for installing. */ @GuardedBy("mLock") private final SparseArrayMap<String, ArraySet<String>> mInstallers = new SparseArrayMap<>(); private volatile boolean mHasBattery = true; private volatile boolean mIsEnabled; private volatile int mBootPhase; Loading Loading @@ -353,6 +358,14 @@ public class InternalResourceService extends SystemService { return mCompleteEconomicPolicy; } /** Returns the number of apps that this app is expected to update at some point. */ int getAppUpdateResponsibilityCount(final int userId, @NonNull final String pkgName) { synchronized (mLock) { // TODO(248274798): return 0 if the app has lost the install permission return ArrayUtils.size(mInstallers.get(userId, pkgName)); } } @NonNull SparseArrayMap<String, InstalledPackageInfo> getInstalledPackages() { synchronized (mLock) { Loading Loading @@ -525,7 +538,8 @@ public class InternalResourceService extends SystemService { } synchronized (mLock) { final InstalledPackageInfo ipo = new InstalledPackageInfo(packageInfo); mPkgCache.add(userId, pkgName, ipo); final InstalledPackageInfo oldIpo = mPkgCache.add(userId, pkgName, ipo); maybeUpdateInstallerStatusLocked(oldIpo, ipo); mUidToPackageCache.add(uid, pkgName); // TODO: only do this when the user first launches the app (app leaves stopped state) mAgent.grantBirthrightLocked(userId, pkgName); Loading @@ -552,7 +566,14 @@ public class InternalResourceService extends SystemService { synchronized (mLock) { mUidToPackageCache.remove(uid, pkgName); mVipOverrides.delete(userId, pkgName); mPkgCache.delete(userId, pkgName); final InstalledPackageInfo ipo = mPkgCache.delete(userId, pkgName); mInstallers.delete(userId, pkgName); if (ipo != null && ipo.installerPackageName != null) { final ArraySet<String> list = mInstallers.get(userId, ipo.installerPackageName); if (list != null) { list.remove(pkgName); } } mAgent.onPackageRemovedLocked(userId, pkgName); } } Loading @@ -574,7 +595,8 @@ public class InternalResourceService extends SystemService { mPackageManager.getInstalledPackagesAsUser(PACKAGE_QUERY_FLAGS, userId); for (int i = pkgs.size() - 1; i >= 0; --i) { final InstalledPackageInfo ipo = new InstalledPackageInfo(pkgs.get(i)); mPkgCache.add(userId, ipo.packageName, ipo); final InstalledPackageInfo oldIpo = mPkgCache.add(userId, ipo.packageName, ipo); maybeUpdateInstallerStatusLocked(oldIpo, ipo); } mAgent.grantBirthrightsLocked(userId); } Loading @@ -590,6 +612,7 @@ public class InternalResourceService extends SystemService { mUidToPackageCache.remove(pkgInfo.uid); } } mInstallers.delete(userId); mPkgCache.delete(userId); mAgent.onUserRemovedLocked(userId); } Loading Loading @@ -746,11 +769,49 @@ public class InternalResourceService extends SystemService { mPackageManager.getInstalledPackagesAsUser(PACKAGE_QUERY_FLAGS, userId); for (int i = pkgs.size() - 1; i >= 0; --i) { final InstalledPackageInfo ipo = new InstalledPackageInfo(pkgs.get(i)); mPkgCache.add(userId, ipo.packageName, ipo); final InstalledPackageInfo oldIpo = mPkgCache.add(userId, ipo.packageName, ipo); maybeUpdateInstallerStatusLocked(oldIpo, ipo); } } } /** * Used to update the set of installed apps for each installer. This only has an effect if the * installer package name is different between {@code oldIpo} and {@code newIpo}. */ @GuardedBy("mLock") private void maybeUpdateInstallerStatusLocked(@Nullable InstalledPackageInfo oldIpo, @NonNull InstalledPackageInfo newIpo) { final boolean changed; if (oldIpo == null) { changed = newIpo.installerPackageName != null; } else { changed = !Objects.equals(oldIpo.installerPackageName, newIpo.installerPackageName); } if (!changed) { return; } // InstallSourceInfo doesn't track userId, so for now, assume the installer on the package's // user profile did the installation. // TODO(246640162): use the actual installer's user ID final int userId = UserHandle.getUserId(newIpo.uid); final String pkgName = newIpo.packageName; if (oldIpo != null) { final ArraySet<String> oldList = mInstallers.get(userId, oldIpo.installerPackageName); if (oldList != null) { oldList.remove(pkgName); } } if (newIpo.installerPackageName != null) { ArraySet<String> newList = mInstallers.get(userId, newIpo.installerPackageName); if (newList == null) { newList = new ArraySet<>(); mInstallers.add(userId, newIpo.installerPackageName, newList); } newList.add(pkgName); } } private void registerListeners() { final IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_BATTERY_CHANGED); Loading Loading @@ -1359,6 +1420,23 @@ public class InternalResourceService extends SystemService { } pw.println(); pw.println(); pw.println("Installers:"); pw.increaseIndent(); for (int u = 0; u < mInstallers.numMaps(); ++u) { final int userId = mInstallers.keyAt(u); for (int p = 0; p < mInstallers.numElementsForKeyAt(u); ++p) { final String pkgName = mInstallers.keyAt(u, p); pw.print(appToString(userId, pkgName)); pw.print(": "); pw.print(mInstallers.valueAt(u, p).size()); pw.println(" apps"); } } pw.decreaseIndent(); pw.println(); mCompleteEconomicPolicy.dump(pw); Loading
apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java +20 −4 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import static android.app.tare.EconomyManager.DEFAULT_JS_HARD_CONSUMPTION_LIMIT_ import static android.app.tare.EconomyManager.DEFAULT_JS_INITIAL_CONSUMPTION_LIMIT_CAKES; import static android.app.tare.EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES; import static android.app.tare.EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED_CAKES; import static android.app.tare.EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER_CAKES; import static android.app.tare.EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_OTHER_APP_CAKES; import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_APP_INSTALL_INSTANT_CAKES; import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_APP_INSTALL_MAX_CAKES; Loading Loading @@ -87,6 +88,7 @@ import static android.app.tare.EconomyManager.KEY_JS_HARD_CONSUMPTION_LIMIT; import static android.app.tare.EconomyManager.KEY_JS_INITIAL_CONSUMPTION_LIMIT; import static android.app.tare.EconomyManager.KEY_JS_MAX_SATIATED_BALANCE; import static android.app.tare.EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED; import static android.app.tare.EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER; import static android.app.tare.EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP; import static android.app.tare.EconomyManager.KEY_JS_REWARD_APP_INSTALL_INSTANT; import static android.app.tare.EconomyManager.KEY_JS_REWARD_APP_INSTALL_MAX; Loading Loading @@ -154,6 +156,7 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy { private long mMinSatiatedBalanceExempted; private long mMinSatiatedBalanceOther; private long mMinSatiatedBalanceIncrementalAppUpdater; private long mMaxSatiatedBalance; private long mInitialSatiatedConsumptionLimit; private long mHardSatiatedConsumptionLimit; Loading Loading @@ -183,11 +186,20 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy { if (mIrs.isPackageRestricted(userId, pkgName)) { return 0; } final long baseBalance; if (mIrs.isPackageExempted(userId, pkgName)) { return mMinSatiatedBalanceExempted; baseBalance = mMinSatiatedBalanceExempted; } else { baseBalance = mMinSatiatedBalanceOther; } // TODO: take other exemptions into account return mMinSatiatedBalanceOther; long minBalance = baseBalance; final int updateResponsibilityCount = mIrs.getAppUpdateResponsibilityCount(userId, pkgName); minBalance += updateResponsibilityCount * mMinSatiatedBalanceIncrementalAppUpdater; return Math.min(minBalance, mMaxSatiatedBalance); } @Override Loading Loading @@ -242,6 +254,9 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy { mMinSatiatedBalanceExempted = getConstantAsCake(mParser, properties, KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED, DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED_CAKES, mMinSatiatedBalanceOther); mMinSatiatedBalanceIncrementalAppUpdater = getConstantAsCake(mParser, properties, KEY_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER, DEFAULT_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER_CAKES); mMaxSatiatedBalance = getConstantAsCake(mParser, properties, KEY_JS_MAX_SATIATED_BALANCE, DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES, Math.max(arcToCake(1), mMinSatiatedBalanceExempted)); Loading Loading @@ -397,10 +412,11 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy { @Override void dump(IndentingPrintWriter pw) { pw.println("Min satiated balances:"); pw.println("Min satiated balance:"); pw.increaseIndent(); pw.print("Exempted", cakeToString(mMinSatiatedBalanceExempted)).println(); pw.print("Other", cakeToString(mMinSatiatedBalanceOther)).println(); pw.print("+App Updater", cakeToString(mMinSatiatedBalanceIncrementalAppUpdater)).println(); pw.decreaseIndent(); pw.print("Max satiated balance", cakeToString(mMaxSatiatedBalance)).println(); pw.print("Consumption limits: ["); Loading
apex/jobscheduler/service/java/com/android/server/tare/Ledger.java +1 −1 Original line number Diff line number Diff line Loading @@ -286,7 +286,7 @@ class Ledger { final int idx = (mRewardBucketIndex - b + NUM_REWARD_BUCKET_WINDOWS) % NUM_REWARD_BUCKET_WINDOWS; final RewardBucket rewardBucket = mRewardBuckets[idx]; if (rewardBucket == null) { if (rewardBucket == null || rewardBucket.startTimeMs == 0) { continue; } Loading
services/tests/mockingservicestests/src/com/android/server/tare/JobSchedulerEconomicPolicyTest.java +39 −6 Original line number Diff line number Diff line Loading @@ -134,15 +134,36 @@ public class JobSchedulerEconomicPolicyTest { mEconomicPolicy.getInitialSatiatedConsumptionLimit()); assertEquals(EconomyManager.DEFAULT_JS_HARD_CONSUMPTION_LIMIT_CAKES, mEconomicPolicy.getHardSatiatedConsumptionLimit()); final String pkgRestricted = "com.pkg.restricted"; when(mIrs.isPackageRestricted(anyInt(), eq(pkgRestricted))).thenReturn(true); assertEquals(0, mEconomicPolicy.getMinSatiatedBalance(0, pkgRestricted)); assertEquals(0, mEconomicPolicy.getMaxSatiatedBalance(0, pkgRestricted)); assertEquals(EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES, mEconomicPolicy.getMaxSatiatedBalance(0, "com.any.other.app")); final String pkgExempted = "com.pkg.exempted"; when(mIrs.isPackageExempted(anyInt(), eq(pkgExempted))).thenReturn(true); assertEquals(EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED_CAKES, mEconomicPolicy.getMinSatiatedBalance(0, pkgExempted)); assertEquals(EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES, mEconomicPolicy.getMaxSatiatedBalance(0, pkgExempted)); final String pkgUpdater = "com.pkg.updater"; when(mIrs.getAppUpdateResponsibilityCount(anyInt(), eq(pkgUpdater))).thenReturn(5); assertEquals(5 * EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER_CAKES + EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_OTHER_APP_CAKES, mEconomicPolicy.getMinSatiatedBalance(0, pkgUpdater)); assertEquals(EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES, mEconomicPolicy.getMaxSatiatedBalance(0, pkgUpdater)); // Make sure it doesn't suggest a min balance greater than max. final int updateCount = (int) (EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES / EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER_CAKES); when(mIrs.getAppUpdateResponsibilityCount(anyInt(), eq(pkgUpdater))) .thenReturn(updateCount); assertEquals(EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES, mEconomicPolicy.getMinSatiatedBalance(0, pkgUpdater)); assertEquals(EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES, mEconomicPolicy.getMaxSatiatedBalance(0, "com.any.other.app")); assertEquals(EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_OTHER_APP_CAKES, mEconomicPolicy.getMinSatiatedBalance(0, "com.any.other.app")); } Loading @@ -152,8 +173,10 @@ public class JobSchedulerEconomicPolicyTest { setDeviceConfigCakes(EconomyManager.KEY_JS_INITIAL_CONSUMPTION_LIMIT, arcToCake(5)); setDeviceConfigCakes(EconomyManager.KEY_JS_HARD_CONSUMPTION_LIMIT, arcToCake(25)); setDeviceConfigCakes(EconomyManager.KEY_JS_MAX_SATIATED_BALANCE, arcToCake(10)); setDeviceConfigCakes(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED, arcToCake(9)); setDeviceConfigCakes(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP, arcToCake(7)); setDeviceConfigCakes(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED, arcToCake(6)); setDeviceConfigCakes(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP, arcToCake(4)); setDeviceConfigCakes(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER, arcToCake(1)); assertEquals(arcToCake(5), mEconomicPolicy.getInitialSatiatedConsumptionLimit()); assertEquals(arcToCake(25), mEconomicPolicy.getHardSatiatedConsumptionLimit()); Loading @@ -163,8 +186,12 @@ public class JobSchedulerEconomicPolicyTest { assertEquals(arcToCake(10), mEconomicPolicy.getMaxSatiatedBalance(0, "com.any.other.app")); final String pkgExempted = "com.pkg.exempted"; when(mIrs.isPackageExempted(anyInt(), eq(pkgExempted))).thenReturn(true); assertEquals(arcToCake(9), mEconomicPolicy.getMinSatiatedBalance(0, pkgExempted)); assertEquals(arcToCake(7), mEconomicPolicy.getMinSatiatedBalance(0, "com.any.other.app")); assertEquals(arcToCake(6), mEconomicPolicy.getMinSatiatedBalance(0, pkgExempted)); assertEquals(arcToCake(4), mEconomicPolicy.getMinSatiatedBalance(0, "com.any.other.app")); final String pkgUpdater = "com.pkg.updater"; when(mIrs.getAppUpdateResponsibilityCount(anyInt(), eq(pkgUpdater))).thenReturn(3); assertEquals(arcToCake(4) + 3 * arcToCake(1), mEconomicPolicy.getMinSatiatedBalance(0, pkgUpdater)); } @Test Loading @@ -175,6 +202,8 @@ public class JobSchedulerEconomicPolicyTest { setDeviceConfigCakes(EconomyManager.KEY_JS_MAX_SATIATED_BALANCE, arcToCake(-1)); setDeviceConfigCakes(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED, arcToCake(-2)); setDeviceConfigCakes(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP, arcToCake(-3)); setDeviceConfigCakes(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER, arcToCake(-4)); assertEquals(arcToCake(1), mEconomicPolicy.getInitialSatiatedConsumptionLimit()); assertEquals(arcToCake(1), mEconomicPolicy.getHardSatiatedConsumptionLimit()); Loading @@ -186,6 +215,10 @@ public class JobSchedulerEconomicPolicyTest { when(mIrs.isPackageExempted(anyInt(), eq(pkgExempted))).thenReturn(true); assertEquals(arcToCake(0), mEconomicPolicy.getMinSatiatedBalance(0, pkgExempted)); assertEquals(arcToCake(0), mEconomicPolicy.getMinSatiatedBalance(0, "com.any.other.app")); final String pkgUpdater = "com.pkg.updater"; when(mIrs.getAppUpdateResponsibilityCount(anyInt(), eq(pkgUpdater))).thenReturn(5); assertEquals(arcToCake(0) + 5 * arcToCake(0), mEconomicPolicy.getMinSatiatedBalance(0, pkgUpdater)); // Test min+max reversed. setDeviceConfigCakes(EconomyManager.KEY_JS_INITIAL_CONSUMPTION_LIMIT, arcToCake(5)); Loading