From 3fe3a3b3c4284f8dd050a922d84c7cd3c0fe2df5 Mon Sep 17 00:00:00 2001 From: VitaliDim <143655987+VitaliDim@users.noreply.github.com> Date: Mon, 16 Oct 2023 11:43:01 -0700 Subject: Add RECEIVER_EXPORTED flag to portrait sys ui register receiver calls; (#176) --- .../google/android/mobly/snippet/bundled/SmsSnippet.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/SmsSnippet.java b/src/main/java/com/google/android/mobly/snippet/bundled/SmsSnippet.java index e8a84c9..362a1b7 100644 --- a/src/main/java/com/google/android/mobly/snippet/bundled/SmsSnippet.java +++ b/src/main/java/com/google/android/mobly/snippet/bundled/SmsSnippet.java @@ -84,7 +84,13 @@ public class SmsSnippet implements Snippet { if (message.length() > MAX_CHAR_COUNT_PER_SMS) { ArrayList parts = mSmsManager.divideMessage(message); receiver.setExpectedMessageCount(parts.size()); - mContext.registerReceiver(receiver, new IntentFilter(SMS_SENT_ACTION)); + if (Build.VERSION.SDK_INT >= 33) { + mContext.registerReceiver(receiver, new IntentFilter(SMS_SENT_ACTION), null, + null, + Context.RECEIVER_EXPORTED); + } else { + mContext.registerReceiver(receiver, new IntentFilter(SMS_SENT_ACTION)); + } mSmsManager.sendMultipartTextMessage( /* destinationAddress= */ phoneNumber, /* scAddress= */ null, @@ -107,7 +113,13 @@ public class SmsSnippet implements Snippet { /* intent= */ new Intent(SMS_SENT_ACTION), /* flags= */ PendingIntent.FLAG_IMMUTABLE); receiver.setExpectedMessageCount(1); - mContext.registerReceiver(receiver, new IntentFilter(SMS_SENT_ACTION)); + if (Build.VERSION.SDK_INT >= 33) { + mContext.registerReceiver(receiver, new IntentFilter(SMS_SENT_ACTION), null, + null, + Context.RECEIVER_EXPORTED); + } else { + mContext.registerReceiver(receiver, new IntentFilter(SMS_SENT_ACTION)); + } mSmsManager.sendTextMessage( /* destinationAddress= */ phoneNumber, /* scAddress= */ null, -- cgit v1.2.3 From 0422da4d29b1addb3bd59687e25ce2ccdc1539c5 Mon Sep 17 00:00:00 2001 From: Kolin Lu Date: Mon, 18 Dec 2023 12:26:12 -0800 Subject: Fix Error Prone (#178) - StaticQualifiedUsingExpression: Static method serializeBluetoothDevice should not be accessed from an object instance; instead use JsonSerializer.serializeBluetoothDevice - MissingOverride: onReceive implements method in BroadcastReceiver; expected @Override - RemoveUnusedImports: Unused imports: java.lang.reflect.InvocationTargetException, java.lang.reflect.Method --- .../com/google/android/mobly/snippet/bundled/WifiManagerSnippet.java | 2 -- .../mobly/snippet/bundled/bluetooth/BluetoothAdapterSnippet.java | 2 +- .../mobly/snippet/bundled/bluetooth/PairingBroadcastReceiver.java | 1 + 3 files changed, 2 insertions(+), 3 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 89a65d2..e457dc3 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 @@ -35,8 +35,6 @@ import com.google.android.mobly.snippet.bundled.utils.Utils; import com.google.android.mobly.snippet.rpc.Rpc; import com.google.android.mobly.snippet.rpc.RpcMinSdk; import com.google.android.mobly.snippet.util.Log; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import org.json.JSONArray; 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 71061fe..07f51e2 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 @@ -343,7 +343,7 @@ public class BluetoothAdapterSnippet implements Snippet { throws BluetoothAdapterSnippetException, InterruptedException, JSONException { ArrayList pairedDevices = new ArrayList<>(); for (BluetoothDevice device : mBluetoothAdapter.getBondedDevices()) { - pairedDevices.add(mJsonSerializer.serializeBluetoothDevice(device)); + pairedDevices.add(JsonSerializer.serializeBluetoothDevice(device)); } return pairedDevices; } 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 69ae433..f704897 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 @@ -20,6 +20,7 @@ public class PairingBroadcastReceiver extends BroadcastReceiver { Utils.adaptShellPermissionIfRequired(mContext); } + @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(BluetoothDevice.ACTION_PAIRING_REQUEST)) { -- cgit v1.2.3 From 0d72c2702677276babac61e54dd79d5b54afe577 Mon Sep 17 00:00:00 2001 From: kolinlu Date: Mon, 18 Dec 2023 17:21:21 -0800 Subject: Refactor manufacturerSpecificData to ManufacturerSpecificData `manufacturerSpecificData` is one of arguments when adding manufacturer specific data (see `AdvertiseData.Builder#addManufacturerData`) Before Change: ``` ad.mbs.bleStartAdvertising( advertiseSettings, { 'IncludeDeviceName': True, 'ManufacturerData': {'ManufacturerId': 224}, 'ManufacturerSpecificData': '[0x78, 0x01]', }, ) ``` After Change: ``` ad.mbs.bleStartAdvertising( advertiseSettings, { 'IncludeDeviceName': True, 'ManufacturerData': { 'ManufacturerId': 224, 'ManufacturerSpecificData': '[0x78, 0x01]', }, }, ) ``` --- .../google/android/mobly/snippet/bundled/utils/JsonDeserializer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/utils/JsonDeserializer.java b/src/main/java/com/google/android/mobly/snippet/bundled/utils/JsonDeserializer.java index a3d5325..c7d5a91 100644 --- a/src/main/java/com/google/android/mobly/snippet/bundled/utils/JsonDeserializer.java +++ b/src/main/java/com/google/android/mobly/snippet/bundled/utils/JsonDeserializer.java @@ -101,7 +101,8 @@ public class JsonDeserializer { JSONObject manufacturerData = jsonObject.getJSONObject("ManufacturerData"); int manufacturerId = manufacturerData.getInt("ManufacturerId"); byte[] manufacturerSpecificData = - Base64.decode(jsonObject.getString("ManufacturerSpecificData"), Base64.DEFAULT); + Base64.decode( + manufacturerData.getString("ManufacturerSpecificData"), Base64.DEFAULT); builder.addManufacturerData(manufacturerId, manufacturerSpecificData); } return builder.build(); -- cgit v1.2.3 From e8dd7dc10ebdf2aed63dcda1914e7ff85a993926 Mon Sep 17 00:00:00 2001 From: amytsengtw <154878544+amytsengtw@users.noreply.github.com> Date: Tue, 26 Dec 2023 17:02:24 +0800 Subject: Use getCallStateForSubscription to replace deprecated getCallState getCallState was deprecated, use getCallStateForSubscription to get the call state. https://developer.android.com/reference/android/telephony/TelephonyManager#getCallState%28%29 --- .../java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java b/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java index 21c5d1e..1463915 100644 --- a/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java +++ b/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java @@ -47,7 +47,7 @@ public class TelephonySnippet implements Snippet { "Gets the call state for the default subscription. Call state values are" + "0: IDLE, 1: RINGING, 2: OFFHOOK") public int getTelephonyCallState() { - return mTelephonyManager.getCallState(); + return mTelephonyManager.getCallStateForSubscription(); } @Rpc( -- cgit v1.2.3 From 5f6542f0c33f66d730c77daa9be14707b80bcb81 Mon Sep 17 00:00:00 2001 From: amytsengtw <154878544+amytsengtw@users.noreply.github.com> Date: Wed, 27 Dec 2023 10:02:21 +0800 Subject: Update TelephonySnippet.java add build version check for getCallStateForSubscription is added in SDK 31 --- .../com/google/android/mobly/snippet/bundled/TelephonySnippet.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java b/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java index 1463915..928fd93 100644 --- a/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java +++ b/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java @@ -55,7 +55,11 @@ public class TelephonySnippet implements Snippet { "Returns a constant indicating the radio technology (network type) currently" + "in use on the device for data transmission.") public int getDataNetworkType() { - return mTelephonyManager.getDataNetworkType(); + if (Build.VERSION.SDK_INT < 31) { + return mTelephonyManager.getDataNetworkType(); + } else { + return mTelephonyManager.getCallStateForSubscription(); + } } @Rpc( -- cgit v1.2.3 From f83b07c68dd834d8926a3730edf0a942f8884280 Mon Sep 17 00:00:00 2001 From: amytsengtw <154878544+amytsengtw@users.noreply.github.com> Date: Wed, 27 Dec 2023 10:17:05 +0800 Subject: Update TelephonySnippet.java --- .../android/mobly/snippet/bundled/TelephonySnippet.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java b/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java index 928fd93..26bae43 100644 --- a/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java +++ b/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java @@ -47,7 +47,11 @@ public class TelephonySnippet implements Snippet { "Gets the call state for the default subscription. Call state values are" + "0: IDLE, 1: RINGING, 2: OFFHOOK") public int getTelephonyCallState() { - return mTelephonyManager.getCallStateForSubscription(); + if (Build.VERSION.SDK_INT < 31) { + return mTelephonyManager.getCallState(); + } else { + return mTelephonyManager.getCallStateForSubscription(); + } } @Rpc( @@ -55,11 +59,7 @@ public class TelephonySnippet implements Snippet { "Returns a constant indicating the radio technology (network type) currently" + "in use on the device for data transmission.") public int getDataNetworkType() { - if (Build.VERSION.SDK_INT < 31) { - return mTelephonyManager.getDataNetworkType(); - } else { - return mTelephonyManager.getCallStateForSubscription(); - } + return mTelephonyManager.getDataNetworkType(); } @Rpc( -- cgit v1.2.3 From b0c54ad43989a41d83bae65a25f5cca1b8e7c058 Mon Sep 17 00:00:00 2001 From: amytsengtw <154878544+amytsengtw@users.noreply.github.com> Date: Wed, 27 Dec 2023 10:21:01 +0800 Subject: Update TelephonySnippet.java --- .../com/google/android/mobly/snippet/bundled/TelephonySnippet.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java b/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java index 26bae43..49c6ab9 100644 --- a/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java +++ b/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java @@ -59,7 +59,11 @@ public class TelephonySnippet implements Snippet { "Returns a constant indicating the radio technology (network type) currently" + "in use on the device for data transmission.") public int getDataNetworkType() { - return mTelephonyManager.getDataNetworkType(); + if (Build.VERSION.SDK_INT < 30) { + return mTelephonyManager.getNetworkType(); + } else { + return mTelephonyManager.getDataNetworkType(); + } } @Rpc( -- cgit v1.2.3 From c907e83d8aed8cef1e511adb72d16406fd543ea9 Mon Sep 17 00:00:00 2001 From: kolinlu Date: Wed, 27 Dec 2023 15:25:30 -0800 Subject: Fix error: package Build does not exist --- .../java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java b/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java index 49c6ab9..edcbf65 100644 --- a/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java +++ b/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java @@ -17,6 +17,7 @@ package com.google.android.mobly.snippet.bundled; import android.content.Context; +import android.os.Build; import android.telephony.TelephonyManager; import androidx.test.platform.app.InstrumentationRegistry; import com.google.android.mobly.snippet.Snippet; -- cgit v1.2.3 From 689db412435f15945fd866a28a0f63d70495276c Mon Sep 17 00:00:00 2001 From: haoma Date: Thu, 4 Jan 2024 15:19:21 +0800 Subject: Add new function: String getPhoneNumber(int simSlot) Add new variant: int getTelephonyCallState(int simSlot) --- build.gradle | 6 ++-- .../mobly/snippet/bundled/TelephonySnippet.java | 42 ++++++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 99839ee..5958ee9 100644 --- a/build.gradle +++ b/build.gradle @@ -29,12 +29,12 @@ allprojects { apply plugin: 'com.android.application' android { - compileSdkVersion 31 + compileSdk 34 defaultConfig { applicationId "com.google.android.mobly.snippet.bundled" - minSdkVersion 26 - targetSdkVersion 31 + minSdk 26 + targetSdk 34 versionCode 1 versionName "0.0.1" setProperty("archivesBaseName", "mobly-bundled-snippets") diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java b/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java index edcbf65..f7e5c8a 100644 --- a/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java +++ b/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java @@ -18,6 +18,8 @@ package com.google.android.mobly.snippet.bundled; import android.content.Context; import android.os.Build; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import androidx.test.platform.app.InstrumentationRegistry; import com.google.android.mobly.snippet.Snippet; @@ -27,10 +29,12 @@ import com.google.android.mobly.snippet.rpc.Rpc; public class TelephonySnippet implements Snippet { private final TelephonyManager mTelephonyManager; + private final SubscriptionManager mSubscriptionManager; public TelephonySnippet() { Context context = InstrumentationRegistry.getInstrumentation().getContext(); mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + mSubscriptionManager = (SubscriptionManager) context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); } @Rpc(description = "Gets the line 1 phone number.") @@ -38,6 +42,22 @@ public class TelephonySnippet implements Snippet { return mTelephonyManager.getLine1Number(); } + @Rpc(description = "Gets phone number for the simSlot (slot# start from 0, only valid for API level > 32)." + + " API level <33 will always return phone number for simSlotIndex = 0") + public String getPhoneNumber(int simSlot) { + String thisNumber = ""; + + if (Build.VERSION.SDK_INT < 33) { + thisNumber = mTelephonyManager.getLine1Number(); + } else { + SubscriptionInfo mSubscriptionInfo = mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(simSlot); + if (mSubscriptionInfo != null) { + thisNumber = mSubscriptionManager.getPhoneNumber(mSubscriptionInfo.getSubscriptionId()); + } + } + return thisNumber; + } + @Rpc(description = "Returns the unique subscriber ID, for example, the IMSI for a GSM phone.") public String getSubscriberId() { return mTelephonyManager.getSubscriberId(); @@ -55,6 +75,28 @@ public class TelephonySnippet implements Snippet { } } + @Rpc( + description = + "Gets the call state for the simSlot (slot# start from 0, only valid for API level > 30). Call state values are" + + "0: IDLE, 1: RINGING, 2: OFFHOOK.") + public int getTelephonyCallState(int simSlot) { + int thisState = -1; + + if (Build.VERSION.SDK_INT < 31) { + thisState = mTelephonyManager.getCallState(); + } else { + SubscriptionInfo mSubscriptionInfo = mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(simSlot); + if (mSubscriptionInfo != null) { + thisState = + mTelephonyManager + .createForSubscriptionId(mSubscriptionInfo.getSubscriptionId()) + .getCallStateForSubscription(); + } + } + + return thisState; + } + @Rpc( description = "Returns a constant indicating the radio technology (network type) currently" -- cgit v1.2.3 From d270e876f2204e41dd99ec02c910fadf8f29cf29 Mon Sep 17 00:00:00 2001 From: haoma Date: Fri, 5 Jan 2024 17:04:32 +0800 Subject: Lower compileSdk and targetSdk to 33 --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 5958ee9..c88f93c 100644 --- a/build.gradle +++ b/build.gradle @@ -29,12 +29,12 @@ allprojects { apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 33 defaultConfig { applicationId "com.google.android.mobly.snippet.bundled" minSdk 26 - targetSdk 34 + targetSdk 33 versionCode 1 versionName "0.0.1" setProperty("archivesBaseName", "mobly-bundled-snippets") -- cgit v1.2.3 From efb63fed6a4630cd278d38b823d49a292f0f429c Mon Sep 17 00:00:00 2001 From: haoma Date: Mon, 8 Jan 2024 11:08:50 +0800 Subject: Merging functions by employing Default and Optional RPCs --- .../mobly/snippet/bundled/TelephonySnippet.java | 44 +++++++++++----------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java b/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java index f7e5c8a..2380b73 100644 --- a/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java +++ b/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java @@ -24,6 +24,7 @@ import android.telephony.TelephonyManager; import androidx.test.platform.app.InstrumentationRegistry; import com.google.android.mobly.snippet.Snippet; import com.google.android.mobly.snippet.rpc.Rpc; +import com.google.android.mobly.snippet.rpc.RpcOptional; /** Snippet class for telephony RPCs. */ public class TelephonySnippet implements Snippet { @@ -37,9 +38,20 @@ public class TelephonySnippet implements Snippet { mSubscriptionManager = (SubscriptionManager) context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); } - @Rpc(description = "Gets the line 1 phone number.") - public String getLine1Number() { - return mTelephonyManager.getLine1Number(); + @Rpc(description = "Gets the line 1 phone number, or optionally get phone number for the simSlot (slot# start from 0, only valid for API level > 32)") + public String getLine1Number(@RpcOptional Integer simSlot) { + String thisNumber = ""; + + if (Build.VERSION.SDK_INT < 33 || simSlot == null) { + thisNumber = mTelephonyManager.getLine1Number(); + } else{ + SubscriptionInfo mSubscriptionInfo = mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(simSlot.intValue()); + if (mSubscriptionInfo != null) { + thisNumber = mSubscriptionManager.getPhoneNumber(mSubscriptionInfo.getSubscriptionId()); + } + } + + return thisNumber; } @Rpc(description = "Gets phone number for the simSlot (slot# start from 0, only valid for API level > 32)." @@ -65,33 +77,23 @@ public class TelephonySnippet implements Snippet { @Rpc( description = - "Gets the call state for the default subscription. Call state values are" - + "0: IDLE, 1: RINGING, 2: OFFHOOK") - public int getTelephonyCallState() { - if (Build.VERSION.SDK_INT < 31) { - return mTelephonyManager.getCallState(); - } else { - return mTelephonyManager.getCallStateForSubscription(); - } - } - - @Rpc( - description = - "Gets the call state for the simSlot (slot# start from 0, only valid for API level > 30). Call state values are" - + "0: IDLE, 1: RINGING, 2: OFFHOOK.") - public int getTelephonyCallState(int simSlot) { + "Gets the call state for the default subscription or optionally get the call state for the simSlot (slot# start from 0, only valid for API level > 30)." + + " Call state values are 0: IDLE, 1: RINGING, 2: OFFHOOK") + public int getTelephonyCallState(@RpcOptional Integer simSlot) { int thisState = -1; if (Build.VERSION.SDK_INT < 31) { - thisState = mTelephonyManager.getCallState(); - } else { - SubscriptionInfo mSubscriptionInfo = mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(simSlot); + return mTelephonyManager.getCallState(); + } else if(simSlot != null){ + SubscriptionInfo mSubscriptionInfo = mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(simSlot.intValue()); if (mSubscriptionInfo != null) { thisState = mTelephonyManager .createForSubscriptionId(mSubscriptionInfo.getSubscriptionId()) .getCallStateForSubscription(); } + }else{ + thisState = mTelephonyManager.getCallStateForSubscription(); } return thisState; -- cgit v1.2.3 From 08d78a84d18e595058fa962c926115286353c7f0 Mon Sep 17 00:00:00 2001 From: haoma Date: Mon, 8 Jan 2024 11:17:43 +0800 Subject: Remove function String getPhoneNumber(int simSlot) --- .../android/mobly/snippet/bundled/TelephonySnippet.java | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java b/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java index 2380b73..85d0565 100644 --- a/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java +++ b/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java @@ -54,22 +54,6 @@ public class TelephonySnippet implements Snippet { return thisNumber; } - @Rpc(description = "Gets phone number for the simSlot (slot# start from 0, only valid for API level > 32)." - + " API level <33 will always return phone number for simSlotIndex = 0") - public String getPhoneNumber(int simSlot) { - String thisNumber = ""; - - if (Build.VERSION.SDK_INT < 33) { - thisNumber = mTelephonyManager.getLine1Number(); - } else { - SubscriptionInfo mSubscriptionInfo = mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(simSlot); - if (mSubscriptionInfo != null) { - thisNumber = mSubscriptionManager.getPhoneNumber(mSubscriptionInfo.getSubscriptionId()); - } - } - return thisNumber; - } - @Rpc(description = "Returns the unique subscriber ID, for example, the IMSI for a GSM phone.") public String getSubscriberId() { return mTelephonyManager.getSubscriberId(); -- cgit v1.2.3 From 66ee7893c2b3f09f35644c3d189f05e6830c125c Mon Sep 17 00:00:00 2001 From: haoma Date: Mon, 8 Jan 2024 11:51:11 +0800 Subject: Update format and assigning @RpcDefault("0") for String getLine1Number(@RpcDefault("0") int simSlot) and int getTelephonyCallState(@RpcDefault("0") int simSlot) --- .../mobly/snippet/bundled/TelephonySnippet.java | 37 +++++++++++++--------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java b/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java index 85d0565..b092254 100644 --- a/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java +++ b/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java @@ -24,7 +24,7 @@ import android.telephony.TelephonyManager; import androidx.test.platform.app.InstrumentationRegistry; import com.google.android.mobly.snippet.Snippet; import com.google.android.mobly.snippet.rpc.Rpc; -import com.google.android.mobly.snippet.rpc.RpcOptional; +import com.google.android.mobly.snippet.rpc.RpcDefault; /** Snippet class for telephony RPCs. */ public class TelephonySnippet implements Snippet { @@ -35,19 +35,26 @@ public class TelephonySnippet implements Snippet { public TelephonySnippet() { Context context = InstrumentationRegistry.getInstrumentation().getContext(); mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); - mSubscriptionManager = (SubscriptionManager) context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); + mSubscriptionManager = + (SubscriptionManager) + context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); } - @Rpc(description = "Gets the line 1 phone number, or optionally get phone number for the simSlot (slot# start from 0, only valid for API level > 32)") - public String getLine1Number(@RpcOptional Integer simSlot) { + @Rpc( + description = + "Gets the line 1 phone number, or optionally get phone number for the " + + "simSlot (slot# start from 0, only valid for API level > 32)") + public String getLine1Number(@RpcDefault("0") int simSlot) { String thisNumber = ""; - if (Build.VERSION.SDK_INT < 33 || simSlot == null) { + if (Build.VERSION.SDK_INT < 33) { thisNumber = mTelephonyManager.getLine1Number(); - } else{ - SubscriptionInfo mSubscriptionInfo = mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(simSlot.intValue()); + } else { + SubscriptionInfo mSubscriptionInfo = + mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(simSlot); if (mSubscriptionInfo != null) { - thisNumber = mSubscriptionManager.getPhoneNumber(mSubscriptionInfo.getSubscriptionId()); + thisNumber = + mSubscriptionManager.getPhoneNumber(mSubscriptionInfo.getSubscriptionId()); } } @@ -61,23 +68,23 @@ public class TelephonySnippet implements Snippet { @Rpc( description = - "Gets the call state for the default subscription or optionally get the call state for the simSlot (slot# start from 0, only valid for API level > 30)." - + " Call state values are 0: IDLE, 1: RINGING, 2: OFFHOOK") - public int getTelephonyCallState(@RpcOptional Integer simSlot) { + "Gets the call state for the default subscription or optionally get the call" + + " state for the simSlot (slot# start from 0, only valid for API" + + " level > 30). Call state values are 0: IDLE, 1: RINGING, 2: OFFHOOK") + public int getTelephonyCallState(@RpcDefault("0") int simSlot) { int thisState = -1; if (Build.VERSION.SDK_INT < 31) { return mTelephonyManager.getCallState(); - } else if(simSlot != null){ - SubscriptionInfo mSubscriptionInfo = mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(simSlot.intValue()); + } else { + SubscriptionInfo mSubscriptionInfo = + mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(simSlot); if (mSubscriptionInfo != null) { thisState = mTelephonyManager .createForSubscriptionId(mSubscriptionInfo.getSubscriptionId()) .getCallStateForSubscription(); } - }else{ - thisState = mTelephonyManager.getCallStateForSubscription(); } return thisState; -- cgit v1.2.3 From fb49c6fe937bf94c11f3bff2151a6e53b3bfec42 Mon Sep 17 00:00:00 2001 From: haoma Date: Mon, 8 Jan 2024 12:47:24 +0800 Subject: Update format to comply w/ G3, and change var type back to Integer for String getLine1Number(@RpcDefault("0") Integer simSlot) and int getTelephonyCallState(@RpcDefault("0") Integer simSlot) --- .../mobly/snippet/bundled/TelephonySnippet.java | 26 +++++++++++++--------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java b/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java index b092254..1495bd0 100644 --- a/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java +++ b/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java @@ -42,16 +42,17 @@ public class TelephonySnippet implements Snippet { @Rpc( description = - "Gets the line 1 phone number, or optionally get phone number for the " + - "simSlot (slot# start from 0, only valid for API level > 32)") - public String getLine1Number(@RpcDefault("0") int simSlot) { + "Gets the line 1 phone number, or optionally get phone number for the " + + "simSlot (slot# start from 0, only valid for API level > 32)") + public String getLine1Number(@RpcDefault("0") Integer simSlot) { String thisNumber = ""; - if (Build.VERSION.SDK_INT < 33) { + if (Build.VERSION.SDK_INT < 33 || simSlot == null) { thisNumber = mTelephonyManager.getLine1Number(); } else { SubscriptionInfo mSubscriptionInfo = - mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(simSlot); + mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex( + simSlot.intValue()); if (mSubscriptionInfo != null) { thisNumber = mSubscriptionManager.getPhoneNumber(mSubscriptionInfo.getSubscriptionId()); @@ -68,23 +69,26 @@ public class TelephonySnippet implements Snippet { @Rpc( description = - "Gets the call state for the default subscription or optionally get the call" + - " state for the simSlot (slot# start from 0, only valid for API" + - " level > 30). Call state values are 0: IDLE, 1: RINGING, 2: OFFHOOK") - public int getTelephonyCallState(@RpcDefault("0") int simSlot) { + "Gets the call state for the default subscription or optionally get the call" + + " state for the simSlot (slot# start from 0, only valid for API" + + " level > 30). Call state values are 0: IDLE, 1: RINGING, 2: OFFHOOK") + public int getTelephonyCallState(@RpcDefault("0") Integer simSlot) { int thisState = -1; if (Build.VERSION.SDK_INT < 31) { return mTelephonyManager.getCallState(); - } else { + } else if (simSlot != null) { SubscriptionInfo mSubscriptionInfo = - mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(simSlot); + mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex( + simSlot.intValue()); if (mSubscriptionInfo != null) { thisState = mTelephonyManager .createForSubscriptionId(mSubscriptionInfo.getSubscriptionId()) .getCallStateForSubscription(); } + } else { + thisState = mTelephonyManager.getCallState(); } return thisState; -- cgit v1.2.3 From ca158c8de21572ff8cd6d7f4f259afac7a93fc3d Mon Sep 17 00:00:00 2001 From: haoma Date: Mon, 8 Jan 2024 17:19:19 +0800 Subject: Removing var type check (simSlot == null) for the following function: String getLine1Number(@RpcDefault("0") Integer simSlot) and int getTelephonyCallState(@RpcDefault("0") Integer simSlot) --- .../com/google/android/mobly/snippet/bundled/TelephonySnippet.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java b/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java index 1495bd0..e4d33ec 100644 --- a/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java +++ b/src/main/java/com/google/android/mobly/snippet/bundled/TelephonySnippet.java @@ -47,7 +47,7 @@ public class TelephonySnippet implements Snippet { public String getLine1Number(@RpcDefault("0") Integer simSlot) { String thisNumber = ""; - if (Build.VERSION.SDK_INT < 33 || simSlot == null) { + if (Build.VERSION.SDK_INT < 33) { thisNumber = mTelephonyManager.getLine1Number(); } else { SubscriptionInfo mSubscriptionInfo = @@ -77,7 +77,7 @@ public class TelephonySnippet implements Snippet { if (Build.VERSION.SDK_INT < 31) { return mTelephonyManager.getCallState(); - } else if (simSlot != null) { + } else { SubscriptionInfo mSubscriptionInfo = mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex( simSlot.intValue()); @@ -87,8 +87,6 @@ public class TelephonySnippet implements Snippet { .createForSubscriptionId(mSubscriptionInfo.getSubscriptionId()) .getCallStateForSubscription(); } - } else { - thisState = mTelephonyManager.getCallState(); } return thisState; -- cgit v1.2.3 From c00e2d62621cf6526c67515b4e50baec79b8339d Mon Sep 17 00:00:00 2001 From: Kolin Lu Date: Mon, 22 Jan 2024 11:00:43 -0800 Subject: Update AndroidManifest.xml to request legacy Bluetooth permissions on older devices (#186) https://developer.android.com/develop/connectivity/bluetooth/bt-permissions Add android:maxSdkVersion="30" for legacy Bluetooth permissions --- src/main/AndroidManifest.xml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index bcf52b2..5d84765 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -11,8 +11,11 @@ - - + + + + + -- cgit v1.2.3 From 4c30f2e6d835ac95b47e0fdfdfaffe5e9e63e4f6 Mon Sep 17 00:00:00 2001 From: nihald2000 <54666918+nihald2000@users.noreply.github.com> Date: Thu, 21 Mar 2024 22:58:23 +0530 Subject: Add `BluetoothHeadsetSnippet` for Bluetooth HFP. (#189) Introduces BluetoothHeadsetClientSnippet for interacting with the Bluetooth Headset Client profile(HFP). The class includes functionality like: * Setting connection policies * Connecting and disconnecting from remote devices * Retrieving connection states * Managing voice recognition --- src/main/AndroidManifest.xml | 1 + .../profiles/BluetoothHeadsetSnippet.java | 163 +++++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 src/main/java/com/google/android/mobly/snippet/bundled/bluetooth/profiles/BluetoothHeadsetSnippet.java diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 5d84765..65731eb 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -51,6 +51,7 @@ com.google.android.mobly.snippet.bundled.bluetooth.BluetoothGattServerSnippet, com.google.android.mobly.snippet.bundled.bluetooth.profiles.BluetoothA2dpSnippet, com.google.android.mobly.snippet.bundled.bluetooth.profiles.BluetoothHearingAidSnippet, + com.google.android.mobly.snippet.bundled.bluetooth.profiles.BluetoothHeadsetSnippet, com.google.android.mobly.snippet.bundled.BluetoothLeAdvertiserSnippet, com.google.android.mobly.snippet.bundled.BluetoothLeScannerSnippet, com.google.android.mobly.snippet.bundled.LogSnippet, diff --git a/src/main/java/com/google/android/mobly/snippet/bundled/bluetooth/profiles/BluetoothHeadsetSnippet.java b/src/main/java/com/google/android/mobly/snippet/bundled/bluetooth/profiles/BluetoothHeadsetSnippet.java new file mode 100644 index 0000000..71cb81d --- /dev/null +++ b/src/main/java/com/google/android/mobly/snippet/bundled/bluetooth/profiles/BluetoothHeadsetSnippet.java @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2024 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.android.mobly.snippet.bundled.bluetooth.profiles; + +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothHeadset; +import android.bluetooth.BluetoothProfile; +import android.content.Context; +import android.content.IntentFilter; +import android.os.Bundle; + +import androidx.test.platform.app.InstrumentationRegistry; + +import com.google.android.mobly.snippet.Snippet; +import com.google.android.mobly.snippet.bundled.bluetooth.PairingBroadcastReceiver; +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 java.util.ArrayList; +import java.util.Set; + +/** + * Custom exception class for handling exceptions within the BluetoothHeadsetSnippet. + * This exception is meant to encapsulate and convey specific error information related to + * BluetoothHeadsetSnippet operations. + */ +public class BluetoothHeadsetSnippet implements Snippet { + + private final JsonSerializer mJsonSerializer = new JsonSerializer(); + private static final BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + + private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext(); + private static class BluetoothHeadsetSnippetException extends Exception { + private static final long serialVersionUID = 1; + + /** + * Constructs a BluetoothHeadsetSnippetException with the specified detail message. + * + * @param msg The detail message providing information about the exception. + */ + BluetoothHeadsetSnippetException(String msg) { + super(msg); + } + } + + private BluetoothHeadset mBluetoothHeadset; + private static final int HEADSET = 1; + + private final BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() { + @Override + public void onServiceConnected(int var1, BluetoothProfile profile) { + if (var1 == HEADSET) { + mBluetoothHeadset = (BluetoothHeadset)profile; + } + } + @Override + public void onServiceDisconnected(int var1) { + if (var1 == HEADSET) { + mBluetoothHeadset = null; + } + } + }; + + public BluetoothHeadsetSnippet() throws Throwable { + IntentFilter filter = new IntentFilter(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED); + mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.HEADSET); + Utils.waitUntil(() -> mBluetoothHeadset != null, 60); + mContext.registerReceiver(new PairingBroadcastReceiver(mContext), filter); + } + + + /** + * Returns the connection state for a Bluetooth device with the specified name. + * + * @param deviceAddress The address of the Bluetooth device. + * @return The connection state for the specified device. + * @throws BluetoothHeadsetSnippetException If no device with the specified name is connected via HEADSET. + */ + @Rpc(description = "Returns connection state.") + public int btHfpGetConnectionState(String deviceAddress) throws BluetoothHeadsetSnippetException { + Set pairedDevices = mBluetoothAdapter.getBondedDevices(); + for (BluetoothDevice device : pairedDevices) { + if (device.getAddress().equalsIgnoreCase(deviceAddress)) { + return mBluetoothHeadset.getConnectionState(device); + } + } + throw new BluetoothHeadsetSnippetException("No device with name " + deviceAddress +" is connected via HEADSET."); + } + + /** + * Starts voice recognition for the Bluetooth device with the specified name. + * + * @param deviceAddress The address of the Bluetooth device. + * @return True if voice recognition is successfully started; false otherwise. + * @throws BluetoothHeadsetSnippetException If no device with the specified name is found or if an error + * occurs during the startVoiceRecognition operation. + */ + @Rpc(description = "Starts voice recognition.") + public boolean btHfpStartVoiceRecognition(String deviceAddress) throws BluetoothHeadsetSnippetException{ + Set pairedDevices = mBluetoothAdapter.getBondedDevices(); + for (BluetoothDevice device : pairedDevices) { + if (device.getAddress().equalsIgnoreCase(deviceAddress)) { + return mBluetoothHeadset.startVoiceRecognition(device); + } + } + throw new BluetoothHeadsetSnippetException("No device with name " + deviceAddress +" is connected via HEADSET."); + } + + + /** + * Stops voice recognition for the Bluetooth device with the specified name. + * + * @param deviceAddress The address of the Bluetooth device. + * @return True if voice recognition is successfully started; false otherwise. + * @throws BluetoothHeadsetSnippetException If no device with the specified name is found or if an error + * occurs during the startVoiceRecognition operation. + */ + @Rpc(description = "Stops voice recognition.") + public boolean btHfpStopVoiceRecognition(String deviceAddress) throws BluetoothHeadsetSnippetException { + Set pairedDevices = mBluetoothAdapter.getBondedDevices(); + for (BluetoothDevice device : pairedDevices) { + if (device.getAddress().equalsIgnoreCase(deviceAddress)) { + return mBluetoothHeadset.stopVoiceRecognition(device); + } + } + throw new BluetoothHeadsetSnippetException("No device with name " + deviceAddress +" is connected via HEADSET."); + } + + @Rpc(description = "Checks whether the headset supports voice recognition;") + public boolean btHfpIsVoiceRecognitionSupported(String deviceAddress) throws BluetoothHeadsetSnippetException { + Set pairedDevices = mBluetoothAdapter.getBondedDevices(); + for (BluetoothDevice device : pairedDevices) { + if (device.getAddress().equalsIgnoreCase(deviceAddress)) { + return mBluetoothHeadset.isVoiceRecognitionSupported(device); + } + } + throw new BluetoothHeadsetSnippetException("No device with name " + deviceAddress +" is connected via HEADSET."); + } + @Rpc(description = "Gets all the devices currently connected via HFP profile.") + public ArrayList btHfpGetConnectedDevices() { + return mJsonSerializer.serializeBluetoothDeviceList(mBluetoothHeadset.getConnectedDevices()); + } + + @Override + public void shutdown() { } +} -- cgit v1.2.3