summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2015-03-13 04:14:30 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2015-03-13 04:14:30 -0700
commitaebf80d8dbea7c6919f50126b6d013dd9d0cb5f8 (patch)
treeed1a0bd6f90ad235b25b6eaaa945dd633eb19378
parent71a813fe10d3ac39676e5d7f9dda83c8ac482018 (diff)
parentf0399274387e1912edfd1503d5b7f20cf604f357 (diff)
downloadandroid_packages_apps_Bluetooth-aebf80d8dbea7c6919f50126b6d013dd9d0cb5f8.tar.gz
android_packages_apps_Bluetooth-aebf80d8dbea7c6919f50126b6d013dd9d0cb5f8.tar.bz2
android_packages_apps_Bluetooth-aebf80d8dbea7c6919f50126b6d013dd9d0cb5f8.zip
Merge "Merge tag 'AU_LINUX_ANDROID_LA.BF64.1.2.1_RB2.05.00.02.081.002' into HEAD"
-rw-r--r--jni/com_android_bluetooth_btservice_AdapterService.cpp6
-rw-r--r--jni/com_android_bluetooth_gatt.cpp16
-rw-r--r--res/values-bn-rBD/strings.xml5
-rw-r--r--res/values-eu-rES/strings.xml7
-rw-r--r--res/values-gl-rES/strings.xml5
-rw-r--r--res/values-hi/test_strings.xml2
-rw-r--r--res/values-is-rIS/strings.xml5
-rw-r--r--res/values-kk-rKZ/strings.xml5
-rw-r--r--res/values-km-rKH/strings.xml12
-rw-r--r--res/values-kn-rIN/strings.xml5
-rw-r--r--res/values-ky-rKG/strings.xml5
-rw-r--r--res/values-mk-rMK/strings.xml5
-rw-r--r--res/values-ml-rIN/strings.xml43
-rw-r--r--res/values-ml-rIN/strings_pbap.xml2
-rw-r--r--res/values-ml-rIN/test_strings.xml2
-rw-r--r--res/values-mr-rIN/strings.xml43
-rw-r--r--res/values-mr-rIN/strings_pbap.xml2
-rw-r--r--res/values-mr-rIN/test_strings.xml2
-rw-r--r--res/values-my-rMM/strings.xml15
-rw-r--r--res/values-ne-rNP/strings.xml5
-rw-r--r--res/values-si-rLK/strings.xml5
-rw-r--r--res/values-sl/strings.xml4
-rw-r--r--res/values-ta-rIN/strings.xml5
-rw-r--r--res/values-te-rIN/strings.xml5
-rw-r--r--res/values-ur-rPK/strings.xml5
-rw-r--r--res/values-uz-rUZ/strings.xml5
-rw-r--r--res/values-zh-rCN/strings_pbap.xml10
-rw-r--r--res/values-zh-rCN/test_strings.xml6
-rw-r--r--src/com/android/bluetooth/Utils.java46
-rw-r--r--src/com/android/bluetooth/a2dp/A2dpService.java11
-rw-r--r--src/com/android/bluetooth/a2dp/A2dpSinkService.java8
-rw-r--r--src/com/android/bluetooth/a2dp/A2dpSinkStateMachine.java9
-rw-r--r--src/com/android/bluetooth/a2dp/A2dpStateMachine.java8
-rw-r--r--src/com/android/bluetooth/avrcp/Avrcp.java27
-rw-r--r--src/com/android/bluetooth/avrcp/AvrcpControllerService.java5
-rw-r--r--src/com/android/bluetooth/btservice/AdapterService.java154
-rw-r--r--src/com/android/bluetooth/btservice/ProfileService.java34
-rw-r--r--src/com/android/bluetooth/gatt/AdvertiseManager.java90
-rw-r--r--src/com/android/bluetooth/gatt/ContextMap.java34
-rw-r--r--src/com/android/bluetooth/gatt/GattDebugUtils.java22
-rw-r--r--src/com/android/bluetooth/gatt/GattService.java113
-rw-r--r--src/com/android/bluetooth/gatt/HandleMap.java23
-rw-r--r--src/com/android/bluetooth/gatt/ScanManager.java3
-rw-r--r--src/com/android/bluetooth/hdp/HealthService.java17
-rw-r--r--src/com/android/bluetooth/hfp/HeadsetPhoneState.java116
-rw-r--r--src/com/android/bluetooth/hfp/HeadsetService.java9
-rw-r--r--src/com/android/bluetooth/hfp/HeadsetStateMachine.java36
-rw-r--r--src/com/android/bluetooth/hfpclient/HeadsetClientService.java8
-rw-r--r--src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java29
-rw-r--r--src/com/android/bluetooth/hid/HidService.java10
-rw-r--r--src/com/android/bluetooth/map/BluetoothMapContent.java286
-rw-r--r--src/com/android/bluetooth/map/BluetoothMapContentObserver.java222
-rwxr-xr-xsrc/com/android/bluetooth/map/BluetoothMapObexServer.java1
-rw-r--r--src/com/android/bluetooth/map/BluetoothMapService.java1
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppIncomingFileConfirmActivity.java6
-rwxr-xr-xsrc/com/android/bluetooth/pan/PanService.java35
-rw-r--r--src/com/android/bluetooth/util/NumberUtils.java46
-rw-r--r--tests/src/com/android/bluetooth/gatt/GattServiceTest.java22
-rw-r--r--tests/src/com/android/bluetooth/util/NumberUtilsTest.java43
59 files changed, 1143 insertions, 568 deletions
diff --git a/jni/com_android_bluetooth_btservice_AdapterService.cpp b/jni/com_android_bluetooth_btservice_AdapterService.cpp
index b75ad1b7f..cb917976e 100644
--- a/jni/com_android_bluetooth_btservice_AdapterService.cpp
+++ b/jni/com_android_bluetooth_btservice_AdapterService.cpp
@@ -973,7 +973,7 @@ static jboolean cancelBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
return result;
}
-static jboolean isConnectedNative(JNIEnv* env, jobject obj, jbyteArray address) {
+static int getConnectionStateNative(JNIEnv* env, jobject obj, jbyteArray address) {
ALOGV("%s:",__FUNCTION__);
if (!sBluetoothInterface) return JNI_FALSE;
@@ -986,7 +986,7 @@ static jboolean isConnectedNative(JNIEnv* env, jobject obj, jbyteArray address)
int ret = sBluetoothInterface->get_connection_state((bt_bdaddr_t *)addr);
env->ReleaseByteArrayElements(address, addr, 0);
- return (ret != 0 ? JNI_TRUE : JNI_FALSE);
+ return ret;
}
static jboolean pinReplyNative(JNIEnv *env, jobject obj, jbyteArray address, jboolean accept,
@@ -1366,7 +1366,7 @@ static JNINativeMethod sMethods[] = {
{"createBondNative", "([BI)Z", (void*) createBondNative},
{"removeBondNative", "([B)Z", (void*) removeBondNative},
{"cancelBondNative", "([B)Z", (void*) cancelBondNative},
- {"isConnectedNative", "([B)Z", (void*) isConnectedNative},
+ {"getConnectionStateNative", "([B)I", (void*) getConnectionStateNative},
{"pinReplyNative", "([BZI[B)Z", (void*) pinReplyNative},
{"sspReplyNative", "([BIZI)Z", (void*) sspReplyNative},
{"getRemoteServicesNative", "([B)Z", (void*) getRemoteServicesNative},
diff --git a/jni/com_android_bluetooth_gatt.cpp b/jni/com_android_bluetooth_gatt.cpp
index 921ad83b3..02a0669bf 100644
--- a/jni/com_android_bluetooth_gatt.cpp
+++ b/jni/com_android_bluetooth_gatt.cpp
@@ -191,6 +191,7 @@ static jmethodID method_onAttributeWrite;
static jmethodID method_onExecuteWrite;
static jmethodID method_onNotificationSent;
static jmethodID method_onServerCongestion;
+static jmethodID method_onServerMtuChanged;
/**
* Static variables
@@ -774,6 +775,13 @@ void btgatts_congestion_cb(int conn_id, bool congested)
checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
}
+void btgatts_mtu_changed_cb(int conn_id, int mtu)
+{
+ CHECK_CALLBACK_ENV
+ sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServerMtuChanged, conn_id, mtu);
+ checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
+}
+
static const btgatt_server_callbacks_t sGattServerCallbacks = {
btgatts_register_app_cb,
btgatts_connection_cb,
@@ -789,7 +797,8 @@ static const btgatt_server_callbacks_t sGattServerCallbacks = {
btgatts_request_exec_write_cb,
btgatts_response_confirmation_cb,
btgatts_indication_sent_cb,
- btgatts_congestion_cb
+ btgatts_congestion_cb,
+ btgatts_mtu_changed_cb
};
/**
@@ -859,6 +868,7 @@ static void classInitNative(JNIEnv* env, jclass clazz) {
method_onExecuteWrite= env->GetMethodID(clazz, "onExecuteWrite", "(Ljava/lang/String;III)V");
method_onNotificationSent = env->GetMethodID(clazz, "onNotificationSent", "(II)V");
method_onServerCongestion = env->GetMethodID(clazz, "onServerCongestion", "(IZ)V");
+ method_onServerMtuChanged = env->GetMethodID(clazz, "onMtuChanged", "(II)V");
info("classInitNative: Success!");
}
@@ -1715,6 +1725,8 @@ static JNINativeMethod sAdvertiseMethods[] = {
{"gattClientUpdateAdvNative", "(IIIIIII)V", (void *) gattClientUpdateAdvNative},
{"gattClientSetAdvDataNative", "(IZZZI[B[B[B)V", (void *) gattClientSetAdvDataNative},
{"gattClientDisableAdvNative", "(I)V", (void *) gattClientDisableAdvNative},
+ {"gattSetAdvDataNative", "(IZZZIII[B[B[B)V", (void *) gattSetAdvDataNative},
+ {"gattAdvertiseNative", "(IZ)V", (void *) gattAdvertiseNative},
};
// JNI functions defined in ScanManager class.
@@ -1758,7 +1770,6 @@ static JNINativeMethod sMethods[] = {
{"gattClientExecuteWriteNative", "(IZ)V", (void *) gattClientExecuteWriteNative},
{"gattClientRegisterForNotificationsNative", "(ILjava/lang/String;IIJJIJJZ)V", (void *) gattClientRegisterForNotificationsNative},
{"gattClientReadRemoteRssiNative", "(ILjava/lang/String;)V", (void *) gattClientReadRemoteRssiNative},
- {"gattAdvertiseNative", "(IZ)V", (void *) gattAdvertiseNative},
{"gattClientConfigureMTUNative", "(II)V", (void *) gattClientConfigureMTUNative},
{"gattConnectionParameterUpdateNative", "(ILjava/lang/String;IIII)V", (void *) gattConnectionParameterUpdateNative},
{"gattServerRegisterAppNative", "(JJ)V", (void *) gattServerRegisterAppNative},
@@ -1776,7 +1787,6 @@ static JNINativeMethod sMethods[] = {
{"gattServerSendNotificationNative", "(III[B)V", (void *) gattServerSendNotificationNative},
{"gattServerSendResponseNative", "(IIIIII[BI)V", (void *) gattServerSendResponseNative},
- {"gattSetAdvDataNative", "(IZZZIII[B[B[B)V", (void *) gattSetAdvDataNative},
{"gattTestNative", "(IJJLjava/lang/String;IIIII)V", (void *) gattTestNative},
};
diff --git a/res/values-bn-rBD/strings.xml b/res/values-bn-rBD/strings.xml
index ebf586c06..a4e297674 100644
--- a/res/values-bn-rBD/strings.xml
+++ b/res/values-bn-rBD/strings.xml
@@ -31,7 +31,7 @@
<string name="bt_enable_cancel" msgid="1988832367505151727">"বাতিল করুন"</string>
<string name="bt_enable_ok" msgid="3432462749994538265">"চালু করুন"</string>
<string name="incoming_file_confirm_title" msgid="8139874248612182627">"ফাইল স্থানান্তর"</string>
- <string name="incoming_file_confirm_content" msgid="2752605552743148036">"আগত ফাইল স্বীকার করবেন?"</string>
+ <string name="incoming_file_confirm_content" msgid="6673812334377911289">"\"<xliff:g id="SENDER">%1$s</xliff:g>\" আপনাকে <xliff:g id="FILE">%2$s</xliff:g>(<xliff:g id="SIZE">%3$s</xliff:g>) পাঠাতে চাইছে। \n\n ফাইলটি গ্রহণ করবেন?"</string>
<string name="incoming_file_confirm_cancel" msgid="2973321832477704805">"অস্বীকার করুন"</string>
<string name="incoming_file_confirm_ok" msgid="281462442932231475">"স্বীকার করুন"</string>
<string name="incoming_file_confirm_timeout_ok" msgid="1414676773249857278">"ঠিক আছে"</string>
@@ -54,9 +54,6 @@
<string name="download_line5" msgid="3069560415845295386">"ফাইল প্রাপ্ত হচ্ছে…"</string>
<string name="download_cancel" msgid="9177305996747500768">"থামান"</string>
<string name="download_ok" msgid="5000360731674466039">"লুকান"</string>
- <string name="incoming_line1" msgid="2127419875681087545">"প্রেরক"</string>
- <string name="incoming_line2" msgid="3348994249285315873">"ফাইলের নাম"</string>
- <string name="incoming_line3" msgid="7954237069667474024">"আকার"</string>
<string name="download_fail_line1" msgid="3846450148862894552">"ফাইল প্রাপ্ত করা যায়নি"</string>
<string name="download_fail_line2" msgid="8950394574689971071">"ফাইল: <xliff:g id="FILE">%1$s</xliff:g>"</string>
<string name="download_fail_line3" msgid="3451040656154861722">"কারণ: <xliff:g id="REASON">%1$s</xliff:g>"</string>
diff --git a/res/values-eu-rES/strings.xml b/res/values-eu-rES/strings.xml
index e8a60a199..833b7d8c9 100644
--- a/res/values-eu-rES/strings.xml
+++ b/res/values-eu-rES/strings.xml
@@ -20,7 +20,7 @@
<string name="permdesc_bluetoothShareManager" msgid="8930572979123190223">"Bluetooth bidezko partekatzeen kudeatzailea atzitzea eta fitxategiak transferitzeko erabiltzea baimentzen die aplikazioei."</string>
<string name="permlab_bluetoothWhitelist" msgid="7091552898592306386">"Sartu sarbidedunen zerrendan Bluetooth gailua."</string>
<string name="permdesc_bluetoothWhitelist" msgid="5494513855192170109">"Bluetooth gailu bat aldi baterako sarbidedunen zerrendan sartzea baimentzen die aplikazioei, gailu honetara fitxategiak bidaltzeko baimena izan dezan, baina gailu honen erabiltzaileari berrespena eskatu beharrik gabe."</string>
- <string name="bt_share_picker_label" msgid="6268100924487046932">"Bluetooth"</string>
+ <string name="bt_share_picker_label" msgid="6268100924487046932">"Bluetootha"</string>
<string name="unknown_device" msgid="9221903979877041009">"Gailu ezezaguna"</string>
<string name="unknownNumber" msgid="4994750948072751566">"Ezezaguna"</string>
<string name="airplane_error_title" msgid="2683839635115739939">"Hegaldi modua"</string>
@@ -31,7 +31,7 @@
<string name="bt_enable_cancel" msgid="1988832367505151727">"Utzi"</string>
<string name="bt_enable_ok" msgid="3432462749994538265">"Aktibatu"</string>
<string name="incoming_file_confirm_title" msgid="8139874248612182627">"Fitxategi-transferentzia"</string>
- <string name="incoming_file_confirm_content" msgid="2752605552743148036">"Sarrerako fitxategia onartu nahi duzu?"</string>
+ <string name="incoming_file_confirm_content" msgid="6673812334377911289">"\"<xliff:g id="SENDER">%1$s</xliff:g>\" igorleak <xliff:g id="FILE">%2$s</xliff:g> fitxategia bidali nahi dizu (<xliff:g id="SIZE">%3$s</xliff:g>).\n\nFitxategia onartu nahi duzu?"</string>
<string name="incoming_file_confirm_cancel" msgid="2973321832477704805">"Baztertu"</string>
<string name="incoming_file_confirm_ok" msgid="281462442932231475">"Onartu"</string>
<string name="incoming_file_confirm_timeout_ok" msgid="1414676773249857278">"Ados"</string>
@@ -54,9 +54,6 @@
<string name="download_line5" msgid="3069560415845295386">"Fitxategia jasotzen…"</string>
<string name="download_cancel" msgid="9177305996747500768">"Gelditu"</string>
<string name="download_ok" msgid="5000360731674466039">"Ezkutatu"</string>
- <string name="incoming_line1" msgid="2127419875681087545">"Igorlea"</string>
- <string name="incoming_line2" msgid="3348994249285315873">"Fitxategi-izena"</string>
- <string name="incoming_line3" msgid="7954237069667474024">"Tamaina"</string>
<string name="download_fail_line1" msgid="3846450148862894552">"Ez da fitxategia jaso"</string>
<string name="download_fail_line2" msgid="8950394574689971071">"Fitxategia: <xliff:g id="FILE">%1$s</xliff:g>"</string>
<string name="download_fail_line3" msgid="3451040656154861722">"Arrazoia: <xliff:g id="REASON">%1$s</xliff:g>"</string>
diff --git a/res/values-gl-rES/strings.xml b/res/values-gl-rES/strings.xml
index 45aa484cf..f3b207c55 100644
--- a/res/values-gl-rES/strings.xml
+++ b/res/values-gl-rES/strings.xml
@@ -31,7 +31,7 @@
<string name="bt_enable_cancel" msgid="1988832367505151727">"Cancelar"</string>
<string name="bt_enable_ok" msgid="3432462749994538265">"Activar"</string>
<string name="incoming_file_confirm_title" msgid="8139874248612182627">"Transferencia de ficheiros"</string>
- <string name="incoming_file_confirm_content" msgid="2752605552743148036">"Queres aceptar o ficheiro entrante?"</string>
+ <string name="incoming_file_confirm_content" msgid="6673812334377911289">"\"<xliff:g id="SENDER">%1$s</xliff:g>\" quere enviarche <xliff:g id="FILE">%2$s</xliff:g> (<xliff:g id="SIZE">%3$s</xliff:g>). \n\n Queres aceptar o ficheiro?"</string>
<string name="incoming_file_confirm_cancel" msgid="2973321832477704805">"Rexeitar"</string>
<string name="incoming_file_confirm_ok" msgid="281462442932231475">"Aceptar"</string>
<string name="incoming_file_confirm_timeout_ok" msgid="1414676773249857278">"Aceptar"</string>
@@ -54,9 +54,6 @@
<string name="download_line5" msgid="3069560415845295386">"Recibindo ficheiro..."</string>
<string name="download_cancel" msgid="9177305996747500768">"Deter"</string>
<string name="download_ok" msgid="5000360731674466039">"Ocultar"</string>
- <string name="incoming_line1" msgid="2127419875681087545">"De"</string>
- <string name="incoming_line2" msgid="3348994249285315873">"Nome do ficheiro"</string>
- <string name="incoming_line3" msgid="7954237069667474024">"Tamaño"</string>
<string name="download_fail_line1" msgid="3846450148862894552">"Ficheiro non recibido"</string>
<string name="download_fail_line2" msgid="8950394574689971071">"Ficheiro: <xliff:g id="FILE">%1$s</xliff:g>"</string>
<string name="download_fail_line3" msgid="3451040656154861722">"Motivo: <xliff:g id="REASON">%1$s</xliff:g>"</string>
diff --git a/res/values-hi/test_strings.xml b/res/values-hi/test_strings.xml
index 80aa68024..5c491802f 100644
--- a/res/values-hi/test_strings.xml
+++ b/res/values-hi/test_strings.xml
@@ -4,7 +4,7 @@
<string name="hello" msgid="1740533743008967039">"नमस्ते दुनिया, परीक्षण गतिविधि"</string>
<string name="app_name" msgid="1203877025577761792">"ब्लूटूथ शेयर"</string>
<string name="insert_record" msgid="1450997173838378132">"रिकॉर्ड सम्मिलित करें"</string>
- <string name="update_record" msgid="2480425402384910635">"रिकॉर्ड की दुबारा पूछें"</string>
+ <string name="update_record" msgid="2480425402384910635">"रिकॉर्ड की पुष्टि करें"</string>
<string name="ack_record" msgid="6716152390978472184">"रिकॉर्ड अभिस्वीकृत करें"</string>
<string name="deleteAll_record" msgid="4383349788485210582">"सभी रिकॉर्ड हटाएं"</string>
<string name="ok_button" msgid="6519033415223065454">"ठीक है"</string>
diff --git a/res/values-is-rIS/strings.xml b/res/values-is-rIS/strings.xml
index 401edd294..9285fca98 100644
--- a/res/values-is-rIS/strings.xml
+++ b/res/values-is-rIS/strings.xml
@@ -31,7 +31,7 @@
<string name="bt_enable_cancel" msgid="1988832367505151727">"Hætta við"</string>
<string name="bt_enable_ok" msgid="3432462749994538265">"Kveikja"</string>
<string name="incoming_file_confirm_title" msgid="8139874248612182627">"Skráaflutningur"</string>
- <string name="incoming_file_confirm_content" msgid="2752605552743148036">"Samþykkja skrá sem berst?"</string>
+ <string name="incoming_file_confirm_content" msgid="6673812334377911289">"„<xliff:g id="SENDER">%1$s</xliff:g>“ vill senda þér <xliff:g id="FILE">%2$s</xliff:g> (<xliff:g id="SIZE">%3$s</xliff:g>). \n\n Samþykkja þessa skrá?"</string>
<string name="incoming_file_confirm_cancel" msgid="2973321832477704805">"Hafna"</string>
<string name="incoming_file_confirm_ok" msgid="281462442932231475">"Samþykkja"</string>
<string name="incoming_file_confirm_timeout_ok" msgid="1414676773249857278">"Í lagi"</string>
@@ -54,9 +54,6 @@
<string name="download_line5" msgid="3069560415845295386">"Tekur á móti skrá…"</string>
<string name="download_cancel" msgid="9177305996747500768">"Stöðva"</string>
<string name="download_ok" msgid="5000360731674466039">"Fela"</string>
- <string name="incoming_line1" msgid="2127419875681087545">"Frá"</string>
- <string name="incoming_line2" msgid="3348994249285315873">"Skráarheiti"</string>
- <string name="incoming_line3" msgid="7954237069667474024">"Stærð"</string>
<string name="download_fail_line1" msgid="3846450148862894552">"Skrá ekki móttekin"</string>
<string name="download_fail_line2" msgid="8950394574689971071">"Skrá: <xliff:g id="FILE">%1$s</xliff:g>"</string>
<string name="download_fail_line3" msgid="3451040656154861722">"Ástæða: <xliff:g id="REASON">%1$s</xliff:g>"</string>
diff --git a/res/values-kk-rKZ/strings.xml b/res/values-kk-rKZ/strings.xml
index c342f1732..cb4991430 100644
--- a/res/values-kk-rKZ/strings.xml
+++ b/res/values-kk-rKZ/strings.xml
@@ -31,7 +31,7 @@
<string name="bt_enable_cancel" msgid="1988832367505151727">"Өшіру"</string>
<string name="bt_enable_ok" msgid="3432462749994538265">"Қосу"</string>
<string name="incoming_file_confirm_title" msgid="8139874248612182627">"Файл жіберу"</string>
- <string name="incoming_file_confirm_content" msgid="2752605552743148036">"Кіріс файлды қабылдау керек пе?"</string>
+ <string name="incoming_file_confirm_content" msgid="6673812334377911289">"\"<xliff:g id="SENDER">%1$s</xliff:g>\" сізге <xliff:g id="FILE">%2$s</xliff:g> (<xliff:g id="SIZE">%3$s</xliff:g>) жіберуді қалайды. \n\n Файл қабылдансын ба?"</string>
<string name="incoming_file_confirm_cancel" msgid="2973321832477704805">"Бас тарту"</string>
<string name="incoming_file_confirm_ok" msgid="281462442932231475">"Қабылдау"</string>
<string name="incoming_file_confirm_timeout_ok" msgid="1414676773249857278">"Жарайды"</string>
@@ -54,9 +54,6 @@
<string name="download_line5" msgid="3069560415845295386">"Файлды қабылдауда…"</string>
<string name="download_cancel" msgid="9177305996747500768">"Тоқтату"</string>
<string name="download_ok" msgid="5000360731674466039">"Жасыру"</string>
- <string name="incoming_line1" msgid="2127419875681087545">"Кімнен"</string>
- <string name="incoming_line2" msgid="3348994249285315873">"Файл атауы"</string>
- <string name="incoming_line3" msgid="7954237069667474024">"Өлшем"</string>
<string name="download_fail_line1" msgid="3846450148862894552">"Файл қабылданбады"</string>
<string name="download_fail_line2" msgid="8950394574689971071">"Файл: <xliff:g id="FILE">%1$s</xliff:g>"</string>
<string name="download_fail_line3" msgid="3451040656154861722">"Себеп: <xliff:g id="REASON">%1$s</xliff:g>"</string>
diff --git a/res/values-km-rKH/strings.xml b/res/values-km-rKH/strings.xml
index 769567b34..e53db4b41 100644
--- a/res/values-km-rKH/strings.xml
+++ b/res/values-km-rKH/strings.xml
@@ -28,13 +28,13 @@
<string name="bt_enable_title" msgid="8657832550503456572"></string>
<string name="bt_enable_line1" msgid="7203551583048149">"ដើម្បី​ប្រើ​​សេវា​ប៊្លូ​ធូ​ស ​ជា​ដំបូង​អ្នក​ត្រូវ​តែ​បើក​​ប៊្លូ​ធូ​ស​សិន​។"</string>
<string name="bt_enable_line2" msgid="4341936569415937994">"បើក​ប៊្លូធូស​ឥឡូវ​នេះ?"</string>
- <string name="bt_enable_cancel" msgid="1988832367505151727">"បោះ​បង់​"</string>
+ <string name="bt_enable_cancel" msgid="1988832367505151727">"បោះ​បង់"</string>
<string name="bt_enable_ok" msgid="3432462749994538265">"បើក"</string>
<string name="incoming_file_confirm_title" msgid="8139874248612182627">"ការ​ផ្ទេរ​ឯកសារ"</string>
<string name="incoming_file_confirm_content" msgid="2752605552743148036">"ទទួល​ឯកសារ​ចូល?"</string>
<string name="incoming_file_confirm_cancel" msgid="2973321832477704805">"បោះបង់"</string>
<string name="incoming_file_confirm_ok" msgid="281462442932231475">"ទទួល"</string>
- <string name="incoming_file_confirm_timeout_ok" msgid="1414676773249857278">"យល់​ព្រម​"</string>
+ <string name="incoming_file_confirm_timeout_ok" msgid="1414676773249857278">"យល់​ព្រម"</string>
<string name="incoming_file_confirm_timeout_content" msgid="172779756093975981">"អស់​ពេល​ទទួល​​ឯកសារ​ចូល​ពី \"<xliff:g id="SENDER">%1$s</xliff:g>\""</string>
<string name="incoming_file_confirm_Notification_title" msgid="2958227698135117210">"ការ​ចែក​រំលែក​ប៊្លូ​ធូ​ស៖ ឯកសារ​ចូល"</string>
<string name="incoming_file_confirm_Notification_caption" msgid="6671081128475981157">"តើ​អ្នក​ចង់​ទទួល​ឯកសារ​នេះ​ឬ​?"</string>
@@ -60,19 +60,19 @@
<string name="download_fail_line1" msgid="3846450148862894552">"មិន​​បាន​ទទួល​​​ឯកសារ"</string>
<string name="download_fail_line2" msgid="8950394574689971071">"ឯកសារ៖ <xliff:g id="FILE">%1$s</xliff:g>"</string>
<string name="download_fail_line3" msgid="3451040656154861722">"មូលហេតុ៖ <xliff:g id="REASON">%1$s</xliff:g>"</string>
- <string name="download_fail_ok" msgid="1521733664438320300">"យល់​ព្រម​"</string>
+ <string name="download_fail_ok" msgid="1521733664438320300">"យល់​ព្រម"</string>
<string name="download_succ_line5" msgid="4509944688281573595">"បាន​ទទួល​​ឯកសារ"</string>
<string name="download_succ_ok" msgid="7053688246357050216">"បើក"</string>
<string name="upload_line1" msgid="2055952074059709052">"ទៅ៖ \"<xliff:g id="RECIPIENT">%1$s</xliff:g>\""</string>
<string name="upload_line3" msgid="4920689672457037437">"ប្រភេទ​ឯកសារ៖ <xliff:g id="TYPE">%1$s</xliff:g> (<xliff:g id="SIZE">%2$s</xliff:g>)"</string>
<string name="upload_line5" msgid="7759322537674229752">"កំពុង​ផ្ញើ​ឯកសារ…"</string>
<string name="upload_succ_line5" msgid="5687317197463383601">"បាន​ផ្ញើ​ឯកសារ"</string>
- <string name="upload_succ_ok" msgid="7705428476405478828">"យល់​ព្រម​"</string>
+ <string name="upload_succ_ok" msgid="7705428476405478828">"យល់​ព្រម"</string>
<string name="upload_fail_line1" msgid="7899394672421491701">"មិន​បាន​ផ្ញើ​ឯកសារ​ទៅ \"<xliff:g id="RECIPIENT">%1$s</xliff:g>\" ។"</string>
<string name="upload_fail_line1_2" msgid="2108129204050841798">"ឯកសារ៖ <xliff:g id="FILE">%1$s</xliff:g>"</string>
<string name="upload_fail_ok" msgid="5807702461606714296">"ព្យាយាម​ម្ដង​ទៀត"</string>
- <string name="upload_fail_cancel" msgid="9118496285835687125">"បិទ​"</string>
- <string name="bt_error_btn_ok" msgid="5965151173011534240">"យល់​ព្រម​"</string>
+ <string name="upload_fail_cancel" msgid="9118496285835687125">"បិទ"</string>
+ <string name="bt_error_btn_ok" msgid="5965151173011534240">"យល់​ព្រម"</string>
<string name="unknown_file" msgid="6092727753965095366">"មិន​ស្គាល់​ឯកសារ"</string>
<string name="unknown_file_desc" msgid="480434281415453287">"គ្មាន​កម្មវិធី​​សម្រាប់​គ្រប់គ្រង​ប្រភេទ​ឯកសារ​នេះ​ទេ។ \n"</string>
<string name="not_exist_file" msgid="3489434189599716133">"គ្មាន​ឯកសារ"</string>
diff --git a/res/values-kn-rIN/strings.xml b/res/values-kn-rIN/strings.xml
index 381fa7c2b..4eb017893 100644
--- a/res/values-kn-rIN/strings.xml
+++ b/res/values-kn-rIN/strings.xml
@@ -31,7 +31,7 @@
<string name="bt_enable_cancel" msgid="1988832367505151727">"ರದ್ದುಮಾಡು"</string>
<string name="bt_enable_ok" msgid="3432462749994538265">"ಆನ್ ಮಾಡು"</string>
<string name="incoming_file_confirm_title" msgid="8139874248612182627">"ಫೈಲ್ ವರ್ಗಾವಣೆ"</string>
- <string name="incoming_file_confirm_content" msgid="2752605552743148036">"ಒಳಬರುವ ಫೈಲ್‌ಗಳನ್ನು ಸ್ವೀಕರಿಸುವುದೇ?"</string>
+ <string name="incoming_file_confirm_content" msgid="6673812334377911289">"\"<xliff:g id="SENDER">%1$s</xliff:g>\" ಅವರು <xliff:g id="FILE">%2$s</xliff:g> (<xliff:g id="SIZE">%3$s</xliff:g>) ಅನ್ನು ನಿಮಗೆ ಕಳುಹಿಸಲು ಬಯಸುತ್ತಾರೆ. \n\n ಫೈಲ್‌ ಅನ್ನು ಸ್ವೀಕರಿಸುವುದೇ?"</string>
<string name="incoming_file_confirm_cancel" msgid="2973321832477704805">"ನಿರಾಕರಿಸಿ"</string>
<string name="incoming_file_confirm_ok" msgid="281462442932231475">"ಸ್ವೀಕರಿಸಿ"</string>
<string name="incoming_file_confirm_timeout_ok" msgid="1414676773249857278">"ಸರಿ"</string>
@@ -54,9 +54,6 @@
<string name="download_line5" msgid="3069560415845295386">"ಫೈಲ್‌ ಸ್ವೀಕರಿಸಲಾಗುತ್ತಿದೆ…"</string>
<string name="download_cancel" msgid="9177305996747500768">"ನಿಲ್ಲಿಸು"</string>
<string name="download_ok" msgid="5000360731674466039">"ಮರೆಮಾಡು"</string>
- <string name="incoming_line1" msgid="2127419875681087545">"ಇವರಿಂದ"</string>
- <string name="incoming_line2" msgid="3348994249285315873">"ಫೈಲ್‌ಹೆಸರು"</string>
- <string name="incoming_line3" msgid="7954237069667474024">"ಗಾತ್ರ"</string>
<string name="download_fail_line1" msgid="3846450148862894552">"ಫೈಲ್‌ ಸ್ವೀಕರಿಸಿಲ್ಲ"</string>
<string name="download_fail_line2" msgid="8950394574689971071">"ಫೈಲ್‌: <xliff:g id="FILE">%1$s</xliff:g>"</string>
<string name="download_fail_line3" msgid="3451040656154861722">"ಕಾರಣ: <xliff:g id="REASON">%1$s</xliff:g>"</string>
diff --git a/res/values-ky-rKG/strings.xml b/res/values-ky-rKG/strings.xml
index 497db3113..6ca5b6dde 100644
--- a/res/values-ky-rKG/strings.xml
+++ b/res/values-ky-rKG/strings.xml
@@ -31,7 +31,7 @@
<string name="bt_enable_cancel" msgid="1988832367505151727">"Айнуу"</string>
<string name="bt_enable_ok" msgid="3432462749994538265">"Жандыруу"</string>
<string name="incoming_file_confirm_title" msgid="8139874248612182627">"Файл өткөрүү"</string>
- <string name="incoming_file_confirm_content" msgid="2752605552743148036">"Келүүчү файл кабыл алынсынбы?"</string>
+ <string name="incoming_file_confirm_content" msgid="6673812334377911289">"\"<xliff:g id="SENDER">%1$s</xliff:g>\" сизге <xliff:g id="FILE">%2$s</xliff:g> (<xliff:g id="SIZE">%3$s</xliff:g>) файлын жөнөткүсү келип жатат. \n\n Файлды кабыл аласызбы?"</string>
<string name="incoming_file_confirm_cancel" msgid="2973321832477704805">"Баш тартуу"</string>
<string name="incoming_file_confirm_ok" msgid="281462442932231475">"Кабыл алуу"</string>
<string name="incoming_file_confirm_timeout_ok" msgid="1414676773249857278">"OK"</string>
@@ -54,9 +54,6 @@
<string name="download_line5" msgid="3069560415845295386">"Файл алынууда…"</string>
<string name="download_cancel" msgid="9177305996747500768">"Токтотуу"</string>
<string name="download_ok" msgid="5000360731674466039">"Жашыруу"</string>
- <string name="incoming_line1" msgid="2127419875681087545">"Кимден"</string>
- <string name="incoming_line2" msgid="3348994249285315873">"Файлдын аталышы"</string>
- <string name="incoming_line3" msgid="7954237069667474024">"Өлчөмү"</string>
<string name="download_fail_line1" msgid="3846450148862894552">"Файл алынган жок"</string>
<string name="download_fail_line2" msgid="8950394574689971071">"Файл: <xliff:g id="FILE">%1$s</xliff:g>"</string>
<string name="download_fail_line3" msgid="3451040656154861722">"Себеп: <xliff:g id="REASON">%1$s</xliff:g>"</string>
diff --git a/res/values-mk-rMK/strings.xml b/res/values-mk-rMK/strings.xml
index 1c19c9157..52c25214b 100644
--- a/res/values-mk-rMK/strings.xml
+++ b/res/values-mk-rMK/strings.xml
@@ -31,7 +31,7 @@
<string name="bt_enable_cancel" msgid="1988832367505151727">"Откажи"</string>
<string name="bt_enable_ok" msgid="3432462749994538265">"Вклучи"</string>
<string name="incoming_file_confirm_title" msgid="8139874248612182627">"Пренос на датотека"</string>
- <string name="incoming_file_confirm_content" msgid="2752605552743148036">"Да се прифати дојдовната датотека?"</string>
+ <string name="incoming_file_confirm_content" msgid="6673812334377911289">"„<xliff:g id="SENDER">%1$s</xliff:g>“ сака да ти испрати <xliff:g id="FILE">%2$s</xliff:g> (<xliff:g id="SIZE">%3$s</xliff:g>). \n \nПрифати датотеката?"</string>
<string name="incoming_file_confirm_cancel" msgid="2973321832477704805">"Одбиј"</string>
<string name="incoming_file_confirm_ok" msgid="281462442932231475">"Прифати"</string>
<string name="incoming_file_confirm_timeout_ok" msgid="1414676773249857278">"Во ред"</string>
@@ -54,9 +54,6 @@
<string name="download_line5" msgid="3069560415845295386">"Примање датотеки..."</string>
<string name="download_cancel" msgid="9177305996747500768">"Запри"</string>
<string name="download_ok" msgid="5000360731674466039">"Сокриј"</string>
- <string name="incoming_line1" msgid="2127419875681087545">"Од"</string>
- <string name="incoming_line2" msgid="3348994249285315873">"Име на датотека"</string>
- <string name="incoming_line3" msgid="7954237069667474024">"Големина"</string>
<string name="download_fail_line1" msgid="3846450148862894552">"Датотеката не е примена"</string>
<string name="download_fail_line2" msgid="8950394574689971071">"Датотека: <xliff:g id="FILE">%1$s</xliff:g>"</string>
<string name="download_fail_line3" msgid="3451040656154861722">"Причина: <xliff:g id="REASON">%1$s</xliff:g>"</string>
diff --git a/res/values-ml-rIN/strings.xml b/res/values-ml-rIN/strings.xml
index 809e4b36b..94166a4a7 100644
--- a/res/values-ml-rIN/strings.xml
+++ b/res/values-ml-rIN/strings.xml
@@ -18,34 +18,34 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="permlab_bluetoothShareManager" msgid="311492132450338925">"ഡൗൺലോഡ് മാനേജർ ആക്‌സസ്സുചെയ്യുക."</string>
<string name="permdesc_bluetoothShareManager" msgid="8930572979123190223">"BluetoothShare മാനേജർ ആക്‌സസ്സുചെയ്യാനും ഫയലുകൾ കൈമാറാൻ അത് ഉപയോഗിക്കാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
- <string name="permlab_bluetoothWhitelist" msgid="7091552898592306386">"വൈറ്റ്‌ലിസ്റ്റ് ബ്ലൂടൂത്ത് ഉപകരണ ആക്‌സസ്സ്."</string>
- <string name="permdesc_bluetoothWhitelist" msgid="5494513855192170109">"ഒരു ബ്ലൂടൂത്ത് ഉപകരണം താൽക്കാലികമായി വൈറ്റ്‌ലിസ്റ്റുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു, അത് ഉപയോക്താവിന്റെ സ്ഥിരീകരണമില്ലാതെ ഈ ഉപകരണത്തിലേക്ക് ഫയലുകൾ അയയ്‌ക്കാൻ ആ ഉപകരണത്തെ അനുവദിക്കുന്നു."</string>
- <string name="bt_share_picker_label" msgid="6268100924487046932">"ബ്ലൂടൂത്ത്"</string>
+ <string name="permlab_bluetoothWhitelist" msgid="7091552898592306386">"വൈറ്റ്‌ലിസ്റ്റ് bluetooth ഉപകരണ ആക്‌സസ്സ്."</string>
+ <string name="permdesc_bluetoothWhitelist" msgid="5494513855192170109">"ഒരു Bluetooth ഉപകരണം താൽക്കാലികമായി വൈറ്റ്‌ലിസ്റ്റുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു, അത് ഉപയോക്താവിന്റെ സ്ഥിരീകരണമില്ലാതെ ഈ ഉപകരണത്തിലേക്ക് ഫയലുകൾ അയയ്‌ക്കാൻ ആ ഉപകരണത്തെ അനുവദിക്കുന്നു."</string>
+ <string name="bt_share_picker_label" msgid="6268100924487046932">"Bluetooth"</string>
<string name="unknown_device" msgid="9221903979877041009">"അജ്ഞാത ഉപകരണം"</string>
<string name="unknownNumber" msgid="4994750948072751566">"അജ്ഞാതം"</string>
<string name="airplane_error_title" msgid="2683839635115739939">"വിമാന മോഡ്"</string>
- <string name="airplane_error_msg" msgid="8698965595254137230">"നിങ്ങൾക്ക് വിമാന മോഡിൽ ബ്ലൂടൂത്ത് ഉപയോഗിക്കാനാകില്ല."</string>
+ <string name="airplane_error_msg" msgid="8698965595254137230">"നിങ്ങൾക്ക് വിമാന മോഡിൽ Bluetooth ഉപയോഗിക്കാനാകില്ല."</string>
<string name="bt_enable_title" msgid="8657832550503456572"></string>
- <string name="bt_enable_line1" msgid="7203551583048149">"ബ്ലൂടൂത്ത് സേവനങ്ങൾ ഉപയോഗിക്കാൻ, നിങ്ങൾ ആദ്യം ബ്ലൂടൂത്ത് ഓൺ ചെയ്യണം."</string>
- <string name="bt_enable_line2" msgid="4341936569415937994">"ഇപ്പോൾ ബ്ലൂടൂത്ത് ഓണാക്കണോ?"</string>
+ <string name="bt_enable_line1" msgid="7203551583048149">"Bluetooth സേവനങ്ങൾ ഉപയോഗിക്കാൻ, നിങ്ങൾ ആദ്യം Bluetooth ഓൺ ചെയ്യണം."</string>
+ <string name="bt_enable_line2" msgid="4341936569415937994">"ഇപ്പോൾ Bluetooth ഓണാക്കണോ?"</string>
<string name="bt_enable_cancel" msgid="1988832367505151727">"റദ്ദാക്കുക"</string>
<string name="bt_enable_ok" msgid="3432462749994538265">"ഓൺ ചെയ്യുക"</string>
<string name="incoming_file_confirm_title" msgid="8139874248612182627">"ഫയൽ കൈമാറൽ"</string>
- <string name="incoming_file_confirm_content" msgid="2752605552743148036">"ഇൻകമിംഗ് ഫയൽ അംഗീകരിക്കണോ?"</string>
+ <string name="incoming_file_confirm_content" msgid="6673812334377911289">"\"<xliff:g id="SENDER">%1$s</xliff:g>\", നിങ്ങൾക്ക് <xliff:g id="FILE">%2$s</xliff:g> (<xliff:g id="SIZE">%3$s</xliff:g>) അയയ്‌ക്കാൻ താൽപ്പര്യപ്പെടുന്നു. \n\n ഫയൽ സ്വീകരിക്കണോ?"</string>
<string name="incoming_file_confirm_cancel" msgid="2973321832477704805">"നിരസിക്കുക"</string>
<string name="incoming_file_confirm_ok" msgid="281462442932231475">"സ്വീകരിക്കുക"</string>
<string name="incoming_file_confirm_timeout_ok" msgid="1414676773249857278">"ശരി"</string>
<string name="incoming_file_confirm_timeout_content" msgid="172779756093975981">"\"<xliff:g id="SENDER">%1$s</xliff:g>\" എന്നയാളിൽ നിന്നും ഒരു ഇൻകമിംഗ് ഫയൽ സ്വീകരിക്കുമ്പോൾ ഒരു കാലഹരണപ്പെടൽ സംഭവിച്ചു"</string>
- <string name="incoming_file_confirm_Notification_title" msgid="2958227698135117210">"ബ്ലൂടൂത്ത് പങ്കിടൽ: ഇൻകമിംഗ് ഫയൽ"</string>
+ <string name="incoming_file_confirm_Notification_title" msgid="2958227698135117210">"Bluetooth പങ്കിടൽ: ഇൻകമിംഗ് ഫയൽ"</string>
<string name="incoming_file_confirm_Notification_caption" msgid="6671081128475981157">"നിങ്ങൾക്ക് ഈ ഫയൽ നേടണോ?"</string>
<string name="incoming_file_toast_msg" msgid="1733710749992901811">"മറ്റൊരു ഉപകരണത്തിൽ നിന്നുള്ള ഇൻകമിംഗ് ഫയൽ. ഈ ഫയൽ നിങ്ങൾക്ക് നേടണമെങ്കിൽ സ്ഥിരീകരിക്കുക."</string>
- <string name="notification_receiving" msgid="4674648179652543984">"ബ്ലൂടൂത്ത് പങ്കിടൽ: <xliff:g id="FILE">%1$s</xliff:g> എന്ന ഫയൽ ലഭിക്കുന്നു"</string>
- <string name="notification_received" msgid="3324588019186687985">"ബ്ലൂടൂത്ത് പങ്കിടൽ: <xliff:g id="FILE">%1$s</xliff:g> ലഭിച്ചു"</string>
- <string name="notification_received_fail" msgid="3619350997285714746">"ബ്ലൂടൂത്ത് പങ്കിടൽ: <xliff:g id="FILE">%1$s</xliff:g> എന്ന ഫയൽ ലഭിച്ചില്ല."</string>
- <string name="notification_sending" msgid="3035748958534983833">"ബ്ലൂടൂത്ത് പങ്കിടൽ: <xliff:g id="FILE">%1$s</xliff:g> എന്ന ഫയൽ അയയ്‌ക്കുന്നു"</string>
- <string name="notification_sent" msgid="9218710861333027778">"ബ്ലൂടൂത്ത് പങ്കിടൽ: <xliff:g id="FILE">%1$s</xliff:g> എന്ന ഫയൽ അയച്ചു"</string>
+ <string name="notification_receiving" msgid="4674648179652543984">"Bluetooth പങ്കിടൽ: <xliff:g id="FILE">%1$s</xliff:g> എന്ന ഫയൽ ലഭിക്കുന്നു"</string>
+ <string name="notification_received" msgid="3324588019186687985">"Bluetooth പങ്കിടൽ: <xliff:g id="FILE">%1$s</xliff:g> ലഭിച്ചു"</string>
+ <string name="notification_received_fail" msgid="3619350997285714746">"Bluetooth പങ്കിടൽ: <xliff:g id="FILE">%1$s</xliff:g> എന്ന ഫയൽ ലഭിച്ചില്ല."</string>
+ <string name="notification_sending" msgid="3035748958534983833">"Bluetooth പങ്കിടൽ: <xliff:g id="FILE">%1$s</xliff:g> എന്ന ഫയൽ അയയ്‌ക്കുന്നു"</string>
+ <string name="notification_sent" msgid="9218710861333027778">"Bluetooth പങ്കിടൽ: <xliff:g id="FILE">%1$s</xliff:g> എന്ന ഫയൽ അയച്ചു"</string>
<string name="notification_sent_complete" msgid="302943281067557969">"100% പൂർത്തിയായി"</string>
- <string name="notification_sent_fail" msgid="6696082233774569445">"ബ്ലൂടൂത്ത് പങ്കിടൽ: <xliff:g id="FILE">%1$s</xliff:g> എന്ന ഫയൽ അയച്ചില്ല"</string>
+ <string name="notification_sent_fail" msgid="6696082233774569445">"Bluetooth പങ്കിടൽ: <xliff:g id="FILE">%1$s</xliff:g> എന്ന ഫയൽ അയച്ചില്ല"</string>
<string name="download_title" msgid="3353228219772092586">"ഫയൽ കൈമാറൽ"</string>
<string name="download_line1" msgid="4926604799202134144">"അയച്ചത്: \"<xliff:g id="SENDER">%1$s</xliff:g>\""</string>
<string name="download_line2" msgid="5876973543019417712">"ഫയൽ: <xliff:g id="FILE">%1$s</xliff:g>"</string>
@@ -54,9 +54,6 @@
<string name="download_line5" msgid="3069560415845295386">"ഫയൽ നേടുന്നു…"</string>
<string name="download_cancel" msgid="9177305996747500768">"നിര്‍ത്തുക"</string>
<string name="download_ok" msgid="5000360731674466039">"മറയ്‌ക്കുക"</string>
- <string name="incoming_line1" msgid="2127419875681087545">"അയച്ചയാൾ"</string>
- <string name="incoming_line2" msgid="3348994249285315873">"ഫയല്‍നാമം"</string>
- <string name="incoming_line3" msgid="7954237069667474024">"വലുപ്പം"</string>
<string name="download_fail_line1" msgid="3846450148862894552">"ഫയൽ ലഭിച്ചില്ല"</string>
<string name="download_fail_line2" msgid="8950394574689971071">"ഫയൽ: <xliff:g id="FILE">%1$s</xliff:g>"</string>
<string name="download_fail_line3" msgid="3451040656154861722">"കാരണം: <xliff:g id="REASON">%1$s</xliff:g>"</string>
@@ -78,7 +75,7 @@
<string name="not_exist_file" msgid="3489434189599716133">"ഫയലൊന്നുമില്ല"</string>
<string name="not_exist_file_desc" msgid="4059531573790529229">"ഈ ഫയൽ നിലവിലില്ല. \n"</string>
<string name="enabling_progress_title" msgid="436157952334723406">"കാത്തിരിക്കുക…"</string>
- <string name="enabling_progress_content" msgid="4601542238119927904">"ബ്ലൂടൂത്ത് ഓൺ ചെയ്യുന്നു…"</string>
+ <string name="enabling_progress_content" msgid="4601542238119927904">"Bluetooth ഓൺ ചെയ്യുന്നു…"</string>
<string name="bt_toast_1" msgid="972182708034353383">"ഫയൽ ലഭിക്കും. അറിയിപ്പ് പാനലിൽ പുരോഗതി പരിശോധിക്കുക."</string>
<string name="bt_toast_2" msgid="8602553334099066582">"ഫയൽ നേടാനാകില്ല."</string>
<string name="bt_toast_3" msgid="6707884165086862518">"\"<xliff:g id="SENDER">%1$s</xliff:g>\" എന്നയാളിൽ നിന്നും ഫയൽ നേടുന്നത് നിർത്തി"</string>
@@ -101,15 +98,15 @@
<string name="status_connection_error" msgid="947681831523219891">"കണക്ഷൻ പരാജയപ്പെട്ടു."</string>
<string name="status_protocol_error" msgid="3245444473429269539">"അഭ്യർത്ഥന ശരിയായി കൈകാര്യം ചെയ്യാനാകില്ല."</string>
<string name="status_unknown_error" msgid="8156660554237824912">"അജ്ഞാത പിശക്."</string>
- <string name="btopp_live_folder" msgid="7967791481444474554">"ബ്ലൂടൂത്ത് ലഭിച്ചു"</string>
+ <string name="btopp_live_folder" msgid="7967791481444474554">"Bluetooth ലഭിച്ചു"</string>
<string name="download_success" msgid="7036160438766730871">"<xliff:g id="FILE_SIZE">%1$s</xliff:g> നേടൽ പൂർത്തിയായി."</string>
<string name="upload_success" msgid="4014469387779648949">"<xliff:g id="FILE_SIZE">%1$s</xliff:g> അയച്ചത് പൂർത്തിയായി."</string>
<string name="inbound_history_title" msgid="6940914942271327563">"ഇൻബൗണ്ട് കൈമാറലുകൾ"</string>
<string name="outbound_history_title" msgid="4279418703178140526">"ഔട്ട്‌ബൗണ്ട് കൈമാറലുകൾ"</string>
<string name="no_transfers" msgid="3482965619151865672">"കൈമാറൽ ചരിത്രം ശൂന്യമാണ്."</string>
<string name="transfer_clear_dlg_msg" msgid="1712376797268438075">"ലിസ്റ്റിൽ നിന്നും എല്ലാ ഇനങ്ങളും മായ്‌ക്കും."</string>
- <string name="outbound_noti_title" msgid="8051906709452260849">"ബ്ലൂടൂത്ത് പങ്കിടൽ: അയച്ച ഫയലുകൾ"</string>
- <string name="inbound_noti_title" msgid="4143352641953027595">"ബ്ലൂടൂത്ത് പങ്കിടൽ: ലഭിച്ച ഫയലുകൾ"</string>
+ <string name="outbound_noti_title" msgid="8051906709452260849">"Bluetooth പങ്കിടൽ: അയച്ച ഫയലുകൾ"</string>
+ <string name="inbound_noti_title" msgid="4143352641953027595">"Bluetooth പങ്കിടൽ: ലഭിച്ച ഫയലുകൾ"</string>
<string name="noti_caption" msgid="7508708288885707365">"<xliff:g id="SUCCESSFUL_NUMBER_0">%1$s</xliff:g> എണ്ണം വിജയകരം, <xliff:g id="UNSUCCESSFUL_NUMBER">%2$s</xliff:g> എണ്ണം പരാജയപ്പെട്ടു."</string>
<string name="transfer_menu_clear_all" msgid="790017462957873132">"ലിസ്റ്റ് മായ്‌ക്കുക"</string>
<string name="transfer_menu_open" msgid="3368984869083107200">"തുറക്കുക"</string>
@@ -117,9 +114,9 @@
<string name="transfer_clear_dlg_title" msgid="2953444575556460386">"മായ്‌ക്കുക"</string>
<string name="bluetooth_map_email_settings_save" msgid="5349902976213455385">"സംരക്ഷിക്കുക"</string>
<string name="bluetooth_map_email_settings_cancel" msgid="5019472404940038118">"റദ്ദാക്കുക"</string>
- <string name="bluetooth_map_email_settings_intro" msgid="6219461401455143988">"ബ്ലൂടൂത്ത് വഴി പങ്കിടേണ്ട ഇമെയിൽ അക്കൗണ്ടുകൾ തിരഞ്ഞെടുക്കുക. കണക്‌റ്റുചെയ്യുമ്പോൾ അക്കൗണ്ടുകളിലേക്കുള്ള എല്ലാ ആക്‌സസ്സും നിങ്ങൾ തുടർന്നും അംഗീകരിക്കേണ്ടതുണ്ട്."</string>
+ <string name="bluetooth_map_email_settings_intro" msgid="6219461401455143988">"Bluetooth വഴി പങ്കിടേണ്ട ഇമെയിൽ അക്കൗണ്ടുകൾ തിരഞ്ഞെടുക്കുക. കണക്‌റ്റുചെയ്യുമ്പോൾ അക്കൗണ്ടുകളിലേക്കുള്ള എല്ലാ ആക്‌സസ്സും നിങ്ങൾ തുടർന്നും അംഗീകരിക്കേണ്ടതുണ്ട്."</string>
<string name="bluetooth_map_email_settings_count" msgid="8884933619108905375">"ശേഷിക്കുന്ന സ്ലോട്ടുകൾ:"</string>
<string name="bluetooth_map_email_settings_app_icon" msgid="6905622365985483669">"അപ്ലിക്കേഷൻ ഐക്കൺ"</string>
- <string name="bluetooth_map_email_settings_title" msgid="2181388147513118336">"ബ്ലൂടൂത്ത് സന്ദേശം പങ്കിടൽ ക്രമീകരണങ്ങൾ"</string>
+ <string name="bluetooth_map_email_settings_title" msgid="2181388147513118336">"Bluetooth സന്ദേശം പങ്കിടൽ ക്രമീകരണങ്ങൾ"</string>
<string name="bluetooth_map_email_settings_no_account_slots_left" msgid="5989596869950397488">"അക്കൗണ്ട് തിരഞ്ഞെടുക്കാനാകില്ല. 0 സ്ലോട്ടുകൾ ശേഷിക്കുന്നു"</string>
</resources>
diff --git a/res/values-ml-rIN/strings_pbap.xml b/res/values-ml-rIN/strings_pbap.xml
index f6d8a12e4..3acf7fc7e 100644
--- a/res/values-ml-rIN/strings_pbap.xml
+++ b/res/values-ml-rIN/strings_pbap.xml
@@ -2,7 +2,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="pbap_session_key_dialog_title" msgid="3580996574333882561">"%1$s എന്നതിനുള്ള സെഷൻ കീ ടൈപ്പുചെയ്യുക"</string>
- <string name="pbap_session_key_dialog_header" msgid="2772472422782758981">"ബ്ലൂടൂത്ത് സെഷൻ കീ ആവശ്യമാണ്"</string>
+ <string name="pbap_session_key_dialog_header" msgid="2772472422782758981">"Bluetooth സെഷൻ കീ ആവശ്യമാണ്"</string>
<string name="pbap_acceptance_timeout_message" msgid="1107401415099814293">"%1$s എന്നതുമായുള്ള കണക്ഷൻ അംഗീകരിക്കുന്നത് കാലഹരണപ്പെട്ടു"</string>
<string name="pbap_authentication_timeout_message" msgid="4166979525521902687">"%1$s എന്നതിൽ സെഷൻ കീ നൽകുന്നത് കാലഹരണപ്പെട്ടു"</string>
<string name="auth_notif_ticker" msgid="1575825798053163744">"Obex പ്രാമാണീകരണ അഭ്യർത്ഥന"</string>
diff --git a/res/values-ml-rIN/test_strings.xml b/res/values-ml-rIN/test_strings.xml
index fe0a192d9..493e180f7 100644
--- a/res/values-ml-rIN/test_strings.xml
+++ b/res/values-ml-rIN/test_strings.xml
@@ -2,7 +2,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="hello" msgid="1740533743008967039">"ഹലോ ലോകമേ, TestActivity"</string>
- <string name="app_name" msgid="1203877025577761792">"ബ്ലൂടൂത്ത് പങ്കിടൽ"</string>
+ <string name="app_name" msgid="1203877025577761792">"Bluetooth പങ്കിടൽ"</string>
<string name="insert_record" msgid="1450997173838378132">"റെക്കോർഡ് ചേർക്കുക"</string>
<string name="update_record" msgid="2480425402384910635">"റെക്കോർഡ് സ്ഥിരീകരിക്കുക"</string>
<string name="ack_record" msgid="6716152390978472184">"Ack റെക്കോർഡ്"</string>
diff --git a/res/values-mr-rIN/strings.xml b/res/values-mr-rIN/strings.xml
index 53bb6255d..bb8ac599d 100644
--- a/res/values-mr-rIN/strings.xml
+++ b/res/values-mr-rIN/strings.xml
@@ -18,34 +18,34 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="permlab_bluetoothShareManager" msgid="311492132450338925">"डाउनलोड व्यवस्थापकावर प्रवेश करा."</string>
<string name="permdesc_bluetoothShareManager" msgid="8930572979123190223">"अ‍ॅपला BluetoothShare व्‍यवस्‍थापकामध्‍ये प्रवेश करण्‍याची आणि फायली स्‍थानांतरित करण्‍यासाठी त्याचा वापर करण्‍याची अनुमती देते."</string>
- <string name="permlab_bluetoothWhitelist" msgid="7091552898592306386">"श्वेतसूची ब्लूटूथ डिव्‍हाइस प्रवेश."</string>
- <string name="permdesc_bluetoothWhitelist" msgid="5494513855192170109">"अ‍ॅपला त्या डिव्‍हाइसला वापरकर्ता पुष्‍टीशिवाय या डिव्‍हासवर फायली पाठविण्‍याची अनुमती देऊन तात्पुरते ब डिव्‍हाइसला श्वेतसूची करण्‍याची अनुमती देते."</string>
- <string name="bt_share_picker_label" msgid="6268100924487046932">"ब"</string>
+ <string name="permlab_bluetoothWhitelist" msgid="7091552898592306386">"श्वेतसूची bluetooth डिव्‍हाइस प्रवेश."</string>
+ <string name="permdesc_bluetoothWhitelist" msgid="5494513855192170109">"अ‍ॅपला त्या डिव्‍हाइसला वापरकर्ता पुष्‍टीशिवाय या डिव्‍हासवर फायली पाठविण्‍याची अनुमती देऊन तात्पुरते Bluetooth डिव्‍हाइसला श्वेतसूची करण्‍याची अनुमती देते."</string>
+ <string name="bt_share_picker_label" msgid="6268100924487046932">"Bluetooth"</string>
<string name="unknown_device" msgid="9221903979877041009">"अज्ञात डिव्हाइस"</string>
<string name="unknownNumber" msgid="4994750948072751566">"अज्ञात"</string>
<string name="airplane_error_title" msgid="2683839635115739939">"विमान मोड"</string>
- <string name="airplane_error_msg" msgid="8698965595254137230">"आपण विमान मोड मध्ये ब वापरू शकत नाही."</string>
+ <string name="airplane_error_msg" msgid="8698965595254137230">"आपण विमान मोड मध्ये Bluetooth वापरू शकत नाही."</string>
<string name="bt_enable_title" msgid="8657832550503456572"></string>
- <string name="bt_enable_line1" msgid="7203551583048149">"ब सेवांचा वापर करण्‍यासाठी, आपण प्रथम ब चालू करा."</string>
- <string name="bt_enable_line2" msgid="4341936569415937994">"आता ब चालू करायचे?"</string>
+ <string name="bt_enable_line1" msgid="7203551583048149">"Bluetooth सेवांचा वापर करण्‍यासाठी, आपण प्रथम Bluetooth चालू करा."</string>
+ <string name="bt_enable_line2" msgid="4341936569415937994">"आता Bluetooth चालू करायचे?"</string>
<string name="bt_enable_cancel" msgid="1988832367505151727">"रद्द करा"</string>
<string name="bt_enable_ok" msgid="3432462749994538265">"चालू करा"</string>
<string name="incoming_file_confirm_title" msgid="8139874248612182627">"फाइल स्थानांतरण"</string>
- <string name="incoming_file_confirm_content" msgid="2752605552743148036">"येणारी फाईल स्‍वीकारायची?"</string>
+ <string name="incoming_file_confirm_content" msgid="6673812334377911289">"\"<xliff:g id="SENDER">%1$s</xliff:g>\" आपल्‍याला <xliff:g id="FILE">%2$s</xliff:g> (<xliff:g id="SIZE">%3$s</xliff:g>) पाठवू इच्‍छित आहे. \n\n फाइल स्‍वीकार करायची?"</string>
<string name="incoming_file_confirm_cancel" msgid="2973321832477704805">"नकार द्या"</string>
<string name="incoming_file_confirm_ok" msgid="281462442932231475">"स्वीकारा"</string>
<string name="incoming_file_confirm_timeout_ok" msgid="1414676773249857278">"ठीक"</string>
<string name="incoming_file_confirm_timeout_content" msgid="172779756093975981">"\"<xliff:g id="SENDER">%1$s</xliff:g>\" कडील फाइल स्‍वीकार करताना वेळ संपली."</string>
- <string name="incoming_file_confirm_Notification_title" msgid="2958227698135117210">"ब शेअर: येणारी फाइल"</string>
+ <string name="incoming_file_confirm_Notification_title" msgid="2958227698135117210">"Bluetooth शेअर: येणारी फाइल"</string>
<string name="incoming_file_confirm_Notification_caption" msgid="6671081128475981157">"आपण ही फाइल प्राप्त करू इच्छिता?"</string>
<string name="incoming_file_toast_msg" msgid="1733710749992901811">"दुसर्‍या डिव्‍हाइस वरील येणारी फाइल. ही फाइल आपण प्राप्त करू इच्‍छिता याची पुष्‍टी करा."</string>
- <string name="notification_receiving" msgid="4674648179652543984">"ब शेअर: <xliff:g id="FILE">%1$s</xliff:g> प्राप्त करीत आहे"</string>
- <string name="notification_received" msgid="3324588019186687985">"ब शेअर: <xliff:g id="FILE">%1$s</xliff:g> प्राप्त केली"</string>
- <string name="notification_received_fail" msgid="3619350997285714746">"ब शेअर: <xliff:g id="FILE">%1$s</xliff:g> फाइल प्राप्त केली नाही"</string>
- <string name="notification_sending" msgid="3035748958534983833">"ब शेअर: <xliff:g id="FILE">%1$s</xliff:g> पाठवित आहे"</string>
- <string name="notification_sent" msgid="9218710861333027778">"ब शेअर: <xliff:g id="FILE">%1$s</xliff:g> पाठविली"</string>
+ <string name="notification_receiving" msgid="4674648179652543984">"Bluetooth शेअर: <xliff:g id="FILE">%1$s</xliff:g> प्राप्त करीत आहे"</string>
+ <string name="notification_received" msgid="3324588019186687985">"Bluetooth शेअर: <xliff:g id="FILE">%1$s</xliff:g> प्राप्त केली"</string>
+ <string name="notification_received_fail" msgid="3619350997285714746">"Bluetooth शेअर: <xliff:g id="FILE">%1$s</xliff:g> फाइल प्राप्त केली नाही"</string>
+ <string name="notification_sending" msgid="3035748958534983833">"Bluetooth शेअर: <xliff:g id="FILE">%1$s</xliff:g> पाठवित आहे"</string>
+ <string name="notification_sent" msgid="9218710861333027778">"Bluetooth शेअर: <xliff:g id="FILE">%1$s</xliff:g> पाठविली"</string>
<string name="notification_sent_complete" msgid="302943281067557969">"100% पूर्ण"</string>
- <string name="notification_sent_fail" msgid="6696082233774569445">"ब शेअर: <xliff:g id="FILE">%1$s</xliff:g> फाइल पाठविली नाही"</string>
+ <string name="notification_sent_fail" msgid="6696082233774569445">"Bluetooth शेअर: <xliff:g id="FILE">%1$s</xliff:g> फाइल पाठविली नाही"</string>
<string name="download_title" msgid="3353228219772092586">"फाइल स्थानांतरण"</string>
<string name="download_line1" msgid="4926604799202134144">"प्रेेषक: \"<xliff:g id="SENDER">%1$s</xliff:g>\""</string>
<string name="download_line2" msgid="5876973543019417712">"फाइल: <xliff:g id="FILE">%1$s</xliff:g>"</string>
@@ -54,9 +54,6 @@
<string name="download_line5" msgid="3069560415845295386">"फाइल प्राप्त करीत आहे..."</string>
<string name="download_cancel" msgid="9177305996747500768">"थांबा"</string>
<string name="download_ok" msgid="5000360731674466039">"लपवा"</string>
- <string name="incoming_line1" msgid="2127419875681087545">"प्रेषक"</string>
- <string name="incoming_line2" msgid="3348994249285315873">"फाईलनाव"</string>
- <string name="incoming_line3" msgid="7954237069667474024">"आकार"</string>
<string name="download_fail_line1" msgid="3846450148862894552">"फाइल प्राप्त केली नाही"</string>
<string name="download_fail_line2" msgid="8950394574689971071">"फाइल: <xliff:g id="FILE">%1$s</xliff:g>"</string>
<string name="download_fail_line3" msgid="3451040656154861722">"कारण: <xliff:g id="REASON">%1$s</xliff:g>"</string>
@@ -78,7 +75,7 @@
<string name="not_exist_file" msgid="3489434189599716133">"फाइल नाही"</string>
<string name="not_exist_file_desc" msgid="4059531573790529229">"फाइल अस्‍तित्वात नाही. \n"</string>
<string name="enabling_progress_title" msgid="436157952334723406">"कृपया प्रतीक्षा करा..."</string>
- <string name="enabling_progress_content" msgid="4601542238119927904">"ब चालू करीत आहे…"</string>
+ <string name="enabling_progress_content" msgid="4601542238119927904">"Bluetooth चालू करीत आहे…"</string>
<string name="bt_toast_1" msgid="972182708034353383">"फाइल प्राप्त होईल. सूचना पॅनेल मधील प्रगती तपासा."</string>
<string name="bt_toast_2" msgid="8602553334099066582">"फाइल प्राप्त होऊ शकत नाही."</string>
<string name="bt_toast_3" msgid="6707884165086862518">"\"<xliff:g id="SENDER">%1$s</xliff:g>\" कडील फाइल प्राप्त करणे थांबविले"</string>
@@ -101,15 +98,15 @@
<string name="status_connection_error" msgid="947681831523219891">"कनेक्‍शन अयशस्‍वी."</string>
<string name="status_protocol_error" msgid="3245444473429269539">"विनंती योग्यरितीने हाताळली जाऊ शकत नाही."</string>
<string name="status_unknown_error" msgid="8156660554237824912">"अज्ञात त्रुटी."</string>
- <string name="btopp_live_folder" msgid="7967791481444474554">"ब प्राप्त केले"</string>
+ <string name="btopp_live_folder" msgid="7967791481444474554">"Bluetooth प्राप्त केले"</string>
<string name="download_success" msgid="7036160438766730871">"<xliff:g id="FILE_SIZE">%1$s</xliff:g> प्राप्त करणे पूर्ण."</string>
<string name="upload_success" msgid="4014469387779648949">"<xliff:g id="FILE_SIZE">%1$s</xliff:g> पाठविणे पूर्ण."</string>
<string name="inbound_history_title" msgid="6940914942271327563">"इनबाउंड स्‍थानांतरणे"</string>
<string name="outbound_history_title" msgid="4279418703178140526">"आउटबाउंड स्‍थानांतरणे"</string>
<string name="no_transfers" msgid="3482965619151865672">"स्‍थानांतरण इतिहास रिक्त आहे."</string>
<string name="transfer_clear_dlg_msg" msgid="1712376797268438075">"सूचीमधून सर्व आयटम साफ केले जातील."</string>
- <string name="outbound_noti_title" msgid="8051906709452260849">"ब शेअर: पाठविलेल्‍या फायली"</string>
- <string name="inbound_noti_title" msgid="4143352641953027595">"ब शेअर: प्राप्त केलेल्‍या फायली"</string>
+ <string name="outbound_noti_title" msgid="8051906709452260849">"Bluetooth शेअर: पाठविलेल्‍या फायली"</string>
+ <string name="inbound_noti_title" msgid="4143352641953027595">"Bluetooth शेअर: प्राप्त केलेल्‍या फायली"</string>
<string name="noti_caption" msgid="7508708288885707365">"<xliff:g id="SUCCESSFUL_NUMBER_0">%1$s</xliff:g> यशस्‍वी, <xliff:g id="UNSUCCESSFUL_NUMBER">%2$s</xliff:g> अयशस्‍वी."</string>
<string name="transfer_menu_clear_all" msgid="790017462957873132">"सूची साफ करा"</string>
<string name="transfer_menu_open" msgid="3368984869083107200">"उघडा"</string>
@@ -117,9 +114,9 @@
<string name="transfer_clear_dlg_title" msgid="2953444575556460386">"साफ करा"</string>
<string name="bluetooth_map_email_settings_save" msgid="5349902976213455385">"जतन करा"</string>
<string name="bluetooth_map_email_settings_cancel" msgid="5019472404940038118">"रद्द करा"</string>
- <string name="bluetooth_map_email_settings_intro" msgid="6219461401455143988">"आपण ब द्वारे सामायिक करू इच्छित असलेली ईमेल खाती निवडा. कनेक्‍ट करताना आपल्याला खात्यांवरील कोणतेही प्रवेश अद्याप स्वीकारावे लागतील."</string>
+ <string name="bluetooth_map_email_settings_intro" msgid="6219461401455143988">"आपण Bluetooth द्वारे सामायिक करू इच्छित असलेली ईमेल खाती निवडा. कनेक्‍ट करताना आपल्याला खात्यांवरील कोणतेही प्रवेश अद्याप स्वीकारावे लागतील."</string>
<string name="bluetooth_map_email_settings_count" msgid="8884933619108905375">"स्लॉट शिल्लक:"</string>
<string name="bluetooth_map_email_settings_app_icon" msgid="6905622365985483669">"अनुप्रयोग चिन्ह"</string>
- <string name="bluetooth_map_email_settings_title" msgid="2181388147513118336">"ब संदेश सामायिकरण सेटिंग्ज"</string>
+ <string name="bluetooth_map_email_settings_title" msgid="2181388147513118336">"Bluetooth संदेश सामायिकरण सेटिंग्ज"</string>
<string name="bluetooth_map_email_settings_no_account_slots_left" msgid="5989596869950397488">"खाते निवडू शकले नाही. 0 स्लॉट शिल्लक"</string>
</resources>
diff --git a/res/values-mr-rIN/strings_pbap.xml b/res/values-mr-rIN/strings_pbap.xml
index 57b3f1d48..9f7e71e71 100644
--- a/res/values-mr-rIN/strings_pbap.xml
+++ b/res/values-mr-rIN/strings_pbap.xml
@@ -2,7 +2,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="pbap_session_key_dialog_title" msgid="3580996574333882561">"%1$s साठी सत्र की टाईप करा"</string>
- <string name="pbap_session_key_dialog_header" msgid="2772472422782758981">"ब सत्र की आवश्‍यक आहे"</string>
+ <string name="pbap_session_key_dialog_header" msgid="2772472422782758981">"Bluetooth सत्र की आवश्‍यक आहे"</string>
<string name="pbap_acceptance_timeout_message" msgid="1107401415099814293">"%1$s सह कनेक्शन स्वीकारणे कालबाह्य झाले"</string>
<string name="pbap_authentication_timeout_message" msgid="4166979525521902687">"%1$s सह सत्र की इनपुट करणे कालबाह्य झाले"</string>
<string name="auth_notif_ticker" msgid="1575825798053163744">"Obex प्रमाणीकरण विनंती"</string>
diff --git a/res/values-mr-rIN/test_strings.xml b/res/values-mr-rIN/test_strings.xml
index 1650fc491..e3808851b 100644
--- a/res/values-mr-rIN/test_strings.xml
+++ b/res/values-mr-rIN/test_strings.xml
@@ -2,7 +2,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="hello" msgid="1740533743008967039">"हॅलो वर्ल्ड, TestActivity"</string>
- <string name="app_name" msgid="1203877025577761792">"ब शेअर"</string>
+ <string name="app_name" msgid="1203877025577761792">"Bluetooth शेअर"</string>
<string name="insert_record" msgid="1450997173838378132">"रेकॉर्ड घाला"</string>
<string name="update_record" msgid="2480425402384910635">"रेकॉर्डची पुष्टी करा"</string>
<string name="ack_record" msgid="6716152390978472184">"Ack रेकॉर्ड"</string>
diff --git a/res/values-my-rMM/strings.xml b/res/values-my-rMM/strings.xml
index aca9f3f8c..76101f37b 100644
--- a/res/values-my-rMM/strings.xml
+++ b/res/values-my-rMM/strings.xml
@@ -23,15 +23,15 @@
<string name="bt_share_picker_label" msgid="6268100924487046932">"ဘလူးတုသ်"</string>
<string name="unknown_device" msgid="9221903979877041009">"မသိသော စက်"</string>
<string name="unknownNumber" msgid="4994750948072751566">"အကြောင်းအရာ မသိရှိ"</string>
- <string name="airplane_error_title" msgid="2683839635115739939">"လေယာဉ်ပျံပေါ်သုံးစနစ်"</string>
+ <string name="airplane_error_title" msgid="2683839635115739939">"လေယာဉ်ပျံပေါ်အသုံးပြုစနစ်"</string>
<string name="airplane_error_msg" msgid="8698965595254137230">"လေယာဥ်ပျံပေါ်သုံးစနစ်တွင် ဘလူးတုသ်အသုံးပြုမရပါ"</string>
<string name="bt_enable_title" msgid="8657832550503456572"></string>
<string name="bt_enable_line1" msgid="7203551583048149">"ဘလူးတုသ်ဆားဗစ်ကိုအသုံးပြုရန် ပထမဦးစွာ ဘလူးတုသ်ကိုဖွင့်ပါ"</string>
<string name="bt_enable_line2" msgid="4341936569415937994">"ယခုပင် ဘလူးတုသ်ကိုဖွင့်မည်လား?"</string>
- <string name="bt_enable_cancel" msgid="1988832367505151727">"ထားတော့"</string>
+ <string name="bt_enable_cancel" msgid="1988832367505151727">"ပယ်ဖျက်သည်"</string>
<string name="bt_enable_ok" msgid="3432462749994538265">"ဖွင့်မည်"</string>
<string name="incoming_file_confirm_title" msgid="8139874248612182627">"ဖိုင်လွှဲပြောင်းခြင်း"</string>
- <string name="incoming_file_confirm_content" msgid="2752605552743148036">"ဝင်လာသည့် ဖိုင်ကို လက်ခံမလား?"</string>
+ <string name="incoming_file_confirm_content" msgid="6673812334377911289">"\"<xliff:g id="SENDER">%1$s</xliff:g>\" မှ သင်ထံပို့ချင်ပါသည်<xliff:g id="FILE">%2$s</xliff:g> (<xliff:g id="SIZE">%3$s</xliff:g>). \n\nဖိုင်ကိုလက်ခံမည်လား?"</string>
<string name="incoming_file_confirm_cancel" msgid="2973321832477704805">"လက်မခံပါ"</string>
<string name="incoming_file_confirm_ok" msgid="281462442932231475">"လက်ခံရန်"</string>
<string name="incoming_file_confirm_timeout_ok" msgid="1414676773249857278">"ကောင်းပြီ"</string>
@@ -54,9 +54,6 @@
<string name="download_line5" msgid="3069560415845295386">"ဖိုင် လက်ခံနေပြီ"</string>
<string name="download_cancel" msgid="9177305996747500768">"ရပ်ဆိုင်းရန်"</string>
<string name="download_ok" msgid="5000360731674466039">"ဖျောက်ထားမည်"</string>
- <string name="incoming_line1" msgid="2127419875681087545">"မှ"</string>
- <string name="incoming_line2" msgid="3348994249285315873">"ဖိုင်အမည်"</string>
- <string name="incoming_line3" msgid="7954237069667474024">"ဆိုက်"</string>
<string name="download_fail_line1" msgid="3846450148862894552">"ဖိုင် မရရှိပါ"</string>
<string name="download_fail_line2" msgid="8950394574689971071">"ဖိုင် - <xliff:g id="FILE">%1$s</xliff:g>"</string>
<string name="download_fail_line3" msgid="3451040656154861722">"အကြောင်းပြချက် - <xliff:g id="REASON">%1$s</xliff:g>"</string>
@@ -102,7 +99,7 @@
<string name="status_protocol_error" msgid="3245444473429269539">"တောင်းခံခြင်းကို မှန်ကန်စွာကိုင်တွယ်မရပါ"</string>
<string name="status_unknown_error" msgid="8156660554237824912">"အမည်မသိသော မှားယွင်းမှု"</string>
<string name="btopp_live_folder" msgid="7967791481444474554">"ဘလူးတုသ် လက်ခံရပြီး"</string>
- <string name="download_success" msgid="7036160438766730871">"<xliff:g id="FILE_SIZE">%1$s</xliff:g> လက်ခံရရှိပြီး"</string>
+ <string name="download_success" msgid="7036160438766730871">"<xliff:g id="FILE_SIZE">%1$s</xliff:g> လက်ခံရပြီး"</string>
<string name="upload_success" msgid="4014469387779648949">"<xliff:g id="FILE_SIZE">%1$s</xliff:g> ပို့ခြင်း ပြီးဆုံးပြီး"</string>
<string name="inbound_history_title" msgid="6940914942271327563">"ပြန်လည်ရောက်လာသော လွှဲမှုများ"</string>
<string name="outbound_history_title" msgid="4279418703178140526">"ပြန်လည်ထွက်မည့် လွှဲမှုများ"</string>
@@ -115,8 +112,8 @@
<string name="transfer_menu_open" msgid="3368984869083107200">"ဖွင့်ရန်"</string>
<string name="transfer_menu_clear" msgid="5854038118831427492">"စာရင်းမှ ရှင်းပစ်မည်"</string>
<string name="transfer_clear_dlg_title" msgid="2953444575556460386">"ရှင်းလင်းရန်"</string>
- <string name="bluetooth_map_email_settings_save" msgid="5349902976213455385">"သိမ်းပါ"</string>
- <string name="bluetooth_map_email_settings_cancel" msgid="5019472404940038118">"ထားတော့"</string>
+ <string name="bluetooth_map_email_settings_save" msgid="5349902976213455385">"သိမ်းဆည်းရန်"</string>
+ <string name="bluetooth_map_email_settings_cancel" msgid="5019472404940038118">"ပယ်ဖျက်ရန်"</string>
<string name="bluetooth_map_email_settings_intro" msgid="6219461401455143988">"သင်က ဘလူးတုသ် မှတစ်ဆင့် မျှဝေလိုသည့် အီးမေးလ် အကောင့်ကို ရွေးပါ။ သင်သည် အကောင့်အား ရယူသုံးလိုမှု မှန်သမျှကို ချိတ်ဆက်လာသည့် အခါမှာ လက်ခံပေးရန် လိုဦးမည်။"</string>
<string name="bluetooth_map_email_settings_count" msgid="8884933619108905375">"ကျန်နေသည့် အပေါက်များ:"</string>
<string name="bluetooth_map_email_settings_app_icon" msgid="6905622365985483669">"အပလီကေးရှင်း အိုင်ကွန်"</string>
diff --git a/res/values-ne-rNP/strings.xml b/res/values-ne-rNP/strings.xml
index f1966027d..225afc0e6 100644
--- a/res/values-ne-rNP/strings.xml
+++ b/res/values-ne-rNP/strings.xml
@@ -31,7 +31,7 @@
<string name="bt_enable_cancel" msgid="1988832367505151727">"रद्द गर्नुहोस्"</string>
<string name="bt_enable_ok" msgid="3432462749994538265">"सक्रिय पार्नुहोस्"</string>
<string name="incoming_file_confirm_title" msgid="8139874248612182627">"फाइल स्थानान्तरण"</string>
- <string name="incoming_file_confirm_content" msgid="2752605552743148036">"आगमन फाइल स्वीकार गर्नुहुन्छ?"</string>
+ <string name="incoming_file_confirm_content" msgid="6673812334377911289">"\" <xliff:g id="SENDER">%1$s</xliff:g>\" ले तपाईँलाई <xliff:g id="FILE">%2$s</xliff:g> ( <xliff:g id="SIZE">%3$s</xliff:g> )। \n \n पठाउन चाहन्छ। फाइल स्वीकार्ने हो?"</string>
<string name="incoming_file_confirm_cancel" msgid="2973321832477704805">"अस्वीकार गर्नुहोस्"</string>
<string name="incoming_file_confirm_ok" msgid="281462442932231475">"स्वीकार्नुहोस्"</string>
<string name="incoming_file_confirm_timeout_ok" msgid="1414676773249857278">"ठीक छ"</string>
@@ -54,9 +54,6 @@
<string name="download_line5" msgid="3069560415845295386">"फाइल प्राप्त गर्दै..."</string>
<string name="download_cancel" msgid="9177305996747500768">"रोक्नुहोस्"</string>
<string name="download_ok" msgid="5000360731674466039">"लुकाउनुहोस्"</string>
- <string name="incoming_line1" msgid="2127419875681087545">"प्रेषक"</string>
- <string name="incoming_line2" msgid="3348994249285315873">"फाइलको नाम"</string>
- <string name="incoming_line3" msgid="7954237069667474024">"आकार"</string>
<string name="download_fail_line1" msgid="3846450148862894552">"फाइल प्राप्त भएन"</string>
<string name="download_fail_line2" msgid="8950394574689971071">"फाइल: <xliff:g id="FILE">%1$s</xliff:g>"</string>
<string name="download_fail_line3" msgid="3451040656154861722">"कारण: <xliff:g id="REASON">%1$s</xliff:g>"</string>
diff --git a/res/values-si-rLK/strings.xml b/res/values-si-rLK/strings.xml
index 4d781b6ce..38b109be6 100644
--- a/res/values-si-rLK/strings.xml
+++ b/res/values-si-rLK/strings.xml
@@ -31,7 +31,7 @@
<string name="bt_enable_cancel" msgid="1988832367505151727">"අවලංගු කරන්න"</string>
<string name="bt_enable_ok" msgid="3432462749994538265">"ක්‍රියාත්මක කරන්න"</string>
<string name="incoming_file_confirm_title" msgid="8139874248612182627">"ගොනු මාරුව"</string>
- <string name="incoming_file_confirm_content" msgid="2752605552743148036">"ඇතුළට එන ගොනුව පිළිගන්නද?"</string>
+ <string name="incoming_file_confirm_content" msgid="6673812334377911289">"\"<xliff:g id="SENDER">%1$s</xliff:g>\" හට ඔබට <xliff:g id="FILE">%2$s</xliff:g> (<xliff:g id="SIZE">%3$s</xliff:g>) යැවීමට අවශ්‍යයි. \n\n ගොනුව පිළිගන්නද?"</string>
<string name="incoming_file_confirm_cancel" msgid="2973321832477704805">"ප්‍රතික්ෂේප කරන්න"</string>
<string name="incoming_file_confirm_ok" msgid="281462442932231475">"පිළිගන්න"</string>
<string name="incoming_file_confirm_timeout_ok" msgid="1414676773249857278">"හරි"</string>
@@ -54,9 +54,6 @@
<string name="download_line5" msgid="3069560415845295386">"ගොනුව ලැබේ…"</string>
<string name="download_cancel" msgid="9177305996747500768">"නතර කරන්න"</string>
<string name="download_ok" msgid="5000360731674466039">"සඟවන්න"</string>
- <string name="incoming_line1" msgid="2127419875681087545">"වෙතින්"</string>
- <string name="incoming_line2" msgid="3348994249285315873">"ගොනුවේ නම"</string>
- <string name="incoming_line3" msgid="7954237069667474024">"ප්‍රමාණය"</string>
<string name="download_fail_line1" msgid="3846450148862894552">"ගොනුව නොලැබිණි"</string>
<string name="download_fail_line2" msgid="8950394574689971071">"ගොනුව: <xliff:g id="FILE">%1$s</xliff:g>"</string>
<string name="download_fail_line3" msgid="3451040656154861722">"හේතුව: <xliff:g id="REASON">%1$s</xliff:g>"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 56e035dea..e6afecfba 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="permlab_bluetoothShareManager" msgid="311492132450338925">"Dostop do upravitelja prenosov."</string>
- <string name="permdesc_bluetoothShareManager" msgid="8930572979123190223">"Aplikaciji omogoča dostop do upravitelja BluetoothShare in njegovo uporabo za prenašanje datotek."</string>
+ <string name="permdesc_bluetoothShareManager" msgid="8930572979123190223">"Programu omogoča dostop do upravitelja BluetoothShare in njegovo uporabo za prenašanje datotek."</string>
<string name="permlab_bluetoothWhitelist" msgid="7091552898592306386">"Doda napravo Bluetooth na seznam z dovoljenim dostopom."</string>
<string name="permdesc_bluetoothWhitelist" msgid="5494513855192170109">"Aplikaciji omogoča, da začasno uvrsti napravo Bluetooth na seznam dovoljenih, kar omogoči napravi pošiljanje datotek v to napravo brez potrditve uporabnika."</string>
<string name="bt_share_picker_label" msgid="6268100924487046932">"Bluetooth"</string>
@@ -74,7 +74,7 @@
<string name="upload_fail_cancel" msgid="9118496285835687125">"Zapri"</string>
<string name="bt_error_btn_ok" msgid="5965151173011534240">"V redu"</string>
<string name="unknown_file" msgid="6092727753965095366">"Neznana datoteka"</string>
- <string name="unknown_file_desc" msgid="480434281415453287">"Ni aplikacije, s katero bi bilo mogoče odpreti to vrsto datoteke. \n"</string>
+ <string name="unknown_file_desc" msgid="480434281415453287">"Ni programa, s katerim bi bilo mogoče odpreti to vrsto datoteke. \n"</string>
<string name="not_exist_file" msgid="3489434189599716133">"Ni datoteke"</string>
<string name="not_exist_file_desc" msgid="4059531573790529229">"Datoteka ne obstaja. \n"</string>
<string name="enabling_progress_title" msgid="436157952334723406">"Počakajte ..."</string>
diff --git a/res/values-ta-rIN/strings.xml b/res/values-ta-rIN/strings.xml
index 0ce8b1c34..9651521d8 100644
--- a/res/values-ta-rIN/strings.xml
+++ b/res/values-ta-rIN/strings.xml
@@ -31,7 +31,7 @@
<string name="bt_enable_cancel" msgid="1988832367505151727">"ரத்துசெய்"</string>
<string name="bt_enable_ok" msgid="3432462749994538265">"இயக்கு"</string>
<string name="incoming_file_confirm_title" msgid="8139874248612182627">"கோப்பு பரிமாற்றம்"</string>
- <string name="incoming_file_confirm_content" msgid="2752605552743148036">"உள்வரும் கோப்பை ஏற்கவா?"</string>
+ <string name="incoming_file_confirm_content" msgid="6673812334377911289">"\"<xliff:g id="SENDER">%1$s</xliff:g>\", <xliff:g id="FILE">%2$s</xliff:g> (<xliff:g id="SIZE">%3$s</xliff:g>) ஐ விரும்புகிறார். \n\n கோப்பை ஏற்கவா?"</string>
<string name="incoming_file_confirm_cancel" msgid="2973321832477704805">"நிராகரி"</string>
<string name="incoming_file_confirm_ok" msgid="281462442932231475">"ஏற்கிறேன்"</string>
<string name="incoming_file_confirm_timeout_ok" msgid="1414676773249857278">"சரி"</string>
@@ -54,9 +54,6 @@
<string name="download_line5" msgid="3069560415845295386">"கோப்பைப் பெறுகிறது…"</string>
<string name="download_cancel" msgid="9177305996747500768">"நிறுத்து"</string>
<string name="download_ok" msgid="5000360731674466039">"மறை"</string>
- <string name="incoming_line1" msgid="2127419875681087545">"அனுப்புநர்"</string>
- <string name="incoming_line2" msgid="3348994249285315873">"கோப்புப்பெயர்"</string>
- <string name="incoming_line3" msgid="7954237069667474024">"அளவு"</string>
<string name="download_fail_line1" msgid="3846450148862894552">"கோப்பு பெறப்படவில்லை"</string>
<string name="download_fail_line2" msgid="8950394574689971071">"கோப்பு: <xliff:g id="FILE">%1$s</xliff:g>"</string>
<string name="download_fail_line3" msgid="3451040656154861722">"காரணம்: <xliff:g id="REASON">%1$s</xliff:g>"</string>
diff --git a/res/values-te-rIN/strings.xml b/res/values-te-rIN/strings.xml
index f83cf0c19..459be435b 100644
--- a/res/values-te-rIN/strings.xml
+++ b/res/values-te-rIN/strings.xml
@@ -31,7 +31,7 @@
<string name="bt_enable_cancel" msgid="1988832367505151727">"రద్దు చేయి"</string>
<string name="bt_enable_ok" msgid="3432462749994538265">"ప్రారంభించు"</string>
<string name="incoming_file_confirm_title" msgid="8139874248612182627">"ఫైల్ బదిలీ"</string>
- <string name="incoming_file_confirm_content" msgid="2752605552743148036">"ఇన్‌కమింగ్ ఫైల్‌ను ఆమోదించాలా?"</string>
+ <string name="incoming_file_confirm_content" msgid="6673812334377911289">"\"<xliff:g id="SENDER">%1$s</xliff:g>\" మీకు <xliff:g id="FILE">%2$s</xliff:g> (<xliff:g id="SIZE">%3$s</xliff:g>)ని పంపాలనుకుంటున్నారు. \n\n ఫైల్‌ను అంగీకరిస్తున్నారా?"</string>
<string name="incoming_file_confirm_cancel" msgid="2973321832477704805">"తిరస్కరిస్తున్నాను"</string>
<string name="incoming_file_confirm_ok" msgid="281462442932231475">"అంగీకరిస్తున్నాను"</string>
<string name="incoming_file_confirm_timeout_ok" msgid="1414676773249857278">"సరే"</string>
@@ -54,9 +54,6 @@
<string name="download_line5" msgid="3069560415845295386">"ఫైల్‌ను స్వీకరిస్తోంది…"</string>
<string name="download_cancel" msgid="9177305996747500768">"ఆపివేయి"</string>
<string name="download_ok" msgid="5000360731674466039">"దాచు"</string>
- <string name="incoming_line1" msgid="2127419875681087545">"దీని నుండి"</string>
- <string name="incoming_line2" msgid="3348994249285315873">"ఫైల్ పేరు"</string>
- <string name="incoming_line3" msgid="7954237069667474024">"పరిమాణం"</string>
<string name="download_fail_line1" msgid="3846450148862894552">"ఫైల్ స్వీకరించబడలేదు"</string>
<string name="download_fail_line2" msgid="8950394574689971071">"ఫైల్: <xliff:g id="FILE">%1$s</xliff:g>"</string>
<string name="download_fail_line3" msgid="3451040656154861722">"కారణం: <xliff:g id="REASON">%1$s</xliff:g>"</string>
diff --git a/res/values-ur-rPK/strings.xml b/res/values-ur-rPK/strings.xml
index 2adbe9765..246d91b49 100644
--- a/res/values-ur-rPK/strings.xml
+++ b/res/values-ur-rPK/strings.xml
@@ -31,7 +31,7 @@
<string name="bt_enable_cancel" msgid="1988832367505151727">"منسوخ کریں"</string>
<string name="bt_enable_ok" msgid="3432462749994538265">"آن کریں"</string>
<string name="incoming_file_confirm_title" msgid="8139874248612182627">"فائل کی منتقلی"</string>
- <string name="incoming_file_confirm_content" msgid="2752605552743148036">"اِن کمنگ فائل قبول کریں؟"</string>
+ <string name="incoming_file_confirm_content" msgid="6673812334377911289">"\"<xliff:g id="SENDER">%1$s</xliff:g>\" آپ کو <xliff:g id="FILE">%2$s</xliff:g> (<xliff:g id="SIZE">%3$s</xliff:g>) بھیجنا چاہتا ہے۔ \n\n فائل قبول کریں؟"</string>
<string name="incoming_file_confirm_cancel" msgid="2973321832477704805">"مسترد کریں"</string>
<string name="incoming_file_confirm_ok" msgid="281462442932231475">"قبول کریں"</string>
<string name="incoming_file_confirm_timeout_ok" msgid="1414676773249857278">"ٹھیک ہے"</string>
@@ -54,9 +54,6 @@
<string name="download_line5" msgid="3069560415845295386">"فائل موصول ہو رہی ہے…"</string>
<string name="download_cancel" msgid="9177305996747500768">"روکیں"</string>
<string name="download_ok" msgid="5000360731674466039">"چھپائیں"</string>
- <string name="incoming_line1" msgid="2127419875681087545">"منجانب"</string>
- <string name="incoming_line2" msgid="3348994249285315873">"فائل کا نام"</string>
- <string name="incoming_line3" msgid="7954237069667474024">"سائز"</string>
<string name="download_fail_line1" msgid="3846450148862894552">"فائل موصول نہیں ہوئی"</string>
<string name="download_fail_line2" msgid="8950394574689971071">"فائل: <xliff:g id="FILE">%1$s</xliff:g>"</string>
<string name="download_fail_line3" msgid="3451040656154861722">"وجہ: <xliff:g id="REASON">%1$s</xliff:g>"</string>
diff --git a/res/values-uz-rUZ/strings.xml b/res/values-uz-rUZ/strings.xml
index aafe74067..7d5f48e03 100644
--- a/res/values-uz-rUZ/strings.xml
+++ b/res/values-uz-rUZ/strings.xml
@@ -31,7 +31,7 @@
<string name="bt_enable_cancel" msgid="1988832367505151727">"Bekor qilish"</string>
<string name="bt_enable_ok" msgid="3432462749994538265">"Yoqish"</string>
<string name="incoming_file_confirm_title" msgid="8139874248612182627">"Fayl uzatish"</string>
- <string name="incoming_file_confirm_content" msgid="2752605552743148036">"Yuborilgan faylni qabul qilasizmi?"</string>
+ <string name="incoming_file_confirm_content" msgid="6673812334377911289">"\"<xliff:g id="SENDER">%1$s</xliff:g>\" sizga <xliff:g id="FILE">%2$s</xliff:g> (<xliff:g id="SIZE">%3$s</xliff:g>)ni jo‘natmoqchi. \n\n Fayl qabul qilinsinmi?"</string>
<string name="incoming_file_confirm_cancel" msgid="2973321832477704805">"Rad qilish"</string>
<string name="incoming_file_confirm_ok" msgid="281462442932231475">"Roziman"</string>
<string name="incoming_file_confirm_timeout_ok" msgid="1414676773249857278">"OK"</string>
@@ -54,9 +54,6 @@
<string name="download_line5" msgid="3069560415845295386">"Fayl qabul qilinmoqda…"</string>
<string name="download_cancel" msgid="9177305996747500768">"To‘xtatish"</string>
<string name="download_ok" msgid="5000360731674466039">"Yashirish"</string>
- <string name="incoming_line1" msgid="2127419875681087545">"Kimdan"</string>
- <string name="incoming_line2" msgid="3348994249285315873">"Fayl nomi"</string>
- <string name="incoming_line3" msgid="7954237069667474024">"Hajmi"</string>
<string name="download_fail_line1" msgid="3846450148862894552">"Fayl qabul qilinmadi"</string>
<string name="download_fail_line2" msgid="8950394574689971071">"Fayl: <xliff:g id="FILE">%1$s</xliff:g>"</string>
<string name="download_fail_line3" msgid="3451040656154861722">"Sababi: <xliff:g id="REASON">%1$s</xliff:g>"</string>
diff --git a/res/values-zh-rCN/strings_pbap.xml b/res/values-zh-rCN/strings_pbap.xml
index dda67e4c3..93c4d900d 100644
--- a/res/values-zh-rCN/strings_pbap.xml
+++ b/res/values-zh-rCN/strings_pbap.xml
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="pbap_session_key_dialog_title" msgid="3580996574333882561">"输入%1$s的会话密钥"</string>
+ <string name="pbap_session_key_dialog_title" msgid="3580996574333882561">"键入 %1$s 的会话密钥"</string>
<string name="pbap_session_key_dialog_header" msgid="2772472422782758981">"需要提供蓝牙会话密钥"</string>
- <string name="pbap_acceptance_timeout_message" msgid="1107401415099814293">"接受与%1$s的连接时出现超时"</string>
- <string name="pbap_authentication_timeout_message" msgid="4166979525521902687">"输入%1$s的会话密钥时出现超时"</string>
- <string name="auth_notif_ticker" msgid="1575825798053163744">"OBEX身份验证请求"</string>
+ <string name="pbap_acceptance_timeout_message" msgid="1107401415099814293">"接受与 %1$s 的连接时超时"</string>
+ <string name="pbap_authentication_timeout_message" msgid="4166979525521902687">"输入带有 %1$s 的会话密钥时超时"</string>
+ <string name="auth_notif_ticker" msgid="1575825798053163744">"OBEX 身份验证请求"</string>
<string name="auth_notif_title" msgid="7599854855681573258">"会话密钥"</string>
- <string name="auth_notif_message" msgid="6667218116427605038">"输入%1$s的会话密钥"</string>
+ <string name="auth_notif_message" msgid="6667218116427605038">"键入 %1$s 的会话密钥"</string>
<string name="defaultname" msgid="4821590500649090078">"Carkit"</string>
<string name="unknownName" msgid="2841414754740600042">"未知名称"</string>
<string name="localPhoneName" msgid="2349001318925409159">"我的名字"</string>
diff --git a/res/values-zh-rCN/test_strings.xml b/res/values-zh-rCN/test_strings.xml
index fd0a0fc78..93d0f70f7 100644
--- a/res/values-zh-rCN/test_strings.xml
+++ b/res/values-zh-rCN/test_strings.xml
@@ -5,10 +5,10 @@
<string name="app_name" msgid="1203877025577761792">"蓝牙共享"</string>
<string name="insert_record" msgid="1450997173838378132">"插入记录"</string>
<string name="update_record" msgid="2480425402384910635">"确认记录"</string>
- <string name="ack_record" msgid="6716152390978472184">"Ack记录"</string>
+ <string name="ack_record" msgid="6716152390978472184">"Ack 记录"</string>
<string name="deleteAll_record" msgid="4383349788485210582">"删除所有记录"</string>
<string name="ok_button" msgid="6519033415223065454">"确定"</string>
<string name="delete_record" msgid="4645040331967533724">"删除记录"</string>
- <string name="start_server" msgid="9034821924409165795">"启动TCP服务器"</string>
- <string name="notify_server" msgid="4369106744022969655">"通知TCP服务器"</string>
+ <string name="start_server" msgid="9034821924409165795">"启动 TCP 服务器"</string>
+ <string name="notify_server" msgid="4369106744022969655">"通知 TCP 服务器"</string>
</resources>
diff --git a/src/com/android/bluetooth/Utils.java b/src/com/android/bluetooth/Utils.java
index 56d5a641b..0b2f836d6 100644
--- a/src/com/android/bluetooth/Utils.java
+++ b/src/com/android/bluetooth/Utils.java
@@ -17,12 +17,17 @@
package com.android.bluetooth;
import android.app.ActivityManager;
+import android.app.ActivityThread;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
+import android.content.Context;
import android.content.ContextWrapper;
+import android.content.pm.UserInfo;
import android.os.Binder;
import android.os.ParcelUuid;
+import android.os.Process;
import android.os.UserHandle;
+import android.os.UserManager;
import android.util.Log;
import java.io.IOException;
@@ -193,12 +198,19 @@ final public class Utils {
// Get the caller's user id then clear the calling identity
// which will be restored in the finally clause.
int callingUser = UserHandle.getCallingUserId();
+ int callingUid = Binder.getCallingUid();
long ident = Binder.clearCallingIdentity();
try {
// With calling identity cleared the current user is the foreground user.
int foregroundUser = ActivityManager.getCurrentUser();
ok = (foregroundUser == callingUser);
+ if (!ok) {
+ // Always allow SystemUI/System access.
+ int systemUiUid = ActivityThread.getPackageManager().getPackageUid(
+ "com.android.systemui", UserHandle.USER_OWNER);
+ ok = (systemUiUid == callingUid) || (Process.SYSTEM_UID == callingUid);
+ }
} catch (Exception ex) {
Log.e(TAG, "checkIfCallerIsSelfOrForegroundUser: Exception ex=" + ex);
ok = false;
@@ -208,6 +220,40 @@ final public class Utils {
return ok;
}
+ public static boolean checkCallerAllowManagedProfiles(Context mContext) {
+ if (mContext == null) {
+ return checkCaller();
+ }
+ boolean ok;
+ // Get the caller's user id and if it's a managed profile, get it's parents
+ // id, then clear the calling identity
+ // which will be restored in the finally clause.
+ int callingUser = UserHandle.getCallingUserId();
+ int callingUid = Binder.getCallingUid();
+ long ident = Binder.clearCallingIdentity();
+ try {
+ UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ UserInfo ui = um.getProfileParent(callingUser);
+ int parentUser = (ui != null) ? ui.id : UserHandle.USER_NULL;
+ // With calling identity cleared the current user is the foreground user.
+ int foregroundUser = ActivityManager.getCurrentUser();
+ ok = (foregroundUser == callingUser) ||
+ (foregroundUser == parentUser);
+ if (!ok) {
+ // Always allow SystemUI/System access.
+ int systemUiUid = ActivityThread.getPackageManager().getPackageUid(
+ "com.android.systemui", UserHandle.USER_OWNER);
+ ok = (systemUiUid == callingUid) || (Process.SYSTEM_UID == callingUid);
+ }
+ } catch (Exception ex) {
+ Log.e(TAG, "checkCallerAllowManagedProfiles: Exception ex=" + ex);
+ ok = false;
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ return ok;
+ }
+
/**
* Enforce the context has android.Manifest.permission.BLUETOOTH_ADMIN permission. A
* {@link SecurityException} would be thrown if neither the calling process or the application
diff --git a/src/com/android/bluetooth/a2dp/A2dpService.java b/src/com/android/bluetooth/a2dp/A2dpService.java
index 97f6a7424..a0d1c30f1 100644
--- a/src/com/android/bluetooth/a2dp/A2dpService.java
+++ b/src/com/android/bluetooth/a2dp/A2dpService.java
@@ -312,4 +312,15 @@ public class A2dpService extends ProfileService {
return service.isA2dpPlaying(device);
}
};
+
+ @Override
+ public void dump(StringBuilder sb) {
+ super.dump(sb);
+ if (mStateMachine != null) {
+ mStateMachine.dump(sb);
+ }
+ if (mAvrcp != null) {
+ mAvrcp.dump(sb);
+ }
+ }
}
diff --git a/src/com/android/bluetooth/a2dp/A2dpSinkService.java b/src/com/android/bluetooth/a2dp/A2dpSinkService.java
index 6a74e9935..433dcd34b 100644
--- a/src/com/android/bluetooth/a2dp/A2dpSinkService.java
+++ b/src/com/android/bluetooth/a2dp/A2dpSinkService.java
@@ -255,4 +255,12 @@ public class A2dpSinkService extends ProfileService {
return service.getAudioConfig(device);
}
};
+
+ @Override
+ public void dump(StringBuilder sb) {
+ super.dump(sb);
+ if (mStateMachine != null) {
+ mStateMachine.dump(sb);
+ }
+ }
}
diff --git a/src/com/android/bluetooth/a2dp/A2dpSinkStateMachine.java b/src/com/android/bluetooth/a2dp/A2dpSinkStateMachine.java
index 13c4ade46..1d585309d 100644
--- a/src/com/android/bluetooth/a2dp/A2dpSinkStateMachine.java
+++ b/src/com/android/bluetooth/a2dp/A2dpSinkStateMachine.java
@@ -173,7 +173,14 @@ final class A2dpSinkStateMachine extends StateMachine {
mAudioConfigs.clear();
}
- private class Disconnected extends State {
+ public void dump(StringBuilder sb) {
+ ProfileService.println(sb, "mCurrentDevice: " + mCurrentDevice);
+ ProfileService.println(sb, "mTargetDevice: " + mTargetDevice);
+ ProfileService.println(sb, "mIncomingDevice: " + mIncomingDevice);
+ ProfileService.println(sb, "StateMachine: " + this.toString());
+ }
+
+ private class Disconnected extends State {
@Override
public void enter() {
log("Enter Disconnected: " + getCurrentMessage().what);
diff --git a/src/com/android/bluetooth/a2dp/A2dpStateMachine.java b/src/com/android/bluetooth/a2dp/A2dpStateMachine.java
index 873e67ff7..3326b4375 100644
--- a/src/com/android/bluetooth/a2dp/A2dpStateMachine.java
+++ b/src/com/android/bluetooth/a2dp/A2dpStateMachine.java
@@ -137,7 +137,6 @@ final class A2dpStateMachine extends StateMachine {
mIntentBroadcastHandler = new IntentBroadcastHandler();
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
-
}
static A2dpStateMachine make(A2dpService svc, Context context) {
@@ -816,6 +815,13 @@ final class A2dpStateMachine extends StateMachine {
}
}
+ public void dump(StringBuilder sb) {
+ ProfileService.println(sb, "mCurrentDevice: " + mCurrentDevice);
+ ProfileService.println(sb, "mTargetDevice: " + mTargetDevice);
+ ProfileService.println(sb, "mIncomingDevice: " + mIncomingDevice);
+ ProfileService.println(sb, "mPlayingA2dpDevice: " + mPlayingA2dpDevice);
+ ProfileService.println(sb, "StateMachine: " + this.toString());
+ }
// Event types for STACK_EVENT message
final private static int EVENT_TYPE_NONE = 0;
diff --git a/src/com/android/bluetooth/avrcp/Avrcp.java b/src/com/android/bluetooth/avrcp/Avrcp.java
index 72e288d45..10090d38d 100644
--- a/src/com/android/bluetooth/avrcp/Avrcp.java
+++ b/src/com/android/bluetooth/avrcp/Avrcp.java
@@ -3553,6 +3553,33 @@ public final class Avrcp {
mHandler.sendMessage(msg);
}
+ public void dump(StringBuilder sb) {
+ sb.append("AVRCP:\n");
+ ProfileService.println(sb, "mMetadata: " + mMetadata);
+ ProfileService.println(sb, "mTransportControlFlags: " + mTransportControlFlags);
+ ProfileService.println(sb, "mCurrentPlayState: " + mCurrentPlayState);
+ ProfileService.println(sb, "mPlayStatusChangedNT: " + mPlayStatusChangedNT);
+ ProfileService.println(sb, "mTrackChangedNT: " + mTrackChangedNT);
+ ProfileService.println(sb, "mTrackNumber: " + mTrackNumber);
+ ProfileService.println(sb, "mCurrentPosMs: " + mCurrentPosMs);
+ ProfileService.println(sb, "mPlayStartTimeMs: " + mPlayStartTimeMs);
+ ProfileService.println(sb, "mSongLengthMs: " + mSongLengthMs);
+ ProfileService.println(sb, "mPlaybackIntervalMs: " + mPlaybackIntervalMs);
+ ProfileService.println(sb, "mPlayPosChangedNT: " + mPlayPosChangedNT);
+ ProfileService.println(sb, "mNextPosMs: " + mNextPosMs);
+ ProfileService.println(sb, "mPrevPosMs: " + mPrevPosMs);
+ ProfileService.println(sb, "mSkipStartTime: " + mSkipStartTime);
+ ProfileService.println(sb, "mFeatures: " + mFeatures);
+ ProfileService.println(sb, "mAbsoluteVolume: " + mAbsoluteVolume);
+ ProfileService.println(sb, "mLastSetVolume: " + mLastSetVolume);
+ ProfileService.println(sb, "mLastDirection: " + mLastDirection);
+ ProfileService.println(sb, "mVolumeStep: " + mVolumeStep);
+ ProfileService.println(sb, "mAudioStreamMax: " + mAudioStreamMax);
+ ProfileService.println(sb, "mVolCmdInProgress: " + mVolCmdInProgress);
+ ProfileService.println(sb, "mAbsVolRetryTimes: " + mAbsVolRetryTimes);
+ ProfileService.println(sb, "mSkipAmount: " + mSkipAmount);
+ }
+
// Do not modify without updating the HAL bt_rc.h files.
// match up with btrc_play_status_t enum of bt_rc.h
diff --git a/src/com/android/bluetooth/avrcp/AvrcpControllerService.java b/src/com/android/bluetooth/avrcp/AvrcpControllerService.java
index b7275d694..0c7e0b6cb 100644
--- a/src/com/android/bluetooth/avrcp/AvrcpControllerService.java
+++ b/src/com/android/bluetooth/avrcp/AvrcpControllerService.java
@@ -265,6 +265,11 @@ public class AvrcpControllerService extends ProfileService {
return Utils.getBytesFromAddress(device.getAddress());
}
+ @Override
+ public void dump(StringBuilder sb) {
+ super.dump(sb);
+ }
+
private native static void classInitNative();
private native void initNative();
private native void cleanupNative();
diff --git a/src/com/android/bluetooth/btservice/AdapterService.java b/src/com/android/bluetooth/btservice/AdapterService.java
index 27c8e5ed0..aaafd2f85 100644
--- a/src/com/android/bluetooth/btservice/AdapterService.java
+++ b/src/com/android/bluetooth/btservice/AdapterService.java
@@ -57,8 +57,10 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.provider.Settings;
+import android.util.EventLog;
import android.util.Log;
import android.util.Pair;
+
import com.android.bluetooth.a2dp.A2dpService;
import com.android.bluetooth.a2dp.A2dpSinkService;
import com.android.bluetooth.hid.HidService;
@@ -67,9 +69,10 @@ import com.android.bluetooth.hfp.HeadsetService;
import com.android.bluetooth.hdp.HealthService;
import com.android.bluetooth.hfpclient.HeadsetClientService;
import com.android.bluetooth.pan.PanService;
-import com.android.bluetooth.R;
import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties;
+import com.android.internal.R;
+
import java.io.FileDescriptor;
import java.io.IOException;
import java.util.ArrayList;
@@ -80,6 +83,7 @@ import java.util.Map;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.List;
+
import android.content.pm.PackageManager;
import android.os.ServiceManager;
@@ -100,6 +104,8 @@ public class AdapterService extends Service {
private int mIdleTimeTotalMs;
private int mEnergyUsedTotalVoltAmpSecMicro;
+ private final ArrayList<ProfileService> mProfiles = new ArrayList<ProfileService>();
+
public static final String ACTION_LOAD_ADAPTER_PROPERTIES =
"com.android.bluetooth.btservice.action.LOAD_ADAPTER_PROPERTIES";
public static final String ACTION_SERVICE_STATE_CHANGED =
@@ -280,6 +286,18 @@ public class AdapterService extends Service {
}
}
+ public void addProfile(ProfileService profile) {
+ synchronized (mProfiles) {
+ mProfiles.add(profile);
+ }
+ }
+
+ public void removeProfile(ProfileService profile) {
+ synchronized (mProfiles) {
+ mProfiles.remove(profile);
+ }
+ }
+
public void onProfileServiceStateChanged(String serviceName, int state) {
Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED);
m.obj=serviceName;
@@ -533,6 +551,8 @@ public class AdapterService extends Service {
private static final int MESSAGE_PROFILE_CONNECTION_STATE_CHANGED = 20;
private static final int MESSAGE_CONNECT_OTHER_PROFILES = 30;
private static final int MESSAGE_PROFILE_INIT_PRIORITIES=40;
+ private static final int MESSAGE_SET_WAKE_ALARM = 100;
+ private static final int MESSAGE_RELEASE_WAKE_ALARM = 110;
private static final int CONNECT_OTHER_PROFILES_TIMEOUT= 6000;
private static final int CONNECT_OTHER_PROFILES_TIMEOUT_DEYALED = 10000;
private static final int MESSAGE_AUTO_CONNECT_PROFILES = 50;
@@ -574,6 +594,17 @@ public class AdapterService extends Service {
autoConnectProfilesDelayed();
break;
}
+ case MESSAGE_SET_WAKE_ALARM: {
+ debugLog( "handleMessage() - MESSAGE_SET_WAKE_ALARM");
+ processSetWakeAlarm((Long) msg.obj, msg.arg1);
+ }
+ break;
+ case MESSAGE_RELEASE_WAKE_ALARM: {
+ debugLog( "handleMessage() - MESSAGE_RELEASE_WAKE_ALARM");
+ mPendingAlarm = null;
+ alarmFiredNative();
+ }
+ break;
}
}
};
@@ -596,7 +627,7 @@ public class AdapterService extends Service {
String serviceName = services[i].getName();
Integer serviceState = mProfileServicesState.get(serviceName);
if(serviceState != null && serviceState != expectedCurrentState) {
- debugLog("setProfileServiceState() - Unable to "
+ debugLog("setProfileServiceState() - Unable to "
+ (state == BluetoothAdapter.STATE_OFF ? "start" : "stop" )
+ " service " + serviceName
+ ". Invalid state: " + serviceState);
@@ -715,7 +746,7 @@ public class AdapterService extends Service {
public String getAddress() {
if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
- (!Utils.checkCaller())) {
+ (!Utils.checkCallerAllowManagedProfiles(mService))) {
Log.w(TAG, "getAddress() - Not allowed for non-active user and non system user");
return null;
}
@@ -760,7 +791,7 @@ public class AdapterService extends Service {
}
public int getScanMode() {
- if (!Utils.checkCaller()) {
+ if (!Utils.checkCallerAllowManagedProfiles(mService)) {
Log.w(TAG, "getScanMode() - Not allowed for non-active user");
return BluetoothAdapter.SCAN_MODE_NONE;
}
@@ -825,7 +856,7 @@ public class AdapterService extends Service {
return service.cancelDiscovery();
}
public boolean isDiscovering() {
- if (!Utils.checkCaller()) {
+ if (!Utils.checkCallerAllowManagedProfiles(mService)) {
Log.w(TAG, "isDiscovering() - Not allowed for non-active user");
return false;
}
@@ -850,7 +881,7 @@ public class AdapterService extends Service {
}
public int getProfileConnectionState(int profile) {
- if (!Utils.checkCaller()) {
+ if (!Utils.checkCallerAllowManagedProfiles(mService)) {
Log.w(TAG, "getProfileConnectionState- Not allowed for non-active user");
return BluetoothProfile.STATE_DISCONNECTED;
}
@@ -900,16 +931,14 @@ public class AdapterService extends Service {
return service.getBondState(device);
}
- public boolean isConnected(BluetoothDevice device) {
+ public int getConnectionState(BluetoothDevice device) {
AdapterService service = getService();
- if (service == null) {
- return false;
- }
- return service.isConnected(device);
+ if (service == null) return 0;
+ return service.getConnectionState(device);
}
public String getRemoteName(BluetoothDevice device) {
- if (!Utils.checkCaller()) {
+ if (!Utils.checkCallerAllowManagedProfiles(mService)) {
Log.w(TAG, "getRemoteName() - Not allowed for non-active user");
return null;
}
@@ -920,7 +949,7 @@ public class AdapterService extends Service {
}
public int getRemoteType(BluetoothDevice device) {
- if (!Utils.checkCaller()) {
+ if (!Utils.checkCallerAllowManagedProfiles(mService)) {
Log.w(TAG, "getRemoteType() - Not allowed for non-active user");
return BluetoothDevice.DEVICE_TYPE_UNKNOWN;
}
@@ -931,7 +960,7 @@ public class AdapterService extends Service {
}
public String getRemoteAlias(BluetoothDevice device) {
- if (!Utils.checkCaller()) {
+ if (!Utils.checkCallerAllowManagedProfiles(mService)) {
Log.w(TAG, "getRemoteAlias() - Not allowed for non-active user");
return null;
}
@@ -978,7 +1007,7 @@ public class AdapterService extends Service {
}
public int getRemoteClass(BluetoothDevice device) {
- if (!Utils.checkCaller()) {
+ if (!Utils.checkCallerAllowManagedProfiles(mService)) {
Log.w(TAG, "getRemoteClass() - Not allowed for non-active user");
return 0;
}
@@ -989,7 +1018,7 @@ public class AdapterService extends Service {
}
public ParcelUuid[] getRemoteUuids(BluetoothDevice device) {
- if (!Utils.checkCaller()) {
+ if (!Utils.checkCallerAllowManagedProfiles(mService)) {
Log.w(TAG, "getRemoteUuids() - Not allowed for non-active user");
return new ParcelUuid[0];
}
@@ -1000,7 +1029,7 @@ public class AdapterService extends Service {
}
public boolean fetchRemoteUuids(BluetoothDevice device) {
- if (!Utils.checkCaller()) {
+ if (!Utils.checkCallerAllowManagedProfiles(mService)) {
Log.w(TAG, "fetchRemoteUuids() - Not allowed for non-active user");
return false;
}
@@ -1107,7 +1136,7 @@ public class AdapterService extends Service {
public ParcelFileDescriptor connectSocket(BluetoothDevice device, int type,
ParcelUuid uuid, int port, int flag) {
- if (!Utils.checkCaller()) {
+ if (!Utils.checkCallerAllowManagedProfiles(mService)) {
Log.w(TAG, "connectSocket() - Not allowed for non-active user");
return null;
}
@@ -1119,7 +1148,7 @@ public class AdapterService extends Service {
public ParcelFileDescriptor createSocketChannel(int type, String serviceName,
ParcelUuid uuid, int port, int flag) {
- if (!Utils.checkCaller()) {
+ if (!Utils.checkCallerAllowManagedProfiles(mService)) {
Log.w(TAG, "createSocketChannel() - Not allowed for non-active user");
return null;
}
@@ -1164,9 +1193,9 @@ public class AdapterService extends Service {
public boolean configHciSnoopLog(boolean enable) {
- if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
- (!Utils.checkCaller())) {
- Log.w(TAG, "configHciSnoopLog() - Not allowed for non-active user");
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ EventLog.writeEvent(0x534e4554 /* SNET */, "Bluetooth", Binder.getCallingUid(),
+ "configHciSnoopLog() - Not allowed for non-active user b/18643224");
return false;
}
@@ -1190,8 +1219,13 @@ public class AdapterService extends Service {
public boolean isMultiAdvertisementSupported() {
AdapterService service = getService();
if (service == null) return false;
- int val = service.getNumOfAdvertisementInstancesSupported();
- return (val >= MIN_ADVT_INSTANCES_FOR_MA);
+ return service.isMultiAdvertisementSupported();
+ }
+
+ public boolean isPeripheralModeSupported() {
+ AdapterService service = getService();
+ if (service == null) return false;
+ return service.isPeripheralModeSupported();
}
public boolean isOffloadedFilteringSupported() {
@@ -1225,6 +1259,14 @@ public class AdapterService extends Service {
if (service == null) return null;
return service.reportActivityInfo();
}
+
+ public String dump() {
+ AdapterService service = getService();
+ if (service == null) {
+ return "AdapterService is null";
+ }
+ return service.dump();
+ }
};
@@ -1674,10 +1716,10 @@ public class AdapterService extends Service {
return deviceProp.getBondState();
}
- boolean isConnected(BluetoothDevice device) {
+ int getConnectionState(BluetoothDevice device) {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
byte[] addr = Utils.getBytesFromAddress(device.getAddress());
- return isConnectedNative(addr);
+ return getConnectionStateNative(addr);
}
String getRemoteName(BluetoothDevice device) {
@@ -1909,6 +1951,11 @@ public class AdapterService extends Service {
return mAdapterProperties.getNumOfAdvertisementInstancesSupported();
}
+ public boolean isMultiAdvertisementSupported() {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return getNumOfAdvertisementInstancesSupported() >= MIN_ADVT_INSTANCES_FOR_MA;
+ }
+
public boolean isRpaOffloadSupported() {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
return mAdapterProperties.isRpaOffloadSupported();
@@ -1924,6 +1971,10 @@ public class AdapterService extends Service {
return mAdapterProperties.getNumOfOffloadedScanFilterSupported();
}
+ public boolean isPeripheralModeSupported() {
+ return getResources().getBoolean(R.bool.config_bluetooth_le_peripheral_mode_supported);
+ }
+
public int getOffloadedScanResultStorage() {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
return mAdapterProperties.getOffloadedScanResultStorage();
@@ -1956,6 +2007,16 @@ public class AdapterService extends Service {
return info;
}
+ private String dump() {
+ StringBuilder sb = new StringBuilder();
+ synchronized (mProfiles) {
+ for (ProfileService profile : mProfiles) {
+ profile.dump(sb);
+ }
+ }
+ return sb.toString();
+ }
+
private static int convertScanModeToHal(int mode) {
switch (mode) {
case BluetoothAdapter.SCAN_MODE_NONE:
@@ -1983,24 +2044,30 @@ public class AdapterService extends Service {
}
// This function is called from JNI. It allows native code to set a single wake
- // alarm. If an alarm is already pending and a new request comes in, the alarm
- // will be rescheduled (i.e. the previously set alarm will be cancelled).
+ // alarm.
private boolean setWakeAlarm(long delayMillis, boolean shouldWake) {
- synchronized (this) {
- if (mPendingAlarm != null) {
- mAlarmManager.cancel(mPendingAlarm);
- }
+ Message m = mHandler.obtainMessage(MESSAGE_SET_WAKE_ALARM);
+ m.obj = new Long(delayMillis);
+ // alarm type
+ m.arg1 = shouldWake ? AlarmManager.ELAPSED_REALTIME_WAKEUP
+ : AlarmManager.ELAPSED_REALTIME;
+ mHandler.sendMessage(m);
- long wakeupTime = SystemClock.elapsedRealtime() + delayMillis;
- int type = shouldWake
- ? AlarmManager.ELAPSED_REALTIME_WAKEUP
- : AlarmManager.ELAPSED_REALTIME;
+ return true;
+ }
- Intent intent = new Intent(ACTION_ALARM_WAKEUP);
- mPendingAlarm = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
- mAlarmManager.setExact(type, wakeupTime, mPendingAlarm);
- return true;
+ // If an alarm is already pending and a new request comes in, the alarm
+ // will be rescheduled (i.e. the previously set alarm will be cancelled).
+ private void processSetWakeAlarm(long delayMillis, int alarmType) {
+ if (mPendingAlarm != null) {
+ mAlarmManager.cancel(mPendingAlarm);
}
+
+ long wakeupTime = SystemClock.elapsedRealtime() + delayMillis;
+
+ Intent intent = new Intent(ACTION_ALARM_WAKEUP);
+ mPendingAlarm = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
+ mAlarmManager.setExact(alarmType, wakeupTime, mPendingAlarm);
}
// This function is called from JNI. It allows native code to acquire a single wake lock.
@@ -2078,10 +2145,7 @@ public class AdapterService extends Service {
private final BroadcastReceiver mAlarmBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- synchronized (AdapterService.this) {
- mPendingAlarm = null;
- alarmFiredNative();
- }
+ mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_RELEASE_WAKE_ALARM));
}
};
@@ -2103,7 +2167,7 @@ public class AdapterService extends Service {
/*package*/ native boolean removeBondNative(byte[] address);
/*package*/ native boolean cancelBondNative(byte[] address);
- /*package*/ native boolean isConnectedNative(byte[] address);
+ /*package*/ native int getConnectionStateNative(byte[] address);
private native boolean startDiscoveryNative();
private native boolean cancelDiscoveryNative();
diff --git a/src/com/android/bluetooth/btservice/ProfileService.java b/src/com/android/bluetooth/btservice/ProfileService.java
index 0c1b70e3f..1b70944ae 100644
--- a/src/com/android/bluetooth/btservice/ProfileService.java
+++ b/src/com/android/bluetooth/btservice/ProfileService.java
@@ -32,6 +32,8 @@ import android.util.Log;
public abstract class ProfileService extends Service {
private static final boolean DBG = false;
+ private static final String TAG = "BluetoothProfileService";
+
//For Debugging only
private static HashMap<String, Integer> sReferenceCount = new HashMap<String,Integer>();
@@ -53,6 +55,8 @@ public abstract class ProfileService extends Service {
protected boolean mStartError=false;
private boolean mCleaningUp = false;
+ private AdapterService mAdapterService;
+
protected String getName() {
return getClass().getSimpleName();
}
@@ -105,6 +109,12 @@ public abstract class ProfileService extends Service {
super.onCreate();
mAdapter = BluetoothAdapter.getDefaultAdapter();
mBinder = initBinder();
+ mAdapterService = AdapterService.getAdapterService();
+ if (mAdapterService != null) {
+ mAdapterService.addProfile(this);
+ } else {
+ Log.w(TAG, "onCreate, null mAdapterService");
+ }
}
public int onStartCommand(Intent intent, int flags, int startId) {
@@ -149,9 +159,23 @@ public abstract class ProfileService extends Service {
return super.onUnbind(intent);
}
+ // for dumpsys support
+ public void dump(StringBuilder sb) {
+ sb.append("Profile: " + mName + "\n");
+ }
+
+ // with indenting for subclasses
+ public static void println(StringBuilder sb, String s) {
+ sb.append(" ");
+ sb.append(s);
+ sb.append("\n");
+ }
+
@Override
public void onDestroy() {
if (DBG) log("Destroying service.");
+ if (mAdapterService != null) mAdapterService.removeProfile(this);
+
if (mCleaningUp) {
if (DBG) log("Cleanup already started... Skipping cleanup()...");
} else {
@@ -194,17 +218,15 @@ public abstract class ProfileService extends Service {
protected void notifyProfileServiceStateChanged(int state) {
//Notify adapter service
- AdapterService sAdapter = AdapterService.getAdapterService();
- if (sAdapter!= null) {
- sAdapter.onProfileServiceStateChanged(getClass().getName(), state);
+ if (mAdapterService != null) {
+ mAdapterService.onProfileServiceStateChanged(getClass().getName(), state);
}
}
public void notifyProfileConnectionStateChanged(BluetoothDevice device,
int profileId, int newState, int prevState) {
- AdapterService svc = AdapterService.getAdapterService();
- if (svc != null) {
- svc.onProfileConnectionStateChanged(device, profileId, newState, prevState);
+ if (mAdapterService != null) {
+ mAdapterService.onProfileConnectionStateChanged(device, profileId, newState, prevState);
}
}
diff --git a/src/com/android/bluetooth/gatt/AdvertiseManager.java b/src/com/android/bluetooth/gatt/AdvertiseManager.java
index 22b20dd6b..b556142b7 100644
--- a/src/com/android/bluetooth/gatt/AdvertiseManager.java
+++ b/src/com/android/bluetooth/gatt/AdvertiseManager.java
@@ -40,7 +40,7 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
- * Manages Bluetooth LE advertising operations and interacts with bluedroid stack.
+ * Manages Bluetooth LE advertising operations and interacts with bluedroid stack. TODO: add tests.
*
* @hide
*/
@@ -56,6 +56,7 @@ class AdvertiseManager {
private static final int MSG_STOP_ADVERTISING = 1;
private final GattService mService;
+ private final AdapterService mAdapterService;
private final Set<AdvertiseClient> mAdvertiseClients;
private final AdvertiseNative mAdvertiseNative;
@@ -68,9 +69,10 @@ class AdvertiseManager {
/**
* Constructor of {@link AdvertiseManager}.
*/
- AdvertiseManager(GattService service) {
- mService = service;
+ AdvertiseManager(GattService service, AdapterService adapterService) {
logd("advertise manager created");
+ mService = service;
+ mAdapterService = adapterService;
mAdvertiseClients = new HashSet<AdvertiseClient>();
mAdvertiseNative = new AdvertiseNative();
}
@@ -272,21 +274,33 @@ class AdvertiseManager {
private static final int ADVERTISING_EVENT_TYPE_SCANNABLE = 2;
private static final int ADVERTISING_EVENT_TYPE_NON_CONNECTABLE = 3;
+ // TODO: Extract advertising logic into interface as we have multiple implementations now.
boolean startAdverising(AdvertiseClient client) {
- int clientIf = client.clientIf;
+ if (!mAdapterService.isMultiAdvertisementSupported() &&
+ !mAdapterService.isPeripheralModeSupported()) {
+ return false;
+ }
+ if (mAdapterService.isMultiAdvertisementSupported()) {
+ return startMultiAdvertising(client);
+ }
+ return startSingleAdvertising(client);
+ }
+
+ boolean startMultiAdvertising(AdvertiseClient client) {
+ logd("starting multi advertising");
resetCountDownLatch();
- mAdvertiseNative.enableAdvertising(client);
+ enableAdvertising(client);
if (!waitForCallback()) {
return false;
}
resetCountDownLatch();
- mAdvertiseNative.setAdvertisingData(clientIf, client.advertiseData, false);
+ setAdvertisingData(client, client.advertiseData, false);
if (!waitForCallback()) {
return false;
}
if (client.scanResponse != null) {
resetCountDownLatch();
- mAdvertiseNative.setAdvertisingData(clientIf, client.scanResponse, true);
+ setAdvertisingData(client, client.scanResponse, true);
if (!waitForCallback()) {
return false;
}
@@ -294,8 +308,29 @@ class AdvertiseManager {
return true;
}
+ boolean startSingleAdvertising(AdvertiseClient client) {
+ logd("starting single advertising");
+ resetCountDownLatch();
+ enableAdvertising(client);
+ if (!waitForCallback()) {
+ return false;
+ }
+ setAdvertisingData(client, client.advertiseData, false);
+ return true;
+ }
+
void stopAdvertising(AdvertiseClient client) {
- gattClientDisableAdvNative(client.clientIf);
+ if (mAdapterService.isMultiAdvertisementSupported()) {
+ gattClientDisableAdvNative(client.clientIf);
+ } else {
+ gattAdvertiseNative(client.clientIf, false);
+ try {
+ mService.onAdvertiseInstanceDisabled(
+ AdvertiseCallback.ADVERTISE_SUCCESS, client.clientIf);
+ } catch (RemoteException e) {
+ Log.d(TAG, "failed onAdvertiseInstanceDisabled", e);
+ }
+ }
}
private void resetCountDownLatch() {
@@ -319,16 +354,21 @@ class AdvertiseManager {
int txPowerLevel = getTxPowerLevel(client.settings);
int advertiseTimeoutSeconds = (int) TimeUnit.MILLISECONDS.toSeconds(
client.settings.getTimeout());
- gattClientEnableAdvNative(
- clientIf,
- minAdvertiseUnit, maxAdvertiseUnit,
- advertiseEventType,
- ADVERTISING_CHANNEL_ALL,
- txPowerLevel,
- advertiseTimeoutSeconds);
+ if (mAdapterService.isMultiAdvertisementSupported()) {
+ gattClientEnableAdvNative(
+ clientIf,
+ minAdvertiseUnit, maxAdvertiseUnit,
+ advertiseEventType,
+ ADVERTISING_CHANNEL_ALL,
+ txPowerLevel,
+ advertiseTimeoutSeconds);
+ } else {
+ gattAdvertiseNative(client.clientIf, true);
+ }
}
- private void setAdvertisingData(int clientIf, AdvertiseData data, boolean isScanResponse) {
+ private void setAdvertisingData(AdvertiseClient client, AdvertiseData data,
+ boolean isScanResponse) {
if (data == null) {
return;
}
@@ -354,9 +394,15 @@ class AdvertiseManager {
}
serviceUuids = advertisingUuidBytes.array();
}
- gattClientSetAdvDataNative(clientIf, isScanResponse, includeName, includeTxPower,
- appearance,
- manufacturerData, serviceData, serviceUuids);
+ if (mAdapterService.isMultiAdvertisementSupported()) {
+ gattClientSetAdvDataNative(client.clientIf, isScanResponse, includeName,
+ includeTxPower, appearance,
+ manufacturerData, serviceData, serviceUuids);
+ } else {
+ gattSetAdvDataNative(client.clientIf, isScanResponse, includeName,
+ includeTxPower, 0, 0, appearance,
+ manufacturerData, serviceData, serviceUuids);
+ }
}
// Combine manufacturer id and manufacturer data.
@@ -455,6 +501,12 @@ class AdvertiseManager {
private native void gattClientSetAdvDataNative(int client_if,
boolean set_scan_rsp, boolean incl_name, boolean incl_txpower, int appearance,
byte[] manufacturer_data, byte[] service_data, byte[] service_uuid);
+
+ private native void gattSetAdvDataNative(int serverIf, boolean setScanRsp, boolean inclName,
+ boolean inclTxPower, int minSlaveConnectionInterval, int maxSlaveConnectionInterval,
+ int appearance, byte[] manufacturerData, byte[] serviceData, byte[] serviceUuid);
+
+ private native void gattAdvertiseNative(int client_if, boolean start);
}
private void logd(String s) {
diff --git a/src/com/android/bluetooth/gatt/ContextMap.java b/src/com/android/bluetooth/gatt/ContextMap.java
index 73b3c7564..5aabf00b3 100644
--- a/src/com/android/bluetooth/gatt/ContextMap.java
+++ b/src/com/android/bluetooth/gatt/ContextMap.java
@@ -134,6 +134,23 @@ import java.util.UUID;
}
/**
+ * Remove the context for a given UUID
+ */
+ void remove(UUID uuid) {
+ synchronized (mApps) {
+ Iterator<App> i = mApps.iterator();
+ while(i.hasNext()) {
+ App entry = i.next();
+ if (entry.uuid.equals(uuid)) {
+ entry.unlinkToDeath();
+ i.remove();
+ break;
+ }
+ }
+ }
+ }
+
+ /**
* Remove the context for a given application ID.
*/
void remove(int id) {
@@ -299,28 +316,23 @@ import java.util.UUID;
/**
* Logs debug information.
*/
- void dump() {
- StringBuilder b = new StringBuilder();
- b.append( "-------------- GATT Context Map ----------------");
- b.append("\nEntries: " + mApps.size());
+ void dump(StringBuilder sb) {
+ sb.append(" Entries: " + mApps.size() + "\n");
Iterator<App> i = mApps.iterator();
while(i.hasNext()) {
App entry = i.next();
List<Connection> connections = getConnectionByApp(entry.id);
- b.append("\n\nApplication Id: " + entry.id);
- b.append("\nUUID: " + entry.uuid);
- b.append("\nConnections: " + connections.size());
+ sb.append("\n Application Id: " + entry.id + "\n");
+ sb.append(" UUID: " + entry.uuid + "\n");
+ sb.append(" Connections: " + connections.size() + "\n");
Iterator<Connection> ii = connections.iterator();
while(ii.hasNext()) {
Connection connection = ii.next();
- b.append("\n " + connection.connId + ": " + connection.address);
+ sb.append(" " + connection.connId + ": " + connection.address + "\n");
}
}
-
- b.append("\n------------------------------------------------");
- Log.d(TAG, b.toString());
}
}
diff --git a/src/com/android/bluetooth/gatt/GattDebugUtils.java b/src/com/android/bluetooth/gatt/GattDebugUtils.java
index 5c42db6a2..a1b37a2ba 100644
--- a/src/com/android/bluetooth/gatt/GattDebugUtils.java
+++ b/src/com/android/bluetooth/gatt/GattDebugUtils.java
@@ -28,13 +28,6 @@ import java.util.UUID;
private static final String TAG = GattServiceConfig.TAG_PREFIX + "DebugUtils";
private static final boolean DEBUG_ADMIN = GattServiceConfig.DEBUG_ADMIN;
- private static final String ACTION_DEBUG_DUMP_CLIENTMAP =
- "android.bluetooth.action.DEBUG_DUMP_CLIENTMAP";
- private static final String ACTION_DEBUG_DUMP_SERVERMAP =
- "android.bluetooth.action.DEBUG_DUMP_SERVERMAP";
- private static final String ACTION_DEBUG_DUMP_HANDLEMAP =
- "android.bluetooth.action.DEBUG_DUMP_HANDLEMAP";
-
private static final String ACTION_GATT_PAIRING_CONFIG =
"android.bluetooth.action.GATT_PAIRING_CONFIG";
@@ -82,23 +75,10 @@ import java.util.UUID;
Log.d(TAG, "handleDebugAction() action=" + action);
/*
- * Debug log functinos
- */
-
- if (ACTION_DEBUG_DUMP_CLIENTMAP.equals(action)) {
- svc.mClientMap.dump();
-
- } else if (ACTION_DEBUG_DUMP_SERVERMAP.equals(action)) {
- svc.mServerMap.dump();
-
- } else if (ACTION_DEBUG_DUMP_HANDLEMAP.equals(action)) {
- svc.mHandleMap.dump();
-
- /*
* PTS test commands
*/
- } else if (ACTION_GATT_TEST_USAGE.equals(action)) {
+ if (ACTION_GATT_TEST_USAGE.equals(action)) {
logUsageInfo();
} else if (ACTION_GATT_TEST_ENABLE.equals(action)) {
diff --git a/src/com/android/bluetooth/gatt/GattService.java b/src/com/android/bluetooth/gatt/GattService.java
index 05ff17a7d..307a87887 100644
--- a/src/com/android/bluetooth/gatt/GattService.java
+++ b/src/com/android/bluetooth/gatt/GattService.java
@@ -40,7 +40,10 @@ import android.os.SystemClock;
import android.util.Log;
import com.android.bluetooth.Utils;
+import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ProfileService;
+import com.android.bluetooth.util.NumberUtils;
+import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
import java.util.Arrays;
@@ -75,6 +78,13 @@ public class GattService extends ProfileService {
private static final int ADVT_STATE_ONFOUND = 0;
private static final int ADVT_STATE_ONLOST = 1;
+ private static final UUID[] HID_UUIDS = {
+ UUID.fromString("00002A4A-0000-1000-8000-00805F9B34FB"),
+ UUID.fromString("00002A4B-0000-1000-8000-00805F9B34FB"),
+ UUID.fromString("00002A4C-0000-1000-8000-00805F9B34FB"),
+ UUID.fromString("00002A4D-0000-1000-8000-00805F9B34FB")
+ };
+
/**
* Search queue to serialize remote onbject inspection.
*/
@@ -180,7 +190,7 @@ public class GattService extends ProfileService {
protected boolean start() {
if (DBG) Log.d(TAG, "start()");
initializeNative();
- mAdvertiseManager = new AdvertiseManager(this);
+ mAdvertiseManager = new AdvertiseManager(this, AdapterService.getAdapterService());
mAdvertiseManager.start();
mScanManager = new ScanManager(this);
@@ -579,7 +589,6 @@ public class GattService extends ProfileService {
void onScanResult(String address, int rssi, byte[] adv_data) {
if (VDBG) Log.d(TAG, "onScanResult() - address=" + address
+ ", rssi=" + rssi);
- ScanRecord record = ScanRecord.parseFromBytes(adv_data);
List<UUID> remoteUuids = parseUuids(adv_data);
for (ScanClient client : mScanManager.getRegularScanQueue()) {
if (client.uuids.length > 0) {
@@ -648,9 +657,7 @@ public class GattService extends ProfileService {
if (client.filters == null || client.filters.isEmpty()) {
return true;
}
- if (DBG) Log.d(TAG, "result: " + scanResult.toString());
for (ScanFilter filter : client.filters) {
- if (DBG) Log.d(TAG, "filter: " + filter.toString());
if (filter.matches(scanResult)) {
return true;
}
@@ -664,8 +671,12 @@ public class GattService extends ProfileService {
if (DBG) Log.d(TAG, "onClientRegistered() - UUID=" + uuid + ", clientIf=" + clientIf);
ClientMap.App app = mClientMap.getByUuid(uuid);
if (app != null) {
- app.id = clientIf;
- app.linkToDeath(new ClientDeathRecipient(clientIf));
+ if (status == 0) {
+ app.id = clientIf;
+ app.linkToDeath(new ClientDeathRecipient(clientIf));
+ } else {
+ mClientMap.remove(uuid);
+ }
app.callback.onClientRegistered(status, clientIf);
}
}
@@ -840,6 +851,12 @@ public class GattService extends ProfileService {
if (VDBG) Log.d(TAG, "onNotify() - address=" + address
+ ", charUuid=" + charUuid + ", length=" + data.length);
+
+ if (isHidUuid(charUuid) &&
+ (0 != checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED))) {
+ return;
+ }
+
ClientMap.App app = mClientMap.getByConnId(connId);
if (app != null) {
app.callback.onNotify(address, srvcType,
@@ -1064,33 +1081,33 @@ public class GattService extends ProfileService {
private Set<ScanResult> parseTruncatedResults(int numRecords, byte[] batchRecord) {
if (DBG) Log.d(TAG, "batch record " + Arrays.toString(batchRecord));
Set<ScanResult> results = new HashSet<ScanResult>(numRecords);
+ long now = SystemClock.elapsedRealtimeNanos();
for (int i = 0; i < numRecords; ++i) {
byte[] record = extractBytes(batchRecord, i * TRUNCATED_RESULT_SIZE,
TRUNCATED_RESULT_SIZE);
byte[] address = extractBytes(record, 0, 6);
- // TODO: remove temp hack.
reverse(address);
BluetoothDevice device = mAdapter.getRemoteDevice(address);
int rssi = record[8];
- // Timestamp is in every 50 ms.
- long timestampNanos = parseTimestampNanos(extractBytes(record, 9, 2));
+ long timestampNanos = now - parseTimestampNanos(extractBytes(record, 9, 2));
results.add(new ScanResult(device, ScanRecord.parseFromBytes(new byte[0]),
rssi, timestampNanos));
}
return results;
}
- private long parseTimestampNanos(byte[] data) {
- long timestampUnit = data[1] & 0xFF << 8 + data[0];
- long timestampNanos = SystemClock.elapsedRealtimeNanos() -
- TimeUnit.MILLISECONDS.toNanos(timestampUnit * 50);
- return timestampNanos;
+ @VisibleForTesting
+ long parseTimestampNanos(byte[] data) {
+ long timestampUnit = NumberUtils.littleEndianByteArrayToInt(data);
+ // Timestamp is in every 50 ms.
+ return TimeUnit.MILLISECONDS.toNanos(timestampUnit * 50);
}
private Set<ScanResult> parseFullResults(int numRecords, byte[] batchRecord) {
Log.d(TAG, "Batch record : " + Arrays.toString(batchRecord));
Set<ScanResult> results = new HashSet<ScanResult>(numRecords);
int position = 0;
+ long now = SystemClock.elapsedRealtimeNanos();
while (position < batchRecord.length) {
byte[] address = extractBytes(batchRecord, position, 6);
// TODO: remove temp hack.
@@ -1102,7 +1119,7 @@ public class GattService extends ProfileService {
// Skip tx power level.
position++;
int rssi = batchRecord[position++];
- long timestampNanos = parseTimestampNanos(extractBytes(batchRecord, position, 2));
+ long timestampNanos = now - parseTimestampNanos(extractBytes(batchRecord, position, 2));
position += 2;
// Combine advertise packet and scan response packet.
@@ -1208,6 +1225,7 @@ public class GattService extends ProfileService {
// Callback for standard advertising instance.
void onAdvertiseCallback(int status, int clientIf) {
if (DBG) Log.d(TAG, "onAdvertiseCallback,- clientIf=" + clientIf + ", status=" + status);
+ mAdvertiseManager.callbackDone(clientIf, status);
}
// Followings are callbacks for Bluetooth LE Advertise operations.
@@ -1437,6 +1455,7 @@ public class GattService extends ProfileService {
int srvcInstanceId, UUID srvcUuid,
int charInstanceId, UUID charUuid, int authReq) {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ if (isHidUuid(charUuid)) enforcePrivilegedPermission();
if (VDBG) Log.d(TAG, "readCharacteristic() - address=" + address);
@@ -1456,6 +1475,7 @@ public class GattService extends ProfileService {
int charInstanceId, UUID charUuid, int writeType,
int authReq, byte[] value) {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ if (isHidUuid(charUuid)) enforcePrivilegedPermission();
if (VDBG) Log.d(TAG, "writeCharacteristic() - address=" + address);
@@ -1478,6 +1498,7 @@ public class GattService extends ProfileService {
int descrInstanceId, UUID descrUuid,
int authReq) {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ if (isHidUuid(charUuid)) enforcePrivilegedPermission();
if (VDBG) Log.d(TAG, "readDescriptor() - address=" + address);
@@ -1501,6 +1522,7 @@ public class GattService extends ProfileService {
int descrInstanceId, UUID descrUuid,
int writeType, int authReq, byte[] value) {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ if (isHidUuid(charUuid)) enforcePrivilegedPermission();
if (VDBG) Log.d(TAG, "writeDescriptor() - address=" + address);
@@ -1541,6 +1563,7 @@ public class GattService extends ProfileService {
int charInstanceId, UUID charUuid,
boolean enable) {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ if (isHidUuid(charUuid)) enforcePrivilegedPermission();
if (DBG) Log.d(TAG, "registerForNotification() - address=" + address + " enable: " + enable);
@@ -1721,9 +1744,6 @@ public class GattService extends ProfileService {
HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle);
if (entry == null) return;
- if (DBG) Log.d(TAG, "onAttributeRead() UUID=" + entry.uuid
- + ", serverIf=" + entry.serverIf + ", type=" + entry.type);
-
mHandleMap.addRequest(transId, attrHandle);
ServerMap.App app = mServerMap.getById(entry.serverIf);
@@ -1779,9 +1799,6 @@ public class GattService extends ProfileService {
HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle);
if (entry == null) return;
- if (DBG) Log.d(TAG, "onAttributeWrite() UUID=" + entry.uuid
- + ", serverIf=" + entry.serverIf + ", type=" + entry.type);
-
mHandleMap.addRequest(transId, attrHandle);
ServerMap.App app = mServerMap.getById(entry.serverIf);
@@ -1842,7 +1859,7 @@ public class GattService extends ProfileService {
}
void onNotificationSent(int connId, int status) throws RemoteException {
- if (DBG) Log.d(TAG, "onNotificationSent() connId=" + connId + ", status=" + status);
+ if (VDBG) Log.d(TAG, "onNotificationSent() connId=" + connId + ", status=" + status);
String address = mServerMap.addressByConnId(connId);
if (address == null) return;
@@ -1874,6 +1891,18 @@ public class GattService extends ProfileService {
}
}
+ void onMtuChanged(int connId, int mtu) throws RemoteException {
+ if (DBG) Log.d(TAG, "onMtuChanged() - connId=" + connId + ", mtu=" + mtu);
+
+ String address = mServerMap.addressByConnId(connId);
+ if (address == null) return;
+
+ ServerMap.App app = mServerMap.getByConnId(connId);
+ if (app == null) return;
+
+ app.callback.onMtuChanged(address, mtu);
+ }
+
/**************************************************************************
* GATT Service functions - SERVER
*************************************************************************/
@@ -2048,6 +2077,13 @@ public class GattService extends ProfileService {
* Private functions
*************************************************************************/
+ private boolean isHidUuid(final UUID uuid) {
+ for (UUID hid_uuid : HID_UUIDS) {
+ if (hid_uuid.equals(uuid)) return true;
+ }
+ return false;
+ }
+
private int getDeviceType(BluetoothDevice device) {
int type = gattClientGetDeviceTypeNative(device.getAddress());
if (DBG) Log.d(TAG, "getDeviceType() - device=" + device
@@ -2258,6 +2294,33 @@ public class GattService extends ProfileService {
return uuids;
}
+ @Override
+ public void dump(StringBuilder sb) {
+ super.dump(sb);
+ println(sb, "mAdvertisingServiceUuids:");
+ for (UUID uuid : mAdvertisingServiceUuids) {
+ println(sb, " " + uuid);
+ }
+ println(sb, "mOnFoundResults:");
+ for (ScanResult result : mOnFoundResults.values()) {
+ println(sb, " " + result);
+ }
+ println(sb, "mOnFoundResults:");
+ for (ServiceDeclaration declaration : mServiceDeclarations) {
+ println(sb, " " + declaration);
+ }
+ println(sb, "mMaxScanFilters: " + mMaxScanFilters);
+
+ sb.append("\nGATT Client Map\n");
+ mClientMap.dump(sb);
+
+ sb.append("\nGATT Server Map\n");
+ mServerMap.dump(sb);
+
+ sb.append("\nGATT Handle Map\n");
+ mHandleMap.dump(sb);
+ }
+
/**************************************************************************
* GATT Test functions
*************************************************************************/
@@ -2351,17 +2414,11 @@ public class GattService extends ProfileService {
private native void gattClientReadRemoteRssiNative(int clientIf,
String address);
- private native void gattAdvertiseNative(int client_if, boolean start);
-
private native void gattClientConfigureMTUNative(int conn_id, int mtu);
private native void gattConnectionParameterUpdateNative(int client_if, String address,
int minInterval, int maxInterval, int latency, int timeout);
- private native void gattSetAdvDataNative(int serverIf, boolean setScanRsp, boolean inclName,
- boolean inclTxPower, int minInterval, int maxInterval,
- int appearance, byte[] manufacturerData, byte[] serviceData, byte[] serviceUuid);
-
private native void gattServerRegisterAppNative(long app_uuid_lsb,
long app_uuid_msb);
diff --git a/src/com/android/bluetooth/gatt/HandleMap.java b/src/com/android/bluetooth/gatt/HandleMap.java
index 187625a43..4a2063984 100644
--- a/src/com/android/bluetooth/gatt/HandleMap.java
+++ b/src/com/android/bluetooth/gatt/HandleMap.java
@@ -196,31 +196,28 @@ class HandleMap {
/**
* Logs debug information.
*/
- void dump() {
- StringBuilder b = new StringBuilder();
- b.append( "-------------- GATT Handle Map -----------------");
- b.append("\nEntries: " + mEntries.size());
- b.append("\nRequests: " + mRequestMap.size());
+ void dump(StringBuilder sb) {
+ sb.append(" Entries: " + mEntries.size() + "\n");
+ sb.append(" Requests: " + mRequestMap.size() + "\n");
for (Entry entry : mEntries) {
- b.append("\n" + entry.serverIf + ": [" + entry.handle + "] ");
+ sb.append(" " + entry.serverIf + ": [" + entry.handle + "] ");
switch(entry.type) {
case TYPE_SERVICE:
- b.append("Service " + entry.uuid);
- b.append(", started " + entry.started);
+ sb.append("Service " + entry.uuid);
+ sb.append(", started " + entry.started);
break;
case TYPE_CHARACTERISTIC:
- b.append(" Characteristic " + entry.uuid);
+ sb.append(" Characteristic " + entry.uuid);
break;
case TYPE_DESCRIPTOR:
- b.append(" Descriptor " + entry.uuid);
+ sb.append(" Descriptor " + entry.uuid);
break;
}
- }
- b.append("\n------------------------------------------------");
- Log.d(TAG, b.toString());
+ sb.append("\n");
+ }
}
}
diff --git a/src/com/android/bluetooth/gatt/ScanManager.java b/src/com/android/bluetooth/gatt/ScanManager.java
index 705d49e72..fb3727adf 100644
--- a/src/com/android/bluetooth/gatt/ScanManager.java
+++ b/src/com/android/bluetooth/gatt/ScanManager.java
@@ -452,7 +452,8 @@ public class ScanManager {
}
void startRegularScan(ScanClient client) {
- if (mFilterIndexStack.isEmpty() && isFilteringSupported()) {
+ if (isFilteringSupported() && mFilterIndexStack.isEmpty() &&
+ mClientFilterIndexMap.isEmpty()) {
initFilterIndexStack();
}
if (isFilteringSupported()) {
diff --git a/src/com/android/bluetooth/hdp/HealthService.java b/src/com/android/bluetooth/hdp/HealthService.java
index 54cc0ef4a..490930ce3 100644
--- a/src/com/android/bluetooth/hdp/HealthService.java
+++ b/src/com/android/bluetooth/hdp/HealthService.java
@@ -813,6 +813,23 @@ public class HealthService extends ProfileService {
return healthDevices;
}
+ @Override
+ public void dump(StringBuilder sb) {
+ super.dump(sb);
+ println(sb, "mHealthChannels:");
+ for (HealthChannel channel : mHealthChannels) {
+ println(sb, " " + channel);
+ }
+ println(sb, "mApps:");
+ for (BluetoothHealthAppConfiguration conf : mApps.keySet()) {
+ println(sb, " " + conf + " : " + mApps.get(conf));
+ }
+ println(sb, "mHealthDevices:");
+ for (BluetoothDevice device : mHealthDevices.keySet()) {
+ println(sb, " " + device + " : " + mHealthDevices.get(device));
+ }
+ }
+
private static class AppInfo {
private IBluetoothHealthCallback mCallback;
private BluetoothHealthDeathRecipient mRcpObj;
diff --git a/src/com/android/bluetooth/hfp/HeadsetPhoneState.java b/src/com/android/bluetooth/hfp/HeadsetPhoneState.java
index e302788ce..95e82f02b 100644
--- a/src/com/android/bluetooth/hfp/HeadsetPhoneState.java
+++ b/src/com/android/bluetooth/hfp/HeadsetPhoneState.java
@@ -21,6 +21,8 @@ import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.util.Log;
import android.bluetooth.BluetoothDevice;
@@ -69,30 +71,78 @@ class HeadsetPhoneState {
private boolean mListening = false;
+ // when HFP Service Level Connection is established
+ private boolean mSlcReady = false;
+
+ private Context mContext = null;
+
+ private PhoneStateListener mPhoneStateListener = null;
+
+ private SubscriptionManager mSubMgr;
+
+ private OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =
+ new OnSubscriptionsChangedListener() {
+ @Override
+ public void onSubscriptionsChanged() {
+ listenForPhoneState(false);
+ listenForPhoneState(true);
+ }
+ };
+
+
HeadsetPhoneState(Context context, HeadsetStateMachine stateMachine) {
mStateMachine = stateMachine;
mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ mContext = context;
+
+ // Register for SubscriptionInfo list changes which is guaranteed
+ // to invoke onSubscriptionInfoChanged and which in turns calls
+ // loadInBackgroud.
+ mSubMgr = SubscriptionManager.from(mContext);
+ mSubMgr.addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
}
public void cleanup() {
listenForPhoneState(false);
+ mSubMgr.removeOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
+
mTelephonyManager = null;
mStateMachine = null;
}
void listenForPhoneState(boolean start) {
+
+ mSlcReady = start;
+
if (start) {
- if (!mListening) {
+ startListenForPhoneState();
+ } else {
+ stopListenForPhoneState();
+ }
+
+ }
+
+ private void startListenForPhoneState() {
+ if (!mListening && mSlcReady) {
+
+ int subId = SubscriptionManager.getDefaultSubId();
+
+ if (SubscriptionManager.isValidSubscriptionId(subId)) {
+ mPhoneStateListener = getPhoneStateListener(subId);
+
mTelephonyManager.listen(mPhoneStateListener,
PhoneStateListener.LISTEN_SERVICE_STATE |
PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
mListening = true;
}
- } else {
- if (mListening) {
- mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
- mListening = false;
- }
+ }
+ }
+
+ private void stopListenForPhoneState() {
+ if (mListening) {
+
+ mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+ mListening = false;
}
}
@@ -203,31 +253,37 @@ class HeadsetPhoneState {
}
}
- private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
- @Override
- public void onServiceStateChanged(ServiceState serviceState) {
- mServiceState = serviceState;
- mService = (serviceState.getState() == ServiceState.STATE_IN_SERVICE) ?
- HeadsetHalConstants.NETWORK_STATE_AVAILABLE :
- HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE;
- setRoam(serviceState.getRoaming() ? HeadsetHalConstants.SERVICE_TYPE_ROAMING
- : HeadsetHalConstants.SERVICE_TYPE_HOME);
- sendDeviceStateChanged();
- }
+ private PhoneStateListener getPhoneStateListener(int subId) {
+ PhoneStateListener mPhoneStateListener = new PhoneStateListener(subId) {
+ @Override
+ public void onServiceStateChanged(ServiceState serviceState) {
- @Override
- public void onSignalStrengthsChanged(SignalStrength signalStrength) {
- int prevSignal = mSignal;
- if (mService == HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE)
- mSignal = 0;
- else
- mSignal = (signalStrength.getLevel() == 4) ? 5 : signalStrength.getLevel();
- // network signal strength is scaled to BT 1-5 levels.
- // This results in a lot of duplicate messages, hence this check
- if (prevSignal != mSignal)
- sendDeviceStateChanged();
- }
- };
+ mServiceState = serviceState;
+ mService = (serviceState.getState() == ServiceState.STATE_IN_SERVICE) ?
+ HeadsetHalConstants.NETWORK_STATE_AVAILABLE :
+ HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE;
+ setRoam(serviceState.getRoaming() ? HeadsetHalConstants.SERVICE_TYPE_ROAMING
+ : HeadsetHalConstants.SERVICE_TYPE_HOME);
+
+ }
+
+ @Override
+ public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+
+ int prevSignal = mSignal;
+ if (mService == HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE)
+ mSignal = 0;
+ else
+ mSignal = (signalStrength.getLevel() == 4) ? 5 : signalStrength.getLevel();
+
+ // network signal strength is scaled to BT 1-5 levels.
+ // This results in a lot of duplicate messages, hence this check
+ if (prevSignal != mSignal)
+ sendDeviceStateChanged();
+ }
+ };
+ return mPhoneStateListener;
+ }
}
diff --git a/src/com/android/bluetooth/hfp/HeadsetService.java b/src/com/android/bluetooth/hfp/HeadsetService.java
index aabe56e68..46629c1e4 100644
--- a/src/com/android/bluetooth/hfp/HeadsetService.java
+++ b/src/com/android/bluetooth/hfp/HeadsetService.java
@@ -141,7 +141,7 @@ public class HeadsetService extends ProfileService {
}
private HeadsetService getService() {
- if (!Utils.checkCaller()) {
+ if (!Utils.checkCallerAllowManagedProfiles(mService)) {
Log.w(TAG,"Headset call not allowed for non-active user");
return null;
}
@@ -581,4 +581,11 @@ public class HeadsetService extends ProfileService {
return true;
}
+ @Override
+ public void dump(StringBuilder sb) {
+ super.dump(sb);
+ if (mStateMachine != null) {
+ mStateMachine.dump(sb);
+ }
+ }
}
diff --git a/src/com/android/bluetooth/hfp/HeadsetStateMachine.java b/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
index 0bec29172..f77a613a0 100644
--- a/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
+++ b/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
@@ -57,11 +57,13 @@ import android.os.ParcelUuid;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.PowerManager;
+import android.os.UserHandle;
import android.os.PowerManager.WakeLock;
import android.telephony.PhoneNumberUtils;
import android.util.Log;
import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.AdapterService;
+import com.android.bluetooth.btservice.ProfileService;
import com.android.internal.util.IState;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
@@ -370,6 +372,20 @@ final class HeadsetStateMachine extends StateMachine {
}
}
+ public void dump(StringBuilder sb) {
+ ProfileService.println(sb, "mCurrentDevice: " + mCurrentDevice);
+ ProfileService.println(sb, "mTargetDevice: " + mTargetDevice);
+ ProfileService.println(sb, "mIncomingDevice: " + mIncomingDevice);
+ ProfileService.println(sb, "mActiveScoDevice: " + mActiveScoDevice);
+ ProfileService.println(sb, "mMultiDisconnectDevice: " + mMultiDisconnectDevice);
+ ProfileService.println(sb, "mVirtualCallStarted: " + mVirtualCallStarted);
+ ProfileService.println(sb, "mVoiceRecognitionStarted: " + mVoiceRecognitionStarted);
+ ProfileService.println(sb, "mWaitingForVoiceRecognition: " + mWaitingForVoiceRecognition);
+ ProfileService.println(sb, "StateMachine: " + this.toString());
+ ProfileService.println(sb, "mPhoneState: " + mPhoneState);
+ ProfileService.println(sb, "mAudioState: " + mAudioState);
+ }
+
private class Disconnected extends State {
@Override
public void enter() {
@@ -2643,7 +2659,8 @@ final class HeadsetStateMachine extends StateMachine {
intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
intent.putExtra(BluetoothProfile.EXTRA_STATE, newState);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
- mService.sendBroadcast(intent, HeadsetService.BLUETOOTH_PERM);
+ mService.sendBroadcastAsUser(intent, UserHandle.ALL,
+ HeadsetService.BLUETOOTH_PERM);
}
private void broadcastAudioState(BluetoothDevice device, int newState, int prevState) {
@@ -2656,7 +2673,7 @@ final class HeadsetStateMachine extends StateMachine {
intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
intent.putExtra(BluetoothProfile.EXTRA_STATE, newState);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
- mService.sendBroadcast(intent, HeadsetService.BLUETOOTH_PERM);
+ mService.sendBroadcastAsUser(intent, UserHandle.ALL, HeadsetService.BLUETOOTH_PERM);
Log.d(TAG, "Audio state " + device + ": " + prevState + "->" + newState);
}
@@ -2681,7 +2698,8 @@ final class HeadsetStateMachine extends StateMachine {
intent.addCategory(BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY
+ "." + Integer.toString(companyId));
- mService.sendBroadcast(intent, HeadsetService.BLUETOOTH_PERM);
+ mService.sendBroadcastAsUser(intent, UserHandle.ALL,
+ HeadsetService.BLUETOOTH_PERM);
}
private void configAudioParameters(BluetoothDevice device)
@@ -3196,14 +3214,14 @@ final class HeadsetStateMachine extends StateMachine {
String number = mPhoneProxy.getSubscriberNumber();
if (number != null) {
atResponseStringNative("+CNUM: ,\"" + number + "\"," +
- PhoneNumberUtils.toaFromString(number) +
- ",,4", getByteAddress(device));
+ PhoneNumberUtils.toaFromString(number) +
+ ",,4", getByteAddress(device));
atResponseCodeNative(HeadsetHalConstants.AT_RESPONSE_OK,
- 0, getByteAddress(device));
+ 0, getByteAddress(device));
} else {
- log("number is null");
- atResponseCodeNative(HeadsetHalConstants.AT_RESPONSE_OK, 0,
- getByteAddress(device));
+ Log.e(TAG, "getSubscriberNumber returns null");
+ atResponseCodeNative(HeadsetHalConstants.AT_RESPONSE_OK,
+ 0, getByteAddress(device));
}
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
diff --git a/src/com/android/bluetooth/hfpclient/HeadsetClientService.java b/src/com/android/bluetooth/hfpclient/HeadsetClientService.java
index 733d8300b..09e3855a7 100644
--- a/src/com/android/bluetooth/hfpclient/HeadsetClientService.java
+++ b/src/com/android/bluetooth/hfpclient/HeadsetClientService.java
@@ -748,4 +748,12 @@ public class HeadsetClientService extends ProfileService {
}
return mStateMachine.getCurrentAgFeatures();
}
+
+ @Override
+ public void dump(StringBuilder sb) {
+ super.dump(sb);
+ if (mStateMachine != null) {
+ mStateMachine.dump(sb);
+ }
+ }
}
diff --git a/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java b/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java
index bf01bbf34..a523cdc91 100644
--- a/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java
+++ b/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java
@@ -158,6 +158,35 @@ final class HeadsetClientStateMachine extends StateMachine {
classInitNative();
}
+ public void dump(StringBuilder sb) {
+ ProfileService.println(sb, "mCurrentDevice: " + mCurrentDevice);
+ ProfileService.println(sb, "mAudioOn: " + mAudioOn);
+ ProfileService.println(sb, "mAudioState: " + mAudioState);
+ ProfileService.println(sb, "mAudioWbs: " + mAudioWbs);
+ ProfileService.println(sb, "mIndicatorNetworkState: " + mIndicatorNetworkState);
+ ProfileService.println(sb, "mIndicatorNetworkType: " + mIndicatorNetworkType);
+ ProfileService.println(sb, "mIndicatorNetworkSignal: " + mIndicatorNetworkSignal);
+ ProfileService.println(sb, "mIndicatorBatteryLevel: " + mIndicatorBatteryLevel);
+ ProfileService.println(sb, "mIndicatorCall: " + mIndicatorCall);
+ ProfileService.println(sb, "mIndicatorCallSetup: " + mIndicatorCallSetup);
+ ProfileService.println(sb, "mIndicatorCallHeld: " + mIndicatorCallHeld);
+ ProfileService.println(sb, "mVgsFromStack: " + mVgsFromStack);
+ ProfileService.println(sb, "mVgmFromStack: " + mVgmFromStack);
+ ProfileService.println(sb, "mRingtone: " + mRingtone);
+ ProfileService.println(sb, "mOperatorName: " + mOperatorName);
+ ProfileService.println(sb, "mSubscriberInfo: " + mSubscriberInfo);
+ ProfileService.println(sb, "mVoiceRecognitionActive: " + mVoiceRecognitionActive);
+ ProfileService.println(sb, "mInBandRingtone: " + mInBandRingtone);
+ ProfileService.println(sb, "mCalls:");
+ for (BluetoothHeadsetClientCall call : mCalls.values()) {
+ ProfileService.println(sb, " " + call);
+ }
+ ProfileService.println(sb, "mCallsUpdate:");
+ for (BluetoothHeadsetClientCall call : mCallsUpdate.values()) {
+ ProfileService.println(sb, " " + call);
+ }
+ }
+
private void clearPendingAction() {
mPendingAction = new Pair<Integer, Object>(NO_ACTION, 0);
}
diff --git a/src/com/android/bluetooth/hid/HidService.java b/src/com/android/bluetooth/hid/HidService.java
index acfe468c5..239b9b6c7 100644
--- a/src/com/android/bluetooth/hid/HidService.java
+++ b/src/com/android/bluetooth/hid/HidService.java
@@ -778,6 +778,16 @@ public class HidService extends ProfileService {
}
}
+ @Override
+ public void dump(StringBuilder sb) {
+ super.dump(sb);
+ println(sb, "mTargetDevice: " + mTargetDevice);
+ println(sb, "mInputDevices:");
+ for (BluetoothDevice device : mInputDevices.keySet()) {
+ println(sb, " " + device + " : " + mInputDevices.get(device));
+ }
+ }
+
// Constants matching Hal header file bt_hh.h
// bthh_connection_state_t
private final static int CONN_STATE_CONNECTED = 0;
diff --git a/src/com/android/bluetooth/map/BluetoothMapContent.java b/src/com/android/bluetooth/map/BluetoothMapContent.java
index 05cd7c46c..3b871f41c 100644
--- a/src/com/android/bluetooth/map/BluetoothMapContent.java
+++ b/src/com/android/bluetooth/map/BluetoothMapContent.java
@@ -56,6 +56,20 @@ import com.android.bluetooth.map.BluetoothMapUtils.TYPE;
import com.google.android.mms.pdu.CharacterSets;
import com.google.android.mms.pdu.PduHeaders;
import android.database.sqlite.SQLiteException;
+import com.android.bluetooth.map.BluetoothMapAppParams;
+
+import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import java.util.*;
@@ -311,8 +325,15 @@ public class BluetoothMapContent {
if (D) Log.d(TAG, sb.toString());
} catch (IOException e) {
- // do nothing for now
- e.printStackTrace();
+ // do nothing for now
+ e.printStackTrace();
+ }
+ }
+
+ private static void close(Closeable c) {
+ try {
+ if (c != null) c.close();
+ } catch (IOException e) {
}
}
@@ -929,10 +950,6 @@ public class BluetoothMapContent {
}
}
- if( name ==null) {
- //set empty value
- name = "";
- }
if (D) Log.d(TAG, "setSenderName: " + name);
e.setSenderName(name);
}
@@ -973,7 +990,7 @@ public class BluetoothMapContent {
Uri uriAddress = Uri.parse(uriStr);
Cursor c = mResolver.query(uriAddress, null, selection,
null, null);
-
+ // TODO: maybe use a projection with only "ct" and "text"
if (c != null && c.moveToFirst()) {
do {
String ct = c.getString(c.getColumnIndex("ct"));
@@ -1103,14 +1120,13 @@ public class BluetoothMapContent {
String orderBy = Contacts.DISPLAY_NAME + " ASC";
Cursor c = mResolver.query(uri, projection, selection, null, orderBy);
-
- if (c != null && c.getCount() >= 1) {
- c.moveToFirst();
- name = c.getString(c.getColumnIndex(Contacts.DISPLAY_NAME));
- }
-
- if (c != null) {
- c.close();
+ try {
+ if (c != null && c.getCount() >= 1) {
+ c.moveToFirst();
+ name = c.getString(c.getColumnIndex(Contacts.DISPLAY_NAME));
+ };
+ } finally {
+ close(c);
}
return name;
}
@@ -1120,15 +1136,16 @@ public class BluetoothMapContent {
String uriStr = String.format("content://mms/%d/addr", id);
Uri uriAddress = Uri.parse(uriStr);
String addr = null;
- Cursor c = r.query(uriAddress, null, selection, null, null);
- if (c != null && c.moveToFirst()) {
- addr = c.getString(c.getColumnIndex("address"));
+ Cursor c = r.query(uriAddress, null, selection, null, null);
+ try {
+ if (c != null && c.moveToFirst()) {
+ addr = c.getString(c.getColumnIndex(Mms.Addr.ADDRESS));
+ }
+ } finally {
+ close(c);
}
- if (c != null) {
- c.close();
- }
return addr;
}
@@ -1511,32 +1528,31 @@ public class BluetoothMapContent {
new String[]{str},
ContactsContract.Contacts.DISPLAY_NAME + " ASC");
- while (c != null && c.moveToNext()) {
- String contactId = c.getString(c.getColumnIndex(ContactsContract.Contacts._ID));
+ try {
+ while (c != null && c.moveToNext()) {
+ String contactId = c.getString(c.getColumnIndex(ContactsContract.Contacts._ID));
- Cursor p = mResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
- ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
- new String[]{contactId},
- null);
+ Cursor p = mResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
+ ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
+ new String[]{contactId},
+ null);
- while (p != null && p.moveToNext()) {
- String number = p.getString(
- p.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
+ try {
+ while (p != null && p.moveToNext()) {
+ String number = p.getString(
+ p.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
- where += " address = " + "'" + number + "'";
- if (!p.isLast()) {
- where += " OR ";
+ where += " address = " + "'" + number + "'";
+ if (!p.isLast()) where += " OR ";
+ }
+ } finally {
+ close(p);
}
+
+ if (!c.isLast()) where += " OR ";
}
- if (!c.isLast()) {
- where += " OR ";
- }
- if (p != null) {
- p.close();
- }
- }
- if (c != null) {
- c.close();
+ } finally {
+ close(c);
}
if (str != null && str.length() > 0) {
@@ -2218,16 +2234,17 @@ public class BluetoothMapContent {
String where = setWhereFilter(folder, fi, ap);
where+= " AND "+ Message.FLAG_LOADED_SELECTION;
+ Log.d(TAG, "where clause is = " + where);
where+= " order by timeStamp desc ";
- //Fetch only maxListCount emails from startOffset
- if(ap.getMaxListCount() > 0 && ap.getMaxListCount() < 65536) {
+ //Fetch only maxListCount emails from startOffset
+ if(ap.getMaxListCount() > 0 && ap.getMaxListCount() < 65536) {
where+=" LIMIT "+ap.getMaxListCount();
- }
- if(ap.getStartOffset() > 0 && ap.getStartOffset() < 65536) {
+ }
+ if(ap.getStartOffset() > 0 && ap.getStartOffset() < 65536) {
where+=" OFFSET "+ap.getStartOffset();
- }
- if (V) Log.d(TAG, "where clause is = " + where);
- try {
+ }
+ if (V) Log.d(TAG, "where clause is = " + where);
+ try {
Cursor c = mResolver.query(uriEmail,
EMAIL_PROJECTION, where + " AND " + Message.FLAG_LOADED_SELECTION, null, "timeStamp desc");
if(c == null) {
@@ -2253,7 +2270,7 @@ public class BluetoothMapContent {
/* Enable this if post sorting and segmenting needed */
bmList.sort();
//Handle OFFSET and MAXLISTCOUNT from DB query
- //bmList.segment(ap.getMaxListCount(), ap.getStartOffset());
+// bmList.segment(ap.getMaxListCount(), ap.getStartOffset());
return bmList;
}
@@ -2334,23 +2351,14 @@ public class BluetoothMapContent {
/* Cache some info used throughout filtering */
FilterInfo fi = new FilterInfo();
setFilterInfo(fi);
-
if (smsSelected(fi, ap)) {
fi.msgType = FilterInfo.TYPE_SMS;
if(ap.getFilterPriority() != 1){ /*SMS cannot have high priority*/
String where = setWhereFilter(folder, fi, ap);
- Cursor c =null;
- //Fetch only maxListCount messages from startOffset
- if(ap.getStartOffset() > 0 && ap.getStartOffset() < 65536) {
- c = mResolver.query(Sms.CONTENT_URI,
- SMS_PROJECTION, where, null, "date DESC" + " limit " +
- ap.getMaxListCount()+" offset "+ ap.getStartOffset());
- }else {
- c = mResolver.query(Sms.CONTENT_URI,
- SMS_PROJECTION, where, null, "date DESC" + " limit " +
- ap.getMaxListCount());
- }
- if (V) Log.d(TAG, "where clause is = " + where);
+
+ Cursor c = mResolver.query(Sms.CONTENT_URI,
+ SMS_PROJECTION, where, null, "date DESC");
+
if (c != null) {
while (c.moveToNext()) {
if (matchAddresses(c, fi, ap)) {
@@ -2366,20 +2374,12 @@ public class BluetoothMapContent {
if (mmsSelected(fi, ap)) {
fi.msgType = FilterInfo.TYPE_MMS;
+
String where = setWhereFilter(folder, fi, ap);
where += " AND " + INTERESTED_MESSAGE_TYPE_CLAUSE;
- Cursor c =null;
- //Fetch only maxListCount messages from startOffset
- if(ap.getStartOffset() > 0 && ap.getStartOffset() < 65536) {
- c = mResolver.query(Mms.CONTENT_URI,
- MMS_PROJECTION, where, null, "date DESC" + " limit " +
- ap.getMaxListCount()+" offset "+ ap.getStartOffset());
- } else {
- c = mResolver.query(Mms.CONTENT_URI,
- MMS_PROJECTION, where, null, "date DESC" + " limit " +
- ap.getMaxListCount());
- }
- if (V) Log.d(TAG, "where clause is = " + where);
+ Cursor c = mResolver.query(Mms.CONTENT_URI,
+ MMS_PROJECTION, where, null, "date DESC");
+
if (c != null) {
int cnt = 0;
while (c.moveToNext()) {
@@ -2392,10 +2392,10 @@ public class BluetoothMapContent {
c.close();
}
}
+
/* Enable this if post sorting and segmenting needed */
bmList.sort();
- //Handle OFFSET and MAXLISTCOUNT from DB query
- //bmList.segment(ap.getMaxListCount(), ap.getStartOffset());
+ bmList.segment(ap.getMaxListCount(), ap.getStartOffset());
return bmList;
}
@@ -2415,8 +2415,8 @@ public class BluetoothMapContent {
SMS_PROJECTION, where, null, "date DESC");
if (c != null) {
- cnt = c.getCount();
- c.close();
+ cnt = c.getCount();
+ c.close();
}
}
@@ -2458,10 +2458,8 @@ public class BluetoothMapContent {
Cursor c = mResolver.query(Sms.CONTENT_URI,
SMS_PROJECTION, where, null, "date DESC");
- if (c != null) {
- cnt = c.getCount();
- c.close();
- }
+ if (c != null) cnt += c.getCount();
+ c.close();
}
if (mmsSelected(fi, ap)) {
@@ -2473,8 +2471,8 @@ public class BluetoothMapContent {
MMS_PROJECTION, where, null, "date DESC");
if (c != null) {
- cnt += c.getCount();
- c.close();
+ cnt += c.getCount();
+ c.close();
}
}
@@ -2568,7 +2566,6 @@ public class BluetoothMapContent {
String contactId = null, contactName = null;
String[] phoneNumbers = null;
String[] emailAddresses = null;
- Cursor p;
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,
Uri.encode(phone));
@@ -2578,53 +2575,42 @@ public class BluetoothMapContent {
String orderBy = Contacts._ID + " ASC";
// Get the contact _ID and name
- p = mResolver.query(uri, projection, selection, null, orderBy);
- if (p != null && p.getCount() >= 1) {
- p.moveToFirst();
- contactId = p.getString(p.getColumnIndex(Contacts._ID));
- contactName = p.getString(p.getColumnIndex(Contacts.DISPLAY_NAME));
- }
- if (p != null)
- p.close();
-
- // Add only original sender's contact number in VCARD.
- phoneNumbers = new String[1];
- phoneNumbers[0] = phone;
- if(contactId != null) {
- // Do not fetch and add all the contacts in vcard to avoid IOT issues with carkits
- /*
- // Fetch all contact phone numbers
- p = mResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
- ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
- new String[]{contactId},
- null);
- if(p != null) {
- int i = 0;
- phoneNumbers = new String[p.getCount()];
- while (p != null && p.moveToNext()) {
- String number = p.getString(
- p.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
- phoneNumbers[i++] = number;
- }
- p.close();
+ Cursor p = mResolver.query(uri, projection, selection, null, orderBy);
+
+ try {
+ if (p != null && p.getCount() >= 1) {
+ p.moveToFirst();
+ contactId = p.getString(p.getColumnIndex(Contacts._ID));
+ contactName = p.getString(p.getColumnIndex(Contacts.DISPLAY_NAME));
}
- */
- // Fetch contact e-mail addresses
- p = mResolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null,
- ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
- new String[]{contactId},
- null);
- if(p != null) {
- int i = 0;
- emailAddresses = new String[p.getCount()];
- while (p != null && p.moveToNext()) {
- String emailAddress = p.getString(
- p.getColumnIndex(ContactsContract.CommonDataKinds.Email.ADDRESS));
- emailAddresses[i++] = emailAddress;
+ // Bail out if we are unable to find a contact, based on the phone number
+ if(contactId == null) {
+ phoneNumbers = new String[1];
+ phoneNumbers[0] = phone;
+ } else {
+ // use only actual phone number
+ phoneNumbers = new String[1];
+ phoneNumbers[0] = phone;
+
+ // Fetch contact e-mail addresses
+ close (p);
+ p = mResolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null,
+ ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
+ new String[]{contactId},
+ null);
+ if (p != null) {
+ int i = 0;
+ emailAddresses = new String[p.getCount()];
+ while (p != null && p.moveToNext()) {
+ String emailAddress = p.getString(
+ p.getColumnIndex(ContactsContract.CommonDataKinds.Email.ADDRESS));
+ emailAddresses[i++] = emailAddress;
+ }
}
- p.close();
}
+ } finally {
+ close(p);
}
if(incoming == true)
message.addOriginator(contactName, contactName, phoneNumbers, emailAddresses); // Use version 3.0 as we only have a formatted name
@@ -2641,11 +2627,13 @@ public class BluetoothMapContent {
String msgBody;
BluetoothMapbMessageSms message = new BluetoothMapbMessageSms();
TelephonyManager tm = (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE);
- Cursor c = mResolver.query(Sms.CONTENT_URI, SMS_PROJECTION, "_ID = " + id, null, null);
- if(c != null && c.moveToFirst())
- {
+ Cursor c = mResolver.query(Sms.CONTENT_URI, SMS_PROJECTION, "_ID = " + id, null, null);
+ if (c == null || !c.moveToFirst()) {
+ throw new IllegalArgumentException("SMS handle not found");
+ }
+ try {
if(V) Log.v(TAG,"c.count: " + c.getCount());
if (tm.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) {
@@ -2685,12 +2673,11 @@ public class BluetoothMapContent {
} else /*if (charset == MAP_MESSAGE_CHARSET_UTF8)*/ {
message.setSmsBody(msgBody);
}
-
- c.close();
-
- return message.encode();
+ } finally {
+ close(c);
}
- throw new IllegalArgumentException("SMS handle not found");
+
+ return message.encode();
}
private void extractMmsAddresses(long id, BluetoothMapbMessageMmsEmail message) {
@@ -2850,6 +2837,7 @@ public class BluetoothMapContent {
} while(c.moveToNext());
c.close();
}
+
message.updateCharset();
}
@@ -2865,8 +2853,11 @@ public class BluetoothMapContent {
int msgBox, threadId;
BluetoothMapbMessageMmsEmail message = new BluetoothMapbMessageMmsEmail();
Cursor c = mResolver.query(Mms.CONTENT_URI, MMS_PROJECTION, "_ID = " + id, null, null);
- if(c != null && c.moveToFirst())
- {
+ if (c == null || !c.moveToFirst()) {
+ throw new IllegalArgumentException("MMS handle not found");
+ }
+
+ try {
message.setType(TYPE.MMS);
// The MMS info:
@@ -2886,24 +2877,13 @@ public class BluetoothMapContent {
message.setDate(c.getLong(c.getColumnIndex(Mms.DATE)) * 1000L);
message.setTextOnly(c.getInt(c.getColumnIndex(Mms.TEXT_ONLY)) == 0 ? false : true); // - TODO: Do we need this - yes, if we have only text, we should not make this a multipart message
message.setIncludeAttachments(appParams.getAttachment() == 0 ? false : true);
- // c.getLong(c.getColumnIndex(Mms.DATE_SENT)); - this is never used
- // c.getInt(c.getColumnIndex(Mms.STATUS)); - don't know what this is
- // The parts
extractMmsParts(id, message);
-
- // The addresses
extractMmsAddresses(id, message);
-
- c.close();
-
- return message.encode();
- }
- else if(c != null) {
- c.close();
+ } finally {
+ close(c);
}
- throw new IllegalArgumentException("MMS handle not found");
+ return message.encode();
}
-
}
diff --git a/src/com/android/bluetooth/map/BluetoothMapContentObserver.java b/src/com/android/bluetooth/map/BluetoothMapContentObserver.java
index 4a8caaafb..f8f1c2bbf 100644
--- a/src/com/android/bluetooth/map/BluetoothMapContentObserver.java
+++ b/src/com/android/bluetooth/map/BluetoothMapContentObserver.java
@@ -14,7 +14,10 @@
*/
package com.android.bluetooth.map;
+
import java.io.ByteArrayInputStream;
+import java.io.Closeable;
+
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
@@ -83,6 +86,13 @@ public class BluetoothMapContentObserver {
private TYPE mSmsType;
+ private static void close(Closeable c) {
+ try {
+ if (c != null) c.close();
+ } catch (IOException e) {
+ }
+ }
+
static final String[] SMS_PROJECTION = new String[] {
BaseColumns._ID,
Sms.THREAD_ID,
@@ -362,41 +372,52 @@ public class BluetoothMapContentObserver {
mMsgListSms.clear();
mMsgListMms.clear();
+
HashMap<Long, Msg> msgListSms = new HashMap<Long, Msg>();
Cursor c = mResolver.query(Sms.CONTENT_URI,
SMS_PROJECTION, null, null, null);
- if (c != null && c.moveToFirst()) {
- do {
- long id = c.getLong(c.getColumnIndex(BaseColumns._ID));
- int type = c.getInt(c.getColumnIndex(Sms.TYPE));
- Msg msg = new Msg(id, type);
- msgListSms.put(id, msg);
- } while (c.moveToNext());
- c.close();
- }
+ try {
+ while (c != null && c.moveToNext()) {
+ long id = c.getLong(c.getColumnIndex(Sms._ID));
+ int type = c.getInt(c.getColumnIndex(Sms.TYPE));
+
+ Msg msg = new Msg(id, type);
+ msgListSms.put(id, msg);
+ }
+ } finally {
+ close(c);
+ }
+
+ synchronized(mMsgListSms) {
+ mMsgListSms.clear();
+ mMsgListSms = msgListSms;
+ }
+
+
- mMsgListSms = msgListSms;
HashMap<Long, Msg> msgListMms = new HashMap<Long, Msg>();
- c = mResolver.query(Mms.CONTENT_URI,
- MMS_PROJECTION, null, null, null);
+ try {
+ while (c != null && c.moveToNext()) {
+ long id = c.getLong(c.getColumnIndex(Mms._ID));
+ int type = c.getInt(c.getColumnIndex(Mms.MESSAGE_BOX));
- if (c != null && c.moveToFirst()) {
- do {
- long id = c.getLong(c.getColumnIndex(BaseColumns._ID));
- int type = c.getInt(c.getColumnIndex(Mms.MESSAGE_BOX));
- Msg msg = new Msg(id, type);
- msgListMms.put(id, msg);
- } while (c.moveToNext());
- c.close();
- }
+ Msg msg = new Msg(id, type );
+ msgListMms.put(id, msg);
+ }
+ } finally {
+ close(c);
+ }
- mMsgListMms = msgListMms;
+ synchronized(mMsgListMms) {
+ mMsgListMms.clear();
+ mMsgListMms = msgListMms;
+ }
}
private void handleMsgListChangesSms() {
@@ -535,7 +556,9 @@ public class BluetoothMapContentObserver {
mResolver.update(uri, contentValues, null, null);
} else {
/* Delete from observer message list to avoid delete notifications */
- mMsgListMms.remove(handle);
+ synchronized(mMsgListMms) {
+ mMsgListMms.remove(handle);
+ }
/* Delete message */
mResolver.delete(uri, null, null);
}
@@ -544,6 +567,7 @@ public class BluetoothMapContentObserver {
if (c != null) {
c.close();
}
+
return res;
}
@@ -603,7 +627,9 @@ public class BluetoothMapContentObserver {
mResolver.update(uri, contentValues, null, null);
} else {
/* Delete from observer message list to avoid delete notifications */
- mMsgListSms.remove(handle);
+ synchronized(mMsgListSms) {
+ mMsgListSms.remove(handle);
+ }
/* Delete message */
mResolver.delete(uri, null, null);
}
@@ -757,15 +783,39 @@ public class BluetoothMapContentObserver {
case SMS_CDMA:
{
/* Add the message to the database */
+
String phone = recipient.getFirstPhoneNumber();
+
String msgBody = ((BluetoothMapbMessageSms) msg).getSmsBody();
- Uri contentUri = Uri.parse("content://sms/" + folder);
- Uri uri = Sms.addMessageToUri(mResolver, contentUri, phone, msgBody,
- "", System.currentTimeMillis(), read, deliveryReport);
- if (uri == null) {
- Log.d(TAG, "pushMessage - failure on add to uri " + contentUri);
- return -1;
+ /* We need to lock the SMS list while updating the database, to avoid sending
+ * events on MCE initiated operation. */
+ Uri contentUri = Uri.parse(Sms.CONTENT_URI+ "/" + folder);
+ Uri uri;
+ synchronized(mMsgListSms) {
+ uri = Sms.addMessageToUri(mResolver, contentUri, phone, msgBody,
+ "", System.currentTimeMillis(), read, deliveryReport);
+
+ if(V) Log.v(TAG, "Sms.addMessageToUri() returned: " + uri);
+ if (uri == null) {
+ if (D) Log.d(TAG, "pushMessage - failure on add to uri " + contentUri);
+ return -1;
+ }
+ Cursor c = mResolver.query(uri, SMS_PROJECTION, null, null, null);
+ try {
+ /* Extract the data for the inserted message, and store in local mirror, to
+ * avoid sending a NewMessage Event. */
+ if (c != null && c.moveToFirst()) {
+ long id = c.getLong(c.getColumnIndex(Sms._ID));
+ int type = c.getInt(c.getColumnIndex(Sms.TYPE));
+ Msg newMsg = new Msg(id, type );
+ mMsgListSms.put(id, newMsg);
+ } else {
+ return -1; // This can only happen, if the message is deleted just as it is added
+ }
+ } finally {
+ close(c);
+ }
}
handle = Long.parseLong(uri.getLastPathSegment());
@@ -836,7 +886,6 @@ public class BluetoothMapContentObserver {
}
-
private void moveDraftToOutbox(long handle) {
ContentResolver contentResolver = mContext.getContentResolver();
/*Move message by changing the msg_box value in the content provider database */
@@ -844,7 +893,8 @@ public class BluetoothMapContentObserver {
String whereClause = " _id= " + handle;
Uri uri = Uri.parse("content://mms");
Cursor queryResult = contentResolver.query(uri, null, whereClause, null, null);
- if (queryResult != null) {
+ try {
+ if (queryResult != null) {
if (queryResult.getCount() > 0) {
queryResult.moveToFirst();
ContentValues data = new ContentValues();
@@ -853,10 +903,14 @@ public class BluetoothMapContentObserver {
contentResolver.update(uri, data, whereClause, null);
Log.d(TAG, "moved draft MMS to outbox");
}
- queryResult.close();
+
addMceInitiatedOperation(Long.toString(handle));
- }else {
+ } else {
Log.d(TAG, "Could not move draft to outbox ");
+
+ }
+ } finally {
+ queryResult.close();
}
}
}
@@ -894,26 +948,50 @@ public class BluetoothMapContentObserver {
// Get thread id
Set<String> recipients = new HashSet<String>();
recipients.addAll(Arrays.asList(to_address));
- values.put("thread_id", Telephony.Threads.getOrCreateThreadId(mContext, recipients));
- Uri uri = Uri.parse("content://mms");
+ values.put(Mms.THREAD_ID, Telephony.Threads.getOrCreateThreadId(mContext, recipients));
+ Uri uri = Mms.CONTENT_URI;
- ContentResolver cr = mContext.getContentResolver();
- uri = cr.insert(uri, values);
+ synchronized (mMsgListMms) {
+ uri = mResolver.insert(uri, values);
- if (uri == null) {
- // unable to insert MMS
- Log.e(TAG, "Unabled to insert MMS " + values + "Uri: " + uri);
- return -1;
- }
+ if (uri == null) {
+ // unable to insert MMS
+ Log.e(TAG, "Unabled to insert MMS " + values + "Uri: " + uri);
+ return -1;
+ }
+ /* As we already have all the values we need, we could skip the query, but
+ doing the query ensures we get any changes made by the content provider
+ at insert. */
+ Cursor c = mResolver.query(uri, MMS_PROJECTION, null, null, null);
+ try {
+ if (c != null && c.moveToFirst()) {
+ long id = c.getLong(c.getColumnIndex(Mms._ID));
+ int type = c.getInt(c.getColumnIndex(Mms.MESSAGE_BOX));
+
+ /* We must filter out any actions made by the MCE. Add the new message to
+ * the list of known messages. */
+
+ Msg newMsg = new Msg(id, type);
+ mMsgListMms.put(id, newMsg);
+ }
+ } finally {
+ close(c);
+ }
+ } // Done adding changes, unlock access to mMsgListMms to allow sending MMS events again
long handle = Long.parseLong(uri.getLastPathSegment());
- ArrayList<MimePart> parts = msg.getMimeParts();
- if (parts != null) {
- Log.v(TAG, " NEW URI " + uri.toString());
- try {
- for(MimePart part : parts) {
- int count = 0;
- count++;
+ if (V) Log.v(TAG, " NEW URI " + uri.toString());
+
+ try {
+ if(msg.getMimeParts() == null) {
+ /* Perhaps this message have been deleted, and no longer have any content, but only headers */
+ Log.w(TAG, "No MMS parts present...");
+ } else {
+ if(V) Log.v(TAG, "Adding " + msg.getMimeParts().size() + " parts to the data base.");
+ int count = 0;
+ for(MimePart part : msg.getMimeParts()) {
+ ++count;
+
values.clear();
if(part.contentType != null &&
part.contentType.toUpperCase().contains("TEXT")) {
@@ -936,7 +1014,7 @@ public class BluetoothMapContentObserver {
values.put("cd", part.contentDisposition);
values.put("text", new String(part.data, "UTF-8"));
uri = Uri.parse("content://mms/" + handle + "/part");
- uri = cr.insert(uri, values);
+ uri = mResolver.insert(uri, values);
if(V) Log.v(TAG, "Added TEXT part");
} else if (part.contentType != null &&
part.contentType.toUpperCase().contains("SMIL")) {
@@ -953,7 +1031,7 @@ public class BluetoothMapContentObserver {
values.put("text", new String(part.data, "UTF-8"));
uri = Uri.parse("content://mms/" + handle + "/part");
- uri = cr.insert(uri, values);
+ uri = mResolver.insert(uri, values);
if(V) Log.v(TAG, "Added SMIL part");
} else /*VIDEO/AUDIO/IMAGE*/ {
writeMmsDataPart(handle, part, count);
@@ -965,12 +1043,13 @@ public class BluetoothMapContentObserver {
}
}
addMceInitiatedOperation("+");
- } catch (UnsupportedEncodingException e) {
+ }
+ }
+ catch (UnsupportedEncodingException e) {
Log.w(TAG, e);
} catch (IOException e) {
Log.w(TAG, e);
}
- }
values.clear();
values.put("contact_id", "null");
values.put("address", "insert-address-token");
@@ -978,7 +1057,7 @@ public class BluetoothMapContentObserver {
values.put("charset", 106);
uri = Uri.parse("content://mms/" + handle + "/addr");
- uri = cr.insert(uri, values);
+ uri = mResolver.insert(uri, values);
if (uri != null && V){
Log.v(TAG, " NEW URI " + uri.toString());
}
@@ -990,7 +1069,7 @@ public class BluetoothMapContentObserver {
values.put("charset", 106);
uri = Uri.parse("content://mms/" + handle + "/addr");
- uri = cr.insert(uri, values);
+ uri = mResolver.insert(uri, values);
if (uri != null && V){
Log.v(TAG, " NEW URI " + uri.toString());
}
@@ -1235,30 +1314,34 @@ public class BluetoothMapContentObserver {
String where = "type = " + Sms.MESSAGE_TYPE_OUTBOX;
Cursor c = mResolver.query(Sms.CONTENT_URI, SMS_PROJECTION, where, null,
null);
+ if (c == null) return;
+ try {
+ while (c!= null && c.moveToNext()) {
+ long id = c.getLong(c.getColumnIndex(Sms._ID));
- if (c != null && c.moveToFirst()) {
- do {
- long id = c.getLong(c.getColumnIndex(BaseColumns._ID));
String msgBody = c.getString(c.getColumnIndex(Sms.BODY));
PushMsgInfo msgInfo = mPushMsgList.get(id);
if (msgInfo == null || msgInfo.resend == false) {
continue;
}
sendMessage(msgInfo, msgBody);
- } while (c.moveToNext());
- c.close();
+ }
+ } finally {
+ close(c);
}
}
private void failPendingMessages() {
/* Move pending messages from outbox to failed */
String where = "type = " + Sms.MESSAGE_TYPE_OUTBOX;
- Cursor c = mResolver.query(Sms.CONTENT_URI, SMS_PROJECTION, where, null,
- null);
+ Cursor c = mResolver.query(Sms.CONTENT_URI, SMS_PROJECTION, where, null, null);
+ if (c == null) return;
+
+
+ try {
+ while (c!= null && c.moveToNext()) {
+ long id = c.getLong(c.getColumnIndex(Sms._ID));
- if (c != null && c.moveToFirst()) {
- do {
- long id = c.getLong(c.getColumnIndex(BaseColumns._ID));
String msgBody = c.getString(c.getColumnIndex(Sms.BODY));
PushMsgInfo msgInfo = mPushMsgList.get(id);
if (msgInfo == null || msgInfo.resend == false) {
@@ -1266,9 +1349,10 @@ public class BluetoothMapContentObserver {
}
Sms.moveMessageToFolder(mContext, msgInfo.uri,
Sms.MESSAGE_TYPE_FAILED, 0);
- } while (c.moveToNext());
+ }
+ } finally {
+ close(c);
}
- if (c != null) c.close();
}
private void removeDeletedMessages() {
@@ -1277,7 +1361,7 @@ public class BluetoothMapContentObserver {
"thread_id = " + DELETED_THREAD_ID, null);
}
- private PhoneStateListener mPhoneListener = new PhoneStateListener (Long.MAX_VALUE - 1,
+ private PhoneStateListener mPhoneListener = new PhoneStateListener (Integer.MAX_VALUE - 1,
Looper.getMainLooper()) {
@Override
public void onServiceStateChanged(ServiceState serviceState) {
diff --git a/src/com/android/bluetooth/map/BluetoothMapObexServer.java b/src/com/android/bluetooth/map/BluetoothMapObexServer.java
index 644191f80..53fedd9da 100755
--- a/src/com/android/bluetooth/map/BluetoothMapObexServer.java
+++ b/src/com/android/bluetooth/map/BluetoothMapObexServer.java
@@ -148,6 +148,7 @@ public class BluetoothMapObexServer extends ServerRequestHandler {
tmpFolder.addFolder("drafts");
}
+
@Override
public int onConnect(final HeaderSet request, HeaderSet reply) {
if (D) Log.d(TAG, "onConnect():");
diff --git a/src/com/android/bluetooth/map/BluetoothMapService.java b/src/com/android/bluetooth/map/BluetoothMapService.java
index 73963b48d..d7d6a6178 100644
--- a/src/com/android/bluetooth/map/BluetoothMapService.java
+++ b/src/com/android/bluetooth/map/BluetoothMapService.java
@@ -1205,4 +1205,5 @@ public class BluetoothMapService extends ProfileService {
return service.getPriority(device);
}
};
+
}
diff --git a/src/com/android/bluetooth/opp/BluetoothOppIncomingFileConfirmActivity.java b/src/com/android/bluetooth/opp/BluetoothOppIncomingFileConfirmActivity.java
index 727b0366a..3c41f3aea 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppIncomingFileConfirmActivity.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppIncomingFileConfirmActivity.java
@@ -198,10 +198,8 @@ public class BluetoothOppIncomingFileConfirmActivity extends AlertActivity imple
private void onTimeout() {
mTimeout = true;
- View view = getLayoutInflater().inflate(R.layout.incoming_dialog, null);
-
- ((TextView)view.findViewById(R.id.from_content)).setText(
- getString(R.string.incoming_file_confirm_timeout_content, mTransInfo.mDeviceName));
+ mAlert.setTitle(getString(R.string.incoming_file_confirm_timeout_content,
+ mTransInfo.mDeviceName));
mAlert.getButton(DialogInterface.BUTTON_NEGATIVE).setVisibility(View.GONE);
mAlert.getButton(DialogInterface.BUTTON_POSITIVE).setText(
getString(R.string.incoming_file_confirm_timeout_ok));
diff --git a/src/com/android/bluetooth/pan/PanService.java b/src/com/android/bluetooth/pan/PanService.java
index aa85c7d2f..ea9b97ed5 100755
--- a/src/com/android/bluetooth/pan/PanService.java
+++ b/src/com/android/bluetooth/pan/PanService.java
@@ -50,9 +50,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
-
/**
* Provides Bluetooth Pan Device profile, as a service in
* the Bluetooth application.
@@ -76,8 +73,6 @@ public class PanService extends ProfileService {
private static final int MESSAGE_DISCONNECT = 2;
private static final int MESSAGE_CONNECT_STATE_CHANGED = 11;
private boolean mTetherOn = false;
- private static final String PAN_PREFERENCE_FILE = "PANMGR";
- private static final String PAN_TETHER_SETTING = "TETHERSTATE";
private BluetoothTetheringNetworkFactory mNetworkFactory;
@@ -109,10 +104,6 @@ public class PanService extends ProfileService {
mNetworkFactory = new BluetoothTetheringNetworkFactory(getBaseContext(), getMainLooper(),
this);
- // Set mTetherOn based on the last saved tethering preference while starting the Pan service
- SharedPreferences tetherSetting = getSharedPreferences(PAN_PREFERENCE_FILE, 0);
- mTetherOn = tetherSetting.getBoolean(PAN_TETHER_SETTING, false);
-
return true;
}
@@ -239,6 +230,7 @@ public class PanService extends ProfileService {
return service.isPanUOn();
}
public boolean isTetheringOn() {
+ // TODO(BT) have a variable marking the on/off state
PanService service = getService();
if (service == null) return false;
return service.isTetheringOn();
@@ -298,6 +290,7 @@ public class PanService extends ProfileService {
return (getPanLocalRoleNative() & BluetoothPan.LOCAL_PANU_ROLE) != 0;
}
boolean isTetheringOn() {
+ // TODO(BT) have a variable marking the on/off state
return mTetherOn;
}
@@ -310,14 +303,6 @@ public class PanService extends ProfileService {
throw new SecurityException("DISALLOW_CONFIG_TETHERING is enabled for this user.");
}
if(mTetherOn != value) {
-
- SharedPreferences tetherSetting = getSharedPreferences(PAN_PREFERENCE_FILE, 0);
- SharedPreferences.Editor editor = tetherSetting.edit();
-
- editor.putBoolean(PAN_TETHER_SETTING, value);
-
- // Commit the edit!
- editor.commit();
//drop any existing panu or pan-nap connection when changing the tethering state
mTetherOn = value;
List<BluetoothDevice> DevList = getConnectedDevices();
@@ -577,6 +562,22 @@ public class PanService extends ProfileService {
return panDevice.mState;
}
+ @Override
+ public void dump(StringBuilder sb) {
+ super.dump(sb);
+ println(sb, "mMaxPanDevices: " + mMaxPanDevices);
+ println(sb, "mPanIfName: " + mPanIfName);
+ println(sb, "mTetherOn: " + mTetherOn);
+ println(sb, "mPanDevices:");
+ for (BluetoothDevice device : mPanDevices.keySet()) {
+ println(sb, " " + device + " : " + mPanDevices.get(device));
+ }
+ println(sb, "mBluetoothIfaceAddresses:");
+ for (String address : mBluetoothIfaceAddresses) {
+ println(sb, " " + address);
+ }
+ }
+
private class BluetoothPanDevice {
private int mState;
private String mIfaceAddr;
diff --git a/src/com/android/bluetooth/util/NumberUtils.java b/src/com/android/bluetooth/util/NumberUtils.java
new file mode 100644
index 000000000..1d2745660
--- /dev/null
+++ b/src/com/android/bluetooth/util/NumberUtils.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+package com.android.bluetooth.util;
+
+/**
+ * Utility for parsing numbers in Bluetooth.
+ */
+public class NumberUtils {
+
+ /**
+ * Convert a byte to unsigned int.
+ */
+ public static int unsignedByteToInt(byte b) {
+ return b & 0xFF;
+ }
+
+ /**
+ * Convert a little endian byte array to integer.
+ */
+ public static int littleEndianByteArrayToInt(byte[] bytes) {
+ int length = bytes.length;
+ if (length == 0) {
+ return 0;
+ }
+ int result = 0;
+ for (int i = length - 1; i >= 0; i--) {
+ int value = unsignedByteToInt(bytes[i]);
+ result += (value << (i * 8));
+ }
+ return result;
+ }
+}
diff --git a/tests/src/com/android/bluetooth/gatt/GattServiceTest.java b/tests/src/com/android/bluetooth/gatt/GattServiceTest.java
new file mode 100644
index 000000000..28c5a10e5
--- /dev/null
+++ b/tests/src/com/android/bluetooth/gatt/GattServiceTest.java
@@ -0,0 +1,22 @@
+
+package com.android.bluetooth.gatt;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.bluetooth.gatt.GattService;
+
+/**
+ * Test cases for {@link GattService}.
+ */
+public class GattServiceTest extends AndroidTestCase {
+
+ @SmallTest
+ public void testParseBatchTimestamp() {
+ GattService service = new GattService();
+ long timestampNanos = service.parseTimestampNanos(new byte[] {
+ -54, 7 });
+ assertEquals(99700000000L, timestampNanos);
+ }
+
+}
diff --git a/tests/src/com/android/bluetooth/util/NumberUtilsTest.java b/tests/src/com/android/bluetooth/util/NumberUtilsTest.java
new file mode 100644
index 000000000..a2fa1aad4
--- /dev/null
+++ b/tests/src/com/android/bluetooth/util/NumberUtilsTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+package com.android.bluetooth.util;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Tests for {@link NumberUtils}.
+ */
+public class NumberUtilsTest extends AndroidTestCase {
+
+ @SmallTest
+ public static void testUnsignedByteToInt() {
+ assertEquals(0, NumberUtils.unsignedByteToInt((byte) 0));
+ assertEquals(19, NumberUtils.unsignedByteToInt((byte) 19));
+ assertEquals(154, NumberUtils.unsignedByteToInt((byte) 154));
+ }
+
+ @SmallTest
+ public void testLittleEndianByteArrayToInt() {
+ assertEquals(1, NumberUtils.littleEndianByteArrayToInt(new byte[] {
+ 1 }));
+ assertEquals(513, NumberUtils.littleEndianByteArrayToInt(new byte[] {
+ 1, 2 }));
+ assertEquals(197121, NumberUtils.littleEndianByteArrayToInt(new byte[] {
+ 1, 2, 3 }));
+ }
+}