diff options
author | Ang Li <angli@google.com> | 2017-04-26 15:21:10 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-26 15:21:10 -0700 |
commit | 4c0c5d68410dda9845e457a37fbb2098e743b550 (patch) | |
tree | e48f79d92eeb48f4c138c9d7bd05eb5a7322e4e0 /src/main/java/com | |
parent | 3c4740c21204e35f4ff4ae2d3e120dc26bb1b038 (diff) | |
download | mobly-bundled-snippets-4c0c5d68410dda9845e457a37fbb2098e743b550.tar.gz |
Add Wi-Fi soft ap related Rpc methods. (#35)
* Add Wi-Fi soft ap related Rpc methods.
* Change wait util to accomodate lambda functions that throw exceptions, which interrupt the wait.
Diffstat (limited to 'src/main/java/com')
4 files changed, 127 insertions, 11 deletions
diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/WifiManagerSnippet.java b/src/main/java/com/google/android/mobly/snippet/bundled/WifiManagerSnippet.java index f4fa0c0..ba9569c 100644 --- a/src/main/java/com/google/android/mobly/snippet/bundled/WifiManagerSnippet.java +++ b/src/main/java/com/google/android/mobly/snippet/bundled/WifiManagerSnippet.java @@ -23,14 +23,17 @@ import android.content.IntentFilter; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; +import android.os.Build; import android.support.annotation.Nullable; import android.support.test.InstrumentationRegistry; import com.google.android.mobly.snippet.Snippet; +import com.google.android.mobly.snippet.bundled.utils.ApiVersionException; import com.google.android.mobly.snippet.bundled.utils.JsonDeserializer; import com.google.android.mobly.snippet.bundled.utils.JsonSerializer; import com.google.android.mobly.snippet.bundled.utils.Utils; import com.google.android.mobly.snippet.rpc.Rpc; import com.google.android.mobly.snippet.util.Log; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import org.json.JSONArray; import org.json.JSONException; @@ -240,6 +243,106 @@ public class WifiManagerSnippet implements Snippet { return mJsonSerializer.toJson(mWifiManager.getDhcpInfo()); } + private void verifyApiVersionForSoftAp() throws ApiVersionException { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + throw new ApiVersionException( + "Soft AP APIs are not supported in Android versions >= N."); + } + } + + @Rpc(description = "Check whether Wi-Fi Soft AP (hotspot) is enabled.") + public boolean wifiIsApEnabled() throws Throwable { + verifyApiVersionForSoftAp(); + try { + return (boolean) + mWifiManager + .getClass() + .getDeclaredMethod("isWifiApEnabled") + .invoke(mWifiManager); + } catch (InvocationTargetException e) { + throw e.getCause(); + } + } + + /** + * Enable Wi-Fi Soft AP (hotspot). + * + * <p>Does not work for release N. + * + * @param configuration The same format as the param wifiNetworkConfig param for wifiConnect. + * @throws Throwable + */ + @Rpc(description = "Enable Wi-Fi Soft AP (hotspot).") + public void wifiEnableSoftAp(@Nullable JSONObject configuration) throws Throwable { + verifyApiVersionForSoftAp(); + // If no configuration is provided, the existing configuration would be used. + WifiConfiguration wifiConfiguration = null; + if (configuration != null) { + wifiConfiguration = JsonDeserializer.jsonToWifiConfig(configuration); + // Have to trim off the extra quotation marks since Soft AP logic interprets + // WifiConfiguration.SSID literally, unlike the WifiManager connection logic. + wifiConfiguration.SSID = JsonSerializer.trimQuotationMarks(wifiConfiguration.SSID); + } + boolean success; + try { + success = + (boolean) + mWifiManager + .getClass() + .getDeclaredMethod( + "setWifiApEnabled", + WifiConfiguration.class, + boolean.class) + .invoke(mWifiManager, wifiConfiguration, true); + } catch (InvocationTargetException e) { + throw e.getCause(); + } + if (!success) { + throw new WifiManagerSnippetException("Failed to initiate turning on Wi-Fi Soft AP."); + } + if (!Utils.waitUntil(() -> wifiIsApEnabled() == true, 60)) { + throw new WifiManagerSnippetException( + "Timed out after 60s waiting for Wi-Fi Soft AP state to turn on with configuration: " + + configuration); + } + } + + /** + * Disables Wi-Fi Soft AP (hotspot). + * + * <p>Does not work for release N. + * + * @throws Throwable + */ + @Rpc(description = "Disable Wi-Fi Soft AP (hotspot).") + public void wifiDisableSoftAp() throws Throwable { + verifyApiVersionForSoftAp(); + boolean success; + try { + success = + (boolean) + mWifiManager + .getClass() + .getDeclaredMethod( + "setWifiApEnabled", + WifiConfiguration.class, + boolean.class) + .invoke( + mWifiManager, + null, /* No configuration needed for disabling */ + false); + } catch (InvocationTargetException e) { + throw e.getCause(); + } + if (!success) { + throw new WifiManagerSnippetException("Failed to initiate turning off Wi-Fi Soft AP."); + } + if (!Utils.waitUntil(() -> wifiIsApEnabled() == false, 60)) { + throw new WifiManagerSnippetException( + "Timed out after 60s waiting for Wi-Fi Soft AP state to turn off."); + } + } + @Override public void shutdown() {} diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/utils/ApiVersionException.java b/src/main/java/com/google/android/mobly/snippet/bundled/utils/ApiVersionException.java new file mode 100644 index 0000000..68f2a55 --- /dev/null +++ b/src/main/java/com/google/android/mobly/snippet/bundled/utils/ApiVersionException.java @@ -0,0 +1,8 @@ +package com.google.android.mobly.snippet.bundled.utils; + +/** Raised for when an Rpc call is not supported by the Android version used. */ +public class ApiVersionException extends Exception { + public ApiVersionException(String message) { + super(message); + } +} diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/utils/JsonSerializer.java b/src/main/java/com/google/android/mobly/snippet/bundled/utils/JsonSerializer.java index 0c1b7a3..45af4a4 100644 --- a/src/main/java/com/google/android/mobly/snippet/bundled/utils/JsonSerializer.java +++ b/src/main/java/com/google/android/mobly/snippet/bundled/utils/JsonSerializer.java @@ -55,7 +55,7 @@ public class JsonSerializer { * * @param originalString */ - private static String trimQuotationMarks(String originalString) { + public static String trimQuotationMarks(String originalString) { String result = originalString; if (originalString.charAt(0) == '"' && originalString.charAt(originalString.length() - 1) == '"') { diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/utils/Utils.java b/src/main/java/com/google/android/mobly/snippet/bundled/utils/Utils.java index 00bfbd2..0ea5313 100644 --- a/src/main/java/com/google/android/mobly/snippet/bundled/utils/Utils.java +++ b/src/main/java/com/google/android/mobly/snippet/bundled/utils/Utils.java @@ -25,21 +25,26 @@ public final class Utils { * <p>This is often used to wait for asynchronous operations to finish and the system to reach a * desired state. * + * <p>If the predicate function throws an exception and interrupts the waiting, the exception + * will be wrapped in an {@link RuntimeException}. + * * @param predicate A lambda function that specifies the condition to wait for. This function * should return true when the desired state has been reached. * @param timeout The number of seconds to wait for before giving up. * @return true if the operation finished before timeout, false otherwise. - * @throws InterruptedException */ - public static boolean waitUntil(Utils.Predicate predicate, int timeout) - throws InterruptedException { + public static boolean waitUntil(Utils.Predicate predicate, int timeout) { timeout *= 10; - while (!predicate.waitCondition() && timeout >= 0) { - Thread.sleep(100); - timeout -= 1; - } - if (predicate.waitCondition()) { - return true; + try { + while (!predicate.waitCondition() && timeout >= 0) { + Thread.sleep(100); + timeout -= 1; + } + if (predicate.waitCondition()) { + return true; + } + } catch (Throwable e) { + throw new RuntimeException(e); } return false; } @@ -49,6 +54,6 @@ public final class Utils { * going on. */ public interface Predicate { - boolean waitCondition(); + boolean waitCondition() throws Throwable; } } |