Loading apex/jobscheduler/service/java/com/android/server/tare/Agent.java +32 −6 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static com.android.server.tare.EconomicPolicy.TYPE_ACTION; import static com.android.server.tare.EconomicPolicy.TYPE_REWARD; import static com.android.server.tare.EconomicPolicy.eventToString; import static com.android.server.tare.EconomicPolicy.getEventType; import static com.android.server.tare.TareUtils.appToString; import static com.android.server.tare.TareUtils.getCurrentTimeMillis; import static com.android.server.tare.TareUtils.narcToString; Loading Loading @@ -195,6 +196,11 @@ class Agent { @GuardedBy("mLock") void noteInstantaneousEventLocked(final int userId, @NonNull final String pkgName, final int eventId, @Nullable String tag) { if (mIrs.isSystem(userId, pkgName)) { // Events are free for the system. Don't bother recording them. return; } final long now = getCurrentTimeMillis(); final Ledger ledger = getLedgerLocked(userId, pkgName); Loading Loading @@ -416,12 +422,15 @@ class Agent { } ongoingEvent.refCount--; if (ongoingEvent.refCount <= 0) { if (!mIrs.isSystem(userId, pkgName)) { final long startElapsed = ongoingEvent.startTimeElapsed; final long startTime = now - (nowElapsed - startElapsed); final long actualDelta = getActualDeltaLocked(ongoingEvent, ledger, nowElapsed, now); final long actualDelta = getActualDeltaLocked(ongoingEvent, ledger, nowElapsed, now); recordTransactionLocked(userId, pkgName, ledger, new Ledger.Transaction(startTime, now, eventId, tag, actualDelta), notifyOnAffordabilityChange); } ongoingEvents.delete(eventId, tag); } if (updateBalanceCheck) { Loading @@ -447,6 +456,15 @@ class Agent { private void recordTransactionLocked(final int userId, @NonNull final String pkgName, @NonNull Ledger ledger, @NonNull Ledger.Transaction transaction, final boolean notifyOnAffordabilityChange) { if (transaction.delta == 0) { // Skip recording transactions with a delta of 0 to save on space. return; } if (mIrs.isSystem(userId, pkgName)) { Slog.wtfStack(TAG, "Tried to adjust system balance for " + appToString(userId, pkgName)); return; } final long maxCirculationAllowed = mIrs.getMaxCirculationLocked(); final long newArcsInCirculation = mCurrentNarcsInCirculation + transaction.delta; if (transaction.delta > 0 && newArcsInCirculation > maxCirculationAllowed) { Loading Loading @@ -549,6 +567,10 @@ class Agent { final PackageInfo pkgInfo = pkgs.get(i); final int userId = UserHandle.getUserId(pkgInfo.applicationInfo.uid); final String pkgName = pkgInfo.packageName; if (mIrs.isSystem(userId, pkgName)) { // No point allocating ARCs to the system. It can do whatever it wants. continue; } Ledger ledger = getLedgerLocked(userId, pkgName); final long minBalance = mIrs.getMinBalanceLocked(userId, pkgName); final double perc = batteryLevel / 100d; Loading Loading @@ -585,6 +607,10 @@ class Agent { final PackageInfo packageInfo = pkgs.get(i); final String pkgName = packageInfo.packageName; final Ledger ledger = getLedgerLocked(userId, pkgName); if (mIrs.isSystem(userId, pkgName)) { // No point allocating ARCs to the system. It can do whatever it wants. continue; } if (ledger.getCurrentBalance() > 0) { // App already got credits somehow. Move along. Slog.wtf(TAG, "App " + pkgName + " had credits before economy was set up"); Loading apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java +51 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.database.ContentObserver; import android.net.Uri; import android.os.BatteryManagerInternal; Loading @@ -47,6 +48,7 @@ import android.util.ArraySet; import android.util.IndentingPrintWriter; import android.util.Log; import android.util.Slog; import android.util.SparseArrayMap; import android.util.SparseSetArray; import com.android.internal.annotations.GuardedBy; Loading Loading @@ -83,6 +85,7 @@ public class InternalResourceService extends SystemService { private final Handler mHandler; private final BatteryManagerInternal mBatteryManagerInternal; private final PackageManager mPackageManager; private final PackageManagerInternal mPackageManagerInternal; private final Agent mAgent; private final CompleteEconomicPolicy mCompleteEconomicPolicy; Loading @@ -97,6 +100,10 @@ public class InternalResourceService extends SystemService { @GuardedBy("mLock") private final SparseSetArray<String> mUidToPackageCache = new SparseSetArray<>(); /** Cached mapping of userId+package to their UIDs (for all users) */ @GuardedBy("mPackageToUidCache") private final SparseArrayMap<String, Integer> mPackageToUidCache = new SparseArrayMap<>(); private volatile boolean mIsEnabled; private volatile int mBootPhase; // In the range [0,100] to represent 0% to 100% battery. Loading Loading @@ -186,6 +193,7 @@ public class InternalResourceService extends SystemService { mHandler = new IrsHandler(TareHandlerThread.get().getLooper()); mBatteryManagerInternal = LocalServices.getService(BatteryManagerInternal.class); mPackageManager = context.getPackageManager(); mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); mEconomyManagerStub = new EconomyManagerStub(); mCompleteEconomicPolicy = new CompleteEconomicPolicy(this); mAgent = new Agent(this, mCompleteEconomicPolicy); Loading Loading @@ -233,10 +241,28 @@ public class InternalResourceService extends SystemService { / 100; } int getUid(final int userId, @NonNull final String pkgName) { synchronized (mPackageToUidCache) { Integer uid = mPackageToUidCache.get(userId, pkgName); if (uid == null) { uid = mPackageManagerInternal.getPackageUid(pkgName, 0, userId); mPackageToUidCache.add(userId, pkgName, uid); } return uid; } } boolean isEnabled() { return mIsEnabled; } boolean isSystem(final int userId, @NonNull String pkgName) { if ("android".equals(pkgName)) { return true; } return UserHandle.isCore(getUid(userId, pkgName)); } void onBatteryLevelChanged() { synchronized (mLock) { final int newBatteryLevel = getCurrentBatteryLevel(); Loading @@ -262,6 +288,9 @@ public class InternalResourceService extends SystemService { Slog.wtf(TAG, "PM couldn't find newly added package: " + pkgName); return; } synchronized (mPackageToUidCache) { mPackageToUidCache.add(userId, pkgName, uid); } synchronized (mLock) { mPkgCache.add(packageInfo); mUidToPackageCache.add(uid, pkgName); Loading @@ -278,6 +307,9 @@ public class InternalResourceService extends SystemService { void onPackageRemoved(final int uid, @NonNull final String pkgName) { final int userId = UserHandle.getUserId(uid); synchronized (mPackageToUidCache) { mPackageToUidCache.delete(userId, pkgName); } synchronized (mLock) { mUidToPackageCache.remove(uid, pkgName); for (int i = 0; i < mPkgCache.size(); ++i) { Loading Loading @@ -448,6 +480,9 @@ public class InternalResourceService extends SystemService { mUidToPackageCache.clear(); getContext().unregisterReceiver(mBroadcastReceiver); } synchronized (mPackageToUidCache) { mPackageToUidCache.clear(); } } private final class IrsHandler extends Handler { Loading Loading @@ -527,6 +562,10 @@ public class InternalResourceService extends SystemService { @Override public void registerAffordabilityChangeListener(int userId, @NonNull String pkgName, @NonNull AffordabilityChangeListener listener, @NonNull ActionBill bill) { if (isSystem(userId, pkgName)) { // The system's affordability never changes. return; } synchronized (mLock) { mAgent.registerAffordabilityChangeListenerLocked(userId, pkgName, listener, bill); } Loading @@ -535,6 +574,10 @@ public class InternalResourceService extends SystemService { @Override public void unregisterAffordabilityChangeListener(int userId, @NonNull String pkgName, @NonNull AffordabilityChangeListener listener, @NonNull ActionBill bill) { if (isSystem(userId, pkgName)) { // The system's affordability never changes. return; } synchronized (mLock) { mAgent.unregisterAffordabilityChangeListenerLocked(userId, pkgName, listener, bill); } Loading @@ -545,6 +588,11 @@ public class InternalResourceService extends SystemService { if (!mIsEnabled) { return true; } if (isSystem(userId, pkgName)) { // The government, I mean the system, can create ARCs as it needs to in order to // operate. return true; } // TODO: take temp-allowlist into consideration long requiredBalance = 0; final List<EconomyManagerInternal.AnticipatedAction> projectedActions = Loading @@ -567,6 +615,9 @@ public class InternalResourceService extends SystemService { if (!mIsEnabled) { return FOREVER_MS; } if (isSystem(userId, pkgName)) { return FOREVER_MS; } long totalCostPerSecond = 0; final List<EconomyManagerInternal.AnticipatedAction> projectedActions = bill.getAnticipatedActions(); Loading apex/jobscheduler/service/java/com/android/server/tare/ProcessStateModifier.java +1 −14 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.app.ActivityManager; import android.app.IUidObserver; import android.content.pm.PackageManagerInternal; import android.os.RemoteException; import android.util.IndentingPrintWriter; import android.util.Slog; Loading @@ -28,7 +27,6 @@ import android.util.SparseArrayMap; import android.util.SparseIntArray; import com.android.internal.annotations.GuardedBy; import com.android.server.LocalServices; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; Loading Loading @@ -56,7 +54,6 @@ class ProcessStateModifier extends Modifier { private final Object mLock = new Object(); private final InternalResourceService mIrs; private final PackageManagerInternal mPackageManagerInternal; /** Cached mapping of userId+package to their UIDs (for all users) */ private final SparseArrayMap<String, Integer> mPackageToUidCache = new SparseArrayMap<>(); Loading Loading @@ -105,7 +102,6 @@ class ProcessStateModifier extends Modifier { ProcessStateModifier(@NonNull InternalResourceService irs) { super(); mIrs = irs; mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); } @Override Loading Loading @@ -143,7 +139,7 @@ class ProcessStateModifier extends Modifier { final int procState; synchronized (mLock) { procState = mUidProcStateBucketCache.get( getUidLocked(userId, pkgName), PROC_STATE_BUCKET_NONE); mIrs.getUid(userId, pkgName), PROC_STATE_BUCKET_NONE); } switch (procState) { case PROC_STATE_BUCKET_TOP: Loading @@ -166,15 +162,6 @@ class ProcessStateModifier extends Modifier { pw.println(mUidProcStateBucketCache); } @GuardedBy("mLock") private int getUidLocked(final int userId, @NonNull final String pkgName) { if (!mPackageToUidCache.contains(userId, pkgName)) { mPackageToUidCache.add(userId, pkgName, mPackageManagerInternal.getPackageUid(pkgName, 0, userId)); } return mPackageToUidCache.get(userId, pkgName); } @ProcStateBucket private int getProcStateBucket(int procState) { if (procState <= ActivityManager.PROCESS_STATE_TOP) { Loading apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java +6 −0 Original line number Diff line number Diff line Loading @@ -69,4 +69,10 @@ class TareUtils { sb.append(" ARCs"); return sb.toString(); } /** Returns a standardized format for printing userId+pkgName combinations. */ @NonNull static String appToString(int userId, String pkgName) { return "<" + userId + ">" + pkgName; } } Loading
apex/jobscheduler/service/java/com/android/server/tare/Agent.java +32 −6 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static com.android.server.tare.EconomicPolicy.TYPE_ACTION; import static com.android.server.tare.EconomicPolicy.TYPE_REWARD; import static com.android.server.tare.EconomicPolicy.eventToString; import static com.android.server.tare.EconomicPolicy.getEventType; import static com.android.server.tare.TareUtils.appToString; import static com.android.server.tare.TareUtils.getCurrentTimeMillis; import static com.android.server.tare.TareUtils.narcToString; Loading Loading @@ -195,6 +196,11 @@ class Agent { @GuardedBy("mLock") void noteInstantaneousEventLocked(final int userId, @NonNull final String pkgName, final int eventId, @Nullable String tag) { if (mIrs.isSystem(userId, pkgName)) { // Events are free for the system. Don't bother recording them. return; } final long now = getCurrentTimeMillis(); final Ledger ledger = getLedgerLocked(userId, pkgName); Loading Loading @@ -416,12 +422,15 @@ class Agent { } ongoingEvent.refCount--; if (ongoingEvent.refCount <= 0) { if (!mIrs.isSystem(userId, pkgName)) { final long startElapsed = ongoingEvent.startTimeElapsed; final long startTime = now - (nowElapsed - startElapsed); final long actualDelta = getActualDeltaLocked(ongoingEvent, ledger, nowElapsed, now); final long actualDelta = getActualDeltaLocked(ongoingEvent, ledger, nowElapsed, now); recordTransactionLocked(userId, pkgName, ledger, new Ledger.Transaction(startTime, now, eventId, tag, actualDelta), notifyOnAffordabilityChange); } ongoingEvents.delete(eventId, tag); } if (updateBalanceCheck) { Loading @@ -447,6 +456,15 @@ class Agent { private void recordTransactionLocked(final int userId, @NonNull final String pkgName, @NonNull Ledger ledger, @NonNull Ledger.Transaction transaction, final boolean notifyOnAffordabilityChange) { if (transaction.delta == 0) { // Skip recording transactions with a delta of 0 to save on space. return; } if (mIrs.isSystem(userId, pkgName)) { Slog.wtfStack(TAG, "Tried to adjust system balance for " + appToString(userId, pkgName)); return; } final long maxCirculationAllowed = mIrs.getMaxCirculationLocked(); final long newArcsInCirculation = mCurrentNarcsInCirculation + transaction.delta; if (transaction.delta > 0 && newArcsInCirculation > maxCirculationAllowed) { Loading Loading @@ -549,6 +567,10 @@ class Agent { final PackageInfo pkgInfo = pkgs.get(i); final int userId = UserHandle.getUserId(pkgInfo.applicationInfo.uid); final String pkgName = pkgInfo.packageName; if (mIrs.isSystem(userId, pkgName)) { // No point allocating ARCs to the system. It can do whatever it wants. continue; } Ledger ledger = getLedgerLocked(userId, pkgName); final long minBalance = mIrs.getMinBalanceLocked(userId, pkgName); final double perc = batteryLevel / 100d; Loading Loading @@ -585,6 +607,10 @@ class Agent { final PackageInfo packageInfo = pkgs.get(i); final String pkgName = packageInfo.packageName; final Ledger ledger = getLedgerLocked(userId, pkgName); if (mIrs.isSystem(userId, pkgName)) { // No point allocating ARCs to the system. It can do whatever it wants. continue; } if (ledger.getCurrentBalance() > 0) { // App already got credits somehow. Move along. Slog.wtf(TAG, "App " + pkgName + " had credits before economy was set up"); Loading
apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java +51 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.database.ContentObserver; import android.net.Uri; import android.os.BatteryManagerInternal; Loading @@ -47,6 +48,7 @@ import android.util.ArraySet; import android.util.IndentingPrintWriter; import android.util.Log; import android.util.Slog; import android.util.SparseArrayMap; import android.util.SparseSetArray; import com.android.internal.annotations.GuardedBy; Loading Loading @@ -83,6 +85,7 @@ public class InternalResourceService extends SystemService { private final Handler mHandler; private final BatteryManagerInternal mBatteryManagerInternal; private final PackageManager mPackageManager; private final PackageManagerInternal mPackageManagerInternal; private final Agent mAgent; private final CompleteEconomicPolicy mCompleteEconomicPolicy; Loading @@ -97,6 +100,10 @@ public class InternalResourceService extends SystemService { @GuardedBy("mLock") private final SparseSetArray<String> mUidToPackageCache = new SparseSetArray<>(); /** Cached mapping of userId+package to their UIDs (for all users) */ @GuardedBy("mPackageToUidCache") private final SparseArrayMap<String, Integer> mPackageToUidCache = new SparseArrayMap<>(); private volatile boolean mIsEnabled; private volatile int mBootPhase; // In the range [0,100] to represent 0% to 100% battery. Loading Loading @@ -186,6 +193,7 @@ public class InternalResourceService extends SystemService { mHandler = new IrsHandler(TareHandlerThread.get().getLooper()); mBatteryManagerInternal = LocalServices.getService(BatteryManagerInternal.class); mPackageManager = context.getPackageManager(); mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); mEconomyManagerStub = new EconomyManagerStub(); mCompleteEconomicPolicy = new CompleteEconomicPolicy(this); mAgent = new Agent(this, mCompleteEconomicPolicy); Loading Loading @@ -233,10 +241,28 @@ public class InternalResourceService extends SystemService { / 100; } int getUid(final int userId, @NonNull final String pkgName) { synchronized (mPackageToUidCache) { Integer uid = mPackageToUidCache.get(userId, pkgName); if (uid == null) { uid = mPackageManagerInternal.getPackageUid(pkgName, 0, userId); mPackageToUidCache.add(userId, pkgName, uid); } return uid; } } boolean isEnabled() { return mIsEnabled; } boolean isSystem(final int userId, @NonNull String pkgName) { if ("android".equals(pkgName)) { return true; } return UserHandle.isCore(getUid(userId, pkgName)); } void onBatteryLevelChanged() { synchronized (mLock) { final int newBatteryLevel = getCurrentBatteryLevel(); Loading @@ -262,6 +288,9 @@ public class InternalResourceService extends SystemService { Slog.wtf(TAG, "PM couldn't find newly added package: " + pkgName); return; } synchronized (mPackageToUidCache) { mPackageToUidCache.add(userId, pkgName, uid); } synchronized (mLock) { mPkgCache.add(packageInfo); mUidToPackageCache.add(uid, pkgName); Loading @@ -278,6 +307,9 @@ public class InternalResourceService extends SystemService { void onPackageRemoved(final int uid, @NonNull final String pkgName) { final int userId = UserHandle.getUserId(uid); synchronized (mPackageToUidCache) { mPackageToUidCache.delete(userId, pkgName); } synchronized (mLock) { mUidToPackageCache.remove(uid, pkgName); for (int i = 0; i < mPkgCache.size(); ++i) { Loading Loading @@ -448,6 +480,9 @@ public class InternalResourceService extends SystemService { mUidToPackageCache.clear(); getContext().unregisterReceiver(mBroadcastReceiver); } synchronized (mPackageToUidCache) { mPackageToUidCache.clear(); } } private final class IrsHandler extends Handler { Loading Loading @@ -527,6 +562,10 @@ public class InternalResourceService extends SystemService { @Override public void registerAffordabilityChangeListener(int userId, @NonNull String pkgName, @NonNull AffordabilityChangeListener listener, @NonNull ActionBill bill) { if (isSystem(userId, pkgName)) { // The system's affordability never changes. return; } synchronized (mLock) { mAgent.registerAffordabilityChangeListenerLocked(userId, pkgName, listener, bill); } Loading @@ -535,6 +574,10 @@ public class InternalResourceService extends SystemService { @Override public void unregisterAffordabilityChangeListener(int userId, @NonNull String pkgName, @NonNull AffordabilityChangeListener listener, @NonNull ActionBill bill) { if (isSystem(userId, pkgName)) { // The system's affordability never changes. return; } synchronized (mLock) { mAgent.unregisterAffordabilityChangeListenerLocked(userId, pkgName, listener, bill); } Loading @@ -545,6 +588,11 @@ public class InternalResourceService extends SystemService { if (!mIsEnabled) { return true; } if (isSystem(userId, pkgName)) { // The government, I mean the system, can create ARCs as it needs to in order to // operate. return true; } // TODO: take temp-allowlist into consideration long requiredBalance = 0; final List<EconomyManagerInternal.AnticipatedAction> projectedActions = Loading @@ -567,6 +615,9 @@ public class InternalResourceService extends SystemService { if (!mIsEnabled) { return FOREVER_MS; } if (isSystem(userId, pkgName)) { return FOREVER_MS; } long totalCostPerSecond = 0; final List<EconomyManagerInternal.AnticipatedAction> projectedActions = bill.getAnticipatedActions(); Loading
apex/jobscheduler/service/java/com/android/server/tare/ProcessStateModifier.java +1 −14 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.app.ActivityManager; import android.app.IUidObserver; import android.content.pm.PackageManagerInternal; import android.os.RemoteException; import android.util.IndentingPrintWriter; import android.util.Slog; Loading @@ -28,7 +27,6 @@ import android.util.SparseArrayMap; import android.util.SparseIntArray; import com.android.internal.annotations.GuardedBy; import com.android.server.LocalServices; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; Loading Loading @@ -56,7 +54,6 @@ class ProcessStateModifier extends Modifier { private final Object mLock = new Object(); private final InternalResourceService mIrs; private final PackageManagerInternal mPackageManagerInternal; /** Cached mapping of userId+package to their UIDs (for all users) */ private final SparseArrayMap<String, Integer> mPackageToUidCache = new SparseArrayMap<>(); Loading Loading @@ -105,7 +102,6 @@ class ProcessStateModifier extends Modifier { ProcessStateModifier(@NonNull InternalResourceService irs) { super(); mIrs = irs; mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); } @Override Loading Loading @@ -143,7 +139,7 @@ class ProcessStateModifier extends Modifier { final int procState; synchronized (mLock) { procState = mUidProcStateBucketCache.get( getUidLocked(userId, pkgName), PROC_STATE_BUCKET_NONE); mIrs.getUid(userId, pkgName), PROC_STATE_BUCKET_NONE); } switch (procState) { case PROC_STATE_BUCKET_TOP: Loading @@ -166,15 +162,6 @@ class ProcessStateModifier extends Modifier { pw.println(mUidProcStateBucketCache); } @GuardedBy("mLock") private int getUidLocked(final int userId, @NonNull final String pkgName) { if (!mPackageToUidCache.contains(userId, pkgName)) { mPackageToUidCache.add(userId, pkgName, mPackageManagerInternal.getPackageUid(pkgName, 0, userId)); } return mPackageToUidCache.get(userId, pkgName); } @ProcStateBucket private int getProcStateBucket(int procState) { if (procState <= ActivityManager.PROCESS_STATE_TOP) { Loading
apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java +6 −0 Original line number Diff line number Diff line Loading @@ -69,4 +69,10 @@ class TareUtils { sb.append(" ARCs"); return sb.toString(); } /** Returns a standardized format for printing userId+pkgName combinations. */ @NonNull static String appToString(int userId, String pkgName) { return "<" + userId + ">" + pkgName; } }