summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2022-07-07 04:50:11 -0700
committerLinux Build Service Account <lnxbuild@localhost>2022-07-07 04:50:11 -0700
commitdd6dc18f57235bf19b3886f51c1c91baa5d62ecc (patch)
tree57eebc6f0878d2d2aa19ccae6ad8332ecbd4c83d
parent241b2b700fd3cf842291ce13513d6bbb50564560 (diff)
parentc8523f5c9dfc0d3cf2f3ecc3c7f89326733fb276 (diff)
Merge c8523f5c9dfc0d3cf2f3ecc3c7f89326733fb276 on remote branch
Change-Id: Ibd4beb7c71dd436610071aff26ccde92e237dfbd
-rw-r--r--android/app/Android.bp7
-rw-r--r--android/app/AndroidManifest.xml4
-rw-r--r--android/app/certs/com.android.bluetooth.pk8 (renamed from android/app/certs/com.android.bluetooth.services.pk8)bin2374 -> 2374 bytes
-rw-r--r--android/app/certs/com.android.bluetooth.x509.pem (renamed from android/app/certs/com.android.bluetooth.services.x509.pem)0
-rw-r--r--android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp13
-rw-r--r--android/app/res/values-af/strings.xml6
-rw-r--r--android/app/res/values-am/strings.xml6
-rw-r--r--android/app/res/values-ar/strings.xml6
-rw-r--r--android/app/res/values-as/strings.xml6
-rw-r--r--android/app/res/values-az/strings.xml6
-rw-r--r--android/app/res/values-b+sr+Latn/strings.xml6
-rw-r--r--android/app/res/values-be/strings.xml6
-rw-r--r--android/app/res/values-bg/strings.xml6
-rw-r--r--android/app/res/values-bn/strings.xml6
-rw-r--r--android/app/res/values-bs/strings.xml6
-rw-r--r--android/app/res/values-ca/strings.xml6
-rw-r--r--android/app/res/values-cs/strings.xml6
-rw-r--r--android/app/res/values-da/strings.xml6
-rw-r--r--android/app/res/values-de/strings.xml6
-rw-r--r--android/app/res/values-el/strings.xml6
-rw-r--r--android/app/res/values-en-rAU/strings.xml6
-rw-r--r--android/app/res/values-en-rCA/strings.xml6
-rw-r--r--android/app/res/values-en-rGB/strings.xml6
-rw-r--r--android/app/res/values-en-rIN/strings.xml6
-rw-r--r--android/app/res/values-en-rXC/strings.xml6
-rw-r--r--android/app/res/values-es-rUS/strings.xml6
-rw-r--r--android/app/res/values-es/strings.xml6
-rw-r--r--android/app/res/values-et/strings.xml6
-rw-r--r--android/app/res/values-eu/strings.xml6
-rw-r--r--android/app/res/values-fa/strings.xml6
-rw-r--r--android/app/res/values-fi/strings.xml6
-rw-r--r--android/app/res/values-fr-rCA/strings.xml6
-rw-r--r--android/app/res/values-fr/strings.xml6
-rw-r--r--android/app/res/values-gl/strings.xml6
-rw-r--r--android/app/res/values-gu/strings.xml6
-rw-r--r--android/app/res/values-hi/strings.xml6
-rw-r--r--android/app/res/values-hr/strings.xml6
-rw-r--r--android/app/res/values-hu/strings.xml6
-rw-r--r--android/app/res/values-hy/strings.xml6
-rw-r--r--android/app/res/values-in/strings.xml6
-rw-r--r--android/app/res/values-is/strings.xml6
-rw-r--r--android/app/res/values-it/strings.xml6
-rw-r--r--android/app/res/values-iw/strings.xml6
-rw-r--r--android/app/res/values-ja/strings.xml6
-rw-r--r--android/app/res/values-ka/strings.xml6
-rw-r--r--android/app/res/values-kk/strings.xml6
-rw-r--r--android/app/res/values-km/strings.xml6
-rw-r--r--android/app/res/values-kn/strings.xml6
-rw-r--r--android/app/res/values-ko/strings.xml6
-rw-r--r--android/app/res/values-ky/strings.xml6
-rw-r--r--android/app/res/values-lo/strings.xml6
-rw-r--r--android/app/res/values-lt/strings.xml6
-rw-r--r--android/app/res/values-lv/strings.xml6
-rw-r--r--android/app/res/values-mk/strings.xml6
-rw-r--r--android/app/res/values-ml/strings.xml6
-rw-r--r--android/app/res/values-mn/strings.xml6
-rw-r--r--android/app/res/values-mr/strings.xml6
-rw-r--r--android/app/res/values-ms/strings.xml6
-rw-r--r--android/app/res/values-my/strings.xml6
-rw-r--r--android/app/res/values-nb/strings.xml6
-rw-r--r--android/app/res/values-ne/strings.xml6
-rw-r--r--android/app/res/values-nl/strings.xml6
-rw-r--r--android/app/res/values-or/strings.xml6
-rw-r--r--android/app/res/values-pa/strings.xml6
-rw-r--r--android/app/res/values-pl/strings.xml6
-rw-r--r--android/app/res/values-pt-rPT/strings.xml6
-rw-r--r--android/app/res/values-pt/strings.xml6
-rw-r--r--android/app/res/values-ro/strings.xml6
-rw-r--r--android/app/res/values-ru/strings.xml6
-rw-r--r--android/app/res/values-si/strings.xml6
-rw-r--r--android/app/res/values-sk/strings.xml6
-rw-r--r--android/app/res/values-sl/strings.xml6
-rw-r--r--android/app/res/values-sq/strings.xml6
-rw-r--r--android/app/res/values-sr/strings.xml6
-rw-r--r--android/app/res/values-sv/strings.xml6
-rw-r--r--android/app/res/values-sw/strings.xml6
-rw-r--r--android/app/res/values-ta/strings.xml6
-rw-r--r--android/app/res/values-te/strings.xml6
-rw-r--r--android/app/res/values-th/strings.xml6
-rw-r--r--android/app/res/values-tl/strings.xml6
-rw-r--r--android/app/res/values-tr/strings.xml6
-rw-r--r--android/app/res/values-uk/strings.xml6
-rw-r--r--android/app/res/values-ur/strings.xml6
-rw-r--r--android/app/res/values-uz/strings.xml6
-rw-r--r--android/app/res/values-vi/strings.xml6
-rw-r--r--android/app/res/values-zh-rCN/strings.xml6
-rw-r--r--android/app/res/values-zh-rHK/strings.xml6
-rw-r--r--android/app/res/values-zh-rTW/strings.xml6
-rw-r--r--android/app/res/values-zu/strings.xml6
-rw-r--r--android/app/res/values/strings.xml2
-rw-r--r--android/app/src/com/android/bluetooth/audio_util/MediaPlayerList.java15
-rw-r--r--android/app/src/com/android/bluetooth/avrcp/AvrcpNativeInterface.java2
-rw-r--r--android/app/src/com/android/bluetooth/bas/BatteryService.java7
-rw-r--r--android/app/src/com/android/bluetooth/bas/BatteryStateMachine.java8
-rw-r--r--android/app/src/com/android/bluetooth/btservice/AdapterProperties.java4
-rw-r--r--android/app/src/com/android/bluetooth/btservice/AdapterService.java10
-rw-r--r--android/app/src/com/android/bluetooth/btservice/BondStateMachine.java2
-rw-r--r--android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java7
-rw-r--r--android/app/src/com/android/bluetooth/gatt/GattService.java13
-rw-r--r--android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java6
-rw-r--r--android/app/src/com/android/bluetooth/opp/BluetoothOppService.java11
-rwxr-xr-xandroid/app/tests/unit/Android.bp2
-rw-r--r--android/app/tests/unit/AndroidManifest.xml6
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/bas/BatteryStateMachineTest.java39
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java2
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java2
-rw-r--r--apex/Android.bp58
-rw-r--r--apex/apex_manifest.json7
-rw-r--r--apex/com.android.btservices.avbpubkey (renamed from apex/com.android.bluetooth.avbpubkey)bin1032 -> 1032 bytes
-rw-r--r--apex/com.android.btservices.pem (renamed from apex/com.android.bluetooth.pem)0
-rw-r--r--apex/com.android.btservices.pk8 (renamed from apex/com.android.bluetooth.pk8)bin2375 -> 2375 bytes
-rw-r--r--apex/com.android.btservices.x509.pem (renamed from apex/com.android.bluetooth.x509.pem)0
-rw-r--r--apex/permissions/Android.bp6
-rw-r--r--apex/permissions/com.android.bluetooth.xml (renamed from apex/permissions/com.android.bluetooth.services.xml)3
-rw-r--r--framework/java/android/bluetooth/BluetoothDevice.java5
-rw-r--r--framework/java/android/bluetooth/le/AdvertisingSetParameters.java2
-rw-r--r--service/java/com/android/server/bluetooth/BluetoothManagerService.java45
-rw-r--r--service/java/com/android/server/bluetooth/BluetoothService.java8
-rw-r--r--system/Android.mk37
-rw-r--r--system/audio_hal_interface/aidl/client_interface_aidl.cc10
-rw-r--r--system/blueberry/facade/hci/le_acl_manager_facade.proto10
-rw-r--r--system/blueberry/tests/gd/cert/adb.py16
-rw-r--r--system/blueberry/tests/gd/cert/closable.py15
-rw-r--r--system/blueberry/tests/gd/cert/gd_device.py58
-rw-r--r--system/blueberry/tests/gd/cert/py_le_acl_manager.py15
-rw-r--r--system/blueberry/tests/gd/hci/le_acl_manager_test.py40
-rw-r--r--system/blueberry/tests/gd_sl4a/gatt/gatt_connect_low_layer_test.py536
-rw-r--r--system/blueberry/tests/gd_sl4a/gd_sl4a_test_runner.py3
-rw-r--r--system/blueberry/tests/gd_sl4a/hci/le_advanced_scanning_test.py20
-rw-r--r--system/blueberry/tests/gd_sl4a/lib/gd_sl4a_base_test.py3
-rw-r--r--system/blueberry/tests/sl4a_sl4a/gatt/gatt_connect_test.py155
-rw-r--r--system/blueberry/utils/bt_gatt_utils.py22
-rw-r--r--system/bta/dm/bta_dm_act.cc82
-rw-r--r--system/bta/dm/bta_dm_api.cc20
-rw-r--r--system/bta/dm/bta_dm_int.h13
-rw-r--r--system/bta/dm/bta_dm_main.cc22
-rw-r--r--system/bta/dm/bta_dm_pm.cc7
-rw-r--r--system/bta/gatt/bta_gattc_act.cc37
-rw-r--r--system/bta/gatt/bta_gattc_api.cc8
-rw-r--r--system/bta/gatt/bta_gattc_main.cc6
-rw-r--r--system/bta/hearing_aid/hearing_aid.cc32
-rw-r--r--system/bta/include/bta_api.h8
-rw-r--r--system/bta/le_audio/le_audio_set_configuration_provider_json.cc13
-rw-r--r--system/btif/Android.bp2
-rw-r--r--system/btif/src/bluetooth.cc12
-rw-r--r--system/btif/src/bluetooth_data_migration.cc126
-rw-r--r--system/btif/src/btif_core.cc2
-rw-r--r--system/btif/src/btif_dm.cc88
-rw-r--r--system/btif/src/btif_gatt_client.cc5
-rw-r--r--system/common/metrics.cc15
-rw-r--r--system/common/metrics.h1
-rw-r--r--system/device/include/interop_database.h6
-rw-r--r--system/gd/facade/facade_main.cc20
-rw-r--r--system/gd/facade/grpc_root_server.cc64
-rw-r--r--system/gd/facade/grpc_root_server.h7
-rw-r--r--system/gd/grpc/grpc_event_queue.h4
-rw-r--r--system/gd/hal/snoop_logger.cc2
-rw-r--r--system/gd/hci/acl_manager.cc15
-rw-r--r--system/gd/hci/acl_manager.h4
-rw-r--r--system/gd/hci/acl_manager/le_acl_connection.h6
-rw-r--r--system/gd/hci/acl_manager/le_impl.h24
-rw-r--r--system/gd/hci/facade/acl_manager_facade.cc15
-rw-r--r--system/gd/hci/facade/le_acl_manager_facade.cc51
-rw-r--r--system/gd/hci/hci_metrics_logging.cc15
-rw-r--r--system/gd/hci/hci_metrics_logging.h7
-rw-r--r--system/gd/hci/le_advertising_manager.cc30
-rw-r--r--system/gd/os/android/metrics.cc16
-rw-r--r--system/gd/os/host/metrics.cc1
-rw-r--r--system/gd/os/linux/metrics.cc1
-rw-r--r--system/gd/os/metrics.h1
-rw-r--r--system/gd/rust/topshim/facade/Android.bp1
-rw-r--r--system/gd/rust/topshim/src/btif.rs3
-rw-r--r--system/include/hardware/bluetooth.h3
-rw-r--r--system/main/shim/acl.cc34
-rw-r--r--system/main/shim/metrics_api.cc5
-rw-r--r--system/main/shim/metrics_api.h2
-rw-r--r--system/main/stack_config.cc2
-rw-r--r--system/service/Android.bp2
-rw-r--r--system/service/hal/bluetooth_interface.cc3
-rw-r--r--system/stack/acl/ble_acl.cc7
-rw-r--r--system/stack/acl/btm_acl.cc2
-rw-r--r--system/stack/btm/btm_ble_bgconn.cc17
-rw-r--r--system/stack/btm/btm_ble_privacy.cc12
-rw-r--r--system/stack/btm/btm_dev.cc9
-rw-r--r--system/stack/btm/btm_sec.cc25
-rw-r--r--system/stack/btu/btu_hcif.cc27
-rw-r--r--system/stack/gatt/connection_manager.cc15
-rw-r--r--system/stack/gatt/connection_manager.h1
-rw-r--r--system/stack/gatt/gatt_api.cc16
-rw-r--r--system/stack/gatt/gatt_utils.cc10
-rw-r--r--system/stack/include/gatt_api.h2
-rw-r--r--system/stack/include/stack_metrics_logging.h1
-rwxr-xr-xsystem/stack/l2cap/l2c_csm.cc2
-rw-r--r--system/stack/metrics/stack_metrics_logging.cc5
-rw-r--r--system/stack/sdp/sdp_utils.cc14
-rw-r--r--system/stack/test/eatt/eatt_test.cc1
-rw-r--r--system/test/headless/Android.bp1
-rw-r--r--system/test/headless/headless.cc2
-rw-r--r--system/test/mock/mock_bta_dm_act.cc5
-rw-r--r--system/test/mock/mock_bta_dm_api.cc9
-rw-r--r--system/test/mock/mock_bta_dm_api.h20
-rw-r--r--system/test/mock/mock_main_shim_metrics_api.cc3
-rw-r--r--system/test/mock/mock_main_shim_metrics_api.h7
-rw-r--r--system/test/mock/mock_stack_gatt_connection_manager.cc5
-rw-r--r--system/test/suite/Android.bp1
-rw-r--r--system/test/suite/adapter/adapter_unittest.cc3
206 files changed, 1934 insertions, 871 deletions
diff --git a/android/app/Android.bp b/android/app/Android.bp
index c8eb3ffbb2..e7bf31b1fd 100644
--- a/android/app/Android.bp
+++ b/android/app/Android.bp
@@ -62,6 +62,7 @@ cc_library_shared {
static_libs: [
"libbluetooth-types",
"libbluetooth",
+ "libc++fs",
],
cflags: [
"-Wall",
@@ -86,7 +87,7 @@ android_app {
":bluetooth-proto-enums-java-gen",
],
aaptflags: [ "--custom-package", "com.android.bluetooth" ],
- certificate: ":com.android.bluetooth.services.certificate",
+ certificate: ":com.android.bluetooth.certificate",
jni_libs: ["libbluetooth_jni"],
libs: [
@@ -157,6 +158,6 @@ genrule {
}
android_app_certificate {
- name: "com.android.bluetooth.services.certificate",
- certificate: "certs/com.android.bluetooth.services"
+ name: "com.android.bluetooth.certificate",
+ certificate: "certs/com.android.bluetooth"
}
diff --git a/android/app/AndroidManifest.xml b/android/app/AndroidManifest.xml
index ed7daa182d..8ed18e2794 100644
--- a/android/app/AndroidManifest.xml
+++ b/android/app/AndroidManifest.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.bluetooth.services"
+ package="com.android.bluetooth"
android:sharedUserId="android.uid.bluetooth">
<!-- Allows access to the Bluetooth Share Manager -->
@@ -29,7 +29,6 @@
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED"/>
<uses-permission android:name="android.permission.BLUETOOTH_MAP"/>
<uses-permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE" />
- <uses-permission android:name="android.permission.DUMP"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
@@ -54,7 +53,6 @@
<uses-permission android:name="android.permission.NETWORK_FACTORY"/>
<uses-permission android:name="android.permission.TETHER_PRIVILEGED"/>
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE"/>
- <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
<uses-permission android:name="android.permission.BLUETOOTH_STACK"/>
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS"/>
<uses-permission android:name="android.permission.MANAGE_USERS"/>
diff --git a/android/app/certs/com.android.bluetooth.services.pk8 b/android/app/certs/com.android.bluetooth.pk8
index c6ea434b5d..c6ea434b5d 100644
--- a/android/app/certs/com.android.bluetooth.services.pk8
+++ b/android/app/certs/com.android.bluetooth.pk8
Binary files differ
diff --git a/android/app/certs/com.android.bluetooth.services.x509.pem b/android/app/certs/com.android.bluetooth.x509.pem
index 396d7c9f43..396d7c9f43 100644
--- a/android/app/certs/com.android.bluetooth.services.x509.pem
+++ b/android/app/certs/com.android.bluetooth.x509.pem
diff --git a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp
index e761eb638d..1c86ca889e 100644
--- a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp
+++ b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp
@@ -953,7 +953,8 @@ static void classInitNative(JNIEnv* env, jclass clazz) {
static bool initNative(JNIEnv* env, jobject obj, jboolean isGuest,
jboolean isCommonCriteriaMode, int configCompareResult,
- jobjectArray initFlags, jboolean isAtvDevice) {
+ jobjectArray initFlags, jboolean isAtvDevice,
+ jstring userDataDirectory) {
ALOGV("%s", __func__);
android_bluetooth_UidTraffic.clazz =
@@ -980,10 +981,15 @@ static bool initNative(JNIEnv* env, jobject obj, jboolean isGuest,
flags[i] = env->GetStringUTFChars(flagObjs[i], NULL);
}
+ const char* user_data_directory =
+ env->GetStringUTFChars(userDataDirectory, NULL);
+
int ret = sBluetoothInterface->init(
&sBluetoothCallbacks, isGuest == JNI_TRUE ? 1 : 0,
isCommonCriteriaMode == JNI_TRUE ? 1 : 0, configCompareResult, flags,
- isAtvDevice == JNI_TRUE ? 1 : 0);
+ isAtvDevice == JNI_TRUE ? 1 : 0, user_data_directory);
+
+ env->ReleaseStringUTFChars(userDataDirectory, user_data_directory);
for (int i = 0; i < flagCount; i++) {
env->ReleaseStringUTFChars(flagObjs[i], flags[i]);
@@ -1774,7 +1780,8 @@ static jboolean allowLowLatencyAudioNative(JNIEnv* env, jobject obj,
static JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"classInitNative", "()V", (void*)classInitNative},
- {"initNative", "(ZZI[Ljava/lang/String;Z)Z", (void*)initNative},
+ {"initNative", "(ZZI[Ljava/lang/String;ZLjava/lang/String;)Z",
+ (void*)initNative},
{"cleanupNative", "()V", (void*)cleanupNative},
{"enableNative", "()Z", (void*)enableNative},
{"disableNative", "()Z", (void*)disableNative},
diff --git a/android/app/res/values-af/strings.xml b/android/app/res/values-af/strings.xml
index 85eca9b42e..6e5004c4b5 100644
--- a/android/app/res/values-af/strings.xml
+++ b/android/app/res/values-af/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Alle items sal uit die lys verwyder word."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth-deling: Gestuurde lêers"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth-deling: Ontvangde lêers"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# onsuksesvol.}other{# onsuksesvol.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# suksesvol, %1$s}other{# suksesvol, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Vee lys uit"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Open"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Verwyder uit lys"</string>
diff --git a/android/app/res/values-am/strings.xml b/android/app/res/values-am/strings.xml
index 2191a25d21..9e534f28b4 100644
--- a/android/app/res/values-am/strings.xml
+++ b/android/app/res/values-am/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"ሁሉም ዓይነቶች ከዝርዝር ውስጥ ይሰረዛሉ።"</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"ብሉቱዝ ማጋሪያ፡ የተላኩ ፋይሎች"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"ብሉቱዝ ማጋሪያ፡ የደረሱ ፋይሎች"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# አልተሳካም።}one{# አልተሳካም።}other{# አልተሳኩም።}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# ተሳክቷል፣ %1$s}one{# ተሳክቷል፣ %1$s}other{# ተሳክተዋል፣ %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"ዝርዝር አጽዳ"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"ክፈት"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"ከዝርዝር አጽዳ"</string>
diff --git a/android/app/res/values-ar/strings.xml b/android/app/res/values-ar/strings.xml
index f339011212..a3b2598fa8 100644
--- a/android/app/res/values-ar/strings.xml
+++ b/android/app/res/values-ar/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"سيتم محو جميع العناصر من القائمة."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"مشاركة البلوتوث: الملفات المرسلة"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"مشاركة البلوتوث: الملفات المستلمة"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{وتعذّر إرسال ملف واحد.}zero{وتعذّر إرسال # ملف.}two{وتعذّر إرسال ملفين.}few{وتعذّر إرسال # ملفات.}many{وتعذّر إرسال # ملفًا.}other{وتعذّر إرسال # ملف.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{‏تم إرسال ملف واحد بنجاح، %1$s}zero{‏تم إرسال # ملف بنجاح، %1$s}two{‏تم إرسال ملفين بنجاح، %1$s}few{‏تم إرسال # ملفات بنجاح، %1$s}many{‏تم إرسال # ملفًا بنجاح، %1$s}other{‏تم إرسال # ملف بنجاح، %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"محو القائمة"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"فتح"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"محو من القائمة"</string>
diff --git a/android/app/res/values-as/strings.xml b/android/app/res/values-as/strings.xml
index b240d68cf4..4ecc5fbee3 100644
--- a/android/app/res/values-as/strings.xml
+++ b/android/app/res/values-as/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"আটাইবোৰ সমল সূচীৰ পৰা মচা হ\'ব।"</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"ব্লুটুথ শ্বেয়াৰ: প্ৰেৰণ কৰা ফাইলসমূহ"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"ব্লুটুথ শ্বেয়াৰ: লাভ কৰা ফাইলসমূহ"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# টা বিফল হৈছে।}one{# টা বিফল হৈছে।}other{# টা বিফল হৈছে।}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# টা সফল হৈছে, %1$s}one{# টা সফল হৈছে, %1$s}other{# টা সফল হৈছে, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"সূচী মচক"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"খোলক"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"সূচীৰ পৰা মচক"</string>
diff --git a/android/app/res/values-az/strings.xml b/android/app/res/values-az/strings.xml
index af24673341..955699203d 100644
--- a/android/app/res/values-az/strings.xml
+++ b/android/app/res/values-az/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Bütün məlumatlar siyahıdan silinəcək."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth paylaşım: Göndərilmiş fayllar"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth paylaşım: Qəbul edilən fayllar"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# uğursuz.}other{# uğursuz.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# uğurlu, %1$s}other{# uğurlu, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Siyahını silin"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Açın"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Siyahıdan silin"</string>
diff --git a/android/app/res/values-b+sr+Latn/strings.xml b/android/app/res/values-b+sr+Latn/strings.xml
index 73d340855b..92f842310f 100644
--- a/android/app/res/values-b+sr+Latn/strings.xml
+++ b/android/app/res/values-b+sr+Latn/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Sve stavke će biti izbrisane sa liste."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Deljenje preko Bluetooth-a: poslate datoteke"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Deljenje preko Bluetooth-a: primljene datoteke"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# neuspešno.}one{# neuspešno.}few{# neuspešna.}other{# neuspešnih.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# uspešno, %1$s}one{# uspešno, %1$s}few{# uspešna, %1$s}other{# uspešnih, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Obriši listu"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Otvori"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Obriši sa liste"</string>
diff --git a/android/app/res/values-be/strings.xml b/android/app/res/values-be/strings.xml
index dadb088662..ed72ab67c9 100644
--- a/android/app/res/values-be/strings.xml
+++ b/android/app/res/values-be/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Усе элементы будуць выдаленыя са спісу."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Перадача праз Bluetooth: адпраўленыя файлы"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Перадача праз Bluetooth: атрыманыя файлы"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{не выканана: #.}one{не выканана: #.}few{не выканана: #.}many{не выканана: #.}other{не выканана: #.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{Выканана: #; %1$s}one{Выканана: #; %1$s}few{Выканана: #; %1$s}many{Выканана: #; %1$s}other{Выканана: #; %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Ачысціць спіс"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Адкрыць"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Выдаліць са спісу"</string>
diff --git a/android/app/res/values-bg/strings.xml b/android/app/res/values-bg/strings.xml
index 5d595f12c9..b2d67422ab 100644
--- a/android/app/res/values-bg/strings.xml
+++ b/android/app/res/values-bg/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Всички елементи ще бъдат премахнати от списъка."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Споделяне чрез Bluetooth: Изпратени файлове"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Споделяне чрез Bluetooth: Получени файлове"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# неуспешно.}other{# неуспешно.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# успешно, %1$s}other{# успешно, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Изчистване на списъка"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Отваряне"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Изчистване от списъка"</string>
diff --git a/android/app/res/values-bn/strings.xml b/android/app/res/values-bn/strings.xml
index c26d95c995..8715f4d441 100644
--- a/android/app/res/values-bn/strings.xml
+++ b/android/app/res/values-bn/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"তালিকা থেকে সমস্ত আইটেম সাফ করা হবে।"</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"ব্লুটুথ share: পাঠানো ফাইলগুলি"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"ব্লুটুথ share: প্রাপ্ত করা ফাইলগুলি"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{#টি ফাইল পাঠানো যায়নি।}one{#টি ফাইল পাঠানো যায়নি।}other{#টি ফাইল পাঠানো যায়নি।}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{#টি ফাইল পাঠানো হয়েছে, %1$s}one{#টি ফাইল পাঠানো হয়েছে, %1$s}other{#টি ফাইল পাঠানো হয়েছে, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"তালিকা সাফ করুন"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"খুলুন"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"তালিকা থেকে সাফ করুন"</string>
diff --git a/android/app/res/values-bs/strings.xml b/android/app/res/values-bs/strings.xml
index 0d1d2e9c6c..fafbf937f6 100644
--- a/android/app/res/values-bs/strings.xml
+++ b/android/app/res/values-bs/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Sve stavke će biti izbrisane sa spiska."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth dijeljenje: Poslani fajlovi"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth dijeljenje: Primljeni fajlovi"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# neuspješno.}one{# neuspješno.}few{# neuspješna.}other{# neuspješnih.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# uspješno, %1$s}one{# uspješno, %1$s}few{# uspješna, %1$s}other{# uspješnih, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Obriši spisak"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Otvori"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Obriši sa spiska"</string>
diff --git a/android/app/res/values-ca/strings.xml b/android/app/res/values-ca/strings.xml
index 76ee2ec8d7..b5ec842308 100644
--- a/android/app/res/values-ca/strings.xml
+++ b/android/app/res/values-ca/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"S\'esborraran tots els elements de la llista."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth: fitxers enviats"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth: fitxers rebuts"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# no completat.}other{# no completats.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# completat, %1$s}other{# completats, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Esborra la llista"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Obre"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Esborra de la llista"</string>
diff --git a/android/app/res/values-cs/strings.xml b/android/app/res/values-cs/strings.xml
index 067970d3ee..764ac842d9 100644
--- a/android/app/res/values-cs/strings.xml
+++ b/android/app/res/values-cs/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Ze seznamu budou vymazány všechny položky."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Sdílení Bluetooth: Odeslané soubory"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Sdílení Bluetooth: Přijaté soubory"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# neúspěch.}few{# neúspěchy.}many{# neúspěchu.}other{# neúspěchů.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# úspěch, %1$s}few{# úspěchy, %1$s}many{# úspěchu, %1$s}other{# úspěchů, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Vymazat obsah seznamu"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Otevřít"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Vymazat ze seznamu"</string>
diff --git a/android/app/res/values-da/strings.xml b/android/app/res/values-da/strings.xml
index b57dc358e2..15881ed4f1 100644
--- a/android/app/res/values-da/strings.xml
+++ b/android/app/res/values-da/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Alle elementer vil blive fjernet fra listen."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth-deling: Sendte filer"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth-deling: Modtagne filer"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# blev ikke sendt.}one{# unsuccessful.}other{# blev ikke sendt.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# blev sendt, %1$s}one{# successful, %1$s}other{# blev sendt, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Ryd liste"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Åbn"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Fjern fra listen"</string>
diff --git a/android/app/res/values-de/strings.xml b/android/app/res/values-de/strings.xml
index 1364f7d39a..719dd9532b 100644
--- a/android/app/res/values-de/strings.xml
+++ b/android/app/res/values-de/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Alle Elemente werden aus der Liste gelöscht."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth-Freigabe: Gesendete Dateien"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth-Freigabe: Empfangene Dateien"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# fehlgeschlagen.}other{# fehlgeschlagen.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# erfolgreich, %1$s}other{# erfolgreich, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Liste löschen"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Öffnen"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Aus Liste löschen"</string>
diff --git a/android/app/res/values-el/strings.xml b/android/app/res/values-el/strings.xml
index a9abf2b586..31c4d0d46a 100644
--- a/android/app/res/values-el/strings.xml
+++ b/android/app/res/values-el/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Όλα τα στοιχεία από τη λίστα θα διαγραφούν."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Κοινή χρήση Bluetooth: Απεσταλμένα αρχεία"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Κοινή χρήση Bluetooth: Ληφθέντα αρχεία"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# ανεπιτυχής.}other{# ανεπιτυχείς.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# επιτυχής, %1$s}other{# επιτυχείς, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Διαγραφή λίστας"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Άνοιγμα"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Διαγραφή από τη λίστα"</string>
diff --git a/android/app/res/values-en-rAU/strings.xml b/android/app/res/values-en-rAU/strings.xml
index 482c645bd4..266667fd53 100644
--- a/android/app/res/values-en-rAU/strings.xml
+++ b/android/app/res/values-en-rAU/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"All items will be cleared from the list."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth share: Sent files"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth share: Received files"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# unsuccessful.}other{# unsuccessful.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# successful, %1$s}other{# successful, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Clear list"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Open"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Clear from list"</string>
diff --git a/android/app/res/values-en-rCA/strings.xml b/android/app/res/values-en-rCA/strings.xml
index e1109f711b..89e7e55847 100644
--- a/android/app/res/values-en-rCA/strings.xml
+++ b/android/app/res/values-en-rCA/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"All items will be cleared from the list."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth share: Sent files"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth share: Received files"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# unsuccessful.}other{# unsuccessful.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# successful, %1$s}other{# successful, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Clear list"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Open"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Clear from list"</string>
diff --git a/android/app/res/values-en-rGB/strings.xml b/android/app/res/values-en-rGB/strings.xml
index 482c645bd4..266667fd53 100644
--- a/android/app/res/values-en-rGB/strings.xml
+++ b/android/app/res/values-en-rGB/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"All items will be cleared from the list."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth share: Sent files"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth share: Received files"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# unsuccessful.}other{# unsuccessful.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# successful, %1$s}other{# successful, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Clear list"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Open"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Clear from list"</string>
diff --git a/android/app/res/values-en-rIN/strings.xml b/android/app/res/values-en-rIN/strings.xml
index 482c645bd4..266667fd53 100644
--- a/android/app/res/values-en-rIN/strings.xml
+++ b/android/app/res/values-en-rIN/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"All items will be cleared from the list."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth share: Sent files"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth share: Received files"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# unsuccessful.}other{# unsuccessful.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# successful, %1$s}other{# successful, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Clear list"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Open"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Clear from list"</string>
diff --git a/android/app/res/values-en-rXC/strings.xml b/android/app/res/values-en-rXC/strings.xml
index 883e31e84b..a47fdcdbc3 100644
--- a/android/app/res/values-en-rXC/strings.xml
+++ b/android/app/res/values-en-rXC/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‎‎‏‎‎‎‎‎‏‎‎‎‏‎‎‏‎‎‏‏‏‏‎‎‏‎‎‏‏‏‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‏‏‏‏‎‎‏‎‏‏‎‎‏‏‏‏‎All items will be cleared from the list.‎‏‎‎‏‎"</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‎‏‏‏‏‎‎‎‏‏‎‎‎‏‏‎‏‎‎‏‎‏‎‏‏‎‎‏‏‎‎‎‎‏‏‏‏‎‏‎‏‎‏‏‏‎‎‏‏‏‎‎‏‎‎‏‎‏‎‎‎‏‏‎Bluetooth share: Sent files‎‏‎‎‏‎"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‎‏‏‏‎‎‏‎‎‏‏‎‏‏‎‎‎‏‎‎‏‏‏‏‎‎‎‏‏‎‏‎‏‎‎‏‎‎‎‏‏‎‎‏‏‎‎‏‏‎‎‏‎Bluetooth share: Received files‎‏‎‎‏‎"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‏‏‎‎‎‏‏‎‎‏‏‎‎‏‎‎‎‏‎‎‎‎‎‎‎‎‎‏‎‏‎‎‎‎‏‏‎‎‏‏‎‏‏‎‎‏‎‏‎‏‎‎‏‏‎# unsuccessful.‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‏‏‎‎‎‏‏‎‎‏‏‎‎‏‎‎‎‏‎‎‎‎‎‎‎‎‎‏‎‏‎‎‎‎‏‏‎‎‏‏‎‏‏‎‎‏‎‏‎‏‎‎‏‏‎# unsuccessful.‎‏‎‎‏‎}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‏‎‎‎‎‏‎‎‎‎‎‏‎‎‏‏‎‏‎‎‏‎‏‎‎‏‏‏‎‏‎‎‎‏‏‎‎‏‎‏‎‎‏‏‎‏‏‎‎‎‏‎# successful, %1$s‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‏‎‎‎‎‏‎‎‎‎‎‏‎‎‏‏‎‏‎‎‏‎‏‎‎‏‏‏‎‏‎‎‎‏‏‎‎‏‎‏‎‎‏‏‎‏‏‎‎‎‏‎# successful, %1$s‎‏‎‎‏‎}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‎‏‎‏‏‎‎‎‎‎‏‏‎‎‏‎‏‏‎‏‏‏‏‎‎‎‎‎‎‏‏‎‏‏‎‏‎‎‎‏‎‏‎‎‎‏‎‎‎‏‎‎‎Clear list‎‏‎‎‏‎"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‎‏‎‎‏‎‎‏‏‏‎‏‏‏‎‏‏‎‏‏‏‎‏‏‏‏‎‏‏‎‎‏‎‏‎‎‏‏‏‏‎‏‎‏‎‎‏‎‎‎‎‎‏‏‎Open‎‏‎‎‏‎"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‎‏‏‏‏‎‎‎‎‎‎‏‏‎‏‎‎‎‏‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‎‎Clear from list‎‏‎‎‏‎"</string>
diff --git a/android/app/res/values-es-rUS/strings.xml b/android/app/res/values-es-rUS/strings.xml
index dab60f5d67..8cfaa73c2f 100644
--- a/android/app/res/values-es-rUS/strings.xml
+++ b/android/app/res/values-es-rUS/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Se borrarán todos los elementos de la lista."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth: archivos enviados"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth: archivos recibidos"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# con error.}other{# con error.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# con éxito, %1$s}other{# con éxito, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Eliminar lista"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Abrir"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Eliminar de la lista"</string>
diff --git a/android/app/res/values-es/strings.xml b/android/app/res/values-es/strings.xml
index 08ecc54915..817e1bf65b 100644
--- a/android/app/res/values-es/strings.xml
+++ b/android/app/res/values-es/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Se borrarán todos los elementos de la lista."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth: archivos enviados"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth: archivos recibidos"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# con error.}other{# con error.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# con éxito, %1$s}other{# con éxito, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Borrar lista"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Abrir"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Borrar de la lista"</string>
diff --git a/android/app/res/values-et/strings.xml b/android/app/res/values-et/strings.xml
index 965d003f6e..f4c8c87d62 100644
--- a/android/app/res/values-et/strings.xml
+++ b/android/app/res/values-et/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Kõik üksused eemaldatakse loendist."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetoothi jagamine: saadetud failid"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetoothi jagamine: vastuvõetud failid"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# ebaõnnestus.}other{# ebaõnnestus.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# õnnestus, %1$s}other{# õnnestus, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Tühjendage loend"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Ava"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Eemaldage loendist"</string>
diff --git a/android/app/res/values-eu/strings.xml b/android/app/res/values-eu/strings.xml
index f36de66629..b257056416 100644
--- a/android/app/res/values-eu/strings.xml
+++ b/android/app/res/values-eu/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Elementu guztiak zerrendatik garbituko dira."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth bidez partekatzea: fitxategiak bidali dira"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth bidez partekatzea: fitxategiak jaso dira"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# hutsegite.}other{# hutsegite.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# partekatze, %1$s}other{# partekatze, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Garbitu zerrenda"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Ireki"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Garbitu zerrendatik"</string>
diff --git a/android/app/res/values-fa/strings.xml b/android/app/res/values-fa/strings.xml
index cf6a5a5524..e1675731ed 100644
--- a/android/app/res/values-fa/strings.xml
+++ b/android/app/res/values-fa/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"همهٔ موارد از فهرست پاک می‌شوند."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"اشتراک بلوتوث: فایل‌های ارسال شده"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"اشتراک بلوتوث: فایل‌های دریافت شده"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# مورد ناموفق.}one{# مورد ناموفق.}other{# مورد ناموفق.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{‏# مورد موفق، %1$s}one{‏# مورد موفق، %1$s}other{‏# مورد موفق، %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"پاک کردن فهرست"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"باز کردن"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"پاک کردن از فهرست"</string>
diff --git a/android/app/res/values-fi/strings.xml b/android/app/res/values-fi/strings.xml
index daa17cf0db..9f658a08dc 100644
--- a/android/app/res/values-fi/strings.xml
+++ b/android/app/res/values-fi/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Koko luettelo tyhjennetään."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth-jako: Lähetetyt tiedostot"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth-jako: Vastaanotetut tiedostot"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# epäonnistui}other{# epäonnistui}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# onnistui, %1$s}other{# onnistui, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Tyhjennä luettelo"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Avaa"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Poista luettelosta"</string>
diff --git a/android/app/res/values-fr-rCA/strings.xml b/android/app/res/values-fr-rCA/strings.xml
index 9e45c9833a..e3c29c7792 100644
--- a/android/app/res/values-fr-rCA/strings.xml
+++ b/android/app/res/values-fr-rCA/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Tous les éléments de la liste seront effacés."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Partage Bluetooth : fichiers envoyés"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Partage Bluetooth : fichiers reçus"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# fichier non transféré.}one{# fichier non transféré.}other{# fichiers non transférés.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# fichier transféré, %1$s}one{# fichier transféré, %1$s}other{# fichiers transférés, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Effacer la liste"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"ouvrir"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Effacer de la liste"</string>
diff --git a/android/app/res/values-fr/strings.xml b/android/app/res/values-fr/strings.xml
index ccce11a9e0..333b95ed8a 100644
--- a/android/app/res/values-fr/strings.xml
+++ b/android/app/res/values-fr/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Tous les éléments de la liste seront effacés."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Partage Bluetooth : fichiers envoyés"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Partage Bluetooth : fichiers reçus"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# échec.}one{# échec.}other{# échecs.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# succès, %1$s}one{# succès, %1$s}other{# succès, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Effacer la liste"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Ouvrir"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Effacer de la liste"</string>
diff --git a/android/app/res/values-gl/strings.xml b/android/app/res/values-gl/strings.xml
index 3346718209..a9b54c3fd8 100644
--- a/android/app/res/values-gl/strings.xml
+++ b/android/app/res/values-gl/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Borraranse todos os elementos da lista."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Uso compartido por Bluetooth: ficheiros enviados"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Uso compartido por Bluetooth: ficheiros recibidos"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# non transferido.}other{# non transferidos.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# transferido, %1$s}other{# transferidos, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Borrar lista"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Abrir"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Borrar da lista"</string>
diff --git a/android/app/res/values-gu/strings.xml b/android/app/res/values-gu/strings.xml
index 966d907931..3653a8aaac 100644
--- a/android/app/res/values-gu/strings.xml
+++ b/android/app/res/values-gu/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"સૂચિમાંથી તમામ આઇટમ્સ સાફ કરવામાં આવશે."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"બ્લૂટૂથ શેર: મોકલેલી ફાઇલો"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"બ્લૂટૂથ શેર: પ્રાપ્ત ફાઇલો"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# અસફળ.}one{# અસફળ.}other{# અસફળ.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# સફળ, %1$s}one{# સફળ, %1$s}other{# સફળ, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"સૂચિ સાફ કરો"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"ખોલો"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"સૂચિમાંથી સાફ કરો"</string>
diff --git a/android/app/res/values-hi/strings.xml b/android/app/res/values-hi/strings.xml
index 1e202e1561..736273c06a 100644
--- a/android/app/res/values-hi/strings.xml
+++ b/android/app/res/values-hi/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"सूची से सभी आइटम साफ़ कर दिए जाएंगे."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"ब्लूटूथ शेयर: भेजी गई फ़ाइलें"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"ब्लूटूथ शेयर: पाई गई फ़ाइलें"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# फ़ाइल शेयर नहीं की जा सकी.}one{# फ़ाइल शेयर नहीं की जा सकी.}other{# फ़ाइलें शेयर नहीं की जा सकीं.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# फ़ाइल शेयर की गई, %1$s}one{# फ़ाइल शेयर की गई, %1$s}other{# फ़ाइलें शेयर की गईं, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"सूची साफ़ करें"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"खोलें"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"सूची से साफ़ करें"</string>
diff --git a/android/app/res/values-hr/strings.xml b/android/app/res/values-hr/strings.xml
index f3094a432f..6e2cfdc85b 100644
--- a/android/app/res/values-hr/strings.xml
+++ b/android/app/res/values-hr/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"S popisa će biti izbrisane sve stavke."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth dijeljenje: poslane datoteke"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth dijeljenje: primljene datoteke"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# neuspješno.}one{# neuspješno.}few{# neuspješno.}other{# neuspješno.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# uspješno, %1$s}one{# uspješno, %1$s}few{# uspješno, %1$s}other{# uspješno, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Izbriši popis"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Otvori"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Izbriši s popisa"</string>
diff --git a/android/app/res/values-hu/strings.xml b/android/app/res/values-hu/strings.xml
index 104a9a94cf..c14d9b0080 100644
--- a/android/app/res/values-hu/strings.xml
+++ b/android/app/res/values-hu/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Minden elemet töröl a listáról."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth-megosztás: elküldött fájlok"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth-megosztás: fogadott fájlok"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# sikertelen.}other{# sikertelen.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# sikeres, %1$s}other{# sikeres, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Lista törlése"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Megnyitás"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Törlés a listáról"</string>
diff --git a/android/app/res/values-hy/strings.xml b/android/app/res/values-hy/strings.xml
index 4ccc27eea9..81e577a036 100644
--- a/android/app/res/values-hy/strings.xml
+++ b/android/app/res/values-hy/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Ցուցակի բոլոր տվյալները կջնջվեն:"</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth համօգտագործում՝ ֆայլերն ուղարկված են"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth համօգտագործում՝ ֆայլերը ստացված են"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# չհաջողված։}one{# չհաջողված։}other{# չհաջողված։}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# հաջողված, %1$s}one{# հաջողված, %1$s}other{# հաջողված, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Ջնջել ցուցակը"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Բաց"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Ջնջել ցուցակից"</string>
diff --git a/android/app/res/values-in/strings.xml b/android/app/res/values-in/strings.xml
index 07223ec90f..cb53c469f3 100644
--- a/android/app/res/values-in/strings.xml
+++ b/android/app/res/values-in/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Semua item akan dihapus dari daftar."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Berbagi bluetooth: Telah mengirimkan file"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Berbagi Bluetooth: File yang diterima"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# gagal.}other{# gagal.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# berhasil, %1$s}other{# berhasil, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Hapus daftar"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Buka"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Hapus dari daftar"</string>
diff --git a/android/app/res/values-is/strings.xml b/android/app/res/values-is/strings.xml
index 1b4232416b..5ca4de3d35 100644
--- a/android/app/res/values-is/strings.xml
+++ b/android/app/res/values-is/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Öll atriði verða hreinsuð af listanum."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth-deiling: Sendar skrár"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth-deiling: Mótteknar skrár"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# mistókst.}one{# mistókst.}other{# mistókust.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# tókst, %1$s}one{# tókst, %1$s}other{# tókust, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Hreinsa lista"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Opna"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Hreinsa af lista"</string>
diff --git a/android/app/res/values-it/strings.xml b/android/app/res/values-it/strings.xml
index 6da3cb55a1..bab5e54100 100644
--- a/android/app/res/values-it/strings.xml
+++ b/android/app/res/values-it/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Tutti gli elementi verranno cancellati dall\'elenco."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth: file inviati"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth: file ricevuti"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# non a buon fine.}other{# non a buon fine.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# a buon fine, %1$s}other{# a buon fine, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Cancella elenco"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Apri"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Cancella da elenco"</string>
diff --git a/android/app/res/values-iw/strings.xml b/android/app/res/values-iw/strings.xml
index 0966718128..ad24f441ba 100644
--- a/android/app/res/values-iw/strings.xml
+++ b/android/app/res/values-iw/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"כל הפריטים ינוקו מהרשימה."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"‏שיתוף Bluetooth: נשלחו קבצים"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"‏שיתוף Bluetooth: התקבלו קבצים"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# נכשל}two{# נכשלו}many{# נכשלו}other{# נכשלו}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{‏# הצליח, %1$s}two{‏# הצליחו, %1$s}many{‏# הצליחו, %1$s}other{‏# הצליחו, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"ניקוי רשימה"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"פתיחה"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"ניקוי מהרשימה"</string>
diff --git a/android/app/res/values-ja/strings.xml b/android/app/res/values-ja/strings.xml
index f2da90e7ca..f79762fcd4 100644
--- a/android/app/res/values-ja/strings.xml
+++ b/android/app/res/values-ja/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"すべてのアイテムがリストから消去されます。"</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth共有: 送信したファイル"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth共有: 受信したファイル"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# 件失敗。}other{# 件失敗。}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# 件成功、%1$s}other{# 件成功、%1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"リストを消去"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"開く"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"リストから消去"</string>
diff --git a/android/app/res/values-ka/strings.xml b/android/app/res/values-ka/strings.xml
index 1ccbf2d887..592eb4f7da 100644
--- a/android/app/res/values-ka/strings.xml
+++ b/android/app/res/values-ka/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"სიიდან ყველა ერთეული ამოიშლება."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth გაზიარება: გაგზავნილი ფაილები"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth გაზიარება: მიღებული ფაილები"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# წარუმატებელი.}other{# წარუმატებელი.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# წარმატებული, %1$s}other{# წარმატებული, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"სიის გასუფთავება"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"გახსნა"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"სიიდან ამოშლა"</string>
diff --git a/android/app/res/values-kk/strings.xml b/android/app/res/values-kk/strings.xml
index e8f9a45b21..16b1fa7e96 100644
--- a/android/app/res/values-kk/strings.xml
+++ b/android/app/res/values-kk/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Тізімнен барлық элементтер алынады."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth бөлісу: Жіберілген файлдар"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth бөлісу: Қабылданған файлдар"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# жіберілмеді.}other{# жіберілмеді.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# жіберілді, %1$s}other{# жіберілді, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Тізімді өшіру"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Ашу"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Тізімнен өшіру."</string>
diff --git a/android/app/res/values-km/strings.xml b/android/app/res/values-km/strings.xml
index bc5415c346..277c0b69e4 100644
--- a/android/app/res/values-km/strings.xml
+++ b/android/app/res/values-km/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"នឹង​សម្អាត​ធាតុ​ទាំងអស់​ពី​បញ្ជី។"</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"ការ​ចែក​រំលែក​ប៊្លូ​ធូ​ស៖ បាន​ផ្ញើ​ឯកសារ"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"ការ​ចែក​រំលែក​ប៊្លូ​ធូ​ស៖ បាន​ទទួល​​​ឯកសារ"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{មិនជោគជ័យ #។}other{មិនជោគជ័យ #។}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{ជោគជ័យ #, %1$s}other{ជោគជ័យ #, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"សម្អាត​បញ្ជី"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"បើក"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"សម្អាត​ពី​បញ្ជី"</string>
diff --git a/android/app/res/values-kn/strings.xml b/android/app/res/values-kn/strings.xml
index 9dbb8f862d..156f83a236 100644
--- a/android/app/res/values-kn/strings.xml
+++ b/android/app/res/values-kn/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"ಪಟ್ಟಿಯಿಂದ ಎಲ್ಲ ಐಟಂಗಳನ್ನು ತೆರವುಗೊಳಿಸಲಾಗುವುದು."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"ಬ್ಲೂಟೂತ್‌ ಹಂಚಿಕೆ: ಕಳುಹಿಸಲಾಗಿರುವ ಫೈಲ್‌‌ಗಳು"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"ಬ್ಲೂಟೂತ್‌ ಹಂಚಿಕೆ: ಫೈಲ್‌ಗಳನ್ನು ಸ್ವೀಕರಿಸಲಾಗಿದೆ"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# ವಿಫಲಗೊಂಡಿದೆ.}one{# ವಿಫಲಗೊಂಡಿದೆ.}other{# ವಿಫಲಗೊಂಡಿದೆ.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# ಯಶಸ್ವಿಯಾಗಿದೆ, %1$s}one{# ಯಶಸ್ವಿಯಾಗಿದೆ, %1$s}other{# ಯಶಸ್ವಿಯಾಗಿದೆ, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"ಪಟ್ಟಿಯನ್ನು ತೆರವುಗೊಳಿಸಿ"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"ತೆರೆಯಿರಿ"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"ಪಟ್ಟಿಯಿಂದ ತೆರವುಗೊಳಿಸಿ"</string>
diff --git a/android/app/res/values-ko/strings.xml b/android/app/res/values-ko/strings.xml
index 2d3e8f7ec3..773087efe3 100644
--- a/android/app/res/values-ko/strings.xml
+++ b/android/app/res/values-ko/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"목록에서 모든 항목이 삭제됩니다."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"블루투스 공유: 파일 보냄"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"블루투스 공유: 파일 받음"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{#개 실패}other{#개 실패}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{#개 성공, %1$s}other{#개 성공, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"목록 지우기"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"열기"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"목록에서 지우기"</string>
diff --git a/android/app/res/values-ky/strings.xml b/android/app/res/values-ky/strings.xml
index c59d1bf233..8ac563eed4 100644
--- a/android/app/res/values-ky/strings.xml
+++ b/android/app/res/values-ky/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Тизмек толугу менен тазаланат."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth бөлүшүү: Файлдар жөнөтүлдү"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth бөлүшүү: Алынган файлдар"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# жөнөтүлгөн жок.}other{# жөнөтүлгөн жок.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# ийгиликтүү жөнөтүлдү, %1$s}other{# ийгиликтүү жөнөтүлдү, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Тизмекти тазалоо"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Ачуу"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Тизмектен алып салуу"</string>
diff --git a/android/app/res/values-lo/strings.xml b/android/app/res/values-lo/strings.xml
index 0bea8630d7..786ae75d20 100644
--- a/android/app/res/values-lo/strings.xml
+++ b/android/app/res/values-lo/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"ລາຍການທັງໝົດຈະຖືກລຶບອອກຈາກລາຍການດັ່ງກ່າວ."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"ແບ່ງປັນໃນ Bluetooth: ໄຟລ໌ສົ່ງແລ້ວ"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"ແບ່ງປັນໃນ Bluetooth: ໄຟລ໌ໄດ້ຮັບແລ້ວ"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# ບໍ່ສຳເລັດ.}other{# ບໍ່ສຳເລັດ.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# ສຳເລັດ, %1$s}other{# ສຳເລັດ, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"ລຶບລາຍການ"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"ເປີດ"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"ລຶບອອກຈາກລາຍການ"</string>
diff --git a/android/app/res/values-lt/strings.xml b/android/app/res/values-lt/strings.xml
index 02ff6e7460..d29f1033f6 100644
--- a/android/app/res/values-lt/strings.xml
+++ b/android/app/res/values-lt/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Visi sąrašo elementai bus išvalyti."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"„Bluetooth“ bendrinimas: išsiųsti failai"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"„Bluetooth“ bendrinimas: gauti failai"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{nesėkmingų: #.}one{nesėkmingų: #.}few{nesėkmingų: #.}many{nesėkmingų: #.}other{nesėkmingų: #.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{Sėkmingų: #, %1$s}one{Sėkmingų: #, %1$s}few{Sėkmingų: #, %1$s}many{Sėkmingų: #, %1$s}other{Sėkmingų: #, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Išvalyti sąrašą"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Atidaryti"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Išvalyti iš sąrašo"</string>
diff --git a/android/app/res/values-lv/strings.xml b/android/app/res/values-lv/strings.xml
index e1d686d533..a250dcff4d 100644
--- a/android/app/res/values-lv/strings.xml
+++ b/android/app/res/values-lv/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"No saraksta tiks notīrīti visi vienumi."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth Share: nosūtītie faili"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth Share: saņemtie faili"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{neizdevās: #.}zero{neizdevās: #.}one{neizdevās: #.}other{neizdevās: #.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{Izdevās: #; %1$s}zero{Izdevās: #; %1$s}one{Izdevās: #; %1$s}other{Izdevās: #; %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Notīrīt sarakstu"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Atvērt"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Notīrīt no saraksta"</string>
diff --git a/android/app/res/values-mk/strings.xml b/android/app/res/values-mk/strings.xml
index 296db6c4d7..72c52117be 100644
--- a/android/app/res/values-mk/strings.xml
+++ b/android/app/res/values-mk/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Сите ставки ќе бидат избришани од списокот."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Сподели преку Bluetooth: Пратени датотеки"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Сподели преку Bluetooth: Примени датотеки"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# неуспешна.}one{# неуспешна.}other{# неуспешни.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# успешна, %1$s}one{# успешна, %1$s}other{# успешни, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Исчисти список"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Отвори"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Исчисти од списокот"</string>
diff --git a/android/app/res/values-ml/strings.xml b/android/app/res/values-ml/strings.xml
index 72776d60f7..58de9dde68 100644
--- a/android/app/res/values-ml/strings.xml
+++ b/android/app/res/values-ml/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"ലിസ്റ്റിൽ നിന്നും എല്ലാ ഇനങ്ങളും മായ്‌ക്കും."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"ബ്ലൂടൂത്ത് പങ്കിടൽ: അയച്ച ഫയലുകൾ"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"ബ്ലൂടൂത്ത് പങ്കിടൽ: ലഭിച്ച ഫയലുകൾ"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# എണ്ണം അയയ്ക്കാനായില്ല.}other{# എണ്ണം അയയ്ക്കാനായില്ല.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# എണ്ണം അയച്ചു, %1$s}other{# എണ്ണം അയച്ചു, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"ലിസ്റ്റ് മായ്‌ക്കുക"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"തുറക്കുക"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"ലിസ്റ്റിൽ നിന്നും മായ്‌ക്കുക"</string>
diff --git a/android/app/res/values-mn/strings.xml b/android/app/res/values-mn/strings.xml
index 039c796659..6eaec121ec 100644
--- a/android/app/res/values-mn/strings.xml
+++ b/android/app/res/values-mn/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Жагсаалтаас бүгдийг нь арилгах болно."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth хуваалцах: Илгээсэн файлууд"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth хуваалцах: Хүлээн авсан файлууд"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# амжилтгүй.}other{# амжилтгүй.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# амжилттай, %1$s}other{# амжилттай, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Жагсаалтыг арилгах"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Нээх"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Жагсаалтаас арилгах"</string>
diff --git a/android/app/res/values-mr/strings.xml b/android/app/res/values-mr/strings.xml
index 9097a639a8..6f7665f332 100644
--- a/android/app/res/values-mr/strings.xml
+++ b/android/app/res/values-mr/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"सूचीमधून सर्व आयटम साफ केले जातील."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"ब्लूटूथ शेअर: पाठवलेल्या फाइल"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"ब्लूटूथ शेअर: मिळवलेल्‍या फाइल"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# यशस्वी झाले नाही.}other{# यशस्वी झाले नाही.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# यशस्वी झाले, %1$s}other{# यशस्वी झाले, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"सूची साफ करा"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"उघडा"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"सूचीमधून साफ करा"</string>
diff --git a/android/app/res/values-ms/strings.xml b/android/app/res/values-ms/strings.xml
index 92cbeaa574..80a72a8d01 100644
--- a/android/app/res/values-ms/strings.xml
+++ b/android/app/res/values-ms/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Semua item akan dipadam bersih daripada senarai."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Perkongsian Bluetooth: Fail diterima"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Perkongsian Bluetooth: Fail diterima"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# tidak berjaya.}other{# tidak berjaya.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# berjaya, %1$s}other{# berjaya, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Padam bersih senarai"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Buka"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Padam bersih daripada senarai"</string>
diff --git a/android/app/res/values-my/strings.xml b/android/app/res/values-my/strings.xml
index 161d6045ba..ef04cfdb30 100644
--- a/android/app/res/values-my/strings.xml
+++ b/android/app/res/values-my/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"အရာများအားလုံး စာရင်းမှ ရှင်းလင်းပစ်လိမ့်မည်"</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"ဘလူးတုသ် ဝေမျှမှု - ဖိုင်ပို့ပြီး"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"ဘလူးတုသ် ဝေမျှမှု - ရရှိပြီးဖိုင်များ"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# ခု မအောင်မြင်ပါ။}other{# ခု မအောင်မြင်ပါ။}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# ခု အောင်မြင်သည်။ %1$s}other{# ခု အောင်မြင်သည်။ %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"စာရင်းကို ဖယ်ရှားရန်"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"ဖွင့်ရန်"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"စာရင်းမှ ရှင်းပစ်မည်"</string>
diff --git a/android/app/res/values-nb/strings.xml b/android/app/res/values-nb/strings.xml
index 1969699bb8..91f1b1fb03 100644
--- a/android/app/res/values-nb/strings.xml
+++ b/android/app/res/values-nb/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Alle elementer fjernes fra listen."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth-deling: Filer sendt"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth-deling: Filer mottatt"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# mislykket.}other{# mislykket.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# vellykket, %1$s}other{# vellykket, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Tøm listen"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Åpne"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Fjern fra listen"</string>
diff --git a/android/app/res/values-ne/strings.xml b/android/app/res/values-ne/strings.xml
index c0e723ddfb..0106f6edb0 100644
--- a/android/app/res/values-ne/strings.xml
+++ b/android/app/res/values-ne/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"सूचीबाट सम्पूर्ण वस्तुहरू मेटाइने छन्।"</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"ब्लुटुथ साझेदारी: पठाइएका फाइलहरू"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"ब्लुटुथ साझेदारी: प्राप्त फाइलहरू"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# वटा फाइल सेयर गर्न सकिएन।}other{# वटा फाइल सेयर गर्न सकिएन।}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# वटा फाइल सेयर गरियो, %1$s}other{# वटा फाइल सेयर गरियो, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"सूची हटाउनुहोस्"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"खोल्नुहोस्"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"सूचीबाट हटाउनुहोस्"</string>
diff --git a/android/app/res/values-nl/strings.xml b/android/app/res/values-nl/strings.xml
index 826d5cf0d5..e8bbc8bc2c 100644
--- a/android/app/res/values-nl/strings.xml
+++ b/android/app/res/values-nl/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Alle items op de lijst worden gewist."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Delen via bluetooth: verzonden bestanden"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Delen via bluetooth: ontvangen bestanden"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# mislukt.}other{# mislukt.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# geslaagd, %1$s}other{# geslaagd, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Lijst wissen"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Openen"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Wissen uit lijst"</string>
diff --git a/android/app/res/values-or/strings.xml b/android/app/res/values-or/strings.xml
index 111d8824bb..e6eeb5b492 100644
--- a/android/app/res/values-or/strings.xml
+++ b/android/app/res/values-or/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"ତାଲିକାରୁ ସମସ୍ତ ଆଇଟମ୍‌କୁ ଖାଲି କରିଦିଆଯିବ।"</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"ବ୍ଲୁଟୂଥ୍‍‌ ସେୟାର୍‌: ପଠାଯାଇଥିବା ଫାଇଲ୍‌"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"ବ୍ଲୁଟୂଥ୍‍‌ ସେୟାର୍‌: ପ୍ରାପ୍ତ କରାଯାଇଥିବା ଫାଇଲ୍‌"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{#ଟି ଅସଫଳ ହୋଇଛି।}other{#ଟି ଅସଫଳ ହୋଇଛି।}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{#ଟି ସଫଳ ହୋଇଛି, %1$s}other{#ଟି ସଫଳ ହୋଇଛି, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"ତାଲିକା ଖାଲି କରନ୍ତୁ"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"ଖୋଲନ୍ତୁ"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"ତାଲିକାରୁ ଖାଲି କରନ୍ତୁ"</string>
diff --git a/android/app/res/values-pa/strings.xml b/android/app/res/values-pa/strings.xml
index b3120c00cd..70454f57a4 100644
--- a/android/app/res/values-pa/strings.xml
+++ b/android/app/res/values-pa/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"ਸਾਰੀਆਂ ਆਈਟਮਾਂ ਸੂਚੀ ਵਿੱਚੋਂ ਹਟਾਈਆਂ ਜਾਣਗੀਆਂ।"</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"ਬਲੂਟੁੱਥ ਸਾਂਝਾਕਰਨ: ਭੇਜੀਆਂ ਗਈਆਂ ਫ਼ਾਈਲਾਂ"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"ਬਲੂਟੁੱਥ ਸਾਂਝਾਕਰਨ: ਪ੍ਰਾਪਤ ਕੀਤੀਆਂ ਫ਼ਾਈਲਾਂ"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# ਅਸਫਲ।}one{# ਅਸਫਲ।}other{# ਅਸਫਲ।}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# ਸਫਲ, %1$s}one{# ਸਫਲ, %1$s}other{# ਸਫਲ, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"ਸੂਚੀ ਹਟਾਓ"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"ਖੋਲ੍ਹੋ"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"ਸੂਚੀ ਵਿੱਚੋਂ ਹਟਾਓ"</string>
diff --git a/android/app/res/values-pl/strings.xml b/android/app/res/values-pl/strings.xml
index 928ea45009..129805a276 100644
--- a/android/app/res/values-pl/strings.xml
+++ b/android/app/res/values-pl/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Wszystkie elementy zostaną usunięte z listy."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Udostępnianie Bluetooth: wysłane pliki"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Udostępnianie Bluetooth: odebrane pliki"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{nieudane: #.}few{nieudane: #.}many{nieudane: #.}other{nieudane: #.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{Udane: #, %1$s}few{Udane: #, %1$s}many{Udane: #, %1$s}other{Udane: #, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Wyczyść listę"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Otwórz"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Usuń z listy"</string>
diff --git a/android/app/res/values-pt-rPT/strings.xml b/android/app/res/values-pt-rPT/strings.xml
index 76d933e5c4..96eaec5aaa 100644
--- a/android/app/res/values-pt-rPT/strings.xml
+++ b/android/app/res/values-pt-rPT/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Todos os itens serão removidos da lista."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Partilha por Bluetooth: ficheiros enviados"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Partilha por Bluetooth: ficheiros recebidos"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# sem êxito.}other{# sem êxito.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# com êxito, %1$s}other{# com êxito, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Limpar lista"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Abrir"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Limpar da lista"</string>
diff --git a/android/app/res/values-pt/strings.xml b/android/app/res/values-pt/strings.xml
index 2682f00161..2a36238b64 100644
--- a/android/app/res/values-pt/strings.xml
+++ b/android/app/res/values-pt/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Todos os itens serão excluídos da lista."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Compartilhamento Bluetooth: Arquivos enviados"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Compartilhamento Bluetooth: Arquivos recebidos"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# falhou.}one{# falhou.}other{# falharam.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# enviado, %1$s}one{# enviado, %1$s}other{# enviados, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Limpar lista"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Abrir"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Limpar da lista"</string>
diff --git a/android/app/res/values-ro/strings.xml b/android/app/res/values-ro/strings.xml
index bd296e65c3..bec5de64c1 100644
--- a/android/app/res/values-ro/strings.xml
+++ b/android/app/res/values-ro/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Toate elementele din listă vor fi eliminate."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Distribuire prin Bluetooth: fișiere trimise"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth: fișiere primite"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# netrimis.}few{# netrimise.}other{# netrimise.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# trimis, %1$s}few{# trimise, %1$s}other{# trimise, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Ștergeți lista"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Deschideți"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Ștergeți din listă"</string>
diff --git a/android/app/res/values-ru/strings.xml b/android/app/res/values-ru/strings.xml
index aee418cd30..7f206e40a5 100644
--- a/android/app/res/values-ru/strings.xml
+++ b/android/app/res/values-ru/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Все элементы будут удалены из списка."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Передано по Bluetooth"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Получено по Bluetooth"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{неуспешно – # файл.}one{неуспешно – # файл.}few{неуспешно – # файла.}many{неуспешно – # файлов.}other{неуспешно – # файла.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{Успешно передан # файл, %1$s}one{Успешно передан # файл, %1$s}few{Успешно передано # файла, %1$s}many{Успешно передано # файлов, %1$s}other{Успешно передано # файла, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Очистить список"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Открыть"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Удалить из списка"</string>
diff --git a/android/app/res/values-si/strings.xml b/android/app/res/values-si/strings.xml
index 0b5ddb80a0..615227e66c 100644
--- a/android/app/res/values-si/strings.xml
+++ b/android/app/res/values-si/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"ලැයිස්තුව වෙතින් සියලු අයිතම හිස් කරනු ඇත."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"බ්ලූටූත් බෙදා ගන්න: ගොනු යැවිණි"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"බ්ලූටූත් බෙදා ගැනීම: ගොනු ලැබිණි"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# අසාර්ථකයි.}one{# අසාර්ථකයි.}other{# අසාර්ථකයි.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# සාර්ථකයි, %1$s}one{# සාර්ථකයි, %1$s}other{# සාර්ථකයි, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"ලැයිස්තුව හිස් කරන්න"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"විවෘත කරන්න"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"ලැයිස්තුව වෙතින් හිස් කරන්න"</string>
diff --git a/android/app/res/values-sk/strings.xml b/android/app/res/values-sk/strings.xml
index b6fc4e338a..1f427882b9 100644
--- a/android/app/res/values-sk/strings.xml
+++ b/android/app/res/values-sk/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Zo zoznamu budú vymazané všetky položky."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth: Odoslané súbory"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth: Prijaté súbory"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# neúspech.}few{# neúspechy.}many{# neúspechu.}other{# neúspechov.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# úspech, %1$s}few{# úspechy, %1$s}many{# úspechu, %1$s}other{# úspechov, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Vymazať zoznam"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Otvoriť"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Vymazať zo zoznamu"</string>
diff --git a/android/app/res/values-sl/strings.xml b/android/app/res/values-sl/strings.xml
index 9fb4e07529..845d3210e1 100644
--- a/android/app/res/values-sl/strings.xml
+++ b/android/app/res/values-sl/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Vsi elementi bodo izbrisani s seznama."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth: Poslane datoteke"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth: Prejete datoteke"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{neuspešno: #.}one{neuspešno: #.}two{neuspešno: #.}few{neuspešno: #.}other{neuspešno: #.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{Uspešno: #, %1$s}one{Uspešno: #, %1$s}two{Uspešno: #, %1$s}few{Uspešno: #, %1$s}other{Uspešno: #, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Počisti seznam"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Odpri"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Počisti s seznama"</string>
diff --git a/android/app/res/values-sq/strings.xml b/android/app/res/values-sq/strings.xml
index 206eaca0ad..2d1a4b83a0 100644
--- a/android/app/res/values-sq/strings.xml
+++ b/android/app/res/values-sq/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Të gjithë artikujt do të pastrohen nga lista."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Shpërndarja përmes Bluetooth-it: Skedarët e dërguar"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Shpërndarja përmes bluetooth-it: Skedarët e pranuar"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# nuk u nda me sukses.}other{# nuk u ndanë me sukses.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# u nda me sukses, %1$s}other{# u ndanë me sukses, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Pastro listën"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Hap"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Pastro nga lista"</string>
diff --git a/android/app/res/values-sr/strings.xml b/android/app/res/values-sr/strings.xml
index 6b125acb42..b9e05b3d24 100644
--- a/android/app/res/values-sr/strings.xml
+++ b/android/app/res/values-sr/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Све ставке ће бити избрисане са листе."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Дељење преко Bluetooth-а: послате датотеке"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Дељење преко Bluetooth-а: примљене датотеке"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# неуспешно.}one{# неуспешно.}few{# неуспешна.}other{# неуспешних.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# успешно, %1$s}one{# успешно, %1$s}few{# успешна, %1$s}other{# успешних, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Обриши листу"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Отвори"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Обриши са листе"</string>
diff --git a/android/app/res/values-sv/strings.xml b/android/app/res/values-sv/strings.xml
index dd29081413..5c11c0b77a 100644
--- a/android/app/res/values-sv/strings.xml
+++ b/android/app/res/values-sv/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Alla objekt tas bort från listan."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth-delning: skickade filer"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth-delning: mottagna filer"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# misslyckades.}other{# misslyckades.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# lyckades, %1$s}other{# lyckades, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Rensa listan"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Öppna"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Ta bort från listan"</string>
diff --git a/android/app/res/values-sw/strings.xml b/android/app/res/values-sw/strings.xml
index 7fc3fc9d46..b42e4a209d 100644
--- a/android/app/res/values-sw/strings.xml
+++ b/android/app/res/values-sw/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Vipengee vyote vitafutwa kutoka kwenye orodha."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Kushiriki kwa bluetooth: Faili zilizotumwa"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Kushiriki kwa bluetooth: Faili zilizopokelewa"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{Haijafanikiwa #.}other{Hazijafanikiwa #.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{Imefanikiwa #, %1$s}other{Zimefanikiwa #, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Futa orodha"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Fungua"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Futa kutoka orodha"</string>
diff --git a/android/app/res/values-ta/strings.xml b/android/app/res/values-ta/strings.xml
index dd28c0f4ce..e46cb87475 100644
--- a/android/app/res/values-ta/strings.xml
+++ b/android/app/res/values-ta/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"பட்டியலிலிருந்து அனைத்தும் அழிக்கப்படும்."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"புளூடூத் பகிர்வு: அனுப்பியவை"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"புளூடூத் பகிர்வு: பெற்ற ஃபைல்கள்"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# அனுப்பப்படவில்லை.}other{# அனுப்பப்படவில்லை.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# அனுப்பப்பட்டது, %1$s}other{# அனுப்பப்பட்டன, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"பட்டியலை அழி"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"திற"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"பட்டியலிலிருந்து அழி"</string>
diff --git a/android/app/res/values-te/strings.xml b/android/app/res/values-te/strings.xml
index 57196ac0e2..920e6d78b1 100644
--- a/android/app/res/values-te/strings.xml
+++ b/android/app/res/values-te/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"లిస్ట్‌ నుండి అన్ని అంశాలు క్లియర్ చేయబడతాయి."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"బ్లూటూత్ షేర్: పంపిన ఫైళ్లు"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"బ్లూటూత్ షేర్: స్వీకరించబడిన ఫైళ్లు"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# విజయవంతం కాలేదు.}other{# విజయవంతం కాలేదు.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# విజయవంతం అయింది, %1$s}other{# విజయవంతం అయింది, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"లిస్ట్‌ను క్లియర్ చేయి"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"తెరువు"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"లిస్ట్‌ నుండి క్లియర్ చేయి"</string>
diff --git a/android/app/res/values-th/strings.xml b/android/app/res/values-th/strings.xml
index e571562c0e..5477f24f3e 100644
--- a/android/app/res/values-th/strings.xml
+++ b/android/app/res/values-th/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"รายการทั้งหมดจะถูกล้างจากรายการ"</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"การแชร์ทางบลูทูธ: ส่งไฟล์แล้ว"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"การแชร์ทางบลูทูธ: รับไฟล์แล้ว"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{ไม่สำเร็จ # รายการ}other{ไม่สำเร็จ # รายการ}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{สำเร็จ # รายการ, %1$s}other{สำเร็จ # รายการ, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"ล้างรายการ"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"เปิด"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"ล้างจากรายการ"</string>
diff --git a/android/app/res/values-tl/strings.xml b/android/app/res/values-tl/strings.xml
index 86257d202f..6edad864ad 100644
--- a/android/app/res/values-tl/strings.xml
+++ b/android/app/res/values-tl/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Iki-clear ang lahat ng mga item mula sa listahan."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth share: Mga naipadalang file"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth share: Mga natanggap na file"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# ang hindi matagumpay.}one{# ang hindi matagumpay.}other{# ang hindi matagumpay.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# ang matagumpay, %1$s}one{# ang matagumpay, %1$s}other{# ang matagumpay, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"I-clear ang listahan"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Buksan"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"I-clear mula sa listahan"</string>
diff --git a/android/app/res/values-tr/strings.xml b/android/app/res/values-tr/strings.xml
index fd74410083..f622f2f015 100644
--- a/android/app/res/values-tr/strings.xml
+++ b/android/app/res/values-tr/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Tüm öğeler listeden temizlenecek."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth paylaşımı: Gönderilen dosyalar"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth paylaşımı: Dosyalar alındı"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# başarısız.}other{# başarısız.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# başarılı, %1$s}other{# başarılı, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Listeyi temizle"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Aç"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Listeden temizle"</string>
diff --git a/android/app/res/values-uk/strings.xml b/android/app/res/values-uk/strings.xml
index ba671525b2..03fd7e6619 100644
--- a/android/app/res/values-uk/strings.xml
+++ b/android/app/res/values-uk/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Зі списку буде видалено всі елементи."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Через Bluetooth: надісл. файли"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Через Bluetooth: отримані файли"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# не надіслано.}one{# не надіслано.}few{# не надіслано.}many{# не надіслано.}other{# не надіслано.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# надіслано, %1$s}one{# надіслано, %1$s}few{# надіслано, %1$s}many{# надіслано, %1$s}other{# надіслано, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Очистити список"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Відкрити"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Видалити зі списку"</string>
diff --git a/android/app/res/values-ur/strings.xml b/android/app/res/values-ur/strings.xml
index e8d26fffb9..0cfee4c29c 100644
--- a/android/app/res/values-ur/strings.xml
+++ b/android/app/res/values-ur/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"سبھی آئٹمز فہرست سے صاف کر دیے جائیں گے۔"</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"بلوٹوتھ اشتراک: ارسال کردہ فائلیں"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"بلوٹوتھ اشتراک: فائلیں موصول ہو گئیں"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# ناکام۔}other{# ناکام۔}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{‏# کامیاب، ‎%1$s‎}other{‏# کامیاب، ‎%1$s‎}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"فہرست صاف کریں"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"کھولیں"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"فہرست سے صاف کریں"</string>
diff --git a/android/app/res/values-uz/strings.xml b/android/app/res/values-uz/strings.xml
index e2b77cc4f9..35a9f95138 100644
--- a/android/app/res/values-uz/strings.xml
+++ b/android/app/res/values-uz/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Barcha qaydlar ro‘yxatdan o‘chirib tashlanadi."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Bluetooth orqali yuborildi"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Bluetooth orqali olindi"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# ta yuborilmadi.}other{# ta yuborilmadi.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# ta yuborildi, %1$s}other{# ta yuborildi, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Ro‘yxatni tozalash"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Ochish"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Ro‘yxatdan o‘chirish"</string>
diff --git a/android/app/res/values-vi/strings.xml b/android/app/res/values-vi/strings.xml
index 1816c9d631..cada7d7b40 100644
--- a/android/app/res/values-vi/strings.xml
+++ b/android/app/res/values-vi/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Tất cả các mục sẽ bị xóa khỏi danh sách."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Chia sẻ qua Bluetooth: Tệp đã gửi"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Chia sẻ qua Bluetooth: Tệp đã nhận"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# không thành công.}other{# không thành công.}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# thành công, %1$s}other{# thành công, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Xóa danh sách"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Mở"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Xóa khỏi danh sách"</string>
diff --git a/android/app/res/values-zh-rCN/strings.xml b/android/app/res/values-zh-rCN/strings.xml
index ec33eb459d..9a74dc8e78 100644
--- a/android/app/res/values-zh-rCN/strings.xml
+++ b/android/app/res/values-zh-rCN/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"所有内容都将从列表中清除。"</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"蓝牙共享:已发送文件"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"蓝牙共享:已接收文件"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# 个文件发送失败。}other{# 个文件发送失败。}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# 个文件发送成功,%1$s}other{# 个文件发送成功,%1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"清除列表"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"打开"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"从列表中清除"</string>
diff --git a/android/app/res/values-zh-rHK/strings.xml b/android/app/res/values-zh-rHK/strings.xml
index b9b8c87466..cd33c81204 100644
--- a/android/app/res/values-zh-rHK/strings.xml
+++ b/android/app/res/values-zh-rHK/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"將會從清單清除所有項目。"</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"藍牙分享:傳送的檔案"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"藍牙分享:接收的檔案"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# 個失敗。}other{# 個失敗。}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{成功傳送 # 個檔案,%1$s}other{成功傳送 # 個檔案,%1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"清除清單"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"開啟"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"從清單清除"</string>
diff --git a/android/app/res/values-zh-rTW/strings.xml b/android/app/res/values-zh-rTW/strings.xml
index 38f15a3e4d..a5c5b8e12a 100644
--- a/android/app/res/values-zh-rTW/strings.xml
+++ b/android/app/res/values-zh-rTW/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"所有項目都會從清單中清除。"</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"藍牙分享:傳送的檔案"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"藍牙分享:接收的檔案"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{# 個失敗。}other{# 個失敗。}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{# 個檔案成功,%1$s}other{# 個檔案成功,%1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"清除清單"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"開啟"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"從清單清除"</string>
diff --git a/android/app/res/values-zu/strings.xml b/android/app/res/values-zu/strings.xml
index b060e0c090..18c798f38c 100644
--- a/android/app/res/values-zu/strings.xml
+++ b/android/app/res/values-zu/strings.xml
@@ -109,10 +109,8 @@
<string name="transfer_clear_dlg_msg" msgid="586117930961007311">"Zonke izintwana zizosulwa ohlwini."</string>
<string name="outbound_noti_title" msgid="2045560896819618979">"Abelana ne-Bluetooth. Amafayela athunyelwe"</string>
<string name="inbound_noti_title" msgid="3730993443609581977">"Abelana ne-Bluetooth: Amafayela atholakele"</string>
- <!-- no translation found for noti_caption_unsuccessful (8321968345160824888) -->
- <skip />
- <!-- no translation found for noti_caption_success (7914987425717863454) -->
- <skip />
+ <string name="noti_caption_unsuccessful" msgid="6679288016450410835">"{count,plural, =1{okungaphumelele #}one{okungaphumelele #}other{okungaphumelele #}}"</string>
+ <string name="noti_caption_success" msgid="7652777514009569713">"{count,plural, =1{okuphumelele #, %1$s}one{okuphumelele #, %1$s}other{okuphumelele #, %1$s}}"</string>
<string name="transfer_menu_clear_all" msgid="3014459758656427076">"Sula uhlu"</string>
<string name="transfer_menu_open" msgid="5193344638774400131">"Vula"</string>
<string name="transfer_menu_clear" msgid="7213491281898188730">"Sula ohlwini"</string>
diff --git a/android/app/res/values/strings.xml b/android/app/res/values/strings.xml
index e6409cbe42..cc489220ba 100644
--- a/android/app/res/values/strings.xml
+++ b/android/app/res/values/strings.xml
@@ -212,9 +212,11 @@
<string name="outbound_noti_title">Bluetooth share: Sent files</string>
<string name="inbound_noti_title">Bluetooth share: Received files</string>
<string name="noti_caption_unsuccessful"> {count, plural,
+ =1 {# unsuccessful.}
other {# unsuccessful.}
}</string>
<string name="noti_caption_success"> {count, plural,
+ =1 {# successful, %1$s}
other {# successful, %1$s}
}</string>
diff --git a/android/app/src/com/android/bluetooth/audio_util/MediaPlayerList.java b/android/app/src/com/android/bluetooth/audio_util/MediaPlayerList.java
index 32c0736a42..1eebe997d6 100644
--- a/android/app/src/com/android/bluetooth/audio_util/MediaPlayerList.java
+++ b/android/app/src/com/android/bluetooth/audio_util/MediaPlayerList.java
@@ -385,14 +385,23 @@ public class MediaPlayerList {
}
int playerIndex = Integer.parseInt(mediaId.substring(0, 2));
- String itemId = mediaId.substring(2);
-
if (!haveMediaBrowser(playerIndex)) {
e("playFolderItem: Do not have the a browsable player with ID " + playerIndex);
return;
}
- mBrowsablePlayers.get(playerIndex).playItem(itemId);
+ BrowsedPlayerWrapper wrapper = mBrowsablePlayers.get(playerIndex);
+ String itemId = mediaId.substring(2);
+ if (TextUtils.isEmpty(itemId)) {
+ itemId = wrapper.getRootId();
+ if (TextUtils.isEmpty(itemId)) {
+ e("playFolderItem: Failed to start playback with an empty media id.");
+ return;
+ }
+ Log.i(TAG, "playFolderItem: Empty media id, trying with the root id for "
+ + wrapper.getPackageName());
+ }
+ wrapper.playItem(itemId);
}
void getFolderItemsMediaPlayerList(GetFolderItemsCallback cb) {
diff --git a/android/app/src/com/android/bluetooth/avrcp/AvrcpNativeInterface.java b/android/app/src/com/android/bluetooth/avrcp/AvrcpNativeInterface.java
index 05ce16b5e6..65668e4617 100644
--- a/android/app/src/com/android/bluetooth/avrcp/AvrcpNativeInterface.java
+++ b/android/app/src/com/android/bluetooth/avrcp/AvrcpNativeInterface.java
@@ -196,7 +196,7 @@ public class AvrcpNativeInterface {
}
void playItem(int playerId, boolean nowPlaying, String mediaId) {
- d("playItem: playerId=" + playerId + " nowPlaying=" + nowPlaying + " mediaId" + mediaId);
+ d("playItem: playerId=" + playerId + " nowPlaying=" + nowPlaying + " mediaId=" + mediaId);
if (mAvrcpService == null) {
Log.d(TAG, "playItem: AvrcpTargetService is null");
return;
diff --git a/android/app/src/com/android/bluetooth/bas/BatteryService.java b/android/app/src/com/android/bluetooth/bas/BatteryService.java
index 8a2969137e..7afa86f207 100644
--- a/android/app/src/com/android/bluetooth/bas/BatteryService.java
+++ b/android/app/src/com/android/bluetooth/bas/BatteryService.java
@@ -416,8 +416,11 @@ public class BatteryService extends ProfileService {
return mAdapterService.getDatabase()
.getProfileConnectionPolicy(device, BluetoothProfile.BATTERY);
}
-
- void handleBatteryChanged(BluetoothDevice device, int batteryLevel) {
+ /**
+ * Called when the battery level of the device is notified.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public void handleBatteryChanged(BluetoothDevice device, int batteryLevel) {
mAdapterService.setBatteryLevel(device, batteryLevel);
}
diff --git a/android/app/src/com/android/bluetooth/bas/BatteryStateMachine.java b/android/app/src/com/android/bluetooth/bas/BatteryStateMachine.java
index b86562d7a0..8f8007a81f 100644
--- a/android/app/src/com/android/bluetooth/bas/BatteryStateMachine.java
+++ b/android/app/src/com/android/bluetooth/bas/BatteryStateMachine.java
@@ -73,7 +73,7 @@ public class BatteryStateMachine extends StateMachine {
WeakReference<BatteryService> mServiceRef;
BluetoothGatt mBluetoothGatt;
- BluetoothGattCallback mGattCallback;
+ GattCallback mGattCallback;
final BluetoothDevice mDevice;
BatteryStateMachine(BluetoothDevice device, BatteryService service, Looper looper) {
@@ -578,7 +578,11 @@ public class BatteryStateMachine extends StateMachine {
}
}
- private void updateBatteryLevel(byte[] value) {
+ @VisibleForTesting
+ void updateBatteryLevel(byte[] value) {
+ if (value.length <= 0) {
+ return;
+ }
int batteryLevel = value[0] & 0xFF;
BatteryService service = mServiceRef.get();
diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java
index 6dce0d1c0b..ad7739c904 100644
--- a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java
+++ b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java
@@ -691,6 +691,10 @@ class AdapterProperties {
BluetoothDevice device = connIntent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
int prevState = connIntent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1);
int state = connIntent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
+ if (state == BluetoothProfile.STATE_CONNECTING) {
+ BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_DEVICE_NAME_REPORTED,
+ mService.getMetricId(device), device.getName());
+ }
Log.d(TAG,
"PROFILE_CONNECTION_STATE_CHANGE: profile=" + profile + ", device=" + device + ", "
+ prevState + " -> " + state);
diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java
index 410e906b0e..f371a255f7 100644
--- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java
+++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java
@@ -496,7 +496,7 @@ public class AdapterService extends Service {
PackageManager.FEATURE_LEANBACK_ONLY);
mUserManager = getSystemService(UserManager.class);
initNative(mUserManager.isGuestUser(), isCommonCriteriaMode(), configCompareResult,
- getInitFlags(), isAtvDevice);
+ getInitFlags(), isAtvDevice, getApplicationInfo().dataDir);
mNativeAvailable = true;
mCallbacks = new RemoteCallbackList<IBluetoothCallback>();
mAppOps = getSystemService(AppOpsManager.class);
@@ -2691,7 +2691,7 @@ public class AdapterService extends Service {
ParcelUuid[] parcels = service.getRemoteUuids(device);
if (parcels == null) {
- parcels = new ParcelUuid[0];
+ return null;
}
return Arrays.asList(parcels);
}
@@ -5121,7 +5121,8 @@ public class AdapterService extends Service {
if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_BLUETOOTH, GD_LINK_POLICY_FLAG, false)) {
initFlags.add(String.format("%s=%s", GD_LINK_POLICY_FLAG, "true"));
}
- if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_BLUETOOTH, GATT_ROBUST_CACHING_FLAG, true)) {
+ if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_BLUETOOTH,
+ GATT_ROBUST_CACHING_FLAG, false)) {
initFlags.add(String.format("%s=%s", GATT_ROBUST_CACHING_FLAG, "true"));
}
if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_BLUETOOTH,
@@ -5443,7 +5444,8 @@ public class AdapterService extends Service {
static native void classInitNative();
native boolean initNative(boolean startRestricted, boolean isCommonCriteriaMode,
- int configCompareResult, String[] initFlags, boolean isAtvDevice);
+ int configCompareResult, String[] initFlags, boolean isAtvDevice,
+ String userDataDirectory);
native void cleanupNative();
diff --git a/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java b/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java
index 0d97b60c89..d62d7ba06d 100644
--- a/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java
+++ b/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java
@@ -331,6 +331,8 @@ final class BondStateMachine extends StateMachine {
} else {
result = mAdapterService.createBondNative(addr, transport);
}
+ BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_DEVICE_NAME_REPORTED,
+ mAdapterService.getMetricId(dev), dev.getName());
BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_BOND_STATE_CHANGED,
mAdapterService.obfuscateAddress(dev), transport, dev.getType(),
BluetoothDevice.BOND_BONDING,
diff --git a/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java b/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java
index 66fe33b334..4bc32b414d 100644
--- a/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java
+++ b/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java
@@ -1046,10 +1046,15 @@ public class DatabaseManager {
// Do not log anything if metadata doesn't fall into above categories
return;
}
+ String[] macAddress = device.getAddress().split(":");
BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_DEVICE_INFO_REPORTED,
mAdapterService.obfuscateAddress(device),
BluetoothProtoEnums.DEVICE_INFO_EXTERNAL, callingApp, manufacturerName, modelName,
- hardwareVersion, softwareVersion, mAdapterService.getMetricId(device));
+ hardwareVersion, softwareVersion, mAdapterService.getMetricId(device),
+ device.getAddressType(),
+ Integer.parseInt(macAddress[0], 16),
+ Integer.parseInt(macAddress[1], 16),
+ Integer.parseInt(macAddress[2], 16));
}
private void logMetadataChange(String address, String log) {
diff --git a/android/app/src/com/android/bluetooth/gatt/GattService.java b/android/app/src/com/android/bluetooth/gatt/GattService.java
index 29c2781d47..2e070cf128 100644
--- a/android/app/src/com/android/bluetooth/gatt/GattService.java
+++ b/android/app/src/com/android/bluetooth/gatt/GattService.java
@@ -3494,6 +3494,7 @@ public class GattService extends ProfileService {
Log.d(TAG, "clientConnect() - address=" + address + ", isDirect=" + isDirect
+ ", opportunistic=" + opportunistic + ", phy=" + phy);
}
+ statsLogAppPackage(address, attributionSource.getPackageName());
statsLogGattConnectionStateChange(
BluetoothProfile.GATT, address, clientIf,
BluetoothProtoEnums.CONNECTION_STATE_CONNECTING);
@@ -4160,6 +4161,7 @@ public class GattService extends ProfileService {
}
app.callback.onServerConnectionState((byte) 0, serverIf, connected, address);
+ statsLogAppPackage(address, app.name);
statsLogGattConnectionStateChange(
BluetoothProfile.GATT_SERVER, address, serverIf, connectionState);
}
@@ -4835,6 +4837,17 @@ public class GattService extends ProfileService {
}
}
+ private void statsLogAppPackage(String address, String app) {
+ BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
+ BluetoothStatsLog.write(
+ BluetoothStatsLog.BLUETOOTH_DEVICE_NAME_REPORTED,
+ mAdapterService.getMetricId(device), app);
+ if (DBG) {
+ Log.d(TAG, "Gatt Logging: metric_id=" + mAdapterService.getMetricId(device)
+ + ", app=" + app);
+ }
+ }
+
private void statsLogGattConnectionStateChange(
int profile, String address, int sessionIndex, int connectionState) {
BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java b/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
index 39d372f6e5..e431c43bde 100644
--- a/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
+++ b/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
@@ -1914,10 +1914,14 @@ public class HeadsetStateMachine extends StateMachine {
String vendorId = deviceInfo[0];
String productId = deviceInfo[1];
String version = deviceInfo[2];
+ String[] macAddress = device.getAddress().split(":");
BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_DEVICE_INFO_REPORTED,
mAdapterService.obfuscateAddress(device), BluetoothProtoEnums.DEVICE_INFO_INTERNAL,
BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_XAPL, vendorId, productId, version,
- null, mAdapterService.getMetricId(device));
+ null, mAdapterService.getMetricId(device),
+ device.getAddressType(),
+ Integer.parseInt(macAddress[0], 16),
+ Integer.parseInt(macAddress[1], 16), Integer.parseInt(macAddress[2], 16));
// feature = 2 indicates that we support battery level reporting only
mNativeInterface.atResponseString(device, "+XAPL=iPhone," + String.valueOf(2));
}
diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppService.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppService.java
index 6fab0ca50c..3bbd85d8ea 100644
--- a/android/app/src/com/android/bluetooth/opp/BluetoothOppService.java
+++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppService.java
@@ -37,7 +37,6 @@ import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothDevicePicker;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
@@ -53,6 +52,8 @@ import android.os.Binder;
import android.os.Handler;
import android.os.Message;
import android.os.Process;
+import android.os.UserHandle;
+import android.os.UserManager;
import android.sysprop.BluetoothProperties;
import android.util.Log;
@@ -251,9 +252,15 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti
Log.v(TAG, "start()");
}
+ //Check for user restrictions before enabling component
+ UserManager mUserManager = getSystemService(UserManager.class);
+ if (!mUserManager.hasUserRestrictionForUser(
+ UserManager.DISALLOW_BLUETOOTH_SHARING, UserHandle.CURRENT)) {
+ setComponentAvailable(LAUNCHER_ACTIVITY, true);
+ }
+
setComponentAvailable(OPP_PROVIDER, true);
setComponentAvailable(OPP_FILE_PROVIDER, true);
- setComponentAvailable(LAUNCHER_ACTIVITY, true);
setComponentAvailable(BT_ENABLE_ACTIVITY, true);
setComponentAvailable(BT_ERROR_ACTIVITY, true);
setComponentAvailable(BT_ENABLING_ACTIVITY, true);
diff --git a/android/app/tests/unit/Android.bp b/android/app/tests/unit/Android.bp
index 1ff2b0e3fc..ab9fe68b48 100755
--- a/android/app/tests/unit/Android.bp
+++ b/android/app/tests/unit/Android.bp
@@ -6,7 +6,7 @@ android_test {
name: "BluetoothInstrumentationTests",
// We only want this apk build for tests.
- certificate: ":com.android.bluetooth.services.certificate",
+ certificate: ":com.android.bluetooth.certificate",
libs: [
"javax.obex",
diff --git a/android/app/tests/unit/AndroidManifest.xml b/android/app/tests/unit/AndroidManifest.xml
index e1927e5402..cf50f48508 100644
--- a/android/app/tests/unit/AndroidManifest.xml
+++ b/android/app/tests/unit/AndroidManifest.xml
@@ -61,11 +61,11 @@
</application>
<!--
This declares that this application uses the instrumentation test runner targeting
- the package of com.android.bluetooth.services. To run the tests use the command:
+ the package of com.android.bluetooth. To run the tests use the command:
"adb shell am instrument -w com.android.bluetooth.tests/android.test.InstrumentationTestRunner"
-->
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.bluetooth.services"
- android:label="Tests for com.android.bluetooth.services"/>
+ android:targetPackage="com.android.bluetooth"
+ android:label="Tests for com.android.bluetooth"/>
</manifest>
diff --git a/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryStateMachineTest.java
index a63f0e3738..f6c3f79fb9 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryStateMachineTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryStateMachineTest.java
@@ -20,14 +20,15 @@ import static android.bluetooth.BluetoothGatt.GATT_SUCCESS;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.after;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.reset;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
@@ -38,22 +39,20 @@ import android.os.Looper;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
-import androidx.test.filters.MediumTest;
-import com.android.bluetooth.R;
import com.android.bluetooth.TestUtils;
import com.android.bluetooth.btservice.AdapterService;
import org.hamcrest.core.IsInstanceOf;
import org.junit.After;
import org.junit.Assert;
-import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
@@ -215,6 +214,36 @@ public class BatteryStateMachineTest {
IsInstanceOf.instanceOf(BatteryStateMachine.Disconnected.class));
}
+ @Test
+ public void testBatteryLevelChanged() {
+ allowConnection(true);
+ allowConnectGatt(true);
+
+ // To create a callback
+ mBatteryStateMachine.connectGatt();
+ mBatteryStateMachine.mGattCallback.updateBatteryLevel(new byte[]{(byte)0x30});
+
+ verify(mBatteryService, timeout(TIMEOUT_MS))
+ .handleBatteryChanged(any(BluetoothDevice.class), eq(0x30));
+ }
+
+ @Test
+ public void testEmptyBatteryLevelIgnored() {
+ allowConnection(true);
+ allowConnectGatt(true);
+
+ // To create a callback
+ mBatteryStateMachine.connectGatt();
+ try {
+ mBatteryStateMachine.mGattCallback.updateBatteryLevel(new byte[0]);
+ } catch (Exception ex) {
+ fail();
+ }
+
+ verify(mBatteryService, after(WAIT_MS).never())
+ .handleBatteryChanged(any(BluetoothDevice.class), anyInt());
+ }
+
// It simulates GATT connection for testing.
public class StubBatteryStateMachine extends BatteryStateMachine {
boolean mShouldAllowGatt = true;
diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java
index 1680713c57..042480d345 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java
@@ -192,7 +192,7 @@ public class AdapterServiceTest {
Assert.assertNotNull(Looper.myLooper());
AdapterService adapterService = new AdapterService();
adapterService.initNative(false /* is_restricted */, false /* is_common_criteria_mode */,
- 0 /* config_compare_result */, new String[0], false);
+ 0 /* config_compare_result */, new String[0], false, "");
adapterService.cleanupNative();
HashMap<String, HashMap<String, String>> adapterConfig = TestUtils.readAdapterConfig();
Assert.assertNotNull(adapterConfig);
diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java
index fb9eb96374..0722e35797 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java
@@ -115,7 +115,7 @@ public class ProfileServiceTest {
mMockAdapterService.initNative(false /* is_restricted */,
false /* is_common_criteria_mode */, 0 /* config_compare_result */,
- new String[0], false);
+ new String[0], false, "");
TestUtils.setAdapterService(mMockAdapterService);
doReturn(mDatabaseManager).when(mMockAdapterService).getDatabase();
diff --git a/apex/Android.bp b/apex/Android.bp
index 348613b7b5..e6fd115971 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -8,11 +8,12 @@ package {
}
linker_config {
- name: "bluetooth-linker-config",
+ name: "btservices-linker-config",
src: "linker.config.json",
installable: false,
}
+// TODO: Remove
apex {
// TODO(b/224561763): Qualcomm to refactor BT modifications into APEX.
name: "com.android.bluetooth",
@@ -33,23 +34,60 @@ apex {
"audio_set_configurations_json",
"audio_set_scenarios_bfbs",
"audio_set_scenarios_json",
- "bluetooth-linker-config",
+ "btservices-linker-config",
"bt_did.conf",
"bt_stack.conf",
- "privapp_allowlist_com.android.bluetooth.services.xml",
+ "privapp_allowlist_com.android.bluetooth.xml",
],
+ key: "com.android.btservices.key",
+ certificate: ":com.android.btservices.certificate",
+ updatable: false,
+ compressible: false,
+}
+
+// Mainline bluetooth apex module.
+apex {
+ name: "com.android.btservices",
+ defaults: ["t-launched-apex-module"],
+ manifest: "apex_manifest.json",
+ bootclasspath_fragments: ["com.android.btservices-bootclasspath-fragment"],
+ systemserverclasspath_fragments: ["com.android.btservices-systemserverclasspath-fragment"],
+ apps: ["Bluetooth"],
+
+ multilib: {
+ first: {
+ // Extractor process runs only with the primary ABI.
+ jni_libs: [
+ "libbluetooth_jni",
+ ],
+ },
+ },
+ min_sdk_version: "current",
+ enabled: false,
- key: "com.android.bluetooth.key",
- certificate: ":com.android.bluetooth.certificate",
+ prebuilts: [
+ "audio_set_configurations_bfbs",
+ "audio_set_configurations_json",
+ "audio_set_scenarios_bfbs",
+ "audio_set_scenarios_json",
+ "btservices-linker-config",
+ "bt_did.conf",
+ "bt_stack.conf",
+ "privapp_allowlist_com.android.bluetooth.xml",
+ ],
+ key: "com.android.btservices.key",
+ certificate: ":com.android.btservices.certificate",
+ updatable: false,
+ compressible: false,
}
apex_key {
- name: "com.android.bluetooth.key",
- public_key: "com.android.bluetooth.avbpubkey",
- private_key: "com.android.bluetooth.pem",
+ name: "com.android.btservices.key",
+ public_key: "com.android.btservices.avbpubkey",
+ private_key: "com.android.btservices.pem",
}
android_app_certificate {
- name: "com.android.bluetooth.certificate",
- certificate: "com.android.bluetooth",
+ name: "com.android.btservices.certificate",
+ certificate: "com.android.btservices",
}
diff --git a/apex/apex_manifest.json b/apex/apex_manifest.json
index b97fc52417..64e7fae37f 100644
--- a/apex/apex_manifest.json
+++ b/apex/apex_manifest.json
@@ -1,6 +1,11 @@
{
- "name": "com.android.bluetooth",
"version": 339990000,
+ "provideNativeLibs": [
+ ],
+ "provideSharedApexLibs": false,
+ "requireSharedApexLibs": [
+ ],
+ "name": "com.android.btservices",
"requireNativeLibs": [
"libaptX_encoder.so",
"libaptXHD_encoder.so"
diff --git a/apex/com.android.bluetooth.avbpubkey b/apex/com.android.btservices.avbpubkey
index 969211f93e..969211f93e 100644
--- a/apex/com.android.bluetooth.avbpubkey
+++ b/apex/com.android.btservices.avbpubkey
Binary files differ
diff --git a/apex/com.android.bluetooth.pem b/apex/com.android.btservices.pem
index dcbd2be1d4..dcbd2be1d4 100644
--- a/apex/com.android.bluetooth.pem
+++ b/apex/com.android.btservices.pem
diff --git a/apex/com.android.bluetooth.pk8 b/apex/com.android.btservices.pk8
index 59f489f8ff..59f489f8ff 100644
--- a/apex/com.android.bluetooth.pk8
+++ b/apex/com.android.btservices.pk8
Binary files differ
diff --git a/apex/com.android.bluetooth.x509.pem b/apex/com.android.btservices.x509.pem
index 71c169c8be..71c169c8be 100644
--- a/apex/com.android.bluetooth.x509.pem
+++ b/apex/com.android.btservices.x509.pem
diff --git a/apex/permissions/Android.bp b/apex/permissions/Android.bp
index 7e3803d84b..fdaad8d469 100644
--- a/apex/permissions/Android.bp
+++ b/apex/permissions/Android.bp
@@ -3,8 +3,8 @@ package {
}
prebuilt_etc {
- name: "privapp_allowlist_com.android.bluetooth.services.xml",
- src: "com.android.bluetooth.services.xml",
+ name: "privapp_allowlist_com.android.bluetooth.xml",
+ src: "com.android.bluetooth.xml",
sub_dir: "permissions",
installable: false,
-} \ No newline at end of file
+}
diff --git a/apex/permissions/com.android.bluetooth.services.xml b/apex/permissions/com.android.bluetooth.xml
index ef7d5524e8..a91256fc21 100644
--- a/apex/permissions/com.android.bluetooth.services.xml
+++ b/apex/permissions/com.android.bluetooth.xml
@@ -16,10 +16,9 @@
-->
<permissions>
- <privapp-permissions package="com.android.bluetooth.services">
+ <privapp-permissions package="com.android.bluetooth">
<permission name="android.permission.BLUETOOTH_PRIVILEGED" />
<permission name="android.permission.CONTROL_INCALL_EXPERIENCE" />
- <permission name="android.permission.DUMP" />
<permission name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
<permission name="android.permission.NFC_HANDOVER_STATUS" />
<permission name="android.permission.WRITE_SECURE_SETTINGS" />
diff --git a/framework/java/android/bluetooth/BluetoothDevice.java b/framework/java/android/bluetooth/BluetoothDevice.java
index 5ab621f627..d2921cf170 100644
--- a/framework/java/android/bluetooth/BluetoothDevice.java
+++ b/framework/java/android/bluetooth/BluetoothDevice.java
@@ -88,7 +88,6 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeoutException;
@@ -2411,8 +2410,8 @@ public final class BluetoothDevice implements Parcelable, Attributable {
new SynchronousResultReceiver();
service.getRemoteUuids(this, mAttributionSource, recv);
List<ParcelUuid> parcels = recv.awaitResultNoInterrupt(getSyncTimeout())
- .getValue(new ArrayList<>());
- return parcels.toArray(new ParcelUuid[parcels.size()]);
+ .getValue(null);
+ return parcels != null ? parcels.toArray(new ParcelUuid[parcels.size()]) : null;
} catch (RemoteException | TimeoutException e) {
Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
}
diff --git a/framework/java/android/bluetooth/le/AdvertisingSetParameters.java b/framework/java/android/bluetooth/le/AdvertisingSetParameters.java
index ecc2d7ccfe..9410eb7b1a 100644
--- a/framework/java/android/bluetooth/le/AdvertisingSetParameters.java
+++ b/framework/java/android/bluetooth/le/AdvertisingSetParameters.java
@@ -450,7 +450,7 @@ public final class AdvertisingSetParameters implements Parcelable {
*/
public Builder setTxPowerLevel(int txPowerLevel) {
String packageName = ActivityThread.currentPackageName();
- if (packageName.equals("com.android.bluetooth.services")) {
+ if (packageName.equals("com.android.bluetooth")) {
int maxPowerLevel = 20;
if (txPowerLevel < TX_POWER_MIN || txPowerLevel > maxPowerLevel) {
throw new IllegalArgumentException("invalid txPowerLevel " + txPowerLevel);
diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java
index fb19c6f848..e7fcf56692 100644
--- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java
+++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java
@@ -115,6 +115,7 @@ public class BluetoothManagerService extends IBluetoothManager.Stub {
private static final int ACTIVE_LOG_MAX_SIZE = 20;
private static final int CRASH_LOG_MAX_SIZE = 100;
+ private static final int DEFAULT_REBIND_COUNT = 3;
private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind
/**
@@ -1538,23 +1539,23 @@ public class BluetoothManagerService extends IBluetoothManager.Stub {
}
synchronized (mProfileServices) {
ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile));
+ Intent intent;
+ if (bluetoothProfile == BluetoothProfile.HEADSET
+ && BluetoothProperties.isProfileHfpAgEnabled().orElse(false)) {
+ intent = new Intent(IBluetoothHeadset.class.getName());
+ } else if (bluetoothProfile == BluetoothProfile.LE_CALL_CONTROL
+ && BluetoothProperties.isProfileCcpServerEnabled().orElse(false)) {
+ intent = new Intent(IBluetoothLeCallControl.class.getName());
+ } else {
+ return false;
+ }
if (psc == null) {
if (DBG) {
Log.d(TAG, "Creating new ProfileServiceConnections object for" + " profile: "
+ bluetoothProfile);
}
-
- Intent intent;
- if (bluetoothProfile == BluetoothProfile.HEADSET) {
- intent = new Intent(IBluetoothHeadset.class.getName());
- } else if (bluetoothProfile== BluetoothProfile.LE_CALL_CONTROL) {
- intent = new Intent(IBluetoothLeCallControl.class.getName());
- } else {
- return false;
- }
-
psc = new ProfileServiceConnections(intent);
- if (!psc.bindService()) {
+ if (!psc.bindService(DEFAULT_REBIND_COUNT)) {
return false;
}
@@ -1689,7 +1690,7 @@ public class BluetoothManagerService extends IBluetoothManager.Stub {
mIntent = intent;
}
- private boolean bindService() {
+ private boolean bindService(int rebindCount) {
int state = BluetoothAdapter.STATE_OFF;
try {
mBluetoothLock.readLock().lock();
@@ -1712,6 +1713,7 @@ public class BluetoothManagerService extends IBluetoothManager.Stub {
&& doBind(mIntent, this, 0, USER_HANDLE_CURRENT_OR_SELF)) {
Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
msg.obj = this;
+ msg.arg1 = rebindCount;
mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
return true;
}
@@ -1738,6 +1740,7 @@ public class BluetoothManagerService extends IBluetoothManager.Stub {
if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) {
Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
msg.obj = this;
+ msg.arg1 = DEFAULT_REBIND_COUNT;
mHandler.sendMessage(msg);
}
}
@@ -2506,8 +2509,11 @@ public class BluetoothManagerService extends IBluetoothManager.Stub {
Log.w(TAG, "psc is null, breaking");
break;
}
- Log.w(TAG, "Calling psc.bindService from MESSAGE_BIND_PROFILE_SERVICE");
- psc.bindService();
+ if (msg.arg1 > 0) {
+ mContext.unbindService(psc);
+ Log.w(TAG, "Calling psc.bindService from MESSAGE_BIND_PROFILE_SERVICE");
+ psc.bindService(msg.arg1 - 1);
+ }
break;
}
case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: {
@@ -3336,9 +3342,14 @@ public class BluetoothManagerService extends IBluetoothManager.Stub {
final ComponentName oppLauncherComponent = new ComponentName(
mContext.getPackageManager().getPackagesForUid(Process.BLUETOOTH_UID)[0],
"com.android.bluetooth.opp.BluetoothOppLauncherActivity");
- final int newState =
- bluetoothSharingDisallowed ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
- : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+ int newState;
+ if (bluetoothSharingDisallowed) {
+ newState = PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+ } else if (BluetoothProperties.isProfileOppEnabled().orElse(false)) {
+ newState = PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+ } else {
+ newState = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+ }
try {
mContext.createContextAsUser(userHandle, 0)
.getPackageManager()
diff --git a/service/java/com/android/server/bluetooth/BluetoothService.java b/service/java/com/android/server/bluetooth/BluetoothService.java
index ff6938e5f6..a729f8213a 100644
--- a/service/java/com/android/server/bluetooth/BluetoothService.java
+++ b/service/java/com/android/server/bluetooth/BluetoothService.java
@@ -50,8 +50,12 @@ public class BluetoothService extends SystemService {
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
publishBinderService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE,
mBluetoothManagerService);
- } else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY &&
- !UserManager.isHeadlessSystemUserMode()) {
+ }
+ }
+
+ @Override
+ public void onUserStarting(@NonNull TargetUser user) {
+ if (!UserManager.isHeadlessSystemUserMode()) {
initialize();
}
}
diff --git a/system/Android.mk b/system/Android.mk
index 1596e4981e..57a50409f0 100644
--- a/system/Android.mk
+++ b/system/Android.mk
@@ -46,13 +46,42 @@ LOCAL_target_executables := \
$(TARGET_OUT_EXECUTABLES)/bluetooth_stack_with_facade
LOCAL_target_libraries := \
+ $(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.bluetooth@1.0.so \
+ $(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.bluetooth@1.1.so \
+ $(TARGET_OUT_SHARED_LIBRARIES)/libandroid_runtime_lazy.so \
+ $(TARGET_OUT_SHARED_LIBRARIES)/libbacktrace.so \
+ $(TARGET_OUT_SHARED_LIBRARIES)/libbase.so \
+ $(TARGET_OUT_SHARED_LIBRARIES)/libbinder_ndk.so \
+ $(TARGET_OUT_SHARED_LIBRARIES)/libbinder.so \
+ $(TARGET_OUT_SHARED_LIBRARIES)/libc++.so \
$(TARGET_OUT_SHARED_LIBRARIES)/libcrypto.so \
- $(TARGET_OUT_SHARED_LIBRARIES)/libbluetooth_gd.so \
+ $(TARGET_OUT_SHARED_LIBRARIES)/libcutils.so \
+ $(TARGET_OUT_SHARED_LIBRARIES)/libgrpc_wrap.so \
$(TARGET_OUT_SHARED_LIBRARIES)/libgrpc++_unsecure.so \
$(TARGET_OUT_SHARED_LIBRARIES)/libgrpc++.so \
- $(TARGET_OUT_SHARED_LIBRARIES)/libgrpc_wrap.so \
- $(TARGET_OUT_SHARED_LIBRARIES)/libstatslog_bt.so
-#LINT.ThenChange(gd/cert/run)
+ $(TARGET_OUT_SHARED_LIBRARIES)/libhidlbase.so \
+ $(TARGET_OUT_SHARED_LIBRARIES)/liblog.so \
+ $(TARGET_OUT_SHARED_LIBRARIES)/liblzma.so \
+ $(TARGET_OUT_SHARED_LIBRARIES)/libprotobuf-cpp-full.so \
+ $(TARGET_OUT_SHARED_LIBRARIES)/libssl.so \
+ $(TARGET_OUT_SHARED_LIBRARIES)/libstatslog_bt.so \
+ $(TARGET_OUT_SHARED_LIBRARIES)/libunwindstack.so \
+ $(TARGET_OUT_SHARED_LIBRARIES)/libutils.so \
+ $(TARGET_OUT_SHARED_LIBRARIES)/libz.so
+ # libclang_rt.asan-aarch64-android.so is only generated for ASAN build and included automatically
+ # on devices
+ # $(TARGET_OUT_SHARED_LIBRARIES)/libclang_rt.asan-aarch64-android.so \
+ # libc.so, libdl_android.so, libdl.so, and libm.so are provided by com.android.runtime APEX
+ # Hence we cannot manually add them here
+ # $(TARGET_OUT_SHARED_LIBRARIES)/libc.so \
+ # $(TARGET_OUT_SHARED_LIBRARIES)/libdl_android.so \
+ # $(TARGET_OUT_SHARED_LIBRARIES)/libdl.so \
+ # $(TARGET_OUT_SHARED_LIBRARIES)/libm.so \
+ # libstatssocket.so is provided by co.android.os.statsd APEX
+ # $(TARGET_OUT_SHARED_LIBRARIES)/libstatssocket.so
+ # linux-vdso.so.1 is always provided by OS
+ # $(TARGET_OUT_SHARED_LIBRARIES)/linux-vdso.so.1
+#LINT.ThenChange(blueberry/tests/gd/cert/gd_device.py)
bluetooth_cert_src_and_bin_zip := \
$(call intermediates-dir-for,PACKAGING,bluetooth_cert_src_and_bin,HOST)/bluetooth_cert_src_and_bin.zip
diff --git a/system/audio_hal_interface/aidl/client_interface_aidl.cc b/system/audio_hal_interface/aidl/client_interface_aidl.cc
index c5ffa0eeb0..814c6c7796 100644
--- a/system/audio_hal_interface/aidl/client_interface_aidl.cc
+++ b/system/audio_hal_interface/aidl/client_interface_aidl.cc
@@ -274,8 +274,14 @@ int BluetoothAudioClientInterface::StartSession() {
auto aidl_retval = provider_->startSession(
stack_if, transport_->GetAudioConfiguration(), latency_modes, &mq_desc);
if (!aidl_retval.isOk()) {
- LOG(FATAL) << __func__ << ": BluetoothAudioHal failure: "
- << aidl_retval.getDescription();
+ if (aidl_retval.getExceptionCode() == EX_ILLEGAL_ARGUMENT) {
+ LOG(ERROR) << __func__ << ": BluetoothAudioHal Error: "
+ << aidl_retval.getDescription() << ", audioConfig="
+ << transport_->GetAudioConfiguration().toString();
+ } else {
+ LOG(FATAL) << __func__ << ": BluetoothAudioHal failure: "
+ << aidl_retval.getDescription();
+ }
return -EPROTO;
}
data_mq.reset(new DataMQ(mq_desc));
diff --git a/system/blueberry/facade/hci/le_acl_manager_facade.proto b/system/blueberry/facade/hci/le_acl_manager_facade.proto
index 844f21ab5b..ad6423fb36 100644
--- a/system/blueberry/facade/hci/le_acl_manager_facade.proto
+++ b/system/blueberry/facade/hci/le_acl_manager_facade.proto
@@ -14,6 +14,9 @@ service LeAclManagerFacade {
rpc FetchAclData(LeHandleMsg) returns (stream LeAclData) {}
rpc FetchIncomingConnection(google.protobuf.Empty) returns (stream LeConnectionEvent) {}
rpc AddDeviceToResolvingList(IrkMsg) returns (google.protobuf.Empty) {}
+ rpc IsOnBackgroundList(BackgroundRequestMsg) returns (BackgroundResultMsg) {}
+ rpc RemoveFromBackgroundList(BackgroundRequestMsg)
+ returns (google.protobuf.Empty) {}
}
message LeHandleMsg {
@@ -44,3 +47,10 @@ message IrkMsg {
bytes local_irk = 3;
}
+message BackgroundRequestMsg {
+ blueberry.facade.BluetoothAddressWithType peer_address = 1;
+}
+
+message BackgroundResultMsg {
+ bool is_on_background_list = 1;
+}
diff --git a/system/blueberry/tests/gd/cert/adb.py b/system/blueberry/tests/gd/cert/adb.py
index 13f63f06b8..65dc990d43 100644
--- a/system/blueberry/tests/gd/cert/adb.py
+++ b/system/blueberry/tests/gd/cert/adb.py
@@ -156,3 +156,19 @@ class BlueberryAdbProxy(AdbProxy):
# The actual port we need to disable via adb is on the remote host.
host_port = remote_port
self.forward(["--remove", "tcp:%d" % host_port])
+
+ def path_exists(self, path):
+ """Check if a file path exists on an Android device
+
+ :param path: file path, could be a directory
+ :return: True if file path exists
+ """
+ try:
+ ret = self.shell("ls {}".format(path))
+ if ret is not None and len(ret) > 0:
+ return True
+ else:
+ return False
+ except AdbError as e:
+ logging.debug("path {} does not exist, error={}".format(path, e))
+ return False
diff --git a/system/blueberry/tests/gd/cert/closable.py b/system/blueberry/tests/gd/cert/closable.py
index a1c0737aef..06a6d0df18 100644
--- a/system/blueberry/tests/gd/cert/closable.py
+++ b/system/blueberry/tests/gd/cert/closable.py
@@ -13,8 +13,9 @@
# 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.
-
+import time
from abc import ABC, abstractmethod
+import logging
class Closable(ABC):
@@ -23,11 +24,17 @@ class Closable(ABC):
return self
def __exit__(self, type, value, traceback):
- self.close()
+ try:
+ self.close()
+ except Exception:
+ logging.warning("Failed to close or already closed")
return traceback is None
def __del__(self):
- self.close()
+ try:
+ self.close()
+ except Exception:
+ logging.warning("Failed to close or already closed")
@abstractmethod
def close(self):
@@ -37,3 +44,5 @@ class Closable(ABC):
def safeClose(closable):
if closable is not None:
closable.close()
+ # sleep for 100ms because GrpcEventQueue takes at most 100 ms to close
+ time.sleep(0.1)
diff --git a/system/blueberry/tests/gd/cert/gd_device.py b/system/blueberry/tests/gd/cert/gd_device.py
index 44a22c6cf7..d79098791c 100644
--- a/system/blueberry/tests/gd/cert/gd_device.py
+++ b/system/blueberry/tests/gd/cert/gd_device.py
@@ -463,6 +463,8 @@ class GdAndroidDevice(GdDeviceBase):
WAIT_FOR_DEVICE_TIMEOUT_SECONDS = 180
WAIT_FOR_DEVICE_SIGINT_TIMEOUT_SECONDS = 1
ADB_ABORT_EXIT_CODE = 134
+ DEVICE_LIB_DIR = "/system/lib64"
+ DEVICE_BIN_DIR = "/system/bin"
def __init__(self, grpc_port: str, grpc_root_server_port: str, signal_port: str, cmd: List[str], label: str,
type_identifier: str, name: str, serial_number: str, verbose_mode: bool):
@@ -490,12 +492,51 @@ class GdAndroidDevice(GdDeviceBase):
logging.info("Port forwarding done on device %s %s" % (self.label, self.serial_number))
# Push test binaries
- self.push_or_die(os.path.join(get_gd_root(), "target", "bluetooth_stack_with_facade"), "system/bin")
- self.push_or_die(os.path.join(get_gd_root(), "target", "libbluetooth_gd.so"), "system/lib64")
- self.push_or_die(os.path.join(get_gd_root(), "target", "libgrpc++_unsecure.so"), "system/lib64")
- self.push_or_die(os.path.join(get_gd_root(), "target", "libgrpc++.so"), "system/lib64")
- self.push_or_die(os.path.join(get_gd_root(), "target", "libgrpc_wrap.so"), "system/lib64")
- self.push_or_die(os.path.join(get_gd_root(), "target", "libstatslog_bt.so"), "system/lib64")
+ local_dir = os.path.join(get_gd_root(), "target")
+
+ def generate_dir_pair(local_dir, device_dir, filename):
+ return os.path.join(local_dir, filename), os.path.join(device_dir, filename)
+
+ # Do not override exist libraries shared by other binaries on the Android device to avoid corrupting the Android device
+ self.push_or_die(*generate_dir_pair(local_dir, self.DEVICE_BIN_DIR, "bluetooth_stack_with_facade"))
+ self.push_or_die(
+ *generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "android.hardware.bluetooth@1.0.so"),
+ overwrite_existing=False)
+ self.push_or_die(
+ *generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "android.hardware.bluetooth@1.1.so"),
+ overwrite_existing=False)
+ self.push_or_die(
+ *generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "libandroid_runtime_lazy.so"), overwrite_existing=False)
+ self.push_or_die(
+ *generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "libbacktrace.so"), overwrite_existing=False)
+ self.push_or_die(*generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "libbase.so"), overwrite_existing=False)
+ self.push_or_die(
+ *generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "libbinder_ndk.so"), overwrite_existing=False)
+ self.push_or_die(*generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "libbinder.so"), overwrite_existing=False)
+ self.push_or_die(*generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "libc++.so"), overwrite_existing=False)
+ # libclang_rt.asan-aarch64-android.so is only needed for ASAN build and is automatically included on device
+ #self.push_or_die(
+ # *generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "libclang_rt.asan-aarch64-android.so"),
+ # overwrite_existing=False)
+ self.push_or_die(*generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "libcrypto.so"), overwrite_existing=False)
+ self.push_or_die(*generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "libcutils.so"), overwrite_existing=False)
+ self.push_or_die(
+ *generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "libgrpc_wrap.so"), overwrite_existing=False)
+ self.push_or_die(*generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "libgrpc++_unsecure.so"))
+ self.push_or_die(*generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "libgrpc++.so"))
+ self.push_or_die(*generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "libhidlbase.so"), overwrite_existing=False)
+ self.push_or_die(*generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "liblog.so"), overwrite_existing=False)
+ self.push_or_die(*generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "liblzma.so"), overwrite_existing=False)
+ self.push_or_die(*generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "libprotobuf-cpp-full.so"))
+ self.push_or_die(*generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "libssl.so"), overwrite_existing=False)
+ self.push_or_die(*generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "libgrpc++.so"))
+ self.push_or_die(*generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "libstatslog_bt.so"))
+ self.push_or_die(
+ *generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "libunwindstack.so"), overwrite_existing=False)
+ self.push_or_die(*generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "libutils.so"), overwrite_existing=False)
+ self.push_or_die(*generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "libgrpc++.so"))
+ self.push_or_die(*generate_dir_pair(local_dir, self.DEVICE_LIB_DIR, "libz.so"), overwrite_existing=False)
+
logging.info("Binaries pushed to device %s %s" % (self.label, self.serial_number))
try:
@@ -674,7 +715,7 @@ class GdAndroidDevice(GdDeviceBase):
(device_time.isoformat(), host_time.isoformat(), int(max_delta_seconds * 1000)),
delta=max_delta_seconds)
- def push_or_die(self, src_file_path, dst_file_path, push_timeout=300):
+ def push_or_die(self, src_file_path, dst_file_path, push_timeout=300, overwrite_existing=True):
"""Pushes a file to the Android device
Args:
@@ -682,6 +723,9 @@ class GdAndroidDevice(GdDeviceBase):
dst_file_path: The destination of the file.
push_timeout: How long to wait for the push to finish in seconds
"""
+ if not overwrite_existing and self.adb.path_exists(dst_file_path):
+ logging.debug("Skip pushing {} to {} as it already exists on device".format(src_file_path, dst_file_path))
+ return
out = self.adb.push([src_file_path, dst_file_path], timeout=push_timeout).decode(UTF_8).rstrip()
if 'error' in out:
asserts.fail('Unable to push file %s to %s due to %s' % (src_file_path, dst_file_path, out))
diff --git a/system/blueberry/tests/gd/cert/py_le_acl_manager.py b/system/blueberry/tests/gd/cert/py_le_acl_manager.py
index 1cb0cbe665..c6df87d19d 100644
--- a/system/blueberry/tests/gd/cert/py_le_acl_manager.py
+++ b/system/blueberry/tests/gd/cert/py_le_acl_manager.py
@@ -55,9 +55,12 @@ class PyLeAclManagerAclConnection(IEventStream, Closable):
safeClose(self.connection_event_stream)
safeClose(self.acl_stream)
- def wait_for_disconnection_complete(self):
+ def disconnect(self):
+ self.le_acl_manager.Disconnect(le_acl_manager_facade.LeHandleMsg(handle=self.handle))
+
+ def wait_for_disconnection_complete(self, timeout=timedelta(seconds=30)):
disconnection_complete = HciCaptures.DisconnectionCompleteCapture()
- assertThat(self.connection_event_stream).emits(disconnection_complete)
+ assertThat(self.connection_event_stream).emits(disconnection_complete, timeout=timeout)
self.disconnect_reason = disconnection_complete.get().GetReason()
def send(self, data):
@@ -124,6 +127,14 @@ class PyLeAclManager(Closable):
self.next_token += 1
return token
+ def is_on_background_list(self, remote_addr):
+ return self.le_acl_manager.IsOnBackgroundList(
+ le_acl_manager_facade.BackgroundRequestMsg(peer_address=remote_addr))
+
+ def remove_from_background_list(self, remote_addr):
+ self.le_acl_manager.RemoveFromBackgroundList(
+ le_acl_manager_facade.BackgroundRequestMsg(peer_address=remote_addr))
+
def complete_connection(self, event_stream):
connection_complete = HciCaptures.LeConnectionCompleteCapture()
assertThat(event_stream).emits(connection_complete)
diff --git a/system/blueberry/tests/gd/hci/le_acl_manager_test.py b/system/blueberry/tests/gd/hci/le_acl_manager_test.py
index 5bdf758e6b..04fc50f79e 100644
--- a/system/blueberry/tests/gd/hci/le_acl_manager_test.py
+++ b/system/blueberry/tests/gd/hci/le_acl_manager_test.py
@@ -403,6 +403,46 @@ class LeAclManagerTest(gd_base_test.GdBaseTestClass):
is_direct=True)
self.dut_le_acl_manager.complete_outgoing_connection(token)
+ def test_background_connection_list(self):
+ self.set_privacy_policy_static()
+
+ # Start background connection
+ token_background = self.dut_le_acl_manager.initiate_connection(
+ remote_addr=common.BluetoothAddressWithType(
+ address=common.BluetoothAddress(address=bytes(self.cert_random_address, 'utf8')),
+ type=int(hci_packets.AddressType.RANDOM_DEVICE_ADDRESS)),
+ is_direct=False)
+
+ # Cert Advertises
+ advertising_handle = 0
+
+ py_hci_adv = self.cert_hci.create_advertisement(advertising_handle, self.cert_random_address,
+ hci_packets.LegacyAdvertisingProperties.ADV_IND, 155, 165)
+
+ py_hci_adv.set_data(b'Im_A_Cert')
+ py_hci_adv.set_scan_response(b'Im_A_C')
+ py_hci_adv.start()
+
+ # Check background connection complete
+ self.dut_le_acl_manager.complete_outgoing_connection(token_background)
+
+ msg = self.dut_le_acl_manager.is_on_background_list(
+ remote_addr=common.BluetoothAddressWithType(
+ address=common.BluetoothAddress(address=bytes(self.cert_random_address, 'utf8')),
+ type=int(hci_packets.AddressType.RANDOM_DEVICE_ADDRESS)))
+ assertThat(msg.is_on_background_list).isEqualTo(True)
+
+ self.dut_le_acl_manager.remove_from_background_list(
+ remote_addr=common.BluetoothAddressWithType(
+ address=common.BluetoothAddress(address=bytes(self.cert_random_address, 'utf8')),
+ type=int(hci_packets.AddressType.RANDOM_DEVICE_ADDRESS)))
+
+ msg = self.dut_le_acl_manager.is_on_background_list(
+ remote_addr=common.BluetoothAddressWithType(
+ address=common.BluetoothAddress(address=bytes(self.cert_random_address, 'utf8')),
+ type=int(hci_packets.AddressType.RANDOM_DEVICE_ADDRESS)))
+ assertThat(msg.is_on_background_list).isEqualTo(False)
+
if __name__ == '__main__':
test_runner.main()
diff --git a/system/blueberry/tests/gd_sl4a/gatt/gatt_connect_low_layer_test.py b/system/blueberry/tests/gd_sl4a/gatt/gatt_connect_low_layer_test.py
new file mode 100644
index 0000000000..316f58ae16
--- /dev/null
+++ b/system/blueberry/tests/gd_sl4a/gatt/gatt_connect_low_layer_test.py
@@ -0,0 +1,536 @@
+#!/usr/bin/env python3
+#
+# Copyright 2022 - The Android Open Source Project
+#
+# 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.
+
+import queue
+import logging
+import time
+from datetime import timedelta
+from grpc import RpcError
+
+from bluetooth_packets_python3 import hci_packets
+from blueberry.facade.hci import le_advertising_manager_facade_pb2 as le_advertising_facade
+from blueberry.facade.hci import le_initiator_address_facade_pb2 as le_initiator_address_facade
+from blueberry.facade import common_pb2 as common
+from blueberry.tests.gd.cert.closable import safeClose
+from blueberry.tests.gd.cert.truth import assertThat
+from blueberry.tests.gd.cert.py_le_acl_manager import PyLeAclManager
+from blueberry.tests.gd_sl4a.lib import gd_sl4a_base_test
+from blueberry.tests.gd_sl4a.lib.bt_constants import ble_scan_settings_modes, ble_address_types, scan_result, ble_scan_settings_phys, ble_scan_settings_callback_types
+from blueberry.tests.gd_sl4a.lib.ble_lib import generate_ble_scan_objects
+from blueberry.utils.bt_gatt_utils import setup_gatt_connection
+from blueberry.utils.bt_gatt_utils import GattTestUtilsError
+from blueberry.utils.bt_gatt_utils import disconnect_gatt_connection
+from blueberry.utils.bt_gatt_utils import wait_for_gatt_disconnect_event
+from blueberry.utils.bt_gatt_utils import wait_for_gatt_connection
+from blueberry.utils.bt_gatt_utils import close_gatt_client
+from mobly.controllers.android_device import AndroidDevice
+from mobly import asserts
+from mobly import test_runner
+from mobly.signals import TestFailure
+
+
+class GattConnectLowLayerTest(gd_sl4a_base_test.GdSl4aBaseTestClass):
+
+ def setup_class(self):
+ super().setup_class(cert_module='HCI_INTERFACES')
+ self.bluetooth_gatt_list = []
+ self.default_timeout = 30 # seconds
+
+ def setup_test(self):
+ super().setup_test()
+ self.cert_le_acl_manager = PyLeAclManager(self.cert)
+
+ def teardown_test(self):
+ try:
+ for bluetooth_gatt in self.bluetooth_gatt_list:
+ self.dut.sl4a.gattClientClose(bluetooth_gatt)
+ except Exception as err:
+ logging.error("Failed to close GATT client, error: {}".format(err))
+ try:
+ safeClose(self.cert_le_acl_manager)
+ except RpcError as err:
+ logging.error("Failed to close CERT acl manager, error: {}".format(err))
+ self.cert_le_acl_manager = None
+ super().teardown_test()
+
+ def _set_cert_privacy_policy_with_random_address(self, random_address):
+ private_policy = le_initiator_address_facade.PrivacyPolicy(
+ address_policy=le_initiator_address_facade.AddressPolicy.USE_STATIC_ADDRESS,
+ address_with_type=common.BluetoothAddressWithType(
+ address=common.BluetoothAddress(address=bytes(random_address, encoding='utf8')),
+ type=common.RANDOM_DEVICE_ADDRESS))
+ self.cert.hci_le_initiator_address.SetPrivacyPolicyForInitiatorAddress(private_policy)
+
+ def _start_cert_advertising_with_random_address(self, device_name, random_address):
+ gap_name = hci_packets.GapData()
+ gap_name.data_type = hci_packets.GapDataType.COMPLETE_LOCAL_NAME
+ gap_name.data = list(bytes(device_name, encoding='utf8'))
+ gap_data = le_advertising_facade.GapDataMsg(data=bytes(gap_name.Serialize()))
+ config = le_advertising_facade.AdvertisingConfig(
+ advertisement=[gap_data],
+ interval_min=512,
+ interval_max=768,
+ advertising_type=le_advertising_facade.AdvertisingEventType.ADV_IND,
+ own_address_type=common.USE_RANDOM_DEVICE_ADDRESS,
+ channel_map=7,
+ filter_policy=le_advertising_facade.AdvertisingFilterPolicy.ALL_DEVICES)
+ request = le_advertising_facade.CreateAdvertiserRequest(config=config)
+ logging.info("Creating advertiser")
+ create_response = self.cert.hci_le_advertising_manager.CreateAdvertiser(request)
+ logging.info("Created advertiser")
+ return create_response
+
+ def _start_dut_scanning_for_address(self, address_type, address):
+ logging.info("Start scanning for address {} with address type {}".format(address, address_type))
+ self.dut.sl4a.bleSetScanSettingsScanMode(ble_scan_settings_modes['low_latency'])
+ filter_list, scan_settings, scan_callback = generate_ble_scan_objects(self.dut.sl4a)
+ # Start scanning on SL4A DUT side
+ self.dut.sl4a.bleSetScanFilterDeviceAddressAndType(address, int(address_type))
+ self.dut.sl4a.bleBuildScanFilter(filter_list)
+ self.dut.sl4a.bleStartBleScan(filter_list, scan_settings, scan_callback)
+ return scan_callback
+
+ def _wait_for_scan_result_event(self, expected_event_name):
+ try:
+ # Verify if there is scan result
+ event_info = self.dut.ed.pop_event(expected_event_name, self.default_timeout)
+ # Print out scan result
+ mac_address = event_info['data']['Result']['deviceInfo']['address']
+ logging.info("Filter advertisement with address {}".format(mac_address))
+ return mac_address, event_info
+ except queue.Empty as error:
+ logging.error("Could not find initial advertisement.")
+ return None, None
+
+ def _stop_advertising(self, advertiser_id):
+ logging.info("Stop advertising")
+ remove_request = le_advertising_facade.RemoveAdvertiserRequest(advertiser_id=advertiser_id)
+ self.cert.hci_le_advertising_manager.RemoveAdvertiser(remove_request)
+ logging.info("Stopped advertising")
+
+ def _stop_scanning(self, scan_callback):
+ logging.info("Stop scanning")
+ self.dut.sl4a.bleStopBleScan(scan_callback)
+ logging.info("Stopped scanning")
+
+ def _disconnect_gatt(self, device: AndroidDevice, bluetooth_gatt, gatt_callback):
+ try:
+ disconnect_gatt_connection(device, bluetooth_gatt, gatt_callback)
+ except GattTestUtilsError as err:
+ logging.error(err)
+ asserts.fail("Cannot disconnect GATT , error={}".format(err))
+ finally:
+ close_gatt_client(device, bluetooth_gatt)
+ if bluetooth_gatt in self.bluetooth_gatt_list:
+ self.bluetooth_gatt_list.remove(bluetooth_gatt)
+
+ def _wait_for_gatt_connection(self, device: AndroidDevice, gatt_callback, bluetooth_gatt):
+ try:
+ wait_for_gatt_connection(device, gatt_callback, bluetooth_gatt, timeout=self.default_timeout)
+ except GattTestUtilsError as err:
+ logging.error(err)
+ asserts.fail("Cannot observe GATT connection , error={}".format(err))
+
+ def _wait_for_gatt_disconnection(self, device: AndroidDevice, gatt_callback):
+ try:
+ wait_for_gatt_disconnect_event(device, gatt_callback)
+ except GattTestUtilsError as err:
+ logging.error(err)
+ asserts.fail("Cannot observe GATT disconnection, error={}".format(err))
+
+ def test_autoconnect_gatt_without_pairing_and_disconnect_quickly(self):
+ """
+ Steps:
+ 1. CERT: advertises with Random Static address
+ 2. DUT: connect without pairing within 30 seconds
+ 3. CERT: verify GATT connection
+ 4. Wait 5 seconds
+ 5. DUT: Disconnect GATT
+ 6. CERT: Verify that GATT is disconnected within 5 seconds
+ """
+ # Use random address on cert side
+ logging.info("Setting random address")
+ RANDOM_ADDRESS = 'D0:05:04:03:02:01'
+ DEVICE_NAME = 'Im_The_CERT!'
+ self._set_cert_privacy_policy_with_random_address(RANDOM_ADDRESS)
+ logging.info("Set random address")
+
+ self.cert_le_acl_manager.listen_for_incoming_connections()
+
+ # Setup cert side to advertise
+ create_response = self._start_cert_advertising_with_random_address(DEVICE_NAME, RANDOM_ADDRESS)
+ logging.info("Started advertising")
+
+ # Setup SL4A DUT side to scan
+ addr_type = ble_address_types["random"]
+ scan_callback_token = self._start_dut_scanning_for_address(addr_type, RANDOM_ADDRESS)
+ logging.info("Started scanning")
+
+ # Wait for results
+ expected_event_name = scan_result.format(scan_callback_token)
+ scanned_mac_address, event_info = self._wait_for_scan_result_event(expected_event_name)
+
+ self._stop_scanning(scan_callback_token)
+ assertThat(scanned_mac_address).isNotNone()
+ assertThat(scanned_mac_address).isEqualTo(RANDOM_ADDRESS)
+
+ autoconnect = True
+ try:
+ bluetooth_gatt, gatt_callback = setup_gatt_connection(
+ self.dut, RANDOM_ADDRESS, autoconnect, timeout_seconds=self.default_timeout)
+ except GattTestUtilsError as err:
+ logging.error(err)
+ asserts.fail("Cannot make the first connection , error={}".format(err))
+ return
+ cert_acl_connection = self.cert_le_acl_manager.complete_incoming_connection()
+ self.dut.log.info("Device {} connected first time".format(RANDOM_ADDRESS))
+ self.dut.log.info("Sleeping 5 seconds to simulate real life connection")
+ time.sleep(5)
+ self.dut.log.info("Disconnecting GATT")
+ self._disconnect_gatt(self.dut, bluetooth_gatt, gatt_callback)
+ self.dut.log.info("Device {} disconnected first time from DUT".format(RANDOM_ADDRESS))
+ logging.info("Waiting 5 seconds to disconnect from CERT")
+ cert_acl_connection.wait_for_disconnection_complete(timeout=timedelta(seconds=5))
+ cert_acl_connection.close()
+ self._stop_advertising(create_response.advertiser_id)
+
+ def test_autoconnect_gatt_twice_with_random_address_without_pairing(self):
+ """
+ Steps:
+ 1. CERT: advertises with Random Static address
+ 2. DUT: connect without pairing
+ 3. CERT: verify GATT connection
+ 4. Wait 5 seconds
+ 5. DUT: Disconnect GATT
+ 6. CERT: Verify that GATT is disconnected within 30 seconds
+ 7. DUT: Try to connect to Cert again, and verify it can be connected
+ within 30 seconds
+ """
+ # Use random address on cert side
+ logging.info("Setting random address")
+ RANDOM_ADDRESS = 'D0:05:04:03:02:01'
+ DEVICE_NAME = 'Im_The_CERT!'
+ self._set_cert_privacy_policy_with_random_address(RANDOM_ADDRESS)
+ logging.info("Set random address")
+
+ self.cert_le_acl_manager.listen_for_incoming_connections()
+
+ # Setup cert side to advertise
+ create_response = self._start_cert_advertising_with_random_address(DEVICE_NAME, RANDOM_ADDRESS)
+ logging.info("Started advertising")
+
+ # Setup SL4A DUT side to scan
+ addr_type = ble_address_types["random"]
+ scan_callback_token = self._start_dut_scanning_for_address(addr_type, RANDOM_ADDRESS)
+ logging.info("Started scanning")
+
+ # Wait for results
+ expected_event_name = scan_result.format(scan_callback_token)
+ scanned_mac_address, event_info = self._wait_for_scan_result_event(expected_event_name)
+
+ self._stop_scanning(scan_callback_token)
+ assertThat(scanned_mac_address).isNotNone()
+ assertThat(scanned_mac_address).isEqualTo(RANDOM_ADDRESS)
+
+ logging.info("Setting up first GATT connection to CERT")
+ autoconnect = True
+ try:
+ bluetooth_gatt, gatt_callback = setup_gatt_connection(
+ self.dut, RANDOM_ADDRESS, autoconnect, timeout_seconds=self.default_timeout)
+ except GattTestUtilsError as err:
+ logging.error(err)
+ asserts.fail("Cannot make the first connection , error={}".format(err))
+ return
+ cert_acl_connection = self.cert_le_acl_manager.complete_incoming_connection()
+ # listen early as GATT might be reconnected on error
+ self.cert_le_acl_manager.listen_for_incoming_connections()
+ self.dut.log.info("Device {} connected first time".format(RANDOM_ADDRESS))
+ self.dut.log.info("Sleeping 5 seconds to simulate real life connection")
+ time.sleep(5)
+ self.dut.log.info("Disconnecting first GATT connection")
+ self._disconnect_gatt(self.dut, bluetooth_gatt, gatt_callback)
+ self.dut.log.info("Device {} disconnected first time from DUT".format(RANDOM_ADDRESS))
+ logging.info("Waiting 30 seconds to disconnect from CERT")
+ cert_acl_connection.wait_for_disconnection_complete(timeout=timedelta(seconds=30))
+ logging.info("Setting up second GATT connection to CERT")
+ try:
+ bluetooth_gatt, gatt_callback = setup_gatt_connection(
+ self.dut, RANDOM_ADDRESS, autoconnect, timeout_seconds=self.default_timeout)
+ except GattTestUtilsError as err:
+ close_gatt_client(self.dut, bluetooth_gatt)
+ logging.error(err)
+ asserts.fail("Cannot make the second connection , error={}".format(err))
+ cert_acl_connection = self.cert_le_acl_manager.complete_incoming_connection()
+ self.dut.log.info("Device {} connected second time".format(RANDOM_ADDRESS))
+ self.dut.log.info("Disconnect second GATT connection")
+ self._disconnect_gatt(self.dut, bluetooth_gatt, gatt_callback)
+ logging.info("Wait for CERT to disconnect")
+ cert_acl_connection.wait_for_disconnection_complete(timeout=timedelta(seconds=30))
+ cert_acl_connection.close()
+ self.dut.log.info("Device {} disconnected second time".format(RANDOM_ADDRESS))
+ self._stop_advertising(create_response.advertiser_id)
+
+ def test_disconnect_autoconnect_without_close(self):
+ """
+ Steps:
+ 1. CERT: advertises with Random Static address
+ 2. DUT: connect without pairing within 30 seconds
+ 3. CERT: verify GATT connection
+ 4. Wait 5 seconds
+ 5. DUT: Disconnect GATT, but do not close it, keep CERT advertising ON
+ 6. CERT: Verify that GATT is disconnected within 5 seconds
+ 7. CERT: Verify that no further GATT connection is made
+ 8. CERT: Stop advertising
+ """
+ # Use random address on cert side
+ logging.info("Setting random address")
+ RANDOM_ADDRESS = 'D0:05:04:03:02:01'
+ DEVICE_NAME = 'Im_The_CERT!'
+ self._set_cert_privacy_policy_with_random_address(RANDOM_ADDRESS)
+ logging.info("Set random address")
+
+ self.cert_le_acl_manager.listen_for_incoming_connections()
+
+ # Setup cert side to advertise
+ create_response = self._start_cert_advertising_with_random_address(DEVICE_NAME, RANDOM_ADDRESS)
+ logging.info("Started advertising")
+
+ # Setup SL4A DUT side to scan
+ addr_type = ble_address_types["random"]
+ scan_callback_token = self._start_dut_scanning_for_address(addr_type, RANDOM_ADDRESS)
+ logging.info("Started scanning")
+
+ # Wait for results
+ expected_event_name = scan_result.format(scan_callback_token)
+ scanned_mac_address, event_info = self._wait_for_scan_result_event(expected_event_name)
+
+ self._stop_scanning(scan_callback_token)
+ assertThat(scanned_mac_address).isNotNone()
+ assertThat(scanned_mac_address).isEqualTo(RANDOM_ADDRESS)
+
+ autoconnect = True
+ try:
+ bluetooth_gatt, gatt_callback = setup_gatt_connection(
+ self.dut, RANDOM_ADDRESS, autoconnect, timeout_seconds=self.default_timeout)
+ except GattTestUtilsError as err:
+ logging.error(err)
+ asserts.fail("Cannot make the first connection , error={}".format(err))
+ return
+ cert_acl_connection = self.cert_le_acl_manager.complete_incoming_connection()
+ self.cert_le_acl_manager.listen_for_incoming_connections()
+ self.dut.log.info("Device {} connected first time".format(RANDOM_ADDRESS))
+ self.dut.log.info("Sleeping 5 seconds to simulate real life connection")
+ time.sleep(5)
+ self.dut.log.info("Disconnect first GATT connection")
+ self._disconnect_gatt(self.dut, bluetooth_gatt, gatt_callback)
+ self.dut.log.info("Device {} disconnected first time from DUT".format(RANDOM_ADDRESS))
+ logging.info("Waiting 5 seconds to disconnect from CERT")
+ cert_acl_connection.wait_for_disconnection_complete(timeout=timedelta(seconds=5))
+ cert_acl_connection.close()
+ logging.info("Verifying that no further GATT connection is made")
+ try:
+ cert_acl_connection = self.cert_le_acl_manager.complete_incoming_connection()
+ asserts.fail("Should not have a GATT connection")
+ except TestFailure:
+ pass
+ logging.info("Stop advertising")
+ self._stop_advertising(create_response.advertiser_id)
+
+ def test_autoconnect_without_proactive_disconnect(self):
+ """
+ Steps:
+ 1. CERT: advertises with Random Static address
+ 2. DUT: connect without pairing within 30 seconds
+ 3. CERT: verify GATT connection
+ 4. Wait 5 seconds
+ 5. CERT: Turn off advertising
+ 6. CERT: Disconnect existing GATT connection
+ 7. DUT: Verify that GATT is disconnected within 5 seconds
+ 8. CERT: Start advertising
+ 9. DUT: Verify GATT connects within 5 seconds
+ 10. CERT: Stop advertising and disconnect DUT
+ 11. DUT: Verify that GATT disconnects within 5 seconds
+ """
+ # Use random address on cert side
+ logging.info("Setting random address")
+ RANDOM_ADDRESS = 'D0:05:04:03:02:01'
+ DEVICE_NAME = 'Im_The_CERT!'
+ self._set_cert_privacy_policy_with_random_address(RANDOM_ADDRESS)
+ logging.info("Set random address")
+
+ self.cert_le_acl_manager.listen_for_incoming_connections()
+
+ # Setup cert side to advertise
+ create_response = self._start_cert_advertising_with_random_address(DEVICE_NAME, RANDOM_ADDRESS)
+ logging.info("Started advertising")
+
+ # Setup SL4A DUT side to scan
+ addr_type = ble_address_types["random"]
+ scan_callback_token = self._start_dut_scanning_for_address(addr_type, RANDOM_ADDRESS)
+ logging.info("Started scanning")
+
+ # Wait for results
+ expected_event_name = scan_result.format(scan_callback_token)
+ scanned_mac_address, event_info = self._wait_for_scan_result_event(expected_event_name)
+
+ self._stop_scanning(scan_callback_token)
+ assertThat(scanned_mac_address).isNotNone()
+ assertThat(scanned_mac_address).isEqualTo(RANDOM_ADDRESS)
+
+ autoconnect = True
+ try:
+ bluetooth_gatt, gatt_callback = setup_gatt_connection(
+ self.dut, RANDOM_ADDRESS, autoconnect, timeout_seconds=self.default_timeout)
+ except GattTestUtilsError as err:
+ logging.error(err)
+ asserts.fail("Cannot make the first connection , error={}".format(err))
+ return
+ cert_acl_connection = self.cert_le_acl_manager.complete_incoming_connection()
+ self.dut.log.info("Device {} connected first time".format(RANDOM_ADDRESS))
+ self.dut.log.info("Sleeping 5 seconds to simulate real life connection")
+ time.sleep(5)
+ logging.info("Stopping cert advertising")
+ self._stop_advertising(create_response.advertiser_id)
+ logging.info("Disconnecting cert")
+ cert_acl_connection.disconnect()
+ logging.info("Waiting for cert to disconnect")
+ cert_acl_connection.wait_for_disconnection_complete(timeout=timedelta(seconds=10))
+ cert_acl_connection.close()
+ logging.info("Waiting for DUT to see disconnection")
+ self._wait_for_gatt_disconnection(self.dut, gatt_callback)
+ self.dut.log.info("Device {} disconnected first time from DUT".format(RANDOM_ADDRESS))
+ logging.info("Waiting 5 seconds to disconnect from CERT")
+ logging.info("Start CERT advertising")
+ self.cert_le_acl_manager.listen_for_incoming_connections()
+ create_response = self._start_cert_advertising_with_random_address(DEVICE_NAME, RANDOM_ADDRESS)
+ logging.info("Waiting for GATT to connect")
+ self._wait_for_gatt_connection(self.dut, gatt_callback, bluetooth_gatt)
+ logging.info("Waiting on CERT as well for background connection")
+ cert_acl_connection = self.cert_le_acl_manager.complete_incoming_connection()
+ logging.info("GATT is connected via background connection")
+ self.dut.log.info("Sleeping 5 seconds to simulate real life connection")
+ time.sleep(5)
+ logging.info("Stopping cert advertising")
+ self._stop_advertising(create_response.advertiser_id)
+ logging.info("Disconnecting cert")
+ cert_acl_connection.disconnect()
+ logging.info("Waiting for cert to disconnect")
+ cert_acl_connection.wait_for_disconnection_complete(timeout=timedelta(seconds=10))
+ cert_acl_connection.close()
+ logging.info("Waiting for DUT to see disconnection")
+ self._wait_for_gatt_disconnection(self.dut, gatt_callback)
+ logging.info("Verifying that no further GATT connection is made")
+ try:
+ self.cert_le_acl_manager.complete_incoming_connection()
+ asserts.fail("Should not have a GATT connection")
+ except TestFailure:
+ pass
+
+ def test_autoconnect_without_proactive_disconnect_repeatedly(self):
+ """
+ Steps:
+ 1. CERT: advertises with Random Static address
+ 2. DUT: connect without pairing within 30 seconds
+ 3. CERT: verify GATT connection
+ 4. Wait 5 seconds
+ 5. CERT: Turn off advertising
+ 6. CERT: Disconnect existing GATT connection
+ 7. DUT: Verify that GATT is disconnected within 5 seconds
+ 8. CERT: Start advertising
+ 9. DUT: Verify GATT connects within 5 seconds
+ 10. CERT: Stop advertising and disconnect DUT
+ 11. DUT: Verify that GATT disconnects within 5 seconds
+ 12. Repeat step 8 to 11 for 20 times
+ """
+ # Use random address on cert side
+ logging.info("Setting random address")
+ RANDOM_ADDRESS = 'D0:05:04:03:02:01'
+ DEVICE_NAME = 'Im_The_CERT!'
+ self._set_cert_privacy_policy_with_random_address(RANDOM_ADDRESS)
+ logging.info("Set random address")
+
+ self.cert_le_acl_manager.listen_for_incoming_connections()
+
+ # Setup cert side to advertise
+ create_response = self._start_cert_advertising_with_random_address(DEVICE_NAME, RANDOM_ADDRESS)
+ logging.info("Started advertising")
+
+ # Setup SL4A DUT side to scan
+ addr_type = ble_address_types["random"]
+ scan_callback_token = self._start_dut_scanning_for_address(addr_type, RANDOM_ADDRESS)
+ logging.info("Started scanning")
+
+ # Wait for results
+ expected_event_name = scan_result.format(scan_callback_token)
+ scanned_mac_address, event_info = self._wait_for_scan_result_event(expected_event_name)
+
+ self._stop_scanning(scan_callback_token)
+ assertThat(scanned_mac_address).isNotNone()
+ assertThat(scanned_mac_address).isEqualTo(RANDOM_ADDRESS)
+
+ autoconnect = True
+ try:
+ bluetooth_gatt, gatt_callback = setup_gatt_connection(
+ self.dut, RANDOM_ADDRESS, autoconnect, timeout_seconds=self.default_timeout)
+ except GattTestUtilsError as err:
+ logging.error(err)
+ asserts.fail("Cannot make the first connection , error={}".format(err))
+ return
+ cert_acl_connection = self.cert_le_acl_manager.complete_incoming_connection()
+ self.dut.log.info("Device {} connected first time".format(RANDOM_ADDRESS))
+ self.dut.log.info("Sleeping 5 seconds to simulate real life connection")
+ time.sleep(5)
+ logging.info("Stopping CERT advertising")
+ self._stop_advertising(create_response.advertiser_id)
+ logging.info("Stopped CERT advertising, now disconnect cert")
+ cert_acl_connection.disconnect()
+ logging.info("Waiting for cert to disconnect")
+ cert_acl_connection.wait_for_disconnection_complete(timeout=timedelta(seconds=10))
+ cert_acl_connection.close()
+ logging.info("Cert disconnected, waiting for DUT to see disconnection event")
+ self._wait_for_gatt_disconnection(self.dut, gatt_callback)
+ self.dut.log.info("Device {} disconnected first time from DUT".format(RANDOM_ADDRESS))
+ logging.info("Waiting 5 seconds to disconnect from CERT")
+ for i in range(20):
+ logging.info("Start advertising on CERT")
+ self.cert_le_acl_manager.listen_for_incoming_connections()
+ create_response = self._start_cert_advertising_with_random_address(DEVICE_NAME, RANDOM_ADDRESS)
+ self.dut.log.info("Wait on DUT for background GATT connection")
+ self._wait_for_gatt_connection(self.dut, gatt_callback, bluetooth_gatt)
+ logging.info("Waiting on CERT as well for background connection")
+ cert_acl_connection = self.cert_le_acl_manager.complete_incoming_connection()
+ logging.info("GATT is connected via background connection")
+ self.dut.log.info("Sleeping 5 seconds to simulate real life connection")
+ time.sleep(5)
+ logging.info("Stop advertising from CERT")
+ self._stop_advertising(create_response.advertiser_id)
+ logging.info("Disconnect from CERT")
+ cert_acl_connection.disconnect()
+ logging.info("Waiting on CERT end for disconnection to happen")
+ cert_acl_connection.wait_for_disconnection_complete(timeout=timedelta(seconds=10))
+ cert_acl_connection.close()
+ self.dut.log.info("Waiting on DUT end for disconnection to happen")
+ self._wait_for_gatt_disconnection(self.dut, gatt_callback)
+ logging.info("Verifying that no further GATT connection is made")
+ try:
+ cert_acl_connection = self.cert_le_acl_manager.complete_incoming_connection()
+ asserts.fail("Should not have a GATT connection")
+ except TestFailure:
+ pass
+
+
+if __name__ == '__main__':
+ test_runner.main()
diff --git a/system/blueberry/tests/gd_sl4a/gd_sl4a_test_runner.py b/system/blueberry/tests/gd_sl4a/gd_sl4a_test_runner.py
index 9c3a29ac4f..803678af18 100644
--- a/system/blueberry/tests/gd_sl4a/gd_sl4a_test_runner.py
+++ b/system/blueberry/tests/gd_sl4a/gd_sl4a_test_runner.py
@@ -16,11 +16,12 @@
from blueberry.tests.gd_sl4a.hci.le_advanced_scanning_test import LeAdvancedScanningTest
from blueberry.tests.gd_sl4a.security.oob_pairing_sl4a_test import OobPairingSl4aTest
+from blueberry.tests.gd_sl4a.gatt.gatt_connect_low_layer_test import GattConnectLowLayerTest
from mobly import suite_runner
import argparse
-ALL_TESTS = [LeAdvancedScanningTest, OobPairingSl4aTest]
+ALL_TESTS = [LeAdvancedScanningTest, OobPairingSl4aTest, GattConnectLowLayerTest]
def main():
diff --git a/system/blueberry/tests/gd_sl4a/hci/le_advanced_scanning_test.py b/system/blueberry/tests/gd_sl4a/hci/le_advanced_scanning_test.py
index 7f12ab7d47..fb7723c201 100644
--- a/system/blueberry/tests/gd_sl4a/hci/le_advanced_scanning_test.py
+++ b/system/blueberry/tests/gd_sl4a/hci/le_advanced_scanning_test.py
@@ -16,8 +16,6 @@
import queue
import logging
-import _thread
-import time
from google.protobuf import empty_pb2 as empty_proto
@@ -698,7 +696,7 @@ class LeAdvancedScanningTest(gd_sl4a_base_test.GdSl4aBaseTestClass):
(RANDOM_ADDRESS, addr_type, self.__get_test_irk().decode("utf-8")))
self.dut.sl4a.bleSetScanSettingsScanMode(ble_scan_settings_modes['low_latency'])
self.dut.sl4a.bleSetScanSettingsLegacy(False)
- self.dut.sl4a.bleSetScanSettingsCallbackType(ble_scan_settings_callback_types['match_lost'])
+ self.dut.sl4a.bleSetScanSettingsCallbackType(ble_scan_settings_callback_types['found_and_lost'])
filter_list, scan_settings, scan_callback = generate_ble_scan_objects(self.dut.sl4a)
expected_event_name = scan_result.format(scan_callback)
@@ -709,16 +707,16 @@ class LeAdvancedScanningTest(gd_sl4a_base_test.GdSl4aBaseTestClass):
self.dut.sl4a.bleStartBleScan(filter_list, scan_settings, scan_callback)
logging.info("Started scanning")
- def run(test, delay):
- time.sleep(delay)
- # Stop advertising to trigger the lost event
- test._stop_advertising(create_response.advertiser_id)
+ # Wait for found event to ensure scanning is started before stopping the advertiser
+ # to trigger lost event, else the lost event might not be caught by the test
+ got_found_result = self._wait_for_scan_result_event(expected_event_name)
+ assertThat(got_found_result).isTrue()
- _thread.start_new_thread(run, (self, 3))
+ self._stop_advertising(create_response.advertiser_id)
- # Wait for results
- got_result = self._wait_for_scan_result_event(expected_event_name)
- assertThat(got_result).isTrue()
+ # Wait for lost event
+ got_lost_result = self._wait_for_scan_result_event(expected_event_name)
+ assertThat(got_lost_result).isTrue()
# Test over
self._stop_scanning(scan_callback)
diff --git a/system/blueberry/tests/gd_sl4a/lib/gd_sl4a_base_test.py b/system/blueberry/tests/gd_sl4a/lib/gd_sl4a_base_test.py
index 24844ff1b8..d673adcc8a 100644
--- a/system/blueberry/tests/gd_sl4a/lib/gd_sl4a_base_test.py
+++ b/system/blueberry/tests/gd_sl4a/lib/gd_sl4a_base_test.py
@@ -34,6 +34,7 @@ from blueberry.tests.gd.cert.gd_device import MOBLY_CONTROLLER_CONFIG_NAME as GD
from blueberry.tests.gd_sl4a.lib.ble_lib import enable_bluetooth, disable_bluetooth, BleLib
from blueberry.facade import rootservice_pb2 as facade_rootservice
from blueberry.tests.gd.cert import gd_device
+from blueberry.utils.bt_test_utils import clear_bonded_devices
class GdSl4aBaseTestClass(BaseTestClass):
@@ -90,9 +91,11 @@ class GdSl4aBaseTestClass(BaseTestClass):
# Then enable Bluetooth
enable_bluetooth(self.dut.sl4a, self.dut.ed)
self.dut.sl4a.bluetoothDisableBLE()
+ clear_bonded_devices(self.dut)
return True
def teardown_test(self):
+ clear_bonded_devices(self.dut)
# Make sure BLE is disabled and Bluetooth is disabled after test
self.dut.sl4a.bluetoothDisableBLE()
disable_bluetooth(self.dut.sl4a, self.dut.ed)
diff --git a/system/blueberry/tests/sl4a_sl4a/gatt/gatt_connect_test.py b/system/blueberry/tests/sl4a_sl4a/gatt/gatt_connect_test.py
index a2dfea1eb3..db9186094e 100644
--- a/system/blueberry/tests/sl4a_sl4a/gatt/gatt_connect_test.py
+++ b/system/blueberry/tests/sl4a_sl4a/gatt/gatt_connect_test.py
@@ -49,6 +49,8 @@ from blueberry.utils.bt_gatt_utils import setup_gatt_connection
from blueberry.utils.bt_gatt_utils import setup_multiple_services
from blueberry.utils.bt_gatt_utils import wait_for_gatt_disconnect_event
from blueberry.utils.bt_test_utils import clear_bonded_devices
+from blueberry.tests.gd.cert.truth import assertThat
+from mobly import asserts
from mobly import test_runner
PHYSICAL_DISCONNECT_TIMEOUT = 5
@@ -90,7 +92,9 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
logging.info("Disconnecting from peripheral device.")
try:
disconnect_gatt_connection(self.central, bluetooth_gatt, gatt_callback)
+ logging.info("Disconnected GATT, closing GATT client.")
close_gatt_client(self.central, bluetooth_gatt)
+ logging.info("Closed GATT client, removing it from local tracker.")
if bluetooth_gatt in self.bluetooth_gatt_list:
self.bluetooth_gatt_list.remove(bluetooth_gatt)
except GattTestUtilsError as err:
@@ -168,9 +172,10 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
self.bluetooth_gatt_list.append(bluetooth_gatt)
except GattTestUtilsError as err:
logging.error(err)
- return False
+ asserts.fail("Failed to connect to GATT, error: {}".format(err))
+ return
self.adv_instances.append(adv_callback)
- return self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)
+ assertThat(self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)).isTrue()
@test_tracker_info(uuid='a839b505-03ac-4783-be7e-1d43129a1948')
def test_gatt_connect_stop_advertising(self):
@@ -208,21 +213,23 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
self.bluetooth_gatt_list.append(bluetooth_gatt)
except GattTestUtilsError as err:
logging.error(err)
- return False
+ asserts.fail("Failed to connect to GATT, error: {}".format(err))
+ return
self.peripheral.sl4a.bleStopBleAdvertising(adv_callback)
try:
event = self.central.ed.pop_event(
GattCallbackString.GATT_CONN_CHANGE.format(gatt_callback, self.default_timeout))
logging.error("Connection event found when not expected: {}".format(event))
- return False
+ asserts.fail("Connection event found when not expected: {}".format(event))
+ return
except Empty:
logging.info("No connection state change as expected")
try:
self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)
except Exception as err:
logging.info("Failed to orchestrate disconnect: {}".format(err))
- return False
- return True
+ asserts.fail("Failed to orchestrate disconnect: {}".format(err))
+ return
@test_tracker_info(uuid='b82f91a8-54bb-4779-a117-73dc7fdb28cc')
def test_gatt_connect_autoconnect(self):
@@ -254,37 +261,53 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
"""
gatt_server_cb = self.peripheral.sl4a.gattServerCreateGattServerCallback()
gatt_server = self.peripheral.sl4a.gattServerOpenGattServer(gatt_server_cb)
+ self.peripheral.log.info("Opened GATT server on CERT, scanning it from DUT")
self.gatt_server_list.append(gatt_server)
autoconnect = False
mac_address, adv_callback, scan_callback = (get_mac_address_of_generic_advertisement(
self.central, self.peripheral))
self.adv_instances.append(adv_callback)
+ self.central.log.info("Discovered BLE advertisement, connecting GATT with autoConnect={}".format(autoconnect))
try:
bluetooth_gatt, gatt_callback = setup_gatt_connection(self.central, mac_address, autoconnect)
+ self.central.log.info("GATT connected, stopping BLE scanning")
self.central.sl4a.bleStopBleScan(scan_callback)
+ self.central.log.info("Stopped BLE scanning")
self.bluetooth_gatt_list.append(bluetooth_gatt)
except GattTestUtilsError as err:
logging.error(err)
- return False
+ asserts.fail("Failed to connect to GATT, error: {}".format(err))
+ return
+ self.central.log.info("Disconnecting GATT")
try:
disconnect_gatt_connection(self.central, bluetooth_gatt, gatt_callback)
+ self.central.log.info("GATT disconnected, closing GATT client")
close_gatt_client(self.central, bluetooth_gatt)
+ self.central.log.info("GATT client closed, removing it from in-memory tracker")
if bluetooth_gatt in self.bluetooth_gatt_list:
self.bluetooth_gatt_list.remove(bluetooth_gatt)
except GattTestUtilsError as err:
logging.error(err)
- return False
+ asserts.fail("Failed to disconnect GATT, error: {}".format(err))
+ return
autoconnect = True
+ self.central.log.info("Connecting GATT with autoConnect={}".format(autoconnect))
bluetooth_gatt = self.central.sl4a.gattClientConnectGatt(
gatt_callback, mac_address, autoconnect, GattTransport.TRANSPORT_AUTO, False, GattPhyMask.PHY_LE_1M_MASK)
+ self.central.log.info("Waiting for GATt to become connected")
self.bluetooth_gatt_list.append(bluetooth_gatt)
expected_event = GattCallbackString.GATT_CONN_CHANGE.format(gatt_callback)
try:
event = self.central.ed.pop_event(expected_event, self.default_timeout)
+ self.central.log.info("Received event={}".format(event))
except Empty:
logging.error(GattCallbackError.GATT_CONN_CHANGE_ERR.format(expected_event))
- test_result = False
- return self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)
+ asserts.fail(GattCallbackError.GATT_CONN_CHANGE_ERR.format(expected_event))
+ return
+ found_state = event['data']['State']
+ expected_state = GattConnectionState.STATE_CONNECTED
+ assertThat(found_state).isEqualTo(expected_state)
+ assertThat(self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)).isTrue()
@test_tracker_info(uuid='e506fa50-7cd9-4bd8-938a-6b85dcfe6bc6')
def test_gatt_connect_opportunistic(self):
@@ -328,7 +351,8 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
self.bluetooth_gatt_list.append(bluetooth_gatt_1)
except GattTestUtilsError as err:
logging.error(err)
- return False
+ asserts.fail("Failed to connect to GATT 1, error: {}".format(err))
+ return
# Make GATT connection 2
try:
bluetooth_gatt_2, gatt_callback_2 = setup_gatt_connection(
@@ -336,7 +360,8 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
self.bluetooth_gatt_list.append(bluetooth_gatt_2)
except GattTestUtilsError as err:
logging.error(err)
- return False
+ asserts.fail("Failed to connect to GATT 2, error: {}".format(err))
+ return
# Disconnect GATT connection 1
try:
disconnect_gatt_connection(self.central, bluetooth_gatt_1, gatt_callback_1)
@@ -345,13 +370,13 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
self.bluetooth_gatt_list.remove(bluetooth_gatt_1)
except GattTestUtilsError as err:
logging.error(err)
- return False
+ asserts.fail("Failed to disconnect GATT 1, error: {}".format(err))
+ return
# Confirm that GATT connection 2 also disconnects
wait_for_gatt_disconnect_event(self.central, gatt_callback_2)
close_gatt_client(self.central, bluetooth_gatt_2)
if bluetooth_gatt_2 in self.bluetooth_gatt_list:
self.bluetooth_gatt_list.remove(bluetooth_gatt_2)
- return True
@test_tracker_info(uuid='1e01838e-c4de-4720-9adf-9e0419378226')
def test_gatt_request_min_mtu(self):
@@ -390,13 +415,13 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
self.bluetooth_gatt_list.append(bluetooth_gatt)
except GattTestUtilsError as err:
logging.error(err)
- return False
+ asserts.fail("Failed to connect to GATT, error: {}".format(err))
+ return
self.adv_instances.append(adv_callback)
expected_mtu = GattMtuSize.MIN
self.central.sl4a.gattClientRequestMtu(bluetooth_gatt, expected_mtu)
- if not self._verify_mtu_changed_on_client_and_server(expected_mtu, gatt_callback, gatt_server_cb):
- return False
- return self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)
+ assertThat(self._verify_mtu_changed_on_client_and_server(expected_mtu, gatt_callback, gatt_server_cb)).isTrue()
+ assertThat(self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)).isTrue()
@test_tracker_info(uuid='c1fa3a2d-fb47-47db-bdd1-458928cd6a5f')
def test_gatt_request_max_mtu(self):
@@ -435,13 +460,13 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
self.bluetooth_gatt_list.append(bluetooth_gatt)
except GattTestUtilsError as err:
logging.error(err)
- return False
+ asserts.fail("Failed to connect to GATT, error: {}".format(err))
+ return
self.adv_instances.append(adv_callback)
expected_mtu = GattMtuSize.MAX
self.central.sl4a.gattClientRequestMtu(bluetooth_gatt, expected_mtu)
- if not self._verify_mtu_changed_on_client_and_server(expected_mtu, gatt_callback, gatt_server_cb):
- return False
- return self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)
+ assertThat(self._verify_mtu_changed_on_client_and_server(expected_mtu, gatt_callback, gatt_server_cb)).isTrue()
+ assertThat(self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)).isTrue()
@test_tracker_info(uuid='4416d483-dec3-46cb-8038-4d82620f873a')
def test_gatt_request_out_of_bounds_mtu(self):
@@ -481,13 +506,14 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
self.bluetooth_gatt_list.append(bluetooth_gatt)
except GattTestUtilsError as err:
logging.error(err)
- return False
+ asserts.fail("Failed to connect to GATT, error: {}".format(err))
+ return
self.adv_instances.append(adv_callback)
unexpected_mtu = GattMtuSize.MIN - 1
self.central.sl4a.gattClientRequestMtu(bluetooth_gatt, unexpected_mtu)
- if self._verify_mtu_changed_on_client_and_server(unexpected_mtu, gatt_callback, gatt_server_cb):
- return False
- return self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)
+ assertThat(self._verify_mtu_changed_on_client_and_server(unexpected_mtu, gatt_callback,
+ gatt_server_cb)).isFalse()
+ assertThat(self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)).isTrue()
@test_tracker_info(uuid='31ffb9ca-cc75-43fb-9802-c19f1c5856b6')
def test_gatt_connect_trigger_on_read_rssi(self):
@@ -524,7 +550,8 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
self.bluetooth_gatt_list.append(bluetooth_gatt)
except GattTestUtilsError as err:
logging.error(err)
- return False
+ asserts.fail("Failed to connect to GATT, error: {}".format(err))
+ return
self.adv_instances.append(adv_callback)
expected_event = GattCallbackString.RD_REMOTE_RSSI.format(gatt_callback)
if self.central.sl4a.gattClientReadRSSI(bluetooth_gatt):
@@ -532,7 +559,7 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
self.central.ed.pop_event(expected_event, self.default_timeout)
except Empty:
logging.error(GattCallbackError.RD_REMOTE_RSSI_ERR.format(expected_event))
- return self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)
+ assertThat(self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)).isTrue()
@test_tracker_info(uuid='dee9ef28-b872-428a-821b-cc62f27ba936')
def test_gatt_connect_trigger_on_services_discovered(self):
@@ -569,7 +596,8 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
self.bluetooth_gatt_list.append(bluetooth_gatt)
except GattTestUtilsError as err:
logging.error(err)
- return False
+ asserts.fail("Failed to connect to GATT, error: {}".format(err))
+ return
self.adv_instances.append(adv_callback)
if self.central.sl4a.gattClientDiscoverServices(bluetooth_gatt):
expected_event = GattCallbackString.GATT_SERV_DISC.format(gatt_callback)
@@ -577,8 +605,9 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
event = self.central.ed.pop_event(expected_event, self.default_timeout)
except Empty:
logging.error(GattCallbackError.GATT_SERV_DISC_ERR.format(expected_event))
- return False
- return self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)
+ asserts.fail(GattCallbackError.GATT_SERV_DISC_ERR.format(expected_event))
+ return
+ assertThat(self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)).isTrue()
@test_tracker_info(uuid='01883bdd-0cf8-48fb-bf15-467bbd4f065b')
def test_gatt_connect_trigger_on_services_discovered_iterate_attributes(self):
@@ -620,7 +649,8 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
self.bluetooth_gatt_list.append(bluetooth_gatt)
except GattTestUtilsError as err:
logging.error(err)
- return False
+ asserts.fail("Failed to connect to GATT, error: {}".format(err))
+ return
self.adv_instances.append(adv_callback)
if self.central.sl4a.gattClientDiscoverServices(bluetooth_gatt):
expected_event = GattCallbackString.GATT_SERV_DISC.format(gatt_callback)
@@ -629,9 +659,10 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
discovered_services_index = event['data']['ServicesIndex']
except Empty:
logging.error(GattCallbackError.GATT_SERV_DISC_ERR.format(expected_event))
- return False
+ asserts.fail(GattCallbackError.GATT_SERV_DISC_ERR.format(expected_event))
+ return
log_gatt_server_uuids(self.central, discovered_services_index)
- return self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)
+ assertThat(self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)).isTrue()
@test_tracker_info(uuid='d4277bee-da99-4f48-8a4d-f81b5389da18')
def test_gatt_connect_with_service_uuid_variations(self):
@@ -666,13 +697,15 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
self.gatt_server_list.append(gatt_server)
except GattTestUtilsError as err:
logging.error(err)
- return False
+ asserts.fail("Failed to setup GATT service, error: {}".format(err))
+ return
try:
bluetooth_gatt, gatt_callback, adv_callback = (orchestrate_gatt_connection(self.central, self.peripheral))
self.bluetooth_gatt_list.append(bluetooth_gatt)
except GattTestUtilsError as err:
logging.error(err)
- return False
+ asserts.fail("Failed to connect to GATT, error: {}".format(err))
+ return
self.adv_instances.append(adv_callback)
if self.central.sl4a.gattClientDiscoverServices(bluetooth_gatt):
expected_event = GattCallbackString.GATT_SERV_DISC.format(gatt_callback)
@@ -680,11 +713,12 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
event = self.central.ed.pop_event(expected_event, self.default_timeout)
except Empty:
logging.error(GattCallbackError.GATT_SERV_DISC_ERR.format(expected_event))
- return False
+ asserts.fail(GattCallbackError.GATT_SERV_DISC_ERR.format(expected_event))
+ return
discovered_services_index = event['data']['ServicesIndex']
log_gatt_server_uuids(self.central, discovered_services_index)
- return self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)
+ assertThat(self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)).isTrue()
@test_tracker_info(uuid='7d3442c5-f71f-44ae-bd35-f2569f01b3b8')
def test_gatt_connect_in_quick_succession(self):
@@ -726,13 +760,14 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
self.central.sl4a.bleStopBleScan(scan_callback)
except GattTestUtilsError as err:
logging.error(err)
- return False
+ asserts.fail("Failed to connect to GATT at iteration {}, error: {}".format(i + 1, err))
+ return
test_result = self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)
if not test_result:
logging.info("Failed to disconnect from peripheral device.")
- return False
+ asserts.fail("Failed to disconnect from peripheral device.")
+ return
self.adv_instances.append(adv_callback)
- return True
@test_tracker_info(uuid='148469d9-7ab0-4c08-b2e9-7e49e88da1fc')
def test_gatt_connect_on_path_attack(self):
@@ -785,9 +820,7 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
gatt_service = self.peripheral.sl4a.gattServerCreateService(service_uuid, GattServiceType.SERVICE_TYPE_PRIMARY)
self.peripheral.sl4a.gattServerAddCharacteristicToService(gatt_service, characteristic)
self.peripheral.sl4a.gattServerAddService(gatt_server, gatt_service)
- result = self._find_service_added_event(gatt_server_cb, service_uuid)
- if not result:
- return False
+ assertThat(self._find_service_added_event(gatt_server_cb, service_uuid)).isTrue()
bluetooth_gatt, gatt_callback, adv_callback = (orchestrate_gatt_connection(self.central, self.peripheral))
self.bluetooth_gatt_list.append(bluetooth_gatt)
self.adv_instances.append(adv_callback)
@@ -797,11 +830,13 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
event = self.central.ed.pop_event(expected_event, self.default_timeout)
except Empty:
logging.error(GattCallbackError.GATT_SERV_DISC_ERR.format(expected_event))
- return False
+ asserts.fail(GattCallbackError.GATT_SERV_DISC_ERR.format(expected_event))
+ return
discovered_services_index = event['data']['ServicesIndex']
else:
logging.info("Failed to discover services.")
- return False
+ asserts.fail("Failed to discover services.")
+ return
test_value = [1, 2, 3, 4, 5, 6, 7]
services_count = self.central.sl4a.gattClientGetDiscoveredServicesCount(discovered_services_index)
for i in range(services_count):
@@ -842,8 +877,7 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
time.sleep(4)
for ad in [self.central, self.peripheral]:
- if not clear_bonded_devices(ad):
- return False
+ assertThat(clear_bonded_devices(ad)).isTrue()
# Necessary sleep time for entries to update unbonded state
time.sleep(2)
@@ -852,8 +886,9 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
bonded_devices = ad.sl4a.bluetoothGetBondedDevices()
if len(bonded_devices) > 0:
logging.error("Failed to unbond devices: {}".format(bonded_devices))
- return False
- return self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)
+ asserts.fail("Failed to unbond devices: {}".format(bonded_devices))
+ return
+ assertThat(self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)).isTrue()
@test_tracker_info(uuid='cc3fc361-7bf1-4ee2-9e46-4a27c88ce6a8')
def test_gatt_connect_get_connected_devices(self):
@@ -893,22 +928,25 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
self.bluetooth_gatt_list.append(bluetooth_gatt)
except GattTestUtilsError as err:
logging.error(err)
- return False
+ asserts.fail("Failed to connect to GATT, error: {}".format(err))
+ return
conn_cen_devices = self.central.sl4a.bluetoothGetConnectedLeDevices(BluetoothProfile.GATT)
conn_per_devices = self.peripheral.sl4a.bluetoothGetConnectedLeDevices(BluetoothProfile.GATT_SERVER)
target_name = self.peripheral.sl4a.bluetoothGetLocalName()
error_message = ("Connected device {} not found in list of connected " "devices {}")
if not any(d['name'] == target_name for d in conn_cen_devices):
logging.error(error_message.format(target_name, conn_cen_devices))
- return False
+ asserts.fail(error_message.format(target_name, conn_cen_devices))
+ return
# For the GATT server only check the size of the list since
# it may or may not include the device name.
target_name = self.central.sl4a.bluetoothGetLocalName()
if not conn_per_devices:
logging.error(error_message.format(target_name, conn_per_devices))
- return False
+ asserts.fail(error_message.format(target_name, conn_per_devices))
+ return
self.adv_instances.append(adv_callback)
- return self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)
+ assertThat(self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback)).isTrue()
@test_tracker_info(uuid='a0a37ca6-9fa8-4d35-9fdb-0e25b4b8a363')
def test_gatt_connect_second_adv_after_canceling_first_adv(self):
@@ -981,11 +1019,13 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
logging.info("Peripheral advertisement found with mac address: {}".format(mac_address_pre_restart))
except Empty:
logging.info("Peripheral advertisement not found")
- test_result = False
+ asserts.fail("Peripheral advertisement not found")
+ return
+ finally:
+ self.peripheral.sl4a.bleStopBleAdvertising(advertise_callback)
# Step 3: Restart peripheral advertising such that a new mac address is
# created.
- self.peripheral.sl4a.bleStopBleAdvertising(advertise_callback)
self.peripheral.sl4a.bleStartBleAdvertising(advertise_callback, advertise_data, advertise_settings)
mac_address_post_restart = mac_address_pre_restart
@@ -997,7 +1037,8 @@ class GattConnectTest(sl4a_sl4a_base_test.Sl4aSl4aBaseTestClass):
logging.info("Peripheral advertisement found with mac address: {}".format(mac_address_post_restart))
except Empty:
logging.info("Peripheral advertisement not found")
- test_result = False
+ asserts.fail("Peripheral advertisement not found")
+ return
if mac_address_pre_restart != mac_address_post_restart:
break
diff --git a/system/blueberry/utils/bt_gatt_utils.py b/system/blueberry/utils/bt_gatt_utils.py
index 4ad42eb3ee..6bb282ac41 100644
--- a/system/blueberry/utils/bt_gatt_utils.py
+++ b/system/blueberry/utils/bt_gatt_utils.py
@@ -48,14 +48,31 @@ def setup_gatt_connection(central: AndroidDevice,
mac_address,
autoconnect,
transport=GattTransport.TRANSPORT_AUTO,
- opportunistic=False):
+ opportunistic=False,
+ timeout_seconds=default_timeout):
gatt_callback = central.sl4a.gattCreateGattCallback()
log.info("Gatt Connect to mac address {}.".format(mac_address))
bluetooth_gatt = central.sl4a.gattClientConnectGatt(gatt_callback, mac_address, autoconnect, transport,
opportunistic, GattPhyMask.PHY_LE_1M_MASK)
expected_event = GattCallbackString.GATT_CONN_CHANGE.format(gatt_callback)
try:
- event = central.ed.pop_event(expected_event, default_timeout)
+ event = central.ed.pop_event(expected_event, timeout_seconds)
+ except Empty:
+ close_gatt_client(central, bluetooth_gatt)
+ raise GattTestUtilsError("Could not establish a connection to "
+ "peripheral. Expected event: {}".format(expected_event))
+ logging.info("Got connection event {}".format(event))
+ if event['data']['State'] != GattConnectionState.STATE_CONNECTED:
+ close_gatt_client(central, bluetooth_gatt)
+ raise GattTestUtilsError("Could not establish a connection to "
+ "peripheral. Event Details: {}".format(pprint.pformat(event)))
+ return bluetooth_gatt, gatt_callback
+
+
+def wait_for_gatt_connection(central: AndroidDevice, gatt_callback, bluetooth_gatt, timeout):
+ expected_event = GattCallbackString.GATT_CONN_CHANGE.format(gatt_callback)
+ try:
+ event = central.ed.pop_event(expected_event, timeout=timeout)
except Empty:
close_gatt_client(central, bluetooth_gatt)
raise GattTestUtilsError("Could not establish a connection to "
@@ -68,7 +85,6 @@ def setup_gatt_connection(central: AndroidDevice,
logging.debug("Failed to close gatt client.")
raise GattTestUtilsError("Could not establish a connection to "
"peripheral. Event Details: {}".format(pprint.pformat(event)))
- return bluetooth_gatt, gatt_callback
def close_gatt_client(central: AndroidDevice, bluetooth_gatt):
diff --git a/system/bta/dm/bta_dm_act.cc b/system/bta/dm/bta_dm_act.cc
index 52bb6448f0..cc6b7930bf 100644
--- a/system/bta/dm/bta_dm_act.cc
+++ b/system/bta/dm/bta_dm_act.cc
@@ -44,7 +44,6 @@
#include "main/shim/shim.h"
#include "osi/include/allocator.h"
#include "osi/include/compat.h"
-#include "osi/include/fixed_queue.h"
#include "osi/include/log.h"
#include "osi/include/osi.h"
#include "stack/btm/btm_ble_int.h"
@@ -321,8 +320,6 @@ void BTA_dm_on_hw_off() {
/* hw is ready, go on with BTA DM initialization */
alarm_free(bta_dm_search_cb.search_timer);
alarm_free(bta_dm_search_cb.gatt_close_timer);
- osi_free(bta_dm_search_cb.p_pending_search);
- fixed_queue_free(bta_dm_search_cb.pending_discovery_queue, osi_free);
memset(&bta_dm_search_cb, 0, sizeof(bta_dm_search_cb));
}
@@ -342,8 +339,6 @@ void BTA_dm_on_hw_on() {
/* hw is ready, go on with BTA DM initialization */
alarm_free(bta_dm_search_cb.search_timer);
alarm_free(bta_dm_search_cb.gatt_close_timer);
- osi_free(bta_dm_search_cb.p_pending_search);
- fixed_queue_free(bta_dm_search_cb.pending_discovery_queue, osi_free);
memset(&bta_dm_search_cb, 0, sizeof(bta_dm_search_cb));
/*
* TODO: Should alarm_free() the bta_dm_search_cb timers during
@@ -352,7 +347,6 @@ void BTA_dm_on_hw_on() {
bta_dm_search_cb.search_timer = alarm_new("bta_dm_search.search_timer");
bta_dm_search_cb.gatt_close_timer =
alarm_new("bta_dm_search.gatt_close_timer");
- bta_dm_search_cb.pending_discovery_queue = fixed_queue_new(SIZE_MAX);
memset(&bta_dm_conn_srvcs, 0, sizeof(bta_dm_conn_srvcs));
memset(&bta_dm_di_cb, 0, sizeof(tBTA_DM_DI_CB));
@@ -996,7 +990,7 @@ static bool bta_dm_read_remote_device_name(const RawAddress& bd_addr,
void bta_dm_inq_cmpl(uint8_t num) {
if (bta_dm_search_get_state() == BTA_DM_SEARCH_CANCELLING) {
bta_dm_search_set_state(BTA_DM_SEARCH_IDLE);
- bta_dm_execute_queued_request();
+ bta_dm_search_cancel_cmpl();
return;
}
@@ -1295,7 +1289,6 @@ void bta_dm_search_cmpl() {
/* no BLE connection, i.e. Classic service discovery end */
if (conn_id == GATT_INVALID_CONN_ID) {
bta_dm_search_cb.p_search_cback(BTA_DM_DISC_CMPL_EVT, nullptr);
- bta_dm_execute_queued_request();
return;
}
@@ -1306,7 +1299,6 @@ void bta_dm_search_cmpl() {
if (count == 0) {
LOG_INFO("Empty GATT database - no BLE services discovered");
bta_dm_search_cb.p_search_cback(BTA_DM_DISC_CMPL_EVT, nullptr);
- bta_dm_execute_queued_request();
return;
}
@@ -1331,8 +1323,6 @@ void bta_dm_search_cmpl() {
bta_dm_search_cb.p_search_cback(BTA_DM_DISC_BLE_RES_EVT, &result);
bta_dm_search_cb.p_search_cback(BTA_DM_DISC_CMPL_EVT, nullptr);
-
- bta_dm_execute_queued_request();
}
/*******************************************************************************
@@ -1429,13 +1419,13 @@ void bta_dm_free_sdp_db() {
*
* Function bta_dm_queue_search
*
- * Description Queues search command
+ * Description Queues search command while search is being cancelled
*
* Returns void
*
******************************************************************************/
void bta_dm_queue_search(tBTA_DM_MSG* p_data) {
- osi_free_and_reset((void**)&bta_dm_search_cb.p_pending_search);
+ bta_dm_search_clear_queue();
bta_dm_search_cb.p_pending_search =
(tBTA_DM_MSG*)osi_malloc(sizeof(tBTA_DM_API_SEARCH));
memcpy(bta_dm_search_cb.p_pending_search, p_data, sizeof(tBTA_DM_API_SEARCH));
@@ -1445,76 +1435,50 @@ void bta_dm_queue_search(tBTA_DM_MSG* p_data) {
*
* Function bta_dm_queue_disc
*
- * Description Queues discovery command
+ * Description Queues discovery command while search is being cancelled
*
* Returns void
*
******************************************************************************/
void bta_dm_queue_disc(tBTA_DM_MSG* p_data) {
- tBTA_DM_MSG* p_pending_discovery =
+ bta_dm_search_clear_queue();
+ bta_dm_search_cb.p_pending_discovery =
(tBTA_DM_MSG*)osi_malloc(sizeof(tBTA_DM_API_DISCOVER));
- memcpy(p_pending_discovery, p_data, sizeof(tBTA_DM_API_DISCOVER));
- fixed_queue_enqueue(bta_dm_search_cb.pending_discovery_queue,
- p_pending_discovery);
+ memcpy(bta_dm_search_cb.p_pending_discovery, p_data,
+ sizeof(tBTA_DM_API_DISCOVER));
}
/*******************************************************************************
*
- * Function bta_dm_execute_queued_request
+ * Function bta_dm_search_clear_queue
*
- * Description Executes queued request if one exists
+ * Description Clears the queue if API search cancel is called
*
* Returns void
*
******************************************************************************/
-void bta_dm_execute_queued_request() {
- if (bta_dm_search_cb.p_pending_search) {
- // Updated queued event to search event to trigger start search
- if (bta_dm_search_cb.p_pending_search->hdr.event ==
- BTA_DM_API_QUEUE_SEARCH_EVT) {
- bta_dm_search_cb.p_pending_search->hdr.event = BTA_DM_API_SEARCH_EVT;
- }
- LOG_INFO("%s Start pending search", __func__);
- bta_sys_sendmsg(bta_dm_search_cb.p_pending_search);
- bta_dm_search_cb.p_pending_search = NULL;
- } else {
- tBTA_DM_MSG* p_pending_discovery = (tBTA_DM_MSG*)fixed_queue_try_dequeue(
- bta_dm_search_cb.pending_discovery_queue);
- if (p_pending_discovery) {
- if (p_pending_discovery->hdr.event == BTA_DM_API_QUEUE_DISCOVER_EVT) {
- p_pending_discovery->hdr.event = BTA_DM_API_DISCOVER_EVT;
- }
- LOG_INFO("%s Start pending discovery", __func__);
- bta_sys_sendmsg(p_pending_discovery);
- }
- }
-}
-
-/*******************************************************************************
- *
- * Function bta_dm_is_search_request_queued
- *
- * Description Checks if there is a queued search request
- *
- * Returns bool
- *
- ******************************************************************************/
-bool bta_dm_is_search_request_queued() {
- return bta_dm_search_cb.p_pending_search != NULL;
+void bta_dm_search_clear_queue() {
+ osi_free_and_reset((void**)&bta_dm_search_cb.p_pending_search);
+ osi_free_and_reset((void**)&bta_dm_search_cb.p_pending_discovery);
}
/*******************************************************************************
*
- * Function bta_dm_search_clear_queue
+ * Function bta_dm_search_cancel_cmpl
*
- * Description Clears the queue if API search cancel is called
+ * Description Search cancel is complete
*
* Returns void
*
******************************************************************************/
-void bta_dm_search_clear_queue() {
- osi_free_and_reset((void**)&bta_dm_search_cb.p_pending_search);
- fixed_queue_flush(bta_dm_search_cb.pending_discovery_queue, osi_free);
+void bta_dm_search_cancel_cmpl() {
+ if (bta_dm_search_cb.p_pending_search) {
+ bta_sys_sendmsg(bta_dm_search_cb.p_pending_search);
+ bta_dm_search_cb.p_pending_search = NULL;
+ } else if (bta_dm_search_cb.p_pending_discovery) {
+ bta_sys_sendmsg(bta_dm_search_cb.p_pending_discovery);
+ bta_dm_search_cb.p_pending_discovery = NULL;
+ }
}
/*******************************************************************************
diff --git a/system/bta/dm/bta_dm_api.cc b/system/bta/dm/bta_dm_api.cc
index 5e1a8787f7..cf060eef77 100644
--- a/system/bta/dm/bta_dm_api.cc
+++ b/system/bta/dm/bta_dm_api.cc
@@ -80,16 +80,11 @@ void BTA_DmSetDeviceName(const char* p_name) {
* Returns void
*
******************************************************************************/
-void BTA_DmSearch(tBTA_DM_SEARCH_CBACK* p_cback, bool is_bonding_or_sdp) {
+void BTA_DmSearch(tBTA_DM_SEARCH_CBACK* p_cback) {
tBTA_DM_API_SEARCH* p_msg =
(tBTA_DM_API_SEARCH*)osi_calloc(sizeof(tBTA_DM_API_SEARCH));
- /* Queue request if a device is bonding or performing service discovery */
- if (is_bonding_or_sdp) {
- p_msg->hdr.event = BTA_DM_API_QUEUE_SEARCH_EVT;
- } else {
- p_msg->hdr.event = BTA_DM_API_SEARCH_EVT;
- }
+ p_msg->hdr.event = BTA_DM_API_SEARCH_EVT;
p_msg->p_cback = p_cback;
bta_sys_sendmsg(p_msg);
@@ -106,8 +101,6 @@ void BTA_DmSearch(tBTA_DM_SEARCH_CBACK* p_cback, bool is_bonding_or_sdp) {
*
******************************************************************************/
void BTA_DmSearchCancel(void) {
- bta_dm_search_clear_queue();
-
switch (bta_dm_search_get_state()) {
case BTA_DM_SEARCH_IDLE:
bta_dm_search_cancel_notify();
@@ -117,6 +110,7 @@ void BTA_DmSearchCancel(void) {
bta_dm_search_cancel();
break;
case BTA_DM_SEARCH_CANCELLING:
+ bta_dm_search_clear_queue();
bta_dm_search_cancel_notify();
break;
case BTA_DM_DISCOVER_ACTIVE:
@@ -138,15 +132,11 @@ void BTA_DmSearchCancel(void) {
*
******************************************************************************/
void BTA_DmDiscover(const RawAddress& bd_addr, tBTA_DM_SEARCH_CBACK* p_cback,
- tBT_TRANSPORT transport, bool is_bonding_or_sdp) {
+ tBT_TRANSPORT transport) {
tBTA_DM_API_DISCOVER* p_msg =
(tBTA_DM_API_DISCOVER*)osi_calloc(sizeof(tBTA_DM_API_DISCOVER));
- if (is_bonding_or_sdp) {
- p_msg->hdr.event = BTA_DM_API_QUEUE_DISCOVER_EVT;
- } else {
- p_msg->hdr.event = BTA_DM_API_DISCOVER_EVT;
- }
+ p_msg->hdr.event = BTA_DM_API_DISCOVER_EVT;
p_msg->bd_addr = bd_addr;
p_msg->transport = transport;
p_msg->p_cback = p_cback;
diff --git a/system/bta/dm/bta_dm_int.h b/system/bta/dm/bta_dm_int.h
index e51d9acb6c..a39c872879 100644
--- a/system/bta/dm/bta_dm_int.h
+++ b/system/bta/dm/bta_dm_int.h
@@ -70,19 +70,17 @@ enum {
BTA_DM_SDP_RESULT_EVT,
BTA_DM_SEARCH_CMPL_EVT,
BTA_DM_DISCOVERY_RESULT_EVT,
- BTA_DM_DISC_CLOSE_TOUT_EVT,
- BTA_DM_API_QUEUE_SEARCH_EVT,
- BTA_DM_API_QUEUE_DISCOVER_EVT
+ BTA_DM_DISC_CLOSE_TOUT_EVT
};
-/* data type for BTA_DM_API_SEARCH_EVT and BTA_DM_API_QUEUE_SEARCH_EVT */
+/* data type for BTA_DM_API_SEARCH_EVT */
typedef struct {
BT_HDR_RIGID hdr;
tBTA_SERVICE_MASK services;
tBTA_DM_SEARCH_CBACK* p_cback;
} tBTA_DM_API_SEARCH;
-/* data type for BTA_DM_API_DISCOVER_EVT and BTA_DM_API_QUEUE_DISCOVER_EVT */
+/* data type for BTA_DM_API_DISCOVER_EVT */
typedef struct {
BT_HDR_RIGID hdr;
RawAddress bd_addr;
@@ -358,7 +356,7 @@ typedef struct {
alarm_t* search_timer;
uint8_t service_index;
tBTA_DM_MSG* p_pending_search;
- fixed_queue_t* pending_discovery_queue;
+ tBTA_DM_MSG* p_pending_discovery;
bool wait_disc;
bool sdp_results;
bluetooth::Uuid uuid;
@@ -535,9 +533,8 @@ extern void bta_dm_search_result(tBTA_DM_MSG* p_data);
extern void bta_dm_discovery_cmpl(tBTA_DM_MSG* p_data);
extern void bta_dm_queue_search(tBTA_DM_MSG* p_data);
extern void bta_dm_queue_disc(tBTA_DM_MSG* p_data);
-extern void bta_dm_execute_queued_request();
-extern bool bta_dm_is_search_request_queued();
extern void bta_dm_search_clear_queue();
+extern void bta_dm_search_cancel_cmpl();
extern void bta_dm_search_cancel_notify();
extern void bta_dm_disc_rmt_name(tBTA_DM_MSG* p_data);
extern tBTA_DM_PEER_DEVICE* bta_dm_find_peer_device(
diff --git a/system/bta/dm/bta_dm_main.cc b/system/bta/dm/bta_dm_main.cc
index 523831b9da..5dd404b46f 100644
--- a/system/bta/dm/bta_dm_main.cc
+++ b/system/bta/dm/bta_dm_main.cc
@@ -82,12 +82,6 @@ bool bta_dm_search_sm_execute(BT_HDR_RIGID* p_msg) {
case BTA_DM_DISC_CLOSE_TOUT_EVT:
bta_dm_close_gatt_conn(message);
break;
- case BTA_DM_API_QUEUE_SEARCH_EVT:
- bta_dm_queue_search(message);
- break;
- case BTA_DM_API_QUEUE_DISCOVER_EVT:
- bta_dm_queue_disc(message);
- break;
}
break;
case BTA_DM_SEARCH_ACTIVE:
@@ -107,20 +101,14 @@ bool bta_dm_search_sm_execute(BT_HDR_RIGID* p_msg) {
case BTA_DM_DISC_CLOSE_TOUT_EVT:
bta_dm_close_gatt_conn(message);
break;
- case BTA_DM_API_DISCOVER_EVT:
- case BTA_DM_API_QUEUE_DISCOVER_EVT:
- bta_dm_queue_disc(message);
- break;
}
break;
case BTA_DM_SEARCH_CANCELLING:
switch (p_msg->event) {
case BTA_DM_API_SEARCH_EVT:
- case BTA_DM_API_QUEUE_SEARCH_EVT:
bta_dm_queue_search(message);
break;
case BTA_DM_API_DISCOVER_EVT:
- case BTA_DM_API_QUEUE_DISCOVER_EVT:
bta_dm_queue_disc(message);
break;
case BTA_DM_SDP_RESULT_EVT:
@@ -130,7 +118,7 @@ bool bta_dm_search_sm_execute(BT_HDR_RIGID* p_msg) {
bta_dm_search_set_state(BTA_DM_SEARCH_IDLE);
bta_dm_free_sdp_db();
bta_dm_search_cancel_notify();
- bta_dm_execute_queued_request();
+ bta_dm_search_cancel_cmpl();
break;
}
break;
@@ -148,14 +136,6 @@ bool bta_dm_search_sm_execute(BT_HDR_RIGID* p_msg) {
case BTA_DM_DISCOVERY_RESULT_EVT:
bta_dm_disc_result(message);
break;
- case BTA_DM_API_SEARCH_EVT:
- case BTA_DM_API_QUEUE_SEARCH_EVT:
- bta_dm_queue_search(message);
- break;
- case BTA_DM_API_DISCOVER_EVT:
- case BTA_DM_API_QUEUE_DISCOVER_EVT:
- bta_dm_queue_disc(message);
- break;
}
break;
}
diff --git a/system/bta/dm/bta_dm_pm.cc b/system/bta/dm/bta_dm_pm.cc
index 204017c06d..504799f962 100644
--- a/system/bta/dm/bta_dm_pm.cc
+++ b/system/bta/dm/bta_dm_pm.cc
@@ -449,7 +449,12 @@ static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, uint8_t id,
}
if (p_bta_dm_ssr_spec[index].max_lat || index == BTA_DM_PM_SSR_HH) {
- bta_dm_pm_ssr(peer_addr, index);
+ /* do not perform ssr for AVDTP start */
+ if (id != BTA_ID_AV || status != BTA_SYS_CONN_BUSY) {
+ bta_dm_pm_ssr(peer_addr, index);
+ } else {
+ LOG_DEBUG("Do not perform SSR when AVDTP start");
+ }
} else {
const controller_t* controller = controller_get_interface();
uint8_t* p = NULL;
diff --git a/system/bta/gatt/bta_gattc_act.cc b/system/bta/gatt/bta_gattc_act.cc
index d170778bd8..cd9da7a949 100644
--- a/system/bta/gatt/bta_gattc_act.cc
+++ b/system/bta/gatt/bta_gattc_act.cc
@@ -158,8 +158,9 @@ void bta_gattc_disable() {
/** start an application interface */
static void bta_gattc_start_if(uint8_t client_if) {
+ LOG_DEBUG("client_if=%d", +client_if);
if (!bta_gattc_cl_get_regcb(client_if)) {
- LOG(ERROR) << "Unable to start app.: Unknown client_if=" << +client_if;
+ LOG_ERROR("Unable to start app.: Unknown client_if=%d", +client_if);
return;
}
@@ -168,22 +169,26 @@ static void bta_gattc_start_if(uint8_t client_if) {
/** Register a GATT client application with BTA */
void bta_gattc_register(const Uuid& app_uuid, tBTA_GATTC_CBACK* p_cback,
- BtaAppRegisterCallback cb, bool eatt_suppport) {
+ BtaAppRegisterCallback cb, bool eatt_support) {
tGATT_STATUS status = GATT_NO_RESOURCES;
uint8_t client_if = 0;
- VLOG(1) << __func__ << ": state:" << +bta_gattc_cb.state;
+ LOG_DEBUG("state: %d, uuid=%s", +bta_gattc_cb.state,
+ app_uuid.ToString().c_str());
/* check if GATTC module is already enabled . Else enable */
if (bta_gattc_cb.state == BTA_GATTC_STATE_DISABLED) {
+ LOG_DEBUG("GATTC module not enabled, enabling it");
bta_gattc_enable();
}
/* todo need to check duplicate uuid */
for (uint8_t i = 0; i < BTA_GATTC_CL_MAX; i++) {
if (!bta_gattc_cb.cl_rcb[i].in_use) {
- if ((bta_gattc_cb.cl_rcb[i].client_if = GATT_Register(
- app_uuid, "GattClient", &bta_gattc_cl_cback, eatt_suppport)) ==
- 0) {
- LOG(ERROR) << "Register with GATT stack failed.";
+ bta_gattc_cb.cl_rcb[i].client_if = GATT_Register(
+ app_uuid, "GattClient", &bta_gattc_cl_cback, eatt_support);
+ if (bta_gattc_cb.cl_rcb[i].client_if == 0) {
+ LOG_ERROR(
+ "Register with GATT stack failed with index %d, trying next index",
+ +i);
status = GATT_ERROR;
} else {
bta_gattc_cb.cl_rcb[i].in_use = true;
@@ -193,6 +198,11 @@ void bta_gattc_register(const Uuid& app_uuid, tBTA_GATTC_CBACK* p_cback,
/* BTA use the same client interface as BTE GATT statck */
client_if = bta_gattc_cb.cl_rcb[i].client_if;
+ LOG_DEBUG(
+ "Registered GATT client interface %d with uuid=%s, starting it on "
+ "main thread",
+ +client_if, app_uuid.ToString().c_str());
+
do_in_main_thread(FROM_HERE,
base::Bind(&bta_gattc_start_if, client_if));
@@ -202,7 +212,12 @@ void bta_gattc_register(const Uuid& app_uuid, tBTA_GATTC_CBACK* p_cback,
}
}
- if (!cb.is_null()) cb.Run(client_if, status);
+ if (!cb.is_null()) {
+ cb.Run(client_if, status);
+ } else {
+ LOG_WARN("No GATT callback available, client_if=%d, status=%d", +client_if,
+ +status);
+ }
}
/** De-Register a GATT client application with BTA */
@@ -1142,12 +1157,14 @@ static void bta_gattc_conn_cback(tGATT_IF gattc_if, const RawAddress& bdaddr,
tGATT_DISCONN_REASON reason,
tBT_TRANSPORT transport) {
if (connected) {
- LOG_INFO("Connected att_id:%hhu transport:%s reason:%s", gattc_if,
+ LOG_INFO("Connected client_if:%hhu addr:%s, transport:%s reason:%s",
+ gattc_if, PRIVATE_ADDRESS(bdaddr),
bt_transport_text(transport).c_str(),
gatt_disconnection_reason_text(reason).c_str());
btif_debug_conn_state(bdaddr, BTIF_DEBUG_CONNECTED, GATT_CONN_OK);
} else {
- LOG_INFO("Disconnected att_id:%hhu transport:%s reason:%s", gattc_if,
+ LOG_INFO("Disconnected att_id:%hhu addr:%s, transport:%s reason:%s",
+ gattc_if, PRIVATE_ADDRESS(bdaddr),
bt_transport_text(transport).c_str(),
gatt_disconnection_reason_text(reason).c_str());
btif_debug_conn_state(bdaddr, BTIF_DEBUG_DISCONNECTED, GATT_CONN_OK);
diff --git a/system/bta/gatt/bta_gattc_api.cc b/system/bta/gatt/bta_gattc_api.cc
index 83735def1c..dafe028e37 100644
--- a/system/bta/gatt/bta_gattc_api.cc
+++ b/system/bta/gatt/bta_gattc_api.cc
@@ -22,6 +22,8 @@
*
******************************************************************************/
+#define LOG_TAG "bta_gattc_api"
+
#include <base/bind.h>
#include <base/logging.h>
@@ -34,6 +36,7 @@
#include "bta/gatt/bta_gattc_int.h"
#include "device/include/controller.h"
#include "osi/include/allocator.h"
+#include "osi/include/log.h"
#include "stack/include/bt_hdr.h"
#include "stack/include/btu.h" // do_in_main_thread
#include "types/bluetooth/uuid.h"
@@ -77,8 +80,11 @@ void BTA_GATTC_Disable(void) {
*/
void BTA_GATTC_AppRegister(tBTA_GATTC_CBACK* p_client_cb,
BtaAppRegisterCallback cb, bool eatt_support) {
- if (!bta_sys_is_register(BTA_ID_GATTC))
+ LOG_DEBUG("eatt_support=%d", eatt_support);
+ if (!bta_sys_is_register(BTA_ID_GATTC)) {
+ LOG_DEBUG("BTA_ID_GATTC not registered in BTA, registering it");
bta_sys_register(BTA_ID_GATTC, &bta_gattc_reg);
+ }
do_in_main_thread(
FROM_HERE, base::Bind(&bta_gattc_register, Uuid::GetRandom(), p_client_cb,
diff --git a/system/bta/gatt/bta_gattc_main.cc b/system/bta/gatt/bta_gattc_main.cc
index 6b4dfbba34..bba20b53d0 100644
--- a/system/bta/gatt/bta_gattc_main.cc
+++ b/system/bta/gatt/bta_gattc_main.cc
@@ -21,12 +21,14 @@
* This file contains the GATT client main functions and state machine.
*
******************************************************************************/
+#define LOG_TAG "bta_gattc_main"
#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include "bt_target.h" // Must be first to define build configuration"
#include "bta/gatt/bta_gattc_int.h"
+#include "osi/include/log.h"
#include "stack/include/bt_hdr.h"
using base::StringPrintf;
@@ -386,11 +388,11 @@ bool bta_gattc_hdl_event(BT_HDR_RIGID* p_msg) {
else
p_clcb = bta_gattc_find_clcb_by_conn_id(p_msg->layer_specific);
- if (p_clcb != NULL) {
+ if (p_clcb != nullptr) {
rt = bta_gattc_sm_execute(p_clcb, p_msg->event,
(const tBTA_GATTC_DATA*)p_msg);
} else {
- VLOG(1) << "Ignore unknown conn ID: " << +p_msg->layer_specific;
+ LOG_ERROR("Ignore unknown conn ID: %d", +p_msg->layer_specific);
}
break;
diff --git a/system/bta/hearing_aid/hearing_aid.cc b/system/bta/hearing_aid/hearing_aid.cc
index 61a83cdda0..774add2cf1 100644
--- a/system/bta/hearing_aid/hearing_aid.cc
+++ b/system/bta/hearing_aid/hearing_aid.cc
@@ -570,7 +570,7 @@ class HearingAidImpl : public HearingAid {
return;
}
- DVLOG(2) << __func__ << " " << address;
+ LOG(INFO) << __func__ << ": " << address;
if (hearingDevice->audio_control_point_handle &&
hearingDevice->audio_status_handle &&
@@ -579,11 +579,14 @@ class HearingAidImpl : public HearingAid {
// Use cached data, jump to read PSM
ReadPSM(hearingDevice);
} else {
+ LOG(INFO) << __func__ << ": " << address
+ << ": do BTA_GATTC_ServiceSearchRequest";
hearingDevice->first_connection = true;
BTA_GATTC_ServiceSearchRequest(hearingDevice->conn_id, &HEARING_AID_UUID);
}
}
+ // Just take care phy update successful case to avoid loop excuting.
void OnPhyUpdateEvent(uint16_t conn_id, uint8_t tx_phys, uint8_t rx_phys,
tGATT_STATUS status) {
HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id);
@@ -591,14 +594,19 @@ class HearingAidImpl : public HearingAid {
DVLOG(2) << "Skipping unknown device, conn_id=" << loghex(conn_id);
return;
}
- if (status == GATT_SUCCESS && tx_phys == PHY_LE_2M &&
- rx_phys == PHY_LE_2M) {
+ if (status != GATT_SUCCESS) {
+ LOG(WARNING) << hearingDevice->address
+ << " phy update fail with status: " << status;
+ return;
+ }
+ if (tx_phys == PHY_LE_2M && rx_phys == PHY_LE_2M) {
LOG(INFO) << hearingDevice->address << " phy update to 2M successful";
return;
}
- LOG(INFO) << hearingDevice->address
- << " phy update to 2M fail, try again. status: " << status
- << ", tx_phys: " << tx_phys << ", rx_phys: " << rx_phys;
+ LOG(INFO)
+ << hearingDevice->address
+ << " phy update successful but not target phy, try again. tx_phys: "
+ << tx_phys << ", rx_phys: " << rx_phys;
BTM_BleSetPhy(hearingDevice->address, PHY_LE_2M, PHY_LE_2M, 0);
}
@@ -624,7 +632,14 @@ class HearingAidImpl : public HearingAid {
VLOG(2) << "Skipping unknown device" << address;
return;
}
- if (hearingDevice->service_changed_rcvd) {
+ LOG(INFO) << __func__ << ": " << address;
+ if (hearingDevice->service_changed_rcvd ||
+ !(hearingDevice->audio_control_point_handle &&
+ hearingDevice->audio_status_handle &&
+ hearingDevice->audio_status_ccc_handle &&
+ hearingDevice->volume_handle && hearingDevice->read_psm_handle)) {
+ LOG(INFO) << __func__ << ": " << address
+ << ": do BTA_GATTC_ServiceSearchRequest";
BTA_GATTC_ServiceSearchRequest(hearingDevice->conn_id, &HEARING_AID_UUID);
}
}
@@ -891,7 +906,8 @@ class HearingAidImpl : public HearingAid {
uint16_t psm = *((uint16_t*)value);
VLOG(2) << "read psm:" << loghex(psm);
- if (hearingDevice->gap_handle == GAP_INVALID_HANDLE) {
+ if (hearingDevice->gap_handle == GAP_INVALID_HANDLE &&
+ BTM_IsEncrypted(hearingDevice->address, BT_TRANSPORT_LE)) {
ConnectSocket(hearingDevice, psm);
}
}
diff --git a/system/bta/include/bta_api.h b/system/bta/include/bta_api.h
index b98c8e4b5a..447823a6a8 100644
--- a/system/bta/include/bta_api.h
+++ b/system/bta/include/bta_api.h
@@ -710,15 +710,13 @@ extern bool BTA_DmSetVisibility(bt_scan_mode_t mode);
* first performs an inquiry; for each device found from the
* inquiry it gets the remote name of the device. If
* parameter services is nonzero, service discovery will be
- * performed on each device for the services specified. If the
- * parameter is_bonding_or_sdp is true, the request will be
- * queued until bonding or sdp completes
+ * performed on each device for the services specified.
*
*
* Returns void
*
******************************************************************************/
-extern void BTA_DmSearch(tBTA_DM_SEARCH_CBACK* p_cback, bool is_bonding_or_sdp);
+extern void BTA_DmSearch(tBTA_DM_SEARCH_CBACK* p_cback);
/*******************************************************************************
*
@@ -746,7 +744,7 @@ extern void BTA_DmSearchCancel(void);
******************************************************************************/
extern void BTA_DmDiscover(const RawAddress& bd_addr,
tBTA_DM_SEARCH_CBACK* p_cback,
- tBT_TRANSPORT transport, bool is_bonding_or_sdp);
+ tBT_TRANSPORT transport);
/*******************************************************************************
*
diff --git a/system/bta/le_audio/le_audio_set_configuration_provider_json.cc b/system/bta/le_audio/le_audio_set_configuration_provider_json.cc
index 9bb2c1c587..719db5fdea 100644
--- a/system/bta/le_audio/le_audio_set_configuration_provider_json.cc
+++ b/system/bta/le_audio/le_audio_set_configuration_provider_json.cc
@@ -40,15 +40,16 @@ using ::le_audio::CodecManager;
#ifdef OS_ANDROID
static const std::vector<
std::pair<const char* /*schema*/, const char* /*content*/>>
- kLeAudioSetConfigs = {{"/apex/com.android.bluetooth/etc/bluetooth/le_audio/"
- "audio_set_configurations.bfbs",
- "/apex/com.android.bluetooth/etc/bluetooth/le_audio/"
- "audio_set_configurations.json"}};
+ kLeAudioSetConfigs = {
+ {"/apex/com.android.btservices/etc/bluetooth/le_audio/"
+ "audio_set_configurations.bfbs",
+ "/apex/com.android.btservices/etc/bluetooth/le_audio/"
+ "audio_set_configurations.json"}};
static const std::vector<
std::pair<const char* /*schema*/, const char* /*content*/>>
- kLeAudioSetScenarios = {{"/apex/com.android.bluetooth/etc/bluetooth/"
+ kLeAudioSetScenarios = {{"/apex/com.android.btservices/etc/bluetooth/"
"le_audio/audio_set_scenarios.bfbs",
- "/apex/com.android.bluetooth/etc/bluetooth/"
+ "/apex/com.android.btservices/etc/bluetooth/"
"le_audio/audio_set_scenarios.json"}};
#else
static const std::vector<
diff --git a/system/btif/Android.bp b/system/btif/Android.bp
index 914d1e574b..15320b1e43 100644
--- a/system/btif/Android.bp
+++ b/system/btif/Android.bp
@@ -106,6 +106,7 @@ cc_defaults {
"co/bta_gatts_co.cc",
// HAL layer
"src/bluetooth.cc",
+ "src/bluetooth_data_migration.cc",
// BTIF implementation
"src/btif_a2dp.cc",
"src/btif_a2dp_control.cc",
@@ -490,6 +491,7 @@ cc_test {
"lib-bt-packets",
"lib-bt-packets-avrcp",
"lib-bt-packets-base",
+ "libc++fs",
"libflatbuffers-cpp",
"libgmock",
"libosi",
diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc
index 771c7b713d..a251067b1c 100644
--- a/system/btif/src/bluetooth.cc
+++ b/system/btif/src/bluetooth.cc
@@ -172,15 +172,25 @@ static bool is_profile(const char* p1, const char* p2) {
*
****************************************************************************/
+const std::vector<std::string> get_allowed_bt_package_name(void);
+void handle_migration(const std::string& dst,
+ const std::vector<std::string>& allowed_bt_package_name);
+
static int init(bt_callbacks_t* callbacks, bool start_restricted,
bool is_common_criteria_mode, int config_compare_result,
- const char** init_flags, bool is_atv) {
+ const char** init_flags, bool is_atv,
+ const char* user_data_directory) {
LOG_INFO(
"%s: start restricted = %d ; common criteria mode = %d, config compare "
"result = %d",
__func__, start_restricted, is_common_criteria_mode,
config_compare_result);
+ if (user_data_directory != nullptr) {
+ handle_migration(std::string(user_data_directory),
+ get_allowed_bt_package_name());
+ }
+
bluetooth::common::InitFlags::Load(init_flags);
if (interface_ready()) return BT_STATUS_DONE;
diff --git a/system/btif/src/bluetooth_data_migration.cc b/system/btif/src/bluetooth_data_migration.cc
new file mode 100644
index 0000000000..45d0bdad73
--- /dev/null
+++ b/system/btif/src/bluetooth_data_migration.cc
@@ -0,0 +1,126 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+#include <base/logging.h>
+
+#include <filesystem>
+#include <string>
+#include <vector>
+
+namespace fs = std::filesystem;
+
+// The user data should be stored in the subdirectory of |USER_DE_PATH|
+static const std::string USER_DE_PATH = "/data/user_de/0";
+
+// The migration process start only if |MIGRATION_FILE_CHECKER| is found in a
+// previous location
+static const std::string MIGRATION_FILE_CHECKER = "databases/bluetooth_db";
+
+// List of possible package_name for bluetooth to get the data from / to
+static const std::vector<std::string> ALLOWED_BT_PACKAGE_NAME = {
+ "com.android.bluetooth", // legacy name
+ "com.android.bluetooth.services", // Beta users
+ "com.google.android.bluetooth.services", // Droid fooder users
+};
+
+// Accessor to get the default allowed package list to be used in migration
+// OEM can call their own method with their own allowed list
+const std::vector<std::string> get_allowed_bt_package_name(void) {
+ return ALLOWED_BT_PACKAGE_NAME;
+}
+
+// Check if |dst| is in |base_dir| subdirectory and check the package name in
+// |dst| is a allowed package name in the |pkg_list|
+//
+// Return an empty string if an issue occurred
+// or the package name contained in |dst| on success
+static std::string parse_destination_package_name(
+ const std::string& dst, const std::string& base_dir,
+ const std::vector<std::string>& pkg_list) {
+ const std::size_t found = dst.rfind("/");
+ // |dst| must contain a '/'
+ if (found == std::string::npos) {
+ LOG(ERROR) << "Destination format not valid " << dst;
+ return "";
+ }
+ // |dst| directory is supposed to be in |base_dir|
+ if (found != base_dir.length()) {
+ LOG(ERROR) << "Destination location not allowed: " << dst;
+ return "";
+ }
+ // This check prevent a '/' to be at the end of |dst|
+ if (found >= dst.length() - 1) {
+ LOG(ERROR) << "Destination format not valid " << dst;
+ return "";
+ }
+
+ const std::string dst_package_name = dst.substr(found + 1); // +1 for '/'
+
+ if (std::find(pkg_list.begin(), pkg_list.end(), dst_package_name) ==
+ pkg_list.end()) {
+ LOG(ERROR) << "Destination package_name not valid: " << dst_package_name
+ << " Created from " << dst;
+ return "";
+ }
+ LOG(INFO) << "Current Bluetooth package name is: " << dst_package_name;
+ return dst_package_name;
+}
+
+// Check for data to migrate from the |allowed_bt_package_name|
+// A migration will be performed if:
+// * |dst| is different than |allowed_bt_package_name|
+// * the following file is found:
+// |USER_DE_PATH|/|allowed_bt_package_name|/|MIGRATION_FILE_CHECKER|
+//
+// After migration occurred, the |MIGRATION_FILE_CHECKER| is deleted to ensure
+// the migration is only performed once
+void handle_migration(const std::string& dst,
+ const std::vector<std::string>& allowed_bt_package_name) {
+ const std::string dst_package_name = parse_destination_package_name(
+ dst, USER_DE_PATH, allowed_bt_package_name);
+ if (dst_package_name.empty()) return;
+
+ for (const auto& pkg_name : allowed_bt_package_name) {
+ std::error_code error;
+
+ if (dst_package_name == pkg_name) {
+ LOG(INFO) << "Same location skipped: " << dst_package_name;
+ continue;
+ }
+ const fs::path dst_path = dst;
+ const fs::path pkg_path = USER_DE_PATH + "/" + pkg_name;
+ const fs::path local_migration_file_checker =
+ pkg_path.string() + "/" + MIGRATION_FILE_CHECKER;
+ if (!fs::exists(local_migration_file_checker, error)) {
+ LOG(INFO) << "Not a valid candidate for migration: " << pkg_path;
+ continue;
+ }
+
+ const fs::copy_options copy_flag =
+ fs::copy_options::overwrite_existing | fs::copy_options::recursive;
+ fs::copy(pkg_path, dst_path, copy_flag, error);
+
+ if (error) {
+ LOG(ERROR) << "Migration failed: " << error.message();
+ } else {
+ fs::remove(local_migration_file_checker);
+ LOG(INFO) << "Migration completed from " << pkg_path << " to " << dst;
+ }
+ break; // Copy from one and only one directory
+ }
+}
diff --git a/system/btif/src/btif_core.cc b/system/btif/src/btif_core.cc
index 935fa3b459..c289758531 100644
--- a/system/btif/src/btif_core.cc
+++ b/system/btif/src/btif_core.cc
@@ -77,7 +77,7 @@ static void bt_jni_msg_ready(void* context);
#define BTE_DID_CONF_FILE "bt_did.conf"
#else // !defined(OS_GENERIC)
#define BTE_DID_CONF_FILE \
- "/apex/com.android.bluetooth/etc/bluetooth/bt_did.conf"
+ "/apex/com.android.btservices/etc/bluetooth/bt_did.conf"
#endif // defined(OS_GENERIC)
#endif // BTE_DID_CONF_FILE
diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc
index 5e8a5140c8..e13fad3236 100644
--- a/system/btif/src/btif_dm.cc
+++ b/system/btif/src/btif_dm.cc
@@ -164,6 +164,9 @@ typedef struct {
bool is_le_nc; /* LE Numeric comparison */
btif_dm_ble_cb_t ble;
uint8_t fail_reason;
+ Uuid::UUID128Bit eir_uuids[32];
+ uint8_t num_eir_uuids;
+ std::set<Uuid::UUID128Bit> uuids;
} btif_dm_pairing_cb_t;
// TODO(jpawlowski): unify ?
@@ -1296,19 +1299,17 @@ static void btif_dm_search_devices_evt(tBTA_DM_SEARCH_EVT event,
&(p_search_data->inq_res.include_rsi));
num_properties++;
- /* EIR queried services */
- std::vector<Uuid> uuid128_list;
+ /* Cache EIR queried services */
if (num_uuids > 0) {
uint16_t* p_uuid16 = (uint16_t*)uuid_list;
+ pairing_cb.num_eir_uuids = 0;
+ LOG_INFO("EIR UUIDS:");
for (int i = 0; i < num_uuids; ++i) {
Uuid uuid = Uuid::From16Bit(p_uuid16[i]);
- uuid128_list.push_back(uuid);
+ LOG_INFO(" %s", uuid.ToString().c_str());
+ pairing_cb.eir_uuids[i] = uuid.To128BitBE();
+ pairing_cb.num_eir_uuids++;
}
-
- BTIF_STORAGE_FILL_PROPERTY(
- &properties[num_properties], BT_PROPERTY_UUIDS,
- num_uuids * Uuid::kNumBytes128, uuid128_list.data());
- num_properties++;
}
status =
@@ -1370,6 +1371,7 @@ static void btif_dm_search_services_evt(tBTA_DM_SEARCH_EVT event,
bt_property_t prop;
uint32_t i = 0;
bt_status_t ret;
+ std::vector<uint8_t> property_value;
RawAddress& bd_addr = p_data->disc_res.bd_addr;
@@ -1391,12 +1393,18 @@ static void btif_dm_search_services_evt(tBTA_DM_SEARCH_EVT event,
prop.len = 0;
if ((p_data->disc_res.result == BTA_SUCCESS) &&
(p_data->disc_res.num_uuids > 0)) {
- prop.val = p_data->disc_res.p_uuid_list;
- prop.len = p_data->disc_res.num_uuids * Uuid::kNumBytes128;
+ LOG_INFO("New UUIDs:");
for (i = 0; i < p_data->disc_res.num_uuids; i++) {
- std::string temp = ((p_data->disc_res.p_uuid_list + i))->ToString();
- LOG_INFO("index:%d uuid:%s", i, temp.c_str());
+ auto uuid = p_data->disc_res.p_uuid_list + i;
+ LOG_INFO("index:%d uuid:%s", i, uuid->ToString().c_str());
+ auto valAsBe = uuid->To128BitBE();
+ pairing_cb.uuids.insert(valAsBe);
}
+ for (auto uuid : pairing_cb.uuids) {
+ property_value.insert(property_value.end(), uuid.begin(), uuid.end());
+ }
+ prop.val = (void*)property_value.data();
+ prop.len = Uuid::kNumBytes128 * pairing_cb.uuids.size();
}
/* onUuidChanged requires getBondedDevices to be populated.
@@ -1408,28 +1416,34 @@ static void btif_dm_search_services_evt(tBTA_DM_SEARCH_EVT event,
LOG_INFO("SDP search done for %s", bd_addr.ToString().c_str());
pairing_cb.sdp_attempts = 0;
- // Both SDP and bonding are done, clear pairing control block in case
- // it is not already cleared
- pairing_cb = {};
-
- // Send one empty UUID to Java to unblock pairing intent when SDP failed
- // or no UUID is discovered
+ // Send UUIDs discovered through EIR to Java to unblock pairing intent
+ // when SDP failed or no UUID is discovered
if (p_data->disc_res.result != BTA_SUCCESS ||
p_data->disc_res.num_uuids == 0) {
- LOG_INFO("SDP failed, send empty UUID to unblock bonding %s",
- bd_addr.ToString().c_str());
+ LOG_INFO("SDP failed, send %d EIR UUIDs to unblock bonding %s",
+ pairing_cb.num_eir_uuids, bd_addr.ToString().c_str());
bt_property_t prop_uuids;
Uuid uuid = {};
-
prop_uuids.type = BT_PROPERTY_UUIDS;
- prop_uuids.val = &uuid;
- prop_uuids.len = Uuid::kNumBytes128;
+ if (pairing_cb.num_eir_uuids > 0) {
+ prop_uuids.val = pairing_cb.eir_uuids;
+ prop_uuids.len = pairing_cb.num_eir_uuids * Uuid::kNumBytes128;
+ } else {
+ prop_uuids.val = &uuid;
+ prop_uuids.len = Uuid::kNumBytes128;
+ }
- /* Send the event to the BTIF */
+ /* Send the event to the BTIF
+ * prop_uuids will be deep copied by this call
+ */
invoke_remote_device_properties_cb(BT_STATUS_SUCCESS, bd_addr, 1,
&prop_uuids);
+ pairing_cb = {};
break;
}
+ // Both SDP and bonding are done, clear pairing control block in case
+ // it is not already cleared
+ pairing_cb = {};
}
if (p_data->disc_res.num_uuids != 0) {
@@ -1457,15 +1471,18 @@ static void btif_dm_search_services_evt(tBTA_DM_SEARCH_EVT event,
std::vector<uint8_t> property_value;
int num_uuids = 0;
+ LOG_INFO("New BLE UUIDs:");
for (Uuid uuid : *p_data->disc_ble_res.services) {
- LOG_VERBOSE("service %s", uuid.ToString().c_str());
+ LOG_INFO("index:%d uuid:%s", num_uuids, uuid.ToString().c_str());
if (btif_is_interesting_le_service(uuid)) {
num_uuids++;
auto valAsBe = uuid.To128BitBE();
- property_value.insert(property_value.end(), valAsBe.begin(),
- valAsBe.end());
+ pairing_cb.uuids.insert(valAsBe);
}
}
+ for (auto uuid : pairing_cb.uuids) {
+ property_value.insert(property_value.end(), uuid.begin(), uuid.end());
+ }
if (num_uuids == 0) {
LOG_INFO("No well known BLE services discovered");
@@ -1475,7 +1492,7 @@ static void btif_dm_search_services_evt(tBTA_DM_SEARCH_EVT event,
RawAddress& bd_addr = p_data->disc_ble_res.bd_addr;
prop[0].type = BT_PROPERTY_UUIDS;
prop[0].val = (void*)property_value.data();
- prop[0].len = Uuid::kNumBytes128 * num_uuids;
+ prop[0].len = Uuid::kNumBytes128 * pairing_cb.uuids.size();
/* Also write this to the NVRAM */
bt_status_t ret =
@@ -1570,7 +1587,7 @@ void BTIF_dm_enable() {
}
}
/* clear control blocks */
- memset(&pairing_cb, 0, sizeof(btif_dm_pairing_cb_t));
+ pairing_cb = {};
pairing_cb.bond_type = tBTM_SEC_DEV_REC::BOND_TYPE_PERSISTENT;
if (enable_address_consolidate) {
LOG_INFO("enable address consolidate");
@@ -1900,16 +1917,10 @@ static void bta_energy_info_cb(tBTM_BLE_TX_TIME_MS tx_time,
void btif_dm_start_discovery(void) {
BTIF_TRACE_EVENT("%s", __func__);
- if (bta_dm_is_search_request_queued()) {
- LOG_INFO("%s skipping start discovery because a request is queued",
- __func__);
- return;
- }
-
/* Will be enabled to true once inquiry busy level has been received */
btif_dm_inquiry_in_progress = false;
/* find nearby devices */
- BTA_DmSearch(btif_dm_search_devices_evt, is_bonding_or_sdp());
+ BTA_DmSearch(btif_dm_search_devices_evt);
}
/*******************************************************************************
@@ -2389,10 +2400,7 @@ void btif_dm_get_remote_services(RawAddress remote_addr, const int transport) {
BTIF_TRACE_EVENT("%s: transport=%d, remote_addr=%s", __func__, transport,
remote_addr.ToString().c_str());
- BTA_DmDiscover(remote_addr, btif_dm_search_services_evt, transport,
- remote_addr != pairing_cb.bd_addr &&
- remote_addr != pairing_cb.static_bdaddr &&
- is_bonding_or_sdp());
+ BTA_DmDiscover(remote_addr, btif_dm_search_services_evt, transport);
}
void btif_dm_enable_service(tBTA_SERVICE_ID service_id, bool enable) {
diff --git a/system/btif/src/btif_gatt_client.cc b/system/btif/src/btif_gatt_client.cc
index 915be7bb4a..08e4431ff9 100644
--- a/system/btif/src/btif_gatt_client.cc
+++ b/system/btif/src/btif_gatt_client.cc
@@ -123,7 +123,7 @@ extern const btgatt_callbacks_t* bt_gatt_callbacks;
LOG_WARN("%s: BTGATT not initialized", __func__); \
return BT_STATUS_NOT_READY; \
} else { \
- LOG_VERBOSE("%s", __func__); \
+ LOG_DEBUG("%s", __func__); \
} \
} while (0)
@@ -207,7 +207,8 @@ static void btif_gattc_upstreams_evt(uint16_t event, char* p_param) {
}
case BTA_GATTC_OPEN_EVT: {
- DVLOG(1) << "BTA_GATTC_OPEN_EVT " << p_data->open.remote_bda;
+ LOG_DEBUG("BTA_GATTC_OPEN_EVT %s",
+ p_data->open.remote_bda.ToString().c_str());
HAL_CBACK(bt_gatt_callbacks, client->open_cb, p_data->open.conn_id,
p_data->open.status, p_data->open.client_if,
p_data->open.remote_bda);
diff --git a/system/common/metrics.cc b/system/common/metrics.cc
index be1d1b3bac..0664186cac 100644
--- a/system/common/metrics.cc
+++ b/system/common/metrics.cc
@@ -859,6 +859,7 @@ void LogSocketConnectionState(
}
void LogManufacturerInfo(const RawAddress& address,
+ android::bluetooth::AddressTypeEnum address_type,
android::bluetooth::DeviceInfoSrcEnum source_type,
const std::string& source_name,
const std::string& manufacturer,
@@ -875,16 +876,20 @@ void LogManufacturerInfo(const RawAddress& address,
BytesField obfuscated_id_field(
address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
address.IsEmpty() ? 0 : obfuscated_id.size());
- int ret = stats_write(BLUETOOTH_DEVICE_INFO_REPORTED, obfuscated_id_field,
- source_type, source_name.c_str(), manufacturer.c_str(),
- model.c_str(), hardware_version.c_str(),
- software_version.c_str(), metric_id);
+ int ret = stats_write(
+ BLUETOOTH_DEVICE_INFO_REPORTED, obfuscated_id_field, source_type,
+ source_name.c_str(), manufacturer.c_str(), model.c_str(),
+ hardware_version.c_str(), software_version.c_str(), metric_id,
+ address_type, address.address[5], address.address[4], address.address[3]);
if (ret < 0) {
LOG(WARNING) << __func__ << ": failed for " << address << ", source_type "
<< source_type << ", source_name " << source_name
<< ", manufacturer " << manufacturer << ", model " << model
<< ", hardware_version " << hardware_version
- << ", software_version " << software_version << ", error "
+ << ", software_version " << software_version
+ << " MAC address type " << address_type
+ << " MAC address prefix " << address.address[5] << " "
+ << address.address[4] << " " << address.address[3] << ", error "
<< ret;
}
}
diff --git a/system/common/metrics.h b/system/common/metrics.h
index 53cad5c3d0..9d33e1b81f 100644
--- a/system/common/metrics.h
+++ b/system/common/metrics.h
@@ -487,6 +487,7 @@ void LogSocketConnectionState(
* @param software_version software version of this device
*/
void LogManufacturerInfo(const RawAddress& address,
+ android::bluetooth::AddressTypeEnum address_type,
android::bluetooth::DeviceInfoSrcEnum source_type,
const std::string& source_name,
const std::string& manufacturer,
diff --git a/system/device/include/interop_database.h b/system/device/include/interop_database.h
index d70a161643..03c584f69a 100644
--- a/system/device/include/interop_database.h
+++ b/system/device/include/interop_database.h
@@ -129,6 +129,9 @@ static const interop_addr_entry_t interop_addr_database[] = {
// OBU II Bluetooth dongle
{{{0x00, 0x04, 0x3e, 0, 0, 0}}, 3, INTEROP_DISABLE_ROLE_SWITCH},
+ // Visteon carkit
+ {{{0x00, 0x0a, 0x30, 0, 0, 0}}, 3, INTEROP_DISABLE_ROLE_SWITCH},
+
// Roman R9020
{{{0x00, 0x23, 0x01, 0, 0, 0}}, 3, INTEROP_DISABLE_ROLE_SWITCH},
@@ -182,9 +185,6 @@ static const interop_addr_entry_t interop_addr_database[] = {
// KDDI Carkit
{{{0x44, 0xea, 0xd8, 0, 0, 0}}, 3, INTEROP_DISABLE_SNIFF},
- // Phonak
- {{{0x70, 0x66, 0x1b, 0, 0, 0}}, 3, INTEROP_DISABLE_SNIFF},
-
// Toyota Camry 2018 Carkit HFP AT+BIND missing
{{{0x94, 0xb2, 0xcc, 0x30, 0, 0}}, 4, INTEROP_SLC_SKIP_BIND_COMMAND},
};
diff --git a/system/gd/facade/facade_main.cc b/system/gd/facade/facade_main.cc
index bc49279cd9..a48df00e5a 100644
--- a/system/gd/facade/facade_main.cc
+++ b/system/gd/facade/facade_main.cc
@@ -51,13 +51,15 @@ extern "C" const char* __asan_default_options() {
namespace {
::bluetooth::facade::GrpcRootServer grpc_root_server;
+std::promise<void> interrupt_promise;
+std::future<void> interrupt_future;
bool interrupted = false;
struct sigaction old_act = {};
void interrupt_handler(int signal_number) {
if (!interrupted) {
interrupted = true;
LOG_INFO("Stopping gRPC root server due to signal: %s[%d]", strsignal(signal_number), signal_number);
- grpc_root_server.StopServer();
+ interrupt_promise.set_value();
} else {
LOG_WARN("Already interrupted by signal: %s[%d]", strsignal(signal_number), signal_number);
}
@@ -94,6 +96,15 @@ bool crash_callback(const void* crash_context, size_t crash_context_size, void*
return true;
}
+// Need to stop server on a thread that is not part of a signal handler due to an issue with gRPC
+// See: https://github.com/grpc/grpc/issues/24884
+void thread_check_shutdown() {
+ LOG_INFO("shutdown thread waiting for interruption");
+ interrupt_future.wait();
+ LOG_INFO("interrupted, stopping server");
+ grpc_root_server.StopServer();
+}
+
} // namespace
// The entry point for the binary with libbluetooth + facades
@@ -148,9 +159,16 @@ int main(int argc, const char** argv) {
LOG_ERROR("sigaction error: %s", strerror(errno));
}
+ LOG_INFO("Starting Server");
grpc_root_server.StartServer("0.0.0.0", root_server_port, grpc_port);
+ LOG_INFO("Server started");
auto wait_thread = std::thread([] { grpc_root_server.RunGrpcLoop(); });
+ interrupt_future = interrupt_promise.get_future();
+ auto shutdown_thread = std::thread{thread_check_shutdown};
wait_thread.join();
+ LOG_INFO("Server terminated");
+ shutdown_thread.join();
+ LOG_INFO("Shutdown thread terminated");
return 0;
}
diff --git a/system/gd/facade/grpc_root_server.cc b/system/gd/facade/grpc_root_server.cc
index 1a76b0dfe0..162405cf1d 100644
--- a/system/gd/facade/grpc_root_server.cc
+++ b/system/gd/facade/grpc_root_server.cc
@@ -29,26 +29,15 @@
#include "hci/facade/le_advertising_manager_facade.h"
#include "hci/facade/le_initiator_address_facade.h"
#include "hci/facade/le_scanning_manager_facade.h"
-#include "hci/hci_layer.h"
-#include "hci/le_advertising_manager.h"
-#include "hci/le_scanning_manager.h"
#include "iso/facade.h"
#include "l2cap/classic/facade.h"
#include "l2cap/le/facade.h"
-#include "neighbor/connectability.h"
-#include "neighbor/discoverability.h"
#include "neighbor/facade/facade.h"
-#include "neighbor/inquiry.h"
-#include "neighbor/name.h"
-#include "neighbor/page.h"
#include "os/log.h"
#include "os/thread.h"
#include "security/facade.h"
-#include "security/security_module.h"
-#include "shim/dumpsys.h"
#include "shim/facade/facade.h"
#include "stack_manager.h"
-#include "storage/storage_module.h"
namespace bluetooth {
namespace facade {
@@ -57,10 +46,9 @@ using ::blueberry::facade::BluetoothModule;
using ::bluetooth::grpc::GrpcModule;
using ::bluetooth::os::Thread;
-namespace {
class RootFacadeService : public ::blueberry::facade::RootFacade::Service {
public:
- RootFacadeService(int grpc_port) : grpc_port_(grpc_port) {}
+ explicit RootFacadeService(int grpc_port) : grpc_port_(grpc_port) {}
::grpc::Status StartStack(
::grpc::ServerContext* context,
@@ -123,13 +111,13 @@ class RootFacadeService : public ::blueberry::facade::RootFacade::Service {
return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "invalid module under test");
}
- stack_thread_ = new Thread("stack_thread", Thread::Priority::NORMAL);
- stack_manager_.StartUp(&modules, stack_thread_);
+ stack_thread_ = std::make_unique<Thread>("stack_thread", Thread::Priority::NORMAL);
+ stack_manager_.StartUp(&modules, stack_thread_.get());
GrpcModule* grpc_module = stack_manager_.GetInstance<GrpcModule>();
grpc_module->StartServer("0.0.0.0", grpc_port_);
- grpc_loop_thread_ = new std::thread([grpc_module] { grpc_module->RunGrpcLoop(); });
+ grpc_loop_thread_ = std::make_unique<std::thread>([grpc_module] { grpc_module->RunGrpcLoop(); });
is_running_ = true;
return ::grpc::Status::OK;
@@ -145,50 +133,56 @@ class RootFacadeService : public ::blueberry::facade::RootFacade::Service {
stack_manager_.GetInstance<GrpcModule>()->StopServer();
grpc_loop_thread_->join();
- delete grpc_loop_thread_;
+ grpc_loop_thread_.reset();
stack_manager_.ShutDown();
- delete stack_thread_;
+ stack_thread_.reset();
is_running_ = false;
return ::grpc::Status::OK;
}
private:
- Thread* stack_thread_ = nullptr;
+ std::unique_ptr<Thread> stack_thread_ = nullptr;
bool is_running_ = false;
- std::thread* grpc_loop_thread_ = nullptr;
+ std::unique_ptr<std::thread> grpc_loop_thread_ = nullptr;
StackManager stack_manager_;
int grpc_port_ = 8898;
};
-RootFacadeService* root_facade_service;
-} // namespace
+struct GrpcRootServer::impl {
+ bool started_ = false;
+ std::unique_ptr<RootFacadeService> root_facade_service_ = nullptr;
+ std::unique_ptr<::grpc::Server> server_ = nullptr;
+};
+
+GrpcRootServer::GrpcRootServer() : pimpl_(new impl()) {}
+
+GrpcRootServer::~GrpcRootServer() = default;
void GrpcRootServer::StartServer(const std::string& address, int grpc_root_server_port, int grpc_port) {
- ASSERT(!started_);
- started_ = true;
+ ASSERT(!pimpl_->started_);
+ pimpl_->started_ = true;
std::string listening_port = address + ":" + std::to_string(grpc_root_server_port);
::grpc::ServerBuilder builder;
- root_facade_service = new RootFacadeService(grpc_port);
- builder.RegisterService(root_facade_service);
+
+ pimpl_->root_facade_service_ = std::make_unique<RootFacadeService>(grpc_port);
+ builder.RegisterService(pimpl_->root_facade_service_.get());
builder.AddListeningPort(listening_port, ::grpc::InsecureServerCredentials());
- server_ = builder.BuildAndStart();
+ pimpl_->server_ = builder.BuildAndStart();
- ASSERT(server_ != nullptr);
+ ASSERT(pimpl_->server_ != nullptr);
}
void GrpcRootServer::StopServer() {
- ASSERT(started_);
- server_->Shutdown();
- started_ = false;
- server_.reset();
- delete root_facade_service;
+ ASSERT(pimpl_->started_);
+ pimpl_->server_->Shutdown();
+ pimpl_->started_ = false;
}
void GrpcRootServer::RunGrpcLoop() {
- ASSERT(started_);
- server_->Wait();
+ ASSERT(pimpl_->started_);
+ pimpl_->server_->Wait();
}
} // namespace facade
diff --git a/system/gd/facade/grpc_root_server.h b/system/gd/facade/grpc_root_server.h
index 12faf26e93..2b310e2054 100644
--- a/system/gd/facade/grpc_root_server.h
+++ b/system/gd/facade/grpc_root_server.h
@@ -26,6 +26,9 @@ namespace facade {
class GrpcRootServer {
public:
+ GrpcRootServer();
+ ~GrpcRootServer();
+
void StartServer(const std::string& address, int grpc_root_server_port, int grpc_port);
void StopServer();
@@ -33,8 +36,8 @@ class GrpcRootServer {
void RunGrpcLoop();
private:
- bool started_ = false;
- std::unique_ptr<::grpc::Server> server_ = nullptr;
+ struct impl;
+ std::unique_ptr<impl> pimpl_;
};
} // namespace facade
diff --git a/system/gd/grpc/grpc_event_queue.h b/system/gd/grpc/grpc_event_queue.h
index ffacb14700..dc1c588708 100644
--- a/system/gd/grpc/grpc_event_queue.h
+++ b/system/gd/grpc/grpc_event_queue.h
@@ -51,8 +51,8 @@ class GrpcEventQueue {
using namespace std::chrono_literals;
LOG_INFO("%s: Entering Loop", log_name_.c_str());
while (!context->IsCancelled()) {
- // Wait for 500 ms so that cancellation can be caught in amortized 250 ms latency
- if (pending_events_.wait_to_take(500ms)) {
+ // Wait for 100 ms so that cancellation can be caught in amortized 50 ms latency
+ if (pending_events_.wait_to_take(100ms)) {
LOG_INFO("%s: Got event from queue", log_name_.c_str());
writer->Write(pending_events_.take());
}
diff --git a/system/gd/hal/snoop_logger.cc b/system/gd/hal/snoop_logger.cc
index a416d2c2b9..72e20e9228 100644
--- a/system/gd/hal/snoop_logger.cc
+++ b/system/gd/hal/snoop_logger.cc
@@ -435,7 +435,7 @@ size_t SnoopLogger::GetMaxPacketsPerBuffer() {
// and 512 KB memory for userdebug/eng builds
auto is_debuggable = os::GetSystemProperty(kIsDebuggableProperty);
size_t btsnooz_max_memory_usage_bytes =
- ((is_debuggable.has_value() && common::StringTrim(is_debuggable.value()) == "1") ? 512 : 256) * 1024;
+ ((is_debuggable.has_value() && common::StringTrim(is_debuggable.value()) == "1") ? 1024 : 256) * 1024;
// Calculate max number of packets based on max memory usage and max packet size
return btsnooz_max_memory_usage_bytes / kDefaultBtSnoozMaxBytesPerPacket;
}
diff --git a/system/gd/hci/acl_manager.cc b/system/gd/hci/acl_manager.cc
index 464d40d1df..400068129e 100644
--- a/system/gd/hci/acl_manager.cc
+++ b/system/gd/hci/acl_manager.cc
@@ -160,6 +160,10 @@ void AclManager::CreateLeConnection(AddressWithType address_with_type, bool is_d
CallOn(pimpl_->le_impl_, &le_impl::create_le_connection, address_with_type, true, is_direct);
}
+void AclManager::IsOnBackgroundList(AddressWithType address_with_type, std::promise<bool> promise) {
+ CallOn(pimpl_->le_impl_, &le_impl::is_on_background_connection_list, address_with_type, std::move(promise));
+}
+
void AclManager::SetLeSuggestedDefaultDataParameters(uint16_t octets, uint16_t time) {
CallOn(pimpl_->le_impl_, &le_impl::set_le_suggested_default_data_parameters, octets, time);
}
@@ -210,6 +214,17 @@ void AclManager::CancelLeConnect(AddressWithType address_with_type) {
CallOn(pimpl_->le_impl_, &le_impl::cancel_connect, address_with_type);
}
+void AclManager::RemoveFromBackgroundList(AddressWithType address_with_type) {
+ CallOn(pimpl_->le_impl_, &le_impl::remove_device_from_background_connection_list, address_with_type);
+}
+
+void AclManager::CancelLeConnectAndRemoveFromBackgroundList(AddressWithType address_with_type) {
+ CallOn(
+ pimpl_->le_impl_,
+ &le_impl::cancel_connection_and_remove_device_from_background_connection_list,
+ address_with_type);
+}
+
void AclManager::AddDeviceToFilterAcceptList(AddressWithType address_with_type) {
CallOn(pimpl_->le_impl_, &le_impl::add_device_to_connect_list, address_with_type);
}
diff --git a/system/gd/hci/acl_manager.h b/system/gd/hci/acl_manager.h
index 1a2d437a4a..4f9aaf7db5 100644
--- a/system/gd/hci/acl_manager.h
+++ b/system/gd/hci/acl_manager.h
@@ -103,8 +103,12 @@ public:
// Generates OnConnectFail with error code "terminated by local host 0x16" if cancelled, or OnConnectSuccess if not
// successfully cancelled and already connected
virtual void CancelConnect(Address address);
+ virtual void RemoveFromBackgroundList(AddressWithType address_with_type);
+ virtual void IsOnBackgroundList(AddressWithType address_with_type, std::promise<bool> promise);
virtual void CancelLeConnect(AddressWithType address_with_type);
+ virtual void CancelLeConnectAndRemoveFromBackgroundList(AddressWithType address_with_type);
+
virtual void AddDeviceToFilterAcceptList(AddressWithType address_with_type);
virtual void RemoveDeviceFromFilterAcceptList(AddressWithType address_with_type);
virtual void ClearFilterAcceptList();
diff --git a/system/gd/hci/acl_manager/le_acl_connection.h b/system/gd/hci/acl_manager/le_acl_connection.h
index 964c88601b..a805d19d68 100644
--- a/system/gd/hci/acl_manager/le_acl_connection.h
+++ b/system/gd/hci/acl_manager/le_acl_connection.h
@@ -78,6 +78,12 @@ class LeAclConnection : public AclConnection {
// Time Range: 100 ms to 32 s
uint16_t supervision_timeout_;
+ // True if connection address was in the filter accept list, false otherwise
+ bool in_filter_accept_list_;
+ bool IsInFilterAcceptList() const {
+ return in_filter_accept_list_;
+ }
+
Address local_resolvable_private_address_ = Address::kEmpty;
Address peer_resolvable_private_address_ = Address::kEmpty;
diff --git a/system/gd/hci/acl_manager/le_impl.h b/system/gd/hci/acl_manager/le_impl.h
index ea2eb1354e..e9d1f0505d 100644
--- a/system/gd/hci/acl_manager/le_impl.h
+++ b/system/gd/hci/acl_manager/le_impl.h
@@ -265,6 +265,7 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
// connection canceled by LeAddressManager.OnPause(), will auto reconnect by LeAddressManager.OnResume()
void on_le_connection_canceled_on_pause() {
ASSERT_LOG(pause_connection, "Connection must be paused to ack the le address manager");
+ arm_on_resume_ = true;
connectability_state_ = ConnectabilityState::DISARMED;
le_address_manager_->AckPause(this);
}
@@ -307,6 +308,7 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
arm_on_resume_ = false;
ready_to_unregister = true;
+ const bool in_filter_accept_list = is_device_in_connect_list(remote_address);
remove_device_from_connect_list(remote_address);
if (!connect_list.empty()) {
@@ -344,6 +346,7 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
connection->interval_ = conn_interval;
connection->latency_ = conn_latency;
connection->supervision_timeout_ = supervision_timeout;
+ connection->in_filter_accept_list_ = in_filter_accept_list;
connections.add(
handle, remote_address, queue_down_end, handler_, connection->GetEventCallbacks([this](uint16_t handle) {
this->connections.invalidate(handle);
@@ -392,6 +395,7 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
arm_on_resume_ = false;
ready_to_unregister = true;
+ const bool in_filter_accept_list = is_device_in_connect_list(remote_address);
remove_device_from_connect_list(remote_address);
if (!connect_list.empty()) {
@@ -439,6 +443,7 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
connection->supervision_timeout_ = supervision_timeout;
connection->local_resolvable_private_address_ = connection_complete.GetLocalResolvablePrivateAddress();
connection->peer_resolvable_private_address_ = connection_complete.GetPeerResolvablePrivateAddress();
+ connection->in_filter_accept_list_ = in_filter_accept_list;
connections.add(
handle, remote_address, queue_down_end, handler_, connection->GetEventCallbacks([this](uint16_t handle) {
this->connections.invalidate(handle);
@@ -464,12 +469,9 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
if (background_connections_.count(remote_address) == 1) {
LOG_INFO("re-add device to connect list");
+ arm_on_resume_ = true;
add_device_to_connect_list(remote_address);
}
- if (!connect_list.empty() && connectability_state_ == ConnectabilityState::DISARMED) {
- LOG_INFO("connect_list is not empty, send a new connection request");
- arm_connectability();
- }
}
void on_le_connection_update_complete(LeMetaEventView view) {
@@ -585,6 +587,7 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
return;
}
connect_list.erase(address_with_type);
+ connecting_le_.erase(address_with_type);
direct_connections_.erase(address_with_type);
register_with_address_manager();
le_address_manager_->RemoveDeviceFromFilterAcceptList(
@@ -643,6 +646,10 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
connectability_state_machine_text(connectability_state_).c_str());
return;
}
+ if (connect_list.empty()) {
+ LOG_ERROR("Attempting to re-arm le connection state machine when filter accept list is empty");
+ return;
+ }
AddressWithType empty(Address::kEmpty, AddressType::RANDOM_DEVICE_ADDRESS);
connectability_state_ = ConnectabilityState::ARMING;
connecting_le_ = connect_list;
@@ -924,6 +931,15 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
background_connections_.erase(address_with_type);
}
+ void is_on_background_connection_list(AddressWithType address_with_type, std::promise<bool> promise) {
+ promise.set_value(background_connections_.find(address_with_type) != background_connections_.end());
+ }
+
+ void cancel_connection_and_remove_device_from_background_connection_list(AddressWithType address_with_type) {
+ remove_device_from_background_connection_list(address_with_type);
+ cancel_connect(address_with_type);
+ }
+
void OnPause() override { // bluetooth::hci::LeAddressManagerCallback
pause_connection = true;
if (connectability_state_ == ConnectabilityState::DISARMED) {
diff --git a/system/gd/hci/facade/acl_manager_facade.cc b/system/gd/hci/facade/acl_manager_facade.cc
index 7e249a1723..0911577cd8 100644
--- a/system/gd/hci/facade/acl_manager_facade.cc
+++ b/system/gd/hci/facade/acl_manager_facade.cc
@@ -64,6 +64,7 @@ class AclManagerFacadeService : public AclManagerFacade::Service, public Connect
::grpc::ServerContext* context,
const ConnectionMsg* request,
::grpc::ServerWriter<ConnectionEvent>* writer) override {
+ LOG_INFO("peer=%s", request->address().c_str());
Address peer;
ASSERT(Address::FromString(request->address(), peer));
acl_manager_->CreateConnection(peer);
@@ -77,6 +78,7 @@ class AclManagerFacadeService : public AclManagerFacade::Service, public Connect
::grpc::Status Disconnect(
::grpc::ServerContext* context, const HandleMsg* request, ::google::protobuf::Empty* response) override {
+ LOG_INFO("handle=%d", request->handle());
std::unique_lock<std::mutex> lock(acl_connections_mutex_);
auto connection = acl_connections_.find(request->handle());
if (connection == acl_connections_.end()) {
@@ -90,6 +92,7 @@ class AclManagerFacadeService : public AclManagerFacade::Service, public Connect
::grpc::Status AuthenticationRequested(
::grpc::ServerContext* context, const HandleMsg* request, ::google::protobuf::Empty* response) override {
+ LOG_INFO("handle=%d", request->handle());
std::unique_lock<std::mutex> lock(acl_connections_mutex_);
auto connection = acl_connections_.find(request->handle());
if (connection == acl_connections_.end()) {
@@ -118,12 +121,14 @@ class AclManagerFacadeService : public AclManagerFacade::Service, public Connect
::grpc::ServerContext* context,
const ConnectionCommandMsg* request,
::google::protobuf::Empty* response) override {
+ LOG_INFO("size=%zu", request->packet().size());
auto command_view =
ConnectionManagementCommandView::Create(AclCommandView::Create(CommandView::Create(PacketView<kLittleEndian>(
std::make_shared<std::vector<uint8_t>>(request->packet().begin(), request->packet().end())))));
if (!command_view.IsValid()) {
return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid command packet");
}
+ LOG_INFO("opcode=%s", OpCodeText(command_view.GetOpCode()).c_str());
switch (command_view.GetOpCode()) {
case OpCode::AUTHENTICATION_REQUESTED: {
GET_CONNECTION(AuthenticationRequestedView::Create(command_view));
@@ -266,6 +271,7 @@ class AclManagerFacadeService : public AclManagerFacade::Service, public Connect
::grpc::ServerContext* context,
const google::protobuf::Empty* request,
::grpc::ServerWriter<ConnectionEvent>* writer) override {
+ LOG_INFO("wait for one incoming connection");
if (per_connection_events_.size() > current_connection_request_) {
return ::grpc::Status(::grpc::StatusCode::RESOURCE_EXHAUSTED, "Only one outstanding connection is supported");
}
@@ -276,6 +282,7 @@ class AclManagerFacadeService : public AclManagerFacade::Service, public Connect
::grpc::Status SendAclData(
::grpc::ServerContext* context, const AclData* request, ::google::protobuf::Empty* response) override {
+ LOG_INFO("handle=%d, size=%zu", request->handle(), request->payload().size());
std::promise<void> promise;
auto future = promise.get_future();
{
@@ -312,6 +319,7 @@ class AclManagerFacadeService : public AclManagerFacade::Service, public Connect
::grpc::Status FetchAclData(
::grpc::ServerContext* context, const HandleMsg* request, ::grpc::ServerWriter<AclData>* writer) override {
+ LOG_INFO("handle=%d", request->handle());
auto connection = acl_connections_.find(request->handle());
if (connection == acl_connections_.end()) {
return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid handle");
@@ -331,19 +339,23 @@ class AclManagerFacadeService : public AclManagerFacade::Service, public Connect
}
void on_incoming_acl(std::shared_ptr<ClassicAclConnection> connection, uint16_t handle) {
+ LOG_INFO("handle=%d, addr=%s", connection->GetHandle(), connection->GetAddress().ToString().c_str());
auto packet = connection->GetAclQueueEnd()->TryDequeue();
auto connection_tracker = acl_connections_.find(handle);
ASSERT_LOG(connection_tracker != acl_connections_.end(), "handle %d", handle);
AclData acl_data;
acl_data.set_handle(handle);
acl_data.set_payload(std::string(packet->begin(), packet->end()));
+ LOG_INFO("length=%zu", acl_data.payload().size());
connection_tracker->second.pending_acl_data_.OnIncomingEvent(acl_data);
}
void OnConnectSuccess(std::unique_ptr<ClassicAclConnection> connection) override {
+ LOG_INFO("handle=%d, addr=%s", connection->GetHandle(), connection->GetAddress().ToString().c_str());
std::unique_lock<std::mutex> lock(acl_connections_mutex_);
std::shared_ptr<ClassicAclConnection> shared_connection = std::move(connection);
uint16_t handle = to_handle(current_connection_request_);
+ acl_connections_.erase(handle);
acl_connections_.emplace(
std::piecewise_construct,
std::forward_as_tuple(handle),
@@ -363,6 +375,7 @@ class AclManagerFacadeService : public AclManagerFacade::Service, public Connect
}
void OnConnectFail(Address address, ErrorCode reason) override {
+ LOG_INFO("addr=%s, reason=%s", address.ToString().c_str(), ErrorCodeText(reason).c_str());
std::unique_ptr<BasePacketBuilder> builder =
ConnectionCompleteBuilder::Create(reason, 0, address, LinkType::ACL, Enable::DISABLED);
ConnectionEvent fail;
@@ -516,7 +529,7 @@ class AclManagerFacadeService : public AclManagerFacade::Service, public Connect
}
void OnDisconnection(ErrorCode reason) override {
- LOG_INFO("OnDisconnection reason: %s", ErrorCodeText(reason).c_str());
+ LOG_INFO("reason: %s", ErrorCodeText(reason).c_str());
std::unique_ptr<BasePacketBuilder> builder =
DisconnectionCompleteBuilder::Create(ErrorCode::SUCCESS, handle_, reason);
ConnectionEvent disconnection;
diff --git a/system/gd/hci/facade/le_acl_manager_facade.cc b/system/gd/hci/facade/le_acl_manager_facade.cc
index 115c69cce2..b5a2d19071 100644
--- a/system/gd/hci/facade/le_acl_manager_facade.cc
+++ b/system/gd/hci/facade/le_acl_manager_facade.cc
@@ -65,6 +65,11 @@ class LeAclManagerFacadeService : public LeAclManagerFacade::Service, public LeC
::grpc::ServerContext* context,
const CreateConnectionMsg* request,
::grpc::ServerWriter<LeConnectionEvent>* writer) override {
+ LOG_INFO(
+ "peer=%s, type=%d, id_direct=%d",
+ request->peer_address().address().address().c_str(),
+ request->peer_address().type(),
+ request->is_direct());
Address peer_address;
ASSERT(Address::FromString(request->peer_address().address().address(), peer_address));
AddressWithType peer(peer_address, static_cast<AddressType>(request->peer_address().type()));
@@ -92,6 +97,7 @@ class LeAclManagerFacadeService : public LeAclManagerFacade::Service, public LeC
::grpc::ServerContext* context,
const ::blueberry::facade::BluetoothAddressWithType* request,
google::protobuf::Empty* response) override {
+ LOG_INFO("peer=%s, type=%d", request->address().address().c_str(), request->type());
Address peer_address;
ASSERT(Address::FromString(request->address().address(), peer_address));
AddressWithType peer(peer_address, static_cast<AddressType>(request->type()));
@@ -109,6 +115,7 @@ class LeAclManagerFacadeService : public LeAclManagerFacade::Service, public LeC
::grpc::Status Disconnect(::grpc::ServerContext* context, const LeHandleMsg* request,
::google::protobuf::Empty* response) override {
+ LOG_INFO("handle=%d", request->handle());
std::unique_lock<std::mutex> lock(acl_connections_mutex_);
auto connection = acl_connections_.find(request->handle());
if (connection == acl_connections_.end()) {
@@ -137,12 +144,14 @@ class LeAclManagerFacadeService : public LeAclManagerFacade::Service, public LeC
::grpc::ServerContext* context,
const LeConnectionCommandMsg* request,
::google::protobuf::Empty* response) override {
+ LOG_INFO("size=%zu", request->packet().size());
auto command_view =
ConnectionManagementCommandView::Create(AclCommandView::Create(CommandView::Create(PacketView<kLittleEndian>(
std::make_shared<std::vector<uint8_t>>(request->packet().begin(), request->packet().end())))));
if (!command_view.IsValid()) {
return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid command packet");
}
+ LOG_INFO("opcode=%s", OpCodeText(command_view.GetOpCode()).c_str());
switch (command_view.GetOpCode()) {
case OpCode::DISCONNECT: {
auto view = DisconnectView::Create(command_view);
@@ -160,6 +169,7 @@ class LeAclManagerFacadeService : public LeAclManagerFacade::Service, public LeC
::grpc::ServerContext* context,
const google::protobuf::Empty* request,
::grpc::ServerWriter<LeConnectionEvent>* writer) override {
+ LOG_INFO("wait for one incoming connection");
if (incoming_connection_events_ != nullptr) {
return ::grpc::Status(
::grpc::StatusCode::RESOURCE_EXHAUSTED, "Only one outstanding incoming connection is supported");
@@ -171,6 +181,7 @@ class LeAclManagerFacadeService : public LeAclManagerFacade::Service, public LeC
::grpc::Status AddDeviceToResolvingList(
::grpc::ServerContext* context, const IrkMsg* request, ::google::protobuf::Empty* response) override {
+ LOG_INFO("peer=%s, type=%d", request->peer().address().address().c_str(), request->peer().type());
Address peer_address;
ASSERT(Address::FromString(request->peer().address().address(), peer_address));
AddressWithType peer(peer_address, static_cast<AddressType>(request->peer().type()));
@@ -201,6 +212,7 @@ class LeAclManagerFacadeService : public LeAclManagerFacade::Service, public LeC
::grpc::Status SendAclData(
::grpc::ServerContext* context, const LeAclData* request, ::google::protobuf::Empty* response) override {
+ LOG_INFO("handle=%d, size=%zu", request->handle(), request->payload().size());
std::promise<void> promise;
auto future = promise.get_future();
{
@@ -236,6 +248,7 @@ class LeAclManagerFacadeService : public LeAclManagerFacade::Service, public LeC
::grpc::Status FetchAclData(
::grpc::ServerContext* context, const LeHandleMsg* request, ::grpc::ServerWriter<LeAclData>* writer) override {
+ LOG_INFO("handle=%d", request->handle());
auto connection = acl_connections_.find(request->handle());
if (connection == acl_connections_.end()) {
return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid handle");
@@ -251,6 +264,7 @@ class LeAclManagerFacadeService : public LeAclManagerFacade::Service, public LeC
}
void on_incoming_acl(std::shared_ptr<LeAclConnection> connection, uint16_t handle) {
+ LOG_INFO("handle=%d, addr=%s", connection->GetHandle(), connection->GetRemoteAddress().ToString().c_str());
auto packet = connection->GetAclQueueEnd()->TryDequeue();
auto connection_tracker = acl_connections_.find(handle);
ASSERT_LOG(connection_tracker != acl_connections_.end(), "handle %d", handle);
@@ -261,15 +275,18 @@ class LeAclManagerFacadeService : public LeAclManagerFacade::Service, public LeC
}
void OnLeConnectSuccess(AddressWithType peer, std::unique_ptr<LeAclConnection> connection) override {
- LOG_INFO("%s", peer.ToString().c_str());
-
+ LOG_INFO("handle=%d, addr=%s", connection->GetHandle(), peer.ToString().c_str());
std::unique_lock<std::mutex> lock(acl_connections_mutex_);
std::shared_ptr<LeAclConnection> shared_connection = std::move(connection);
uint16_t handle = shared_connection->GetHandle();
auto role = shared_connection->GetRole();
if (role == Role::PERIPHERAL) {
ASSERT(incoming_connection_events_ != nullptr);
- per_connection_events_.emplace(peer, incoming_connection_events_);
+ if (per_connection_events_.find(peer) == per_connection_events_.end()) {
+ per_connection_events_.emplace(peer, incoming_connection_events_);
+ } else {
+ per_connection_events_[peer] = incoming_connection_events_;
+ }
incoming_connection_events_.reset();
} else if (direct_connection_address_ == peer) {
direct_connection_address_ = AddressWithType();
@@ -278,6 +295,7 @@ class LeAclManagerFacadeService : public LeAclManagerFacade::Service, public LeC
} else {
ASSERT_LOG(per_connection_events_.count(peer) > 0, "No connection request for %s", peer.ToString().c_str());
}
+ acl_connections_.erase(handle);
acl_connections_.emplace(
std::piecewise_construct,
std::forward_as_tuple(handle),
@@ -297,6 +315,7 @@ class LeAclManagerFacadeService : public LeAclManagerFacade::Service, public LeC
}
void OnLeConnectFail(AddressWithType address, ErrorCode reason) override {
+ LOG_INFO("addr=%s, reason=%s", address.ToString().c_str(), ErrorCodeText(reason).c_str());
std::unique_ptr<BasePacketBuilder> builder = LeConnectionCompleteBuilder::Create(
reason, 0, Role::CENTRAL, address.GetAddressType(), address.GetAddress(), 0, 0, 0, ClockAccuracy::PPM_20);
LeConnectionEvent fail;
@@ -336,6 +355,7 @@ class LeAclManagerFacadeService : public LeAclManagerFacade::Service, public LeC
void OnPhyUpdate(hci::ErrorCode hci_status, uint8_t tx_phy, uint8_t rx_phy) override {}
void OnLocalAddressUpdate(AddressWithType address_with_type) override {}
void OnDisconnection(ErrorCode reason) override {
+ LOG_INFO("reason: %s", ErrorCodeText(reason).c_str());
std::unique_ptr<BasePacketBuilder> builder =
DisconnectionCompleteBuilder::Create(ErrorCode::SUCCESS, handle_, reason);
LeConnectionEvent disconnection;
@@ -358,6 +378,31 @@ class LeAclManagerFacadeService : public LeAclManagerFacade::Service, public LeC
std::to_string(handle_)};
};
+ ::grpc::Status IsOnBackgroundList(
+ ::grpc::ServerContext* context,
+ const ::blueberry::facade::hci::BackgroundRequestMsg* request,
+ ::blueberry::facade::hci::BackgroundResultMsg* msg) {
+ Address peer_address;
+ ASSERT(Address::FromString(request->peer_address().address().address(), peer_address));
+ AddressWithType peer(peer_address, static_cast<AddressType>(request->peer_address().type()));
+ std::promise<bool> promise;
+ auto future = promise.get_future();
+ acl_manager_->IsOnBackgroundList(peer, std::move(promise));
+ msg->set_is_on_background_list(future.get());
+ return ::grpc::Status::OK;
+ }
+
+ ::grpc::Status RemoveFromBackgroundList(
+ ::grpc::ServerContext* context,
+ const ::blueberry::facade::hci::BackgroundRequestMsg* request,
+ ::google::protobuf::Empty* response) {
+ Address peer_address;
+ ASSERT(Address::FromString(request->peer_address().address().address(), peer_address));
+ AddressWithType peer(peer_address, static_cast<AddressType>(request->peer_address().type()));
+ acl_manager_->RemoveFromBackgroundList(peer);
+ return ::grpc::Status::OK;
+ }
+
private:
AclManager* acl_manager_;
::bluetooth::os::Handler* facade_handler_;
diff --git a/system/gd/hci/hci_metrics_logging.cc b/system/gd/hci/hci_metrics_logging.cc
index 80655d5162..9c864ac8ad 100644
--- a/system/gd/hci/hci_metrics_logging.cc
+++ b/system/gd/hci/hci_metrics_logging.cc
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h>
#include <frameworks/proto_logging/stats/enums/bluetooth/hci/enums.pb.h>
#include "common/strings.h"
@@ -512,7 +511,12 @@ void log_link_layer_connection_other_hci_event(EventView packet, storage::Storag
status = connection_complete_view.GetStatus();
// besides log link layer connection events, also log remote device manufacturer info
- log_remote_device_information(address, connection_handle, status, storage_module);
+ log_remote_device_information(
+ address,
+ android::bluetooth::ADDRESS_TYPE_PUBLIC,
+ connection_handle,
+ status,
+ storage_module);
break;
}
case EventCode::CONNECTION_REQUEST: {
@@ -1048,7 +1052,11 @@ void log_classic_pairing_command_complete(EventView event_view, std::unique_ptr<
}
void log_remote_device_information(
- const Address& address, uint32_t connection_handle, ErrorCode status, storage::StorageModule* storage_module) {
+ const Address& address,
+ android::bluetooth::AddressTypeEnum address_type,
+ uint32_t connection_handle,
+ ErrorCode status,
+ storage::StorageModule* storage_module) {
if (address.IsEmpty()) {
return;
}
@@ -1059,6 +1067,7 @@ void log_remote_device_information(
sdp_di_vendor_id_source << "N:SDP::DIP::" << common::ToHexString(device.GetSdpDiVendorIdSource().value_or(0)).c_str();
os::LogMetricManufacturerInfo(
address,
+ address_type,
android::bluetooth::DeviceInfoSrcEnum::DEVICE_INFO_INTERNAL,
sdp_di_vendor_id_source.str(),
common::ToHexString(device.GetSdpDiManufacturer().value_or(0)).c_str(),
diff --git a/system/gd/hci/hci_metrics_logging.h b/system/gd/hci/hci_metrics_logging.h
index de463db944..37a230aa7e 100644
--- a/system/gd/hci/hci_metrics_logging.h
+++ b/system/gd/hci/hci_metrics_logging.h
@@ -15,6 +15,7 @@
*/
#pragma once
+#include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h>
#include "hci/hci_packets.h"
#include "storage/storage_module.h"
@@ -34,6 +35,10 @@ void log_classic_pairing_command_complete(EventView event, std::unique_ptr<Comma
void log_classic_pairing_other_hci_event(EventView packet);
void log_remote_device_information(
- const Address& address, uint32_t connection_handle, ErrorCode status, storage::StorageModule* storage_module);
+ const Address& address,
+ android::bluetooth::AddressTypeEnum address_type,
+ uint32_t connection_handle,
+ ErrorCode status,
+ storage::StorageModule* storage_module);
} // namespace hci
} // namespace bluetooth \ No newline at end of file
diff --git a/system/gd/hci/le_advertising_manager.cc b/system/gd/hci/le_advertising_manager.cc
index 95979bf683..0832c25790 100644
--- a/system/gd/hci/le_advertising_manager.cc
+++ b/system/gd/hci/le_advertising_manager.cc
@@ -223,6 +223,7 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
id++;
}
if (id == num_instances_) {
+ LOG_WARN("Number of max instances %d reached", (uint16_t)num_instances_);
return kInvalidId;
}
advertising_sets_[id].in_use = true;
@@ -1259,6 +1260,11 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
ErrorCodeText(status_view.GetStatus()).c_str());
}
}
+
+ void start_advertising_fail(int reg_id, AdvertisingCallback::AdvertisingStatus status) {
+ ASSERT(status != AdvertisingCallback::AdvertisingStatus::SUCCESS);
+ advertising_callbacks_->OnAdvertisingSetStarted(reg_id, kInvalidId, 0, status);
+ }
};
LeAdvertisingManager::LeAdvertisingManager() {
@@ -1298,16 +1304,26 @@ AdvertiserId LeAdvertisingManager::create_advertiser(
if (config.own_address_type == hci::OwnAddressType::RESOLVABLE_OR_PUBLIC_ADDRESS ||
config.own_address_type == hci::OwnAddressType::RESOLVABLE_OR_RANDOM_ADDRESS) {
LOG_WARN("Peer address can not be empty");
+ CallOn(
+ pimpl_.get(), &impl::start_advertising_fail, reg_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR);
return kInvalidId;
}
if (config.advertising_type == hci::AdvertisingType::ADV_DIRECT_IND ||
config.advertising_type == hci::AdvertisingType::ADV_DIRECT_IND_LOW) {
LOG_WARN("Peer address can not be empty for directed advertising");
+ CallOn(
+ pimpl_.get(), &impl::start_advertising_fail, reg_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR);
return kInvalidId;
}
}
AdvertiserId id = pimpl_->allocate_advertiser();
if (id == kInvalidId) {
+ LOG_WARN("Number of max instances reached");
+ CallOn(
+ pimpl_.get(),
+ &impl::start_advertising_fail,
+ reg_id,
+ AdvertisingCallback::AdvertisingStatus::TOO_MANY_ADVERTISERS);
return id;
}
GetHandler()->Post(common::BindOnce(
@@ -1338,29 +1354,43 @@ AdvertiserId LeAdvertisingManager::ExtendedCreateAdvertiser(
if (config.directed) {
if (config.peer_address == Address::kEmpty) {
LOG_INFO("Peer address can not be empty for directed advertising");
+ CallOn(
+ pimpl_.get(), &impl::start_advertising_fail, reg_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR);
return kInvalidId;
}
}
if (config.channel_map == 0) {
LOG_INFO("At least one channel must be set in the map");
+ CallOn(pimpl_.get(), &impl::start_advertising_fail, reg_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR);
return kInvalidId;
}
if (!config.legacy_pdus) {
if (config.connectable && config.scannable) {
LOG_INFO("Extended advertising PDUs can not be connectable and scannable");
+ CallOn(
+ pimpl_.get(), &impl::start_advertising_fail, reg_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR);
return kInvalidId;
}
if (config.high_duty_directed_connectable) {
LOG_INFO("Extended advertising PDUs can not be high duty cycle");
+ CallOn(
+ pimpl_.get(), &impl::start_advertising_fail, reg_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR);
return kInvalidId;
}
}
if (config.interval_min > config.interval_max) {
LOG_INFO("Advertising interval: min (%hu) > max (%hu)", config.interval_min, config.interval_max);
+ CallOn(pimpl_.get(), &impl::start_advertising_fail, reg_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR);
return kInvalidId;
}
AdvertiserId id = pimpl_->allocate_advertiser();
if (id == kInvalidId) {
+ LOG_WARN("Number of max instances reached");
+ CallOn(
+ pimpl_.get(),
+ &impl::start_advertising_fail,
+ reg_id,
+ AdvertisingCallback::AdvertisingStatus::TOO_MANY_ADVERTISERS);
return id;
}
CallOn(
diff --git a/system/gd/os/android/metrics.cc b/system/gd/os/android/metrics.cc
index 8286ad170f..3be618823e 100644
--- a/system/gd/os/android/metrics.cc
+++ b/system/gd/os/android/metrics.cc
@@ -355,6 +355,7 @@ void LogMetricSocketConnectionState(
void LogMetricManufacturerInfo(
const Address& address,
+ android::bluetooth::AddressTypeEnum address_type,
android::bluetooth::DeviceInfoSrcEnum source_type,
const std::string& source_name,
const std::string& manufacturer,
@@ -374,11 +375,16 @@ void LogMetricManufacturerInfo(
model.c_str(),
hardware_version.c_str(),
software_version.c_str(),
- metric_id);
+ metric_id,
+ address_type,
+ address.address[5],
+ address.address[4],
+ address.address[3]);
if (ret < 0) {
LOG_WARN(
- "Failed for %s, source_type %d, source_name %s, manufacturer %s, model %s, hardware_version %s, "
- "software_version %s, error %d",
+ "Failed for %s, source_type %d, source_name %s, manufacturer %s, model %s, "
+ "hardware_version %s, "
+ "software_version %s, MAC address type %d MAC address prefix %d %d %d, error %d",
address.ToString().c_str(),
source_type,
source_name.c_str(),
@@ -386,6 +392,10 @@ void LogMetricManufacturerInfo(
model.c_str(),
hardware_version.c_str(),
software_version.c_str(),
+ address_type,
+ address.address[5],
+ address.address[4],
+ address.address[3],
ret);
}
}
diff --git a/system/gd/os/host/metrics.cc b/system/gd/os/host/metrics.cc
index f83e59c053..b17571452a 100644
--- a/system/gd/os/host/metrics.cc
+++ b/system/gd/os/host/metrics.cc
@@ -80,6 +80,7 @@ void LogMetricLinkLayerConnectionEvent(
void LogMetricManufacturerInfo(
const Address& address,
+ android::bluetooth::AddressTypeEnum address_type,
android::bluetooth::DeviceInfoSrcEnum source_type,
const std::string& source_name,
const std::string& manufacturer,
diff --git a/system/gd/os/linux/metrics.cc b/system/gd/os/linux/metrics.cc
index 926f545d36..37bd67356a 100644
--- a/system/gd/os/linux/metrics.cc
+++ b/system/gd/os/linux/metrics.cc
@@ -80,6 +80,7 @@ void LogMetricLinkLayerConnectionEvent(
void LogMetricManufacturerInfo(
const Address& address,
+ android::bluetooth::AddressTypeEnum address_type,
android::bluetooth::DeviceInfoSrcEnum source_type,
const std::string& source_name,
const std::string& manufacturer,
diff --git a/system/gd/os/metrics.h b/system/gd/os/metrics.h
index 73b9484042..3b1ae51850 100644
--- a/system/gd/os/metrics.h
+++ b/system/gd/os/metrics.h
@@ -245,6 +245,7 @@ void LogMetricSocketConnectionState(
*/
void LogMetricManufacturerInfo(
const hci::Address& address,
+ android::bluetooth::AddressTypeEnum address_type,
android::bluetooth::DeviceInfoSrcEnum source_type,
const std::string& source_name,
const std::string& manufacturer,
diff --git a/system/gd/rust/topshim/facade/Android.bp b/system/gd/rust/topshim/facade/Android.bp
index 27f26937fa..5d2b06b2ca 100644
--- a/system/gd/rust/topshim/facade/Android.bp
+++ b/system/gd/rust/topshim/facade/Android.bp
@@ -64,6 +64,7 @@ rust_binary_host {
"libbt_topshim_cxx",
"libbt-audio-hal-interface",
"libaudio-a2dp-hw-utils",
+ "libc++fs",
],
shared_libs: [
"libcrypto",
diff --git a/system/gd/rust/topshim/src/btif.rs b/system/gd/rust/topshim/src/btif.rs
index 452d7a6e2d..922024d3e8 100644
--- a/system/gd/rust/topshim/src/btif.rs
+++ b/system/gd/rust/topshim/src/btif.rs
@@ -895,7 +895,8 @@ impl BluetoothInterface {
is_common_criteria_mode,
config_compare_result,
flags,
- is_atv
+ is_atv,
+ std::ptr::null()
);
self.is_init = init == 0;
diff --git a/system/include/hardware/bluetooth.h b/system/include/hardware/bluetooth.h
index da9b51f787..96e425ca24 100644
--- a/system/include/hardware/bluetooth.h
+++ b/system/include/hardware/bluetooth.h
@@ -594,7 +594,8 @@ typedef struct {
*/
int (*init)(bt_callbacks_t* callbacks, bool guest_mode,
bool is_common_criteria_mode, int config_compare_result,
- const char** init_flags, bool is_atv);
+ const char** init_flags, bool is_atv,
+ const char* user_data_directory);
/** Enable Bluetooth. */
int (*enable)();
diff --git a/system/main/shim/acl.cc b/system/main/shim/acl.cc
index 86edaa0e8b..0d27c7df7e 100644
--- a/system/main/shim/acl.cc
+++ b/system/main/shim/acl.cc
@@ -779,6 +779,10 @@ class LeShimAclConnection
return connection_->locally_initiated_;
}
+ bool IsInFilterAcceptList() const {
+ return connection_->IsInFilterAcceptList();
+ }
+
private:
OnDisconnect on_disconnect_;
const shim::legacy::acl_le_link_interface_t interface_;
@@ -930,6 +934,7 @@ struct shim::legacy::Acl::impl {
if (connection != handle_to_le_connection_map_.end()) {
auto remote_address_with_type =
connection->second->GetRemoteAddressWithType();
+ GetAclManager()->RemoveFromBackgroundList(remote_address_with_type);
connection->second->InitiateDisconnect(
ToDisconnectReasonFromLegacy(reason));
LOG_DEBUG("Disconnection initiated le remote:%s handle:%hu",
@@ -966,7 +971,8 @@ struct shim::legacy::Acl::impl {
void ignore_le_connection_from(
const hci::AddressWithType& address_with_type) {
shadow_acceptlist_.Remove(address_with_type);
- GetAclManager()->CancelLeConnect(address_with_type);
+ GetAclManager()->CancelLeConnectAndRemoveFromBackgroundList(
+ address_with_type);
LOG_DEBUG("Ignore Le connection from remote:%s",
PRIVATE_ADDRESS(address_with_type));
BTM_LogHistory(kBtmLogTag, ToLegacyAddressWithType(address_with_type),
@@ -1338,12 +1344,16 @@ void shim::legacy::Acl::CancelClassicConnection(const hci::Address& address) {
void shim::legacy::Acl::AcceptLeConnectionFrom(
const hci::AddressWithType& address_with_type, bool is_direct,
std::promise<bool> promise) {
+ LOG_DEBUG("AcceptLeConnectionFrom %s",
+ PRIVATE_ADDRESS(address_with_type.GetAddress()));
handler_->CallOn(pimpl_.get(), &Acl::impl::accept_le_connection_from,
address_with_type, is_direct, std::move(promise));
}
void shim::legacy::Acl::IgnoreLeConnectionFrom(
const hci::AddressWithType& address_with_type) {
+ LOG_DEBUG("IgnoreLeConnectionFrom %s",
+ PRIVATE_ADDRESS(address_with_type.GetAddress()));
handler_->CallOn(pimpl_.get(), &Acl::impl::ignore_le_connection_from,
address_with_type);
}
@@ -1516,12 +1526,6 @@ void shim::legacy::Acl::OnLeConnectSuccess(
std::chrono::system_clock::now()));
pimpl_->handle_to_le_connection_map_[handle]->RegisterCallbacks();
- pimpl_->handle_to_le_connection_map_[handle]
- ->ReadRemoteControllerInformation();
-
- tBLE_BD_ADDR legacy_address_with_type =
- ToLegacyAddressWithType(address_with_type);
-
// Once an le connection has successfully been established
// the device address is removed from the controller accept list.
@@ -1536,6 +1540,22 @@ void shim::legacy::Acl::OnLeConnectSuccess(
pimpl_->shadow_acceptlist_.Remove(address_with_type);
}
+ if (!pimpl_->handle_to_le_connection_map_[handle]->IsInFilterAcceptList() &&
+ connection_role == hci::Role::CENTRAL) {
+ pimpl_->handle_to_le_connection_map_[handle]->InitiateDisconnect(
+ hci::DisconnectReason::REMOTE_USER_TERMINATED_CONNECTION);
+ LOG_INFO("Disconnected ACL after connection canceled");
+ BTM_LogHistory(kBtmLogTag, ToLegacyAddressWithType(address_with_type),
+ "Connection canceled", "Le");
+ return;
+ }
+
+ pimpl_->handle_to_le_connection_map_[handle]
+ ->ReadRemoteControllerInformation();
+
+ tBLE_BD_ADDR legacy_address_with_type =
+ ToLegacyAddressWithType(address_with_type);
+
TRY_POSTING_ON_MAIN(
acl_interface_.connection.le.on_connected, legacy_address_with_type,
handle, ToLegacyRole(connection_role), conn_interval, conn_latency,
diff --git a/system/main/shim/metrics_api.cc b/system/main/shim/metrics_api.cc
index 74784f879c..99832be023 100644
--- a/system/main/shim/metrics_api.cc
+++ b/system/main/shim/metrics_api.cc
@@ -128,13 +128,14 @@ void LogMetricSocketConnectionState(
void LogMetricManufacturerInfo(
const RawAddress& raw_address,
+ android::bluetooth::AddressTypeEnum address_type,
android::bluetooth::DeviceInfoSrcEnum source_type,
const std::string& source_name, const std::string& manufacturer,
const std::string& model, const std::string& hardware_version,
const std::string& software_version) {
Address address = bluetooth::ToGdAddress(raw_address);
- bluetooth::os::LogMetricManufacturerInfo(address, source_type, source_name,
- manufacturer, model,
+ bluetooth::os::LogMetricManufacturerInfo(address, address_type, source_type,
+ source_name, manufacturer, model,
hardware_version, software_version);
}
diff --git a/system/main/shim/metrics_api.h b/system/main/shim/metrics_api.h
index 51ee8df2ba..ce13876180 100644
--- a/system/main/shim/metrics_api.h
+++ b/system/main/shim/metrics_api.h
@@ -202,7 +202,7 @@ void LogMetricSocketConnectionState(
* @param software_version software version of this device
*/
void LogMetricManufacturerInfo(
- const RawAddress& address,
+ const RawAddress& address, android::bluetooth::AddressTypeEnum address_type,
android::bluetooth::DeviceInfoSrcEnum source_type,
const std::string& source_name, const std::string& manufacturer,
const std::string& model, const std::string& hardware_version,
diff --git a/system/main/stack_config.cc b/system/main/stack_config.cc
index c86c0b0aa5..29387a4c24 100644
--- a/system/main/stack_config.cc
+++ b/system/main/stack_config.cc
@@ -46,7 +46,7 @@ static future_t* init() {
#elif defined(OS_GENERIC)
const char* path = "bt_stack.conf";
#else // !defined(OS_GENERIC)
- const char* path = "/apex/com.android.bluetooth/etc/bluetooth/bt_stack.conf";
+ const char* path = "/apex/com.android.btservices/etc/bluetooth/bt_stack.conf";
#endif // defined(OS_GENERIC)
CHECK(path != NULL);
diff --git a/system/service/Android.bp b/system/service/Android.bp
index cfd29794e2..91dcff058d 100644
--- a/system/service/Android.bp
+++ b/system/service/Android.bp
@@ -113,6 +113,7 @@ cc_binary {
"libbt-sbc-encoder",
"libbt-stack",
"libbt-utils",
+ "libc++fs",
"libchrome",
"libflatbuffers-cpp",
"libFraunhoferAAC",
@@ -193,6 +194,7 @@ cc_test {
"libbt-sbc-encoder",
"libbt-stack",
"libbt-utils",
+ "libc++fs",
"libchrome",
"libgmock",
"liblog",
diff --git a/system/service/hal/bluetooth_interface.cc b/system/service/hal/bluetooth_interface.cc
index fbf0ef8cd2..f959d61a22 100644
--- a/system/service/hal/bluetooth_interface.cc
+++ b/system/service/hal/bluetooth_interface.cc
@@ -353,7 +353,8 @@ class BluetoothInterfaceImpl : public BluetoothInterface {
// Initialize the Bluetooth interface. Set up the adapter (Bluetooth DM) API
// callbacks.
- status = hal_iface_->init(&bt_callbacks, false, false, 0, nullptr, false);
+ status = hal_iface_->init(&bt_callbacks, false, false, 0, nullptr, false,
+ nullptr);
if (status != BT_STATUS_SUCCESS) {
LOG(ERROR) << "Failed to initialize Bluetooth stack";
return false;
diff --git a/system/stack/acl/ble_acl.cc b/system/stack/acl/ble_acl.cc
index a09012a37b..08b74489c9 100644
--- a/system/stack/acl/ble_acl.cc
+++ b/system/stack/acl/ble_acl.cc
@@ -125,12 +125,7 @@ void acl_ble_enhanced_connection_complete_from_shim(
uint16_t conn_interval, uint16_t conn_latency, uint16_t conn_timeout,
const RawAddress& local_rpa, const RawAddress& peer_rpa,
tBLE_ADDR_TYPE peer_addr_type) {
- if (!connection_manager::remove_unconditional_from_shim(
- address_with_type.bda)) {
- LOG_WARN(
- "Unable to remove from legacy connection manager accept list addr:%s",
- PRIVATE_ADDRESS(address_with_type.bda));
- }
+ connection_manager::on_connection_complete(address_with_type.bda);
tBLE_BD_ADDR resolved_address_with_type;
const bool is_in_security_db = maybe_resolve_received_address(
diff --git a/system/stack/acl/btm_acl.cc b/system/stack/acl/btm_acl.cc
index 85eb5d8580..16ee57b5a9 100644
--- a/system/stack/acl/btm_acl.cc
+++ b/system/stack/acl/btm_acl.cc
@@ -1416,6 +1416,8 @@ void StackAclBtmAcl::btm_acl_role_changed(tHCI_STATUS hci_status,
void btm_acl_role_changed(tHCI_STATUS hci_status, const RawAddress& bd_addr,
tHCI_ROLE new_role) {
+ btm_rejectlist_role_change_device(bd_addr, hci_status);
+
if (hci_status == HCI_SUCCESS) {
l2c_link_role_changed(&bd_addr, new_role, hci_status);
} else {
diff --git a/system/stack/btm/btm_ble_bgconn.cc b/system/stack/btm/btm_ble_bgconn.cc
index d093aa5a2a..ef07cdb011 100644
--- a/system/stack/btm/btm_ble_bgconn.cc
+++ b/system/stack/btm/btm_ble_bgconn.cc
@@ -205,8 +205,14 @@ bool BTM_AcceptlistAdd(const RawAddress& address) {
LOG_WARN("Controller does not support Le");
return false;
}
+
+ tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(address);
+ if (p_dev_rec != NULL && p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) {
+ p_dev_rec->ble.in_controller_list |= BTM_ACCEPTLIST_BIT;
+ }
+
return bluetooth::shim::ACL_AcceptLeConnectionFrom(
- convert_to_address_with_type(address, btm_find_dev(address)),
+ convert_to_address_with_type(address, p_dev_rec),
/* is_direct */ false);
}
@@ -216,8 +222,15 @@ void BTM_AcceptlistRemove(const RawAddress& address) {
LOG_WARN("Controller does not support Le");
return;
}
+
+ tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(address);
+ if (p_dev_rec != NULL && p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) {
+ p_dev_rec->ble.in_controller_list &= ~BTM_ACCEPTLIST_BIT;
+ }
+
bluetooth::shim::ACL_IgnoreLeConnectionFrom(
- convert_to_address_with_type(address, btm_find_dev(address)));
+ convert_to_address_with_type(address, p_dev_rec));
+ return;
}
/** Clear the acceptlist, end any pending acceptlist connections */
diff --git a/system/stack/btm/btm_ble_privacy.cc b/system/stack/btm/btm_ble_privacy.cc
index 0a3035dadf..b2f26faf15 100644
--- a/system/stack/btm/btm_ble_privacy.cc
+++ b/system/stack/btm/btm_ble_privacy.cc
@@ -434,10 +434,9 @@ tBTM_STATUS btm_ble_remove_resolving_list_entry(tBTM_SEC_DEV_REC* p_dev_rec) {
BTM_VendorSpecificCommand(HCI_VENDOR_BLE_RPA_VSC,
BTM_BLE_META_REMOVE_IRK_LEN, param,
btm_ble_resolving_list_vsc_op_cmpl);
+ btm_ble_enq_resolving_list_pending(p_dev_rec->bd_addr,
+ BTM_BLE_META_REMOVE_IRK_ENTRY);
}
-
- btm_ble_enq_resolving_list_pending(p_dev_rec->bd_addr,
- BTM_BLE_META_REMOVE_IRK_ENTRY);
return BTM_CMD_STARTED;
}
@@ -495,11 +494,10 @@ bool btm_ble_read_resolving_list_entry(tBTM_SEC_DEV_REC* p_dev_rec) {
BTM_VendorSpecificCommand(HCI_VENDOR_BLE_RPA_VSC, BTM_BLE_META_READ_IRK_LEN,
param, btm_ble_resolving_list_vsc_op_cmpl);
- }
-
- btm_ble_enq_resolving_list_pending(p_dev_rec->bd_addr,
- BTM_BLE_META_READ_IRK_ENTRY);
+ btm_ble_enq_resolving_list_pending(p_dev_rec->bd_addr,
+ BTM_BLE_META_READ_IRK_ENTRY);
+ }
return true;
}
diff --git a/system/stack/btm/btm_dev.cc b/system/stack/btm/btm_dev.cc
index eeb37be055..4067e3d46e 100644
--- a/system/stack/btm/btm_dev.cc
+++ b/system/stack/btm/btm_dev.cc
@@ -136,6 +136,9 @@ void wipe_secrets_and_remove(tBTM_SEC_DEV_REC* p_dev_rec) {
list_remove(btm_cb.sec_dev_rec, p_dev_rec);
}
+/** Removes the device from acceptlist */
+extern void BTM_AcceptlistRemove(const RawAddress& address);
+
/** Free resources associated with the device associated with |bd_addr| address.
*
* *** WARNING ***
@@ -162,6 +165,12 @@ bool BTM_SecDeleteDevice(const RawAddress& bd_addr) {
if (p_dev_rec != NULL) {
RawAddress bda = p_dev_rec->bd_addr;
+ if (p_dev_rec->ble.in_controller_list & BTM_ACCEPTLIST_BIT) {
+ LOG_INFO("Remove device %s from filter accept list before delete record",
+ PRIVATE_ADDRESS(bd_addr));
+ BTM_AcceptlistRemove(p_dev_rec->bd_addr);
+ }
+
/* Clear out any saved BLE keys */
btm_sec_clear_ble_keys(p_dev_rec);
wipe_secrets_and_remove(p_dev_rec);
diff --git a/system/stack/btm/btm_sec.cc b/system/stack/btm/btm_sec.cc
index f42e89ab89..4a83cde884 100644
--- a/system/stack/btm/btm_sec.cc
+++ b/system/stack/btm/btm_sec.cc
@@ -3638,9 +3638,12 @@ void btm_sec_connected(const RawAddress& bda, uint16_t handle,
return;
}
- /* If initiated dedicated bonding, return the link key now, and initiate
- * disconnect */
- /* If dedicated bonding, and we now have a link key, we are all done */
+ /*
+ * The device is still in the pairing state machine and we now have the
+ * link key. If we have not sent the link key, send it now and remove
+ * the authenticate requirement bit. Reset the pairing state machine
+ * and inform l2cap if the directed bonding was initiated.
+ */
if (is_pairing_device && (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN)) {
if (p_dev_rec->link_key_not_sent) {
p_dev_rec->link_key_not_sent = false;
@@ -3650,20 +3653,20 @@ void btm_sec_connected(const RawAddress& bda, uint16_t handle,
p_dev_rec->security_required &= ~BTM_SEC_OUT_AUTHENTICATE;
/* remember flag before it is initialized */
- bool is_pair_flags_we_started_dd = false;
- if (btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD)
- is_pair_flags_we_started_dd = true;
- else
- is_pair_flags_we_started_dd = false;
-
+ const bool is_pair_flags_we_started_dd =
+ btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD;
btm_sec_change_pairing_state(BTM_PAIR_STATE_IDLE);
if (is_pair_flags_we_started_dd) {
/* Let l2cap start bond timer */
l2cu_update_lcb_4_bonding(p_dev_rec->bd_addr, true);
}
-
- return;
+ LOG_INFO("Connection complete during pairing process peer:%s",
+ PRIVATE_ADDRESS(bda));
+ BTM_LogHistory(kBtmLogTag, bda, "Dedicated bonding",
+ base::StringPrintf("Initiated:%c pairing_flag:0x%02x",
+ (is_pair_flags_we_started_dd) ? 'T' : 'F',
+ p_dev_rec->sec_flags));
}
p_dev_rec->hci_handle = handle;
diff --git a/system/stack/btu/btu_hcif.cc b/system/stack/btu/btu_hcif.cc
index a356b56581..4d24c48150 100644
--- a/system/stack/btu/btu_hcif.cc
+++ b/system/stack/btu/btu_hcif.cc
@@ -83,7 +83,6 @@ static void btu_hcif_command_complete_evt(BT_HDR* response, void* context);
static void btu_hcif_command_status_evt(uint8_t status, BT_HDR* command,
void* context);
static void btu_hcif_hardware_error_evt(uint8_t* p);
-static void btu_hcif_role_change_evt(const uint8_t* p);
static void btu_hcif_mode_change_evt(uint8_t* p);
static void btu_hcif_link_key_notification_evt(const uint8_t* p);
static void btu_hcif_read_clock_off_comp_evt(uint8_t* p);
@@ -283,9 +282,6 @@ void btu_hcif_process_event(UNUSED_ATTR uint8_t controller_id,
case HCI_HARDWARE_ERROR_EVT:
btu_hcif_hardware_error_evt(p);
break;
- case HCI_ROLE_CHANGE_EVT:
- btu_hcif_role_change_evt(p);
- break;
case HCI_NUM_COMPL_DATA_PKTS_EVT:
acl_process_num_completed_pkts(p, hci_evt_len);
break;
@@ -430,6 +426,7 @@ void btu_hcif_process_event(UNUSED_ATTR uint8_t controller_id,
case HCI_CONNECTION_COMP_EVT: // EventCode::CONNECTION_COMPLETE
case HCI_READ_RMT_FEATURES_COMP_EVT: // EventCode::READ_REMOTE_SUPPORTED_FEATURES_COMPLETE
case HCI_READ_RMT_VERSION_COMP_EVT: // EventCode::READ_REMOTE_VERSION_INFORMATION_COMPLETE
+ case HCI_ROLE_CHANGE_EVT: // EventCode::ROLE_CHANGE
default:
LOG_ERROR(
"Unexpectedly received event_code:0x%02x that should not be "
@@ -1490,28 +1487,6 @@ static void btu_hcif_hardware_error_evt(uint8_t* p) {
/*******************************************************************************
*
- * Function btu_hcif_role_change_evt
- *
- * Description Process event HCI_ROLE_CHANGE_EVT
- *
- * Returns void
- *
- ******************************************************************************/
-static void btu_hcif_role_change_evt(const uint8_t* p) {
- uint8_t status;
- RawAddress bda;
- uint8_t role;
-
- STREAM_TO_UINT8(status, p);
- STREAM_TO_BDADDR(bda, p);
- STREAM_TO_UINT8(role, p);
-
- btm_rejectlist_role_change_device(bda, status);
- btm_acl_role_changed(to_hci_status_code(status), bda, to_hci_role(role));
-}
-
-/*******************************************************************************
- *
* Function btu_hcif_mode_change_evt
*
* Description Process event HCI_MODE_CHANGE_EVT
diff --git a/system/stack/gatt/connection_manager.cc b/system/stack/gatt/connection_manager.cc
index c6052c236c..fd38bb5e05 100644
--- a/system/stack/gatt/connection_manager.cc
+++ b/system/stack/gatt/connection_manager.cc
@@ -149,21 +149,6 @@ bool remove_unconditional(const RawAddress& address) {
return true;
}
-/** Removes the registrations for connection for given device.
- * but does not change the controller acceptlist. Used for
- * shim purposes.
- * Returns true if anything was removed, false otherwise */
-bool remove_unconditional_from_shim(const RawAddress& address) {
- LOG_DEBUG("address=%s", address.ToString().c_str());
- auto it = bgconn_dev.find(address);
- if (it == bgconn_dev.end()) {
- LOG_WARN("address %s is not found", address.ToString().c_str());
- return false;
- }
- bgconn_dev.erase(it);
- return true;
-}
-
/** Remove device from the background connection device list or listening to
* advertising list. Returns true if device was on the list and was
* successfully removed */
diff --git a/system/stack/gatt/connection_manager.h b/system/stack/gatt/connection_manager.h
index fe2bd93299..d3eb3e39b9 100644
--- a/system/stack/gatt/connection_manager.h
+++ b/system/stack/gatt/connection_manager.h
@@ -41,7 +41,6 @@ extern bool background_connect_add(tAPP_ID app_id, const RawAddress& address);
extern bool background_connect_remove(tAPP_ID app_id,
const RawAddress& address);
extern bool remove_unconditional(const RawAddress& address);
-extern bool remove_unconditional_from_shim(const RawAddress& address);
extern void reset(bool after_reset);
diff --git a/system/stack/gatt/gatt_api.cc b/system/stack/gatt/gatt_api.cc
index b55e62563e..303223f6af 100644
--- a/system/stack/gatt/gatt_api.cc
+++ b/system/stack/gatt/gatt_api.cc
@@ -998,8 +998,8 @@ tGATT_IF GATT_Register(const Uuid& app_uuid128, std::string name,
for (i_gatt_if = 0, p_reg = gatt_cb.cl_rcb; i_gatt_if < GATT_MAX_APPS;
i_gatt_if++, p_reg++) {
if (p_reg->in_use && p_reg->app_uuid128 == app_uuid128) {
- LOG(ERROR) << __func__ << ": Application already registered "
- << app_uuid128;
+ LOG_ERROR("Application already registered, uuid=%s",
+ app_uuid128.ToString().c_str());
return 0;
}
}
@@ -1022,9 +1022,8 @@ tGATT_IF GATT_Register(const Uuid& app_uuid128, std::string name,
}
}
- LOG(ERROR) << __func__
- << ": Unable to register GATT client, MAX client reached: "
- << GATT_MAX_APPS;
+ LOG_ERROR("Unable to register GATT client, MAX client reached: %d",
+ GATT_MAX_APPS);
return 0;
}
@@ -1111,7 +1110,7 @@ void GATT_Deregister(tGATT_IF gatt_if) {
void GATT_StartIf(tGATT_IF gatt_if) {
tGATT_REG* p_reg;
tGATT_TCB* p_tcb;
- RawAddress bda;
+ RawAddress bda = {};
uint8_t start_idx, found_idx;
uint16_t conn_id;
tBT_TRANSPORT transport;
@@ -1124,10 +1123,15 @@ void GATT_StartIf(tGATT_IF gatt_if) {
while (
gatt_find_the_connected_bda(start_idx, bda, &found_idx, &transport)) {
p_tcb = gatt_find_tcb_by_addr(bda, transport);
+ LOG_INFO("GATT interface %d already has connected device %s", +gatt_if,
+ bda.ToString().c_str());
if (p_reg->app_cb.p_conn_cb && p_tcb) {
conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
+ LOG_INFO("Invoking callback with connection id %d", conn_id);
(*p_reg->app_cb.p_conn_cb)(gatt_if, bda, conn_id, true, GATT_CONN_OK,
transport);
+ } else {
+ LOG_INFO("Skipping callback as none is registered");
}
start_idx = ++found_idx;
}
diff --git a/system/stack/gatt/gatt_utils.cc b/system/stack/gatt/gatt_utils.cc
index 11a0f85eb6..991944a190 100644
--- a/system/stack/gatt/gatt_utils.cc
+++ b/system/stack/gatt/gatt_utils.cc
@@ -21,14 +21,16 @@
* this file contains GATT utility functions
*
******************************************************************************/
+#define LOG_TAG "gatt_utils"
+
#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include <cstdint>
#include "bt_target.h" // Must be first to define build configuration
-#include "main/shim/shim.h"
#include "osi/include/allocator.h"
+#include "osi/include/log.h"
#include "stack/btm/btm_sec.h"
#include "stack/eatt/eatt.h"
#include "stack/gatt/connection_manager.h"
@@ -257,7 +259,7 @@ bool gatt_find_the_connected_bda(uint8_t start_idx, RawAddress& bda,
tBT_TRANSPORT* p_transport) {
uint8_t i;
bool found = false;
- VLOG(1) << __func__ << " start_idx=" << +start_idx;
+ LOG_DEBUG("start_idx=%d", +start_idx);
for (i = start_idx; i < GATT_MAX_PHY_CHANNEL; i++) {
if (gatt_cb.tcb[i].in_use && gatt_cb.tcb[i].ch_state == GATT_CH_OPEN) {
@@ -265,11 +267,11 @@ bool gatt_find_the_connected_bda(uint8_t start_idx, RawAddress& bda,
*p_found_idx = i;
*p_transport = gatt_cb.tcb[i].transport;
found = true;
- VLOG(1) << " bda :" << bda;
+ LOG_DEBUG("bda: %s", bda.ToString().c_str());
break;
}
}
- VLOG(1) << StringPrintf(" found=%d found_idx=%d", found, i);
+ LOG_DEBUG("found=%d found_idx=%d", found, +i);
return found;
}
diff --git a/system/stack/include/gatt_api.h b/system/stack/include/gatt_api.h
index 33a6eaee6d..b38e943302 100644
--- a/system/stack/include/gatt_api.h
+++ b/system/stack/include/gatt_api.h
@@ -247,7 +247,7 @@ inline std::string gatt_disconnection_reason_text(
/* max legth of an attribute value
*/
#ifndef GATT_MAX_ATTR_LEN
-#define GATT_MAX_ATTR_LEN 600
+#define GATT_MAX_ATTR_LEN 512
#endif
/* default GATT MTU size over LE link
diff --git a/system/stack/include/stack_metrics_logging.h b/system/stack/include/stack_metrics_logging.h
index 56921ddbdf..158c98f610 100644
--- a/system/stack/include/stack_metrics_logging.h
+++ b/system/stack/include/stack_metrics_logging.h
@@ -43,6 +43,7 @@ void log_sdp_attribute(const RawAddress& address, uint16_t protocol_uuid,
const char* attribute_value);
void log_manufacturer_info(const RawAddress& address,
+ android::bluetooth::AddressTypeEnum address_type,
android::bluetooth::DeviceInfoSrcEnum source_type,
const std::string& source_name,
const std::string& manufacturer,
diff --git a/system/stack/l2cap/l2c_csm.cc b/system/stack/l2cap/l2c_csm.cc
index a398e033fd..3646964dd4 100755
--- a/system/stack/l2cap/l2c_csm.cc
+++ b/system/stack/l2cap/l2c_csm.cc
@@ -517,7 +517,7 @@ static void l2c_csm_term_w4_sec_comp(tL2C_CCB* p_ccb, tL2CEVT event,
(*p_ccb->p_rcb->api.pL2CA_CreditBasedConnectInd_Cb)(
p_ccb->p_lcb->remote_bd_addr, pending_cids, p_ccb->p_rcb->psm,
- p_ccb->peer_cfg.mtu, p_ccb->remote_id);
+ p_ccb->peer_conn_cfg.mtu, p_ccb->remote_id);
} else {
/* Handle BLE CoC */
LOG_DEBUG("Calling Connect_Ind_Cb(), CID: 0x%04x",
diff --git a/system/stack/metrics/stack_metrics_logging.cc b/system/stack/metrics/stack_metrics_logging.cc
index 50f029f803..4e23bd2a08 100644
--- a/system/stack/metrics/stack_metrics_logging.cc
+++ b/system/stack/metrics/stack_metrics_logging.cc
@@ -57,6 +57,7 @@ void log_sdp_attribute(const RawAddress& address, uint16_t protocol_uuid,
}
void log_manufacturer_info(const RawAddress& address,
+ android::bluetooth::AddressTypeEnum address_type,
android::bluetooth::DeviceInfoSrcEnum source_type,
const std::string& source_name,
const std::string& manufacturer,
@@ -64,8 +65,8 @@ void log_manufacturer_info(const RawAddress& address,
const std::string& hardware_version,
const std::string& software_version) {
bluetooth::shim::LogMetricManufacturerInfo(
- address, source_type, source_name, manufacturer, model, hardware_version,
- software_version);
+ address, address_type, source_type, source_name, manufacturer, model,
+ hardware_version, software_version);
}
void log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum key,
diff --git a/system/stack/sdp/sdp_utils.cc b/system/stack/sdp/sdp_utils.cc
index 44078ae720..761883e60e 100644
--- a/system/stack/sdp/sdp_utils.cc
+++ b/system/stack/sdp/sdp_utils.cc
@@ -22,6 +22,9 @@
*
******************************************************************************/
+#include <base/logging.h>
+#include <log/log.h>
+
#include <array>
#include <cstdint>
#include <cstring>
@@ -40,8 +43,6 @@
#include "types/bluetooth/uuid.h"
#include "types/raw_address.h"
-#include <base/logging.h>
-
using bluetooth::Uuid;
static const uint8_t sdp_base_uuid[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x00, 0x80, 0x00, 0x00, 0x80,
@@ -126,6 +127,10 @@ static uint16_t sdpu_find_most_specific_service_uuid(tSDP_DISC_REC* p_rec) {
if (p_attr->attr_id == ATTR_ID_SERVICE_CLASS_ID_LIST &&
SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE) {
tSDP_DISC_ATTR* p_first_attr = p_attr->attr_value.v.p_sub_attr;
+ if (p_first_attr == nullptr) {
+ android_errorWriteLog(0x534e4554, "227203684");
+ return 0;
+ }
if (SDP_DISC_ATTR_TYPE(p_first_attr->attr_len_type) == UUID_DESC_TYPE &&
SDP_DISC_ATTR_LEN(p_first_attr->attr_len_type) == 2) {
return p_first_attr->attr_value.v.u16;
@@ -273,8 +278,9 @@ void sdpu_log_attribute_metrics(const RawAddress& bda,
// [N - native]::SDP::[DIP - Device ID Profile]
ss << "N:SDP::DIP::" << loghex(di_record.rec.vendor_id_source);
log_manufacturer_info(
- bda, android::bluetooth::DeviceInfoSrcEnum::DEVICE_INFO_INTERNAL,
- ss.str(), loghex(di_record.rec.vendor), loghex(di_record.rec.product),
+ bda, android::bluetooth::AddressTypeEnum::ADDRESS_TYPE_PUBLIC,
+ android::bluetooth::DeviceInfoSrcEnum::DEVICE_INFO_INTERNAL, ss.str(),
+ loghex(di_record.rec.vendor), loghex(di_record.rec.product),
loghex(di_record.rec.version), "");
std::string bda_string = bda.ToString();
diff --git a/system/stack/test/eatt/eatt_test.cc b/system/stack/test/eatt/eatt_test.cc
index 1bdca362e1..3eda92c468 100644
--- a/system/stack/test/eatt/eatt_test.cc
+++ b/system/stack/test/eatt/eatt_test.cc
@@ -93,6 +93,7 @@ class EattTest : public testing::Test {
connected_cids_.push_back(cid);
ASSERT_TRUE(channel->state_ == EattChannelState::EATT_CHANNEL_OPENED);
+ ASSERT_TRUE(channel->tx_mtu_ == EATT_MIN_MTU_MPS);
} else {
l2cap_app_info_.pL2CA_Error_Cb(cid, L2CAP_CONN_NO_RESOURCES);
diff --git a/system/test/headless/Android.bp b/system/test/headless/Android.bp
index 87f94c1b2a..92c6302ccf 100644
--- a/system/test/headless/Android.bp
+++ b/system/test/headless/Android.bp
@@ -61,6 +61,7 @@ cc_test {
"libbt_shim_ffi",
"libbt-stack",
"libbt-utils",
+ "libc++fs",
"libflatbuffers-cpp",
"libFraunhoferAAC",
"libg722codec",
diff --git a/system/test/headless/headless.cc b/system/test/headless/headless.cc
index 821ee0591f..23884c1763 100644
--- a/system/test/headless/headless.cc
+++ b/system/test/headless/headless.cc
@@ -215,7 +215,7 @@ void HeadlessStack::SetUp() {
const bool is_atv = false;
int status = bluetoothInterface.init(
&bt_callbacks, start_restricted, is_common_criteria_mode,
- config_compare_result, StackInitFlags(), is_atv);
+ config_compare_result, StackInitFlags(), is_atv, nullptr);
(status == BT_STATUS_SUCCESS)
? LOG(INFO) << __func__ << " Initialized bluetooth callbacks"
diff --git a/system/test/mock/mock_bta_dm_act.cc b/system/test/mock/mock_bta_dm_act.cc
index f77e90b9b5..67030ccf5a 100644
--- a/system/test/mock/mock_bta_dm_act.cc
+++ b/system/test/mock/mock_bta_dm_act.cc
@@ -92,6 +92,7 @@ struct bta_dm_rm_cback bta_dm_rm_cback;
struct bta_dm_rmt_name bta_dm_rmt_name;
struct bta_dm_sdp_result bta_dm_sdp_result;
struct bta_dm_search_cancel bta_dm_search_cancel;
+struct bta_dm_search_cancel_cmpl bta_dm_search_cancel_cmpl;
struct bta_dm_search_cancel_notify bta_dm_search_cancel_notify;
struct bta_dm_search_clear_queue bta_dm_search_clear_queue;
struct bta_dm_search_cmpl bta_dm_search_cmpl;
@@ -337,6 +338,10 @@ void bta_dm_search_cancel() {
mock_function_count_map[__func__]++;
test::mock::bta_dm_act::bta_dm_search_cancel();
}
+void bta_dm_search_cancel_cmpl() {
+ mock_function_count_map[__func__]++;
+ test::mock::bta_dm_act::bta_dm_search_cancel_cmpl();
+}
void bta_dm_search_cancel_notify() {
mock_function_count_map[__func__]++;
test::mock::bta_dm_act::bta_dm_search_cancel_notify();
diff --git a/system/test/mock/mock_bta_dm_api.cc b/system/test/mock/mock_bta_dm_api.cc
index 4cbab7ef4b..bbb46abd9f 100644
--- a/system/test/mock/mock_bta_dm_api.cc
+++ b/system/test/mock/mock_bta_dm_api.cc
@@ -163,10 +163,9 @@ void BTA_DmConfirm(const RawAddress& bd_addr, bool accept) {
test::mock::bta_dm_api::BTA_DmConfirm(bd_addr, accept);
}
void BTA_DmDiscover(const RawAddress& bd_addr, tBTA_DM_SEARCH_CBACK* p_cback,
- tBT_TRANSPORT transport, bool is_bonding_or_sd) {
+ tBT_TRANSPORT transport) {
mock_function_count_map[__func__]++;
- test::mock::bta_dm_api::BTA_DmDiscover(bd_addr, p_cback, transport,
- is_bonding_or_sd);
+ test::mock::bta_dm_api::BTA_DmDiscover(bd_addr, p_cback, transport);
}
bool BTA_DmGetConnectionState(const RawAddress& bd_addr) {
mock_function_count_map[__func__]++;
@@ -185,9 +184,9 @@ tBTA_STATUS BTA_DmRemoveDevice(const RawAddress& bd_addr) {
mock_function_count_map[__func__]++;
return test::mock::bta_dm_api::BTA_DmRemoveDevice(bd_addr);
}
-void BTA_DmSearch(tBTA_DM_SEARCH_CBACK* p_cback, bool is_bonding_or_sdp) {
+void BTA_DmSearch(tBTA_DM_SEARCH_CBACK* p_cback) {
mock_function_count_map[__func__]++;
- test::mock::bta_dm_api::BTA_DmSearch(p_cback, is_bonding_or_sdp);
+ test::mock::bta_dm_api::BTA_DmSearch(p_cback);
}
void BTA_DmSearchCancel(void) {
mock_function_count_map[__func__]++;
diff --git a/system/test/mock/mock_bta_dm_api.h b/system/test/mock/mock_bta_dm_api.h
index d9dd9ba4ed..3e64ff3679 100644
--- a/system/test/mock/mock_bta_dm_api.h
+++ b/system/test/mock/mock_bta_dm_api.h
@@ -280,15 +280,15 @@ extern struct BTA_DmConfirm BTA_DmConfirm;
// Name: BTA_DmDiscover
// Params: const RawAddress& bd_addr, tBTA_DM_SEARCH_CBACK* p_cback,
-// tBT_TRANSPORT transport, bool is_bonding_or_sd Return: void
+// tBT_TRANSPORT transport Return: void
struct BTA_DmDiscover {
std::function<void(const RawAddress& bd_addr, tBTA_DM_SEARCH_CBACK* p_cback,
- tBT_TRANSPORT transport, bool is_bonding_or_sd)>
+ tBT_TRANSPORT transport)>
body{[](const RawAddress& bd_addr, tBTA_DM_SEARCH_CBACK* p_cback,
- tBT_TRANSPORT transport, bool is_bonding_or_sd) {}};
+ tBT_TRANSPORT transport) {}};
void operator()(const RawAddress& bd_addr, tBTA_DM_SEARCH_CBACK* p_cback,
- tBT_TRANSPORT transport, bool is_bonding_or_sd) {
- body(bd_addr, p_cback, transport, is_bonding_or_sd);
+ tBT_TRANSPORT transport) {
+ body(bd_addr, p_cback, transport);
};
};
extern struct BTA_DmDiscover BTA_DmDiscover;
@@ -340,14 +340,12 @@ struct BTA_DmRemoveDevice {
extern struct BTA_DmRemoveDevice BTA_DmRemoveDevice;
// Name: BTA_DmSearch
-// Params: tBTA_DM_SEARCH_CBACK* p_cback, bool is_bonding_or_sdp
+// Params: tBTA_DM_SEARCH_CBACK* p_cback
// Return: void
struct BTA_DmSearch {
- std::function<void(tBTA_DM_SEARCH_CBACK* p_cback, bool is_bonding_or_sdp)>
- body{[](tBTA_DM_SEARCH_CBACK* p_cback, bool is_bonding_or_sdp) {}};
- void operator()(tBTA_DM_SEARCH_CBACK* p_cback, bool is_bonding_or_sdp) {
- body(p_cback, is_bonding_or_sdp);
- };
+ std::function<void(tBTA_DM_SEARCH_CBACK* p_cback)> body{
+ [](tBTA_DM_SEARCH_CBACK* p_cback) {}};
+ void operator()(tBTA_DM_SEARCH_CBACK* p_cback) { body(p_cback); };
};
extern struct BTA_DmSearch BTA_DmSearch;
diff --git a/system/test/mock/mock_main_shim_metrics_api.cc b/system/test/mock/mock_main_shim_metrics_api.cc
index 25b32283fc..30aeeb1111 100644
--- a/system/test/mock/mock_main_shim_metrics_api.cc
+++ b/system/test/mock/mock_main_shim_metrics_api.cc
@@ -165,13 +165,14 @@ void bluetooth::shim::LogMetricSocketConnectionState(
}
void bluetooth::shim::LogMetricManufacturerInfo(
const RawAddress& raw_address,
+ android::bluetooth::AddressTypeEnum address_type,
android::bluetooth::DeviceInfoSrcEnum source_type,
const std::string& source_name, const std::string& manufacturer,
const std::string& model, const std::string& hardware_version,
const std::string& software_version) {
mock_function_count_map[__func__]++;
test::mock::main_shim_metrics_api::LogMetricManufacturerInfo(
- raw_address, source_type, source_name, manufacturer, model,
+ raw_address, address_type, source_type, source_name, manufacturer, model,
hardware_version, software_version);
}
bool bluetooth::shim::CountCounterMetrics(int32_t key, int64_t count) {
diff --git a/system/test/mock/mock_main_shim_metrics_api.h b/system/test/mock/mock_main_shim_metrics_api.h
index 39f4e7f866..b42529f8a7 100644
--- a/system/test/mock/mock_main_shim_metrics_api.h
+++ b/system/test/mock/mock_main_shim_metrics_api.h
@@ -258,24 +258,27 @@ extern struct LogMetricSocketConnectionState LogMetricSocketConnectionState;
// std::string& software_version Returns: void
struct LogMetricManufacturerInfo {
std::function<void(const RawAddress& raw_address,
+ android::bluetooth::AddressTypeEnum address_type,
android::bluetooth::DeviceInfoSrcEnum source_type,
const std::string& source_name,
const std::string& manufacturer, const std::string& model,
const std::string& hardware_version,
const std::string& software_version)>
body{[](const RawAddress& raw_address,
+ android::bluetooth::AddressTypeEnum address_type,
android::bluetooth::DeviceInfoSrcEnum source_type,
const std::string& source_name, const std::string& manufacturer,
const std::string& model, const std::string& hardware_version,
const std::string& software_version) {}};
void operator()(const RawAddress& raw_address,
+ android::bluetooth::AddressTypeEnum address_type,
android::bluetooth::DeviceInfoSrcEnum source_type,
const std::string& source_name,
const std::string& manufacturer, const std::string& model,
const std::string& hardware_version,
const std::string& software_version) {
- body(raw_address, source_type, source_name, manufacturer, model,
- hardware_version, software_version);
+ body(raw_address, address_type, source_type, source_name, manufacturer,
+ model, hardware_version, software_version);
};
};
extern struct LogMetricManufacturerInfo LogMetricManufacturerInfo;
diff --git a/system/test/mock/mock_stack_gatt_connection_manager.cc b/system/test/mock/mock_stack_gatt_connection_manager.cc
index 70505501ca..99f2904289 100644
--- a/system/test/mock/mock_stack_gatt_connection_manager.cc
+++ b/system/test/mock/mock_stack_gatt_connection_manager.cc
@@ -71,11 +71,6 @@ bool connection_manager::remove_unconditional(const RawAddress& address) {
mock_function_count_map[__func__]++;
return false;
}
-bool connection_manager::remove_unconditional_from_shim(
- const RawAddress& address) {
- mock_function_count_map[__func__]++;
- return false;
-}
std::set<tAPP_ID> connection_manager::get_apps_connecting_to(
const RawAddress& address) {
mock_function_count_map[__func__]++;
diff --git a/system/test/suite/Android.bp b/system/test/suite/Android.bp
index ec9545fa90..c39b1eb204 100644
--- a/system/test/suite/Android.bp
+++ b/system/test/suite/Android.bp
@@ -92,6 +92,7 @@ cc_defaults {
"liblc3",
"libosi",
"libstatslog_bt",
+ "libc++fs",
],
header_libs: [
"libhardware_headers",
diff --git a/system/test/suite/adapter/adapter_unittest.cc b/system/test/suite/adapter/adapter_unittest.cc
index 64beb40850..03aa5c949b 100644
--- a/system/test/suite/adapter/adapter_unittest.cc
+++ b/system/test/suite/adapter/adapter_unittest.cc
@@ -181,7 +181,8 @@ TEST_F(BluetoothTest, AdapterCleanupDuringDiscovery) {
ASSERT_TRUE(bt_callbacks != nullptr);
for (int i = 0; i < kTestRepeatCount; ++i) {
- bt_interface()->init(bt_callbacks, false, false, 0, nullptr, false);
+ bt_interface()->init(bt_callbacks, false, false, 0, nullptr, false,
+ nullptr);
EXPECT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS);
semaphore_wait(adapter_state_changed_callback_sem_);
EXPECT_EQ(GetState(), BT_STATE_ON) << "Adapter did not turn on.";