Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
      5  * use this file except in compliance with the License. You may obtain a copy
      6  * 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, WITHOUT
     12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     13  * License for the specific language governing permissions and limitations
     14  * under the License.
     15  */
     16 package android.appsecurity.cts;
     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 import com.android.tradefed.testtype.IAbi;
     23 import com.android.tradefed.util.AbiUtils;
     24 
     25 import junit.framework.TestCase;
     26 
     27 import java.io.File;
     28 import java.io.FileNotFoundException;
     29 import java.util.ArrayList;
     30 import java.util.List;
     31 
     32 /**
     33  * Base class for invoking the install-multiple command via ADB. Subclass this for less typing:
     34  *
     35  * <code>
     36  *     private class InstallMultiple extends BaseInstallMultiple&lt;InstallMultiple&gt; {
     37  *         public InstallMultiple() {
     38  *             super(getDevice(), null, null);
     39  *         }
     40  *     }
     41  * </code>
     42  */
     43 public class BaseInstallMultiple<T extends BaseInstallMultiple<?>> {
     44     private final ITestDevice mDevice;
     45     private final IBuildInfo mBuild;
     46     private final IAbi mAbi;
     47 
     48     private final List<String> mArgs = new ArrayList<>();
     49     private final List<File> mApks = new ArrayList<>();
     50     private final List<String> mSplits = new ArrayList<>();
     51     private boolean mUseNaturalAbi;
     52 
     53     public BaseInstallMultiple(ITestDevice device, IBuildInfo buildInfo, IAbi abi) {
     54         mDevice = device;
     55         mBuild = buildInfo;
     56         mAbi = abi;
     57         addArg("-g");
     58     }
     59 
     60     T addArg(String arg) {
     61         mArgs.add(arg);
     62         return (T) this;
     63     }
     64 
     65     T addApk(String apk) throws FileNotFoundException {
     66         CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild);
     67         mApks.add(buildHelper.getTestFile(apk));
     68         return (T) this;
     69     }
     70 
     71     T removeSplit(String split) {
     72         mSplits.add(split);
     73         return (T) this;
     74     }
     75 
     76     T inheritFrom(String packageName) {
     77         addArg("-r");
     78         addArg("-p " + packageName);
     79         return (T) this;
     80     }
     81 
     82     T useNaturalAbi() {
     83         mUseNaturalAbi = true;
     84         return (T) this;
     85     }
     86 
     87     T allowTest() {
     88         addArg("-t");
     89         return (T) this;
     90     }
     91 
     92     T locationAuto() {
     93         addArg("--install-location 0");
     94         return (T) this;
     95     }
     96 
     97     T locationInternalOnly() {
     98         addArg("--install-location 1");
     99         return (T) this;
    100     }
    101 
    102     T locationPreferExternal() {
    103         addArg("--install-location 2");
    104         return (T) this;
    105     }
    106 
    107     T forceUuid(String uuid) {
    108         addArg("--force-uuid " + uuid);
    109         return (T) this;
    110     }
    111 
    112     T forUser(int userId) {
    113         addArg("--user " + userId);
    114         return (T) this;
    115     }
    116 
    117     void run() throws DeviceNotAvailableException {
    118         run(true, null);
    119     }
    120 
    121     void runExpectingFailure() throws DeviceNotAvailableException {
    122         run(false, null);
    123     }
    124 
    125     void runExpectingFailure(String failure) throws DeviceNotAvailableException {
    126         run(false, failure);
    127     }
    128 
    129     private void run(boolean expectingSuccess, String failure) throws DeviceNotAvailableException {
    130         final ITestDevice device = mDevice;
    131 
    132         // Create an install session
    133         final StringBuilder cmd = new StringBuilder();
    134         cmd.append("pm install-create");
    135         for (String arg : mArgs) {
    136             cmd.append(' ').append(arg);
    137         }
    138         if (!mUseNaturalAbi && mAbi != null) {
    139             cmd.append(' ').append(AbiUtils.createAbiFlag(mAbi.getName()));
    140         }
    141 
    142         String result = device.executeShellCommand(cmd.toString());
    143         TestCase.assertTrue(result, result.startsWith("Success"));
    144 
    145         final int start = result.lastIndexOf("[");
    146         final int end = result.lastIndexOf("]");
    147         int sessionId = -1;
    148         try {
    149             if (start != -1 && end != -1 && start < end) {
    150                 sessionId = Integer.parseInt(result.substring(start + 1, end));
    151             }
    152         } catch (NumberFormatException e) {
    153         }
    154         if (sessionId == -1) {
    155             throw new IllegalStateException("Failed to create install session: " + result);
    156         }
    157 
    158         // Push our files into session. Ideally we'd use stdin streaming,
    159         // but ddmlib doesn't support it yet.
    160         for (int i = 0; i < mApks.size(); i++) {
    161             final File apk = mApks.get(i);
    162             final String remotePath = "/data/local/tmp/" + i + "_" + apk.getName();
    163             if (!device.pushFile(apk, remotePath)) {
    164                 throw new IllegalStateException("Failed to push " + apk);
    165             }
    166 
    167             cmd.setLength(0);
    168             cmd.append("pm install-write");
    169             cmd.append(' ').append(sessionId);
    170             cmd.append(' ').append(i + "_" + apk.getName());
    171             cmd.append(' ').append(remotePath);
    172 
    173             result = device.executeShellCommand(cmd.toString());
    174             TestCase.assertTrue(result, result.startsWith("Success"));
    175         }
    176 
    177         for (int i = 0; i < mSplits.size(); i++) {
    178             final String split = mSplits.get(i);
    179 
    180             cmd.setLength(0);
    181             cmd.append("pm install-remove");
    182             cmd.append(' ').append(sessionId);
    183             cmd.append(' ').append(split);
    184 
    185             result = device.executeShellCommand(cmd.toString());
    186             TestCase.assertTrue(result, result.startsWith("Success"));
    187         }
    188 
    189         // Everything staged; let's pull trigger
    190         cmd.setLength(0);
    191         cmd.append("pm install-commit");
    192         cmd.append(' ').append(sessionId);
    193 
    194         result = device.executeShellCommand(cmd.toString()).trim();
    195         if (failure == null) {
    196             if (expectingSuccess) {
    197                 TestCase.assertTrue(result, result.startsWith("Success"));
    198             } else {
    199                 TestCase.assertFalse(result, result.startsWith("Success"));
    200             }
    201         } else {
    202             TestCase.assertTrue(result, result.contains(failure));
    203         }
    204     }
    205 }
    206