Merge "Simplify app removal code."
This commit is contained in:
committed by
Android (Google) Code Review
commit
38226653ab
@@ -27,7 +27,6 @@ import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.UserHandle;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.LongArrayQueue;
|
||||
import android.util.Slog;
|
||||
@@ -294,12 +293,11 @@ public class CountQuotaTracker extends QuotaTracker {
|
||||
|
||||
@Override
|
||||
@GuardedBy("mLock")
|
||||
void handleRemovedAppLocked(String packageName, int uid) {
|
||||
void handleRemovedAppLocked(final int userId, @NonNull String packageName) {
|
||||
if (packageName == null) {
|
||||
Slog.wtf(TAG, "Told app removed but given null package name.");
|
||||
return;
|
||||
}
|
||||
final int userId = UserHandle.getUserId(uid);
|
||||
|
||||
mEventTimes.delete(userId, packageName);
|
||||
mExecutionStatsCache.delete(userId, packageName);
|
||||
|
||||
@@ -19,8 +19,6 @@ package com.android.server.utils.quota;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@@ -57,11 +55,9 @@ public class MultiRateLimiter {
|
||||
private final Object mLock = new Object();
|
||||
@GuardedBy("mLock")
|
||||
private final CountQuotaTracker[] mQuotaTrackers;
|
||||
private final PackageManager mPackageManager;
|
||||
|
||||
private MultiRateLimiter(List<CountQuotaTracker> quotaTrackers, PackageManager packageManager) {
|
||||
private MultiRateLimiter(List<CountQuotaTracker> quotaTrackers) {
|
||||
mQuotaTrackers = quotaTrackers.toArray(EMPTY_TRACKER_ARRAY);
|
||||
mPackageManager = packageManager;
|
||||
}
|
||||
|
||||
/** Record that an event happened and count it towards the given quota. */
|
||||
@@ -105,17 +101,11 @@ public class MultiRateLimiter {
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private void clearLocked(int userId, @NonNull String packageName) {
|
||||
try {
|
||||
int uid = mPackageManager.getApplicationInfoAsUser(packageName, 0, userId).uid;
|
||||
for (CountQuotaTracker quotaTracker : mQuotaTrackers) {
|
||||
// This method behaves as if the package has been removed from the device, which
|
||||
// isn't the case here, but it does similar clean-up to what we are aiming for here,
|
||||
// so it works for this use case.
|
||||
quotaTracker.onAppRemovedLocked(packageName, uid);
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Slog.e(TAG, "clear(userId, packageName) called with unrecognized arguments, no "
|
||||
+ "action taken");
|
||||
for (CountQuotaTracker quotaTracker : mQuotaTrackers) {
|
||||
// This method behaves as if the package has been removed from the device, which
|
||||
// isn't the case here, but it does similar clean-up to what we are aiming for here,
|
||||
// so it works for this use case.
|
||||
quotaTracker.onAppRemovedLocked(userId, packageName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +116,8 @@ public class MultiRateLimiter {
|
||||
private final Context mContext;
|
||||
private final Categorizer mCategorizer;
|
||||
private final Category mCategory;
|
||||
@Nullable private final QuotaTracker.Injector mInjector;
|
||||
@Nullable
|
||||
private final QuotaTracker.Injector mInjector;
|
||||
|
||||
/**
|
||||
* Creates a new builder and allows to inject an object that can be used
|
||||
@@ -149,7 +140,7 @@ public class MultiRateLimiter {
|
||||
/**
|
||||
* Adds another rate limit to be used in {@link MultiRateLimiter}.
|
||||
*
|
||||
* @param limit The maximum event count an app can have in the rolling time window.
|
||||
* @param limit The maximum event count an app can have in the rolling time window.
|
||||
* @param windowSize The rolling time window to use when checking quota usage.
|
||||
*/
|
||||
public Builder addRateLimit(int limit, Duration windowSize) {
|
||||
@@ -182,7 +173,7 @@ public class MultiRateLimiter {
|
||||
* limit.
|
||||
*/
|
||||
public MultiRateLimiter build() {
|
||||
return new MultiRateLimiter(mQuotaTrackers, mContext.getPackageManager());
|
||||
return new MultiRateLimiter(mQuotaTrackers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,7 +183,7 @@ public class MultiRateLimiter {
|
||||
public final Duration mWindowSize;
|
||||
|
||||
/**
|
||||
* @param limit The maximum count of some occurrence in the rolling time window.
|
||||
* @param limit The maximum count of some occurrence in the rolling time window.
|
||||
* @param windowSize The rolling time window to use when checking quota usage.
|
||||
*/
|
||||
private RateLimit(int limit, Duration windowSize) {
|
||||
@@ -201,7 +192,7 @@ public class MultiRateLimiter {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param limit The maximum count of some occurrence in the rolling time window.
|
||||
* @param limit The maximum count of some occurrence in the rolling time window.
|
||||
* @param windowSize The rolling time window to use when checking quota usage.
|
||||
*/
|
||||
public static RateLimit create(int limit, Duration windowSize) {
|
||||
|
||||
@@ -132,7 +132,7 @@ abstract class QuotaTracker {
|
||||
case Intent.ACTION_PACKAGE_FULLY_REMOVED:
|
||||
final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
|
||||
synchronized (mLock) {
|
||||
onAppRemovedLocked(getPackageName(intent), uid);
|
||||
onAppRemovedLocked(UserHandle.getUserId(uid), getPackageName(intent));
|
||||
}
|
||||
break;
|
||||
case Intent.ACTION_USER_REMOVED:
|
||||
@@ -358,21 +358,20 @@ abstract class QuotaTracker {
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
abstract void handleRemovedAppLocked(String packageName, int uid);
|
||||
abstract void handleRemovedAppLocked(int userId, @NonNull String packageName);
|
||||
|
||||
@GuardedBy("mLock")
|
||||
void onAppRemovedLocked(String packageName, int uid) {
|
||||
void onAppRemovedLocked(final int userId, @NonNull String packageName) {
|
||||
if (packageName == null) {
|
||||
Slog.wtf(TAG, "Told app removed but given null package name.");
|
||||
return;
|
||||
}
|
||||
final int userId = UserHandle.getUserId(uid);
|
||||
|
||||
mInQuotaAlarmListener.removeAlarmsLocked(userId, packageName);
|
||||
|
||||
mFreeQuota.delete(userId, packageName);
|
||||
|
||||
handleRemovedAppLocked(packageName, uid);
|
||||
handleRemovedAppLocked(userId, packageName);
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
|
||||
@@ -16,29 +16,15 @@
|
||||
|
||||
package com.android.server.utils.quota;
|
||||
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.UserHandle;
|
||||
import android.testing.TestableContext;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoSession;
|
||||
import org.mockito.quality.Strictness;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
@@ -46,20 +32,15 @@ import java.time.Duration;
|
||||
public class MultiRateLimiterTest {
|
||||
|
||||
private static final int USER_ID = 1;
|
||||
private static final int UID_1 = 10_001;
|
||||
private static final String PACKAGE_NAME_1 = "com.android.package.one";
|
||||
private static final String PACKAGE_NAME_2 = "com.android.package.two";
|
||||
private static final String TAG = "tag";
|
||||
|
||||
@Rule
|
||||
public final TestableContext mTestableContext =
|
||||
public final TestableContext mContext =
|
||||
new TestableContext(InstrumentationRegistry.getContext(), null);
|
||||
|
||||
private final InjectorForTest mInjector = new InjectorForTest();
|
||||
private MockitoSession mMockingSession;
|
||||
private ContextWrapper mContext;
|
||||
|
||||
@Mock private PackageManager mPackageManager;
|
||||
|
||||
private static class InjectorForTest extends QuotaTracker.Injector {
|
||||
Duration mElapsedTime = Duration.ZERO;
|
||||
@@ -75,38 +56,9 @@ public class MultiRateLimiterTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
mMockingSession = mockitoSession()
|
||||
.initMocks(this)
|
||||
.strictness(Strictness.LENIENT)
|
||||
.mockStatic(UserHandle.class)
|
||||
.startMocking();
|
||||
doReturn(USER_ID).when(() -> UserHandle.getUserId(UID_1));
|
||||
|
||||
ApplicationInfo applicationInfo = new ApplicationInfo();
|
||||
applicationInfo.uid = UID_1;
|
||||
when(mPackageManager.getApplicationInfoAsUser(PACKAGE_NAME_1, 0, USER_ID))
|
||||
.thenReturn(applicationInfo);
|
||||
|
||||
mContext = new ContextWrapper(mTestableContext) {
|
||||
@Override
|
||||
public PackageManager getPackageManager() {
|
||||
return mPackageManager;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
if (mMockingSession != null) {
|
||||
mMockingSession.finishMocking();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleRateLimit_belowLimit_isWithinQuota() {
|
||||
MultiRateLimiter multiRateLimiter = new MultiRateLimiter.Builder(mContext, mInjector)
|
||||
MultiRateLimiter multiRateLimiter = new MultiRateLimiter.Builder(mContext, mInjector)
|
||||
.addRateLimit(3, Duration.ofSeconds(20))
|
||||
.build();
|
||||
|
||||
@@ -125,7 +77,7 @@ public class MultiRateLimiterTest {
|
||||
|
||||
@Test
|
||||
public void testSingleRateLimit_aboveLimit_isNotWithinQuota() {
|
||||
MultiRateLimiter multiRateLimiter = new MultiRateLimiter.Builder(mContext, mInjector)
|
||||
MultiRateLimiter multiRateLimiter = new MultiRateLimiter.Builder(mContext, mInjector)
|
||||
.addRateLimit(3, Duration.ofSeconds(20))
|
||||
.build();
|
||||
|
||||
@@ -145,7 +97,7 @@ public class MultiRateLimiterTest {
|
||||
|
||||
@Test
|
||||
public void testSingleRateLimit_afterGoingAboveQuotaAndWaitingWindow_isBackWithinQuota() {
|
||||
MultiRateLimiter multiRateLimiter = new MultiRateLimiter.Builder(mContext, mInjector)
|
||||
MultiRateLimiter multiRateLimiter = new MultiRateLimiter.Builder(mContext, mInjector)
|
||||
.addRateLimit(3, Duration.ofSeconds(20))
|
||||
.build();
|
||||
|
||||
@@ -214,7 +166,7 @@ public class MultiRateLimiterTest {
|
||||
|
||||
@Test
|
||||
public void createSingleRateLimit_testItLimitsOnlyGivenUptc() {
|
||||
MultiRateLimiter multiRateLimiter = new MultiRateLimiter.Builder(mContext, mInjector)
|
||||
MultiRateLimiter multiRateLimiter = new MultiRateLimiter.Builder(mContext, mInjector)
|
||||
.addRateLimit(3, Duration.ofSeconds(20))
|
||||
.build();
|
||||
|
||||
@@ -245,7 +197,7 @@ public class MultiRateLimiterTest {
|
||||
|
||||
@Test
|
||||
public void clearRateLimiterForPackage_afterReachingQuota_quotaIsReset() {
|
||||
MultiRateLimiter multiRateLimiter = new MultiRateLimiter.Builder(mContext, mInjector)
|
||||
MultiRateLimiter multiRateLimiter = new MultiRateLimiter.Builder(mContext, mInjector)
|
||||
.addRateLimit(1, Duration.ofSeconds(100))
|
||||
.build();
|
||||
|
||||
@@ -270,7 +222,7 @@ public class MultiRateLimiterTest {
|
||||
|
||||
@Test
|
||||
public void clearRateLimiterForPackage_doesntAffectOtherPackages() {
|
||||
MultiRateLimiter multiRateLimiter = new MultiRateLimiter.Builder(mContext, mInjector)
|
||||
MultiRateLimiter multiRateLimiter = new MultiRateLimiter.Builder(mContext, mInjector)
|
||||
.addRateLimit(1, Duration.ofSeconds(100))
|
||||
.build();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user