1 /* 2 * Copyright (C) 2017 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.compatibility.common.tradefed.targetprep; 18 19 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper; 20 import com.android.compatibility.common.tradefed.testtype.CompatibilityTest; 21 import com.android.tradefed.build.IBuildInfo; 22 import com.android.tradefed.config.Option; 23 import com.android.tradefed.device.DeviceNotAvailableException; 24 import com.android.tradefed.device.ITestDevice; 25 import com.android.tradefed.log.LogUtil.CLog; 26 27 import java.nio.file.Paths; 28 import java.io.File; 29 import java.io.FileNotFoundException; 30 import java.util.Map; 31 import java.util.HashMap; 32 33 /** 34 * An {@link PreconditionPreparer} that collects one device file. 35 */ 36 public class DeviceFileCollector extends PreconditionPreparer { 37 38 @Option(name = CompatibilityTest.SKIP_DEVICE_INFO_OPTION, 39 shortName = 'd', 40 description = "Whether device info collection should be skipped") 41 private boolean mSkipDeviceInfo = false; 42 43 @Option(name = "src-file", description = "The file path to copy to the results dir") 44 private String mSrcFile; 45 46 @Option(name = "dest-file", description = "The destination file path under the result") 47 private String mDestFile; 48 49 /** 50 * If device.getProperty(key) is not value for all properties listed, the collection will be 51 * skipped. If this map is empty, mSrcFile will always be collected. 52 * 53 * This can be specified by the following option: 54 * {@code <option name="property" key="foo" value="bar"/>} 55 */ 56 @Option(name = "property", description = "run this test on device with this property value") 57 private Map<String, String> mPropertyMap = new HashMap<>(); 58 59 private File mResultFile; 60 61 /** 62 * {@inheritDoc} 63 */ 64 @Override 65 public void run(ITestDevice device, IBuildInfo buildInfo) { 66 if (mSkipDeviceInfo) 67 return; 68 69 if (!matchProperties(device)) 70 return; 71 72 createResultDir(buildInfo); 73 if (mResultFile != null && !mResultFile.isDirectory() && 74 mSrcFile != null && !mSrcFile.isEmpty()) { 75 76 try { 77 if (device.doesFileExist(mSrcFile)) { 78 device.pullFile(mSrcFile, mResultFile); 79 } else { 80 CLog.w(String.format("File does not exist on device: \"%s\"", mSrcFile)); 81 } 82 } catch (DeviceNotAvailableException e) { 83 CLog.e("Caught exception during pull."); 84 CLog.e(e); 85 } 86 } 87 } 88 89 private void createResultDir(IBuildInfo buildInfo) { 90 CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(buildInfo); 91 try { 92 File resultDir = buildHelper.getResultDir(); 93 if (mDestFile == null || mDestFile.isEmpty()) { 94 mDestFile = Paths.get(mSrcFile).getFileName().toString(); 95 } 96 mResultFile = Paths.get(resultDir.getAbsolutePath(), mDestFile).toFile(); 97 resultDir = mResultFile.getParentFile(); 98 resultDir.mkdirs(); 99 if (!resultDir.isDirectory()) { 100 CLog.e("%s is not a directory", resultDir.getAbsolutePath()); 101 return; 102 } 103 } catch (FileNotFoundException fnfe) { 104 fnfe.printStackTrace(); 105 } 106 } 107 108 private boolean matchProperties(ITestDevice device) { 109 for (Map.Entry<String, String> propEntry : mPropertyMap.entrySet()) { 110 try { 111 String actualValue = device.getProperty(propEntry.getKey()); 112 if (!propEntry.getValue().equals(actualValue)) { 113 CLog.i("Skipping '%s' because property doesn't match. " 114 + "(key=%s, expected=%s, actual=%s)", 115 mSrcFile, propEntry.getKey(), propEntry.getValue(), actualValue); 116 return false; 117 } 118 } catch (DeviceNotAvailableException e) { 119 CLog.e("Caught exception during property check."); 120 CLog.e(e); 121 return false; 122 } 123 } 124 return true; 125 } 126 } 127