aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXianyuan Jia <xianyuanjia@google.com>2023-05-31 16:43:19 -0700
committerXianyuan Jia <xianyuanjia@google.com>2023-05-31 16:47:14 -0700
commit0572ba0c003cf5085e70857effbbc0d7307f916c (patch)
treeeff080336e00b85aa5a9bca21392b3854e9bb5a3
parentc581b7acf6288f91011d28742cc73d1ef276b2ca (diff)
parentfbd882fa01fb2134303c697195ab93b739e4ee87 (diff)
downloadmobly-bundled-snippets-0572ba0c003cf5085e70857effbbc0d7307f916c.tar.gz
Merge remote-tracking branch 'aosp/upstream-master' into mbs-update
Bug: 283858728 Test: local Change-Id: If62871b17b14740ea56b45d8ccce615d53f63635
-rw-r--r--Android.bp1
-rw-r--r--METADATA4
-rw-r--r--build.gradle28
-rw-r--r--gradle/wrapper/gradle-wrapper.properties2
-rw-r--r--src/main/AndroidManifest.xml2
-rw-r--r--src/main/java/com/google/android/mobly/snippet/bundled/AudioSnippet.java21
-rw-r--r--src/main/java/com/google/android/mobly/snippet/bundled/WifiManagerSnippet.java12
-rw-r--r--src/main/java/com/google/android/mobly/snippet/bundled/bluetooth/BluetoothAdapterSnippet.java53
-rw-r--r--src/main/java/com/google/android/mobly/snippet/bundled/utils/JsonSerializer.java41
-rw-r--r--src/main/java/com/google/android/mobly/snippet/bundled/utils/RpcEnum.java7
10 files changed, 131 insertions, 40 deletions
diff --git a/Android.bp b/Android.bp
index 6277a91..a3d1737 100644
--- a/Android.bp
+++ b/Android.bp
@@ -35,6 +35,7 @@ android_library {
"gson",
"guava",
"mobly-snippet-lib",
+ "androidx.test.uiautomator_uiautomator",
],
srcs: [
"src/main/**/*.java",
diff --git a/METADATA b/METADATA
index dc73649..51a155a 100644
--- a/METADATA
+++ b/METADATA
@@ -13,7 +13,7 @@ third_party {
type: GIT
value: "https://github.com/google/mobly-bundled-snippets"
}
- version: "1ff2867fb8645c5792656bd4b822d70bbce44ec2"
- last_upgrade_date { year: 2021 month: 12 day: 8 }
+ version: "fbd882fa01fb2134303c697195ab93b739e4ee87"
+ last_upgrade_date { year: 2023 month: 5 day: 31 }
license_type: NOTICE
}
diff --git a/build.gradle b/build.gradle
index 82e103d..99839ee 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,10 +1,10 @@
buildscript {
repositories {
- jcenter()
google()
+ mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:4.1.2'
+ classpath 'com.android.tools.build:gradle:7.3.1'
// NOTE: Do not place your application dependencies here.
}
@@ -17,7 +17,7 @@ plugins {
allprojects {
repositories {
google()
- jcenter()
+ mavenCentral()
}
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
@@ -29,14 +29,12 @@ allprojects {
apply plugin: 'com.android.application'
android {
- compileSdkVersion 29
- buildToolsVersion "30.0.2"
+ compileSdkVersion 31
defaultConfig {
applicationId "com.google.android.mobly.snippet.bundled"
- minSdkVersion 15
- // Set target to 22 to avoid having to deal with runtime permissions.
- targetSdkVersion 22
+ minSdkVersion 26
+ targetSdkVersion 31
versionCode 1
versionName "0.0.1"
setProperty("archivesBaseName", "mobly-bundled-snippets")
@@ -71,14 +69,16 @@ artifacts {
}
dependencies {
- implementation 'androidx.test:runner:1.3.0'
- implementation 'com.google.android.mobly:mobly-snippet-lib:1.2.0'
+ implementation 'androidx.test:runner:1.5.2'
+ implementation 'com.android.support:multidex:1.0.3'
+ implementation 'com.android.support.test.uiautomator:uiautomator-v18:2.1.3'
+ implementation 'com.google.android.mobly:mobly-snippet-lib:1.4.0'
implementation 'com.google.code.gson:gson:2.8.6'
- implementation 'com.google.guava:guava:30.1-jre'
- implementation 'com.google.errorprone:error_prone_annotations:2.5.1'
+ implementation 'com.google.guava:guava:31.0.1-jre'
+ implementation 'com.google.errorprone:error_prone_annotations:2.15.0'
- testImplementation 'com.google.errorprone:error_prone_annotations:2.5.1'
- testImplementation 'com.google.guava:guava:30.1-jre'
+ testImplementation 'com.google.errorprone:error_prone_annotations:2.15.0'
+ testImplementation 'com.google.guava:guava:31.0.1-jre'
testImplementation 'com.google.truth:truth:1.1.2'
testImplementation 'junit:junit:4.13.2'
}
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 1ba6cc2..e9e3b96 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index 795c063..08341c3 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -11,7 +11,9 @@
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+ <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
+ <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<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" />
diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/AudioSnippet.java b/src/main/java/com/google/android/mobly/snippet/bundled/AudioSnippet.java
index 9b4874f..10a2c07 100644
--- a/src/main/java/com/google/android/mobly/snippet/bundled/AudioSnippet.java
+++ b/src/main/java/com/google/android/mobly/snippet/bundled/AudioSnippet.java
@@ -104,6 +104,24 @@ public class AudioSnippet implements Snippet {
AudioManager.STREAM_VOICE_CALL, value, 0 /* flags, 0 = no flags */);
}
+ @Rpc(description = "Gets the alarm volume.")
+ public Integer getAlarmVolume() {
+ return mAudioManager.getStreamVolume(AudioManager.STREAM_ALARM);
+ }
+
+ @Rpc(description = "Gets the maximum alarm volume value.")
+ public int getAlarmMaxVolume() {
+ return mAudioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM);
+ }
+
+ @Rpc(
+ description =
+ "Sets the alarm stream volume. The minimum value is 0. Use 'getAlarmMaxVolume'"
+ + " to determine the maximum.")
+ public void setAlarmVolume(Integer value) {
+ mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM, value, 0 /* flags, 0 = no flags */);
+ }
+
@Rpc(description = "Silences all audio streams.")
public void muteAll() throws Exception {
/* Get numStreams from AudioSystem through reflection. If for some reason this fails,
@@ -129,6 +147,9 @@ public class AudioSnippet implements Snippet {
setMusicVolume(0);
}
+ @Rpc(description = "Mute alarm stream.")
+ public void muteAlarm() { setAlarmVolume(0); }
+
@Override
public void shutdown() {}
}
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 cf577c3..7e1a416 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
@@ -88,8 +88,18 @@ public class WifiManagerSnippet implements Snippet {
failedConfigs.add(config);
}
}
+
+ // If removeNetwork is called on a network with both an open and OWE config, it will remove
+ // both. The subsequent call on the same network will fail. The clear operation may succeed
+ // even if failures appear in the log below.
if (!failedConfigs.isEmpty()) {
- throw new WifiManagerSnippetException("Failed to remove networks: " + failedConfigs);
+ Log.e("Encountered error while removing networks: " + failedConfigs);
+ }
+
+ // Re-check configured configs list to ensure that it is cleared
+ unremovedConfigs = mWifiManager.getConfiguredNetworks();
+ if (!unremovedConfigs.isEmpty()) {
+ throw new WifiManagerSnippetException("Failed to remove networks: " + unremovedConfigs);
}
}
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 6e66e43..c16a2b0 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
@@ -25,6 +25,10 @@ import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
import com.google.android.mobly.snippet.Snippet;
import com.google.android.mobly.snippet.bundled.utils.JsonSerializer;
import com.google.android.mobly.snippet.bundled.utils.Utils;
@@ -34,6 +38,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Pattern;
import org.json.JSONException;
/** Snippet class exposing Android APIs in BluetoothAdapter. */
@@ -46,6 +51,10 @@ public class BluetoothAdapterSnippet implements Snippet {
public BluetoothAdapterSnippetException(String msg) {
super(msg);
}
+
+ public BluetoothAdapterSnippetException(String msg, Throwable err) {
+ super(msg, err);
+ }
}
// Timeout to measure consistent BT state.
@@ -93,6 +102,16 @@ public class BluetoothAdapterSnippet implements Snippet {
return null;
}
+ /* Gets the UiDevice instance for UI operations. */
+ private static UiDevice getUiDevice() throws BluetoothAdapterSnippetException {
+ try {
+ return UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ } catch (IllegalStateException e) {
+ throw new BluetoothAdapterSnippetException("Failed to get UiDevice. Please ensure that "
+ + "no other UiAutomation service is running.", e);
+ }
+ }
+
@Rpc(description = "Enable bluetooth with a 30s timeout.")
public void btEnable() throws BluetoothAdapterSnippetException, InterruptedException {
if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
@@ -100,7 +119,19 @@ public class BluetoothAdapterSnippet implements Snippet {
}
waitForStableBtState();
- if (!mBluetoothAdapter.enable()) {
+ if (Build.VERSION.SDK_INT >= 33) {
+ // BluetoothAdapter#enable is removed from public SDK for 33 and above, so uses an
+ // intent instead.
+ UiDevice uiDevice = getUiDevice();
+ Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
+ enableIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ // Triggers the system UI popup to ask for explicit permission.
+ mContext.startActivity(enableIntent);
+ // Clicks the "ALLOW" button.
+ BySelector allowButtonSelector = By.text(TEXT_PATTERN_ALLOW).clickable(true);
+ uiDevice.wait(Until.findObject(allowButtonSelector), 10);
+ uiDevice.findObject(allowButtonSelector).click();
+ } else if (!mBluetoothAdapter.enable()) {
throw new BluetoothAdapterSnippetException("Failed to start enabling bluetooth.");
}
if (!Utils.waitUntil(
@@ -200,7 +231,20 @@ public class BluetoothAdapterSnippet implements Snippet {
throw new BluetoothAdapterSnippetException(
"Bluetooth is not enabled, cannot become discoverable.");
}
- if (Build.VERSION.SDK_INT > 29) {
+ if (Build.VERSION.SDK_INT >= 31) {
+ // BluetoothAdapter#setScanMode is removed from public SDK for 31 and above, so uses an
+ // intent instead.
+ UiDevice uiDevice = getUiDevice();
+ Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
+ discoverableIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, duration);
+ // Triggers the system UI popup to ask for explicit permission.
+ mContext.startActivity(discoverableIntent);
+ // Clicks the "ALLOW" button.
+ BySelector allowButtonSelector = By.text(TEXT_PATTERN_ALLOW).clickable(true);
+ uiDevice.wait(Until.findObject(allowButtonSelector), 10);
+ uiDevice.findObject(allowButtonSelector).click();
+ } else if (Build.VERSION.SDK_INT >= 30) {
if (!(boolean)
Utils.invokeByReflection(
mBluetoothAdapter,
@@ -221,6 +265,9 @@ public class BluetoothAdapterSnippet implements Snippet {
}
}
+ private static final Pattern TEXT_PATTERN_ALLOW =
+ Pattern.compile("allow", Pattern.CASE_INSENSITIVE);
+
@Rpc(description = "Cancel ongoing bluetooth discovery.")
public void btCancelDiscovery() throws BluetoothAdapterSnippetException {
if (!mBluetoothAdapter.isDiscovering()) {
@@ -305,7 +352,7 @@ public class BluetoothAdapterSnippet implements Snippet {
return;
}
}
- throw new NoSuchElementException("No device wih address " + deviceAddress + " is paired.");
+ throw new NoSuchElementException("No device with address " + deviceAddress + " is paired.");
}
@Override
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 82e1e4f..82e6f7c 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
@@ -27,6 +27,7 @@ import android.net.wifi.WifiInfo;
import android.os.Build;
import android.os.Bundle;
import android.os.ParcelUuid;
+import android.util.SparseArray;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.lang.reflect.Modifier;
@@ -41,17 +42,13 @@ import org.json.JSONObject;
* A collection of methods used to serialize data types defined in Android API into JSON strings.
*/
public class JsonSerializer {
- private static Gson mGson;
-
- public JsonSerializer() {
- GsonBuilder builder = new GsonBuilder();
- mGson =
- builder.serializeNulls()
- .excludeFieldsWithModifiers(Modifier.STATIC)
- .enableComplexMapKeySerialization()
- .disableInnerClassSerialization()
- .create();
- }
+ private static final Gson gson =
+ new GsonBuilder()
+ .serializeNulls()
+ .excludeFieldsWithModifiers(Modifier.STATIC)
+ .enableComplexMapKeySerialization()
+ .disableInnerClassSerialization()
+ .create();
/**
* Remove the extra quotation marks from the beginning and the end of a string.
@@ -89,11 +86,11 @@ public class JsonSerializer {
* @throws JSONException
*/
private JSONObject defaultSerialization(Object data) throws JSONException {
- return new JSONObject(mGson.toJson(data));
+ return new JSONObject(gson.toJson(data));
}
private JSONObject serializeDhcpInfo(DhcpInfo data) throws JSONException {
- JSONObject result = new JSONObject(mGson.toJson(data));
+ JSONObject result = new JSONObject(gson.toJson(data));
int ipAddress = data.ipAddress;
byte[] addressBytes = {
(byte) (0xff & ipAddress),
@@ -111,14 +108,14 @@ public class JsonSerializer {
}
private JSONObject serializeWifiConfiguration(WifiConfiguration data) throws JSONException {
- JSONObject result = new JSONObject(mGson.toJson(data));
+ JSONObject result = new JSONObject(gson.toJson(data));
result.put("Status", WifiConfiguration.Status.strings[data.status]);
result.put("SSID", trimQuotationMarks(data.SSID));
return result;
}
private JSONObject serializeWifiInfo(WifiInfo data) throws JSONException {
- JSONObject result = new JSONObject(mGson.toJson(data));
+ JSONObject result = new JSONObject(gson.toJson(data));
result.put("SSID", trimQuotationMarks(data.getSSID()));
for (SupplicantState state : SupplicantState.values()) {
if (data.getSupplicantState().equals(state)) {
@@ -187,6 +184,20 @@ public class JsonSerializer {
Bundle result = new Bundle();
result.putString("DeviceName", record.getDeviceName());
result.putInt("TxPowerLevel", record.getTxPowerLevel());
+ result.putBundle(
+ "manufacturerSpecificData", serializeBleScanManufacturerSpecificData(record));
+ return result;
+ }
+
+ /** Serialize manufacturer specific data from ScanRecord for Bluetooth LE. */
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ private Bundle serializeBleScanManufacturerSpecificData(ScanRecord record) {
+ Bundle result = new Bundle();
+ SparseArray<byte[]> sparseArray = record.getManufacturerSpecificData();
+ for (int i = 0; i < sparseArray.size(); i++) {
+ int key = sparseArray.keyAt(i);
+ result.putByteArray(String.valueOf(key), sparseArray.get(key));
+ }
return result;
}
diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/utils/RpcEnum.java b/src/main/java/com/google/android/mobly/snippet/bundled/utils/RpcEnum.java
index d3d95ae..d6442a8 100644
--- a/src/main/java/com/google/android/mobly/snippet/bundled/utils/RpcEnum.java
+++ b/src/main/java/com/google/android/mobly/snippet/bundled/utils/RpcEnum.java
@@ -29,8 +29,8 @@ import com.google.common.collect.ImmutableBiMap;
public class RpcEnum {
private final ImmutableBiMap<String, Integer> mEnums;
- private RpcEnum(ImmutableBiMap.Builder<String, Integer> builder, int minSdk) {
- mEnums = builder.build();
+ private RpcEnum(ImmutableBiMap.Builder<String, Integer> builder) {
+ mEnums = builder.buildOrThrow();
}
/**
@@ -64,7 +64,6 @@ public class RpcEnum {
/** Builder for RpcEnum. */
public static class Builder {
private final ImmutableBiMap.Builder<String, Integer> builder;
- public int minSdk = 0;
public Builder() {
builder = new ImmutableBiMap.Builder<>();
@@ -83,7 +82,7 @@ public class RpcEnum {
}
public RpcEnum build() {
- return new RpcEnum(builder, minSdk);
+ return new RpcEnum(builder);
}
}
}