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.device.DeviceNotAvailableException;
21 import com.android.tradefed.device.ITestDevice;
22 import com.android.tradefed.invoker.TestInformation;
23 import com.android.tradefed.invoker.logger.InvocationMetricLogger;
24 import com.android.tradefed.invoker.logger.InvocationMetricLogger.InvocationMetricKey;
25 import com.android.tradefed.log.LogUtil.CLog;
26 import com.android.tradefed.result.error.InfraErrorIdentifier;
27 
28 /**
29  * A {@link ITargetPreparer} that configures wifi on the device if necessary.
30  *
31  * <p>Unlike {@link DeviceSetup}, this preparer works when adb is not root aka user builds.
32  */
33 @OptionClass(alias = "wifi")
34 public class WifiPreparer extends BaseTargetPreparer {
35 
36     @Option(name="wifi-network", description="the name of wifi network to connect to.")
37     private String mWifiNetwork = null;
38 
39     @Option(name="wifi-psk", description="WPA-PSK passphrase of wifi network to connect to.")
40     private String mWifiPsk = null;
41 
42     @Option(name = "disconnect-wifi-after-test", description =
43             "disconnect from wifi network after test completes.")
44     private boolean mDisconnectWifiAfterTest = true;
45 
46     @Option(name = "monitor-network", description =
47             "monitor network connectivity during test.")
48     private boolean mMonitorNetwork = true;
49 
50     @Option(name = "skip", description = "skip the connectivity check and wifi setup")
51     private boolean mSkip = false;
52 
53     @Option(name = "verify-only", description = "Skip setup and verify a wifi connection.")
54     private boolean mVerifyOnly = false;
55 
56     /** {@inheritDoc} */
57     @Override
setUp(TestInformation testInfo)58     public void setUp(TestInformation testInfo)
59             throws TargetSetupError, BuildError, DeviceNotAvailableException {
60         if (mSkip) {
61             return;
62         }
63         ITestDevice device = testInfo.getDevice();
64         if (mVerifyOnly) {
65             if (!device.isWifiEnabled()) {
66                 throw new TargetSetupError(
67                         "The device does not have wifi enabled.", device.getDeviceDescriptor());
68             } else if (!device.checkConnectivity()) {
69                 throw new TargetSetupError(
70                         "The device has no wifi connection.", device.getDeviceDescriptor());
71             }
72             return;
73         }
74 
75         if (mWifiNetwork == null) {
76             throw new TargetSetupError("wifi-network not specified", device.getDeviceDescriptor());
77         }
78 
79         InvocationMetricLogger.addInvocationMetrics(InvocationMetricKey.WIFI_AP_NAME, mWifiNetwork);
80         if (!device.connectToWifiNetworkIfNeeded(mWifiNetwork, mWifiPsk)) {
81             throw new TargetSetupError(
82                     String.format(
83                             "Failed to connect to wifi network %s on %s",
84                             mWifiNetwork, device.getSerialNumber()),
85                     device.getDeviceDescriptor(),
86                     InfraErrorIdentifier.WIFI_FAILED_CONNECT);
87         }
88         if (mMonitorNetwork) {
89             device.enableNetworkMonitor();
90         }
91     }
92 
93     /** {@inheritDoc} */
94     @Override
tearDown(TestInformation testInfo, Throwable e)95     public void tearDown(TestInformation testInfo, Throwable e) throws DeviceNotAvailableException {
96         if (mSkip || mVerifyOnly) {
97             return;
98         }
99         ITestDevice device = testInfo.getDevice();
100         if (e instanceof DeviceFailedToBootError) {
101             CLog.d("boot failure: skipping wifi teardown");
102             return;
103         }
104 
105         if (mMonitorNetwork) {
106             device.disableNetworkMonitor();
107         }
108 
109         if (mWifiNetwork != null && mDisconnectWifiAfterTest && device.isWifiEnabled()) {
110             if (!device.disconnectFromWifi()) {
111                 CLog.w("Failed to disconnect from wifi network on %s", device.getSerialNumber());
112                 return;
113             }
114             CLog.i("Successfully disconnected from wifi network on %s", device.getSerialNumber());
115         }
116     }
117 }
118