Merge "Add overuse configuration cache in CarWatchdogService." into sc-v2-dev
diff --git a/service/src/com/android/car/watchdog/CarWatchdogService.java b/service/src/com/android/car/watchdog/CarWatchdogService.java
index 4e26cb7..f0f559c 100644
--- a/service/src/com/android/car/watchdog/CarWatchdogService.java
+++ b/service/src/com/android/car/watchdog/CarWatchdogService.java
@@ -244,12 +244,14 @@
@Override
public void dump(IndentingPrintWriter writer) {
- writer.println("*CarWatchdogService*");
+ writer.println("*" + getClass().getSimpleName() + "*");
+ writer.increaseIndent();
synchronized (mLock) {
writer.println("Current garage mode: " + toGarageModeString(mCurrentGarageMode));
}
mWatchdogProcessHandler.dump(writer);
mWatchdogPerfHandler.dump(writer);
+ writer.decreaseIndent();
}
/**
diff --git a/service/src/com/android/car/watchdog/OveruseConfigurationCache.java b/service/src/com/android/car/watchdog/OveruseConfigurationCache.java
new file mode 100644
index 0000000..1402ef6
--- /dev/null
+++ b/service/src/com/android/car/watchdog/OveruseConfigurationCache.java
@@ -0,0 +1,360 @@
+/*
+ * 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.car.watchdog;
+
+import static com.android.car.watchdog.WatchdogPerfHandler.INTERNAL_APPLICATION_CATEGORY_TYPE_MAPS;
+import static com.android.car.watchdog.WatchdogPerfHandler.INTERNAL_APPLICATION_CATEGORY_TYPE_MEDIA;
+
+import android.automotive.watchdog.PerStateBytes;
+import android.automotive.watchdog.internal.ApplicationCategoryType;
+import android.automotive.watchdog.internal.ComponentType;
+import android.automotive.watchdog.internal.IoOveruseConfiguration;
+import android.automotive.watchdog.internal.PackageMetadata;
+import android.automotive.watchdog.internal.PerStateIoOveruseThreshold;
+import android.automotive.watchdog.internal.ResourceOveruseConfiguration;
+import android.automotive.watchdog.internal.ResourceSpecificConfiguration;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.IndentingPrintWriter;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.function.BiFunction;
+
+/**
+ * Cache to store overuse configurations in memory.
+ *
+ * <p>It assumes that the error checking and loading/merging initial configs are done prior to
+ * setting the cache.
+ */
+public final class OveruseConfigurationCache {
+ static final PerStateBytes DEFAULT_THRESHOLD =
+ constructPerStateBytes(Long.MAX_VALUE, Long.MAX_VALUE, Long.MAX_VALUE);
+
+ private final Object mLock = new Object();
+ @GuardedBy("mLock")
+ private final ArraySet<String> mSafeToKillSystemPackages = new ArraySet<>();
+ @GuardedBy("mLock")
+ private final ArraySet<String> mSafeToKillVendorPackages = new ArraySet<>();
+ @GuardedBy("mLock")
+ private final List<String> mVendorPackagePrefixes = new ArrayList<>();
+ @GuardedBy("mLock")
+ private final SparseArray<ArraySet<String>> mPackagesByAppCategoryType = new SparseArray<>();
+ @GuardedBy("mLock")
+ private final SparseArray<PerStateBytes> mGenericIoThresholdsByComponent = new SparseArray<>();
+ @GuardedBy("mLock")
+ private final ArrayMap<String, PerStateBytes> mIoThresholdsBySystemPackages = new ArrayMap<>();
+ @GuardedBy("mLock")
+ private final ArrayMap<String, PerStateBytes> mIoThresholdsByVendorPackages = new ArrayMap<>();
+ @GuardedBy("mLock")
+ private final SparseArray<PerStateBytes> mIoThresholdsByAppCategoryType = new SparseArray<>();
+
+ /** Dumps the contents of the cache. */
+ public void dump(IndentingPrintWriter writer) {
+ writer.println("*" + getClass().getSimpleName() + "*");
+ writer.increaseIndent();
+ synchronized (mLock) {
+ writer.println("mSafeToKillSystemPackages: " + mSafeToKillSystemPackages);
+ writer.println("mSafeToKillVendorPackages: " + mSafeToKillVendorPackages);
+ writer.println("mVendorPackagePrefixes: " + mVendorPackagePrefixes);
+ writer.println("mPackagesByAppCategoryType: ");
+ writer.increaseIndent();
+ for (int i = 0; i < mPackagesByAppCategoryType.size(); ++i) {
+ writer.print("App category: "
+ + toApplicationCategoryTypeString(mPackagesByAppCategoryType.keyAt(i)));
+ writer.println(", Packages: " + mPackagesByAppCategoryType.valueAt(i));
+ }
+ writer.decreaseIndent();
+ writer.println("mGenericIoThresholdsByComponent: ");
+ writer.increaseIndent();
+ for (int i = 0; i < mGenericIoThresholdsByComponent.size(); ++i) {
+ writer.print("Component type: "
+ + toComponentTypeString(mGenericIoThresholdsByComponent.keyAt(i)));
+ writer.print(", Threshold: ");
+ dumpPerStateBytes(mGenericIoThresholdsByComponent.valueAt(i), writer);
+ }
+ writer.decreaseIndent();
+ writer.println("mIoThresholdsBySystemPackages: ");
+ writer.increaseIndent();
+ for (int i = 0; i < mIoThresholdsBySystemPackages.size(); ++i) {
+ writer.print("Package name: " + mIoThresholdsBySystemPackages.keyAt(i));
+ writer.print(", Threshold: ");
+ dumpPerStateBytes(mIoThresholdsBySystemPackages.valueAt(i), writer);
+ }
+ writer.decreaseIndent();
+ writer.println("mIoThresholdsByVendorPackages: ");
+ writer.increaseIndent();
+ for (int i = 0; i < mIoThresholdsByVendorPackages.size(); ++i) {
+ writer.print("Package name: " + mIoThresholdsByVendorPackages.keyAt(i));
+ writer.print(", Threshold: ");
+ dumpPerStateBytes(mIoThresholdsByVendorPackages.valueAt(i), writer);
+ }
+ writer.decreaseIndent();
+ writer.println("mIoThresholdsByAppCategoryType: ");
+ writer.increaseIndent();
+ for (int i = 0; i < mIoThresholdsByAppCategoryType.size(); ++i) {
+ writer.print("App category: "
+ + toApplicationCategoryTypeString(mIoThresholdsByAppCategoryType.keyAt(i)));
+ writer.print(", Threshold: ");
+ dumpPerStateBytes(mIoThresholdsByAppCategoryType.valueAt(i), writer);
+ }
+ writer.decreaseIndent();
+ }
+ writer.decreaseIndent();
+ }
+
+ /** Overwrites the configurations in the cache. */
+ public void set(List<ResourceOveruseConfiguration> configs) {
+ synchronized (mLock) {
+ clearLocked();
+ for (int i = 0; i < configs.size(); i++) {
+ ResourceOveruseConfiguration config = configs.get(i);
+ switch (config.componentType) {
+ case ComponentType.SYSTEM:
+ mSafeToKillSystemPackages.addAll(config.safeToKillPackages);
+ break;
+ case ComponentType.VENDOR:
+ mSafeToKillVendorPackages.addAll(config.safeToKillPackages);
+ mVendorPackagePrefixes.addAll(config.vendorPackagePrefixes);
+ for (int j = 0; j < config.packageMetadata.size(); ++j) {
+ PackageMetadata meta = config.packageMetadata.get(j);
+ ArraySet<String> packages =
+ mPackagesByAppCategoryType.get(meta.appCategoryType);
+ if (packages == null) {
+ packages = new ArraySet<>();
+ }
+ packages.add(meta.packageName);
+ mPackagesByAppCategoryType.append(meta.appCategoryType, packages);
+ }
+ break;
+ default:
+ // All third-party apps are killable.
+ break;
+ }
+ for (int j = 0; j < config.resourceSpecificConfigurations.size(); ++j) {
+ if (config.resourceSpecificConfigurations.get(j).getTag()
+ == ResourceSpecificConfiguration.ioOveruseConfiguration) {
+ setIoThresholdsLocked(config.componentType,
+ config.resourceSpecificConfigurations.get(j)
+ .getIoOveruseConfiguration());
+ }
+ }
+ }
+ }
+ }
+
+ /** Returns the threshold for the given package and component type. */
+ public PerStateBytes fetchThreshold(String genericPackageName,
+ @ComponentType int componentType) {
+ synchronized (mLock) {
+ PerStateBytes threshold = null;
+ switch (componentType) {
+ case ComponentType.SYSTEM:
+ threshold = mIoThresholdsBySystemPackages.get(genericPackageName);
+ if (threshold != null) {
+ return copyPerStateBytes(threshold);
+ }
+ break;
+ case ComponentType.VENDOR:
+ threshold = mIoThresholdsByVendorPackages.get(genericPackageName);
+ if (threshold != null) {
+ return copyPerStateBytes(threshold);
+ }
+ break;
+ }
+ threshold = fetchAppCategorySpecificThresholdLocked(genericPackageName);
+ if (threshold != null) {
+ return copyPerStateBytes(threshold);
+ }
+ threshold = mGenericIoThresholdsByComponent.get(componentType);
+ return threshold != null ? copyPerStateBytes(threshold)
+ : copyPerStateBytes(DEFAULT_THRESHOLD);
+ }
+ }
+
+ /** Returns whether or not the given package is safe-to-kill on resource overuse. */
+ public boolean isSafeToKill(String genericPackageName, @ComponentType int componentType,
+ List<String> sharedPackages) {
+ synchronized (mLock) {
+ BiFunction<List<String>, Set<String>, Boolean> isSafeToKillAnyPackage =
+ (packages, safeToKillPackages) -> {
+ if (packages == null) {
+ return false;
+ }
+ for (int i = 0; i < packages.size(); i++) {
+ if (safeToKillPackages.contains(packages.get(i))) {
+ return true;
+ }
+ }
+ return false;
+ };
+
+ switch (componentType) {
+ case ComponentType.SYSTEM:
+ if (mSafeToKillSystemPackages.contains(genericPackageName)) {
+ return true;
+ }
+ return isSafeToKillAnyPackage.apply(sharedPackages, mSafeToKillSystemPackages);
+ case ComponentType.VENDOR:
+ if (mSafeToKillVendorPackages.contains(genericPackageName)) {
+ return true;
+ }
+ /*
+ * Packages under the vendor shared UID may contain system packages because when
+ * CarWatchdogService derives the shared component type it attributes system
+ * packages as vendor packages when there is at least one vendor package.
+ */
+ return isSafeToKillAnyPackage.apply(sharedPackages, mSafeToKillSystemPackages)
+ || isSafeToKillAnyPackage.apply(sharedPackages,
+ mSafeToKillVendorPackages);
+ default:
+ // Third-party apps are always killable
+ return true;
+ }
+ }
+ }
+
+ /** Returns the list of vendor package prefixes. */
+ public List<String> getVendorPackagePrefixes() {
+ synchronized (mLock) {
+ return new ArrayList<>(mVendorPackagePrefixes);
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void clearLocked() {
+ mSafeToKillSystemPackages.clear();
+ mSafeToKillVendorPackages.clear();
+ mVendorPackagePrefixes.clear();
+ mPackagesByAppCategoryType.clear();
+ mGenericIoThresholdsByComponent.clear();
+ mIoThresholdsBySystemPackages.clear();
+ mIoThresholdsByVendorPackages.clear();
+ mIoThresholdsByAppCategoryType.clear();
+ }
+
+ @GuardedBy("mLock")
+ private void setIoThresholdsLocked(int componentType, IoOveruseConfiguration ioConfig) {
+ mGenericIoThresholdsByComponent.append(componentType,
+ ioConfig.componentLevelThresholds.perStateWriteBytes);
+ switch (componentType) {
+ case ComponentType.SYSTEM:
+ populateThresholdsByPackagesLocked(
+ ioConfig.packageSpecificThresholds, mIoThresholdsBySystemPackages);
+ break;
+ case ComponentType.VENDOR:
+ populateThresholdsByPackagesLocked(
+ ioConfig.packageSpecificThresholds, mIoThresholdsByVendorPackages);
+ setIoThresholdsByAppCategoryTypeLocked(ioConfig.categorySpecificThresholds);
+ break;
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void setIoThresholdsByAppCategoryTypeLocked(
+ List<PerStateIoOveruseThreshold> thresholds) {
+ for (int i = 0; i < thresholds.size(); ++i) {
+ PerStateIoOveruseThreshold threshold = thresholds.get(i);
+ switch(threshold.name) {
+ case INTERNAL_APPLICATION_CATEGORY_TYPE_MAPS:
+ mIoThresholdsByAppCategoryType.append(
+ ApplicationCategoryType.MAPS, threshold.perStateWriteBytes);
+ break;
+ case INTERNAL_APPLICATION_CATEGORY_TYPE_MEDIA:
+ mIoThresholdsByAppCategoryType.append(ApplicationCategoryType.MEDIA,
+ threshold.perStateWriteBytes);
+ break;
+ }
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void populateThresholdsByPackagesLocked(List<PerStateIoOveruseThreshold> thresholds,
+ ArrayMap<String, PerStateBytes> thresholdsByPackages) {
+ for (int i = 0; i < thresholds.size(); ++i) {
+ thresholdsByPackages.put(
+ thresholds.get(i).name, thresholds.get(i).perStateWriteBytes);
+ }
+ }
+
+ @GuardedBy("mLock")
+ private PerStateBytes fetchAppCategorySpecificThresholdLocked(String genericPackageName) {
+ for (int i = 0; i < mPackagesByAppCategoryType.size(); ++i) {
+ if (mPackagesByAppCategoryType.valueAt(i).contains(genericPackageName)) {
+ return mIoThresholdsByAppCategoryType.get(mPackagesByAppCategoryType.keyAt(i));
+ }
+ }
+ return null;
+ }
+
+ private static String toApplicationCategoryTypeString(@ApplicationCategoryType int type) {
+ switch (type) {
+ case ApplicationCategoryType.MAPS:
+ return "ApplicationCategoryType.MAPS";
+ case ApplicationCategoryType.MEDIA:
+ return "ApplicationCategoryType.MEDIA";
+ case ApplicationCategoryType.OTHERS:
+ return "ApplicationCategoryType.OTHERS";
+ default:
+ return "Invalid ApplicationCategoryType";
+ }
+ }
+
+ private static String toComponentTypeString(@ComponentType int type) {
+ switch (type) {
+ case ComponentType.SYSTEM:
+ return "ComponentType.SYSTEM";
+ case ComponentType.VENDOR:
+ return "ComponentType.VENDOR";
+ case ComponentType.THIRD_PARTY:
+ return "ComponentType.THIRD_PARTY";
+ default:
+ return "ComponentType.UNKNOWN";
+ }
+ }
+
+ private static void dumpPerStateBytes(PerStateBytes perStateBytes,
+ IndentingPrintWriter writer) {
+ if (perStateBytes == null) {
+ writer.println("{NULL}");
+ return;
+ }
+ writer.println("{Foreground bytes: " + perStateBytes.foregroundBytes
+ + ", Background bytes: " + perStateBytes.backgroundBytes + ", Garage mode bytes: "
+ + perStateBytes.garageModeBytes + '}');
+ }
+
+ private static PerStateBytes constructPerStateBytes(long fgBytes, long bgBytes, long gmBytes) {
+ return new PerStateBytes() {{
+ foregroundBytes = fgBytes;
+ backgroundBytes = bgBytes;
+ garageModeBytes = gmBytes;
+ }};
+ }
+
+ private static PerStateBytes copyPerStateBytes(PerStateBytes perStateBytes) {
+ return new PerStateBytes() {{
+ foregroundBytes = perStateBytes.foregroundBytes;
+ backgroundBytes = perStateBytes.backgroundBytes;
+ garageModeBytes = perStateBytes.garageModeBytes;
+ }};
+ }
+}
diff --git a/service/src/com/android/car/watchdog/WatchdogPerfHandler.java b/service/src/com/android/car/watchdog/WatchdogPerfHandler.java
index 557addb..774b806 100644
--- a/service/src/com/android/car/watchdog/WatchdogPerfHandler.java
+++ b/service/src/com/android/car/watchdog/WatchdogPerfHandler.java
@@ -151,6 +151,7 @@
private final Handler mMainHandler;
private final Handler mServiceHandler;
private final WatchdogStorage mWatchdogStorage;
+ private final OveruseConfigurationCache mOveruseConfigurationCache;
private final Object mLock = new Object();
@GuardedBy("mLock")
private final ArrayMap<String, PackageResourceUsage> mUsageByUserPackage = new ArrayMap<>();
@@ -163,10 +164,6 @@
@GuardedBy("mLock")
private final SparseArray<ArrayList<ResourceOveruseListenerInfo>>
mOveruseSystemListenerInfosByUid = new SparseArray<>();
- @GuardedBy("mLock")
- private final ArraySet<String> mSafeToKillSystemPackages = new ArraySet<>();
- @GuardedBy("mLock")
- private final ArraySet<String> mSafeToKillVendorPackages = new ArraySet<>();
/** Default killable state for packages. Updated only for {@link UserHandle.ALL} user handle. */
@GuardedBy("mLock")
private final ArraySet<String> mDefaultNotKillableGenericPackages = new ArraySet<>();
@@ -218,6 +215,7 @@
mServiceHandler = new Handler(CarServiceUtils.getHandlerThread(
CarWatchdogService.class.getSimpleName()).getLooper());
mWatchdogStorage = watchdogStorage;
+ mOveruseConfigurationCache = new OveruseConfigurationCache();
mTimeSource = SYSTEM_INSTANCE;
mOveruseHandlingDelayMills = OVERUSE_HANDLING_DELAY_MILLS;
mCurrentUxState = UX_STATE_NO_DISTRACTION;
@@ -254,6 +252,7 @@
/*
* TODO(b/183436216): Implement this method.
*/
+ mOveruseConfigurationCache.dump(writer);
}
/** Retries any pending requests on re-connecting to the daemon */
@@ -557,7 +556,8 @@
packageInfo.applicationInfo);
int killableState = getPackageKillableStateForUserPackageLocked(
userId, genericPackageName, componentType,
- isSafeToKillLocked(genericPackageName, componentType, null));
+ mOveruseConfigurationCache.isSafeToKill(
+ genericPackageName, componentType, /* sharedPackages= */null));
states.add(new PackageKillableState(packageInfo.packageName, userId,
killableState));
continue;
@@ -582,7 +582,8 @@
}
int killableState = getPackageKillableStateForUserPackageLocked(
userId, genericPackageName, componentType,
- isSafeToKillLocked(genericPackageName, componentType, packageNames));
+ mOveruseConfigurationCache.isSafeToKill(
+ genericPackageName, componentType, packageNames));
for (int i = 0; i < applicationInfos.size(); ++i) {
states.add(new PackageKillableState(
applicationInfos.get(i).packageName, userId, killableState));
@@ -806,25 +807,9 @@
Slogf.e(TAG, "Fetched resource overuse configurations are empty");
return;
}
- synchronized (mLock) {
- mSafeToKillSystemPackages.clear();
- mSafeToKillVendorPackages.clear();
- for (int i = 0; i < internalConfigs.size(); i++) {
- switch (internalConfigs.get(i).componentType) {
- case ComponentType.SYSTEM:
- mSafeToKillSystemPackages.addAll(internalConfigs.get(i).safeToKillPackages);
- break;
- case ComponentType.VENDOR:
- mSafeToKillVendorPackages.addAll(internalConfigs.get(i).safeToKillPackages);
- mPackageInfoHandler.setVendorPackagePrefixes(
- internalConfigs.get(i).vendorPackagePrefixes);
- break;
- default:
- // All third-party apps are killable.
- break;
- }
- }
- }
+ mOveruseConfigurationCache.set(internalConfigs);
+ mPackageInfoHandler.setVendorPackagePrefixes(
+ mOveruseConfigurationCache.getVendorPackagePrefixes());
if (DEBUG) {
Slogf.d(TAG, "Fetched and synced resource overuse configs.");
}
@@ -1242,45 +1227,6 @@
}
}
- @GuardedBy("mLock")
- private boolean isSafeToKillLocked(String genericPackageName, int componentType,
- List<String> sharedPackages) {
- BiFunction<List<String>, Set<String>, Boolean> isSafeToKillAnyPackage =
- (packages, safeToKillPackages) -> {
- if (packages == null) {
- return false;
- }
- for (int i = 0; i < packages.size(); i++) {
- if (safeToKillPackages.contains(packages.get(i))) {
- return true;
- }
- }
- return false;
- };
-
- switch (componentType) {
- case ComponentType.SYSTEM:
- if (mSafeToKillSystemPackages.contains(genericPackageName)) {
- return true;
- }
- return isSafeToKillAnyPackage.apply(sharedPackages, mSafeToKillSystemPackages);
- case ComponentType.VENDOR:
- if (mSafeToKillVendorPackages.contains(genericPackageName)) {
- return true;
- }
- /*
- * Packages under the vendor shared UID may contain system packages because when
- * CarWatchdogService derives the shared component type it attributes system
- * packages as vendor packages when there is at least one vendor package.
- */
- return isSafeToKillAnyPackage.apply(sharedPackages, mSafeToKillSystemPackages)
- || isSafeToKillAnyPackage.apply(sharedPackages, mSafeToKillVendorPackages);
- default:
- // Third-party apps are always killable
- return true;
- }
- }
-
private int[] getAliveUserIds() {
UserManager userManager = UserManager.get(mContext);
List<UserHandle> aliveUsers = userManager.getUserHandles(/* excludeDying= */ true);
diff --git a/service/src/com/android/car/watchdog/WatchdogProcessHandler.java b/service/src/com/android/car/watchdog/WatchdogProcessHandler.java
index 63aa135..e0cd6f3 100644
--- a/service/src/com/android/car/watchdog/WatchdogProcessHandler.java
+++ b/service/src/com/android/car/watchdog/WatchdogProcessHandler.java
@@ -122,6 +122,7 @@
} else {
writer.println("none");
}
+ writer.decreaseIndent();
}
}
diff --git a/tests/carservice_unit_test/src/com/android/car/watchdog/CarWatchdogServiceUnitTest.java b/tests/carservice_unit_test/src/com/android/car/watchdog/CarWatchdogServiceUnitTest.java
index b6fb9db..8f30d7a 100644
--- a/tests/carservice_unit_test/src/com/android/car/watchdog/CarWatchdogServiceUnitTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/watchdog/CarWatchdogServiceUnitTest.java
@@ -1280,65 +1280,50 @@
@Test
public void testGetPackageKillableStatesAsUserWithSafeToKillPackages() throws Exception {
- mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12);
+ mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 100, 101);
injectPackageInfos(Arrays.asList(
- constructPackageManagerPackageInfo("system_package.non_critical.A", 1102459, null),
- constructPackageManagerPackageInfo("third_party_package", 1103456, null),
- constructPackageManagerPackageInfo("vendor_package.critical.B", 1101278, null),
- constructPackageManagerPackageInfo("vendor_package.non_critical.A", 1105573, null),
- constructPackageManagerPackageInfo("third_party_package", 1203456, null),
- constructPackageManagerPackageInfo("vendor_package.critical.B", 1201278, null)));
-
- List<android.automotive.watchdog.internal.ResourceOveruseConfiguration> configs =
- sampleInternalResourceOveruseConfigurations();
- injectResourceOveruseConfigsAndWait(configs);
+ constructPackageManagerPackageInfo("system_package.non_critical.A", 10002459, null),
+ constructPackageManagerPackageInfo("third_party_package", 10003456, null),
+ constructPackageManagerPackageInfo("vendor_package.critical.B", 10001278, null),
+ constructPackageManagerPackageInfo("vendor_package.non_critical.A", 10005573, null),
+ constructPackageManagerPackageInfo("third_party_package", 10103456, null),
+ constructPackageManagerPackageInfo("vendor_package.critical.B", 10101278, null)));
PackageKillableStateSubject.assertThat(
mCarWatchdogService.getPackageKillableStatesAsUser(UserHandle.ALL))
.containsExactly(
- new PackageKillableState("system_package.non_critical.A", 11,
+ new PackageKillableState("system_package.non_critical.A", 100,
PackageKillableState.KILLABLE_STATE_YES),
- new PackageKillableState("third_party_package", 11,
+ new PackageKillableState("third_party_package", 100,
PackageKillableState.KILLABLE_STATE_YES),
- new PackageKillableState("vendor_package.critical.B", 11,
+ new PackageKillableState("vendor_package.critical.B", 100,
PackageKillableState.KILLABLE_STATE_NEVER),
- new PackageKillableState("vendor_package.non_critical.A", 11,
+ new PackageKillableState("vendor_package.non_critical.A", 100,
PackageKillableState.KILLABLE_STATE_YES),
- new PackageKillableState("third_party_package", 12,
+ new PackageKillableState("third_party_package", 101,
PackageKillableState.KILLABLE_STATE_YES),
- new PackageKillableState("vendor_package.critical.B", 12,
+ new PackageKillableState("vendor_package.critical.B", 101,
PackageKillableState.KILLABLE_STATE_NEVER));
}
@Test
public void testGetPackageKillableStatesAsUserWithVendorPackagePrefixes() throws Exception {
- mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11);
- /* Package names which start with "system" are constructed as system packages. */
- injectPackageInfos(Arrays.asList(
- constructPackageManagerPackageInfo("system_package_as_vendor", 1102459, null)));
-
- android.automotive.watchdog.internal.ResourceOveruseConfiguration vendorConfig =
- new android.automotive.watchdog.internal.ResourceOveruseConfiguration();
- vendorConfig.componentType = ComponentType.VENDOR;
- vendorConfig.safeToKillPackages = Collections.singletonList("system_package_as_vendor");
- vendorConfig.vendorPackagePrefixes = Collections.singletonList(
- "system_package_as_vendor");
- injectResourceOveruseConfigsAndWait(Collections.singletonList(vendorConfig));
+ mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 100);
+ injectPackageInfos(Collections.singletonList(constructPackageManagerPackageInfo(
+ "some_pkg_as_vendor_pkg", 10002459, /* sharedUserId= */ null, /* flags= */ 0,
+ ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT)));
List<PackageKillableState> killableStates =
- mCarWatchdogService.getPackageKillableStatesAsUser(new UserHandle(11));
+ mCarWatchdogService.getPackageKillableStatesAsUser(new UserHandle(100));
- /* When CarWatchdogService connects with the watchdog daemon, CarWatchdogService fetches
- * resource overuse configs from watchdog daemon. The vendor package prefixes in the
- * configs help identify vendor packages. The safe-to-kill list in the configs helps
- * identify safe-to-kill vendor packages. |system_package_as_vendor| is a critical system
- * package by default but with the latest resource overuse configs, this package should be
- * classified as a safe-to-kill vendor package.
- */
+ // The vendor package prefixes in the resource overuse configs help identify vendor
+ // packages. The safe-to-kill list in the vendor configs helps identify safe-to-kill vendor
+ // packages. |system_package_as_vendor| is a critical system package by default but with
+ // the resource overuse configs, this package should be classified as a safe-to-kill vendor
+ // package.
PackageKillableStateSubject.assertThat(killableStates)
- .containsExactly(
- new PackageKillableState("system_package_as_vendor", 11,
- PackageKillableState.KILLABLE_STATE_YES));
+ .containsExactly(new PackageKillableState("some_pkg_as_vendor_pkg", 100,
+ PackageKillableState.KILLABLE_STATE_YES));
}
@Test
@@ -1374,71 +1359,55 @@
@Test
public void testGetPackageKillableStatesAsUserWithSharedUidsAndSafeToKillPackages()
throws Exception {
- mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11);
+ mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 100);
injectPackageInfos(Arrays.asList(
constructPackageManagerPackageInfo(
- "vendor_package.non_critical.A", 1103456, "vendor_shared_package.A"),
+ "vendor_package.non_critical.A", 10003456, "vendor_shared_package.A"),
constructPackageManagerPackageInfo(
- "system_package.A", 1103456, "vendor_shared_package.A"),
+ "system_package.A", 10003456, "vendor_shared_package.A"),
constructPackageManagerPackageInfo(
- "vendor_package.B", 1103456, "vendor_shared_package.A"),
+ "vendor_package.B", 10003456, "vendor_shared_package.A"),
constructPackageManagerPackageInfo(
- "third_party_package.C", 1105678, "third_party_shared_package"),
+ "third_party_package.C", 10005678, "third_party_shared_package"),
constructPackageManagerPackageInfo(
- "third_party_package.D", 1105678, "third_party_shared_package")));
-
- android.automotive.watchdog.internal.ResourceOveruseConfiguration vendorConfig =
- new android.automotive.watchdog.internal.ResourceOveruseConfiguration();
- vendorConfig.componentType = ComponentType.VENDOR;
- vendorConfig.safeToKillPackages = Collections.singletonList(
- "vendor_package.non_critical.A");
- vendorConfig.vendorPackagePrefixes = new ArrayList<>();
- injectResourceOveruseConfigsAndWait(Collections.singletonList(vendorConfig));
+ "third_party_package.D", 10005678, "third_party_shared_package")));
PackageKillableStateSubject.assertThat(
- mCarWatchdogService.getPackageKillableStatesAsUser(new UserHandle(11)))
+ mCarWatchdogService.getPackageKillableStatesAsUser(new UserHandle(100)))
.containsExactly(
- new PackageKillableState("vendor_package.non_critical.A", 11,
+ new PackageKillableState("vendor_package.non_critical.A", 100,
PackageKillableState.KILLABLE_STATE_YES),
- new PackageKillableState("system_package.A", 11,
+ new PackageKillableState("system_package.A", 100,
PackageKillableState.KILLABLE_STATE_YES),
- new PackageKillableState("vendor_package.B", 11,
+ new PackageKillableState("vendor_package.B", 100,
PackageKillableState.KILLABLE_STATE_YES),
- new PackageKillableState("third_party_package.C", 11,
+ new PackageKillableState("third_party_package.C", 100,
PackageKillableState.KILLABLE_STATE_YES),
- new PackageKillableState("third_party_package.D", 11,
+ new PackageKillableState("third_party_package.D", 100,
PackageKillableState.KILLABLE_STATE_YES));
}
@Test
public void testGetPackageKillableStatesAsUserWithSharedUidsAndSafeToKillSharedPackage()
throws Exception {
- mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11);
+ mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 100);
injectPackageInfos(Arrays.asList(
constructPackageManagerPackageInfo(
- "vendor_package.non_critical.A", 1103456, "vendor_shared_package.B"),
+ "vendor_package.A", 10003456, "vendor_shared_package.non_critical.B"),
constructPackageManagerPackageInfo(
- "system_package.non_critical.A", 1103456, "vendor_shared_package.B"),
+ "system_package.A", 10003456, "vendor_shared_package.non_critical.B"),
constructPackageManagerPackageInfo(
- "vendor_package.non_critical.B", 1103456, "vendor_shared_package.B")));
-
- android.automotive.watchdog.internal.ResourceOveruseConfiguration vendorConfig =
- new android.automotive.watchdog.internal.ResourceOveruseConfiguration();
- vendorConfig.componentType = ComponentType.VENDOR;
- vendorConfig.safeToKillPackages = Collections.singletonList(
- "shared:vendor_shared_package.B");
- vendorConfig.vendorPackagePrefixes = new ArrayList<>();
- injectResourceOveruseConfigsAndWait(Collections.singletonList(vendorConfig));
+ "vendor_package.B", 10003456, "vendor_shared_package.non_critical.B")));
PackageKillableStateSubject.assertThat(
- mCarWatchdogService.getPackageKillableStatesAsUser(new UserHandle(11)))
+ mCarWatchdogService.getPackageKillableStatesAsUser(new UserHandle(100)))
.containsExactly(
- new PackageKillableState("vendor_package.non_critical.A", 11,
+ new PackageKillableState("vendor_package.A", 100,
PackageKillableState.KILLABLE_STATE_YES),
- new PackageKillableState("system_package.non_critical.A", 11,
+ new PackageKillableState("system_package.A", 100,
PackageKillableState.KILLABLE_STATE_YES),
- new PackageKillableState("vendor_package.non_critical.B", 11,
+ new PackageKillableState("vendor_package.B", 100,
PackageKillableState.KILLABLE_STATE_YES));
}
@@ -1503,12 +1472,16 @@
sampleResourceOveruseConfigurations(), CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO))
.isEqualTo(CarWatchdogManager.RETURN_CODE_SUCCESS);
- /* Expect two calls, the first is made at car watchdog service init */
- verify(mMockCarWatchdogDaemon, times(2)).getResourceOveruseConfigurations();
-
InternalResourceOveruseConfigurationSubject
.assertThat(captureOnSetResourceOveruseConfigurations())
.containsExactlyElementsIn(sampleInternalResourceOveruseConfigurations());
+
+ // CarService fetches and syncs resource overuse configuration on the main thread by posting
+ // a new message. Wait until this completes.
+ CarServiceUtils.runOnMainSync(() -> {});
+
+ /* Expect two calls, the first is made at car watchdog service init */
+ verify(mMockCarWatchdogDaemon, times(2)).getResourceOveruseConfigurations();
}
@Test
@@ -1689,9 +1662,6 @@
@Test
public void testGetResourceOveruseConfigurations() throws Exception {
- when(mMockCarWatchdogDaemon.getResourceOveruseConfigurations())
- .thenReturn(sampleInternalResourceOveruseConfigurations());
-
List<ResourceOveruseConfiguration> actualConfigs =
mCarWatchdogService.getResourceOveruseConfigurations(
CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO);
@@ -1725,9 +1695,6 @@
.when(() -> ServiceManager.getService(CAR_WATCHDOG_DAEMON_INTERFACE));
mCarWatchdogDaemonBinderDeathRecipient.binderDied();
- when(mMockCarWatchdogDaemon.getResourceOveruseConfigurations())
- .thenReturn(sampleInternalResourceOveruseConfigurations());
-
List<ResourceOveruseConfiguration> actualConfigs =
mCarWatchdogService.getResourceOveruseConfigurations(
CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO);
@@ -2693,6 +2660,126 @@
verify(mMockCarWatchdogDaemon, never()).controlProcessHealthCheck(anyBoolean());
}
+ @Test
+ public void testOveruseConfigurationCacheGetVendorPackagePrefixes() throws Exception {
+ OveruseConfigurationCache cache = new OveruseConfigurationCache();
+
+ cache.set(sampleInternalResourceOveruseConfigurations());
+
+ assertWithMessage("Vendor package prefixes").that(cache.getVendorPackagePrefixes())
+ .containsExactly("vendor_package", "some_pkg_as_vendor_pkg");
+ }
+
+ @Test
+ public void testOveruseConfigurationCacheFetchThreshold() throws Exception {
+ OveruseConfigurationCache cache = new OveruseConfigurationCache();
+
+ cache.set(sampleInternalResourceOveruseConfigurations());
+
+ InternalPerStateBytesSubject.assertWithMessage(
+ cache.fetchThreshold("system_package.non_critical.A", ComponentType.SYSTEM),
+ "System package with generic threshold")
+ .isEqualTo(constructPerStateBytes(10, 20, 30));
+
+ InternalPerStateBytesSubject.assertWithMessage(
+ cache.fetchThreshold("system_package.A", ComponentType.SYSTEM),
+ "System package with package specific threshold")
+ .isEqualTo(constructPerStateBytes(40, 50, 60));
+
+ InternalPerStateBytesSubject.assertWithMessage(
+ cache.fetchThreshold("system_package.MEDIA", ComponentType.SYSTEM),
+ "System package with media category threshold")
+ .isEqualTo(constructPerStateBytes(200, 400, 600));
+
+ InternalPerStateBytesSubject.assertWithMessage(
+ cache.fetchThreshold("vendor_package.non_critical.A", ComponentType.VENDOR),
+ "Vendor package with generic threshold")
+ .isEqualTo(constructPerStateBytes(20, 40, 60));
+
+ InternalPerStateBytesSubject.assertWithMessage(
+ cache.fetchThreshold("vendor_package.A", ComponentType.VENDOR),
+ "Vendor package with package specific threshold")
+ .isEqualTo(constructPerStateBytes(80, 100, 120));
+
+ InternalPerStateBytesSubject.assertWithMessage(
+ cache.fetchThreshold("vendor_package.MEDIA", ComponentType.VENDOR),
+ "Vendor package with media category threshold")
+ .isEqualTo(constructPerStateBytes(200, 400, 600));
+
+ InternalPerStateBytesSubject.assertWithMessage(
+ cache.fetchThreshold("third_party_package.A",
+ ComponentType.THIRD_PARTY),
+ "3p package with generic threshold").isEqualTo(constructPerStateBytes(30, 60, 90));
+
+ InternalPerStateBytesSubject.assertWithMessage(
+ cache.fetchThreshold("third_party_package.MAPS", ComponentType.VENDOR),
+ "3p package with maps category threshold")
+ .isEqualTo(constructPerStateBytes(2200, 4400, 6600));
+ }
+
+ @Test
+ public void testOveruseConfigurationCacheIsSafeToKill() throws Exception {
+ OveruseConfigurationCache cache = new OveruseConfigurationCache();
+
+ cache.set(sampleInternalResourceOveruseConfigurations());
+
+ assertWithMessage("isSafeToKill non-critical system package").that(cache.isSafeToKill(
+ "system_package.non_critical.A", ComponentType.SYSTEM, null)).isTrue();
+
+ assertWithMessage("isSafeToKill shared non-critical system package")
+ .that(cache.isSafeToKill("system_package.A", ComponentType.SYSTEM,
+ Collections.singletonList("system_package.non_critical.A"))).isTrue();
+
+ assertWithMessage("isSafeToKill non-critical vendor package").that(cache.isSafeToKill(
+ "vendor_package.non_critical.A", ComponentType.VENDOR, null)).isTrue();
+
+ assertWithMessage("isSafeToKill shared non-critical vendor package")
+ .that(cache.isSafeToKill("vendor_package.A", ComponentType.VENDOR,
+ Collections.singletonList("vendor_package.non_critical.A"))).isTrue();
+
+ assertWithMessage("isSafeToKill 3p package").that(cache.isSafeToKill(
+ "third_party_package.A", ComponentType.THIRD_PARTY, null)).isTrue();
+
+ assertWithMessage("isSafeToKill critical system package").that(cache.isSafeToKill(
+ "system_package.A", ComponentType.SYSTEM, null)).isFalse();
+
+ assertWithMessage("isSafeToKill critical vendor package").that(cache.isSafeToKill(
+ "vendor_package.A", ComponentType.VENDOR, null)).isFalse();
+ }
+
+ @Test
+ public void testOverwriteOveruseConfigurationCache() throws Exception {
+ OveruseConfigurationCache cache = new OveruseConfigurationCache();
+
+ cache.set(sampleInternalResourceOveruseConfigurations());
+
+ cache.set(new ArrayList<>());
+
+ assertWithMessage("Vendor package prefixes").that(cache.getVendorPackagePrefixes())
+ .isEmpty();
+
+ InternalPerStateBytesSubject.assertWithMessage(
+ cache.fetchThreshold("system_package.A", ComponentType.SYSTEM),
+ "System package with default threshold")
+ .isEqualTo(OveruseConfigurationCache.DEFAULT_THRESHOLD);
+
+ InternalPerStateBytesSubject.assertWithMessage(
+ cache.fetchThreshold("vendor_package.A", ComponentType.VENDOR),
+ "Vendor package with default threshold")
+ .isEqualTo(OveruseConfigurationCache.DEFAULT_THRESHOLD);
+
+ InternalPerStateBytesSubject.assertWithMessage(
+ cache.fetchThreshold("third_party_package.A", ComponentType.THIRD_PARTY),
+ "3p package with default threshold")
+ .isEqualTo(OveruseConfigurationCache.DEFAULT_THRESHOLD);
+
+ assertWithMessage("isSafeToKill any system package").that(cache.isSafeToKill(
+ "system_package.non_critical.A", ComponentType.SYSTEM, null)).isFalse();
+
+ assertWithMessage("isSafeToKill any vendor package").that(cache.isSafeToKill(
+ "vendor_package.non_critical.A", ComponentType.VENDOR, null)).isFalse();
+ }
+
public static android.automotive.watchdog.PerStateBytes constructPerStateBytes(
long fgBytes, long bgBytes, long gmBytes) {
android.automotive.watchdog.PerStateBytes perStateBytes =
@@ -2703,10 +2790,12 @@
return perStateBytes;
}
- private void mockWatchdogDaemon() {
+ private void mockWatchdogDaemon() throws Exception {
when(mMockBinder.queryLocalInterface(anyString())).thenReturn(mMockCarWatchdogDaemon);
when(mMockCarWatchdogDaemon.asBinder()).thenReturn(mMockBinder);
doReturn(mMockBinder).when(() -> ServiceManager.getService(CAR_WATCHDOG_DAEMON_INTERFACE));
+ when(mMockCarWatchdogDaemon.getResourceOveruseConfigurations()).thenReturn(
+ sampleInternalResourceOveruseConfigurations());
mIsDaemonCrashed = false;
}
@@ -2963,22 +3052,6 @@
return resourceOveruseConfigurationsCaptor.getValue();
}
- private void injectResourceOveruseConfigsAndWait(
- List<android.automotive.watchdog.internal.ResourceOveruseConfiguration> configs)
- throws Exception {
- when(mMockCarWatchdogDaemon.getResourceOveruseConfigurations()).thenReturn(configs);
- /* Trigger CarWatchdogService to fetch/sync resource overuse configurations by changing the
- * daemon connection status from connected -> disconnected -> connected.
- */
- crashWatchdogDaemon();
- restartWatchdogDaemonAndAwait();
-
- /* Method should be invoked 2 times. Once at test setup and once more after the daemon
- * crashes and reconnects.
- */
- verify(mMockCarWatchdogDaemon, times(2)).getResourceOveruseConfigurations();
- }
-
private SparseArray<PackageIoOveruseStats> injectIoOveruseStatsForPackages(
SparseArray<String> genericPackageNameByUid, Set<String> killablePackages,
Set<String> shouldNotifyPackages) throws Exception {
@@ -3185,14 +3258,20 @@
}
private static ResourceOveruseConfiguration.Builder sampleResourceOveruseConfigurationBuilder(
- int componentType, IoOveruseConfiguration ioOveruseConfig) {
+ @ComponentType int componentType, IoOveruseConfiguration ioOveruseConfig) {
String prefix = WatchdogPerfHandler.toComponentTypeStr(componentType).toLowerCase();
List<String> safeToKill = Arrays.asList(prefix + "_package.non_critical.A",
- prefix + "_pkg.non_critical.B");
- List<String> vendorPrefixes = Arrays.asList(prefix + "_package", prefix + "_pkg");
+ prefix + "_pkg.non_critical.B",
+ "shared:" + prefix + "_shared_package.non_critical.B",
+ "some_pkg_as_" + prefix + "_pkg");
+ List<String> vendorPrefixes = Arrays.asList(
+ prefix + "_package", "some_pkg_as_" + prefix + "_pkg");
Map<String, String> pkgToAppCategory = new ArrayMap<>();
- pkgToAppCategory.put(prefix + "_package.non_critical.A",
- "android.car.watchdog.app.category.MEDIA");
+ pkgToAppCategory.put("system_package.MEDIA", "android.car.watchdog.app.category.MEDIA");
+ pkgToAppCategory.put("system_package.A", "android.car.watchdog.app.category.MAPS");
+ pkgToAppCategory.put("vendor_package.MEDIA", "android.car.watchdog.app.category.MEDIA");
+ pkgToAppCategory.put("vendor_package.A", "android.car.watchdog.app.category.MAPS");
+ pkgToAppCategory.put("third_party_package.MAPS", "android.car.watchdog.app.category.MAPS");
ResourceOveruseConfiguration.Builder configBuilder =
new ResourceOveruseConfiguration.Builder(componentType, safeToKill,
vendorPrefixes, pkgToAppCategory);
@@ -3201,49 +3280,57 @@
}
private static IoOveruseConfiguration.Builder sampleIoOveruseConfigurationBuilder(
- int componentType) {
+ @ComponentType int componentType) {
String prefix = WatchdogPerfHandler.toComponentTypeStr(componentType).toLowerCase();
PerStateBytes componentLevelThresholds = new PerStateBytes(
- /* foregroundModeBytes= */ 10, /* backgroundModeBytes= */ 20,
- /* garageModeBytes= */ 30);
+ /* foregroundModeBytes= */ componentType * 10L,
+ /* backgroundModeBytes= */ componentType * 20L,
+ /* garageModeBytes= */ componentType * 30L);
Map<String, PerStateBytes> packageSpecificThresholds = new ArrayMap<>();
packageSpecificThresholds.put(prefix + "_package.A", new PerStateBytes(
- /* foregroundModeBytes= */ 40, /* backgroundModeBytes= */ 50,
- /* garageModeBytes= */ 60));
+ /* foregroundModeBytes= */ componentType * 40L,
+ /* backgroundModeBytes= */ componentType * 50L,
+ /* garageModeBytes= */ componentType * 60L));
Map<String, PerStateBytes> appCategorySpecificThresholds = new ArrayMap<>();
appCategorySpecificThresholds.put(
ResourceOveruseConfiguration.APPLICATION_CATEGORY_TYPE_MEDIA,
- new PerStateBytes(/* foregroundModeBytes= */ 100, /* backgroundModeBytes= */ 200,
- /* garageModeBytes= */ 300));
+ new PerStateBytes(/* foregroundModeBytes= */ componentType * 100L,
+ /* backgroundModeBytes= */ componentType * 200L,
+ /* garageModeBytes= */ componentType * 300L));
appCategorySpecificThresholds.put(
ResourceOveruseConfiguration.APPLICATION_CATEGORY_TYPE_MAPS,
- new PerStateBytes(/* foregroundModeBytes= */ 1100, /* backgroundModeBytes= */ 2200,
- /* garageModeBytes= */ 3300));
+ new PerStateBytes(/* foregroundModeBytes= */ componentType * 1100L,
+ /* backgroundModeBytes= */ componentType * 2200L,
+ /* garageModeBytes= */ componentType * 3300L));
List<IoOveruseAlertThreshold> systemWideThresholds = Collections.singletonList(
- new IoOveruseAlertThreshold(/* durationInSeconds= */ 10,
- /* writtenBytesPerSecond= */ 200));
+ new IoOveruseAlertThreshold(/* durationInSeconds= */ componentType * 10L,
+ /* writtenBytesPerSecond= */ componentType * 200L));
return new IoOveruseConfiguration.Builder(componentLevelThresholds,
packageSpecificThresholds, appCategorySpecificThresholds, systemWideThresholds);
}
private static android.automotive.watchdog.internal.ResourceOveruseConfiguration
- sampleInternalResourceOveruseConfiguration(int componentType,
+ sampleInternalResourceOveruseConfiguration(@ComponentType int componentType,
android.automotive.watchdog.internal.IoOveruseConfiguration ioOveruseConfig) {
String prefix = WatchdogPerfHandler.toComponentTypeStr(componentType).toLowerCase();
android.automotive.watchdog.internal.ResourceOveruseConfiguration config =
new android.automotive.watchdog.internal.ResourceOveruseConfiguration();
config.componentType = componentType;
config.safeToKillPackages = Arrays.asList(prefix + "_package.non_critical.A",
- prefix + "_pkg.non_critical.B");
- config.vendorPackagePrefixes = Arrays.asList(prefix + "_package", prefix + "_pkg");
-
- PackageMetadata metadata = new PackageMetadata();
- metadata.packageName = prefix + "_package.non_critical.A";
- metadata.appCategoryType = ApplicationCategoryType.MEDIA;
- config.packageMetadata = Collections.singletonList(metadata);
+ prefix + "_pkg.non_critical.B",
+ "shared:" + prefix + "_shared_package.non_critical.B",
+ "some_pkg_as_" + prefix + "_pkg");
+ config.vendorPackagePrefixes = Arrays.asList(
+ prefix + "_package", "some_pkg_as_" + prefix + "_pkg");
+ config.packageMetadata = Arrays.asList(
+ constructPackageMetadata("system_package.MEDIA", ApplicationCategoryType.MEDIA),
+ constructPackageMetadata("system_package.A", ApplicationCategoryType.MAPS),
+ constructPackageMetadata("vendor_package.MEDIA", ApplicationCategoryType.MEDIA),
+ constructPackageMetadata("vendor_package.A", ApplicationCategoryType.MAPS),
+ constructPackageMetadata("third_party_package.MAPS", ApplicationCategoryType.MAPS));
ResourceSpecificConfiguration resourceSpecificConfig = new ResourceSpecificConfiguration();
resourceSpecificConfig.setIoOveruseConfiguration(ioOveruseConfig);
@@ -3253,28 +3340,41 @@
}
private static android.automotive.watchdog.internal.IoOveruseConfiguration
- sampleInternalIoOveruseConfiguration(int componentType) {
+ sampleInternalIoOveruseConfiguration(@ComponentType int componentType) {
String prefix = WatchdogPerfHandler.toComponentTypeStr(componentType).toLowerCase();
android.automotive.watchdog.internal.IoOveruseConfiguration config =
new android.automotive.watchdog.internal.IoOveruseConfiguration();
config.componentLevelThresholds = constructPerStateIoOveruseThreshold(
- WatchdogPerfHandler.toComponentTypeStr(componentType), /* fgBytes= */ 10,
- /* bgBytes= */ 20, /* gmBytes= */ 30);
+ WatchdogPerfHandler.toComponentTypeStr(componentType),
+ /* fgBytes= */ componentType * 10L, /* bgBytes= */ componentType * 20L,
+ /*gmBytes= */ componentType * 30L);
config.packageSpecificThresholds = Collections.singletonList(
- constructPerStateIoOveruseThreshold(prefix + "_package.A", /* fgBytes= */ 40,
- /* bgBytes= */ 50, /* gmBytes= */ 60));
+ constructPerStateIoOveruseThreshold(prefix + "_package.A",
+ /* fgBytes= */ componentType * 40L, /* bgBytes= */ componentType * 50L,
+ /* gmBytes= */ componentType * 60L));
config.categorySpecificThresholds = Arrays.asList(
constructPerStateIoOveruseThreshold(
WatchdogPerfHandler.INTERNAL_APPLICATION_CATEGORY_TYPE_MEDIA,
- /* fgBytes= */ 100, /* bgBytes= */ 200, /* gmBytes= */ 300),
+ /* fgBytes= */ componentType * 100L, /* bgBytes= */ componentType * 200L,
+ /* gmBytes= */ componentType * 300L),
constructPerStateIoOveruseThreshold(
WatchdogPerfHandler.INTERNAL_APPLICATION_CATEGORY_TYPE_MAPS,
- /* fgBytes= */ 1100, /* bgBytes= */ 2200, /* gmBytes= */ 3300));
+ /* fgBytes= */ componentType * 1100L, /* bgBytes= */ componentType * 2200L,
+ /* gmBytes= */ componentType * 3300L));
config.systemWideThresholds = Collections.singletonList(
- constructInternalIoOveruseAlertThreshold(/* duration= */ 10, /* writeBPS= */ 200));
+ constructInternalIoOveruseAlertThreshold(
+ /* duration= */ componentType * 10L, /* writeBPS= */ componentType * 200L));
return config;
}
+ private static PackageMetadata constructPackageMetadata(
+ String packageName, @ApplicationCategoryType int appCategoryType) {
+ PackageMetadata metadata = new PackageMetadata();
+ metadata.packageName = packageName;
+ metadata.appCategoryType = appCategoryType;
+ return metadata;
+ }
+
private static PerStateIoOveruseThreshold constructPerStateIoOveruseThreshold(String name,
long fgBytes, long bgBytes, long gmBytes) {
PerStateIoOveruseThreshold threshold = new PerStateIoOveruseThreshold();
diff --git a/tests/carservice_unit_test/src/com/android/car/watchdog/InternalIoOveruseConfigurationSubject.java b/tests/carservice_unit_test/src/com/android/car/watchdog/InternalIoOveruseConfigurationSubject.java
index 9cb67da..47e496e 100644
--- a/tests/carservice_unit_test/src/com/android/car/watchdog/InternalIoOveruseConfigurationSubject.java
+++ b/tests/carservice_unit_test/src/com/android/car/watchdog/InternalIoOveruseConfigurationSubject.java
@@ -19,7 +19,6 @@
import static com.google.common.truth.Truth.assertAbout;
import android.annotation.Nullable;
-import android.automotive.watchdog.PerStateBytes;
import android.automotive.watchdog.internal.IoOveruseAlertThreshold;
import android.automotive.watchdog.internal.IoOveruseConfiguration;
import android.automotive.watchdog.internal.PerStateIoOveruseThreshold;
@@ -71,9 +70,10 @@
if (actual == null || expected == null) {
return (actual == null) && (expected == null);
}
- return actual.componentLevelThresholds.name == expected.componentLevelThresholds.name
- && isPerStateBytesEquals(actual.componentLevelThresholds.perStateWriteBytes,
- expected.componentLevelThresholds.perStateWriteBytes)
+ return actual.componentLevelThresholds.name.equals(expected.componentLevelThresholds.name)
+ && InternalPerStateBytesSubject.isEquals(
+ actual.componentLevelThresholds.perStateWriteBytes,
+ expected.componentLevelThresholds.perStateWriteBytes)
&& isPerStateThresholdEquals(actual.packageSpecificThresholds,
expected.packageSpecificThresholds)
&& isPerStateThresholdEquals(actual.categorySpecificThresholds,
@@ -104,10 +104,9 @@
public static String toString(PerStateIoOveruseThreshold threshold) {
StringBuilder builder = new StringBuilder();
- builder.append("{Name: ").append(threshold.name).append(", WriteBytes: {fgBytes: ")
- .append(threshold.perStateWriteBytes.foregroundBytes).append(", bgBytes: ")
- .append(threshold.perStateWriteBytes.backgroundBytes).append(", gmBytes: ")
- .append(threshold.perStateWriteBytes.garageModeBytes).append("}}");
+ builder.append("{Name: ").append(threshold.name).append(", WriteBytes: ");
+ InternalPerStateBytesSubject.toStringBuilder(builder, threshold.perStateWriteBytes);
+ builder.append("}");
return builder.toString();
}
@@ -139,12 +138,6 @@
return actualStr.equals(expectedStr);
}
- private static boolean isPerStateBytesEquals(PerStateBytes acutal, PerStateBytes expected) {
- return acutal.foregroundBytes == expected.foregroundBytes
- && acutal.backgroundBytes == expected.backgroundBytes
- && acutal.garageModeBytes == expected.garageModeBytes;
- }
-
private static Set<String> toPerStateThresholdStrings(
List<PerStateIoOveruseThreshold> thresholds) {
return thresholds.stream().map(x -> String.format("%s:{%d,%d,%d}", x.name,
diff --git a/tests/carservice_unit_test/src/com/android/car/watchdog/InternalPerStateBytesSubject.java b/tests/carservice_unit_test/src/com/android/car/watchdog/InternalPerStateBytesSubject.java
new file mode 100644
index 0000000..2f97e13
--- /dev/null
+++ b/tests/carservice_unit_test/src/com/android/car/watchdog/InternalPerStateBytesSubject.java
@@ -0,0 +1,88 @@
+/*
+ * 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.car.watchdog;
+
+import static com.google.common.truth.Truth.assertAbout;
+
+import android.annotation.Nullable;
+import android.automotive.watchdog.PerStateBytes;
+
+import com.google.common.truth.FailureMetadata;
+import com.google.common.truth.Subject;
+import com.google.common.truth.Truth;
+
+public final class InternalPerStateBytesSubject extends Subject {
+ // Boiler-plate Subject.Factory for PerStateBytesSubject
+ private static final Subject.Factory<com.android.car.watchdog.InternalPerStateBytesSubject,
+ PerStateBytes> PER_STATE_BYTES_SUBJECT_FACTORY =
+ com.android.car.watchdog.InternalPerStateBytesSubject::new;
+ private static final String NULL_ENTRY_STRING = "{NULL}";
+
+ private final PerStateBytes mActual;
+
+ // User-defined entry point
+ public static InternalPerStateBytesSubject assertThat(@Nullable PerStateBytes perStateBytes) {
+ return assertAbout(PER_STATE_BYTES_SUBJECT_FACTORY).that(perStateBytes);
+ }
+
+ // Static method for getting the subject factory (for use with assertAbout())
+ public static Subject.Factory<InternalPerStateBytesSubject, PerStateBytes> perStateBytes() {
+ return PER_STATE_BYTES_SUBJECT_FACTORY;
+ }
+
+ public static InternalPerStateBytesSubject assertWithMessage(
+ @Nullable PerStateBytes perStateBytes, String format, Object... args) {
+ return Truth.assertWithMessage(format, args).about(PER_STATE_BYTES_SUBJECT_FACTORY)
+ .that(perStateBytes);
+ }
+
+ private InternalPerStateBytesSubject(FailureMetadata failureMetadata,
+ @Nullable PerStateBytes subject) {
+ super(failureMetadata, subject);
+ this.mActual = subject;
+ }
+
+ // User-defined test assertion SPI below this point
+ public void isEqualTo(PerStateBytes expected) {
+ if (mActual == expected) {
+ return;
+ }
+ check("foregroundBytes").that(mActual.foregroundBytes).isEqualTo(expected.foregroundBytes);
+ check("backgroundBytes").that(mActual.backgroundBytes).isEqualTo(expected.backgroundBytes);
+ check("garageModeBytes").that(mActual.garageModeBytes).isEqualTo(expected.garageModeBytes);
+ }
+
+ public static boolean isEquals(PerStateBytes actual, PerStateBytes expected) {
+ if (actual == null || expected == null) {
+ return (actual == null) && (expected == null);
+ }
+ return actual.foregroundBytes == expected.foregroundBytes
+ && actual.backgroundBytes == expected.backgroundBytes
+ && actual.garageModeBytes == expected.garageModeBytes;
+ }
+
+ public static StringBuilder toStringBuilder(
+ StringBuilder builder, PerStateBytes perStateBytes) {
+ if (perStateBytes == null) {
+ return builder.append(NULL_ENTRY_STRING);
+ }
+ return builder.append("{Foreground bytes: ").append(perStateBytes.foregroundBytes)
+ .append(", Background bytes: ").append(perStateBytes.backgroundBytes)
+ .append(", Garage mode bytes: ").append(perStateBytes.garageModeBytes)
+ .append('}');
+ }
+}
diff --git a/tests/carservice_unit_test/src/com/android/car/watchdog/IoUsageStatsEntrySubject.java b/tests/carservice_unit_test/src/com/android/car/watchdog/IoUsageStatsEntrySubject.java
index 91f5875..0479c93 100644
--- a/tests/carservice_unit_test/src/com/android/car/watchdog/IoUsageStatsEntrySubject.java
+++ b/tests/carservice_unit_test/src/com/android/car/watchdog/IoUsageStatsEntrySubject.java
@@ -20,7 +20,6 @@
import android.annotation.Nullable;
import android.automotive.watchdog.IoOveruseStats;
-import android.automotive.watchdog.PerStateBytes;
import com.google.common.truth.Correspondence;
import com.google.common.truth.FailureMetadata;
@@ -80,7 +79,7 @@
}
return actual.userId == expected.userId && actual.packageName.equals(expected.packageName)
&& actual.ioUsage.getTotalTimesKilled() == expected.ioUsage.getTotalTimesKilled()
- && isEqualsPerStateBytes(actual.ioUsage.getForgivenWriteBytes(),
+ && InternalPerStateBytesSubject.isEquals(actual.ioUsage.getForgivenWriteBytes(),
expected.ioUsage.getForgivenWriteBytes())
&& isEqualsIoOveruseStats(actual.ioUsage.getInternalIoOveruseStats(),
expected.ioUsage.getInternalIoOveruseStats());
@@ -92,22 +91,14 @@
return (actual == null) && (expected == null);
}
return actual.killableOnOveruse == expected.killableOnOveruse
- && isEqualsPerStateBytes(actual.remainingWriteBytes, expected.remainingWriteBytes)
+ && InternalPerStateBytesSubject.isEquals(
+ actual.remainingWriteBytes, expected.remainingWriteBytes)
&& actual.startTime == expected.startTime
&& actual.durationInSeconds == expected.durationInSeconds
- && isEqualsPerStateBytes(actual.writtenBytes, expected.writtenBytes)
+ && InternalPerStateBytesSubject.isEquals(actual.writtenBytes, expected.writtenBytes)
&& actual.totalOveruses == expected.totalOveruses;
}
- private static boolean isEqualsPerStateBytes(PerStateBytes actual, PerStateBytes expected) {
- if (actual == null || expected == null) {
- return (actual == null) && (expected == null);
- }
- return actual.foregroundBytes == expected.foregroundBytes
- && actual.backgroundBytes == expected.backgroundBytes
- && actual.garageModeBytes == expected.garageModeBytes;
- }
-
private static String toString(Iterable<WatchdogStorage.IoUsageStatsEntry> entries) {
StringBuilder builder = new StringBuilder();
builder.append('[');
@@ -135,7 +126,7 @@
builder.append("{IoOveruseStats: ");
toStringBuilder(builder, ioUsage.getInternalIoOveruseStats());
builder.append(", ForgivenWriteBytes: ");
- toStringBuilder(builder, ioUsage.getForgivenWriteBytes());
+ InternalPerStateBytesSubject.toStringBuilder(builder, ioUsage.getForgivenWriteBytes());
return builder.append(", Total times killed: ").append(ioUsage.getTotalTimesKilled())
.append('}');
}
@@ -147,26 +138,15 @@
}
builder.append("{Killable on overuse: ").append(stats.killableOnOveruse)
.append(", Remaining write bytes: ");
- toStringBuilder(builder, stats.remainingWriteBytes);
+ InternalPerStateBytesSubject.toStringBuilder(builder, stats.remainingWriteBytes);
builder.append(", Start time: ").append(stats.startTime)
.append(", Duration: ").append(stats.durationInSeconds).append(" seconds")
.append(", Total overuses: ").append(stats.totalOveruses)
.append(", Written bytes: ");
- toStringBuilder(builder, stats.writtenBytes);
+ InternalPerStateBytesSubject.toStringBuilder(builder, stats.writtenBytes);
return builder.append('}');
}
- private static StringBuilder toStringBuilder(
- StringBuilder builder, PerStateBytes perStateBytes) {
- if (perStateBytes == null) {
- return builder.append(NULL_ENTRY_STRING);
- }
- return builder.append("{Foreground bytes: ").append(perStateBytes.foregroundBytes)
- .append(", Background bytes: ").append(perStateBytes.backgroundBytes)
- .append(", Garage mode bytes: ").append(perStateBytes.garageModeBytes)
- .append('}');
- }
-
private IoUsageStatsEntrySubject(FailureMetadata failureMetadata,
@Nullable Iterable<WatchdogStorage.IoUsageStatsEntry> iterableSubject) {
super(failureMetadata, iterableSubject);