diff options
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 })); + } +} |