diff options
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 Binary files differindex c6ea434b5d..c6ea434b5d 100644 --- a/android/app/certs/com.android.bluetooth.services.pk8 +++ b/android/app/certs/com.android.bluetooth.pk8 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 Binary files differindex 969211f93e..969211f93e 100644 --- a/apex/com.android.bluetooth.avbpubkey +++ b/apex/com.android.btservices.avbpubkey 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 Binary files differindex 59f489f8ff..59f489f8ff 100644 --- a/apex/com.android.bluetooth.pk8 +++ b/apex/com.android.btservices.pk8 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."; |