Loading apex/jobscheduler/service/java/com/android/server/tare/Agent.java +12 −5 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ 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; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -460,8 +461,9 @@ class Agent { Math.min(ongoingEvent.reward.maxDailyReward - rewardSum, computedDelta)); } @VisibleForTesting @GuardedBy("mLock") private void recordTransactionLocked(final int userId, @NonNull final String pkgName, void recordTransactionLocked(final int userId, @NonNull final String pkgName, @NonNull Ledger ledger, @NonNull Ledger.Transaction transaction, final boolean notifyOnAffordabilityChange) { if (transaction.delta == 0) { Loading @@ -476,12 +478,14 @@ class Agent { final long maxCirculationAllowed = mIrs.getMaxCirculationLocked(); final long newArcsInCirculation = mCurrentNarcsInCirculation + transaction.delta; if (transaction.delta > 0 && newArcsInCirculation > maxCirculationAllowed) { final long newDelta = maxCirculationAllowed - mCurrentNarcsInCirculation; // Set lower bound at 0 so we don't accidentally take away credits when we were trying // to _give_ the app credits. final long newDelta = Math.max(0, maxCirculationAllowed - mCurrentNarcsInCirculation); Slog.i(TAG, "Would result in too many credits in circulation. Decreasing transaction " + eventToString(transaction.eventId) + (transaction.tag == null ? "" : ":" + transaction.tag) + " for " + appToString(userId, pkgName) + " by " + (transaction.delta - newDelta)); + " by " + narcToString(transaction.delta - newDelta)); transaction = new Ledger.Transaction( transaction.startTimeMs, transaction.endTimeMs, transaction.eventId, transaction.tag, newDelta); Loading @@ -490,12 +494,15 @@ class Agent { if (transaction.delta > 0 && originalBalance + transaction.delta > mCompleteEconomicPolicy.getMaxSatiatedBalance()) { final long newDelta = mCompleteEconomicPolicy.getMaxSatiatedBalance() - originalBalance; // Set lower bound at 0 so we don't accidentally take away credits when we were trying // to _give_ the app credits. final long newDelta = Math.max(0, mCompleteEconomicPolicy.getMaxSatiatedBalance() - originalBalance); Slog.i(TAG, "Would result in becoming too rich. Decreasing transaction " + eventToString(transaction.eventId) + (transaction.tag == null ? "" : ":" + transaction.tag) + " for " + appToString(userId, pkgName) + " by " + (transaction.delta - newDelta)); + " by " + narcToString(transaction.delta - newDelta)); transaction = new Ledger.Transaction( transaction.startTimeMs, transaction.endTimeMs, transaction.eventId, transaction.tag, newDelta); Loading services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java 0 → 100644 +183 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.tare; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.app.AlarmManager; import android.content.Context; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.server.LocalServices; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoSession; import org.mockito.quality.Strictness; /** Tests various aspects of the Agent. */ @RunWith(AndroidJUnit4.class) @SmallTest public class AgentTest { private MockitoSession mMockingSession; @Mock private CompleteEconomicPolicy mEconomicPolicy; @Mock private Context mContext; @Mock private InternalResourceService mIrs; @Before public void setUp() { mMockingSession = mockitoSession() .initMocks(this) .strictness(Strictness.LENIENT) .mockStatic(LocalServices.class) .startMocking(); when(mIrs.getContext()).thenReturn(mContext); when(mContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mock(AlarmManager.class)); } @After public void tearDown() { if (mMockingSession != null) { mMockingSession.finishMocking(); } } @Test public void testRecordTransaction_UnderMax() { Agent agent = new Agent(mIrs, mEconomicPolicy); Ledger ledger = new Ledger(); doReturn(1_000_000L).when(mIrs).getMaxCirculationLocked(); doReturn(1_000_000L).when(mEconomicPolicy).getMaxSatiatedBalance(); Ledger.Transaction transaction = new Ledger.Transaction(0, 0, 0, null, 5); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(5, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, 995); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(1000, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, -500); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(500, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, 999_500L); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(1_000_000L, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, -1_000_001L); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(-1, ledger.getCurrentBalance()); } @Test public void testRecordTransaction_MaxCirculation() { Agent agent = new Agent(mIrs, mEconomicPolicy); Ledger ledger = new Ledger(); doReturn(1000L).when(mIrs).getMaxCirculationLocked(); doReturn(1000L).when(mEconomicPolicy).getMaxSatiatedBalance(); Ledger.Transaction transaction = new Ledger.Transaction(0, 0, 0, null, 5); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(5, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, 995); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(1000, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, -500); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(500, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, 2000); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(1000, ledger.getCurrentBalance()); // MaxCirculation can change as the battery level changes. Any already allocated ARCSs // shouldn't be removed by recordTransaction(). doReturn(900L).when(mIrs).getMaxCirculationLocked(); transaction = new Ledger.Transaction(0, 0, 0, null, 100); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(1000, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, -50); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(950, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, -200); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(750, ledger.getCurrentBalance()); doReturn(800L).when(mIrs).getMaxCirculationLocked(); transaction = new Ledger.Transaction(0, 0, 0, null, 100); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(800, ledger.getCurrentBalance()); } @Test public void testRecordTransaction_MaxSatiatedBalance() { Agent agent = new Agent(mIrs, mEconomicPolicy); Ledger ledger = new Ledger(); doReturn(1_000_000L).when(mIrs).getMaxCirculationLocked(); doReturn(1000L).when(mEconomicPolicy).getMaxSatiatedBalance(); Ledger.Transaction transaction = new Ledger.Transaction(0, 0, 0, null, 5); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(5, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, 995); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(1000, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, -500); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(500, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, 999_500L); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(1_000, ledger.getCurrentBalance()); // Shouldn't change in normal operation, but adding test case in case it does. doReturn(900L).when(mEconomicPolicy).getMaxSatiatedBalance(); transaction = new Ledger.Transaction(0, 0, 0, null, 500); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(1_000, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, -1001); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(-1, ledger.getCurrentBalance()); } } Loading
apex/jobscheduler/service/java/com/android/server/tare/Agent.java +12 −5 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ 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; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -460,8 +461,9 @@ class Agent { Math.min(ongoingEvent.reward.maxDailyReward - rewardSum, computedDelta)); } @VisibleForTesting @GuardedBy("mLock") private void recordTransactionLocked(final int userId, @NonNull final String pkgName, void recordTransactionLocked(final int userId, @NonNull final String pkgName, @NonNull Ledger ledger, @NonNull Ledger.Transaction transaction, final boolean notifyOnAffordabilityChange) { if (transaction.delta == 0) { Loading @@ -476,12 +478,14 @@ class Agent { final long maxCirculationAllowed = mIrs.getMaxCirculationLocked(); final long newArcsInCirculation = mCurrentNarcsInCirculation + transaction.delta; if (transaction.delta > 0 && newArcsInCirculation > maxCirculationAllowed) { final long newDelta = maxCirculationAllowed - mCurrentNarcsInCirculation; // Set lower bound at 0 so we don't accidentally take away credits when we were trying // to _give_ the app credits. final long newDelta = Math.max(0, maxCirculationAllowed - mCurrentNarcsInCirculation); Slog.i(TAG, "Would result in too many credits in circulation. Decreasing transaction " + eventToString(transaction.eventId) + (transaction.tag == null ? "" : ":" + transaction.tag) + " for " + appToString(userId, pkgName) + " by " + (transaction.delta - newDelta)); + " by " + narcToString(transaction.delta - newDelta)); transaction = new Ledger.Transaction( transaction.startTimeMs, transaction.endTimeMs, transaction.eventId, transaction.tag, newDelta); Loading @@ -490,12 +494,15 @@ class Agent { if (transaction.delta > 0 && originalBalance + transaction.delta > mCompleteEconomicPolicy.getMaxSatiatedBalance()) { final long newDelta = mCompleteEconomicPolicy.getMaxSatiatedBalance() - originalBalance; // Set lower bound at 0 so we don't accidentally take away credits when we were trying // to _give_ the app credits. final long newDelta = Math.max(0, mCompleteEconomicPolicy.getMaxSatiatedBalance() - originalBalance); Slog.i(TAG, "Would result in becoming too rich. Decreasing transaction " + eventToString(transaction.eventId) + (transaction.tag == null ? "" : ":" + transaction.tag) + " for " + appToString(userId, pkgName) + " by " + (transaction.delta - newDelta)); + " by " + narcToString(transaction.delta - newDelta)); transaction = new Ledger.Transaction( transaction.startTimeMs, transaction.endTimeMs, transaction.eventId, transaction.tag, newDelta); Loading
services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java 0 → 100644 +183 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.tare; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.app.AlarmManager; import android.content.Context; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.server.LocalServices; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoSession; import org.mockito.quality.Strictness; /** Tests various aspects of the Agent. */ @RunWith(AndroidJUnit4.class) @SmallTest public class AgentTest { private MockitoSession mMockingSession; @Mock private CompleteEconomicPolicy mEconomicPolicy; @Mock private Context mContext; @Mock private InternalResourceService mIrs; @Before public void setUp() { mMockingSession = mockitoSession() .initMocks(this) .strictness(Strictness.LENIENT) .mockStatic(LocalServices.class) .startMocking(); when(mIrs.getContext()).thenReturn(mContext); when(mContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mock(AlarmManager.class)); } @After public void tearDown() { if (mMockingSession != null) { mMockingSession.finishMocking(); } } @Test public void testRecordTransaction_UnderMax() { Agent agent = new Agent(mIrs, mEconomicPolicy); Ledger ledger = new Ledger(); doReturn(1_000_000L).when(mIrs).getMaxCirculationLocked(); doReturn(1_000_000L).when(mEconomicPolicy).getMaxSatiatedBalance(); Ledger.Transaction transaction = new Ledger.Transaction(0, 0, 0, null, 5); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(5, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, 995); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(1000, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, -500); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(500, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, 999_500L); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(1_000_000L, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, -1_000_001L); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(-1, ledger.getCurrentBalance()); } @Test public void testRecordTransaction_MaxCirculation() { Agent agent = new Agent(mIrs, mEconomicPolicy); Ledger ledger = new Ledger(); doReturn(1000L).when(mIrs).getMaxCirculationLocked(); doReturn(1000L).when(mEconomicPolicy).getMaxSatiatedBalance(); Ledger.Transaction transaction = new Ledger.Transaction(0, 0, 0, null, 5); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(5, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, 995); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(1000, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, -500); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(500, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, 2000); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(1000, ledger.getCurrentBalance()); // MaxCirculation can change as the battery level changes. Any already allocated ARCSs // shouldn't be removed by recordTransaction(). doReturn(900L).when(mIrs).getMaxCirculationLocked(); transaction = new Ledger.Transaction(0, 0, 0, null, 100); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(1000, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, -50); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(950, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, -200); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(750, ledger.getCurrentBalance()); doReturn(800L).when(mIrs).getMaxCirculationLocked(); transaction = new Ledger.Transaction(0, 0, 0, null, 100); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(800, ledger.getCurrentBalance()); } @Test public void testRecordTransaction_MaxSatiatedBalance() { Agent agent = new Agent(mIrs, mEconomicPolicy); Ledger ledger = new Ledger(); doReturn(1_000_000L).when(mIrs).getMaxCirculationLocked(); doReturn(1000L).when(mEconomicPolicy).getMaxSatiatedBalance(); Ledger.Transaction transaction = new Ledger.Transaction(0, 0, 0, null, 5); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(5, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, 995); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(1000, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, -500); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(500, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, 999_500L); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(1_000, ledger.getCurrentBalance()); // Shouldn't change in normal operation, but adding test case in case it does. doReturn(900L).when(mEconomicPolicy).getMaxSatiatedBalance(); transaction = new Ledger.Transaction(0, 0, 0, null, 500); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(1_000, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, -1001); agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(-1, ledger.getCurrentBalance()); } }