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,