blob: 8696091239c2c5308511a20c3c6fbd4050f9e620 [file] [log] [blame]
/*
* 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.assertTrue;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import org.junit.Assert;
import org.junit.rules.ExternalResource;
import org.junit.rules.TemporaryFolder;
import java.io.File;
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;
// The paths of the files pushed onto the device through this rule.
private ArrayList<String> mPushedFiles = new ArrayList<>();
// The package names of packages installed through this rule.
private ArrayList<String> mInstalledPackages = new ArrayList<>();
private final TemporaryFolder mHostTempFolder;
private final DeviceProvider mDeviceProvider;
SystemPreparer(TemporaryFolder hostTempFolder, DeviceProvider deviceProvider) {
mHostTempFolder = hostTempFolder;
mDeviceProvider = deviceProvider;
}
/** Copies a file within the host test jar to a path on device. */
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;
}
/** Installs an APK within the host test jar onto the device. */
SystemPreparer installResourceApk(String resourcePath, String packageName)
throws DeviceNotAvailableException, IOException {
final ITestDevice device = mDeviceProvider.getDevice();
final File tmpFile = copyResourceToTemp(resourcePath);
final String result = device.installPackage(tmpFile, true);
Assert.assertNull(result);
mInstalledPackages.add(packageName);
return this;
}
/** Sets the enable state of an overlay pacakage. */
SystemPreparer setOverlayEnabled(String packageName, boolean enabled)
throws ExecutionException, DeviceNotAvailableException {
final ITestDevice device = mDeviceProvider.getDevice();
// 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 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"));
}
return this;
}
/** Restarts the device and waits until after boot is completed. */
SystemPreparer reboot() throws DeviceNotAvailableException {
final ITestDevice device = mDeviceProvider.getDevice();
device.reboot();
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);
final ClassLoader classLoader = getClass().getClassLoader();
try (InputStream assetIs = classLoader.getResource(resourcePath).openStream();
FileOutputStream assetOs = new FileOutputStream(tempFile)) {
if (assetIs == null) {
throw new IllegalStateException("Failed to find resource " + resourcePath);
}
int b;
while ((b = assetIs.read()) >= 0) {
assetOs.write(b);
}
}
return tempFile;
}
/** Removes installed packages and files that were pushed to the device. */
@Override
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());
}
}
interface DeviceProvider {
ITestDevice getDevice();
}
}