1 /* 2 * Copyright (C) 2012 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.targetprep; 17 18 import com.android.tradefed.config.Option; 19 import com.android.tradefed.config.OptionClass; 20 import com.android.tradefed.dependencies.ExternalDependency; 21 import com.android.tradefed.dependencies.IExternalDependency; 22 import com.android.tradefed.dependencies.connectivity.NetworkDependency; 23 import com.android.tradefed.device.DeviceNotAvailableException; 24 import com.android.tradefed.device.ITestDevice; 25 import com.android.tradefed.device.LocalAndroidVirtualDevice; 26 import com.android.tradefed.device.cloud.NestedRemoteDevice; 27 import com.android.tradefed.device.cloud.RemoteAndroidVirtualDevice; 28 import com.android.tradefed.invoker.TestInformation; 29 import com.android.tradefed.invoker.logger.InvocationMetricLogger; 30 import com.android.tradefed.invoker.logger.InvocationMetricLogger.InvocationMetricKey; 31 import com.android.tradefed.log.LogUtil.CLog; 32 import com.android.tradefed.result.error.InfraErrorIdentifier; 33 34 import com.google.common.base.Strings; 35 36 import java.util.LinkedHashSet; 37 import java.util.Set; 38 39 /** 40 * A {@link ITargetPreparer} that configures wifi on the device if necessary. 41 * 42 * <p>Unlike {@link DeviceSetup}, this preparer works when adb is not root aka user builds. 43 */ 44 @OptionClass(alias = "wifi") 45 public class WifiPreparer extends BaseTargetPreparer implements IExternalDependency { 46 47 @Option(name="wifi-network", description="the name of wifi network to connect to.") 48 private String mWifiNetwork = null; 49 50 @Option(name="wifi-psk", description="WPA-PSK passphrase of wifi network to connect to.") 51 private String mWifiPsk = null; 52 53 @Option(name = "disconnect-wifi-after-test", description = 54 "disconnect from wifi network after test completes.") 55 private boolean mDisconnectWifiAfterTest = true; 56 57 @Option(name = "monitor-network", description = 58 "monitor network connectivity during test.") 59 private boolean mMonitorNetwork = true; 60 61 @Option(name = "skip", description = "skip the connectivity check and wifi setup") 62 private boolean mSkip = false; 63 64 @Option(name = "verify-only", description = "Skip setup and verify a wifi connection.") 65 private boolean mVerifyOnly = false; 66 67 /** {@inheritDoc} */ 68 @Override setUp(TestInformation testInfo)69 public void setUp(TestInformation testInfo) 70 throws TargetSetupError, BuildError, DeviceNotAvailableException { 71 if (mSkip) { 72 return; 73 } 74 ITestDevice device = testInfo.getDevice(); 75 if (mVerifyOnly) { 76 if (!device.isWifiEnabled()) { 77 throw new TargetSetupError( 78 "The device does not have wifi enabled.", 79 device.getDeviceDescriptor(), 80 InfraErrorIdentifier.NO_WIFI); 81 } else if (!device.checkConnectivity()) { 82 throw new TargetSetupError( 83 "The device has no wifi connection.", 84 device.getDeviceDescriptor(), 85 InfraErrorIdentifier.NO_WIFI); 86 } 87 return; 88 } 89 90 if (mWifiNetwork == null) { 91 throw new TargetSetupError( 92 "wifi-network not specified", 93 device.getDeviceDescriptor(), 94 InfraErrorIdentifier.OPTION_CONFIGURATION_ERROR); 95 } 96 97 InvocationMetricLogger.addInvocationMetrics(InvocationMetricKey.WIFI_AP_NAME, mWifiNetwork); 98 if (!device.connectToWifiNetworkIfNeeded(mWifiNetwork, mWifiPsk)) { 99 InfraErrorIdentifier errorIdentifier = InfraErrorIdentifier.WIFI_FAILED_CONNECT; 100 if (device instanceof RemoteAndroidVirtualDevice 101 || device instanceof NestedRemoteDevice 102 || device instanceof LocalAndroidVirtualDevice) { 103 // Error identifier for virtual devices. 104 errorIdentifier = InfraErrorIdentifier.VIRTUAL_WIFI_FAILED_CONNECT; 105 } 106 throw new TargetSetupError( 107 String.format( 108 "Failed to connect to wifi network %s on %s", 109 mWifiNetwork, device.getSerialNumber()), 110 device.getDeviceDescriptor(), 111 errorIdentifier); 112 } 113 if (mMonitorNetwork) { 114 device.enableNetworkMonitor(); 115 } 116 } 117 118 /** {@inheritDoc} */ 119 @Override tearDown(TestInformation testInfo, Throwable e)120 public void tearDown(TestInformation testInfo, Throwable e) throws DeviceNotAvailableException { 121 if (mSkip || mVerifyOnly) { 122 return; 123 } 124 ITestDevice device = testInfo.getDevice(); 125 if (e instanceof DeviceFailedToBootError) { 126 CLog.d("boot failure: skipping wifi teardown"); 127 return; 128 } 129 if (e instanceof DeviceNotAvailableException) { 130 CLog.d("device is not available. skipping wifi teardown"); 131 return; 132 } 133 134 if (mMonitorNetwork) { 135 device.disableNetworkMonitor(); 136 } 137 138 if (mWifiNetwork != null && mDisconnectWifiAfterTest && device.isWifiEnabled()) { 139 if (!device.disconnectFromWifi()) { 140 CLog.w("Failed to disconnect from wifi network on %s", device.getSerialNumber()); 141 return; 142 } 143 CLog.i("Successfully disconnected from wifi network on %s", device.getSerialNumber()); 144 } 145 } 146 147 @Override getDependencies()148 public Set<ExternalDependency> getDependencies() { 149 Set<ExternalDependency> externalDependencies = new LinkedHashSet<>(); 150 if (!mSkip && (mVerifyOnly || !Strings.isNullOrEmpty(mWifiNetwork))) { 151 externalDependencies.add(new NetworkDependency()); 152 } 153 return externalDependencies; 154 } 155 } 156