1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.transparency.test; 17 18 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper; 19 import com.android.tradefed.build.IBuildInfo; 20 import com.android.tradefed.device.DeviceNotAvailableException; 21 import com.android.tradefed.device.ITestDevice; 22 23 import junit.framework.TestCase; 24 25 import java.io.File; 26 import java.io.FileNotFoundException; 27 import java.util.ArrayList; 28 import java.util.HashMap; 29 import java.util.List; 30 import java.util.Map; 31 32 /** 33 * Base class for invoking the install-multiple command via ADB. Subclass this for less typing: 34 * 35 * <code> private class InstallMultiple extends BaseInstallMultiple<InstallMultiple> { public 36 * InstallMultiple() { super(getDevice(), null); } } </code> 37 */ 38 /*package*/ class BaseInstallMultiple<T extends BaseInstallMultiple<?>> { 39 40 private final ITestDevice mDevice; 41 private final IBuildInfo mBuild; 42 43 private final List<String> mArgs = new ArrayList<>(); 44 private final Map<File, String> mFileToRemoteMap = new HashMap<>(); 45 BaseInstallMultiple(ITestDevice device, IBuildInfo buildInfo)46 /*package*/ BaseInstallMultiple(ITestDevice device, IBuildInfo buildInfo) { 47 mDevice = device; 48 mBuild = buildInfo; 49 addArg("-g"); 50 } 51 addArg(String arg)52 T addArg(String arg) { 53 mArgs.add(arg); 54 return (T) this; 55 } 56 addFile(String filename)57 T addFile(String filename) throws FileNotFoundException { 58 return addFile(filename, filename); 59 } 60 addFile(String filename, String remoteName)61 T addFile(String filename, String remoteName) throws FileNotFoundException { 62 CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild); 63 mFileToRemoteMap.put(buildHelper.getTestFile(filename), remoteName); 64 return (T) this; 65 } 66 inheritFrom(String packageName)67 T inheritFrom(String packageName) { 68 addArg("-r"); 69 addArg("-p " + packageName); 70 return (T) this; 71 } 72 run()73 void run() throws DeviceNotAvailableException { 74 run(true); 75 } 76 runExpectingFailure()77 void runExpectingFailure() throws DeviceNotAvailableException { 78 run(false); 79 } 80 run(boolean expectingSuccess)81 private void run(boolean expectingSuccess) throws DeviceNotAvailableException { 82 final ITestDevice device = mDevice; 83 84 // Create an install session 85 final StringBuilder cmd = new StringBuilder(); 86 cmd.append("pm install-create"); 87 for (String arg : mArgs) { 88 cmd.append(' ').append(arg); 89 } 90 91 String result = device.executeShellCommand(cmd.toString()); 92 TestCase.assertTrue(result, result.startsWith("Success")); 93 94 final int start = result.lastIndexOf("["); 95 final int end = result.lastIndexOf("]"); 96 int sessionId = -1; 97 try { 98 if (start != -1 && end != -1 && start < end) { 99 sessionId = Integer.parseInt(result.substring(start + 1, end)); 100 } 101 } catch (NumberFormatException e) { 102 throw new IllegalStateException("Failed to parse install session: " + result); 103 } 104 if (sessionId == -1) { 105 throw new IllegalStateException("Failed to create install session: " + result); 106 } 107 108 // Push our files into session. Ideally we'd use stdin streaming, 109 // but ddmlib doesn't support it yet. 110 for (final Map.Entry<File, String> entry : mFileToRemoteMap.entrySet()) { 111 final File file = entry.getKey(); 112 final String remoteName = entry.getValue(); 113 final String remotePath = "/data/local/tmp/" + file.getName(); 114 if (!device.pushFile(file, remotePath)) { 115 throw new IllegalStateException("Failed to push " + file); 116 } 117 118 cmd.setLength(0); 119 cmd.append("pm install-write"); 120 cmd.append(' ').append(sessionId); 121 cmd.append(' ').append(remoteName); 122 cmd.append(' ').append(remotePath); 123 124 result = device.executeShellCommand(cmd.toString()); 125 TestCase.assertTrue(result, result.startsWith("Success")); 126 } 127 128 // Everything staged; let's pull trigger 129 cmd.setLength(0); 130 cmd.append("pm install-commit"); 131 cmd.append(' ').append(sessionId); 132 133 result = device.executeShellCommand(cmd.toString()); 134 if (expectingSuccess) { 135 TestCase.assertTrue(result, result.contains("Success")); 136 } else { 137 TestCase.assertFalse(result, result.contains("Success")); 138 } 139 } 140 } 141