diff options
author | Xianyuan Jia <xianyuanjia@google.com> | 2023-05-31 16:43:19 -0700 |
---|---|---|
committer | Xianyuan Jia <xianyuanjia@google.com> | 2023-05-31 16:47:14 -0700 |
commit | 0572ba0c003cf5085e70857effbbc0d7307f916c (patch) | |
tree | eff080336e00b85aa5a9bca21392b3854e9bb5a3 | |
parent | c581b7acf6288f91011d28742cc73d1ef276b2ca (diff) | |
parent | fbd882fa01fb2134303c697195ab93b739e4ee87 (diff) | |
download | mobly-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.bp | 1 | ||||
-rw-r--r-- | METADATA | 4 | ||||
-rw-r--r-- | build.gradle | 28 | ||||
-rw-r--r-- | gradle/wrapper/gradle-wrapper.properties | 2 | ||||
-rw-r--r-- | src/main/AndroidManifest.xml | 2 | ||||
-rw-r--r-- | src/main/java/com/google/android/mobly/snippet/bundled/AudioSnippet.java | 21 | ||||
-rw-r--r-- | src/main/java/com/google/android/mobly/snippet/bundled/WifiManagerSnippet.java | 12 | ||||
-rw-r--r-- | src/main/java/com/google/android/mobly/snippet/bundled/bluetooth/BluetoothAdapterSnippet.java | 53 | ||||
-rw-r--r-- | src/main/java/com/google/android/mobly/snippet/bundled/utils/JsonSerializer.java | 41 | ||||
-rw-r--r-- | src/main/java/com/google/android/mobly/snippet/bundled/utils/RpcEnum.java | 7 |
10 files changed, 131 insertions, 40 deletions
@@ -35,6 +35,7 @@ android_library { "gson", "guava", "mobly-snippet-lib", + "androidx.test.uiautomator_uiautomator", ], srcs: [ "src/main/**/*.java", @@ -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); } } } |