diff options
author | Ryan Mitchell <rtmitchell@google.com> | 2020-04-10 15:53:05 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2020-04-10 15:53:05 +0000 |
commit | cca1593b23235f6491203506088e23fee84283e7 (patch) | |
tree | 23170fb1330dd74027bcb60b76602fef8660238f | |
parent | 32bb3440b49ceb7e380e3c34590e8fa80083deb3 (diff) | |
parent | 6cb79cdfb777e817c29e574aed1f2711996b578c (diff) |
Merge changes from topic "invalidate_idmap" into rvc-dev am: 6cb79cdfb7
Change-Id: Iec3d0e3bab28964442c5aada00c2586e284feb92
38 files changed, 429 insertions, 119 deletions
diff --git a/cmds/idmap2/TEST_MAPPING b/cmds/idmap2/TEST_MAPPING index 26ccf038cba2..9e0fb84c7949 100644 --- a/cmds/idmap2/TEST_MAPPING +++ b/cmds/idmap2/TEST_MAPPING @@ -3,5 +3,10 @@ { "name" : "idmap2_tests" } + ], + "imports": [ + { + "path": "frameworks/base/services/core/java/com/android/server/om" + } ] } diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp index 9cae926d56d7..b8f1a1c0ee72 100644 --- a/cmds/idmap2/idmap2d/Idmap2Service.cpp +++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp @@ -149,15 +149,21 @@ Status Idmap2Service::createIdmap(const std::string& target_apk_path, return error(idmap.GetErrorMessage()); } + // idmap files are mapped with mmap in libandroidfw. Deleting and recreating the idmap guarantees + // that existing memory maps will continue to be valid and unaffected. + unlink(idmap_path.c_str()); + umask(kIdmapFilePermissionMask); std::ofstream fout(idmap_path); if (fout.fail()) { return error("failed to open idmap path " + idmap_path); } + BinaryStreamVisitor visitor(fout); (*idmap)->accept(&visitor); fout.close(); if (fout.fail()) { + unlink(idmap_path.c_str()); return error("failed to write to idmap path " + idmap_path); } diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java index d2e848b9562a..47ccc2f0badb 100644 --- a/core/java/android/app/ResourcesManager.java +++ b/core/java/android/app/ResourcesManager.java @@ -344,7 +344,7 @@ public class ResourcesManager { ApkAssets apkAssets = null; if (mLoadedApkAssets != null) { apkAssets = mLoadedApkAssets.get(newKey); - if (apkAssets != null) { + if (apkAssets != null && apkAssets.isUpToDate()) { return apkAssets; } } @@ -353,7 +353,7 @@ public class ResourcesManager { final WeakReference<ApkAssets> apkAssetsRef = mCachedApkAssets.get(newKey); if (apkAssetsRef != null) { apkAssets = apkAssetsRef.get(); - if (apkAssets != null) { + if (apkAssets != null && apkAssets.isUpToDate()) { if (mLoadedApkAssets != null) { mLoadedApkAssets.put(newKey, apkAssets); } diff --git a/core/tests/overlaytests/host/Android.bp b/core/tests/overlaytests/host/Android.bp index a2fcef56b780..2b38cca2db36 100644 --- a/core/tests/overlaytests/host/Android.bp +++ b/core/tests/overlaytests/host/Android.bp @@ -16,7 +16,7 @@ java_test_host { name: "OverlayHostTests", srcs: ["src/**/*.java"], libs: ["tradefed"], - test_suites: ["general-tests"], + test_suites: ["device-tests"], target_required: [ "OverlayHostTests_NonPlatformSignatureOverlay", "OverlayHostTests_PlatformSignatureStaticOverlay", diff --git a/core/tests/overlaytests/host/src/com/android/server/om/hosttest/InstallOverlayTests.java b/core/tests/overlaytests/host/src/com/android/server/om/hosttest/InstallOverlayTests.java index eec7be22c78b..d898d222b8de 100644 --- a/core/tests/overlaytests/host/src/com/android/server/om/hosttest/InstallOverlayTests.java +++ b/core/tests/overlaytests/host/src/com/android/server/om/hosttest/InstallOverlayTests.java @@ -78,14 +78,9 @@ public class InstallOverlayTests extends BaseHostJUnit4Test { } @Test - public void failToInstallPlatformSignedStaticOverlay() throws Exception { - try { - installPackage("OverlayHostTests_PlatformSignatureStaticOverlay.apk"); - fail("installed a static overlay"); - } catch (Exception e) { - // Expected. - } - assertFalse(overlayManagerContainsPackage(SIG_OVERLAY_PACKAGE_NAME)); + public void installedIsStaticOverlayIsMutable() throws Exception { + installPackage("OverlayHostTests_PlatformSignatureStaticOverlay.apk"); + assertTrue(isOverlayMutable(SIG_OVERLAY_PACKAGE_NAME)); } @Test @@ -229,6 +224,10 @@ public class InstallOverlayTests extends BaseHostJUnit4Test { return shell("cmd overlay list").contains(pkg); } + private boolean isOverlayMutable(String pkg) throws Exception { + return shell("cmd overlay dump ismutable " + pkg).contains("true"); + } + private String shell(final String cmd) throws Exception { return getDevice().executeShellCommand(cmd); } diff --git a/core/tests/overlaytests/host/test-apps/SignatureOverlay/Android.mk b/core/tests/overlaytests/host/test-apps/SignatureOverlay/Android.mk index cc7704b0ce98..f3c0abd8293f 100644 --- a/core/tests/overlaytests/host/test-apps/SignatureOverlay/Android.mk +++ b/core/tests/overlaytests/host/test-apps/SignatureOverlay/Android.mk @@ -20,7 +20,7 @@ include $(CLEAR_VARS) LOCAL_MODULE_TAGS := tests LOCAL_PACKAGE_NAME := OverlayHostTests_NonPlatformSignatureOverlay LOCAL_SDK_VERSION := current -LOCAL_COMPATIBILITY_SUITE := general-tests +LOCAL_COMPATIBILITY_SUITE := device-tests LOCAL_AAPT_FLAGS := --custom-package $(my_package_prefix)_bad include $(BUILD_PACKAGE) @@ -28,7 +28,8 @@ include $(CLEAR_VARS) LOCAL_MODULE_TAGS := tests LOCAL_PACKAGE_NAME := OverlayHostTests_PlatformSignatureStaticOverlay LOCAL_SDK_VERSION := current -LOCAL_COMPATIBILITY_SUITE := general-tests +LOCAL_COMPATIBILITY_SUITE := device-tests +LOCAL_CERTIFICATE := platform LOCAL_MANIFEST_FILE := static/AndroidManifest.xml LOCAL_AAPT_FLAGS := --custom-package $(my_package_prefix)_static include $(BUILD_PACKAGE) @@ -37,7 +38,7 @@ include $(CLEAR_VARS) LOCAL_MODULE_TAGS := tests LOCAL_PACKAGE_NAME := OverlayHostTests_PlatformSignatureOverlay LOCAL_SDK_VERSION := current -LOCAL_COMPATIBILITY_SUITE := general-tests +LOCAL_COMPATIBILITY_SUITE := device-tests LOCAL_CERTIFICATE := platform LOCAL_AAPT_FLAGS := --custom-package $(my_package_prefix)_v1 LOCAL_AAPT_FLAGS += --version-code 1 --version-name v1 diff --git a/core/tests/overlaytests/host/test-apps/UpdateOverlay/Android.mk b/core/tests/overlaytests/host/test-apps/UpdateOverlay/Android.mk index f8607f44bda6..878f05d57662 100644 --- a/core/tests/overlaytests/host/test-apps/UpdateOverlay/Android.mk +++ b/core/tests/overlaytests/host/test-apps/UpdateOverlay/Android.mk @@ -19,7 +19,7 @@ LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := $(call all-java-files-under,src) LOCAL_PACKAGE_NAME := OverlayHostTests_UpdateOverlay LOCAL_SDK_VERSION := current -LOCAL_COMPATIBILITY_SUITE := general-tests +LOCAL_COMPATIBILITY_SUITE := device-tests LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules LOCAL_USE_AAPT2 := true LOCAL_AAPT_FLAGS := --no-resource-removal @@ -31,7 +31,7 @@ include $(CLEAR_VARS) LOCAL_MODULE_TAGS := tests LOCAL_PACKAGE_NAME := OverlayHostTests_FrameworkOverlayV1 LOCAL_SDK_VERSION := current -LOCAL_COMPATIBILITY_SUITE := general-tests +LOCAL_COMPATIBILITY_SUITE := device-tests LOCAL_CERTIFICATE := platform LOCAL_AAPT_FLAGS := --custom-package $(my_package_prefix)_v1 LOCAL_AAPT_FLAGS += --version-code 1 --version-name v1 @@ -43,7 +43,7 @@ include $(CLEAR_VARS) LOCAL_MODULE_TAGS := tests LOCAL_PACKAGE_NAME := OverlayHostTests_FrameworkOverlayV2 LOCAL_SDK_VERSION := current -LOCAL_COMPATIBILITY_SUITE := general-tests +LOCAL_COMPATIBILITY_SUITE := device-tests LOCAL_CERTIFICATE := platform LOCAL_AAPT_FLAGS := --custom-package $(my_package_prefix)_v2 LOCAL_AAPT_FLAGS += --version-code 2 --version-name v2 @@ -57,7 +57,7 @@ include $(CLEAR_VARS) LOCAL_MODULE_TAGS := tests LOCAL_PACKAGE_NAME := OverlayHostTests_AppOverlayV1 LOCAL_SDK_VERSION := current -LOCAL_COMPATIBILITY_SUITE := general-tests +LOCAL_COMPATIBILITY_SUITE := device-tests LOCAL_AAPT_FLAGS := --custom-package $(my_package_prefix)_v1 LOCAL_AAPT_FLAGS += --version-code 1 --version-name v1 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/app/v1/res @@ -68,7 +68,7 @@ include $(CLEAR_VARS) LOCAL_MODULE_TAGS := tests LOCAL_PACKAGE_NAME := OverlayHostTests_AppOverlayV2 LOCAL_SDK_VERSION := current -LOCAL_COMPATIBILITY_SUITE := general-tests +LOCAL_COMPATIBILITY_SUITE := device-tests LOCAL_AAPT_FLAGS := --custom-package $(my_package_prefix)_v2 LOCAL_AAPT_FLAGS += --version-code 2 --version-name v2 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/app/v2/res diff --git a/core/tests/overlaytests/remount/host/Android.bp b/core/tests/overlaytests/remount/Android.bp index 3825c55f3b4b..9baedf81d6e0 100644 --- a/core/tests/overlaytests/remount/host/Android.bp +++ b/core/tests/overlaytests/remount/Android.bp @@ -24,5 +24,7 @@ java_test_host { ":OverlayRemountedTest_SharedLibrary", ":OverlayRemountedTest_SharedLibraryOverlay", ":OverlayRemountedTest_Target", + ":OverlayRemountedTest_TargetUpgrade", + ":OverlayRemountedTest_Overlay", ], } diff --git a/core/tests/overlaytests/remount/host/AndroidTest.xml b/core/tests/overlaytests/remount/AndroidTest.xml index 087b7313693d..087b7313693d 100644 --- a/core/tests/overlaytests/remount/host/AndroidTest.xml +++ b/core/tests/overlaytests/remount/AndroidTest.xml diff --git a/core/tests/overlaytests/remount/src/com/android/overlaytest/remounted/OverlayRemountedTestBase.java b/core/tests/overlaytests/remount/src/com/android/overlaytest/remounted/OverlayRemountedTestBase.java new file mode 100644 index 000000000000..00a53c45d797 --- /dev/null +++ b/core/tests/overlaytests/remount/src/com/android/overlaytest/remounted/OverlayRemountedTestBase.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.overlaytest.remounted; + +import static org.junit.Assert.fail; + +import com.android.tradefed.device.DeviceNotAvailableException; +import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.rules.RuleChain; +import org.junit.rules.TemporaryFolder; + +public class OverlayRemountedTestBase extends BaseHostJUnit4Test { + static final long ASSERT_RESOURCE_TIMEOUT_MS = 30000; + + static final String TARGET_APK = "OverlayRemountedTest_Target.apk"; + static final String TARGET_PACKAGE = "com.android.overlaytest.remounted.target"; + static final String TARGET_UPGRADE_APK = "OverlayRemountedTest_TargetUpgrade.apk"; + static final String OVERLAY_APK = "OverlayRemountedTest_Overlay.apk"; + static final String OVERLAY_PACKAGE = "com.android.overlaytest.remounted.target.overlay"; + static final String SHARED_LIBRARY_APK = + "OverlayRemountedTest_SharedLibrary.apk"; + static final String SHARED_LIBRARY_PACKAGE = + "com.android.overlaytest.remounted.shared_library"; + static final String SHARED_LIBRARY_OVERLAY_APK = + "OverlayRemountedTest_SharedLibraryOverlay.apk"; + static final String SHARED_LIBRARY_OVERLAY_PACKAGE = + "com.android.overlaytest.remounted.shared_library.overlay"; + + private final TemporaryFolder mTemporaryFolder = new TemporaryFolder(); + protected final SystemPreparer mPreparer = new SystemPreparer(mTemporaryFolder, + this::getDevice); + + @Rule + public final RuleChain ruleChain = RuleChain.outerRule(mTemporaryFolder).around(mPreparer); + + @Before + public void startBefore() throws DeviceNotAvailableException { + getDevice().waitForDeviceAvailable(); + } + + /** Builds the full name of a resource in the form package:type/entry. */ + String resourceName(String pkg, String type, String entry) { + return String.format("%s:%s/%s", pkg, type, entry); + } + + void assertResource(String resourceName, String expectedValue) + throws DeviceNotAvailableException { + String result = null; + + final long endMillis = System.currentTimeMillis() + ASSERT_RESOURCE_TIMEOUT_MS; + while (System.currentTimeMillis() <= endMillis) { + result = getDevice().executeShellCommand( + String.format("cmd overlay lookup %s %s", TARGET_PACKAGE, resourceName)); + if (result.equals(expectedValue + "\n") || + result.endsWith("-> " + expectedValue + "\n")) { + return; + } + + try { + Thread.sleep(200); + } catch (InterruptedException ignore) { + } + } + + fail(String.format("expected: <[%s]> in: <[%s]>", expectedValue, result)); + } +} diff --git a/core/tests/overlaytests/remount/host/src/com/android/overlaytest/remounted/OverlaySharedLibraryTest.java b/core/tests/overlaytests/remount/src/com/android/overlaytest/remounted/OverlaySharedLibraryTest.java index 06b2ac8f9e22..49d1894c9bae 100644 --- a/core/tests/overlaytests/remount/host/src/com/android/overlaytest/remounted/OverlaySharedLibraryTest.java +++ b/core/tests/overlaytests/remount/src/com/android/overlaytest/remounted/OverlaySharedLibraryTest.java @@ -16,42 +16,13 @@ package com.android.overlaytest.remounted; -import static org.junit.Assert.assertTrue; - -import com.android.tradefed.device.DeviceNotAvailableException; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; -import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; -import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; @RunWith(DeviceJUnit4ClassRunner.class) -public class OverlaySharedLibraryTest extends BaseHostJUnit4Test { - private static final String TARGET_APK = "OverlayRemountedTest_Target.apk"; - private static final String TARGET_PACKAGE = "com.android.overlaytest.remounted.target"; - private static final String SHARED_LIBRARY_APK = - "OverlayRemountedTest_SharedLibrary.apk"; - private static final String SHARED_LIBRARY_PACKAGE = - "com.android.overlaytest.remounted.shared_library"; - private static final String SHARED_LIBRARY_OVERLAY_APK = - "OverlayRemountedTest_SharedLibraryOverlay.apk"; - private static final String SHARED_LIBRARY_OVERLAY_PACKAGE = - "com.android.overlaytest.remounted.shared_library.overlay"; - - public final TemporaryFolder temporaryFolder = new TemporaryFolder(); - public final SystemPreparer preparer = new SystemPreparer(temporaryFolder, this::getDevice); - - @Rule - public final RuleChain ruleChain = RuleChain.outerRule(temporaryFolder).around(preparer); - - @Before - public void startBefore() throws DeviceNotAvailableException { - getDevice().waitForDeviceAvailable(); - } +public class OverlaySharedLibraryTest extends OverlayRemountedTestBase { @Test public void testSharedLibrary() throws Exception { @@ -60,7 +31,7 @@ public class OverlaySharedLibraryTest extends BaseHostJUnit4Test { final String libraryResource = resourceName(SHARED_LIBRARY_PACKAGE, "bool", "shared_library_overlaid"); - preparer.pushResourceFile(SHARED_LIBRARY_APK, "/product/app/SharedLibrary.apk") + mPreparer.pushResourceFile(SHARED_LIBRARY_APK, "/product/app/SharedLibrary.apk") .installResourceApk(SHARED_LIBRARY_OVERLAY_APK, SHARED_LIBRARY_OVERLAY_PACKAGE) .reboot() .setOverlayEnabled(SHARED_LIBRARY_OVERLAY_PACKAGE, false) @@ -71,7 +42,7 @@ public class OverlaySharedLibraryTest extends BaseHostJUnit4Test { assertResource(libraryResource, "false"); // Overlay the shared library resource. - preparer.setOverlayEnabled(SHARED_LIBRARY_OVERLAY_PACKAGE, true); + mPreparer.setOverlayEnabled(SHARED_LIBRARY_OVERLAY_PACKAGE, true); assertResource(targetResource, "true"); assertResource(libraryResource, "true"); } @@ -83,7 +54,7 @@ public class OverlaySharedLibraryTest extends BaseHostJUnit4Test { final String libraryResource = resourceName(SHARED_LIBRARY_PACKAGE, "bool", "shared_library_overlaid"); - preparer.pushResourceFile(SHARED_LIBRARY_APK, "/product/app/SharedLibrary.apk") + mPreparer.pushResourceFile(SHARED_LIBRARY_APK, "/product/app/SharedLibrary.apk") .installResourceApk(SHARED_LIBRARY_OVERLAY_APK, SHARED_LIBRARY_OVERLAY_PACKAGE) .setOverlayEnabled(SHARED_LIBRARY_OVERLAY_PACKAGE, true) .reboot() @@ -92,18 +63,4 @@ public class OverlaySharedLibraryTest extends BaseHostJUnit4Test { assertResource(targetResource, "true"); assertResource(libraryResource, "true"); } - - /** Builds the full name of a resource in the form package:type/entry. */ - String resourceName(String pkg, String type, String entry) { - return String.format("%s:%s/%s", pkg, type, entry); - } - - void assertResource(String resourceName, String expectedValue) - throws DeviceNotAvailableException { - final String result = getDevice().executeShellCommand( - String.format("cmd overlay lookup %s %s", TARGET_PACKAGE, resourceName)); - assertTrue(String.format("expected: <[%s]> in: <[%s]>", expectedValue, result), - result.equals(expectedValue + "\n") || - result.endsWith("-> " + expectedValue + "\n")); - } } diff --git a/core/tests/overlaytests/remount/src/com/android/overlaytest/remounted/PackagedUpgradedTest.java b/core/tests/overlaytests/remount/src/com/android/overlaytest/remounted/PackagedUpgradedTest.java new file mode 100644 index 000000000000..f685ec1580ad --- /dev/null +++ b/core/tests/overlaytests/remount/src/com/android/overlaytest/remounted/PackagedUpgradedTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.overlaytest.remounted; + +import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(DeviceJUnit4ClassRunner.class) +public class PackagedUpgradedTest extends OverlayRemountedTestBase { + + @Test + public void testTargetUpgrade() throws Exception { + final String targetOverlaid = resourceName(TARGET_PACKAGE, "bool", "target_overlaid"); + final String targetReference = resourceName(TARGET_PACKAGE, "bool", "target_reference"); + + mPreparer.pushResourceFile(TARGET_APK, "/product/app/OverlayTarget.apk") + .reboot() + .installResourceApk(OVERLAY_APK, OVERLAY_PACKAGE) + .setOverlayEnabled(OVERLAY_PACKAGE, true); + + assertResource(targetReference, "@" + 0x7f010000 + " -> true"); + assertResource(targetOverlaid, "true"); + + mPreparer.installResourceApk(TARGET_UPGRADE_APK, TARGET_PACKAGE); + + assertResource(targetReference, "@" + 0x7f0100ff + " -> true"); + assertResource(targetOverlaid, "true"); + } + + @Test + public void testTargetRelocated() throws Exception { + final String targetOverlaid = resourceName(TARGET_PACKAGE, "bool", "target_overlaid"); + final String originalPath = "/product/app/OverlayTarget.apk"; + + mPreparer.pushResourceFile(TARGET_APK, originalPath) + .reboot() + .installResourceApk(OVERLAY_APK, OVERLAY_PACKAGE) + .setOverlayEnabled(OVERLAY_PACKAGE, true); + + assertResource(targetOverlaid, "true"); + + mPreparer.remount(); + getDevice().deleteFile(originalPath); + mPreparer.pushResourceFile(TARGET_UPGRADE_APK, "/product/app/OverlayTarget2.apk") + .reboot(); + + assertResource(targetOverlaid, "true"); + } +} diff --git a/core/tests/overlaytests/remount/host/src/com/android/overlaytest/remounted/SystemPreparer.java b/core/tests/overlaytests/remount/src/com/android/overlaytest/remounted/SystemPreparer.java index 8696091239c2..b45b8eabf7c0 100644 --- a/core/tests/overlaytests/remount/host/src/com/android/overlaytest/remounted/SystemPreparer.java +++ b/core/tests/overlaytests/remount/src/com/android/overlaytest/remounted/SystemPreparer.java @@ -18,8 +18,6 @@ package com.android.overlaytest.remounted; import static org.junit.Assert.assertTrue; -import static java.util.concurrent.TimeUnit.MILLISECONDS; - import com.android.tradefed.device.DeviceNotAvailableException; import com.android.tradefed.device.ITestDevice; @@ -32,10 +30,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executor; -import java.util.concurrent.FutureTask; -import java.util.concurrent.TimeoutException; class SystemPreparer extends ExternalResource { private static final long OVERLAY_ENABLE_TIMEOUT_MS = 30000; @@ -58,7 +52,7 @@ class SystemPreparer extends ExternalResource { SystemPreparer pushResourceFile(String resourcePath, String outputPath) throws DeviceNotAvailableException, IOException { final ITestDevice device = mDeviceProvider.getDevice(); - device.executeAdbCommand("remount"); + remount(); assertTrue(device.pushFile(copyResourceToTemp(resourcePath), outputPath)); mPushedFiles.add(outputPath); return this; @@ -69,7 +63,7 @@ class SystemPreparer extends ExternalResource { throws DeviceNotAvailableException, IOException { final ITestDevice device = mDeviceProvider.getDevice(); final File tmpFile = copyResourceToTemp(resourcePath); - final String result = device.installPackage(tmpFile, true); + final String result = device.installPackage(tmpFile, true /* reinstall */); Assert.assertNull(result); mInstalledPackages.add(packageName); return this; @@ -77,34 +71,29 @@ class SystemPreparer extends ExternalResource { /** Sets the enable state of an overlay pacakage. */ SystemPreparer setOverlayEnabled(String packageName, boolean enabled) - throws ExecutionException, DeviceNotAvailableException { + throws DeviceNotAvailableException { final ITestDevice device = mDeviceProvider.getDevice(); + final String enable = enabled ? "enable" : "disable"; // Wait for the overlay to change its enabled state. - final FutureTask<Boolean> enabledListener = new FutureTask<>(() -> { - while (true) { - device.executeShellCommand(String.format("cmd overlay %s %s", - enabled ? "enable" : "disable", packageName)); - - final String result = device.executeShellCommand("cmd overlay dump " + packageName); - final int startIndex = result.indexOf("mIsEnabled"); - final int endIndex = result.indexOf('\n', startIndex); - if (result.substring(startIndex, endIndex).contains((enabled) ? "true" : "false")) { - return true; - } + final long endMillis = System.currentTimeMillis() + OVERLAY_ENABLE_TIMEOUT_MS; + String result; + while (System.currentTimeMillis() <= endMillis) { + device.executeShellCommand(String.format("cmd overlay %s %s", enable, packageName)); + result = device.executeShellCommand("cmd overlay dump isenabled " + + packageName); + if (((enabled) ? "true\n" : "false\n").equals(result)) { + return this; } - }); - final Executor executor = (cmd) -> new Thread(cmd).start(); - executor.execute(enabledListener); - try { - enabledListener.get(OVERLAY_ENABLE_TIMEOUT_MS, MILLISECONDS); - } catch (InterruptedException ignored) { - } catch (TimeoutException e) { - throw new IllegalStateException(device.executeShellCommand("cmd overlay list")); + try { + Thread.sleep(200); + } catch (InterruptedException ignore) { + } } - return this; + throw new IllegalStateException(String.format("Failed to %s overlay %s:\n%s", enable, + packageName, device.executeShellCommand("cmd overlay list"))); } /** Restarts the device and waits until after boot is completed. */ @@ -114,6 +103,11 @@ class SystemPreparer extends ExternalResource { return this; } + SystemPreparer remount() throws DeviceNotAvailableException { + mDeviceProvider.getDevice().executeAdbCommand("remount"); + return this; + } + /** Copies a file within the host test jar to a temporary file on the host machine. */ private File copyResourceToTemp(String resourcePath) throws IOException { final File tempFile = mHostTempFolder.newFile(resourcePath); @@ -138,7 +132,7 @@ class SystemPreparer extends ExternalResource { protected void after() { final ITestDevice device = mDeviceProvider.getDevice(); try { - device.executeAdbCommand("remount"); + remount(); for (final String file : mPushedFiles) { device.deleteFile(file); } diff --git a/core/tests/overlaytests/remount/test-apps/Overlay/Android.bp b/core/tests/overlaytests/remount/test-apps/Overlay/Android.bp new file mode 100644 index 000000000000..447601972f78 --- /dev/null +++ b/core/tests/overlaytests/remount/test-apps/Overlay/Android.bp @@ -0,0 +1,18 @@ +// 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: "OverlayRemountedTest_Overlay", + sdk_version: "current", +} diff --git a/core/tests/overlaytests/remount/test-apps/Overlay/AndroidManifest.xml b/core/tests/overlaytests/remount/test-apps/Overlay/AndroidManifest.xml new file mode 100644 index 000000000000..d6d706c2da62 --- /dev/null +++ b/core/tests/overlaytests/remount/test-apps/Overlay/AndroidManifest.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2020 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. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.overlaytest.remounted.target.overlay"> + <application android:hasCode="false" /> + <overlay android:targetPackage="com.android.overlaytest.remounted.target" + android:targetName="TestResources" /> +</manifest>
\ No newline at end of file diff --git a/core/tests/overlaytests/remount/test-apps/Overlay/res/values/values.xml b/core/tests/overlaytests/remount/test-apps/Overlay/res/values/values.xml new file mode 100644 index 000000000000..675e44f19f95 --- /dev/null +++ b/core/tests/overlaytests/remount/test-apps/Overlay/res/values/values.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2020 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. + --> + +<resources> + <bool name="target_overlaid">true</bool> +</resources> diff --git a/core/tests/overlaytests/remount/host/test-apps/SharedLibrary/Android.bp b/core/tests/overlaytests/remount/test-apps/SharedLibrary/Android.bp index ffb0572c3fd0..ffb0572c3fd0 100644 --- a/core/tests/overlaytests/remount/host/test-apps/SharedLibrary/Android.bp +++ b/core/tests/overlaytests/remount/test-apps/SharedLibrary/Android.bp diff --git a/core/tests/overlaytests/remount/host/test-apps/SharedLibrary/AndroidManifest.xml b/core/tests/overlaytests/remount/test-apps/SharedLibrary/AndroidManifest.xml index 06e3f6a99410..06e3f6a99410 100644 --- a/core/tests/overlaytests/remount/host/test-apps/SharedLibrary/AndroidManifest.xml +++ b/core/tests/overlaytests/remount/test-apps/SharedLibrary/AndroidManifest.xml diff --git a/core/tests/overlaytests/remount/host/test-apps/SharedLibrary/res/values/overlayable.xml b/core/tests/overlaytests/remount/test-apps/SharedLibrary/res/values/overlayable.xml index 1b06f6d7530b..1b06f6d7530b 100644 --- a/core/tests/overlaytests/remount/host/test-apps/SharedLibrary/res/values/overlayable.xml +++ b/core/tests/overlaytests/remount/test-apps/SharedLibrary/res/values/overlayable.xml diff --git a/core/tests/overlaytests/remount/host/test-apps/SharedLibrary/res/values/public.xml b/core/tests/overlaytests/remount/test-apps/SharedLibrary/res/values/public.xml index 5b9db163a274..5b9db163a274 100644 --- a/core/tests/overlaytests/remount/host/test-apps/SharedLibrary/res/values/public.xml +++ b/core/tests/overlaytests/remount/test-apps/SharedLibrary/res/values/public.xml diff --git a/core/tests/overlaytests/remount/host/test-apps/SharedLibrary/res/values/values.xml b/core/tests/overlaytests/remount/test-apps/SharedLibrary/res/values/values.xml index 2dc47a7ecf61..2dc47a7ecf61 100644 --- a/core/tests/overlaytests/remount/host/test-apps/SharedLibrary/res/values/values.xml +++ b/core/tests/overlaytests/remount/test-apps/SharedLibrary/res/values/values.xml diff --git a/core/tests/overlaytests/remount/host/test-apps/SharedLibraryOverlay/Android.bp b/core/tests/overlaytests/remount/test-apps/SharedLibraryOverlay/Android.bp index 0d29aec909d5..0d29aec909d5 100644 --- a/core/tests/overlaytests/remount/host/test-apps/SharedLibraryOverlay/Android.bp +++ b/core/tests/overlaytests/remount/test-apps/SharedLibraryOverlay/Android.bp diff --git a/core/tests/overlaytests/remount/host/test-apps/SharedLibraryOverlay/AndroidManifest.xml b/core/tests/overlaytests/remount/test-apps/SharedLibraryOverlay/AndroidManifest.xml index 53a4e61949da..53a4e61949da 100644 --- a/core/tests/overlaytests/remount/host/test-apps/SharedLibraryOverlay/AndroidManifest.xml +++ b/core/tests/overlaytests/remount/test-apps/SharedLibraryOverlay/AndroidManifest.xml diff --git a/core/tests/overlaytests/remount/host/test-apps/SharedLibraryOverlay/res/values/values.xml b/core/tests/overlaytests/remount/test-apps/SharedLibraryOverlay/res/values/values.xml index f66448a8d991..f66448a8d991 100644 --- a/core/tests/overlaytests/remount/host/test-apps/SharedLibraryOverlay/res/values/values.xml +++ b/core/tests/overlaytests/remount/test-apps/SharedLibraryOverlay/res/values/values.xml diff --git a/core/tests/overlaytests/remount/target/Android.bp b/core/tests/overlaytests/remount/test-apps/Target/Android.bp index 83f9f28b3f48..a8910eb8dae2 100644 --- a/core/tests/overlaytests/remount/target/Android.bp +++ b/core/tests/overlaytests/remount/test-apps/Target/Android.bp @@ -1,4 +1,4 @@ -// Copyright (C) 2018 The Android Open Source Project +// 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. @@ -14,7 +14,12 @@ android_test_helper_app { name: "OverlayRemountedTest_Target", - srcs: ["src/**/*.java"], sdk_version: "test_current", libs: ["OverlayRemountedTest_SharedLibrary"], } + +android_test_helper_app { + name: "OverlayRemountedTest_TargetUpgrade", + resource_dirs: ["res_upgrade"], + sdk_version: "test_current", +} diff --git a/core/tests/overlaytests/remount/target/AndroidManifest.xml b/core/tests/overlaytests/remount/test-apps/Target/AndroidManifest.xml index dc07dca16718..d1c7b7e8bb9d 100644 --- a/core/tests/overlaytests/remount/target/AndroidManifest.xml +++ b/core/tests/overlaytests/remount/test-apps/Target/AndroidManifest.xml @@ -19,8 +19,7 @@ package="com.android.overlaytest.remounted.target"> <application> - <uses-library android:name="android.test.runner" /> <uses-library android:name="com.android.overlaytest.remounted.shared_library" - android:required="true" /> + android:required="false" /> </application> </manifest> diff --git a/core/tests/overlaytests/remount/test-apps/Target/res/values/overlayable.xml b/core/tests/overlaytests/remount/test-apps/Target/res/values/overlayable.xml new file mode 100644 index 000000000000..4aa5bcee8f3d --- /dev/null +++ b/core/tests/overlaytests/remount/test-apps/Target/res/values/overlayable.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2020 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. + --> + +<resources> + <overlayable name="TestResources"> + <policy type="public"> + <item type="bool" name="target_overlaid" /> + </policy> + </overlayable> +</resources> diff --git a/core/tests/overlaytests/remount/target/res/values/values.xml b/core/tests/overlaytests/remount/test-apps/Target/res/values/values.xml index b5f444a5eb72..76253a95b766 100644 --- a/core/tests/overlaytests/remount/target/res/values/values.xml +++ b/core/tests/overlaytests/remount/test-apps/Target/res/values/values.xml @@ -17,4 +17,10 @@ <resources xmlns:sharedlib="http://schemas.android.com/apk/res/com.android.overlaytest.remounted.shared_library"> <bool name="uses_shared_library_overlaid">@sharedlib:bool/shared_library_overlaid</bool> + + <!-- This resource has a different id in the updated version of this target app to test that the + idmap is regenerated when the target is updated. --> + <bool name="target_overlaid">false</bool> + <public type="bool" name="target_overlaid" id="0x7f010000" /> + <bool name="target_reference">@bool/target_overlaid</bool> </resources> diff --git a/core/tests/overlaytests/remount/test-apps/Target/res_upgrade/values/overlayable.xml b/core/tests/overlaytests/remount/test-apps/Target/res_upgrade/values/overlayable.xml new file mode 100644 index 000000000000..4aa5bcee8f3d --- /dev/null +++ b/core/tests/overlaytests/remount/test-apps/Target/res_upgrade/values/overlayable.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2020 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. + --> + +<resources> + <overlayable name="TestResources"> + <policy type="public"> + <item type="bool" name="target_overlaid" /> + </policy> + </overlayable> +</resources> diff --git a/core/tests/overlaytests/remount/test-apps/Target/res_upgrade/values/values.xml b/core/tests/overlaytests/remount/test-apps/Target/res_upgrade/values/values.xml new file mode 100644 index 000000000000..f552cb0776ab --- /dev/null +++ b/core/tests/overlaytests/remount/test-apps/Target/res_upgrade/values/values.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2020 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. + --> +<resources> + <!-- This resource has a different id in the updated target app than the base target app to test + that the idmap is regenerated when the target is updated. --> + <bool name="target_overlaid">false</bool> + <public type="bool" name="target_overlaid" id="0x7f0100ff" /> + <bool name="target_reference">@bool/target_overlaid</bool> +</resources>
\ No newline at end of file diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp index 918e7af12d31..05f4d6b63a4c 100644 --- a/libs/androidfw/ApkAssets.cpp +++ b/libs/androidfw/ApkAssets.cpp @@ -385,7 +385,7 @@ std::unique_ptr<const ApkAssets> ApkAssets::LoadOverlay(const std::string& idmap const StringPiece idmap_data( reinterpret_cast<const char*>(idmap_asset->getBuffer(true /*wordAligned*/)), static_cast<size_t>(idmap_asset->getLength())); - std::unique_ptr<const LoadedIdmap> loaded_idmap = LoadedIdmap::Load(idmap_data); + std::unique_ptr<const LoadedIdmap> loaded_idmap = LoadedIdmap::Load(idmap_path, idmap_data); if (loaded_idmap == nullptr) { LOG(ERROR) << "failed to load IDMAP " << idmap_path; return {}; @@ -538,8 +538,9 @@ bool ApkAssets::IsUpToDate() const { // Loaders are invalidated by the app, not the system, so assume they are up to date. return true; } + return (!loaded_idmap_ || loaded_idmap_->IsUpToDate()) && + last_mod_time_ == getFileModDate(path_.c_str()); - return last_mod_time_ == getFileModDate(path_.c_str()); } } // namespace android diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp index 0b2fd9ec982d..eb6ee9525bb9 100644 --- a/libs/androidfw/Idmap.cpp +++ b/libs/androidfw/Idmap.cpp @@ -20,6 +20,7 @@ #include "android-base/logging.h" #include "android-base/stringprintf.h" +#include "androidfw/misc.h" #include "androidfw/ResourceTypes.h" #include "androidfw/Util.h" #include "utils/ByteOrder.h" @@ -192,7 +193,9 @@ static bool IsValidIdmapHeader(const StringPiece& data) { return true; } -LoadedIdmap::LoadedIdmap(const Idmap_header* header, +LoadedIdmap::LoadedIdmap(std::string&& idmap_path, + const time_t last_mod_time, + const Idmap_header* header, const Idmap_data_header* data_header, const Idmap_target_entry* target_entries, const Idmap_overlay_entry* overlay_entries, @@ -201,7 +204,9 @@ LoadedIdmap::LoadedIdmap(const Idmap_header* header, data_header_(data_header), target_entries_(target_entries), overlay_entries_(overlay_entries), - string_pool_(string_pool) { + string_pool_(string_pool), + idmap_path_(std::move(idmap_path)), + idmap_last_mod_time_(last_mod_time) { size_t length = strnlen(reinterpret_cast<const char*>(header_->overlay_path), arraysize(header_->overlay_path)); @@ -212,7 +217,8 @@ LoadedIdmap::LoadedIdmap(const Idmap_header* header, target_apk_path_.assign(reinterpret_cast<const char*>(header_->target_path), length); } -std::unique_ptr<const LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_data) { +std::unique_ptr<const LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_path, + const StringPiece& idmap_data) { ATRACE_CALL(); if (!IsValidIdmapHeader(idmap_data)) { return {}; @@ -275,10 +281,14 @@ std::unique_ptr<const LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_da // Can't use make_unique because LoadedIdmap constructor is private. std::unique_ptr<LoadedIdmap> loaded_idmap = std::unique_ptr<LoadedIdmap>( - new LoadedIdmap(header, data_header, target_entries, overlay_entries, - idmap_string_pool.release())); + new LoadedIdmap(idmap_path.to_string(), getFileModDate(idmap_path.data()), header, + data_header, target_entries, overlay_entries, idmap_string_pool.release())); return std::move(loaded_idmap); } +bool LoadedIdmap::IsUpToDate() const { + return idmap_last_mod_time_ == getFileModDate(idmap_path_.c_str()); +} + } // namespace android diff --git a/libs/androidfw/include/androidfw/Idmap.h b/libs/androidfw/include/androidfw/Idmap.h index ccb57f373473..ecc1ce65d124 100644 --- a/libs/androidfw/include/androidfw/Idmap.h +++ b/libs/androidfw/include/androidfw/Idmap.h @@ -142,7 +142,13 @@ class IdmapResMap { class LoadedIdmap { public: // Loads an IDMAP from a chunk of memory. Returns nullptr if the IDMAP data was malformed. - static std::unique_ptr<const LoadedIdmap> Load(const StringPiece& idmap_data); + static std::unique_ptr<const LoadedIdmap> Load(const StringPiece& idmap_path, + const StringPiece& idmap_data); + + // Returns the path to the IDMAP. + inline const std::string& IdmapPath() const { + return idmap_path_; + } // Returns the path to the RRO (Runtime Resource Overlay) APK for which this IDMAP was generated. inline const std::string& OverlayApkPath() const { @@ -167,6 +173,10 @@ class LoadedIdmap { return OverlayDynamicRefTable(data_header_, overlay_entries_, target_assigned_package_id); } + // Returns whether the idmap file on disk has not been modified since the construction of this + // LoadedIdmap. + bool IsUpToDate() const; + protected: // Exposed as protected so that tests can subclass and mock this class out. LoadedIdmap() = default; @@ -177,13 +187,17 @@ class LoadedIdmap { const Idmap_overlay_entry* overlay_entries_; const std::unique_ptr<ResStringPool> string_pool_; + const std::string idmap_path_; std::string overlay_apk_path_; std::string target_apk_path_; + const time_t idmap_last_mod_time_; private: DISALLOW_COPY_AND_ASSIGN(LoadedIdmap); - explicit LoadedIdmap(const Idmap_header* header, + explicit LoadedIdmap(std::string&& idmap_path, + time_t last_mod_time, + const Idmap_header* header, const Idmap_data_header* data_header, const Idmap_target_entry* target_entries, const Idmap_overlay_entry* overlay_entries, diff --git a/libs/androidfw/tests/Idmap_test.cpp b/libs/androidfw/tests/Idmap_test.cpp index 41ba637da5d7..7aa0dbbafab3 100644 --- a/libs/androidfw/tests/Idmap_test.cpp +++ b/libs/androidfw/tests/Idmap_test.cpp @@ -38,7 +38,7 @@ class IdmapTest : public ::testing::Test { protected: void SetUp() override { // Move to the test data directory so the idmap can locate the overlay APK. - std::string original_path = base::GetExecutableDirectory(); + original_path = base::GetExecutableDirectory(); chdir(GetTestDataPath().c_str()); system_assets_ = ApkAssets::Load("system/system.apk"); @@ -49,10 +49,14 @@ class IdmapTest : public ::testing::Test { overlayable_assets_ = ApkAssets::Load("overlayable/overlayable.apk"); ASSERT_NE(nullptr, overlayable_assets_); + } + + void TearDown() override { chdir(original_path.c_str()); } protected: + std::string original_path; std::unique_ptr<const ApkAssets> system_assets_; std::unique_ptr<const ApkAssets> overlay_assets_; std::unique_ptr<const ApkAssets> overlayable_assets_; @@ -221,8 +225,7 @@ TEST_F(IdmapTest, OverlaidResourceHasSameName) { TEST_F(IdmapTest, OverlayLoaderInterop) { std::string contents; - auto loader_assets = ApkAssets::LoadTable(GetTestDataPath() + "/loader/resources.arsc", - PROPERTY_LOADER); + auto loader_assets = ApkAssets::LoadTable("loader/resources.arsc", PROPERTY_LOADER); AssetManager2 asset_manager; asset_manager.SetApkAssets({overlayable_assets_.get(), loader_assets.get(), @@ -241,4 +244,25 @@ TEST_F(IdmapTest, OverlayLoaderInterop) { ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "loader"); } +TEST_F(IdmapTest, OverlayAssetsIsUpToDate) { + std::string idmap_contents; + ASSERT_TRUE(base::ReadFileToString("overlay/overlay.idmap", &idmap_contents)); + + TemporaryFile temp_file; + ASSERT_TRUE(base::WriteStringToFile(idmap_contents, temp_file.path)); + + auto apk_assets = ApkAssets::LoadOverlay(temp_file.path); + ASSERT_NE(nullptr, apk_assets); + ASSERT_TRUE(apk_assets->IsUpToDate()); + + unlink(temp_file.path); + ASSERT_FALSE(apk_assets->IsUpToDate()); + sleep(2); + + base::WriteStringToFile("hello", temp_file.path); + sleep(2); + + ASSERT_FALSE(apk_assets->IsUpToDate()); +} + } // namespace diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java index 43fc7ed0e39d..90c85ada9def 100644 --- a/services/core/java/com/android/server/om/IdmapManager.java +++ b/services/core/java/com/android/server/om/IdmapManager.java @@ -63,20 +63,23 @@ class IdmapManager { mIdmapDaemon = IdmapDaemon.getInstance(); } + /** + * Creates the idmap for the target/overlay combination and returns whether the idmap file was + * modified. + */ boolean createIdmap(@NonNull final PackageInfo targetPackage, @NonNull final PackageInfo overlayPackage, int userId) { if (DEBUG) { Slog.d(TAG, "create idmap for " + targetPackage.packageName + " and " + overlayPackage.packageName); } - final int sharedGid = UserHandle.getSharedAppGid(targetPackage.applicationInfo.uid); final String targetPath = targetPackage.applicationInfo.getBaseCodePath(); final String overlayPath = overlayPackage.applicationInfo.getBaseCodePath(); try { int policies = calculateFulfilledPolicies(targetPackage, overlayPackage, userId); boolean enforce = enforceOverlayable(overlayPackage); if (mIdmapDaemon.verifyIdmap(targetPath, overlayPath, policies, enforce, userId)) { - return true; + return false; } return mIdmapDaemon.createIdmap(targetPath, overlayPath, policies, enforce, userId) != null; diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java index d108e76e37df..05a4a38feef1 100644 --- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java +++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java @@ -700,14 +700,15 @@ final class OverlayManagerServiceImpl { final PackageInfo overlayPackage = mPackageManager.getPackageInfo(overlayPackageName, userId); - // Immutable RROs targeting to "android", ie framework-res.apk, are handled by native layers. + // Immutable RROs targeting to "android", ie framework-res.apk, are handled by native + // layers. + boolean modified = false; if (targetPackage != null && overlayPackage != null && !("android".equals(targetPackageName) && !isPackageConfiguredMutable(overlayPackageName))) { - mIdmapManager.createIdmap(targetPackage, overlayPackage, userId); + modified |= mIdmapManager.createIdmap(targetPackage, overlayPackage, userId); } - boolean modified = false; if (overlayPackage != null) { modified |= mSettings.setBaseCodePath(overlayPackageName, userId, overlayPackage.applicationInfo.getBaseCodePath()); diff --git a/services/core/java/com/android/server/om/TEST_MAPPING b/services/core/java/com/android/server/om/TEST_MAPPING index 75229a1adccc..6edd76f1810a 100644 --- a/services/core/java/com/android/server/om/TEST_MAPPING +++ b/services/core/java/com/android/server/om/TEST_MAPPING @@ -15,6 +15,9 @@ "name": "OverlayHostTests" }, { + "name": "OverlayRemountedTest" + }, + { "name": "CtsAppSecurityHostTestCases", "options": [ { diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java index 820e61cb0a08..9eda718ed922 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java +++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java @@ -377,8 +377,7 @@ class OverlayManagerServiceImplTestsBase { return false; } final String key = createKey(overlayPackage.packageName, userId); - mIdmapFiles.add(key); - return true; + return mIdmapFiles.add(key); } @Override |