diff --git a/apct-tests/perftests/core/Android.mk b/apct-tests/perftests/core/Android.mk
index 3f87a1c8b5980..968478c3f338a 100644
--- a/apct-tests/perftests/core/Android.mk
+++ b/apct-tests/perftests/core/Android.mk
@@ -9,8 +9,11 @@ LOCAL_SRC_FILES := \
src/android/os/ISomeService.aidl
LOCAL_STATIC_JAVA_LIBRARIES := \
+ androidx.appcompat_appcompat \
androidx.test.rules \
androidx.annotation_annotation \
+ apct-perftests-overlay-apps \
+ apct-perftests-resources-manager-apps \
apct-perftests-utils \
guava
@@ -25,5 +28,6 @@ LOCAL_JNI_SHARED_LIBRARIES := libperftestscore_jni
LOCAL_ASSET_DIR := $(TOP)/external/google-fonts/dancing-script
LOCAL_COMPATIBILITY_SUITE += device-tests
+LOCAL_CERTIFICATE := platform
-include $(BUILD_PACKAGE)
+include $(BUILD_PACKAGE)
\ No newline at end of file
diff --git a/apct-tests/perftests/core/AndroidManifest.xml b/apct-tests/perftests/core/AndroidManifest.xml
index a564a4d27fb3a..525975d36772f 100644
--- a/apct-tests/perftests/core/AndroidManifest.xml
+++ b/apct-tests/perftests/core/AndroidManifest.xml
@@ -5,8 +5,11 @@
-
+
+
+
+
+
diff --git a/apct-tests/perftests/core/apps/overlay/Android.bp b/apct-tests/perftests/core/apps/overlay/Android.bp
new file mode 100644
index 0000000000000..7bee30ee9cb49
--- /dev/null
+++ b/apct-tests/perftests/core/apps/overlay/Android.bp
@@ -0,0 +1,188 @@
+// Copyright (C) 2019 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.
+
+android_test_helper_app {
+ name: "Overlay0",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.overlay0",
+ ]
+}
+
+android_test_helper_app {
+ name: "Overlay1",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.overlay1",
+ ]
+}
+
+android_test_helper_app {
+ name: "Overlay2",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.overlay2",
+ ]
+}
+
+android_test_helper_app {
+ name: "Overlay3",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.overlay3",
+ ]
+}
+
+android_test_helper_app {
+ name: "Overlay4",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.overlay4",
+ ]
+}
+
+android_test_helper_app {
+ name: "Overlay5",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.overlay5",
+ ]
+}
+
+android_test_helper_app {
+ name: "Overlay6",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.overlay6",
+ ]
+}
+
+android_test_helper_app {
+ name: "Overlay7",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.overlay7",
+ ]
+}
+android_test_helper_app {
+ name: "Overlay8",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.overlay8",
+ ]
+}
+
+android_test_helper_app {
+ name: "Overlay9",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.overlay9",
+ ]
+}
+
+android_test_helper_app {
+ name: "LargeOverlay0",
+ resource_dirs : [ "res_large" ],
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.overlay.large0",
+ ]
+}
+
+android_test_helper_app {
+ name: "LargeOverlay1",
+ resource_dirs : [ "res_large" ],
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.overlay.large1",
+ ]
+}
+
+android_test_helper_app {
+ name: "LargeOverlay2",
+ resource_dirs : [ "res_large" ],
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.overlay.large2",
+ ]
+}
+
+android_test_helper_app {
+ name: "LargeOverlay3",
+ resource_dirs : [ "res_large" ],
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.overlay.large3",
+ ]
+}
+
+android_test_helper_app {
+ name: "LargeOverlay4",
+ resource_dirs : [ "res_large" ],
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.overlay.large4",
+ ]
+}
+
+android_test_helper_app {
+ name: "LargeOverlay5",
+ resource_dirs : [ "res_large" ],
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.overlay.large5",
+ ]
+}
+
+android_test_helper_app {
+ name: "LargeOverlay6",
+ resource_dirs : [ "res_large" ],
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.overlay.large6",
+ ]
+}
+
+android_test_helper_app {
+ name: "LargeOverlay7",
+ resource_dirs : [ "res_large" ],
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.overlay.large7",
+ ]
+}
+
+android_test_helper_app {
+ name: "LargeOverlay8",
+ resource_dirs : [ "res_large" ],
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.overlay.large8",
+ ]
+}
+
+android_test_helper_app {
+ name: "LargeOverlay9",
+ resource_dirs : [ "res_large" ],
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.overlay.large9",
+ ]
+}
+
+java_library {
+ name: "apct-perftests-overlay-apps",
+ java_resources: [
+ ":Overlay0",
+ ":Overlay1",
+ ":Overlay2",
+ ":Overlay3",
+ ":Overlay4",
+ ":Overlay5",
+ ":Overlay6",
+ ":Overlay7",
+ ":Overlay8",
+ ":Overlay9",
+ ":LargeOverlay0",
+ ":LargeOverlay1",
+ ":LargeOverlay2",
+ ":LargeOverlay3",
+ ":LargeOverlay4",
+ ":LargeOverlay5",
+ ":LargeOverlay6",
+ ":LargeOverlay7",
+ ":LargeOverlay8",
+ ":LargeOverlay9",
+ ],
+}
\ No newline at end of file
diff --git a/apct-tests/perftests/core/apps/overlay/AndroidManifest.xml b/apct-tests/perftests/core/apps/overlay/AndroidManifest.xml
new file mode 100644
index 0000000000000..52f5a89bc9e47
--- /dev/null
+++ b/apct-tests/perftests/core/apps/overlay/AndroidManifest.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apct-tests/perftests/core/apps/overlay/res/values/values.xml b/apct-tests/perftests/core/apps/overlay/res/values/values.xml
new file mode 100644
index 0000000000000..a1a8d83eb1935
--- /dev/null
+++ b/apct-tests/perftests/core/apps/overlay/res/values/values.xml
@@ -0,0 +1,19 @@
+
+
+
+
+ B
+
diff --git a/apct-tests/perftests/core/apps/overlay/res_large/values/values.xml b/apct-tests/perftests/core/apps/overlay/res_large/values/values.xml
new file mode 100644
index 0000000000000..e74144648e322
--- /dev/null
+++ b/apct-tests/perftests/core/apps/overlay/res_large/values/values.xml
@@ -0,0 +1,274 @@
+
+
+
+
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+
diff --git a/apct-tests/perftests/core/apps/reources_manager/Android.bp b/apct-tests/perftests/core/apps/reources_manager/Android.bp
new file mode 100644
index 0000000000000..451613236140a
--- /dev/null
+++ b/apct-tests/perftests/core/apps/reources_manager/Android.bp
@@ -0,0 +1,34 @@
+// Copyright (C) 2019 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.
+
+android_test_helper_app {
+ name: "LargeResourcesCompressed",
+ static_libs: [ "androidx.appcompat_appcompat" ],
+}
+
+genrule {
+ name: "LargeResourcesUncompressed",
+ srcs: [ ":LargeResourcesCompressed" ],
+ out: ["LargeResourcesUncompressed.apk"],
+ cmd: "cp $(in) $(out) && unzip -o $(out) resources.arsc"
+ + " && zip $(out) resources.arsc"
+}
+
+java_library {
+ name: "apct-perftests-resources-manager-apps",
+ java_resources: [
+ ":LargeResourcesCompressed",
+ ":LargeResourcesUncompressed",
+ ],
+}
\ No newline at end of file
diff --git a/apct-tests/perftests/core/apps/reources_manager/AndroidManifest.xml b/apct-tests/perftests/core/apps/reources_manager/AndroidManifest.xml
new file mode 100644
index 0000000000000..adb4e406c6082
--- /dev/null
+++ b/apct-tests/perftests/core/apps/reources_manager/AndroidManifest.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apct-tests/perftests/core/res/color/color_state_list.xml b/apct-tests/perftests/core/res/color/color_state_list.xml
new file mode 100644
index 0000000000000..142e47ae2738b
--- /dev/null
+++ b/apct-tests/perftests/core/res/color/color_state_list.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apct-tests/perftests/core/res/values/overlayable.xml b/apct-tests/perftests/core/res/values/overlayable.xml
new file mode 100644
index 0000000000000..70cedd7b0b757
--- /dev/null
+++ b/apct-tests/perftests/core/res/values/overlayable.xml
@@ -0,0 +1,280 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apct-tests/perftests/core/res/values/strings.xml b/apct-tests/perftests/core/res/values/strings.xml
deleted file mode 100644
index 7ab325f79dc76..0000000000000
--- a/apct-tests/perftests/core/res/values/strings.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
- text text text text text text text text text text text text
- text text text text text text text text text text text text text text text text
- text text text text text text text text text text text text text text text text
- text text text text text text text text text text text text text text text text
- text text text text text text text text text text text text text text text text
- text text text text text text text text text text text text text text text text
- text text text text text text text typo text text text text text text text text
- text text text text text text text text text text text text text text text text
- text text text text text text text text text text text text text text text text
- text text text text text text text text text text text text text text text text
- text text text text text text text text text text text text text text text text
- text text text text text text text text text text text text
- text text
-
diff --git a/apct-tests/perftests/core/res/values/values.xml b/apct-tests/perftests/core/res/values/values.xml
new file mode 100644
index 0000000000000..aad42ba04e110
--- /dev/null
+++ b/apct-tests/perftests/core/res/values/values.xml
@@ -0,0 +1,368 @@
+
+
+
+
+ text text text text text text text text text text text text
+ text text text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text text text
+ text text text text text text text typo text text text text text text text text
+ text text text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text text text
+ text text text text text text text text text text text text
+
+
+ - 1 text
+ - %d texts
+
+
+
+ - Run
+ - the
+ - performance
+ - tests!
+ - Run
+ - the
+ - performance
+ - tests!
+ - Run
+ - the
+ - performance
+ - tests!
+ - Run
+ - the
+ - performance
+ - tests!
+ - Run
+ - the
+ - performance
+ - tests!
+ - Run
+ - the
+ - performance
+ - tests!
+ - Run
+ - the
+ - performance
+ - tests!
+ - Run
+ - the
+ - performance
+ - tests!
+
+
+
+ - 0
+ - 1
+ - 2
+ - 3
+ - 0
+ - 1
+ - 2
+ - 3
+ - 0
+ - 1
+ - 2
+ - 3
+ - 0
+ - 1
+ - 2
+ - 3
+ - 0
+ - 1
+ - 2
+ - 3
+ - 0
+ - 1
+ - 2
+ - 3
+ - 0
+ - 1
+ - 2
+ - 3
+ - 0
+ - 1
+ - 2
+ - 3
+
+
+ #ffffff
+
+ 42
+
+ text text
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+ B
+
diff --git a/apct-tests/perftests/core/src/android/app/OverlayManagerPerfTest.java b/apct-tests/perftests/core/src/android/app/OverlayManagerPerfTest.java
new file mode 100644
index 0000000000000..fcb13a8d51f15
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/app/OverlayManagerPerfTest.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2019 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 android.app;
+
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.content.om.OverlayManager;
+import android.os.UserHandle;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.perftests.utils.TestPackageInstaller;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+
+import com.android.perftests.core.R;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.concurrent.Executor;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Benchmarks for {@link android.content.om.OverlayManager}.
+ */
+@LargeTest
+public class OverlayManagerPerfTest {
+ private static final int OVERLAY_PKG_COUNT = 10;
+ private static Context sContext;
+ private static OverlayManager sOverlayManager;
+ private static Executor sExecutor;
+ private static ArrayList sSmallOverlays =
+ new ArrayList<>();
+ private static ArrayList sLargeOverlays =
+ new ArrayList<>();
+
+ @Rule
+ public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+ @BeforeClass
+ public static void classSetUp() throws Exception {
+ sContext = InstrumentationRegistry.getTargetContext();
+ sOverlayManager = new OverlayManager(sContext);
+ sExecutor = (command) -> new Thread(command).start();
+
+ // Install all of the test overlays.
+ TestPackageInstaller installer = new TestPackageInstaller(sContext);
+ for (int i = 0; i < OVERLAY_PKG_COUNT; i++) {
+ sSmallOverlays.add(installer.installPackage("Overlay" + i +".apk"));
+ sLargeOverlays.add(installer.installPackage("LargeOverlay" + i +".apk"));
+ }
+ }
+
+ @AfterClass
+ public static void classTearDown() throws Exception {
+ for (TestPackageInstaller.InstalledPackage overlay : sSmallOverlays) {
+ overlay.uninstall();
+ }
+
+ for (TestPackageInstaller.InstalledPackage overlay : sLargeOverlays) {
+ overlay.uninstall();
+ }
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ // Disable all test overlays after each test.
+ for (TestPackageInstaller.InstalledPackage overlay : sSmallOverlays) {
+ assertSetEnabled(sContext, overlay.getPackageName(), false);
+ }
+
+ for (TestPackageInstaller.InstalledPackage overlay : sLargeOverlays) {
+ assertSetEnabled(sContext, overlay.getPackageName(), false);
+ }
+ }
+
+ /**
+ * Enables the overlay and waits for the APK path change sto be propagated to the context
+ * AssetManager.
+ */
+ private void assertSetEnabled(Context context, String overlayPackage, boolean eanabled)
+ throws Exception {
+ sOverlayManager.setEnabled(overlayPackage, true, UserHandle.SYSTEM);
+
+ // Wait for the overlay changes to propagate
+ FutureTask task = new FutureTask<>(() -> {
+ while (true) {
+ for (String path : context.getAssets().getApkPaths()) {
+ if (eanabled == path.contains(overlayPackage)) {
+ return true;
+ }
+ }
+ }
+ });
+
+ sExecutor.execute(task);
+ assertTrue("Failed to load overlay " + overlayPackage,
+ task.get(20, TimeUnit.SECONDS));
+ }
+
+ @Test
+ public void setEnabledWarmCache() throws Exception {
+ String packageName = sSmallOverlays.get(0).getPackageName();
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ assertSetEnabled(sContext, packageName, true);
+
+ // Disable the overlay for the next iteration of the test
+ state.pauseTiming();
+ assertSetEnabled(sContext, packageName, false);
+ state.resumeTiming();
+ }
+ }
+
+ @Test
+ public void setEnabledColdCacheSmallOverlay() throws Exception {
+ String packageName = sSmallOverlays.get(0).getPackageName();
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ assertSetEnabled(sContext, packageName, true);
+
+ // Disable the overlay and remove the idmap for the next iteration of the test
+ state.pauseTiming();
+ assertSetEnabled(sContext, packageName, false);
+ sOverlayManager.invalidateCachesForOverlay(packageName, UserHandle.SYSTEM);
+ state.resumeTiming();
+ }
+ }
+
+ @Test
+ public void setEnabledColdCacheLargeOverlay() throws Exception {
+ String packageName = sLargeOverlays.get(0).getPackageName();
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ assertSetEnabled(sContext, packageName, true);
+
+ // Disable the overlay and remove the idmap for the next iteration of the test
+ state.pauseTiming();
+ assertSetEnabled(sContext, packageName, false);
+ sOverlayManager.invalidateCachesForOverlay(packageName, UserHandle.SYSTEM);
+ state.resumeTiming();
+ }
+ }
+
+ @Test
+ public void setEnabledDisable() throws Exception {
+ String packageName = sSmallOverlays.get(0).getPackageName();
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ assertSetEnabled(sContext, packageName, true);
+ state.resumeTiming();
+
+ assertSetEnabled(sContext, packageName, false);
+ }
+ }
+
+ @Test
+ public void getStringOneSmallOverlay() throws Exception {
+ String packageName = sSmallOverlays.get(0).getPackageName();
+ assertSetEnabled(sContext, packageName, true);
+
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ sContext.getString(R.string.short_text);
+ }
+
+ assertSetEnabled(sContext, packageName, false);
+ }
+
+ @Test
+ public void getStringOneLargeOverlay() throws Exception {
+ String packageName = sLargeOverlays.get(0).getPackageName();
+ assertSetEnabled(sContext, packageName, true);
+
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ for (int resId = R.string.short_text000; resId < R.string.short_text255; resId++) {
+ sContext.getString(resId);
+ }
+ }
+
+ assertSetEnabled(sContext, packageName, false);
+ }
+
+ @Test
+ public void getStringTenOverlays() throws Exception {
+ // Enable all test overlays
+ for (TestPackageInstaller.InstalledPackage overlay : sSmallOverlays) {
+ assertSetEnabled(sContext, overlay.getPackageName(), true);
+ }
+
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ sContext.getString(R.string.short_text);
+ }
+ }
+
+ @Test
+ public void getStringLargeTenOverlays() throws Exception {
+ // Enable all test overlays
+ for (TestPackageInstaller.InstalledPackage overlay : sLargeOverlays) {
+ assertSetEnabled(sContext, overlay.getPackageName(), true);
+ }
+
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ for (int resId = R.string.short_text000; resId < R.string.short_text255; resId++) {
+ sContext.getString(resId);
+ }
+ }
+ }
+}
diff --git a/apct-tests/perftests/core/src/android/app/ResourcesManagerPerfTest.java b/apct-tests/perftests/core/src/android/app/ResourcesManagerPerfTest.java
new file mode 100644
index 0000000000000..2955d2ca7d0e6
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/app/ResourcesManagerPerfTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2018 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 android.app;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.view.Display;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Benchmarks for {@link android.app.ResourcesManager}.
+ */
+@LargeTest
+public class ResourcesManagerPerfTest {
+ private static Context sContext;
+ private static File sResourcesCompressed;
+ private static File sResourcesUncompressed;
+
+ @Rule
+ public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ sContext = InstrumentationRegistry.getTargetContext();
+ sResourcesCompressed = copyApkToTemp("LargeResourcesCompressed.apk",
+ "LargeResourcesCompressed.apk");
+ sResourcesUncompressed = copyApkToTemp("LargeResourcesUncompressed.apk",
+ "LargeResourcesUncompressed.apk");
+ }
+
+ @AfterClass
+ public static void tearDown() {
+ Assert.assertTrue(sResourcesCompressed.delete());
+ Assert.assertTrue(sResourcesUncompressed.delete());
+ }
+
+ private static File copyApkToTemp(String inputFileName, String fileName) throws Exception {
+ File file = File.createTempFile(fileName, null, sContext.getCacheDir());
+ try (OutputStream tempOutputStream = new FileOutputStream(file);
+ InputStream is = sContext.getResources().getAssets().openNonAsset(inputFileName)) {
+ byte[] buffer = new byte[4096];
+ int n;
+ while ((n = is.read(buffer)) >= 0) {
+ tempOutputStream.write(buffer, 0, n);
+ }
+ tempOutputStream.flush();
+ }
+ return file;
+ }
+
+ private void getResourcesForPath(String path) {
+ ResourcesManager.getInstance().getResources(null, path, null, null, null,
+ Display.DEFAULT_DISPLAY, null, sContext.getResources().getCompatibilityInfo(),
+ null);
+ }
+
+ @Test
+ public void getResourcesCached() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ getResourcesForPath(sResourcesCompressed.getPath());
+ while (state.keepRunning()) {
+ getResourcesForPath(sResourcesCompressed.getPath());
+ }
+ }
+
+ @Test
+ public void getResourcesCompressedUncached() {
+ ResourcesManager resourcesManager = ResourcesManager.getInstance();
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ resourcesManager.invalidatePath(sResourcesCompressed.getPath());
+ state.resumeTiming();
+
+ getResourcesForPath(sResourcesCompressed.getPath());
+ }
+ }
+
+ @Test
+ public void getResourcesUncompressedUncached() {
+ ResourcesManager resourcesManager = ResourcesManager.getInstance();
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ resourcesManager.invalidatePath(sResourcesUncompressed.getPath());
+ state.resumeTiming();
+
+ getResourcesForPath(sResourcesUncompressed.getPath());
+ }
+ }
+
+ @Test
+ public void applyConfigurationToResourcesLocked() {
+ ResourcesManager resourcesManager = ResourcesManager.getInstance();
+ Configuration c = new Configuration(resourcesManager.getConfiguration());
+ c.uiMode = Configuration.UI_MODE_TYPE_WATCH;
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ resourcesManager.applyConfigurationToResources(c, null);
+
+ // Alternate configurations to ensure the set configuration is different each iteration
+ if (c.uiMode == Configuration.UI_MODE_TYPE_WATCH) {
+ c.uiMode = Configuration.UI_MODE_TYPE_TELEVISION;
+ } else {
+ c.uiMode = Configuration.UI_MODE_TYPE_WATCH;
+ }
+ }
+ }
+}
diff --git a/apct-tests/perftests/core/src/android/app/ResourcesPerfTest.java b/apct-tests/perftests/core/src/android/app/ResourcesPerfTest.java
index c3e43ee074534..72162448a2e06 100644
--- a/apct-tests/perftests/core/src/android/app/ResourcesPerfTest.java
+++ b/apct-tests/perftests/core/src/android/app/ResourcesPerfTest.java
@@ -18,15 +18,18 @@ package android.app;
import static org.junit.Assert.fail;
-import android.content.res.AssetManager;
+import android.content.Context;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
+import android.util.TypedValue;
+import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
-import org.junit.After;
+import com.android.perftests.core.R;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -43,36 +46,123 @@ public class ResourcesPerfTest {
@Rule
public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
- private AssetManager mAsset;
private Resources mRes;
- private int mTextId;
- private int mColorId;
- private int mIntegerId;
- private int mLayoutId;
-
@Before
public void setUp() {
- mAsset = new AssetManager();
- mAsset.addAssetPath("/system/framework/framework-res.apk");
- mRes = new Resources(mAsset, null, null);
-
- mTextId = mRes.getIdentifier("cancel", "string", "android");
- mColorId = mRes.getIdentifier("transparent", "color", "android");
- mIntegerId = mRes.getIdentifier("config_shortAnimTime", "integer", "android");
- mLayoutId = mRes.getIdentifier("two_line_list_item", "layout", "android");
+ Context context = InstrumentationRegistry.getTargetContext();
+ mRes = context.getResources();
}
- @After
- public void tearDown() {
- mAsset.close();
+ @Test
+ public void getValue() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ TypedValue value = new TypedValue();
+ while (state.keepRunning()) {
+ mRes.getValue(R.integer.forty_two, value, false /* resolve_refs */);
+ }
+ }
+
+ @Test
+ public void getFrameworkValue() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ TypedValue value = new TypedValue();
+ while (state.keepRunning()) {
+ mRes.getValue(com.android.internal.R.integer.autofill_max_visible_datasets, value,
+ false /* resolve_refs */);
+ }
+ }
+
+ @Test
+ public void getValueString() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ TypedValue value = new TypedValue();
+ while (state.keepRunning()) {
+ mRes.getValue(R.string.long_text, value, false /* resolve_refs */);
+ }
+ }
+
+ @Test
+ public void getFrameworkStringValue() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ TypedValue value = new TypedValue();
+ while (state.keepRunning()) {
+ mRes.getValue(com.android.internal.R.string.cancel, value, false /* resolve_refs */);
+ }
+ }
+
+ @Test
+ public void getValueManyConfigurations() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ TypedValue value = new TypedValue();
+ while (state.keepRunning()) {
+ mRes.getValue(com.android.internal.R.string.mmcc_illegal_me, value,
+ false /* resolve_refs */);
+ }
}
@Test
public void getText() {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
- mRes.getText(mTextId);
+ mRes.getText(R.string.long_text);
+ }
+ }
+
+
+ @Test
+ public void getFont() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ mRes.getFont(R.font.samplefont);
+ }
+ }
+
+ @Test
+ public void getString() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ mRes.getString(R.string.long_text);
+ }
+ }
+
+ @Test
+ public void getQuantityString() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ mRes.getQuantityString(R.plurals.plurals_text, 5);
+ }
+ }
+
+ @Test
+ public void getQuantityText() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ mRes.getQuantityText(R.plurals.plurals_text, 5);
+ }
+ }
+
+ @Test
+ public void getTextArray() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ mRes.getTextArray(R.array.strings);
+ }
+ }
+
+ @Test
+ public void getStringArray() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ mRes.getStringArray(R.array.strings);
+ }
+ }
+
+ @Test
+ public void getIntegerArray() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ mRes.getIntArray(R.array.ints);
}
}
@@ -80,15 +170,23 @@ public class ResourcesPerfTest {
public void getColor() {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
- mRes.getColor(mColorId, null);
+ mRes.getColor(R.color.white, null);
}
}
@Test
- public void getInteger() {
+ public void getColorStateList() {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
- mRes.getInteger(mIntegerId);
+ mRes.getColorStateList(R.color.color_state_list, null);
+ }
+ }
+
+ @Test
+ public void getVectorDrawable() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ mRes.getDrawable(R.drawable.vector_drawable01, null);
}
}
@@ -96,7 +194,7 @@ public class ResourcesPerfTest {
public void getLayoutAndTravese() {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
- try (XmlResourceParser parser = mRes.getLayout(mLayoutId)) {
+ try (XmlResourceParser parser = mRes.getLayout(R.layout.test_relative_layout)) {
while (parser.next() != XmlPullParser.END_DOCUMENT) {
// Walk the entire tree
}
@@ -105,4 +203,23 @@ public class ResourcesPerfTest {
}
}
}
-}
+
+ @Test
+ public void getLayoutAndTraverseInvalidateCaches() {
+ mRes.flushLayoutCache();
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ try (XmlResourceParser parser = mRes.getLayout(R.layout.test_relative_layout)) {
+ while (parser.next() != XmlPullParser.END_DOCUMENT) {
+ // Walk the entire tree
+ }
+ } catch (IOException | XmlPullParserException exception) {
+ fail("Parsing of the layout failed. Something is really broken");
+ }
+
+ state.pauseTiming();
+ mRes.flushLayoutCache();
+ state.resumeTiming();
+ }
+ }
+}
\ No newline at end of file
diff --git a/apct-tests/perftests/core/src/android/app/ResourcesThemePerfTest.java b/apct-tests/perftests/core/src/android/app/ResourcesThemePerfTest.java
index 1b07572fd3f8c..6123e69b584e9 100644
--- a/apct-tests/perftests/core/src/android/app/ResourcesThemePerfTest.java
+++ b/apct-tests/perftests/core/src/android/app/ResourcesThemePerfTest.java
@@ -16,13 +16,19 @@
package android.app;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
import android.content.res.Resources;
+import android.os.UserHandle;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
+import android.view.Display;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -35,13 +41,69 @@ public class ResourcesThemePerfTest {
@Rule
public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+ private Context mContext;
+ private int mThemeResId;
private Resources.Theme mTheme;
@Before
- public void setUp() {
- Context context = InstrumentationRegistry.getTargetContext();
- mTheme = context.getTheme();
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getTargetContext();
+ mThemeResId = com.android.perftests.core.R.style.Base_V7_Theme_AppCompat;
+ mTheme = mContext.getResources().newTheme();
+ mTheme.applyStyle(mThemeResId, true /* force */);
+ }
+ @Test
+ public void applyStyle() {
+ Resources.Theme destTheme = mContext.getResources().newTheme();
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ destTheme.applyStyle(mThemeResId, true /* force */);
+ }
+ }
+
+ @Test
+ public void rebase() {
+ Resources.Theme destTheme = mContext.getResources().newTheme();
+ destTheme.applyStyle(mThemeResId, true /* force */);
+ destTheme.applyStyle(android.R.style.Theme_Material, true /* force */);
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ destTheme.rebase();
+ }
+ }
+
+ @Test
+ public void setToSameAssetManager() {
+ Resources.Theme destTheme = mContext.getResources().newTheme();
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ destTheme.setTo(mTheme);
+ }
+ }
+
+ @Test
+ public void setToDifferentAssetManager() throws Exception {
+ // Create a new Resources object with the same asset paths but a different AssetManager
+ PackageManager packageManager = mContext.getApplicationContext().getPackageManager();
+ ApplicationInfo ai = packageManager.getApplicationInfo(mContext.getPackageName(),
+ UserHandle.myUserId());
+
+ ResourcesManager resourcesManager = ResourcesManager.getInstance();
+ Configuration c = resourcesManager.getConfiguration();
+ c.orientation = (c.orientation == Configuration.ORIENTATION_PORTRAIT)
+ ? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT;
+
+ Resources destResources = resourcesManager.getResources(null, ai.sourceDir,
+ ai.splitSourceDirs, ai.resourceDirs, ai.sharedLibraryFiles, Display.DEFAULT_DISPLAY,
+ c, mContext.getResources().getCompatibilityInfo(), null);
+ Assert.assertNotEquals(destResources.getAssets(), mContext.getAssets());
+
+ Resources.Theme destTheme = destResources.newTheme();
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ destTheme.setTo(mTheme);
+ }
}
@Test
@@ -51,5 +113,4 @@ public class ResourcesThemePerfTest {
mTheme.obtainStyledAttributes(android.R.style.Theme_Material, android.R.styleable.View);
}
}
-
-}
+}
\ No newline at end of file
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/TestPackageInstaller.java b/apct-tests/perftests/utils/src/android/perftests/utils/TestPackageInstaller.java
new file mode 100644
index 0000000000000..a433d801acaf6
--- /dev/null
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/TestPackageInstaller.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2019 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 android.perftests.utils;
+
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.IntentSender;
+import android.content.pm.PackageInstaller;
+import android.content.res.Resources;
+import android.util.Log;
+
+import org.junit.Assert;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+/**
+ * Installs packages included within the assets directory.
+ */
+public class TestPackageInstaller {
+ private static final String LOG_TAG = "TestPackageInstaller";
+ private static final String BROADCAST_ACTION =
+ "com.android.perftests.core.ACTION_INSTALL_COMMIT";
+
+ private final Context mContext;
+ public TestPackageInstaller(Context context) {
+ mContext = context;
+ }
+
+
+
+ /**
+ * Installs an APK located at the specified path in the assets directory.
+ **/
+ public InstalledPackage installPackage(String resourceName) throws IOException,
+ InterruptedException {
+ Log.d(LOG_TAG, "Installing resource APK '" + resourceName + "'");
+ LocalBroadcastReceiver intentSender = new LocalBroadcastReceiver(mContext);
+
+ // Initialize the package install session.
+ PackageInstaller packageInstaller = mContext.getPackageManager().getPackageInstaller();
+ PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
+ PackageInstaller.SessionParams.MODE_FULL_INSTALL);
+ params.setInstallAsInstantApp(false);
+ int sessionId = packageInstaller.createSession(params);
+ PackageInstaller.Session session = packageInstaller.openSession(sessionId);
+
+ // Copy the apk to the install session.
+ try (OutputStream os = session.openWrite("TestPackageInstaller", 0, -1);
+ InputStream is = mContext.getResources().getAssets().openNonAsset(resourceName)) {
+ if (is == null) {
+ throw new IOException("Resource " + resourceName + " not found");
+ }
+ byte[] buffer = new byte[4096];
+ int n;
+ while ((n = is.read(buffer)) >= 0) {
+ os.write(buffer, 0, n);
+ }
+ }
+
+ session.commit(intentSender.getIntentSender(sessionId));
+ session.close();
+
+ // Retrieve the results of the installation.
+ Intent intent = intentSender.getIntentSenderResult();
+ int status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS,
+ PackageInstaller.STATUS_FAILURE);
+ Assert.assertEquals(PackageInstaller.STATUS_SUCCESS, status);
+ String packageName = intent.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME);
+ return new InstalledPackage(sessionId, packageName);
+ }
+
+ public class InstalledPackage {
+ private int mSessionId;
+ private String mPackageName;
+
+ private InstalledPackage(int sessionId, String packageName) {
+ mSessionId = sessionId;
+ mPackageName = packageName;
+ }
+
+ public String getPackageName() {
+ return mPackageName;
+ }
+
+ public void uninstall() throws Exception {
+ Log.d(LOG_TAG, "Uninstalling package '" + mPackageName + "'");
+ LocalBroadcastReceiver intentSender = new LocalBroadcastReceiver(mContext);
+ PackageInstaller packageInstaller = mContext.getPackageManager().getPackageInstaller();
+ packageInstaller.uninstall(mPackageName, intentSender.getIntentSender(mSessionId));
+ int status = intentSender.getIntentSenderResult()
+ .getIntExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE);
+ Assert.assertEquals(PackageInstaller.STATUS_SUCCESS, status);
+ }
+ }
+
+ private class LocalBroadcastReceiver extends BroadcastReceiver {
+ private final BlockingQueue mIntentSenderResults = new LinkedBlockingQueue<>();
+ private final Context mContext;
+
+ private LocalBroadcastReceiver(Context context) {
+ mContext = context;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mIntentSenderResults.add(intent);
+ }
+
+ IntentSender getIntentSender(int sessionId) {
+ String action = BROADCAST_ACTION + "." + sessionId;
+ IntentFilter filter = new IntentFilter(action);
+ mContext.registerReceiver(this, filter);
+
+ Intent intent = new Intent(action);
+ PendingIntent pending = PendingIntent.getBroadcast(mContext, sessionId, intent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+ return pending.getIntentSender();
+ }
+
+ Intent getIntentSenderResult() throws InterruptedException {
+ return mIntentSenderResults.take();
+ }
+ }
+}
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 40cb29fc80ab2..cb9ebac728ecd 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -20,6 +20,7 @@ import static android.app.ActivityThread.DEBUG_CONFIGURATION;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
@@ -191,6 +192,17 @@ public class ResourcesManager {
}
}
Log.i(TAG, "Invalidated " + count + " asset managers that referenced " + path);
+
+ for (int i = mCachedApkAssets.size() - 1; i >= 0; i--) {
+ final ApkKey key = mCachedApkAssets.keyAt(i);
+ if (key.path.equals(path)) {
+ WeakReference apkAssetsRef = mCachedApkAssets.remove(key);
+ if (apkAssetsRef != null && apkAssetsRef.get() != null) {
+ apkAssetsRef.get().close();
+ }
+ mCachedApkAssets.remove(key);
+ }
+ }
}
}
@@ -1000,6 +1012,14 @@ public class ResourcesManager {
}
}
+ @TestApi
+ public final boolean applyConfigurationToResources(@NonNull Configuration config,
+ @Nullable CompatibilityInfo compat) {
+ synchronized(this) {
+ return applyConfigurationToResourcesLocked(config, compat);
+ }
+ }
+
public final boolean applyConfigurationToResourcesLocked(@NonNull Configuration config,
@Nullable CompatibilityInfo compat) {
try {
diff --git a/core/java/android/content/om/IOverlayManager.aidl b/core/java/android/content/om/IOverlayManager.aidl
index 43a4fe5bc4142..3d7e3befd9f19 100644
--- a/core/java/android/content/om/IOverlayManager.aidl
+++ b/core/java/android/content/om/IOverlayManager.aidl
@@ -157,4 +157,10 @@ interface IOverlayManager {
* Returns the list of default overlay packages, or an empty array if there are none.
*/
String[] getDefaultOverlayPackages();
+
+ /**
+ * Invalidates and removes the idmap for an overlay,
+ * @param packageName The name of the overlay package whose idmap should be deleted.
+ */
+ void invalidateCachesForOverlay(in String packageName, in int userIs);
}
diff --git a/core/java/android/content/om/OverlayManager.java b/core/java/android/content/om/OverlayManager.java
index f2716fedc1861..853e8189ea8a7 100644
--- a/core/java/android/content/om/OverlayManager.java
+++ b/core/java/android/content/om/OverlayManager.java
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -163,4 +164,28 @@ public class OverlayManager {
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Returns information about all overlays for the given target package for
+ * the specified user. The returned list is ordered according to the
+ * overlay priority with the highest priority at the end of the list.
+ *
+ * @param targetPackageName The name of the target package.
+ * @param user The user to get the OverlayInfos for.
+ *
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(anyOf = {
+ "android.permission.INTERACT_ACROSS_USERS",
+ })
+ @NonNull
+ public void invalidateCachesForOverlay(@NonNull final String targetPackageName,
+ @NonNull UserHandle user) {
+ try {
+ mService.invalidateCachesForOverlay(targetPackageName, user.getIdentifier());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/content/res/ApkAssets.java b/core/java/android/content/res/ApkAssets.java
index 69462ab994832..a35ad567ed81a 100644
--- a/core/java/android/content/res/ApkAssets.java
+++ b/core/java/android/content/res/ApkAssets.java
@@ -188,7 +188,7 @@ public final class ApkAssets {
/**
* Closes this class and the contained {@link #mStringBlock}.
*/
- public void close() throws Throwable {
+ public void close() {
synchronized (this) {
if (mOpen) {
mOpen = false;
diff --git a/core/java/android/content/res/StringBlock.java b/core/java/android/content/res/StringBlock.java
index b7bc8229fa450..2ae1932c34376 100644
--- a/core/java/android/content/res/StringBlock.java
+++ b/core/java/android/content/res/StringBlock.java
@@ -175,7 +175,7 @@ final class StringBlock {
}
}
- public void close() throws Throwable {
+ public void close() {
synchronized (this) {
if (mOpen) {
mOpen = false;
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 83bea9dd1efce..9e7b46485d4ce 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -737,6 +737,25 @@ public final class OverlayManagerService extends SystemService {
}
}
+ @Override
+ public void invalidateCachesForOverlay(@Nullable String packageName, int userId)
+ throws RemoteException {
+ if (packageName == null) {
+ return;
+ }
+
+ enforceChangeOverlayPackagesPermission("invalidateCachesForOverlay");
+ userId = handleIncomingUser(userId, "invalidateCachesForOverlay");
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ mImpl.removeIdmapForOverlay(packageName, userId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
@Override
public void onShellCommand(@NonNull final FileDescriptor in,
@NonNull final FileDescriptor out, @NonNull final FileDescriptor err,
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index 934511bf88d15..019c9528f8abc 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -651,6 +651,11 @@ final class OverlayManagerServiceImpl {
return mDefaultOverlays;
}
+ void removeIdmapForOverlay(String packageName, int userId) {
+ final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
+ removeIdmapIfPossible(oi);
+ }
+
List getEnabledOverlayPackageNames(@NonNull final String targetPackageName,
final int userId) {
final List overlays = mSettings.getOverlaysForTarget(targetPackageName,