Merge "Store volume only when Hearing Aid devices are not active" into qt-dev
diff --git a/jni/com_android_bluetooth_btservice_AdapterService.cpp b/jni/com_android_bluetooth_btservice_AdapterService.cpp
index 6b4867f..0ac85f4 100644
--- a/jni/com_android_bluetooth_btservice_AdapterService.cpp
+++ b/jni/com_android_bluetooth_btservice_AdapterService.cpp
@@ -683,7 +683,8 @@
}
}
-static bool initNative(JNIEnv* env, jobject obj) {
+static bool initNative(JNIEnv* env, jobject obj, jboolean isGuest,
+ jboolean isSingleUserMode) {
ALOGV("%s", __func__);
android_bluetooth_UidTraffic.clazz =
@@ -697,7 +698,9 @@
return JNI_FALSE;
}
- int ret = sBluetoothInterface->init(&sBluetoothCallbacks);
+ int ret = sBluetoothInterface->init(&sBluetoothCallbacks,
+ isGuest == JNI_TRUE ? 1 : 0,
+ isSingleUserMode == JNI_TRUE ? 1 : 0);
if (ret != BT_STATUS_SUCCESS) {
ALOGE("Error while setting the callbacks: %d\n", ret);
sBluetoothInterface = NULL;
@@ -750,11 +753,11 @@
return JNI_TRUE;
}
-static jboolean enableNative(JNIEnv* env, jobject obj, jboolean isGuest) {
+static jboolean enableNative(JNIEnv* env, jobject obj) {
ALOGV("%s", __func__);
if (!sBluetoothInterface) return JNI_FALSE;
- int ret = sBluetoothInterface->enable(isGuest == JNI_TRUE ? 1 : 0);
+ int ret = sBluetoothInterface->enable();
return (ret == BT_STATUS_SUCCESS || ret == BT_STATUS_DONE) ? JNI_TRUE
: JNI_FALSE;
}
@@ -1237,9 +1240,9 @@
static JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"classInitNative", "()V", (void*)classInitNative},
- {"initNative", "()Z", (void*)initNative},
+ {"initNative", "(ZZ)Z", (void*)initNative},
{"cleanupNative", "()V", (void*)cleanupNative},
- {"enableNative", "(Z)Z", (void*)enableNative},
+ {"enableNative", "()Z", (void*)enableNative},
{"disableNative", "()Z", (void*)disableNative},
{"setAdapterPropertyNative", "(I[B)Z", (void*)setAdapterPropertyNative},
{"getAdapterPropertiesNative", "()Z", (void*)getAdapterPropertiesNative},
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index cf2b0d3..3d30f17 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -43,7 +43,7 @@
<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_sent_complete" msgid="302943281067557969">"100% पूर्ण"</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="download_title" msgid="3353228219772092586">"फ़ाइल ट्रांसफ़र करें"</string>
<string name="download_line1" msgid="4926604799202134144">"प्रेषक: \"<xliff:g id="SENDER">%1$s</xliff:g>\""</string>
@@ -102,8 +102,8 @@
<string name="status_unknown_error" msgid="8156660554237824912">"अज्ञात गड़बड़ी."</string>
<string name="btopp_live_folder" msgid="7967791481444474554">"ब्लूटूथ से मिली फ़ाइलें"</string>
<string name="opp_notification_group" msgid="3486303082135789982">"ब्लूटूथ के ज़रिए शेयर"</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="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>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 4465490..d05c7b3 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -100,7 +100,7 @@
<string name="status_connection_error" msgid="947681831523219891">"Neuspješno povezivanje."</string>
<string name="status_protocol_error" msgid="3245444473429269539">"Zahtjev nije moguće ispravno obraditi."</string>
<string name="status_unknown_error" msgid="8156660554237824912">"Nepoznata pogreška."</string>
- <string name="btopp_live_folder" msgid="7967791481444474554">"Bluetooth primljen"</string>
+ <string name="btopp_live_folder" msgid="7967791481444474554">"Primljeno Bluetoothom"</string>
<string name="opp_notification_group" msgid="3486303082135789982">"Dijeljenje Bluetoothom"</string>
<string name="download_success" msgid="7036160438766730871">"<xliff:g id="FILE_SIZE">%1$s</xliff:g> primljeno u cijelosti."</string>
<string name="upload_success" msgid="4014469387779648949">"<xliff:g id="FILE_SIZE">%1$s</xliff:g> Poslano u potpunosti."</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index c838d42..f5eeca9 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -100,7 +100,7 @@
<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">"블루투스로 받은 파일"</string>
<string name="opp_notification_group" msgid="3486303082135789982">"블루투스 공유"</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>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 91c96c5..0ed4aa9 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -97,7 +97,7 @@
<string name="status_file_error" msgid="3671917770630165299">"Сактагычта маселе бар."</string>
<string name="status_no_sd_card_nosdcard" msgid="573631036356922221">"USB эстутуму жок."</string>
<string name="status_no_sd_card_default" msgid="396564893716701954">"SD-карта жок. Өткөрүлгөн файлдарды сактоо үчүн SD-картаны салыңыз."</string>
- <string name="status_connection_error" msgid="947681831523219891">"Туташуу ийгиликсиз."</string>
+ <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">"Bluetooth аркылуу алынгандар"</string>
@@ -127,7 +127,7 @@
<string name="bluetooth_map_settings_cancel" msgid="9205350798049865699">"Жокко чыгаруу"</string>
<string name="bluetooth_map_settings_intro" msgid="6482369468223987562">"Bluetooth аркылуу бөлүшө турган каттоо эсептерин тандаңыз. Туташкан сайын каттоо эсептерине кирүү мүмкүнчүлүгүн ырастап турушуңуз керек."</string>
<string name="bluetooth_map_settings_count" msgid="4557473074937024833">"Калган көзөнөктөр:"</string>
- <string name="bluetooth_map_settings_app_icon" msgid="7105805610929114707">"Колдонмонун сөлөкөтү"</string>
+ <string name="bluetooth_map_settings_app_icon" msgid="7105805610929114707">"Колдонмонун сүрөтчөсү"</string>
<string name="bluetooth_map_settings_title" msgid="7420332483392851321">"Bluetooth билдирүү бөлүшүү жөндөөлөрү"</string>
<string name="bluetooth_map_settings_no_account_slots_left" msgid="1796029082612965251">"Аккаунт тандалбай жатат: 0 орун калды"</string>
<string name="bluetooth_connected" msgid="6718623220072656906">"Bluetooth аудио туташты"</string>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index 1613376..7e7763a 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -22,7 +22,7 @@
<string name="permdesc_bluetoothWhitelist" msgid="5494513855192170109">"အက်ပ်အား ဘလူးတုသ်စက်ကို ယာယီခွင့်ပြုစာရင်းထဲ ထည့်ရန်ခွင့်ပြုကာ အသုံးပြုသူ၏ အတည်ပြုချက်မရယူပဲ ဖိုင်များကို စက်ထဲသို့ ပို့ခွင့်ပြုမည်"</string>
<string name="bt_share_picker_label" msgid="6268100924487046932">"ဘလူးတုသ်"</string>
<string name="unknown_device" msgid="9221903979877041009">"မသိသော စက်"</string>
- <string name="unknownNumber" msgid="4994750948072751566">"မသိပါ"</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="bt_enable_title" msgid="8657832550503456572"></string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 2c4410a..8819773 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -106,7 +106,7 @@
<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="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>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index ea25889..07cab6a 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/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">"ਡਾਊਨਲੋਡ ਪ੍ਰਬੰਧਕ ਤੱਕ ਪਹੁੰਚ।"</string>
- <string name="permdesc_bluetoothShareManager" msgid="8930572979123190223">"ਐਪ ਨੂੰ ਬਲੂਟੁੱਥShare ਪ੍ਰਬੰਧਕ ਤੱਕ ਪਹੁੰਚ ਅਤੇ ਫ਼ਾਈਲਾਂ ਟ੍ਰਾਂਸਫਰ ਕਰਨ ਲਈ ਇਸਦੀ ਵਰਤੋਂ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</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>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index f6a51a2..8cfec4f 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -23,7 +23,7 @@
<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>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index d6bed0f..dfb352a 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -106,7 +106,7 @@
<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="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>
diff --git a/src/com/android/bluetooth/a2dp/A2dpService.java b/src/com/android/bluetooth/a2dp/A2dpService.java
index be0ac0c..f9be61a 100644
--- a/src/com/android/bluetooth/a2dp/A2dpService.java
+++ b/src/com/android/bluetooth/a2dp/A2dpService.java
@@ -571,7 +571,7 @@
if (previousActiveDevice != null) {
if (!mAudioManager.isStreamMute(AudioManager.STREAM_MUSIC)) {
mAudioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
- AudioManager.ADJUST_MUTE, 0);
+ AudioManager.ADJUST_MUTE, AudioManager.FLAG_BLUETOOTH_ABS_VOLUME);
wasMuted = true;
}
mAudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
@@ -595,7 +595,7 @@
mAudioManager.handleBluetoothA2dpDeviceConfigChange(mActiveDevice);
if (wasMuted) {
mAudioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
- AudioManager.ADJUST_UNMUTE, 0);
+ AudioManager.ADJUST_MUTE, AudioManager.FLAG_BLUETOOTH_ABS_VOLUME);
}
}
}
diff --git a/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java b/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java
index e951ed5..e41def0 100644
--- a/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java
+++ b/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java
@@ -224,6 +224,10 @@
Log.d(TAG, " connect device: " + device
+ ", InstanceMap start state: " + sb.toString());
}
+ if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) {
+ Log.w(TAG, "Connection not allowed: <" + device.getAddress() + "> is PRIORITY_OFF");
+ return false;
+ }
A2dpSinkStateMachine stateMachine = getOrCreateStateMachine(device);
if (stateMachine != null) {
stateMachine.connect();
@@ -233,7 +237,6 @@
Log.e(TAG, "Maxed out on the number of allowed MAP connections. "
+ "Connect request rejected on " + device);
return false;
-
}
}
diff --git a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java
index c1beb59..0bf34de 100644
--- a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java
+++ b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java
@@ -221,6 +221,7 @@
PlaybackState.Builder pbb = new PlaybackState.Builder();
pbb.setState(PlaybackState.STATE_ERROR, PlaybackState.PLAYBACK_POSITION_UNKNOWN,
1.0f).setActions(0);
+ pbb.setErrorMessage(mService.getString(R.string.bluetooth_disconnected));
BluetoothMediaBrowserService.notifyChanged(pbb.build());
mService.sBrowseTree.mRootNode.removeChild(
mBrowseTree.mRootNode);
diff --git a/src/com/android/bluetooth/avrcpcontroller/BluetoothMediaBrowserService.java b/src/com/android/bluetooth/avrcpcontroller/BluetoothMediaBrowserService.java
index 7a7eb63..3504cd4 100644
--- a/src/com/android/bluetooth/avrcpcontroller/BluetoothMediaBrowserService.java
+++ b/src/com/android/bluetooth/avrcpcontroller/BluetoothMediaBrowserService.java
@@ -71,6 +71,11 @@
| MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
mSession.setQueueTitle(getString(R.string.bluetooth_a2dp_sink_queue_name));
mSession.setQueue(mMediaQueue);
+ PlaybackState.Builder playbackStateBuilder = new PlaybackState.Builder();
+ playbackStateBuilder.setState(PlaybackState.STATE_ERROR,
+ PlaybackState.PLAYBACK_POSITION_UNKNOWN, 1.0f).setActions(0);
+ playbackStateBuilder.setErrorMessage(getString(R.string.bluetooth_disconnected));
+ mSession.setPlaybackState(playbackStateBuilder.build());
sBluetoothMediaBrowserService = this;
}
diff --git a/src/com/android/bluetooth/btservice/AdapterService.java b/src/com/android/bluetooth/btservice/AdapterService.java
index 955a664..508eacf 100644
--- a/src/com/android/bluetooth/btservice/AdapterService.java
+++ b/src/com/android/bluetooth/btservice/AdapterService.java
@@ -286,7 +286,7 @@
}
mRunningProfiles.add(profile);
if (GattService.class.getSimpleName().equals(profile.getName())) {
- enableNativeWithGuestFlag();
+ enableNative();
} else if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length
&& mRegisteredProfiles.size() == mRunningProfiles.size()) {
mAdapterProperties.onBluetoothReady();
@@ -393,7 +393,7 @@
mAdapterProperties = new AdapterProperties(this);
mAdapterStateMachine = AdapterState.make(this);
mJniCallbacks = new JniCallbacks(this, mAdapterProperties);
- initNative();
+ initNative(isGuest(), isSingleUserMode());
mNativeAvailable = true;
mCallbacks = new RemoteCallbackList<IBluetoothCallback>();
mAppOps = getSystemService(AppOpsManager.class);
@@ -2853,11 +2853,12 @@
}
};
- private void enableNativeWithGuestFlag() {
- boolean isGuest = UserManager.get(this).isGuestUser();
- if (!enableNative(isGuest)) {
- Log.e(TAG, "enableNative() returned false");
- }
+ private boolean isGuest() {
+ return UserManager.get(this).isGuestUser();
+ }
+
+ private boolean isSingleUserMode() {
+ return UserManager.get(this).hasUserRestriction(UserManager.DISALLOW_ADD_USER);
}
/**
@@ -2876,12 +2877,12 @@
static native void classInitNative();
- native boolean initNative();
+ native boolean initNative(boolean startRestricted, boolean isSingleUserMode);
native void cleanupNative();
/*package*/
- native boolean enableNative(boolean startRestricted);
+ native boolean enableNative();
/*package*/
native boolean disableNative();
diff --git a/src/com/android/bluetooth/btservice/SilenceDeviceManager.java b/src/com/android/bluetooth/btservice/SilenceDeviceManager.java
index ec01130..e8ec235 100644
--- a/src/com/android/bluetooth/btservice/SilenceDeviceManager.java
+++ b/src/com/android/bluetooth/btservice/SilenceDeviceManager.java
@@ -64,8 +64,6 @@
private final ServiceFactory mFactory;
private Handler mHandler = null;
private Looper mLooper = null;
- private A2dpService mA2dpService = null;
- private HeadsetService mHeadsetService = null;
private final Map<BluetoothDevice, Boolean> mSilenceDevices = new HashMap<>();
private final List<BluetoothDevice> mA2dpConnectedDevices = new ArrayList<>();
@@ -225,8 +223,6 @@
filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
filter.addAction(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED);
mAdapterService.registerReceiver(mReceiver, filter);
- mA2dpService = mFactory.getA2dpService();
- mHeadsetService = mFactory.getHeadsetService();
}
void cleanup() {
@@ -234,8 +230,6 @@
Log.v(TAG, "cleanup()");
}
mSilenceDevices.clear();
- mA2dpService = null;
- mHeadsetService = null;
mAdapterService.unregisterReceiver(mReceiver);
}
@@ -268,16 +262,14 @@
}
mSilenceDevices.replace(device, state);
- if (mA2dpService == null) {
- Log.d(TAG, "A2dpService is null!");
- return;
+ A2dpService a2dpService = mFactory.getA2dpService();
+ if (a2dpService != null) {
+ a2dpService.setSilenceMode(device, state);
}
- if (mHeadsetService == null) {
- Log.d(TAG, "HeadsetService is null!");
- return;
+ HeadsetService headsetService = mFactory.getHeadsetService();
+ if (headsetService != null) {
+ headsetService.setSilenceMode(device, state);
}
- mA2dpService.setSilenceMode(device, state);
- mHeadsetService.setSilenceMode(device, state);
Log.i(TAG, "Silence mode change " + device.getAddress() + ": " + oldState + " -> "
+ state);
broadcastSilenceStateChange(device, state);
diff --git a/src/com/android/bluetooth/mapclient/MapClientService.java b/src/com/android/bluetooth/mapclient/MapClientService.java
index 3f432ca..9989a98 100644
--- a/src/com/android/bluetooth/mapclient/MapClientService.java
+++ b/src/com/android/bluetooth/mapclient/MapClientService.java
@@ -101,6 +101,10 @@
Log.d(TAG, "MAP connect device: " + device
+ ", InstanceMap start state: " + sb.toString());
}
+ if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) {
+ Log.w(TAG, "Connection not allowed: <" + device.getAddress() + "> is PRIORITY_OFF");
+ return false;
+ }
MceStateMachine mapStateMachine = mMapInstanceMap.get(device);
if (mapStateMachine == null) {
// a map state machine instance doesn't exist yet, create a new one if we can.
diff --git a/src/com/android/bluetooth/mapclient/MceStateMachine.java b/src/com/android/bluetooth/mapclient/MceStateMachine.java
index 36c1ee0..11b634c 100644
--- a/src/com/android/bluetooth/mapclient/MceStateMachine.java
+++ b/src/com/android/bluetooth/mapclient/MceStateMachine.java
@@ -51,6 +51,7 @@
import android.content.Intent;
import android.net.Uri;
import android.os.Message;
+import android.provider.Telephony;
import android.telecom.PhoneAccount;
import android.telephony.SmsManager;
import android.util.Log;
@@ -68,8 +69,10 @@
import java.util.ArrayList;
import java.util.Calendar;
+import java.util.Date;
import java.util.HashMap;
import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
/* The MceStateMachine is responsible for setting up and maintaining a connection to a single
* specific Messaging Server Equipment endpoint. Upon connect command an SDP record is retrieved,
@@ -122,6 +125,48 @@
new HashMap<>(MAX_MESSAGES);
private Bmessage.Type mDefaultMessageType = Bmessage.Type.SMS_CDMA;
+ /**
+ * An object to hold the necessary meta-data for each message so we can broadcast it alongside
+ * the message content.
+ *
+ * This is necessary because the metadata is inferred or received separately from the actual
+ * message content.
+ *
+ * Note: In the future it may be best to use the entries from the MessageListing in full instead
+ * of this small subset.
+ */
+ private class MessageMetadata {
+ private final String mHandle;
+ private final Long mTimestamp;
+ private boolean mRead;
+
+ MessageMetadata(String handle, Long timestamp, boolean read) {
+ mHandle = handle;
+ mTimestamp = timestamp;
+ mRead = read;
+ }
+
+ public String getHandle() {
+ return mHandle;
+ }
+
+ public Long getTimestamp() {
+ return mTimestamp;
+ }
+
+ public synchronized boolean getRead() {
+ return mRead;
+ }
+
+ public synchronized void setRead(boolean read) {
+ mRead = read;
+ }
+ }
+
+ // Map each message to its metadata via the handle
+ private ConcurrentHashMap<String, MessageMetadata> mMessages =
+ new ConcurrentHashMap<String, MessageMetadata>();
+
MceStateMachine(MapClientService service, BluetoothDevice device) {
this(service, device, null);
}
@@ -340,7 +385,6 @@
}
onConnectionStateChanged(mPreviousState, BluetoothProfile.STATE_CONNECTING);
- BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
// When commanded to connect begin SDP to find the MAS server.
mDevice.sdpSearch(BluetoothUuid.MAS);
sendMessageDelayed(MSG_CONNECTING_TIMEOUT, TIMEOUT);
@@ -504,6 +548,15 @@
mPreviousState = BluetoothProfile.STATE_CONNECTED;
}
+ /**
+ * Given a message notification event, will ensure message caching and updating and update
+ * interested applications.
+ *
+ * Message notifications arrive for both remote message reception and Message-Listing object
+ * updates that are triggered by the server side.
+ *
+ * @param msg - A Message object containing a EventReport object describing the remote event
+ */
private void processNotification(Message msg) {
if (DBG) {
Log.d(TAG, "Handler: msg: " + msg.what);
@@ -519,7 +572,14 @@
switch (ev.getType()) {
case NEW_MESSAGE:
- //mService.get().sendNewMessageNotification(ev);
+ // Infer the timestamp for this message as 'now' and read status false
+ // instead of getting the message listing data for it
+ if (!mMessages.contains(ev.getHandle())) {
+ Calendar calendar = Calendar.getInstance();
+ MessageMetadata metadata = new MessageMetadata(ev.getHandle(),
+ calendar.getTime().getTime(), false);
+ mMessages.put(ev.getHandle(), metadata);
+ }
mMasClient.makeRequest(new RequestGetMessage(ev.getHandle(),
MasClient.CharsetType.UTF_8, false));
break;
@@ -535,6 +595,8 @@
// Sets the specified message status to "read" (from "unread" status, mostly)
private void markMessageRead(RequestGetMessage request) {
if (DBG) Log.d(TAG, "markMessageRead");
+ MessageMetadata metadata = mMessages.get(request.getHandle());
+ metadata.setRead(true);
mMasClient.makeRequest(new RequestSetMessageStatus(
request.getHandle(), RequestSetMessageStatus.StatusIndicator.READ));
}
@@ -546,21 +608,41 @@
request.getHandle(), RequestSetMessageStatus.StatusIndicator.DELETED));
}
+ /**
+ * Given the result of a Message Listing request, will cache the contents of each Message in
+ * the Message Listing Object and kick off requests to retrieve message contents from the
+ * remote device.
+ *
+ * @param request - A request object that has been resolved and returned with a message list
+ */
private void processMessageListing(RequestGetMessagesListing request) {
if (DBG) {
Log.d(TAG, "processMessageListing");
}
- ArrayList<com.android.bluetooth.mapclient.Message> messageHandles = request.getList();
- if (messageHandles != null) {
- for (com.android.bluetooth.mapclient.Message handle : messageHandles) {
+ ArrayList<com.android.bluetooth.mapclient.Message> messageListing = request.getList();
+ if (messageListing != null) {
+ for (com.android.bluetooth.mapclient.Message msg : messageListing) {
if (DBG) {
Log.d(TAG, "getting message ");
}
- getMessage(handle.getHandle());
+ // A message listing coming from the server should always have up to date data
+ mMessages.put(msg.getHandle(), new MessageMetadata(msg.getHandle(),
+ msg.getDateTime().getTime(), msg.isRead()));
+ getMessage(msg.getHandle());
}
}
}
+ /**
+ * Given the response of a GetMessage request, will broadcast the bMessage contents on to
+ * all registered applications.
+ *
+ * Inbound messages arrive as bMessage objects following a GetMessage request. GetMessage
+ * uses a message handle that can arrive from both a GetMessageListing request or a Message
+ * Notification event.
+ *
+ * @param request - A request object that has been resolved and returned with message data
+ */
private void processInboundMessage(RequestGetMessage request) {
Bmessage message = request.getMessage();
if (DBG) {
@@ -589,10 +671,18 @@
Log.d(TAG, "Recipients" + message.getRecipients().toString());
}
+ // Grab the message metadata and update the cached read status from the bMessage
+ MessageMetadata metadata = mMessages.get(request.getHandle());
+ metadata.setRead(request.getMessage().getStatus() == Bmessage.Status.READ);
+
Intent intent = new Intent();
intent.setAction(BluetoothMapClient.ACTION_MESSAGE_RECEIVED);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
intent.putExtra(BluetoothMapClient.EXTRA_MESSAGE_HANDLE, request.getHandle());
+ intent.putExtra(BluetoothMapClient.EXTRA_MESSAGE_TIMESTAMP,
+ metadata.getTimestamp());
+ intent.putExtra(BluetoothMapClient.EXTRA_MESSAGE_READ_STATUS,
+ metadata.getRead());
intent.putExtra(android.content.Intent.EXTRA_TEXT, message.getBodyContent());
VCardEntry originator = message.getOriginator();
if (originator != null) {
@@ -611,7 +701,12 @@
intent.putExtra(BluetoothMapClient.EXTRA_SENDER_CONTACT_NAME,
originator.getDisplayName());
}
- mService.sendBroadcast(intent);
+ // Only send to the current default SMS app if one exists
+ String defaultMessagingPackage = Telephony.Sms.getDefaultSmsPackage(mService);
+ if (defaultMessagingPackage != null) {
+ intent.setPackage(defaultMessagingPackage);
+ }
+ mService.sendBroadcast(intent, android.Manifest.permission.RECEIVE_SMS);
break;
case MMS:
diff --git a/src/com/android/bluetooth/opp/BluetoothOppService.java b/src/com/android/bluetooth/opp/BluetoothOppService.java
index 545f1ec..914b9b6 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppService.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppService.java
@@ -243,6 +243,10 @@
@Override
public boolean stop() {
+ if (sBluetoothOppService == null) {
+ Log.w(TAG, "stop() called before start()");
+ return true;
+ }
setBluetoothOppService(null);
mHandler.sendMessage(mHandler.obtainMessage(STOP_LISTENER));
return true;
diff --git a/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceTest.java b/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceTest.java
index 39eda7b..d82d28b 100644
--- a/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceTest.java
+++ b/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceTest.java
@@ -15,7 +15,11 @@
*/
package com.android.bluetooth.a2dpsink;
+import static org.mockito.Mockito.*;
+
import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
import android.content.Context;
import androidx.test.InstrumentationRegistry;
@@ -26,6 +30,7 @@
import com.android.bluetooth.R;
import com.android.bluetooth.TestUtils;
import com.android.bluetooth.btservice.AdapterService;
+import com.android.bluetooth.btservice.storage.DatabaseManager;
import org.junit.After;
import org.junit.Assert;
@@ -47,6 +52,7 @@
@Rule public final ServiceTestRule mServiceRule = new ServiceTestRule();
@Mock private AdapterService mAdapterService;
+ @Mock private DatabaseManager mDatabaseManager;
@Before
public void setUp() throws Exception {
@@ -61,6 +67,7 @@
// Try getting the Bluetooth adapter
mAdapter = BluetoothAdapter.getDefaultAdapter();
Assert.assertNotNull(mAdapter);
+ when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager);
}
@After
@@ -74,8 +81,43 @@
TestUtils.clearAdapterService(mAdapterService);
}
+ private BluetoothDevice makeBluetoothDevice(String address) {
+ return mAdapter.getRemoteDevice(address);
+ }
+
+ /**
+ * Mock the priority of a bluetooth device
+ *
+ * @param device - The bluetooth device you wish to mock the priority of
+ * @param priority - The priority value you want the device to have
+ */
+ private void mockDevicePriority(BluetoothDevice device, int priority) {
+ when(mDatabaseManager.getProfilePriority(device, BluetoothProfile.A2DP_SINK))
+ .thenReturn(priority);
+ }
+
@Test
public void testInitialize() {
Assert.assertNotNull(A2dpSinkService.getA2dpSinkService());
}
+
+ /**
+ * Test that a PRIORITY_ON device is connected to
+ */
+ @Test
+ public void testConnect() {
+ BluetoothDevice device = makeBluetoothDevice("11:11:11:11:11:11");
+ mockDevicePriority(device, BluetoothProfile.PRIORITY_ON);
+ Assert.assertTrue(mService.connect(device));
+ }
+
+ /**
+ * Test that a PRIORITY_OFF device is not connected to
+ */
+ @Test
+ public void testConnectPriorityOffDevice() {
+ BluetoothDevice device = makeBluetoothDevice("11:11:11:11:11:11");
+ mockDevicePriority(device, BluetoothProfile.PRIORITY_OFF);
+ Assert.assertFalse(mService.connect(device));
+ }
}
diff --git a/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java b/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java
index 58f29ae..14adf89 100644
--- a/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java
+++ b/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java
@@ -89,6 +89,7 @@
MockitoAnnotations.initMocks(this);
TestUtils.setAdapterService(mAdapterService);
TestUtils.startService(mServiceRule, AvrcpControllerService.class);
+ doReturn(mTargetContext.getResources()).when(mAvrcpControllerService).getResources();
// This line must be called to make sure relevant objects are initialized properly
mAdapter = BluetoothAdapter.getDefaultAdapter();
diff --git a/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java b/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java
index 897863e..82fa163 100644
--- a/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java
+++ b/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java
@@ -101,7 +101,7 @@
}
Assert.assertNotNull(Looper.myLooper());
AdapterService adapterService = new AdapterService();
- adapterService.initNative();
+ adapterService.initNative(false /* is_restricted */, false /* is_single_user_mode */);
adapterService.cleanupNative();
HashMap<String, HashMap<String, String>> adapterConfig = TestUtils.readAdapterConfig();
Assert.assertNotNull(adapterConfig);
diff --git a/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java b/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java
index 999ccd1..6567398 100644
--- a/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java
+++ b/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java
@@ -96,7 +96,7 @@
mProfiles = Config.getSupportedProfiles();
- mMockAdapterService.initNative();
+ mMockAdapterService.initNative(false /* is_restricted */, false /* is_single_user_mode */);
TestUtils.setAdapterService(mMockAdapterService);
diff --git a/tests/unit/src/com/android/bluetooth/mapclient/MapClientTest.java b/tests/unit/src/com/android/bluetooth/mapclient/MapClientTest.java
index b80e75e..bc25a11 100644
--- a/tests/unit/src/com/android/bluetooth/mapclient/MapClientTest.java
+++ b/tests/unit/src/com/android/bluetooth/mapclient/MapClientTest.java
@@ -16,8 +16,11 @@
package com.android.bluetooth.mapclient;
+import static org.mockito.Mockito.*;
+
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
import android.content.Context;
import androidx.test.InstrumentationRegistry;
@@ -28,6 +31,7 @@
import com.android.bluetooth.R;
import com.android.bluetooth.TestUtils;
import com.android.bluetooth.btservice.AdapterService;
+import com.android.bluetooth.btservice.storage.DatabaseManager;
import org.junit.After;
import org.junit.Assert;
@@ -53,6 +57,7 @@
@Mock private AdapterService mAdapterService;
@Mock private MnsService mMockMnsService;
+ @Mock private DatabaseManager mDatabaseManager;
@Rule public final ServiceTestRule mServiceRule = new ServiceTestRule();
@@ -69,6 +74,7 @@
Assert.assertNotNull(mService);
cleanUpInstanceMap();
mAdapter = BluetoothAdapter.getDefaultAdapter();
+ when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager);
}
@After
@@ -92,6 +98,17 @@
Assert.assertTrue(mService.getInstanceMap().isEmpty());
}
+ /**
+ * Mock the priority of a bluetooth device
+ *
+ * @param device - The bluetooth device you wish to mock the priority of
+ * @param priority - The priority value you want the device to have
+ */
+ private void mockDevicePriority(BluetoothDevice device, int priority) {
+ when(mDatabaseManager.getProfilePriority(device, BluetoothProfile.MAP_CLIENT))
+ .thenReturn(priority);
+ }
+
@Test
public void testInitialize() {
Assert.assertNotNull(MapClientService.getMapClientService());
@@ -107,6 +124,7 @@
Assert.assertNull(mService.getInstanceMap().get(device));
// connect a bluetooth device
+ mockDevicePriority(device, BluetoothProfile.PRIORITY_ON);
Assert.assertTrue(mService.connect(device));
// is the statemachine created
@@ -116,6 +134,25 @@
}
/**
+ * Test that a PRIORITY_OFF device is not connected to
+ */
+ @Test
+ public void testConnectPriorityOffDevice() {
+ // make sure there is no statemachine already defined for this device
+ BluetoothDevice device = makeBluetoothDevice("11:11:11:11:11:11");
+ Assert.assertNull(mService.getInstanceMap().get(device));
+
+ // connect a bluetooth device
+ mockDevicePriority(device, BluetoothProfile.PRIORITY_OFF);
+ Assert.assertFalse(mService.connect(device));
+
+ // is the statemachine created
+ Map<BluetoothDevice, MceStateMachine> map = mService.getInstanceMap();
+ Assert.assertEquals(0, map.size());
+ Assert.assertNull(map.get(device));
+ }
+
+ /**
* Test connecting MAXIMUM_CONNECTED_DEVICES devices.
*/
@Test
@@ -132,8 +169,9 @@
Assert.assertNull(mService.getInstanceMap().get(d));
}
- // run the test - connect all devices
+ // run the test - connect all devices, set their priorities to on
for (BluetoothDevice d : list) {
+ mockDevicePriority(d, BluetoothProfile.PRIORITY_ON);
Assert.assertTrue(mService.connect(d));
}