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