1 /* 2 * Copyright (C) 2013 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.build; 18 19 import com.android.tradefed.config.Option; 20 import com.android.tradefed.config.OptionClass; 21 import com.android.tradefed.device.DeviceNotAvailableException; 22 import com.android.tradefed.device.ITestDevice; 23 import com.android.tradefed.device.StubDevice; 24 import com.android.tradefed.log.LogUtil.CLog; 25 import com.android.tradefed.util.FileUtil; 26 27 import java.io.File; 28 import java.io.IOException; 29 30 /** 31 * A {@link IDeviceBuildProvider} that bootstraps build info from the test device 32 * 33 * <p> 34 * This is typically used for devices with an externally supplied build, i.e. not generated by 35 * in-house build system. Certain information, specifically the branch, is not actually available 36 * from the device, therefore it's artificially generated. 37 * 38 * <p>All build meta data info comes from various ro.* property fields on device 39 * 40 * <p>Currently this build provider generates meta data as follows: 41 * <ul> 42 * <li>branch: 43 * $(ro.product.brand)-$(ro.product.name)-$(ro.product.device)-$(ro.build.version.release), 44 * for example: 45 * <ul> 46 * <li>for Google Play edition Samsung S4 running Android 4.2: samsung-jgedlteue-jgedlte-4.2 47 * <li>for Nexus 7 running Android 4.2: google-nakasi-grouper-4.2 48 * </ul> 49 * <li>build flavor: as provided by {@link ITestDevice#getBuildFlavor()} 50 * <li>build alias: as provided by {@link ITestDevice#getBuildAlias()} 51 * <li>build id: as provided by {@link ITestDevice#getBuildId()} 52 */ 53 @OptionClass(alias = "bootstrap-build") 54 public class BootstrapBuildProvider implements IDeviceBuildProvider { 55 56 @Option(name="build-target", description="build target name to supply.") 57 private String mBuildTargetName = "bootstrapped"; 58 59 @Option(name="branch", description="build branch name to supply.") 60 private String mBranch = null; 61 62 @Option( 63 name = "build-id", 64 description = "Specify the build id to report instead of the one from the device." 65 ) 66 private String mBuildId = null; 67 68 @Option(name="shell-available-timeout", 69 description="Time to wait in seconds for device shell to become available. " + 70 "Default to 300 seconds.") 71 private long mShellAvailableTimeout = 5 * 60; 72 73 @Option(name="tests-dir", description="Path to top directory of expanded tests zip") 74 private File mTestsDir = null; 75 76 private boolean mCreatedTestDir = false; 77 78 @Override getBuild()79 public IBuildInfo getBuild() throws BuildRetrievalError { 80 throw new UnsupportedOperationException("Call getBuild(ITestDevice)"); 81 } 82 83 @Override buildNotTested(IBuildInfo info)84 public void buildNotTested(IBuildInfo info) { 85 // no op 86 CLog.i("ignoring buildNotTested call, build = %s ", info.getBuildId()); 87 } 88 89 @Override cleanUp(IBuildInfo info)90 public void cleanUp(IBuildInfo info) { 91 // If we created the tests dir, we delete it. 92 if (mCreatedTestDir) { 93 FileUtil.recursiveDelete(((IDeviceBuildInfo) info).getTestsDir()); 94 } 95 } 96 97 @Override getBuild(ITestDevice device)98 public IBuildInfo getBuild(ITestDevice device) throws BuildRetrievalError, 99 DeviceNotAvailableException { 100 String buildId = mBuildId; 101 // If mBuildId is set, do not use the device build-id 102 if (buildId == null) { 103 buildId = device.getBuildId(); 104 } 105 IBuildInfo info = new DeviceBuildInfo(buildId, mBuildTargetName); 106 if (!(device.getIDevice() instanceof StubDevice)) { 107 if (!device.waitForDeviceShell(mShellAvailableTimeout * 1000)) { 108 throw new DeviceNotAvailableException( 109 String.format( 110 "Shell did not become available in %d seconds", 111 mShellAvailableTimeout), 112 device.getSerialNumber()); 113 } 114 if (mBranch == null) { 115 mBranch = 116 String.format( 117 "%s-%s-%s-%s", 118 device.getProperty("ro.product.brand"), 119 device.getProperty("ro.product.name"), 120 device.getProductVariant(), 121 device.getProperty("ro.build.version.release")); 122 } 123 } else { 124 // In order to avoid issue with a null branch, use a placeholder stub for StubDevice. 125 mBranch = "stub"; 126 } 127 info.setBuildBranch(mBranch); 128 info.setBuildFlavor(device.getBuildFlavor()); 129 info.addBuildAttribute("build_alias", device.getBuildAlias()); 130 if (mTestsDir != null && mTestsDir.isDirectory()) { 131 info.setFile("testsdir", mTestsDir, buildId); 132 } 133 // Avoid tests dir being null, by creating a temporary dir. 134 if (mTestsDir == null) { 135 mCreatedTestDir = true; 136 try { 137 mTestsDir = FileUtil.createTempDir("bootstrap-test-dir"); 138 } catch (IOException e) { 139 throw new BuildRetrievalError(e.getMessage(), e); 140 } 141 ((IDeviceBuildInfo) info).setTestsDir(mTestsDir, "1"); 142 } 143 return info; 144 } 145 } 146