Home | History | Annotate | Download | only in build
      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 package com.android.tradefed.build;
     17 
     18 import com.android.tradefed.config.Option;
     19 import com.android.tradefed.config.OptionClass;
     20 import com.android.tradefed.log.LogUtil.CLog;
     21 import com.android.tradefed.targetprep.FlashingResourcesParser;
     22 import com.android.tradefed.targetprep.IFlashingResourcesParser;
     23 import com.android.tradefed.targetprep.TargetSetupError;
     24 import com.android.tradefed.util.SystemUtil;
     25 import com.android.tradefed.util.ZipUtil;
     26 
     27 import com.google.common.annotations.VisibleForTesting;
     28 import com.google.common.io.PatternFilenameFilter;
     29 
     30 import java.io.File;
     31 import java.io.IOException;
     32 import java.util.ArrayList;
     33 import java.util.Arrays;
     34 import java.util.List;
     35 
     36 /**
     37  * A {@link IBuildProvider} that constructs a {@link IDeviceBuildInfo} based on a provided
     38  * filesystem directory path.
     39  * <p/>
     40  * Specific device build files are recognized based on a configurable set of patterns.
     41  */
     42 @OptionClass(alias = "local-device-build")
     43 public class LocalDeviceBuildProvider extends StubBuildProvider {
     44 
     45     private static final String BUILD_INFO_FILE = "android-info.txt";
     46     private static final String BUILD_DIR_OPTION_NAME = "build-dir";
     47 
     48     private String mBootloaderVersion = null;
     49     private String mRadioVersion = null;
     50 
     51     @Option(name = BUILD_DIR_OPTION_NAME, description = "the directory containing device files.")
     52     private File mBuildDir = SystemUtil.getProductOutputDir();
     53 
     54     @Option(name = "device-img-pattern", description =
     55             "the regex use to find device system image zip file within --build-dir.")
     56     private String mImgPattern = ".*-img-.*\\.zip";
     57 
     58     @Option(name = "test-dir", description = "the directory containing test artifacts.")
     59     private File mTestDir = null;
     60 
     61     @Option(name = "test-dir-pattern", description =
     62             "the regex use to find optional test artifact directory within --build-dir. " +
     63             "Will be ignored if a test-dir is set.")
     64     private String mTestDirPattern = ".*-tests-.*";
     65 
     66     @Option(name = "bootloader-pattern", description =
     67             "the regex use to find device bootloader image file within --build-dir.")
     68     private String mBootloaderPattern = "bootloader.*\\.img";
     69 
     70     @Option(name = "radio-pattern", description =
     71             "the regex use to find device radio image file within --build-dir.")
     72     private String mRadioPattern = "radio.*\\.img";
     73 
     74     /**
     75      * {@inheritDoc}
     76      */
     77     @Override
     78     public IBuildInfo getBuild() throws BuildRetrievalError {
     79         if (mBuildDir == null) {
     80             throw new BuildRetrievalError(
     81                     "Product output directory is not specified. If running "
     82                             + "from a Android source tree, make sure `lunch` has been run; "
     83                             + "if outside, provide a valid path via --"
     84                             + BUILD_DIR_OPTION_NAME);
     85         }
     86         if (!mBuildDir.exists()) {
     87             throw new BuildRetrievalError(String.format("Directory '%s' does not exist. " +
     88                     "Please provide a valid path via --%s", mBuildDir.getAbsolutePath(),
     89                     BUILD_DIR_OPTION_NAME));
     90         }
     91         if (!mBuildDir.isDirectory()) {
     92             throw new BuildRetrievalError(String.format("Path '%s' is not a directory. " +
     93                     "Please provide a valid path via --%s", mBuildDir.getAbsolutePath(),
     94                     BUILD_DIR_OPTION_NAME));
     95         }
     96         CLog.d("Using device build files from %s", mBuildDir.getAbsolutePath());
     97 
     98         BuildInfo stubBuild = (BuildInfo)super.getBuild();
     99         DeviceBuildInfo buildInfo = new DeviceBuildInfo(stubBuild.getBuildId(),
    100                 stubBuild.getBuildTargetName());
    101         buildInfo.addAllBuildAttributes(stubBuild);
    102 
    103         setDeviceImageFile(buildInfo);
    104         parseBootloaderAndRadioVersions(buildInfo);
    105         setTestsDir(buildInfo);
    106         setBootloaderImage(buildInfo);
    107         setRadioImage(buildInfo);
    108 
    109         return buildInfo;
    110     }
    111 
    112     /**
    113      * Parse bootloader and radio versions from the android build info file.
    114      *
    115      * @param buildInfo a {@link DeviceBuildInfo}
    116      * @throws BuildRetrievalError
    117      */
    118     void parseBootloaderAndRadioVersions(DeviceBuildInfo buildInfo) throws BuildRetrievalError {
    119         try {
    120             IFlashingResourcesParser flashingResourcesParser;
    121             flashingResourcesParser = new FlashingResourcesParser(
    122                     buildInfo.getDeviceImageFile());
    123             mBootloaderVersion = flashingResourcesParser.getRequiredBootloaderVersion();
    124             mRadioVersion = flashingResourcesParser.getRequiredBasebandVersion();
    125         } catch (TargetSetupError e) {
    126             throw new BuildRetrievalError("Unable parse bootloader and radio versions", e);
    127         }
    128     }
    129 
    130     /**
    131      * Find and and set matching device image file to the build.
    132      *
    133      * @param buildInfo a {@link DeviceBuildInfo} to set the device image file
    134      * @throws BuildRetrievalError
    135      */
    136     @VisibleForTesting
    137     void setDeviceImageFile(DeviceBuildInfo buildInfo) throws BuildRetrievalError {
    138         File deviceImgFile = findFileInDir(mImgPattern);
    139         if (deviceImgFile == null) {
    140             CLog.i("Unable to find build image zip on %s", mBuildDir.getAbsolutePath());
    141             deviceImgFile = createBuildImageZip();
    142             if (deviceImgFile == null) {
    143                 throw new BuildRetrievalError(String.format(
    144                         "Could not find device image file matching matching '%s' in '%s'.",
    145                         mImgPattern, mBuildDir.getAbsolutePath()));
    146             }
    147         }
    148         CLog.i("Set build image zip to %s", deviceImgFile.getAbsolutePath());
    149         buildInfo.setDeviceImageFile(deviceImgFile, buildInfo.getBuildId());
    150     }
    151 
    152     /**
    153      * Creates a build image zip file from the given build-dir
    154      *
    155      * @return the {@link File} referencing the zip output.
    156      * @throws BuildRetrievalError
    157      */
    158     @VisibleForTesting
    159     File createBuildImageZip() throws BuildRetrievalError {
    160         File zipFile = null;
    161         File[] imageFiles = mBuildDir.listFiles(new PatternFilenameFilter(".*\\.img"));
    162         File buildInfo = findFileInDir(BUILD_INFO_FILE);
    163         List<File> buildFiles = new ArrayList<>(Arrays.asList(imageFiles));
    164         buildFiles.add(buildInfo);
    165         try {
    166             zipFile = ZipUtil.createZip(buildFiles);
    167         } catch (IOException e) {
    168             throw new BuildRetrievalError("Unable to create build image zip file", e);
    169         }
    170         CLog.i("Created build image zip on: %s", zipFile.getAbsolutePath());
    171         return zipFile;
    172     }
    173 
    174     void setRadioImage(DeviceBuildInfo buildInfo) throws BuildRetrievalError {
    175         File radioImgFile = findFileInDir(mRadioPattern);
    176         if (radioImgFile != null) {
    177             buildInfo.setBasebandImage(radioImgFile, mRadioVersion);
    178         }
    179     }
    180 
    181     void setBootloaderImage(DeviceBuildInfo buildInfo) throws BuildRetrievalError {
    182         File bootloaderImgFile = findFileInDir(mBootloaderPattern);
    183         if (bootloaderImgFile != null) {
    184             buildInfo.setBootloaderImageFile(bootloaderImgFile, mBootloaderVersion);
    185         }
    186     }
    187 
    188     /**
    189      * Find and set a test directory to the build.
    190      *
    191      * @param buildInfo a {@link DeviceBuildInfo} to set the test directory
    192      * @throws BuildRetrievalError
    193      */
    194     @VisibleForTesting
    195     void setTestsDir(DeviceBuildInfo buildInfo) throws BuildRetrievalError {
    196         File testsDir = null;
    197         // If test-dir is specified, use it
    198         if (mTestDir != null) {
    199             CLog.i("Looking for tests on %s", mTestDir.getAbsolutePath());
    200             testsDir = mTestDir;
    201         } else {
    202             CLog.i("Looking for tests on %s matching %s", mBuildDir.getAbsolutePath(),
    203                     mTestDirPattern);
    204             testsDir = findFileInDir(mTestDirPattern);
    205         }
    206         if (testsDir != null) {
    207             buildInfo.setTestsDir(testsDir, buildInfo.getBuildId());
    208             CLog.d("Using test files from %s", testsDir.getAbsolutePath());
    209         }
    210     }
    211 
    212     /**
    213      * Find a matching file in the build directory.
    214      *
    215      * @param regex Regular expression to match a file
    216      * @return A matching {@link File} or null if none is found
    217      * @throws BuildRetrievalError
    218      */
    219     @VisibleForTesting
    220     File findFileInDir(String regex) throws BuildRetrievalError {
    221         return findFileInDir(regex, mBuildDir);
    222     }
    223 
    224     /**
    225      * Find a matching file in a given directory.
    226      *
    227      * @param regex Regular expression to match a file
    228      * @param dir a {@link File} referencing the directory to search
    229      * @return A matching {@link File} or null if none is found
    230      * @throws BuildRetrievalError
    231      */
    232     @VisibleForTesting
    233     File findFileInDir(String regex, File dir) throws BuildRetrievalError {
    234         File[] files = dir.listFiles(new PatternFilenameFilter(regex));
    235         if (files.length == 0) {
    236             return null;
    237         } else if (files.length > 1) {
    238             throw new BuildRetrievalError(String.format(
    239                     "Found more than one file matching '%s' in '%s'.", regex,
    240                     mBuildDir.getAbsolutePath()));
    241         }
    242         return files[0];
    243     }
    244 
    245     /**
    246      * {@inheritDoc}
    247      */
    248     @Override
    249     public void buildNotTested(IBuildInfo info) {
    250         // ignore
    251     }
    252 
    253     /**
    254      * {@inheritDoc}
    255      */
    256     @Override
    257     public void cleanUp(IBuildInfo info) {
    258         // ignore
    259     }
    260 
    261     String getBootloaderVersion() {
    262         return mBootloaderVersion;
    263     }
    264 
    265     void setBootloaderVersion(String bootloaderVersion) {
    266         mBootloaderVersion = bootloaderVersion;
    267     }
    268 
    269     String getRadioVersion() {
    270         return mRadioVersion;
    271     }
    272 
    273     void setRadioVersion(String radioVersion) {
    274         mRadioVersion = radioVersion;
    275     }
    276 
    277     File getBuildDir() {
    278         return mBuildDir;
    279     }
    280 
    281     void setBuildDir(File buildDir) {
    282         this.mBuildDir = buildDir;
    283     }
    284 
    285     File getTestDir() {
    286         return mTestDir;
    287     }
    288 
    289     void setTestDir(File testDir) {
    290         this.mTestDir = testDir;
    291     }
    292 
    293     String getTestDirPattern() {
    294         return mTestDirPattern;
    295     }
    296 
    297     void setTestDirPattern(String testDirPattern) {
    298         this.mTestDirPattern = testDirPattern;
    299     }
    300 }
    301