aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKolin Lu <kolinlu@google.com>2023-07-20 10:00:48 -0700
committerGitHub <noreply@github.com>2023-07-20 10:00:48 -0700
commit363a22ae26a277dfbf6c7a0c6596d1a7c08a39f1 (patch)
treefccb6a72a9c459a7bb9fa4eb0f359592313c24d7
parentd56020d155e315bab4e1877a917dc83dabedef86 (diff)
parentaf75836bb4622ce286f480b55e6a070fc7a5b105 (diff)
downloadmobly-bundled-snippets-363a22ae26a277dfbf6c7a0c6596d1a7c08a39f1.tar.gz
Merge pull request #169 from stplaydog/btfix
Solve permission issues when performing btDiscoverAndGetResults
-rw-r--r--src/main/AndroidManifest.xml2
-rw-r--r--src/main/java/com/google/android/mobly/snippet/bundled/WifiManagerSnippet.java37
-rw-r--r--src/main/java/com/google/android/mobly/snippet/bundled/bluetooth/BluetoothAdapterSnippet.java30
-rw-r--r--src/main/java/com/google/android/mobly/snippet/bundled/bluetooth/PairingBroadcastReceiver.java4
-rw-r--r--src/main/java/com/google/android/mobly/snippet/bundled/utils/Utils.java24
5 files changed, 61 insertions, 36 deletions
diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index 075fbe8..bcf52b2 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -17,6 +17,7 @@
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
+ <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
@@ -39,6 +40,7 @@
android:name="androidx.multidex.MultiDexApplication">
<meta-data
android:name="mobly-snippets"
+ android:testOnly="true"
android:value="com.google.android.mobly.snippet.bundled.AccountSnippet,
com.google.android.mobly.snippet.bundled.AudioSnippet,
com.google.android.mobly.snippet.bundled.bluetooth.BluetoothAdapterSnippet,
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 7e1a416..89a65d2 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
@@ -16,7 +16,6 @@
package com.google.android.mobly.snippet.bundled;
-import android.app.UiAutomation;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -44,6 +43,9 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.net.wifi.SupplicantState;
+
+import com.google.android.mobly.snippet.bundled.utils.Utils;
+
/** Snippet class exposing Android APIs in WifiManager. */
public class WifiManagerSnippet implements Snippet {
private static class WifiManagerSnippetException extends Exception {
@@ -52,10 +54,6 @@ public class WifiManagerSnippet implements Snippet {
public WifiManagerSnippetException(String msg) {
super(msg);
}
-
- public WifiManagerSnippetException(String msg, Throwable err) {
- super(msg, err);
- }
}
private static final int TIMEOUT_TOGGLE_STATE = 30;
@@ -69,7 +67,7 @@ public class WifiManagerSnippet implements Snippet {
mWifiManager =
(WifiManager)
mContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
- adaptShellPermissionIfRequired();
+ Utils.adaptShellPermissionIfRequired(mContext);
}
@Rpc(
@@ -403,33 +401,6 @@ public class WifiManagerSnippet implements Snippet {
@Override
public void shutdown() {}
- /**
- * Elevates permission as require for proper wifi controls.
- *
- * Starting in Android Q (29), additional restrictions are added for wifi operation. See
- * below Android Q privacy changes for additional details.
- * https://developer.android.com/preview/privacy/camera-connectivity
- *
- * @throws Throwable if failed to cleanup connection with UiAutomation
- */
- private void adaptShellPermissionIfRequired() throws Throwable {
- if (mContext.getApplicationContext().getApplicationInfo().targetSdkVersion >= 29
- && Build.VERSION.SDK_INT >= 29) {
- Log.d("Elevating permission require to enable support for wifi operation in Android Q+");
- UiAutomation uia = InstrumentationRegistry.getInstrumentation().getUiAutomation();
- uia.adoptShellPermissionIdentity();
- try {
- Class<?> cls = Class.forName("android.app.UiAutomation");
- Method destroyMethod = cls.getDeclaredMethod("destroy");
- destroyMethod.invoke(uia);
- } catch (NoSuchMethodException
- | IllegalAccessException
- | ClassNotFoundException
- | InvocationTargetException e) {
- throw new WifiManagerSnippetException("Failed to cleaup Ui Automation", e);
- }
- }
- }
private class WifiScanReceiver extends BroadcastReceiver {
diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/bluetooth/BluetoothAdapterSnippet.java b/src/main/java/com/google/android/mobly/snippet/bundled/bluetooth/BluetoothAdapterSnippet.java
index 2fd836b..71061fe 100644
--- a/src/main/java/com/google/android/mobly/snippet/bundled/bluetooth/BluetoothAdapterSnippet.java
+++ b/src/main/java/com/google/android/mobly/snippet/bundled/bluetooth/BluetoothAdapterSnippet.java
@@ -36,7 +36,10 @@ 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.util.ArrayList;
+import java.util.Collections;
import java.util.List;
+import java.util.HashMap;
+import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
@@ -69,9 +72,13 @@ public class BluetoothAdapterSnippet implements Snippet {
private static final ConcurrentHashMap<String, BluetoothDevice> mDiscoveryResults =
new ConcurrentHashMap<>();
private volatile boolean mIsDiscoveryFinished = false;
+ private final Map<String, BroadcastReceiver> mReceivers;
- public BluetoothAdapterSnippet() {
+ public BluetoothAdapterSnippet() throws Throwable {
mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ // Use a synchronized map to avoid racing problems
+ mReceivers = Collections.synchronizedMap(new HashMap<String, BroadcastReceiver>());
+ Utils.adaptShellPermissionIfRequired(mContext);
mPackageManager = mContext.getPackageManager();
}
@@ -193,6 +200,20 @@ public class BluetoothAdapterSnippet implements Snippet {
return mBluetoothAdapter.getName();
}
+ @Rpc(description = "Automatically confirm the incoming BT pairing request.")
+ public void btStartAutoAcceptIncomingPairRequest() throws Throwable {
+ BroadcastReceiver receiver = new PairingBroadcastReceiver(mContext);
+ mContext.registerReceiver(
+ receiver, PairingBroadcastReceiver.filter);
+ mReceivers.put("AutoAcceptIncomingPairReceiver", receiver);
+ }
+
+ @Rpc(description = "Stop the incoming BT pairing request.")
+ public void btStopAutoAcceptIncomingPairRequest() throws Throwable {
+ BroadcastReceiver receiver = mReceivers.remove("AutoAcceptIncomingPairReceiver");
+ mContext.unregisterReceiver(receiver);
+ }
+
@Rpc(description = "Returns the hardware address of the local Bluetooth adapter.")
public String btGetAddress() {
return mBluetoothAdapter.getAddress();
@@ -369,7 +390,12 @@ public class BluetoothAdapterSnippet implements Snippet {
}
@Override
- public void shutdown() {}
+ public void shutdown() {
+ for (Map.Entry<String, BroadcastReceiver> entry : mReceivers.entrySet()) {
+ mContext.unregisterReceiver(entry.getValue());
+ }
+ mReceivers.clear();
+ }
private class BluetoothScanReceiver extends BroadcastReceiver {
diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/bluetooth/PairingBroadcastReceiver.java b/src/main/java/com/google/android/mobly/snippet/bundled/bluetooth/PairingBroadcastReceiver.java
index 0cfd362..69ae433 100644
--- a/src/main/java/com/google/android/mobly/snippet/bundled/bluetooth/PairingBroadcastReceiver.java
+++ b/src/main/java/com/google/android/mobly/snippet/bundled/bluetooth/PairingBroadcastReceiver.java
@@ -8,14 +8,16 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import com.google.android.mobly.snippet.util.Log;
+import com.google.android.mobly.snippet.bundled.utils.Utils;
@TargetApi(Build.VERSION_CODES.KITKAT)
public class PairingBroadcastReceiver extends BroadcastReceiver {
private final Context mContext;
public static IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST);
- public PairingBroadcastReceiver(Context context) {
+ public PairingBroadcastReceiver(Context context) throws Throwable {
mContext = context;
+ Utils.adaptShellPermissionIfRequired(mContext);
}
public void onReceive(Context context, Intent intent) {
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 376bcb5..bd9a76f 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
@@ -16,9 +16,14 @@
package com.google.android.mobly.snippet.bundled.utils;
+import android.app.UiAutomation;
+import android.os.Build;
+import android.content.Context;
+import androidx.test.platform.app.InstrumentationRegistry;
import com.google.android.mobly.snippet.bundled.SmsSnippet;
import com.google.android.mobly.snippet.event.EventCache;
import com.google.android.mobly.snippet.event.SnippetEvent;
+import com.google.android.mobly.snippet.util.Log;
import com.google.common.primitives.Primitives;
import com.google.common.reflect.TypeToken;
import java.lang.reflect.InvocationTargetException;
@@ -210,4 +215,23 @@ public final class Utils {
}
return new String(hexChars);
}
+
+ public static void adaptShellPermissionIfRequired(Context context) throws Throwable {
+ if (context.getApplicationContext().getApplicationInfo().targetSdkVersion >= 29
+ && Build.VERSION.SDK_INT >= 29) {
+ Log.d("Elevating permission require to enable support for privileged operation in Android Q+");
+ UiAutomation uia = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ uia.adoptShellPermissionIdentity();
+ try {
+ Class<?> cls = Class.forName("android.app.UiAutomation");
+ Method destroyMethod = cls.getDeclaredMethod("destroy");
+ destroyMethod.invoke(uia);
+ } catch (NoSuchMethodException
+ | IllegalAccessException
+ | ClassNotFoundException
+ | InvocationTargetException e) {
+ throw new RuntimeException("Failed to cleaup Ui Automation", e);
+ }
+ }
+ }
}