1 /* 2 * Copyright (C) 2022 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 17 package android.appenumeration.cts; 18 19 import static org.hamcrest.MatcherAssert.assertThat; 20 import static org.hamcrest.Matchers.startsWith; 21 22 import com.android.compatibility.common.util.SystemUtil; 23 24 import java.io.File; 25 import java.util.ArrayList; 26 import java.util.List; 27 28 /** 29 * A class to support the split installation via the pm command. 30 */ 31 public class InstallMultiple { 32 private final List<String> mArgs = new ArrayList<>(); 33 private final List<File> mApks = new ArrayList<>(); 34 35 /** 36 * Adds an argument to the 'pm install-create' command. 37 */ addArg(String arg)38 public InstallMultiple addArg(String arg) { 39 mArgs.add(arg); 40 return this; 41 } 42 43 /** 44 * Adds a file path of apk for the installation. 45 */ addApk(String apk)46 public InstallMultiple addApk(String apk) { 47 mApks.add(new File(apk)); 48 return this; 49 } 50 51 /** 52 * To indicate that this installation is used to add one or more split apks to an existing 53 * base apk on the device. 54 */ inheritFrom(String packageName)55 public InstallMultiple inheritFrom(String packageName) { 56 addArg("-p " + packageName); 57 return this; 58 } 59 60 /** 61 * Do not kill application while the split apks updated. 62 */ dontKill()63 public InstallMultiple dontKill() { 64 addArg("--dont-kill"); 65 return this; 66 } 67 68 /** 69 * Invokes the pm command. 70 */ run()71 public void run() { 72 final int sessionId = createSession(); 73 writeSession(sessionId); 74 commitSession(sessionId); 75 } 76 createSession()77 private int createSession() { 78 final StringBuilder cmd = new StringBuilder("pm install-create"); 79 for (String arg : mArgs) { 80 cmd.append(' ').append(arg); 81 } 82 final String result = SystemUtil.runShellCommand(cmd.toString()); 83 assertThat(result, startsWith("Success")); 84 85 final int start = result.lastIndexOf("["); 86 final int end = result.lastIndexOf("]"); 87 int sessionId = -1; 88 try { 89 if (start != -1 && end != -1 && start < end) { 90 sessionId = Integer.parseInt(result.substring(start + 1, end)); 91 } 92 } catch (NumberFormatException e) { 93 } 94 if (sessionId == -1) { 95 throw new IllegalStateException("Failed to create install session: " + result); 96 } 97 return sessionId; 98 } 99 writeSession(int sessionId)100 private void writeSession(int sessionId) { 101 for (int i = 0; i < mApks.size(); i++) { 102 final File apk = mApks.get(i); 103 final StringBuilder cmd = new StringBuilder("pm install-write"); 104 cmd.append(' ').append(sessionId); 105 cmd.append(' ').append(i + "_" + apk.getName()); 106 cmd.append(' ').append(apk.getAbsolutePath()); 107 108 final String result = SystemUtil.runShellCommand(cmd.toString()); 109 assertThat(result, startsWith("Success")); 110 } 111 } 112 commitSession(int sessionId)113 private void commitSession(int sessionId) { 114 final StringBuilder cmd = new StringBuilder("pm install-commit"); 115 cmd.append(' ').append(sessionId); 116 117 final String result = SystemUtil.runShellCommand(cmd.toString()); 118 assertThat(result, startsWith("Success")); 119 } 120 } 121