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 boolean mUseNaturalAbi;
     51 
     52     public BaseInstallMultiple(ITestDevice device, IBuildInfo buildInfo, IAbi abi) {
     53         mDevice = device;
     54         mBuild = buildInfo;
     55         mAbi = abi;
     56         addArg("-g");
     57     }
     58 
     59     T addArg(String arg) {
     60         mArgs.add(arg);
     61         return (T) this;
     62     }
     63 
     64     T addApk(String apk) throws FileNotFoundException {
     65         CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild);
     66         mApks.add(buildHelper.getTestFile(apk));
     67         return (T) this;
     68     }
     69 
     70     T inheritFrom(String packageName) {
     71         addArg("-r");
     72         addArg("-p " + packageName);
     73         return (T) this;
     74     }
     75 
     76     T useNaturalAbi() {
     77         mUseNaturalAbi = true;
     78         return (T) this;
     79     }
     80 
     81     T locationAuto() {
     82         addArg("--install-location 0");
     83         return (T) this;
     84     }
     85 
     86     T locationInternalOnly() {
     87         addArg("--install-location 1");
     88         return (T) this;
     89     }
     90 
     91     T locationPreferExternal() {
     92         addArg("--install-location 2");
     93         return (T) this;
     94     }
     95 
     96     T forceUuid(String uuid) {
     97         addArg("--force-uuid " + uuid);
     98         return (T) this;
     99     }
    100 
    101     void run() throws DeviceNotAvailableException {
    102         run(true);
    103     }
    104 
    105     void runExpectingFailure() throws DeviceNotAvailableException {
    106         run(false);
    107     }
    108 
    109     private void run(boolean expectingSuccess) throws DeviceNotAvailableException {
    110         final ITestDevice device = mDevice;
    111 
    112         // Create an install session
    113         final StringBuilder cmd = new StringBuilder();
    114         cmd.append("pm install-create");
    115         for (String arg : mArgs) {
    116             cmd.append(' ').append(arg);
    117         }
    118         if (!mUseNaturalAbi && mAbi != null) {
    119             cmd.append(' ').append(AbiUtils.createAbiFlag(mAbi.getName()));
    120         }
    121 
    122         String result = device.executeShellCommand(cmd.toString());
    123         TestCase.assertTrue(result, result.startsWith("Success"));
    124 
    125         final int start = result.lastIndexOf("[");
    126         final int end = result.lastIndexOf("]");
    127         int sessionId = -1;
    128         try {
    129             if (start != -1 && end != -1 && start < end) {
    130                 sessionId = Integer.parseInt(result.substring(start + 1, end));
    131             }
    132         } catch (NumberFormatException e) {
    133         }
    134         if (sessionId == -1) {
    135             throw new IllegalStateException("Failed to create install session: " + result);
    136         }
    137 
    138         // Push our files into session. Ideally we'd use stdin streaming,
    139         // but ddmlib doesn't support it yet.
    140         for (int i = 0; i < mApks.size(); i++) {
    141             final File apk = mApks.get(i);
    142             final String remotePath = "/data/local/tmp/" + i + "_" + apk.getName();
    143             if (!device.pushFile(apk, remotePath)) {
    144                 throw new IllegalStateException("Failed to push " + apk);
    145             }
    146 
    147             cmd.setLength(0);
    148             cmd.append("pm install-write");
    149             cmd.append(' ').append(sessionId);
    150             cmd.append(' ').append(i + "_" + apk.getName());
    151             cmd.append(' ').append(remotePath);
    152 
    153             result = device.executeShellCommand(cmd.toString());
    154             TestCase.assertTrue(result, result.startsWith("Success"));
    155         }
    156 
    157         // Everything staged; let's pull trigger
    158         cmd.setLength(0);
    159         cmd.append("pm install-commit");
    160         cmd.append(' ').append(sessionId);
    161 
    162         result = device.executeShellCommand(cmd.toString());
    163         if (expectingSuccess) {
    164             TestCase.assertTrue(result, result.startsWith("Success"));
    165         } else {
    166             TestCase.assertFalse(result, result.startsWith("Success"));
    167         }
    168     }
    169 }
    170