aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJinhui Wang <jinhuiw@google.com>2016-08-19 18:26:13 -0700
committerJinhui Wang <jinhuiw@google.com>2016-08-24 10:35:10 -0700
commit92acce1a02118d0b0468b01a486fa3ccc757c61e (patch)
treef5037d9f3879803455cbc2c72b2b551f985c2dfe
parent22d065954bcdd50f2e1054a5e53aa486317d81a3 (diff)
downloadAfwTestHarness-92acce1a02118d0b0468b01a486fa3ccc757c61e.tar.gz
Make test harness support WEP wifi
Created and util app to connect wifi. Update AfwTesWifiPreparer to connect WEP wifi with the util app. Change-Id: I01ef074323600a1b7a0f84b404d388355989c566
-rw-r--r--AfwTestCaseList.mk3
-rw-r--r--apps/Util/Android.mk33
-rw-r--r--apps/Util/AndroidManifest.xml34
-rw-r--r--apps/Util/README.txt17
-rw-r--r--apps/Util/src/com/android/afwtest/util/NetworkMonitor.java98
-rw-r--r--apps/Util/src/com/android/afwtest/util/Wifi.java133
-rw-r--r--apps/Util/src/com/android/afwtest/util/WifiConfig.java145
-rw-r--r--apps/Util/src/com/android/afwtest/util/WifiConnector.java145
-rw-r--r--libs/CommonLib/src/com/android/afwtest/common/NetworkUtils.java104
-rw-r--r--tools/tradefed-host/res/config/afw-test-wifi.xml6
-rw-r--r--tools/tradefed-host/src/com/android/afwtest/tradefed/targetprep/AfwTestEnvDumper.java4
-rw-r--r--tools/tradefed-host/src/com/android/afwtest/tradefed/targetprep/AfwTestTargetPreparer.java2
-rw-r--r--tools/tradefed-host/src/com/android/afwtest/tradefed/targetprep/AfwTestUserRemover.java8
-rw-r--r--tools/tradefed-host/src/com/android/afwtest/tradefed/targetprep/AfwTestWifiPreparer.java110
14 files changed, 825 insertions, 17 deletions
diff --git a/AfwTestCaseList.mk b/AfwTestCaseList.mk
index adae60f..ea16169 100644
--- a/AfwTestCaseList.mk
+++ b/AfwTestCaseList.mk
@@ -24,7 +24,8 @@ afw_th_test_packages := \
# Support packages
afw_th_support_packages := \
AfwThDeviceAdmin \
- AfwThSystemUtil
+ AfwThSystemUtil \
+ AfwThUtil
# All the test case apk files that will end up under the repository/testcases
diff --git a/apps/Util/Android.mk b/apps/Util/Android.mk
new file mode 100644
index 0000000..89742c4
--- /dev/null
+++ b/apps/Util/Android.mk
@@ -0,0 +1,33 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := AfwThCommonLib
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := AfwThUtil
+
+LOCAL_SDK_VERSION := 22
+
+include $(BUILD_AFW_TEST_SUPPORT_PACKAGE)
diff --git a/apps/Util/AndroidManifest.xml b/apps/Util/AndroidManifest.xml
new file mode 100644
index 0000000..f270fcc
--- /dev/null
+++ b/apps/Util/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.afwtest.util" >
+
+ <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+
+ <uses-sdk android:minSdkVersion="22" android:targetSdkVersion="22" />
+
+ <instrumentation android:name=".Wifi"
+ android:targetPackage="com.android.afwtest.util"
+ android:label="Afw Test Harness Utility App">
+ </instrumentation>
+
+ <application android:label="Afw Test Harness Util">
+ </application>
+</manifest>
diff --git a/apps/Util/README.txt b/apps/Util/README.txt
new file mode 100644
index 0000000..8d17880
--- /dev/null
+++ b/apps/Util/README.txt
@@ -0,0 +1,17 @@
+- About
+
+ Common util app that works on user builds.
+
+- Usage: connect a wifi
+
+ adb shell am instrument -w -e action connect \
+ -e ssid <ssid> -e security_type <security_type> -e password <password> \
+ com.android.afwtest.util/.Wifi
+
+ security_type could be WPA, WEP or NONE. Default to be NONE if no password is specified; default
+ to be WPA if password is given.
+
+- Usage: disconnect from wifi
+
+ adb shell am instrument -w -e action disconnect com.android.afwtest.util/.Wifi
+
diff --git a/apps/Util/src/com/android/afwtest/util/NetworkMonitor.java b/apps/Util/src/com/android/afwtest/util/NetworkMonitor.java
new file mode 100644
index 0000000..b432549
--- /dev/null
+++ b/apps/Util/src/com/android/afwtest/util/NetworkMonitor.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.afwtest.util;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.util.Log;
+
+import com.android.afwtest.common.NetworkUtils;
+
+/**
+ * Monitor the state of the data network. Invoke a callback when the network is connected
+ */
+public class NetworkMonitor {
+ private static final String TAG = "afwtest.NetworkMonitor";
+
+ /** State notification callback. Expect some duplicate notifications. */
+ public interface Callback {
+ /** Notify on network connected. */
+ void onNetworkConnected();
+ /** Notify on network disconnected. */
+ void onNetworkDisconnected();
+ }
+
+ /** Application context. */
+ private final Context mContext;
+
+ /** Registered callback that is listening to network events. */
+ private final Callback mCallback;
+
+ /** Whether receiver is registered. */
+ private boolean mReceiverRegistered;
+
+ /**
+ * Start watching the network and monitoring the checkin service. Immediately invokes one of the
+ * callback methods to report the current state, and then invokes callback methods over time as
+ * the state changes.
+ *
+ * @param context to use for intent observers and such
+ * @param callback to invoke when the network status changes
+ */
+ public NetworkMonitor(Context context, Callback callback) {
+ mContext = context;
+ mCallback = callback;
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+
+ context.registerReceiver(mBroadcastReceiver, filter);
+
+ mReceiverRegistered = true;
+ }
+
+ /**
+ * Stop watching the network and checkin service.
+ */
+ public synchronized void close() {
+ if (mReceiverRegistered) {
+ mContext.unregisterReceiver(mBroadcastReceiver);
+ mReceiverRegistered = false;
+ }
+ }
+
+ /**
+ * Broadcast receiver.
+ */
+ public final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.i(TAG, String.format("onReceive: %s", intent.toString()));
+
+ if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
+ if (NetworkUtils.isConnectedToWifi(context)) {
+ mCallback.onNetworkConnected();
+ } else {
+ mCallback.onNetworkDisconnected();
+ }
+ }
+ }
+ };
+}
diff --git a/apps/Util/src/com/android/afwtest/util/Wifi.java b/apps/Util/src/com/android/afwtest/util/Wifi.java
new file mode 100644
index 0000000..e55ab40
--- /dev/null
+++ b/apps/Util/src/com/android/afwtest/util/Wifi.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.afwtest.util;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.afwtest.common.NetworkUtils;
+
+/**
+ * Adds a wifi network to system.
+ */
+public class Wifi extends Instrumentation {
+
+ private static final String TAG = "afwtest.Wifi";
+
+ private static final String ACTION_CONNECT = "connect";
+ private static final String ACTION_DISCONNECT = "disconnect";
+
+ /** Supported actions: connect, disconnect*/
+ private String mAction;
+
+ private String mSSID, mSecurityType, mPassword;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onCreate(Bundle arguments) {
+ super.onCreate(arguments);
+ mAction = arguments.getString("action", "");
+ mSSID = arguments.getString("ssid", "");
+ if (!mSSID.startsWith("\"") || !mSSID.endsWith("\"")) {
+ mSSID = String.format("\"%s\"", mSSID);
+ }
+ mSecurityType = arguments.getString("security_type", "");
+ mPassword = arguments.getString("password", "");
+ start();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onStart() {
+ // Handle connect action
+ if (ACTION_CONNECT.equals(mAction)) {
+ handleConnect();
+ } else if (ACTION_DISCONNECT.equals(mAction)) {
+ handleDisconnect();
+ } else {
+ handleError(String.format("Invalid action: %s", mAction));
+ }
+ }
+
+ /**
+ * Handles connecting wifi request.
+ */
+ private void handleConnect() {
+ if (!NetworkUtils.enableWifi(getContext())) {
+ handleError("Failed to enable wifi.");
+ }
+
+ // If the expected wifi is already connected, return.
+ if (NetworkUtils.isConnectedToSpecifiedWifi(getContext(), mSSID)) {
+ Log.i(TAG, String.format("Wifi already connected: %s (%s)", mSSID, mSecurityType));
+ handleSuccess();
+ } else {
+ WifiConnector wifiConnector = new WifiConnector(getContext(),
+ mSSID,
+ mSecurityType,
+ mPassword);
+ if (wifiConnector.connect()) {
+ Log.i(TAG, String.format("Connected to wifi: %s (%s)", mSSID, mSecurityType));
+ handleSuccess();
+ } else {
+ handleError(String.
+ format("Failed to connect to wifi: %s (%s)", mSSID, mSecurityType));
+ }
+ }
+ }
+
+ /**
+ * Handles wifi disconnecting request.
+ *
+ * Handled by removing all configured networks.
+ */
+ private void handleDisconnect() {
+ if (!NetworkUtils.disconnectFromWifi(getContext())) {
+ handleError("Failed to disconnect from Wifi");
+ } else {
+ Log.i(TAG, "Wifi disconnected.");
+ handleSuccess();
+ }
+ }
+
+ /**
+ * Handles error by exiting instrumentation.
+ *
+ * @param errorMsg error msg
+ */
+ private void handleError(String errorMsg) {
+ Log.i(TAG, errorMsg);
+ Bundle results = new Bundle();
+ results.putString("error", errorMsg);
+ finish(Activity.RESULT_CANCELED, results);
+ }
+
+ /**
+ * Handles success execution
+ */
+ private void handleSuccess() {
+ Bundle results = new Bundle();
+ results.putString("result", "SUCCESS");
+ finish(Activity.RESULT_OK, results);
+ }
+} \ No newline at end of file
diff --git a/apps/Util/src/com/android/afwtest/util/WifiConfig.java b/apps/Util/src/com/android/afwtest/util/WifiConfig.java
new file mode 100644
index 0000000..f49d710
--- /dev/null
+++ b/apps/Util/src/com/android/afwtest/util/WifiConfig.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.afwtest.util;
+
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.Locale;
+
+/**
+ * Utility class for configuring a new WiFi network.
+ */
+public final class WifiConfig {
+
+ private static final String TAG = "afwtest.WifiConfig";
+
+ /** Security type enum. */
+ enum SecurityType {
+ NONE,
+ WPA,
+ WEP
+ }
+
+ /** {@link WifiManager} instance. */
+ private final WifiManager mWifiManager;
+
+ /**
+ * Constructor.
+ *
+ * @param manager {@link WifiManager} object
+ */
+ public WifiConfig(WifiManager manager) {
+ mWifiManager = manager;
+ }
+
+ /**
+ * Adds a new WiFi network.
+ *
+ * @param ssid Wifi SSID
+ * @param type Wifi security type
+ * @param password Wifi password
+ * @return the ID of the newly created network description. Returns -1 on failure.
+ */
+ public int addNetwork(String ssid, String type, String password) {
+ WifiConfiguration wifiConf = new WifiConfiguration();
+ SecurityType securityType;
+ if (type == null || TextUtils.isEmpty(type)) {
+ securityType = SecurityType.NONE;
+ } else {
+ try {
+ securityType = Enum.valueOf(SecurityType.class, type.toUpperCase(Locale.US));
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, String.format("Invalid Wifi security type: %s", type));
+ return -1;
+ }
+ }
+ // If we have a password, and no security type, assume WPA.
+ if (securityType.equals(SecurityType.NONE) && !TextUtils.isEmpty(password)) {
+ securityType = SecurityType.WPA;
+ }
+
+ wifiConf.SSID = ssid;
+ wifiConf.status = WifiConfiguration.Status.ENABLED;
+ switch (securityType) {
+ case NONE:
+ wifiConf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+ wifiConf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
+ break;
+ case WPA:
+ updateForWPAConfiguration(wifiConf, password);
+ break;
+ case WEP:
+ updateForWEPConfiguration(wifiConf, password);
+ break;
+ }
+
+ int netId = mWifiManager.addNetwork(wifiConf);
+
+ if (netId != -1) {
+ // Setting disableOthers to 'true' should trigger a connection attempt.
+ mWifiManager.enableNetwork(netId, true);
+ mWifiManager.saveConfiguration();
+ }
+
+ return netId;
+ }
+
+ /**
+ * Updates WAP Wifi configuration.
+ *
+ * @param wifiConf {@link WifiConfiguration} object to update
+ * @param password Wifi password
+ */
+ protected void updateForWPAConfiguration(WifiConfiguration wifiConf, String password) {
+ wifiConf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+ wifiConf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
+ wifiConf.allowedProtocols.set(WifiConfiguration.Protocol.WPA); // For WPA
+ wifiConf.allowedProtocols.set(WifiConfiguration.Protocol.RSN); // For WPA2
+ wifiConf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
+ wifiConf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
+ wifiConf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
+ wifiConf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
+ if (!TextUtils.isEmpty(password)) {
+ wifiConf.preSharedKey = "\"" + password + "\"";
+ }
+ }
+
+ /**
+ * Updates WEP Wifi configuration.
+ *
+ * @param wifiConf {@link WifiConfiguration} object to update
+ * @param password Wifi password
+ */
+ protected void updateForWEPConfiguration(WifiConfiguration wifiConf, String password) {
+ wifiConf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+ wifiConf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
+ wifiConf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
+ wifiConf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
+ wifiConf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
+ wifiConf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
+ wifiConf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
+ int length = password.length();
+ if ((length == 10 || length == 26 || length == 58) && password.matches("[0-9A-Fa-f]*")) {
+ wifiConf.wepKeys[0] = password;
+ } else {
+ wifiConf.wepKeys[0] = '"' + password + '"';
+ }
+ wifiConf.wepTxKeyIndex = 0;
+ }
+} \ No newline at end of file
diff --git a/apps/Util/src/com/android/afwtest/util/WifiConnector.java b/apps/Util/src/com/android/afwtest/util/WifiConnector.java
new file mode 100644
index 0000000..f10ab2d
--- /dev/null
+++ b/apps/Util/src/com/android/afwtest/util/WifiConnector.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.afwtest.util;
+
+import android.content.Context;
+import android.net.wifi.WifiManager;
+import android.os.SystemClock;
+import android.util.Log;
+
+import com.android.afwtest.common.NetworkUtils;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Utility class responsible for connecting wifi.
+ */
+public final class WifiConnector implements NetworkMonitor.Callback {
+
+ private static final String TAG = "afwtest.WifiConnector";
+
+ /** Connection retry base duration. */
+ private static final int RETRY_SLEEP_DURATION_BASE_MS = 500;
+ /** Connection retry duration multiplier. */
+ private static final int RETRY_SLEEP_MULTIPLIER = 2;
+ /** Max connection attempts. */
+ private static final int MAX_ATTEMPS = 6;
+ /** Wifi reconnection timeout. */
+ private static final int RECONNECT_TIMEOUT_MS = (int)TimeUnit.MINUTES.toMillis(1);
+
+ private final Context mContext;
+ private final String mSSID, mSecurityType, mPassword;
+ private final WifiManager mWifiManager;
+ private final WifiConfig mWifiConfig;
+
+ /**
+ * {@link Semaphore}, indicating result is available if it's value > 0.
+ */
+ private Semaphore mLock = new Semaphore(0);
+
+ /**
+ * Constructor.
+ *
+ * @param context {@link Context} object
+ * @param ssid Wifi SSID
+ * @param securityType Wifi security type
+ * @param password Wifi password
+ */
+ public WifiConnector(Context context, String ssid, String securityType, String password) {
+ mContext = context;
+ mSSID = ssid;
+ mSecurityType = securityType;
+ mPassword = password;
+ mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ mWifiConfig = new WifiConfig(mWifiManager);
+ }
+
+ /**
+ * Connects to WIFI.
+ *
+ * @return {@code true} if the given WIFI is connected; {@code false} othwerise
+ */
+ public boolean connect() {
+ if (!NetworkUtils.enableWifi(mContext)) {
+ Log.e(TAG, "Failed to enable WIFI.");
+ return false;
+ }
+
+ NetworkMonitor networkMonitor = new NetworkMonitor(mContext, this);
+
+ try {
+ int netId = -1;
+
+ int nextSleepTimeMs = RETRY_SLEEP_DURATION_BASE_MS;
+ int attempts = MAX_ATTEMPS;
+ while (attempts > 0) {
+ if (netId == -1) {
+ netId = mWifiConfig.addNetwork(mSSID, mSecurityType, mPassword);
+ }
+
+ if (netId == -1) {
+ Log.e(TAG, "Failed to save network.");
+ } else if (!mWifiManager.reconnect()) {
+ Log.e(TAG, "Unable to connect to wifi");
+ } else {
+ // Connected
+ break;
+ }
+
+ --attempts;
+ // Sleep before next attempt
+ Log.e(TAG, String.format("Retrying in %s ms.", nextSleepTimeMs));
+ SystemClock.sleep(nextSleepTimeMs);
+ // Increase the next sleep time.
+ nextSleepTimeMs *= RETRY_SLEEP_MULTIPLIER;
+ }
+
+ // Failed to add network or reconnect.
+ if (netId == -1 || attempts <= 0) {
+ return false;
+ }
+
+ // Wait for connection event
+ mLock.tryAcquire(RECONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ return true;
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Failed to connect to wifi", e);
+ } finally {
+ networkMonitor.close();
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onNetworkConnected() {
+ if (NetworkUtils.isConnectedToSpecifiedWifi(mContext, mSSID)) {
+ // Let's the waiter know it's connected.
+ mLock.release();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onNetworkDisconnected() {
+ }
+} \ No newline at end of file
diff --git a/libs/CommonLib/src/com/android/afwtest/common/NetworkUtils.java b/libs/CommonLib/src/com/android/afwtest/common/NetworkUtils.java
new file mode 100644
index 0000000..ef7e00c
--- /dev/null
+++ b/libs/CommonLib/src/com/android/afwtest/common/NetworkUtils.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.afwtest.common;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiManager;
+import android.util.Log;
+
+/**
+ * Network utilities.
+ */
+public class NetworkUtils {
+ private static final String TAG = "afwtest.NetworkUtils";
+
+ /**
+ * Enables Wifi.
+ *
+ * @param context {@link Context} object
+ * @return {@code true} if Wifi is enabled successfully; {@code false} otherwise
+ */
+ public static boolean enableWifi(Context context) {
+ WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ return wifiManager != null
+ && (wifiManager.isWifiEnabled() || wifiManager.setWifiEnabled(true));
+ }
+
+ /**
+ * Returns whether the device is currently connected to a wifi.
+ *
+ * @param context {@link Context} object
+ * @return {@code true} if connected to Wifi; {@code false} otherwise
+ */
+ public static boolean isConnectedToWifi(Context context) {
+ NetworkInfo info = getActiveNetworkInfo(context);
+ return info != null
+ && info.isConnected()
+ && info.getType() == ConnectivityManager.TYPE_WIFI;
+ }
+
+ /**
+ * Checks if connected with expected wifi.
+ *
+ * @param context {@link Context} object
+ * @param ssid Wifi SSID
+ * @return {@code true} if the expected wifi
+ */
+ public static boolean isConnectedToSpecifiedWifi(Context context, String ssid) {
+ WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ return ssid != null
+ && wifiManager != null
+ && isConnectedToWifi(context)
+ && wifiManager.getConnectionInfo() != null
+ && ssid.equals(wifiManager.getConnectionInfo().getSSID());
+ }
+
+ /**
+ * Gets the active network.
+ *
+ * @param context {@link Context} object
+ * @return active {@link NetworkInfo}
+ */
+ private static NetworkInfo getActiveNetworkInfo(Context context) {
+ ConnectivityManager cm =
+ (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ if (cm != null) {
+ return cm.getActiveNetworkInfo();
+ }
+ return null;
+ }
+
+ /**
+ * Disconnects a device from the connected Wi-Fi network by removing the network configuration.
+ *
+ * @param context {@link Context} object
+ */
+ public static boolean disconnectFromWifi(Context context) {
+ WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ if (wifiManager.isWifiEnabled() && isConnectedToWifi(context)) {
+ String wifiSsid = wifiManager.getConnectionInfo().getSSID();
+ if (!wifiManager.removeNetwork(wifiManager.getConnectionInfo().getNetworkId())) {
+ Log.e(TAG, String.format("Failed to remove Wifi %s", wifiSsid));
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/tools/tradefed-host/res/config/afw-test-wifi.xml b/tools/tradefed-host/res/config/afw-test-wifi.xml
index 962aec3..24a6260 100644
--- a/tools/tradefed-host/res/config/afw-test-wifi.xml
+++ b/tools/tradefed-host/res/config/afw-test-wifi.xml
@@ -16,9 +16,15 @@
<configuration description="Connect to wifi network">
+ <!-- Install device admin app -->
+ <target_preparer class="com.android.cts.tradefed.targetprep.CtsApkInstaller">
+ <option name="test-file-name" value="AfwThUtil.apk" />
+ </target_preparer>
+
<target_preparer class="com.android.afwtest.tradefed.targetprep.AfwTestWifiPreparer" >
<option name="wifi-config-file" value="afw-test.props"/>
<option name="wifi-ssid-key" value="wifi_ssid"/>
+ <option name="wifi-security-type-key" value="wifi_security_type"/>
<option name="wifi-password-key" value="wifi_password"/>
<option name="disconnect-wifi-after-test" value="false"/>
</target_preparer>
diff --git a/tools/tradefed-host/src/com/android/afwtest/tradefed/targetprep/AfwTestEnvDumper.java b/tools/tradefed-host/src/com/android/afwtest/tradefed/targetprep/AfwTestEnvDumper.java
index cdb0b28..6d6717e 100644
--- a/tools/tradefed-host/src/com/android/afwtest/tradefed/targetprep/AfwTestEnvDumper.java
+++ b/tools/tradefed-host/src/com/android/afwtest/tradefed/targetprep/AfwTestEnvDumper.java
@@ -86,7 +86,7 @@ public class AfwTestEnvDumper extends AfwTestTargetPreparer implements ITargetCl
os.write(str.getBytes());
StreamUtil.flushAndCloseStream(os);
- CLog.i("Dumped file: " + dumpFile.getAbsolutePath());
+ CLog.i(String.format("Dumped file: %s", dumpFile.getAbsolutePath()));
} catch (IOException exception) {
CLog.e("Failed to dump app versions to file", e);
}
@@ -95,7 +95,7 @@ public class AfwTestEnvDumper extends AfwTestTargetPreparer implements ITargetCl
/**
* Gets environment configurations as string.
*
- * @param deivce testing device
+ * @param device testing device
* @return environment configuration as string
*/
protected String getEnv(ITestDevice device) throws DeviceNotAvailableException {
diff --git a/tools/tradefed-host/src/com/android/afwtest/tradefed/targetprep/AfwTestTargetPreparer.java b/tools/tradefed-host/src/com/android/afwtest/tradefed/targetprep/AfwTestTargetPreparer.java
index 3316e6b..cfca249 100644
--- a/tools/tradefed-host/src/com/android/afwtest/tradefed/targetprep/AfwTestTargetPreparer.java
+++ b/tools/tradefed-host/src/com/android/afwtest/tradefed/targetprep/AfwTestTargetPreparer.java
@@ -171,7 +171,7 @@ public abstract class AfwTestTargetPreparer {
protected void fastbootFormat(ITestDevice device, String partition)
throws DeviceNotAvailableException, TargetSetupError {
- CLog.i("Attempting: fastboot format %s", partition);
+ CLog.i(String.format("Attempting: fastboot format %s", partition));
CommandResult r = device.executeLongFastbootCommand("format", partition);
if (r.getStatus() != CommandStatus.SUCCESS) {
throw new TargetSetupError(
diff --git a/tools/tradefed-host/src/com/android/afwtest/tradefed/targetprep/AfwTestUserRemover.java b/tools/tradefed-host/src/com/android/afwtest/tradefed/targetprep/AfwTestUserRemover.java
index 832a9a9..c21c8e6 100644
--- a/tools/tradefed-host/src/com/android/afwtest/tradefed/targetprep/AfwTestUserRemover.java
+++ b/tools/tradefed-host/src/com/android/afwtest/tradefed/targetprep/AfwTestUserRemover.java
@@ -92,9 +92,13 @@ public class AfwTestUserRemover implements ITargetCleaner {
}
if (device.removeUser(userId)) {
- CLog.i("Successfully removed user %d on %s", userId, device.getSerialNumber());
+ CLog.i(String.format("Successfully removed user %d on %s",
+ userId,
+ device.getSerialNumber()));
} else {
- CLog.e("Failed to remove user %d on %s", userId, device.getSerialNumber());
+ CLog.e(String.format("Failed to remove user %d on %s",
+ userId,
+ device.getSerialNumber()));
success = false;
}
}
diff --git a/tools/tradefed-host/src/com/android/afwtest/tradefed/targetprep/AfwTestWifiPreparer.java b/tools/tradefed-host/src/com/android/afwtest/tradefed/targetprep/AfwTestWifiPreparer.java
index ffa9def..1355be8 100644
--- a/tools/tradefed-host/src/com/android/afwtest/tradefed/targetprep/AfwTestWifiPreparer.java
+++ b/tools/tradefed-host/src/com/android/afwtest/tradefed/targetprep/AfwTestWifiPreparer.java
@@ -38,6 +38,15 @@ import java.util.Properties;
@OptionClass(alias = "afw-test-wifi")
public final class AfwTestWifiPreparer extends AfwTestTargetPreparer implements ITargetCleaner {
+ /**
+ * Package name of the system util app.
+ */
+ private static final String UTIL_PKG_NAME = "com.android.afwtest.util";
+
+ /** Shell command template for connect/disconnect wifi. */
+ private static final String ADB_SHELL_CMD_TEMPL =
+ "am instrument -w %s com.android.afwtest.util/.Wifi";
+
@Option(name = "wifi-config-file",
description = "The file name containing wifi configuration.")
private String mConfigFileName = null;
@@ -46,6 +55,10 @@ public final class AfwTestWifiPreparer extends AfwTestTargetPreparer implements
description = "The key of wifi ssid in the config file.")
private String mWifiSsidKey = null;
+ @Option(name = "wifi-security-type-key",
+ description = "The key of wifi security type in the config file.")
+ private String mWifiSecurityType = null;
+
@Option(name = "wifi-password-key",
description = "The key of wifi password in the config file.")
private String mWifiPasswordKey = null;
@@ -58,6 +71,9 @@ public final class AfwTestWifiPreparer extends AfwTestTargetPreparer implements
description = "Disconnect from wifi network after test completes.")
private boolean mDisconnectWifiAfterTest = true;
+ /** Whether to connect with AfwThUtil app. */
+ private boolean mWifiConnectedWithUtilApp = false;
+
/**
* {@inheritDoc}
*/
@@ -74,30 +90,38 @@ public final class AfwTestWifiPreparer extends AfwTestTargetPreparer implements
}
File configFile = new File(getCtsBuildHelper(buildInfo).getTestCasesDir(), mConfigFileName);
- Properties props = null;
+ Properties props;
try {
props = readProperties(configFile);
} catch (IOException e) {
- throw new TargetSetupError("Failed to read prop file: " + configFile.getAbsolutePath());
+ throw new TargetSetupError(
+ String.format("Failed to read prop file: %s", configFile.getAbsolutePath()));
}
String wifiSsid = props.getProperty(mWifiSsidKey, "");
+ String wifiSecurityType = props.getProperty(mWifiSecurityType, "");
String wifiPassword = props.getProperty(mWifiPasswordKey, "");
if (wifiSsid.isEmpty()) {
- throw new TargetSetupError(
- mWifiSsidKey + " not specified in file " + configFile.getAbsolutePath());
+ throw new TargetSetupError(String.format(
+ "%s not specified in file %s", mWifiSsidKey, configFile.getAbsolutePath()));
+ }
+
+ // tradefed doesn't support WEP wifi; connect to it by AfwThUtil
+ if ("WEP".equals(wifiSecurityType)) {
+ mWifiConnectedWithUtilApp = true;
+ connectWifiWithUtilApp(device, wifiSsid, wifiSecurityType, wifiPassword);
+ return;
}
// Implement retry.
for (int i = 0; i < mWifiAttempts; ++i) {
try {
-
if (device.connectToWifiNetworkIfNeeded(wifiSsid, wifiPassword)) {
return;
}
- } catch(Exception e) {
- CLog.e("Error trying to connect to Wifi:", e);
+ } catch (Exception e) {
+ CLog.e(e);
}
boolean lastAttempt = (i + 1) == mWifiAttempts;
if (!lastAttempt) {
@@ -117,16 +141,80 @@ public final class AfwTestWifiPreparer extends AfwTestTargetPreparer implements
throws DeviceNotAvailableException {
if (mDisconnectWifiAfterTest && device.isWifiEnabled()) {
- if (device.disconnectFromWifi()) {
- CLog.i("Successfully disconnected from wifi network on %s",
- device.getSerialNumber());
+ if (mWifiConnectedWithUtilApp) {
+ disconnectWifiWithUtilApp(device);
} else {
- CLog.w("Failed to disconnect from wifi network on %s", device.getSerialNumber());
+ if (device.disconnectFromWifi()) {
+ CLog.i("Successfully disconnected from wifi network on %s",
+ device.getSerialNumber());
+ } else {
+ CLog.w("Failed to disconnect from wifi network on %s",
+ device.getSerialNumber());
+ }
}
}
}
/**
+ * Connects to wifi with AfwThUtil app.
+ *
+ * @param device test device
+ * @param wifiSSID WIFI SSID
+ * @param securityType WIFI security type
+ * @param password WIFI password
+ */
+ private void connectWifiWithUtilApp(ITestDevice device,
+ String wifiSSID,
+ String securityType,
+ String password)
+ throws TargetSetupError, DeviceNotAvailableException {
+ String args = String.format("-e action connect -e ssid %s", wifiSSID);
+ if (securityType != null && !securityType.isEmpty()) {
+ args = String.format("%s -e security_type %s", args, securityType);
+ }
+ if (password != null && !password.isEmpty()) {
+ args = String.format("%s -e password %s", args, password);
+ }
+
+ String cmdStr = String.format(ADB_SHELL_CMD_TEMPL, args);
+ CLog.i(String.format("Shell: %s", cmdStr));
+ String result = device.executeShellCommand(cmdStr);
+ if (result != null && result.contains("result=SUCCESS")) {
+ CLog.i(String.format(
+ "Successfully connected to wifi network %s(security_type=%s) on %s",
+ wifiSSID,
+ securityType,
+ device.getSerialNumber()));
+ } else {
+ throw new TargetSetupError(String.format(
+ "Failed to connected to wifi network %s(security_type=%s) on %s: %s",
+ wifiSSID,
+ securityType,
+ device.getSerialNumber(),
+ result));
+ }
+ }
+
+ /**
+ * Disconnects from Wifi with AfwThUtil app.
+ *
+ * @param device test device
+ */
+ private void disconnectWifiWithUtilApp(ITestDevice device) throws DeviceNotAvailableException {
+ String cmdStr = String.format(ADB_SHELL_CMD_TEMPL, "-e action disconnect");
+ CLog.i(String.format("Shell: %s", cmdStr));
+ String result = device.executeShellCommand(cmdStr);
+ if (result != null && result.contains("result=SUCCESS")) {
+ CLog.i(String.format("Successfully disconnected from wifi network on %s",
+ device.getSerialNumber()));
+ } else {
+ CLog.w(String.format("Failed to disconnect from wifi network on %s: %s",
+ device.getSerialNumber(),
+ result));
+ }
+ }
+
+ /**
* Help function to read {@link Properties} from a file.
*
* @param file {@link File} to read properties from