Skip to content

Commit de3ba93

Browse files
j-gaocopybara-github
authored andcommitted
Open source NetworkConnector and related files
PiperOrigin-RevId: 929726770
1 parent 87ded1d commit de3ba93

8 files changed

Lines changed: 796 additions & 0 deletions

File tree

src/java/com/google/devtools/mobileharness/api/model/error/AndroidErrorId.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,11 @@ public enum AndroidErrorId implements ErrorId {
863863
ANDROID_FILE_OPERATOR_REMOVE_FILE_INVALID_ARGUMENT(150_405, ErrorType.CUSTOMER_ISSUE),
864864
ANDROID_FILE_OPERATOR_PREPARE_DES_DIR_ERROR(150_406, ErrorType.INFRA_ISSUE),
865865

866+
// NetworkConnector: 150_601 ~ 150_700
867+
NETWORK_CONNECTOR_CONNECT_TO_WIFI_ERROR(150_601, ErrorType.INFRA_ISSUE),
868+
NETWORK_CONNECTOR_INSTALL_WIFIUTIL_ERROR(150_602, ErrorType.INFRA_ISSUE),
869+
NETWORK_CONNECTOR_CONNECT_TO_WIFI_FAILURE(150_603, ErrorType.DEPENDENCY_ISSUE),
870+
866871
// AndroidAccountManager: 150_701 ~ 150_800
867872
ANDROID_ACCOUNT_MANAGER_CHECK_DEVICE_ROOTED_ERROR(150_701, ErrorType.INFRA_ISSUE),
868873
ANDROID_ACCOUNT_MANAGER_UNROOTED_DEVICE_NOT_SUPPORT_LST(150_702, ErrorType.CUSTOMER_ISSUE),

src/java/com/google/devtools/mobileharness/platform/android/connectivity/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ java_library(
2525
"//:omnilab_fusion",
2626
"//src/java/com/google/devtools/deviceinfra/ext/devicemanagement/device/platform/android:__subpackages__",
2727
"//src/java/com/google/devtools/mobileharness/platform/android/app/devicedaemon:__pkg__",
28+
"//src/java/com/google/devtools/mobileharness/platform/android/lightning/networkconnector:__pkg__",
2829
"//src/javatests/com/google/devtools/deviceinfra/ext/devicemanagement/device/platform/android:__subpackages__",
30+
"//src/javatests/com/google/devtools/mobileharness/platform/android/lightning/networkconnector:__pkg__",
2931
],
3032
deps = [
3133
":enums",
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Copyright 2022 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
#
15+
16+
load("@rules_java//java:defs.bzl", "java_library")
17+
18+
package(
19+
default_applicable_licenses = ["//:license"],
20+
default_visibility = [
21+
"//:deviceinfra_all_pkg",
22+
],
23+
)
24+
25+
java_library(
26+
name = "networkconnector",
27+
srcs = [
28+
"NetworkConnector.java",
29+
"WifiConnectArgs.java",
30+
],
31+
deps = [
32+
"//src/java/com/google/devtools/mobileharness/api/model/error",
33+
"//src/java/com/google/devtools/mobileharness/platform/android/connectivity:android_connectivity_util",
34+
"//src/java/com/google/devtools/mobileharness/platform/android/lightning/apkinstaller",
35+
"//src/java/com/google/devtools/mobileharness/platform/android/lightning/shared:shared_log_util",
36+
"//src/java/com/google/devtools/mobileharness/platform/android/systemsetting:system_setting_util",
37+
"//src/java/com/google/devtools/mobileharness/shared/util/auto:auto_value",
38+
"//src/java/com/google/devtools/mobileharness/shared/util/flags",
39+
"//src/java/com/google/devtools/mobileharness/shared/util/logging:google_logger",
40+
"//src/java/com/google/wireless/qa/mobileharness/shared/android:wifi_util",
41+
"//src/java/com/google/wireless/qa/mobileharness/shared/api/device",
42+
"//src/java/com/google/wireless/qa/mobileharness/shared/log",
43+
"//src/java/com/google/wireless/qa/mobileharness/shared/util:device",
44+
"@maven//:com_google_code_findbugs_jsr305",
45+
"@maven//:com_google_errorprone_error_prone_annotations",
46+
"@maven//:com_google_guava_guava",
47+
],
48+
)
Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
/*
2+
* Copyright 2022 Google LLC
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+
* https://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.google.devtools.mobileharness.platform.android.lightning.networkconnector;
18+
19+
import com.google.common.annotations.VisibleForTesting;
20+
import com.google.common.base.Strings;
21+
import com.google.common.flogger.FluentLogger;
22+
import com.google.devtools.mobileharness.api.model.error.AndroidErrorId;
23+
import com.google.devtools.mobileharness.api.model.error.MobileHarnessException;
24+
import com.google.devtools.mobileharness.platform.android.connectivity.AndroidConnectivityUtil;
25+
import com.google.devtools.mobileharness.platform.android.connectivity.ConnectToWifiArgs;
26+
import com.google.devtools.mobileharness.platform.android.lightning.apkinstaller.ApkInstallArgs;
27+
import com.google.devtools.mobileharness.platform.android.lightning.apkinstaller.ApkInstaller;
28+
import com.google.devtools.mobileharness.platform.android.lightning.shared.SharedLogUtil;
29+
import com.google.devtools.mobileharness.platform.android.systemsetting.AndroidSystemSettingUtil;
30+
import com.google.devtools.mobileharness.shared.util.flags.Flags;
31+
import com.google.errorprone.annotations.CanIgnoreReturnValue;
32+
import com.google.wireless.qa.mobileharness.shared.android.WifiUtil;
33+
import com.google.wireless.qa.mobileharness.shared.api.device.Device;
34+
import com.google.wireless.qa.mobileharness.shared.log.LogCollector;
35+
import com.google.wireless.qa.mobileharness.shared.util.DeviceUtil;
36+
import java.time.Duration;
37+
import java.util.logging.Level;
38+
import javax.annotation.Nullable;
39+
40+
/**
41+
* Network connector for managing Android device network.
42+
*
43+
* <p>Please keep all methods in this class sorted in alphabetical order by name.
44+
*/
45+
public class NetworkConnector {
46+
47+
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
48+
49+
private final WifiUtil wifiUtil;
50+
51+
private final AndroidConnectivityUtil connectivityUtil;
52+
53+
private final ApkInstaller apkInstaller;
54+
55+
private final AndroidSystemSettingUtil systemSettingUtil;
56+
57+
public NetworkConnector() {
58+
this(
59+
new WifiUtil(),
60+
new AndroidConnectivityUtil(),
61+
new ApkInstaller(),
62+
new AndroidSystemSettingUtil());
63+
}
64+
65+
@VisibleForTesting
66+
NetworkConnector(
67+
WifiUtil wifiUtil,
68+
AndroidConnectivityUtil connectivityUtil,
69+
ApkInstaller apkInstaller,
70+
AndroidSystemSettingUtil systemSettingUtil) {
71+
this.wifiUtil = wifiUtil;
72+
this.connectivityUtil = connectivityUtil;
73+
this.apkInstaller = apkInstaller;
74+
this.systemSettingUtil = systemSettingUtil;
75+
}
76+
77+
/**
78+
* Connects device to a WiFi network.
79+
*
80+
* @param device the device that connects to given wifi
81+
* @param connectArgs argument wrapper for connecting wifi
82+
* @param log log of the currently running test, usually from {@code TestInfo}
83+
* @return {@code true} if device connects to given wifi successfully, or {@code false} if failed
84+
* connecting device to given wifi, or it's not a MH managed device.
85+
* @throws MobileHarnessException if logFailuresOnly is {@code false} and it failed connecting to
86+
* wifi, or failed to get wifiutil apk path, or falied to install wifiutil on device.
87+
* @throws InterruptedException if the thread executing the commands is interrupted.
88+
*/
89+
@CanIgnoreReturnValue
90+
public boolean connectToWifi(
91+
Device device, WifiConnectArgs connectArgs, @Nullable LogCollector<?> log)
92+
throws MobileHarnessException, InterruptedException {
93+
String deviceId = device.getDeviceId();
94+
if (Flags.disableWifiUtilFunc.getNonNull()) {
95+
SharedLogUtil.logMsg(
96+
logger,
97+
Level.INFO,
98+
log,
99+
/* cause= */ null,
100+
"Ignoring attempt to connect device %s to WiFi while WifiUtil functionality is"
101+
+ " disabled.",
102+
deviceId);
103+
return false;
104+
}
105+
if (DeviceUtil.inSharedLab()) {
106+
SharedLogUtil.logMsg(
107+
logger,
108+
Level.SEVERE,
109+
log,
110+
/* cause= */ null,
111+
"Ignoring attempt to connect device %s to WiFi while not managing devices.",
112+
deviceId);
113+
return false;
114+
}
115+
116+
String wifiSsid = connectArgs.wifiSsid();
117+
String wifiPsk = connectArgs.wifiPsk().orElse(null);
118+
boolean scanSsid = connectArgs.scanSsid().orElse(false);
119+
boolean logFailuresOnly = connectArgs.logFailuresOnly().orElse(false);
120+
Duration waitTimeout = connectArgs.waitTimeout().orElse(Duration.ofMinutes(2));
121+
int retryNum = connectArgs.retryNum().orElse(0);
122+
123+
int sdkVersion = systemSettingUtil.getDeviceSdkVersion(deviceId);
124+
String currentSsid = null;
125+
try {
126+
currentSsid = connectivityUtil.getNetworkSsid(deviceId, sdkVersion);
127+
} catch (MobileHarnessException e) {
128+
SharedLogUtil.logMsg(
129+
logger,
130+
Level.WARNING,
131+
log,
132+
e,
133+
"Failed to get current SSID for device %s, try to connect it to WiFi(SSID=%s) anyway",
134+
deviceId,
135+
wifiSsid);
136+
}
137+
if (wifiSsid.equals(currentSsid)) {
138+
SharedLogUtil.logMsg(
139+
logger,
140+
log,
141+
"Device %s has already connected to WiFi(SSID=%s), skipped",
142+
deviceId,
143+
wifiSsid);
144+
return true;
145+
}
146+
SharedLogUtil.logMsg(logger, log, "Install WifiUtil for %s", deviceId);
147+
String wifiUtilApkPath;
148+
try {
149+
wifiUtilApkPath = wifiUtil.getWifiUtilApkPath();
150+
apkInstaller.installApkIfNotExist(
151+
device,
152+
ApkInstallArgs.builder().setApkPath(wifiUtilApkPath).setGrantPermissions(true).build(),
153+
log);
154+
} catch (MobileHarnessException e) {
155+
String msg =
156+
String.format("Failed installing WifiUtil on device %s:%n%s", deviceId, e.getMessage());
157+
if (logFailuresOnly) {
158+
SharedLogUtil.logMsg(logger, Level.WARNING, log, e, "%s", msg);
159+
return false;
160+
} else {
161+
throw new MobileHarnessException(
162+
AndroidErrorId.NETWORK_CONNECTOR_INSTALL_WIFIUTIL_ERROR, msg, e);
163+
}
164+
}
165+
166+
SharedLogUtil.logMsg(logger, log, "Connecting to WiFi(SSID=%s) for %s", wifiSsid, deviceId);
167+
boolean connectedToWifi = false;
168+
Exception connectWifiException = null;
169+
String msg = String.format("Failed connecting to WiFi(SSID=%s) for %s", wifiSsid, deviceId);
170+
if (retryNum != 0) {
171+
msg =
172+
String.format(
173+
"Failed connecting to WiFi(SSID=%s) for %s after %d retries",
174+
wifiSsid, deviceId, retryNum);
175+
}
176+
int retryCnt = retryNum;
177+
ConnectToWifiArgs.Builder argsBuilder =
178+
ConnectToWifiArgs.builder()
179+
.setSerial(deviceId)
180+
.setSdkVersion(sdkVersion)
181+
.setWifiSsid(wifiSsid)
182+
.setScanSsid(scanSsid)
183+
.setWaitTimeout(waitTimeout);
184+
if (!Strings.isNullOrEmpty(wifiPsk)) {
185+
argsBuilder.setWifiPsk(wifiPsk);
186+
}
187+
188+
do {
189+
if (retryCnt > 0 && retryNum == 0) {
190+
// Forces connecting to wifi at the last retry when the given retry number > 0.
191+
argsBuilder.setForceTryConnect(true);
192+
}
193+
try {
194+
connectedToWifi = connectivityUtil.connectToWifi(argsBuilder.build(), log);
195+
} catch (MobileHarnessException e) {
196+
connectWifiException = e;
197+
}
198+
if (connectedToWifi) {
199+
return true;
200+
}
201+
if (retryNum > 0) {
202+
try {
203+
connectivityUtil.reEnableWifi(device.getDeviceId(), log);
204+
} catch (MobileHarnessException e) {
205+
connectWifiException = e;
206+
}
207+
}
208+
} while (--retryNum >= 0);
209+
210+
SharedLogUtil.logMsg(logger, Level.WARNING, log, connectWifiException, "%s", msg);
211+
212+
if (!logFailuresOnly) {
213+
if (connectWifiException != null) {
214+
throw new MobileHarnessException(
215+
AndroidErrorId.NETWORK_CONNECTOR_CONNECT_TO_WIFI_ERROR, msg, connectWifiException);
216+
} else {
217+
throw new MobileHarnessException(
218+
AndroidErrorId.NETWORK_CONNECTOR_CONNECT_TO_WIFI_FAILURE, msg);
219+
}
220+
}
221+
return false;
222+
}
223+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2022 Google LLC
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+
* https://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.google.devtools.mobileharness.platform.android.lightning.networkconnector;
18+
19+
import com.google.auto.value.AutoValue;
20+
import java.time.Duration;
21+
import java.util.Optional;
22+
23+
/** Wrapper for arguments used for connecting device to a given wifi. */
24+
@AutoValue
25+
public abstract class WifiConnectArgs {
26+
27+
/** The SSID of the Wifi. */
28+
public abstract String wifiSsid();
29+
30+
/** The password of the Wifi. */
31+
public abstract Optional<String> wifiPsk();
32+
33+
/** Whether to scan for hidden SSID. */
34+
public abstract Optional<Boolean> scanSsid();
35+
36+
/**
37+
* Whether to log caught MobileHarnessException only when fail to connect wifi, instead of
38+
* throwing it out.
39+
*/
40+
public abstract Optional<Boolean> logFailuresOnly();
41+
42+
/** Waiting timeout to connect device to given ssid. */
43+
public abstract Optional<Duration> waitTimeout();
44+
45+
/** Number of retrying if failed to connect the device to the given ssid. */
46+
public abstract Optional<Integer> retryNum();
47+
48+
public static Builder builder() {
49+
return new AutoValue_WifiConnectArgs.Builder();
50+
}
51+
52+
/** Auto value builder for {@link WifiConnectArgs}. */
53+
@AutoValue.Builder
54+
public abstract static class Builder {
55+
56+
public abstract Builder setWifiSsid(String wifiSsid);
57+
58+
public abstract Builder setWifiPsk(String wifiPsk);
59+
60+
public abstract Builder setScanSsid(boolean scanSsid);
61+
62+
public abstract Builder setLogFailuresOnly(boolean logFailuresOnly);
63+
64+
public abstract Builder setWaitTimeout(Duration waitTimeout);
65+
66+
public abstract Builder setRetryNum(Integer retryNum);
67+
68+
public abstract WifiConnectArgs build();
69+
}
70+
}

src/java/com/google/wireless/qa/mobileharness/shared/log/testing/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ package(
2424
default_visibility = [
2525
"//java/com/google/wireless/qa/mobileharness/shared/log/testing:__subpackages__",
2626
"//src/javatests/com/google/devtools/mobileharness/platform/android/lightning/fileoperator:__subpackages__",
27+
"//src/javatests/com/google/devtools/mobileharness/platform/android/lightning/networkconnector:__subpackages__",
2728
"//src/javatests/com/google/wireless/qa/mobileharness/shared/log:__subpackages__",
2829
],
2930
)

0 commit comments

Comments
 (0)