Merge "Fix remounting overlay tests failure"
diff --git a/core/tests/overlaytests/remount/host/AndroidTest.xml b/core/tests/overlaytests/remount/host/AndroidTest.xml
index 11eadf1a..087b731 100644
--- a/core/tests/overlaytests/remount/host/AndroidTest.xml
+++ b/core/tests/overlaytests/remount/host/AndroidTest.xml
@@ -19,9 +19,6 @@
<option name="test-tag" value="OverlayRemountedTest" />
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
- <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="run-command" value="remount" />
- </target_preparer>
<test class="com.android.tradefed.testtype.HostTest">
<option name="jar" value="OverlayRemountedTest.jar" />
diff --git a/core/tests/overlaytests/remount/host/src/com/android/overlaytest/remounted/OverlayHostTest.java b/core/tests/overlaytests/remount/host/src/com/android/overlaytest/remounted/OverlayHostTest.java
deleted file mode 100644
index 84af187..0000000
--- a/core/tests/overlaytests/remount/host/src/com/android/overlaytest/remounted/OverlayHostTest.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * 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 com.android.overlaytest.remounted;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-
-import org.junit.Rule;
-import org.junit.rules.RuleChain;
-import org.junit.rules.TemporaryFolder;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class OverlayHostTest extends BaseHostJUnit4Test {
- private static final long TIME_OUT_MS = 30000;
- private static final String RES_INSTRUMENTATION_ARG = "res";
- private static final String OVERLAY_INSTRUMENTATION_ARG = "overlays";
- private static final String RESOURCES_TYPE_SUFFIX = "_type";
- private static final String RESOURCES_DATA_SUFFIX = "_data";
-
- public final TemporaryFolder mTemporaryFolder = new TemporaryFolder();
- public final SystemPreparer mPreparer = new SystemPreparer(mTemporaryFolder, this::getDevice);
-
- @Rule
- public final RuleChain ruleChain = RuleChain.outerRule(mTemporaryFolder).around(mPreparer);
- private Map<String, String> mLastResults;
-
- /**
- * Retrieves the values of the resources in the test package. The test package must use the
- * {@link com.android.overlaytest.remounted.target.ResourceRetrievalRunner} instrumentation.
- **/
- void retrieveResource(String testPackageName, List<String> requiredOverlayPaths,
- String... resourceNames) throws DeviceNotAvailableException {
- final HashMap<String, String> args = new HashMap<>();
- if (!requiredOverlayPaths.isEmpty()) {
- // Enclose the require overlay paths in quotes so the arguments will be string arguments
- // rather than file arguments.
- args.put(OVERLAY_INSTRUMENTATION_ARG,
- String.format("\"%s\"", String.join(" ", requiredOverlayPaths)));
- }
-
- if (resourceNames.length == 0) {
- throw new IllegalArgumentException("Must specify at least one resource to retrieve.");
- }
-
- // Pass the names of the resources to retrieve into the test as one string.
- args.put(RES_INSTRUMENTATION_ARG,
- String.format("\"%s\"", String.join(" ", resourceNames)));
-
- runDeviceTests(getDevice(), null, testPackageName, null, null, null, TIME_OUT_MS,
- TIME_OUT_MS, TIME_OUT_MS, false, false, args);
-
- // Retrieve the results of the most recently run test.
- mLastResults = (getLastDeviceRunResults().getRunMetrics() == mLastResults) ? null :
- getLastDeviceRunResults().getRunMetrics();
- }
-
- /** Returns the base resource directories of the specified packages. */
- List<String> getPackagePaths(String... packageNames)
- throws DeviceNotAvailableException {
- final ArrayList<String> paths = new ArrayList<>();
- for (String packageName : packageNames) {
- // Use the package manager shell command to find the path of the package.
- final String result = getDevice().executeShellCommand(
- String.format("pm dump %s | grep \"resourcePath=\"", packageName));
- assertNotNull("Failed to find path for package " + packageName, result);
- int splitIndex = result.indexOf('=');
- assertTrue(splitIndex >= 0);
- paths.add(result.substring(splitIndex + 1).trim());
- }
- return paths;
- }
-
- /** 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);
- }
-
- /**
- * Asserts that the type and data of a a previously retrieved is the same as expected.
- * @param resourceName the full name of the resource in the form package:type/entry
- * @param type the expected {@link android.util.TypedValue} type of the resource
- * @param data the expected value of the resource when coerced to a string using
- * {@link android.util.TypedValue#coerceToString()}
- **/
- void assertResource(String resourceName, int type, String data) {
- assertNotNull("Failed to get test results", mLastResults);
- assertNotEquals("No resource values were retrieved", mLastResults.size(), 0);
- assertEquals("" + type, mLastResults.get(resourceName + RESOURCES_TYPE_SUFFIX));
- assertEquals("" + data, mLastResults.get(resourceName + RESOURCES_DATA_SUFFIX));
- }
-}
diff --git a/core/tests/overlaytests/remount/host/src/com/android/overlaytest/remounted/OverlaySharedLibraryTest.java b/core/tests/overlaytests/remount/host/src/com/android/overlaytest/remounted/OverlaySharedLibraryTest.java
index 4939e16..06b2ac8 100644
--- a/core/tests/overlaytests/remount/host/src/com/android/overlaytest/remounted/OverlaySharedLibraryTest.java
+++ b/core/tests/overlaytests/remount/host/src/com/android/overlaytest/remounted/OverlaySharedLibraryTest.java
@@ -16,17 +16,21 @@
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;
-import java.util.Collections;
-import java.util.List;
-
@RunWith(DeviceJUnit4ClassRunner.class)
-public class OverlaySharedLibraryTest extends OverlayHostTest {
+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 =
@@ -38,6 +42,17 @@
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();
+ }
+
@Test
public void testSharedLibrary() throws Exception {
final String targetResource = resourceName(TARGET_PACKAGE, "bool",
@@ -45,23 +60,20 @@
final String libraryResource = resourceName(SHARED_LIBRARY_PACKAGE, "bool",
"shared_library_overlaid");
- mPreparer.pushResourceFile(SHARED_LIBRARY_APK, "/product/app/SharedLibrary.apk")
+ preparer.pushResourceFile(SHARED_LIBRARY_APK, "/product/app/SharedLibrary.apk")
.installResourceApk(SHARED_LIBRARY_OVERLAY_APK, SHARED_LIBRARY_OVERLAY_PACKAGE)
.reboot()
.setOverlayEnabled(SHARED_LIBRARY_OVERLAY_PACKAGE, false)
.installResourceApk(TARGET_APK, TARGET_PACKAGE);
// The shared library resource is not currently overlaid.
- retrieveResource(Collections.emptyList(), targetResource, libraryResource);
- assertResource(targetResource, 0x12 /* TYPE_INT_BOOLEAN */, "false");
- assertResource(libraryResource, 0x12 /* TYPE_INT_BOOLEAN */, "false");
+ assertResource(targetResource, "false");
+ assertResource(libraryResource, "false");
// Overlay the shared library resource.
- mPreparer.setOverlayEnabled(SHARED_LIBRARY_OVERLAY_PACKAGE, true);
- retrieveResource(getPackagePaths(SHARED_LIBRARY_OVERLAY_PACKAGE), targetResource,
- libraryResource);
- assertResource(targetResource, 0x12 /* TYPE_INT_BOOLEAN */, "true");
- assertResource(libraryResource, 0x12 /* TYPE_INT_BOOLEAN */, "true");
+ preparer.setOverlayEnabled(SHARED_LIBRARY_OVERLAY_PACKAGE, true);
+ assertResource(targetResource, "true");
+ assertResource(libraryResource, "true");
}
@Test
@@ -71,20 +83,27 @@
final String libraryResource = resourceName(SHARED_LIBRARY_PACKAGE, "bool",
"shared_library_overlaid");
- mPreparer.pushResourceFile(SHARED_LIBRARY_APK, "/product/app/SharedLibrary.apk")
+ preparer.pushResourceFile(SHARED_LIBRARY_APK, "/product/app/SharedLibrary.apk")
.installResourceApk(SHARED_LIBRARY_OVERLAY_APK, SHARED_LIBRARY_OVERLAY_PACKAGE)
.setOverlayEnabled(SHARED_LIBRARY_OVERLAY_PACKAGE, true)
.reboot()
.installResourceApk(TARGET_APK, TARGET_PACKAGE);
- retrieveResource(getPackagePaths(SHARED_LIBRARY_OVERLAY_PACKAGE), targetResource,
- libraryResource);
- assertResource(targetResource, 0x12 /* TYPE_INT_BOOLEAN */, "true");
- assertResource(libraryResource, 0x12 /* TYPE_INT_BOOLEAN */, "true");
+ assertResource(targetResource, "true");
+ assertResource(libraryResource, "true");
}
- private void retrieveResource(List<String> requiredOverlayPaths, String... resourceNames)
+ /** 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 {
- retrieveResource(TARGET_PACKAGE, requiredOverlayPaths, resourceNames);
+ 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/host/src/com/android/overlaytest/remounted/SystemPreparer.java b/core/tests/overlaytests/remount/host/src/com/android/overlaytest/remounted/SystemPreparer.java
index 7028f2f..8696091 100644
--- a/core/tests/overlaytests/remount/host/src/com/android/overlaytest/remounted/SystemPreparer.java
+++ b/core/tests/overlaytests/remount/host/src/com/android/overlaytest/remounted/SystemPreparer.java
@@ -38,8 +38,7 @@
import java.util.concurrent.TimeoutException;
class SystemPreparer extends ExternalResource {
- private static final long REBOOT_SLEEP_MS = 30000;
- private static final long OVERLAY_ENABLE_TIMEOUT_MS = 20000;
+ private static final long OVERLAY_ENABLE_TIMEOUT_MS = 30000;
// The paths of the files pushed onto the device through this rule.
private ArrayList<String> mPushedFiles = new ArrayList<>();
@@ -59,6 +58,7 @@
SystemPreparer pushResourceFile(String resourcePath,
String outputPath) throws DeviceNotAvailableException, IOException {
final ITestDevice device = mDeviceProvider.getDevice();
+ device.executeAdbCommand("remount");
assertTrue(device.pushFile(copyResourceToTemp(resourcePath), outputPath));
mPushedFiles.add(outputPath);
return this;
@@ -77,7 +77,7 @@
/** Sets the enable state of an overlay pacakage. */
SystemPreparer setOverlayEnabled(String packageName, boolean enabled)
- throws ExecutionException, TimeoutException {
+ throws ExecutionException, DeviceNotAvailableException {
final ITestDevice device = mDeviceProvider.getDevice();
// Wait for the overlay to change its enabled state.
@@ -86,8 +86,10 @@
device.executeShellCommand(String.format("cmd overlay %s %s",
enabled ? "enable" : "disable", packageName));
- final String pattern = (enabled ? "[x]" : "[ ]") + " " + packageName;
- if (device.executeShellCommand("cmd overlay list").contains(pattern)) {
+ 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;
}
}
@@ -98,6 +100,8 @@
try {
enabledListener.get(OVERLAY_ENABLE_TIMEOUT_MS, MILLISECONDS);
} catch (InterruptedException ignored) {
+ } catch (TimeoutException e) {
+ throw new IllegalStateException(device.executeShellCommand("cmd overlay list"));
}
return this;
@@ -106,14 +110,7 @@
/** Restarts the device and waits until after boot is completed. */
SystemPreparer reboot() throws DeviceNotAvailableException {
final ITestDevice device = mDeviceProvider.getDevice();
- device.executeShellCommand("stop");
- device.executeShellCommand("start");
- try {
- // Sleep until the device is ready for test execution.
- Thread.sleep(REBOOT_SLEEP_MS);
- } catch (InterruptedException ignored) {
- }
-
+ device.reboot();
return this;
}
@@ -141,12 +138,14 @@
protected void after() {
final ITestDevice device = mDeviceProvider.getDevice();
try {
+ device.executeAdbCommand("remount");
for (final String file : mPushedFiles) {
device.deleteFile(file);
}
for (final String packageName : mInstalledPackages) {
device.uninstallPackage(packageName);
}
+ device.reboot();
} catch (DeviceNotAvailableException e) {
Assert.fail(e.toString());
}
diff --git a/core/tests/overlaytests/remount/target/AndroidManifest.xml b/core/tests/overlaytests/remount/target/AndroidManifest.xml
index 32fec43..dc07dca 100644
--- a/core/tests/overlaytests/remount/target/AndroidManifest.xml
+++ b/core/tests/overlaytests/remount/target/AndroidManifest.xml
@@ -23,8 +23,4 @@
<uses-library android:name="com.android.overlaytest.remounted.shared_library"
android:required="true" />
</application>
-
- <instrumentation android:name="com.android.overlaytest.remounted.target.ResourceRetrievalRunner"
- android:targetPackage="com.android.overlaytest.remounted.target"
- android:label="Remounted system RRO tests" />
</manifest>
diff --git a/core/tests/overlaytests/remount/target/src/com/android/overlaytest/remounted/target/ResourceRetrievalRunner.java b/core/tests/overlaytests/remount/target/src/com/android/overlaytest/remounted/target/ResourceRetrievalRunner.java
deleted file mode 100644
index 2e4c211..0000000
--- a/core/tests/overlaytests/remount/target/src/com/android/overlaytest/remounted/target/ResourceRetrievalRunner.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * 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 com.android.overlaytest.remounted.target;
-
-import android.app.Activity;
-import android.app.Instrumentation;
-import android.content.res.Resources;
-import android.os.Bundle;
-import android.util.Log;
-import android.util.TypedValue;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.concurrent.Executor;
-import java.util.concurrent.FutureTask;
-import java.util.concurrent.TimeUnit;
-
-/**
- * An {@link Instrumentation} that retrieves the value of specified resources within the
- * application.
- **/
-public class ResourceRetrievalRunner extends Instrumentation {
- private static final String TAG = ResourceRetrievalRunner.class.getSimpleName();
-
- // A list of whitespace separated resource names of which to retrieve the resource values.
- private static final String RESOURCE_LIST_TAG = "res";
-
- // A list of whitespace separated overlay package paths that must be present before retrieving
- // resource values.
- private static final String REQUIRED_OVERLAYS_LIST_TAG = "overlays";
-
- // The suffixes of the keys returned from the instrumentation. To retrieve the type of a
- // resource looked up with the instrumentation, append the {@link #RESOURCES_TYPE_SUFFIX} suffix
- // to the end of the name of the resource. For the value of a resource, use
- // {@link #RESOURCES_DATA_SUFFIX} instead.
- private static final String RESOURCES_TYPE_SUFFIX = "_type";
- private static final String RESOURCES_DATA_SUFFIX = "_data";
-
- // The amount of time in seconds to wait for the overlays to be present in the AssetManager.
- private static final int OVERLAY_PATH_TIMEOUT = 60;
-
- private final ArrayList<String> mResourceNames = new ArrayList<>();
- private final ArrayList<String> mOverlayPaths = new ArrayList<>();
- private final Bundle mResult = new Bundle();
-
- /**
- * Receives the instrumentation arguments and runs the resource retrieval.
- * The entry with key {@link #RESOURCE_LIST_TAG} in the {@link Bundle} arguments is a
- * whitespace separated string of resource names of which to retrieve the resource values.
- * The entry with key {@link #REQUIRED_OVERLAYS_LIST_TAG} in the {@link Bundle} arguments is a
- * whitespace separated string of overlay package paths prefixes that must be present before
- * retrieving the resource values.
- */
- @Override
- public void onCreate(Bundle arguments) {
- super.onCreate(arguments);
- mResourceNames.addAll(Arrays.asList(arguments.getString(RESOURCE_LIST_TAG).split(" ")));
- if (arguments.containsKey(REQUIRED_OVERLAYS_LIST_TAG)) {
- mOverlayPaths.addAll(Arrays.asList(
- arguments.getString(REQUIRED_OVERLAYS_LIST_TAG).split(" ")));
- }
- start();
- }
-
- @Override
- public void onStart() {
- final Resources res = getContext().getResources();
- res.getAssets().setResourceResolutionLoggingEnabled(true);
-
- if (!mOverlayPaths.isEmpty()) {
- Log.d(TAG, String.format("Waiting for overlay paths [%s]",
- String.join(",", mOverlayPaths)));
-
- // Wait for all required overlays to be present in the AssetManager.
- final FutureTask<Boolean> overlayListener = new FutureTask<>(() -> {
- while (!mOverlayPaths.isEmpty()) {
- final String[] apkPaths = res.getAssets().getApkPaths();
- for (String path : apkPaths) {
- for (String overlayPath : mOverlayPaths) {
- if (path.startsWith(overlayPath)) {
- mOverlayPaths.remove(overlayPath);
- break;
- }
- }
- }
- }
- return true;
- });
-
- try {
- final Executor executor = (t) -> new Thread(t).start();
- executor.execute(overlayListener);
- overlayListener.get(OVERLAY_PATH_TIMEOUT, TimeUnit.SECONDS);
- } catch (Exception e) {
- Log.e(TAG, String.format("Failed to wait for required overlays [%s]",
- String.join(",", mOverlayPaths)), e);
- finish(Activity.RESULT_CANCELED, mResult);
- }
- }
-
- // Retrieve the values for each resource passed in.
- final TypedValue typedValue = new TypedValue();
- for (final String resourceName : mResourceNames) {
- try {
- final int resId = res.getIdentifier(resourceName, null, null);
- res.getValue(resId, typedValue, true);
- Log.d(TAG, String.format("Resolution for 0x%s: %s", Integer.toHexString(resId),
- res.getAssets().getLastResourceResolution()));
- } catch (Resources.NotFoundException e) {
- Log.e(TAG, "Failed to retrieve value for resource " + resourceName, e);
- finish(Activity.RESULT_CANCELED, mResult);
- }
-
- putValue(resourceName, typedValue);
- }
-
- finish(Activity.RESULT_OK, mResult);
- }
-
- private void putValue(String resourceName, TypedValue value) {
- mResult.putInt(resourceName + RESOURCES_TYPE_SUFFIX, value.type);
- final CharSequence textValue = value.coerceToString();
- mResult.putString(resourceName + RESOURCES_DATA_SUFFIX,
- textValue == null ? "null" : textValue.toString());
- }
-}