/* * 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.transparency.test; import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper; import com.android.tradefed.build.IBuildInfo; import com.android.tradefed.device.DeviceNotAvailableException; import com.android.tradefed.device.ITestDevice; import junit.framework.TestCase; import java.io.File; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Base class for invoking the install-multiple command via ADB. Subclass this for less typing: * * private class InstallMultiple extends BaseInstallMultiple<InstallMultiple> { public * InstallMultiple() { super(getDevice(), null); } } */ /*package*/ class BaseInstallMultiple> { private final ITestDevice mDevice; private final IBuildInfo mBuild; private final List mArgs = new ArrayList<>(); private final Map mFileToRemoteMap = new HashMap<>(); /*package*/ BaseInstallMultiple(ITestDevice device, IBuildInfo buildInfo) { mDevice = device; mBuild = buildInfo; addArg("-g"); } T addArg(String arg) { mArgs.add(arg); return (T) this; } T addFile(String filename) throws FileNotFoundException { return addFile(filename, filename); } T addFile(String filename, String remoteName) throws FileNotFoundException { CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild); mFileToRemoteMap.put(buildHelper.getTestFile(filename), remoteName); return (T) this; } T inheritFrom(String packageName) { addArg("-r"); addArg("-p " + packageName); return (T) this; } void run() throws DeviceNotAvailableException { run(true); } void runExpectingFailure() throws DeviceNotAvailableException { run(false); } private void run(boolean expectingSuccess) throws DeviceNotAvailableException { final ITestDevice device = mDevice; // Create an install session final StringBuilder cmd = new StringBuilder(); cmd.append("pm install-create"); for (String arg : mArgs) { cmd.append(' ').append(arg); } String result = device.executeShellCommand(cmd.toString()); TestCase.assertTrue(result, result.startsWith("Success")); final int start = result.lastIndexOf("["); final int end = result.lastIndexOf("]"); int sessionId = -1; try { if (start != -1 && end != -1 && start < end) { sessionId = Integer.parseInt(result.substring(start + 1, end)); } } catch (NumberFormatException e) { throw new IllegalStateException("Failed to parse install session: " + result); } if (sessionId == -1) { throw new IllegalStateException("Failed to create install session: " + result); } // Push our files into session. Ideally we'd use stdin streaming, // but ddmlib doesn't support it yet. for (final Map.Entry entry : mFileToRemoteMap.entrySet()) { final File file = entry.getKey(); final String remoteName = entry.getValue(); final String remotePath = "/data/local/tmp/" + file.getName(); if (!device.pushFile(file, remotePath)) { throw new IllegalStateException("Failed to push " + file); } cmd.setLength(0); cmd.append("pm install-write"); cmd.append(' ').append(sessionId); cmd.append(' ').append(remoteName); cmd.append(' ').append(remotePath); result = device.executeShellCommand(cmd.toString()); TestCase.assertTrue(result, result.startsWith("Success")); } // Everything staged; let's pull trigger cmd.setLength(0); cmd.append("pm install-commit"); cmd.append(' ').append(sessionId); result = device.executeShellCommand(cmd.toString()); if (expectingSuccess) { TestCase.assertTrue(result, result.contains("Success")); } else { TestCase.assertFalse(result, result.contains("Success")); } } }