Home | History | Annotate | Download | only in targetprep
      1 /*
      2  * Copyright (C) 2011 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 com.android.tradefed.targetprep;
     18 
     19 import com.android.ddmlib.Log;
     20 import com.android.tradefed.build.IBuildInfo;
     21 import com.android.tradefed.config.Option;
     22 import com.android.tradefed.config.Option.Importance;
     23 import com.android.tradefed.config.OptionClass;
     24 import com.android.tradefed.device.CollectingOutputReceiver;
     25 import com.android.tradefed.device.DeviceNotAvailableException;
     26 import com.android.tradefed.device.ITestDevice;
     27 import com.android.tradefed.log.LogUtil.CLog;
     28 import com.android.tradefed.util.AbiFormatter;
     29 import com.google.common.annotations.VisibleForTesting;
     30 
     31 import java.io.File;
     32 import java.util.ArrayList;
     33 import java.util.Collection;
     34 import java.util.List;
     35 import java.util.concurrent.TimeUnit;
     36 
     37 /**
     38  * A {@link ITargetPreparer} that installs one or more apks located on the filesystem.
     39  *
     40  * <p>This class should only be used for installing apks from the filesystem when all versions of
     41  * the test rely on the apk being on the filesystem. For tests which use {@link TestAppInstallSetup}
     42  * to install apks from the tests zip file, use {@code --alt-dir} to specify an alternate directory
     43  * on the filesystem containing the apk for other test configurations (for example, local runs where
     44  * the tests zip file is not present).
     45  */
     46 @OptionClass(alias = "install-apk")
     47 public class InstallApkSetup extends BaseTargetPreparer {
     48 
     49     private static final String LOG_TAG = InstallApkSetup.class.getSimpleName();
     50 
     51     @Option(name = "apk-path", description =
     52             "the filesystem path of the apk to install. Can be repeated.",
     53             importance = Importance.IF_UNSET)
     54     private Collection<File> mApkPaths = new ArrayList<File>();
     55 
     56     @Option(name = AbiFormatter.FORCE_ABI_STRING,
     57             description = AbiFormatter.FORCE_ABI_DESCRIPTION,
     58             importance = Importance.IF_UNSET)
     59     private String mForceAbi = null;
     60 
     61     @Option(name = "install-arg",
     62             description = "Additional arguments to be passed to install command, "
     63                     + "including leading dash, e.g. \"-d\"")
     64     private Collection<String> mInstallArgs = new ArrayList<>();
     65 
     66     @Option(name = "post-install-cmd", description =
     67             "optional post-install adb shell commands; can be repeated.")
     68     private List<String> mPostInstallCmds = new ArrayList<>();
     69 
     70     @Option(name = "post-install-cmd-timeout", description =
     71             "max time allowed in ms for a post-install adb shell command." +
     72                     "DeviceUnresponsiveException will be thrown if it is timed out.")
     73     private long mPostInstallCmdTimeout = 2 * 60 * 1000;  // default to 2 minutes
     74 
     75     @Option(name = "throw-if-install-fail", description =
     76             "Throw exception if the APK installation failed due to any reason.")
     77     private boolean mThrowIfInstallFail = false;
     78 
     79     /**
     80      * {@inheritDoc}
     81      */
     82     @Override
     83     public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
     84             BuildError, DeviceNotAvailableException {
     85         for (File apk : mApkPaths) {
     86             if (!apk.exists()) {
     87                 throw new TargetSetupError(String.format("%s does not exist",
     88                         apk.getAbsolutePath()), device.getDeviceDescriptor());
     89             }
     90             Log.i(LOG_TAG, String.format("Installing %s on %s", apk.getName(),
     91                     device.getSerialNumber()));
     92             if (mForceAbi != null) {
     93                 String abi = AbiFormatter.getDefaultAbi(device, mForceAbi);
     94                 if (abi != null) {
     95                     mInstallArgs.add(String.format("--abi %s", abi));
     96                 }
     97             }
     98             String result = device.installPackage(apk, true, mInstallArgs.toArray(new String[]{}));
     99             if (result != null) {
    100                 if (mThrowIfInstallFail) {
    101                     throw new TargetSetupError(String.format(
    102                             "Stopping test: failed to install %s on device %s. Reason: %s",
    103                             apk.getAbsolutePath(), device.getSerialNumber(), result),
    104                             device.getDeviceDescriptor());
    105                 }
    106                 Log.e(LOG_TAG, String.format("Failed to install %s on device %s. Reason: %s",
    107                         apk.getAbsolutePath(), device.getSerialNumber(), result));
    108             }
    109         }
    110 
    111         if (mPostInstallCmds != null && !mPostInstallCmds.isEmpty()) {
    112             for (String cmd : mPostInstallCmds) {
    113                 // If the command had any output, the executeShellCommand method will log it at the
    114                 // VERBOSE level; so no need to do any logging from here.
    115                 CLog.d("About to run setup command on device %s: %s",
    116                         device.getSerialNumber(), cmd);
    117                 device.executeShellCommand(cmd, new CollectingOutputReceiver(),
    118                         mPostInstallCmdTimeout, TimeUnit.MILLISECONDS, 1);
    119             }
    120         }
    121     }
    122 
    123     protected Collection<File> getApkPaths() {
    124         return mApkPaths;
    125     }
    126 
    127     /**
    128      * Sets APK paths. Exposed for testing.
    129      */
    130     @VisibleForTesting
    131     public void setApkPaths(Collection<File> paths) {
    132         mApkPaths = paths;
    133     }
    134 
    135     /**
    136      * Set throw if install fail. Exposed for testing.
    137      */
    138     @VisibleForTesting
    139     public void setThrowIfInstallFail(boolean throwIfInstallFail) {
    140         mThrowIfInstallFail = throwIfInstallFail;
    141     }
    142 }
    143