1 /* 2 * Copyright (C) 2016 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.device; 17 18 import com.android.annotations.VisibleForTesting; 19 import com.android.ddmlib.IDevice; 20 import com.android.tradefed.device.DeviceManager.FastbootDevice; 21 import com.android.tradefed.device.IDeviceSelection.BaseDeviceType; 22 import com.android.tradefed.device.cloud.ManagedRemoteDevice; 23 import com.android.tradefed.device.cloud.NestedDeviceStateMonitor; 24 import com.android.tradefed.device.cloud.NestedRemoteDevice; 25 import com.android.tradefed.device.cloud.RemoteAndroidVirtualDevice; 26 import com.android.tradefed.device.cloud.VmRemoteDevice; 27 import com.android.tradefed.util.IRunUtil; 28 import com.android.tradefed.util.RunUtil; 29 import com.android.tradefed.util.SystemUtil; 30 31 import java.util.Arrays; 32 import java.util.HashSet; 33 import java.util.Set; 34 import java.util.regex.Matcher; 35 import java.util.regex.Pattern; 36 37 /** 38 * Factory to create the different kind of devices that can be monitored by Tf 39 */ 40 public class ManagedTestDeviceFactory implements IManagedTestDeviceFactory { 41 42 public static final String NOTIFY_AS_NATIVE = "NOTIFY_AS_NATIVE"; 43 public static final String IPADDRESS_PATTERN = 44 "((^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." 45 + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." 46 + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." 47 + "([01]?\\d\\d?|2[0-4]\\d|25[0-5]))|(localhost)){1}"; 48 49 protected boolean mFastbootEnabled; 50 protected IDeviceManager mDeviceManager; 51 protected IDeviceMonitor mAllocationMonitor; 52 protected static final String CHECK_PM_CMD = "ls %s"; 53 protected static final String EXPECTED_RES = "/system/bin/pm"; 54 protected static final String EXPECTED_ERROR = "No such file or directory"; 55 protected static final long FRAMEWORK_CHECK_SLEEP_MS = 500; 56 protected static final int FRAMEWORK_CHECK_MAX_RETRY = 3; 57 ManagedTestDeviceFactory(boolean fastbootEnabled, IDeviceManager deviceManager, IDeviceMonitor allocationMonitor)58 public ManagedTestDeviceFactory(boolean fastbootEnabled, IDeviceManager deviceManager, 59 IDeviceMonitor allocationMonitor) { 60 mFastbootEnabled = fastbootEnabled; 61 mDeviceManager = deviceManager; 62 mAllocationMonitor = allocationMonitor; 63 } 64 65 @Override createRequestedDevice(IDevice idevice, IDeviceSelection options)66 public IManagedTestDevice createRequestedDevice(IDevice idevice, IDeviceSelection options) { 67 IManagedTestDevice testDevice = null; 68 if (BaseDeviceType.NATIVE_DEVICE.equals(options.getBaseDeviceTypeRequested())) { 69 testDevice = 70 new NativeDevice( 71 idevice, 72 new NativeDeviceStateMonitor(mDeviceManager, idevice, mFastbootEnabled), 73 mAllocationMonitor); 74 testDevice.setDeviceState(TestDeviceState.NOT_AVAILABLE); 75 } else { 76 // Default to-go device is Android full stack device. 77 testDevice = 78 new TestDevice( 79 idevice, 80 new DeviceStateMonitor(mDeviceManager, idevice, mFastbootEnabled), 81 mAllocationMonitor); 82 testDevice.setDeviceState(TestDeviceState.NOT_AVAILABLE); 83 } 84 return testDevice; 85 } 86 87 /** 88 * {@inheritDoc} 89 */ 90 @Override createDevice(IDevice idevice)91 public IManagedTestDevice createDevice(IDevice idevice) { 92 IManagedTestDevice testDevice = null; 93 if (idevice instanceof VmRemoteDevice) { 94 testDevice = 95 new ManagedRemoteDevice( 96 idevice, 97 new DeviceStateMonitor(mDeviceManager, idevice, mFastbootEnabled), 98 mAllocationMonitor); 99 testDevice.setDeviceState(TestDeviceState.NOT_AVAILABLE); 100 } else if (idevice instanceof RemoteAvdIDevice) { 101 testDevice = 102 new RemoteAndroidVirtualDevice( 103 idevice, 104 new DeviceStateMonitor(mDeviceManager, idevice, mFastbootEnabled), 105 mAllocationMonitor); 106 testDevice.setDeviceState(TestDeviceState.NOT_AVAILABLE); 107 } else if (idevice instanceof StubLocalAndroidVirtualDevice) { 108 // Virtual device to be launched by TradeFed locally. 109 testDevice = 110 new LocalAndroidVirtualDevice( 111 idevice, 112 new DeviceStateMonitor(mDeviceManager, idevice, mFastbootEnabled), 113 mAllocationMonitor); 114 } else if (isTcpDeviceSerial(idevice.getSerialNumber())) { 115 if (isRemoteEnvironment()) { 116 // If we are in a remote environment, treat the device as such 117 testDevice = 118 new NestedRemoteDevice( 119 idevice, 120 new NestedDeviceStateMonitor( 121 mDeviceManager, idevice, mFastbootEnabled), 122 mAllocationMonitor); 123 } else { 124 Set<String> nativeSerials = new HashSet<>(); 125 if (System.getenv(NOTIFY_AS_NATIVE) != null) { 126 nativeSerials.addAll(Arrays.asList(System.getenv(NOTIFY_AS_NATIVE).split(","))); 127 } 128 if (nativeSerials.contains(idevice.getSerialNumber())) { 129 testDevice = 130 new NativeDevice( 131 idevice, 132 new NativeDeviceStateMonitor( 133 mDeviceManager, idevice, mFastbootEnabled), 134 mAllocationMonitor); 135 } else { 136 // Handle device connected via 'adb connect' 137 testDevice = 138 new RemoteAndroidDevice( 139 idevice, 140 new DeviceStateMonitor( 141 mDeviceManager, idevice, mFastbootEnabled), 142 mAllocationMonitor); 143 testDevice.setDeviceState(TestDeviceState.NOT_AVAILABLE); 144 } 145 } 146 } else { 147 // Default to-go device is Android full stack device. 148 testDevice = new TestDevice(idevice, 149 new DeviceStateMonitor(mDeviceManager, idevice, mFastbootEnabled), 150 mAllocationMonitor); 151 } 152 153 if (idevice instanceof FastbootDevice) { 154 if (((FastbootDevice) idevice).isFastbootD()) { 155 testDevice.setDeviceState(TestDeviceState.FASTBOOTD); 156 } else { 157 testDevice.setDeviceState(TestDeviceState.FASTBOOT); 158 } 159 } else if (idevice instanceof StubDevice) { 160 testDevice.setDeviceState(TestDeviceState.NOT_AVAILABLE); 161 } 162 testDevice.setFastbootEnabled(mFastbootEnabled); 163 testDevice.setFastbootPath(mDeviceManager.getFastbootPath()); 164 return testDevice; 165 } 166 167 /** Return the default {@link IRunUtil} instance. */ 168 @VisibleForTesting getRunUtil()169 protected IRunUtil getRunUtil() { 170 return RunUtil.getDefault(); 171 } 172 173 /** 174 * Return true if we are currently running in a remote environment. This will alter the device 175 * behavior. 176 */ 177 @VisibleForTesting isRemoteEnvironment()178 protected boolean isRemoteEnvironment() { 179 return SystemUtil.isRemoteEnvironment(); 180 } 181 182 /** Create a {@link CollectingOutputReceiver}. */ 183 @VisibleForTesting createOutputReceiver()184 protected CollectingOutputReceiver createOutputReceiver() { 185 return new CollectingOutputReceiver(); 186 } 187 188 /** 189 * {@inheritDoc} 190 */ 191 @Override setFastbootEnabled(boolean enable)192 public void setFastbootEnabled(boolean enable) { 193 mFastbootEnabled = enable; 194 } 195 196 /** 197 * Helper to device if it's a serial from a remotely connected device. serial format of tcp 198 * device is <ip or locahost>:<port> 199 */ isTcpDeviceSerial(String serial)200 public static boolean isTcpDeviceSerial(String serial) { 201 final String remotePattern = IPADDRESS_PATTERN + "(:)([0-9]{2,5})(\\b)"; 202 Pattern pattern = Pattern.compile(remotePattern); 203 Matcher match = pattern.matcher(serial.trim()); 204 if (match.find()) { 205 return true; 206 } 207 return false; 208 } 209 } 210