summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLalit Kansara <lkansara@codeaurora.org>2016-12-06 14:47:45 +0530
committerLalit Kansara <lkansara@codeaurora.org>2016-12-06 14:47:45 +0530
commitaa2a937e6c8c9c93cc1a5fe344c368b4276243c1 (patch)
tree05648e985b986d372f3a3d7f60cab8d6b77e244d
parentc7ae94e96c0c7bb93ec80d548c024a968c411d32 (diff)
parent1c40f9218d815e4e67482fb8913fce6850e4fb1c (diff)
downloadandroid_packages_apps_Bluetooth-aa2a937e6c8c9c93cc1a5fe344c368b4276243c1.tar.gz
android_packages_apps_Bluetooth-aa2a937e6c8c9c93cc1a5fe344c368b4276243c1.tar.bz2
android_packages_apps_Bluetooth-aa2a937e6c8c9c93cc1a5fe344c368b4276243c1.zip
Merge commit '1c40f9218d815e4e67482fb8913fce6850e4fb1c' into remote
Conflicts: jni/com_android_bluetooth_hfp.cpp src/com/android/bluetooth/avrcp/Avrcp.java src/com/android/bluetooth/btservice/AdapterService.java src/com/android/bluetooth/btservice/RemoteDevices.java src/com/android/bluetooth/hfp/HeadsetStateMachine.java src/com/android/bluetooth/map/BluetoothMapContentObserver.java src/com/android/bluetooth/map/BluetoothMapService.java src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java src/com/android/bluetooth/pan/PanService.java src/com/android/bluetooth/pbap/BluetoothPbapReceiver.java Change-Id: I41068ac7787983519220fe6fee1e65ff66298db1
-rw-r--r--jni/com_android_bluetooth_a2dp.cpp7
-rw-r--r--jni/com_android_bluetooth_hfp.cpp1
-rw-r--r--res/values-ca/strings.xml2
-rw-r--r--res/values-fa/strings.xml2
-rw-r--r--res/values-fa/strings_pbap.xml2
-rw-r--r--res/values-hy-rAM/strings.xml4
-rw-r--r--res/values-lt/strings.xml2
-rw-r--r--res/values-my-rMM/strings.xml12
-rw-r--r--res/values-ro/strings.xml2
-rw-r--r--res/values/config.xml17
-rw-r--r--src/com/android/bluetooth/btservice/AdapterService.java28
-rw-r--r--src/com/android/bluetooth/btservice/RemoteDevices.java60
-rw-r--r--src/com/android/bluetooth/btservice/bluetooth.proto3
-rw-r--r--src/com/android/bluetooth/gatt/AdvertiseManager.java2
-rw-r--r--src/com/android/bluetooth/gatt/ContextMap.java16
-rw-r--r--src/com/android/bluetooth/gatt/GattService.java30
-rw-r--r--src/com/android/bluetooth/gatt/HandleMap.java2
-rw-r--r--src/com/android/bluetooth/gatt/ScanManager.java31
-rw-r--r--src/com/android/bluetooth/hfp/HeadsetHalConstants.java4
-rw-r--r--src/com/android/bluetooth/hfp/HeadsetService.java24
-rwxr-xr-x[-rw-r--r--]src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java1
-rwxr-xr-xsrc/com/android/bluetooth/map/BluetoothMapContent.java16
-rwxr-xr-xsrc/com/android/bluetooth/map/BluetoothMapContentObserver.java87
-rw-r--r--src/com/android/bluetooth/map/BluetoothMapMessageListingElement.java9
-rw-r--r--src/com/android/bluetooth/map/BluetoothMapObexServer.java40
-rwxr-xr-xsrc/com/android/bluetooth/map/BluetoothMapService.java1
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppHandoverReceiver.java40
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java6
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java1
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppUtility.java3
-rwxr-xr-xsrc/com/android/bluetooth/pan/PanService.java4
-rw-r--r--src/com/android/bluetooth/pbap/BluetoothPbapReceiver.java11
-rw-r--r--src/com/android/bluetooth/util/Interop.java87
33 files changed, 443 insertions, 114 deletions
diff --git a/jni/com_android_bluetooth_a2dp.cpp b/jni/com_android_bluetooth_a2dp.cpp
index 912a772e2..b2f2f8b55 100644
--- a/jni/com_android_bluetooth_a2dp.cpp
+++ b/jni/com_android_bluetooth_a2dp.cpp
@@ -203,6 +203,11 @@ static void initNative(JNIEnv *env, jobject object, jint maxA2dpConnections,
mCallbacksObj = NULL;
}
+ if ((mCallbacksObj = env->NewGlobalRef(object)) == NULL) {
+ ALOGE("Failed to allocate Global Ref for A2DP Callbacks");
+ return;
+ }
+
if ( (sBluetoothA2dpInterface = (btav_interface_t *)
btInf->get_profile_interface(BT_PROFILE_ADVANCED_AUDIO_ID)) == NULL) {
ALOGE("Failed to get Bluetooth A2DP Interface");
@@ -216,8 +221,6 @@ static void initNative(JNIEnv *env, jobject object, jint maxA2dpConnections,
sBluetoothA2dpInterface = NULL;
return;
}
-
- mCallbacksObj = env->NewGlobalRef(object);
}
static void cleanupNative(JNIEnv *env, jobject object) {
diff --git a/jni/com_android_bluetooth_hfp.cpp b/jni/com_android_bluetooth_hfp.cpp
index 839a3d670..beacfa886 100644
--- a/jni/com_android_bluetooth_hfp.cpp
+++ b/jni/com_android_bluetooth_hfp.cpp
@@ -726,7 +726,6 @@ static jboolean cindResponseNative(JNIEnv *env, jobject object,
return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}
-
static jboolean atResponseStringNative(JNIEnv *env, jobject object, jstring response_str,
jbyteArray address) {
jbyte *addr;
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 53ce8179f..ed31bb1b1 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -27,7 +27,7 @@
<string name="airplane_error_msg" msgid="8698965595254137230">"No pots utilitzar Bluetooth en mode d\'avió."</string>
<string name="bt_enable_title" msgid="8657832550503456572"></string>
<string name="bt_enable_line1" msgid="7203551583048149">"Per utilitzar serveis Bluetooth, primer cal que activeu el Bluetooth."</string>
- <string name="bt_enable_line2" msgid="4341936569415937994">"Voleu activar el Bluetooth ara?"</string>
+ <string name="bt_enable_line2" msgid="4341936569415937994">"Vols activar el Bluetooth ara?"</string>
<string name="bt_enable_cancel" msgid="1988832367505151727">"Cancel·la"</string>
<string name="bt_enable_ok" msgid="3432462749994538265">"Activa"</string>
<string name="incoming_file_confirm_title" msgid="8139874248612182627">"Transferència del fitxer"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 9e390dd9a..bdffe8634 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -99,7 +99,7 @@
<string name="status_no_sd_card" product="default" msgid="5760944071743325592">"‏هیچ کارت SD موجود نیست. برای ذخیره فایل‌های منتقل شده، یک کارت SD در گوشی قرار دهید."</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="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="upload_success" msgid="4014469387779648949">"<xliff:g id="FILE_SIZE">%1$s</xliff:g> ارسال کامل شد."</string>
diff --git a/res/values-fa/strings_pbap.xml b/res/values-fa/strings_pbap.xml
index 945d4426a..0667ebbee 100644
--- a/res/values-fa/strings_pbap.xml
+++ b/res/values-fa/strings_pbap.xml
@@ -5,7 +5,7 @@
<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="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="defaultname" msgid="4821590500649090078">"کیت خودرو"</string>
diff --git a/res/values-hy-rAM/strings.xml b/res/values-hy-rAM/strings.xml
index ed242a940..efef63b5c 100644
--- a/res/values-hy-rAM/strings.xml
+++ b/res/values-hy-rAM/strings.xml
@@ -23,8 +23,8 @@
<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">"Դուք չեք կարող օգտվել Bluetooth-ից ինքնաթիռային ռեժիմում:"</string>
+ <string name="airplane_error_title" msgid="2683839635115739939">"Ինքնաթիռի ռեժիմ"</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">"Bluetooth ծառայություններից օգտվելու համար նախ պետք է միացնեք Bluetooth-ը:"</string>
<string name="bt_enable_line2" msgid="4341936569415937994">"Միացնե՞լ Bluetooth-ը հիմա:"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index a7ae86f1d..69cf285a1 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -16,7 +16,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">"Pasiekti atsisiuntimo tvarkyklę."</string>
+ <string name="permlab_bluetoothShareManager" msgid="311492132450338925">"Pasiekti atsisiuntimo tvarkytuvę."</string>
<string name="permdesc_bluetoothShareManager" msgid="8930572979123190223">"Leidžiama programai pasiekti „BluetoothShare“ tvarkyklę ir naudoti ją failams perkelti."</string>
<string name="permlab_bluetoothWhitelist" msgid="7091552898592306386">"Į baltąjį sąrašą įtraukto „Bluetooth“ įrenginio prieiga."</string>
<string name="permdesc_bluetoothWhitelist" msgid="5494513855192170109">"Leidžiama programai laikinai į baltąjį sąrašą įtraukti „Bluetooth“ įrenginį, suteikiant jam galimybę siųsti failus į šį įrenginį be naudotojo patvirtinimo."</string>
diff --git a/res/values-my-rMM/strings.xml b/res/values-my-rMM/strings.xml
index a71b29839..2bbb0106f 100644
--- a/res/values-my-rMM/strings.xml
+++ b/res/values-my-rMM/strings.xml
@@ -19,7 +19,7 @@
<string name="permlab_bluetoothShareManager" msgid="311492132450338925">"ဒေါင်းလုပ်မန်နေဂျာကို အသုံးပြုနိုင်မည်"</string>
<string name="permdesc_bluetoothShareManager" msgid="8930572979123190223">"အပလီကေးရှင်းအား ဘလူးတုသ်မျှဝေမှု မန်နေဂျာကို အသုံးပြုခွင့်ပေးပြီး ဖိုင်လွှဲရန် အသုံးပြုပါ"</string>
<string name="permlab_bluetoothWhitelist" msgid="7091552898592306386">"ဘလူးတုသ်ယာယီခွင့်ပြုစာရင်းကို အသုံးပြုခွင့်"</string>
- <string name="permdesc_bluetoothWhitelist" msgid="5494513855192170109">"အပလီကေးရှင်းအား ဘလူးတုသ်စက်ကို ယာယီခွင့်ပြုစာရင်းထဲ ထည့်ရန်ခွင့်ပြုကာ အသုံးပြုသူ၏ အတည်ပြုချက်မရယူပဲ ဖိုင်များကို စက်ထဲသို့ ပို့ခွင့်ပြုမည်"</string>
+ <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>
@@ -28,7 +28,7 @@
<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>
@@ -120,12 +120,12 @@
<string name="transfer_menu_clear_all" msgid="790017462957873132">"စာရင်းကို ဖယ်ရှားရန်"</string>
<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_settings_save" msgid="7635491847388074606">"သိမ်းဆည်းရန်"</string>
- <string name="bluetooth_map_settings_cancel" msgid="9205350798049865699">"မလုပ်တော့ပါ"</string>
+ <string name="transfer_clear_dlg_title" msgid="2953444575556460386">"ရှင်းရန်"</string>
+ <string name="bluetooth_map_settings_save" msgid="7635491847388074606">"သိမ်းရန်"</string>
+ <string name="bluetooth_map_settings_cancel" msgid="9205350798049865699">"မလုပ်တော့"</string>
<string name="bluetooth_map_settings_intro" msgid="6482369468223987562">"ဘလူးတုသ်မှ မျှဝေလိုသော အကောင့်များကို ရွေးပါ။ ချိတ်ဆက်သည့်အခါ အကောင့်များအား ဝင်ခွင့်ပြုဖို့ လက်ခံပေးရပါလိမ့်ဦးမည်။"</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">"ဘလူးတုသ် စာ မျှဝေရေး ဆက်တင်များ"</string>
<string name="bluetooth_map_settings_no_account_slots_left" msgid="1796029082612965251">"ရွေးထားသည့် အကောင့်ကို မရွေးနိုင်ပါ။ သုည အပေါက်များ ကျန်နေ"</string>
<string name="bluetooth_connected" msgid="6718623220072656906">"ဘလူးတုသ်အသံ ချိတ်ဆက်ပြီးပါပြီ"</string>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 9a4a53648..85423d718 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -82,7 +82,7 @@
<string name="bt_toast_2" msgid="8602553334099066582">"Fișierul nu poate fi primit."</string>
<string name="bt_toast_3" msgid="6707884165086862518">"Primirea fișierului de la „<xliff:g id="SENDER">%1$s</xliff:g>” a fost anulată"</string>
<string name="bt_toast_4" msgid="4678812947604395649">"Se trimite fișierul către „<xliff:g id="RECIPIENT">%1$s</xliff:g>”"</string>
- <string name="bt_toast_5" msgid="2846870992823019494">"Se trimit <xliff:g id="NUMBER">%1$s</xliff:g> (de) fișiere către „<xliff:g id="RECIPIENT">%2$s</xliff:g>”"</string>
+ <string name="bt_toast_5" msgid="2846870992823019494">"Se trimit <xliff:g id="NUMBER">%1$s</xliff:g> fișiere către „<xliff:g id="RECIPIENT">%2$s</xliff:g>”"</string>
<string name="bt_toast_6" msgid="1855266596936622458">"Trimiterea fișierului către „<xliff:g id="RECIPIENT">%1$s</xliff:g>” a fost anulată"</string>
<string name="bt_sm_2_1" product="nosdcard" msgid="352165168004521000">"Nu există spațiu suficient pe stocarea USB pentru a salva fișierul de la „<xliff:g id="SENDER">%1$s</xliff:g>”"</string>
<string name="bt_sm_2_1" product="default" msgid="1989018443456803630">"Nu există suficient spațiu pe cardul SD pentru a salva fișierul de la „<xliff:g id="SENDER">%1$s</xliff:g>”"</string>
diff --git a/res/values/config.xml b/res/values/config.xml
index dcbe20837..90e513d36 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -35,14 +35,25 @@
of the location permissions. -->
<bool name="strict_location_check">true</bool>
- <!-- Specifies the min/max connection interval parameters for high priority
- and low power GATT configurations. These values are in multiples of
- 1.25ms. -->
+ <!-- Specifies the min/max connection interval parameters for high priority,
+ balanced and low power GATT configurations. These values are in
+ multiples of 1.25ms. -->
<integer name="gatt_high_priority_min_interval">9</integer>
<integer name="gatt_high_priority_max_interval">12</integer>
+ <!-- Default specs recommended interval is 30 (24 * 1.25) -> 50 (40 * 1.25)
+ ms. -->
+ <integer name="gatt_balanced_priority_min_interval">24</integer>
+ <integer name="gatt_balanced_priority_max_interval">40</integer>
<integer name="gatt_low_power_min_interval">80</integer>
<integer name="gatt_low_power_max_interval">100</integer>
+ <!-- Specifies latency parameters for high priority, balanced and low power
+ GATT configurations. These values represents the number of packets a
+ slave device is allowed to skip. -->
+ <integer name="gatt_high_priority_latency">0</integer>
+ <integer name="gatt_balanced_priority_latency">0</integer>
+ <integer name="gatt_low_power_latency">2</integer>
+
<bool name="headset_client_initial_audio_route_allowed">true</bool>
<!-- For AVRCP absolute volume feature. If the threshold is non-zero,
diff --git a/src/com/android/bluetooth/btservice/AdapterService.java b/src/com/android/bluetooth/btservice/AdapterService.java
index 4dcca00b0..f4d029796 100644
--- a/src/com/android/bluetooth/btservice/AdapterService.java
+++ b/src/com/android/bluetooth/btservice/AdapterService.java
@@ -89,7 +89,8 @@ import android.os.SystemProperties;
public class AdapterService extends Service {
private static final String TAG = "BluetoothAdapterService";
- private static final boolean DBG = false;
+ private static final boolean DBG = true;
+ private static final boolean VERBOSE = false;
private static final boolean TRACE_REF = false;
private static final int MIN_ADVT_INSTANCES_FOR_MA = 5;
private static final int MIN_OFFLOADED_FILTERS = 10;
@@ -539,6 +540,8 @@ public class AdapterService extends Service {
mProfileObserver = new ProfileObserver(getApplicationContext(), this, new Handler());
mProfileObserver.start();
mVendor.init();
+
+ setAdapterService(this);
}
@Override
@@ -594,9 +597,6 @@ public class AdapterService extends Service {
// Ignore.
}
- //FIXME: Set static instance here???
- setAdapterService(this);
-
//Start Gatt service
setGattProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON);
}
@@ -2680,11 +2680,12 @@ public class AdapterService extends Service {
}
}
- debugLog("energyInfoCallback() status = " + status +
- "tx_time = " + tx_time + "rx_time = " + rx_time +
- "idle_time = " + idle_time + "energy_used = " + energy_used +
- "ctrl_state = " + ctrl_state +
- "traffic = " + Arrays.toString(data));
+ verboseLog("energyInfoCallback() status = " + status +
+ "tx_time = " + tx_time + "rx_time = " + rx_time +
+ "idle_time = " + idle_time +
+ "energy_used = " + energy_used +
+ "ctrl_state = " + ctrl_state +
+ "traffic = " + Arrays.toString(data));
}
private int getIdleCurrentMa() {
@@ -2730,8 +2731,8 @@ public class AdapterService extends Service {
enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
if (args.length > 0) {
- debugLog("dumpsys arguments, check for protobuf output: " +
- TextUtils.join(" ", args));
+ verboseLog("dumpsys arguments, check for protobuf output: "
+ + TextUtils.join(" ", args));
if (args[0].startsWith("--proto")) {
if (args[0].equals("--proto-java-bin")) {
dumpJava(fd);
@@ -2779,6 +2780,7 @@ public class AdapterService extends Service {
private void dumpJava(FileDescriptor fd) {
BluetoothProto.BluetoothLog log = new BluetoothProto.BluetoothLog();
+ log.setNumBondedDevices(getBondedDevices().length);
for (ProfileService profile : mProfiles) {
profile.dumpProto(log);
@@ -2806,6 +2808,10 @@ public class AdapterService extends Service {
if (DBG) Log.d(TAG, msg);
}
+ private void verboseLog(String msg) {
+ if (VERBOSE) Log.v(TAG, msg);
+ }
+
private void errorLog(String msg) {
Log.e(TAG, msg);
}
diff --git a/src/com/android/bluetooth/btservice/RemoteDevices.java b/src/com/android/bluetooth/btservice/RemoteDevices.java
index 19089a742..94c469d8f 100644
--- a/src/com/android/bluetooth/btservice/RemoteDevices.java
+++ b/src/com/android/bluetooth/btservice/RemoteDevices.java
@@ -30,12 +30,15 @@ import com.android.bluetooth.Utils;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.ArrayList;
import java.util.HashMap;
-
+import java.util.LinkedList;
+import java.util.Queue;
final class RemoteDevices {
private static final boolean DBG = false;
private static final String TAG = "BluetoothRemoteDevices";
+ // Maximum number of device properties to remember
+ private static final int MAX_DEVICE_QUEUE_SIZE = 200;
private static BluetoothAdapter mAdapter;
private static AdapterService mAdapterService;
@@ -45,13 +48,15 @@ final class RemoteDevices {
private static final int UUID_INTENT_DELAY = 6000;
private static final int MESSAGE_UUID_INTENT = 1;
- private HashMap<BluetoothDevice, DeviceProperties> mDevices;
+ private HashMap<String, DeviceProperties> mDevices;
+ private Queue<String> mDeviceQueue;
RemoteDevices(AdapterService service) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
mAdapterService = service;
mSdpTracker = new ArrayList<BluetoothDevice>();
- mDevices = new HashMap<BluetoothDevice, DeviceProperties>();
+ mDevices = new HashMap<String, DeviceProperties>();
+ mDeviceQueue = new LinkedList<String>();
}
@@ -61,6 +66,9 @@ final class RemoteDevices {
if (mDevices != null)
mDevices.clear();
+
+ if (mDeviceQueue != null)
+ mDeviceQueue.clear();
}
@Override
@@ -70,28 +78,36 @@ final class RemoteDevices {
DeviceProperties getDeviceProperties(BluetoothDevice device) {
synchronized (mDevices) {
- return mDevices.get(device);
+ return mDevices.get(device.getAddress());
}
}
BluetoothDevice getDevice(byte[] address) {
- synchronized (mDevices) {
- for (BluetoothDevice dev : mDevices.keySet()) {
- if (dev.getAddress().equals(Utils.getAddressStringFromByte(address))) {
- return dev;
- }
- }
- }
- return null;
+ DeviceProperties prop = mDevices.get(Utils.getAddressStringFromByte(address));
+ if (prop == null)
+ return null;
+ return prop.getDevice();
}
DeviceProperties addDeviceProperties(byte[] address) {
synchronized (mDevices) {
DeviceProperties prop = new DeviceProperties();
- BluetoothDevice device =
- mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address));
+ prop.mDevice = mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address));
prop.mAddress = address;
- mDevices.put(device, prop);
+ String key = Utils.getAddressStringFromByte(address);
+ DeviceProperties pv = mDevices.put(key, prop);
+
+ if (pv == null) {
+ mDeviceQueue.offer(key);
+ if (mDeviceQueue.size() > MAX_DEVICE_QUEUE_SIZE) {
+ String deleteKey = mDeviceQueue.poll();
+ for (BluetoothDevice device : mAdapterService.getBondedDevices()) {
+ if (device.getAddress().equals(deleteKey)) return prop;
+ }
+ debugLog("Removing device " + deleteKey + " from property map");
+ mDevices.remove(deleteKey);
+ }
+ }
return prop;
}
}
@@ -105,6 +121,7 @@ final class RemoteDevices {
private int mDeviceType;
private String mAlias;
private int mBondState;
+ private BluetoothDevice mDevice;
DeviceProperties() {
mBondState = BluetoothDevice.BOND_NONE;
@@ -147,6 +164,15 @@ final class RemoteDevices {
}
/**
+ * @return the mDevice
+ */
+ BluetoothDevice getDevice() {
+ synchronized (mObject) {
+ return mDevice;
+ }
+ }
+
+ /**
* @return mRssi
*/
short getRssi() {
@@ -235,6 +261,7 @@ final class RemoteDevices {
BluetoothDevice bdDevice = getDevice(address);
DeviceProperties device;
if (bdDevice == null) {
+ debugLog("Added new device property");
device = addDeviceProperties(address);
bdDevice = getDevice(address);
} else {
@@ -244,11 +271,12 @@ final class RemoteDevices {
for (int j = 0; j < types.length && device != null; j++) {
type = types[j];
val = values[j];
- if(val.length <= 0)
+ if (val.length <= 0)
errorLog("devicePropertyChangedCallback: bdDevice: " + bdDevice
+ ", value is empty for type: " + type);
else {
synchronized(mObject) {
+ debugLog("Property type: " + type);
switch (type) {
case AbstractionLayer.BT_PROPERTY_BDNAME:
device.mName = new String(val);
diff --git a/src/com/android/bluetooth/btservice/bluetooth.proto b/src/com/android/bluetooth/btservice/bluetooth.proto
index 11311ea58..77ded7807 100644
--- a/src/com/android/bluetooth/btservice/bluetooth.proto
+++ b/src/com/android/bluetooth/btservice/bluetooth.proto
@@ -25,6 +25,9 @@ message BluetoothLog {
// Scan event information.
repeated ScanEvent scan_event = 4;
+
+ // Number of bonded devices.
+ optional int32 num_bonded_devices = 5;
}
// The information about the device.
diff --git a/src/com/android/bluetooth/gatt/AdvertiseManager.java b/src/com/android/bluetooth/gatt/AdvertiseManager.java
index 058bf4b59..3fb4aa945 100644
--- a/src/com/android/bluetooth/gatt/AdvertiseManager.java
+++ b/src/com/android/bluetooth/gatt/AdvertiseManager.java
@@ -194,7 +194,7 @@ class AdvertiseManager {
private void handleStartAdvertising(AdvertiseClient client) {
Utils.enforceAdminPermission(mService);
int clientIf = client.clientIf;
- if (mAdvertiseClients.contains(clientIf)) {
+ if (mAdvertiseClients.contains(client)) {
postCallback(clientIf, AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED);
return;
}
diff --git a/src/com/android/bluetooth/gatt/ContextMap.java b/src/com/android/bluetooth/gatt/ContextMap.java
index e3044d586..024572792 100644
--- a/src/com/android/bluetooth/gatt/ContextMap.java
+++ b/src/com/android/bluetooth/gatt/ContextMap.java
@@ -190,6 +190,7 @@ import com.android.bluetooth.btservice.BluetoothProto;
while (i.hasNext()) {
App entry = i.next();
if (entry.id == id) {
+ removeConnectionsByAppId(id);
entry.unlinkToDeath();
entry.appScanStats.isRegistered = false;
i.remove();
@@ -205,7 +206,7 @@ import com.android.bluetooth.btservice.BluetoothProto;
void addConnection(int id, int connId, String address) {
synchronized (mConnections) {
App entry = getById(id);
- if (entry != null){
+ if (entry != null) {
mConnections.add(new Connection(connId, address, id));
}
}
@@ -228,6 +229,19 @@ import com.android.bluetooth.btservice.BluetoothProto;
}
/**
+ * Remove all connections for a given application ID.
+ */
+ void removeConnectionsByAppId(int appId) {
+ Iterator<Connection> i = mConnections.iterator();
+ while (i.hasNext()) {
+ Connection connection = i.next();
+ if (connection.appId == appId) {
+ i.remove();
+ }
+ }
+ }
+
+ /**
* Get an application context by ID.
*/
App getById(int id) {
diff --git a/src/com/android/bluetooth/gatt/GattService.java b/src/com/android/bluetooth/gatt/GattService.java
index 0595ae510..f8bef759d 100644
--- a/src/com/android/bluetooth/gatt/GattService.java
+++ b/src/com/android/bluetooth/gatt/GattService.java
@@ -237,6 +237,7 @@ public class GattService extends ProfileService {
boolean permissionCheck(int connId, int handle) {
List<BluetoothGattService> db = gattClientDatabases.get(connId);
+ if (db == null) return true;
for (BluetoothGattService service : db) {
for (BluetoothGattCharacteristic characteristic: service.getCharacteristics()) {
@@ -759,7 +760,15 @@ public class GattService extends ProfileService {
void onSearchCompleted(int connId, int status) throws RemoteException {
if (DBG) Log.d(TAG, "onSearchCompleted() - connId=" + connId+ ", status=" + status);
// Gatt DB is ready!
- gattClientGetGattDbNative(connId);
+
+ // This callback was called from the jni_workqueue thread. If we make request to the stack
+ // on the same thread, it might cause deadlock. Schedule request on a new thread instead.
+ Thread t = new Thread(new Runnable() {
+ public void run() {
+ gattClientGetGattDbNative(connId);
+ }
+ });
+ t.start();
}
GattDbElement GetSampleGattDbElement() {
@@ -1638,12 +1647,11 @@ public class GattService extends ProfileService {
void connectionParameterUpdate(int clientIf, String address, int connectionPriority) {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- // Default spec recommended interval is 30->50 ms
- int minInterval = 24; // 24 * 1.25ms = 30ms
- int maxInterval = 40; // 40 * 1.25ms = 50ms
+ int minInterval;
+ int maxInterval;
// Slave latency
- int latency = 0;
+ int latency;
// Link supervision timeout is measured in N * 10ms
int timeout = 2000; // 20s
@@ -1653,12 +1661,22 @@ public class GattService extends ProfileService {
case BluetoothGatt.CONNECTION_PRIORITY_HIGH:
minInterval = getResources().getInteger(R.integer.gatt_high_priority_min_interval);
maxInterval = getResources().getInteger(R.integer.gatt_high_priority_max_interval);
+ latency = getResources().getInteger(R.integer.gatt_high_priority_latency);
break;
case BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER:
minInterval = getResources().getInteger(R.integer.gatt_low_power_min_interval);
maxInterval = getResources().getInteger(R.integer.gatt_low_power_max_interval);
- latency = 2;
+ latency = getResources().getInteger(R.integer.gatt_low_power_latency);
+ break;
+
+ default:
+ // Using the values for CONNECTION_PRIORITY_BALANCED.
+ minInterval =
+ getResources().getInteger(R.integer.gatt_balanced_priority_min_interval);
+ maxInterval =
+ getResources().getInteger(R.integer.gatt_balanced_priority_max_interval);
+ latency = getResources().getInteger(R.integer.gatt_balanced_priority_latency);
break;
}
diff --git a/src/com/android/bluetooth/gatt/HandleMap.java b/src/com/android/bluetooth/gatt/HandleMap.java
index 4a2063984..27a7a7194 100644
--- a/src/com/android/bluetooth/gatt/HandleMap.java
+++ b/src/com/android/bluetooth/gatt/HandleMap.java
@@ -69,7 +69,6 @@ class HandleMap {
this.type = type;
this.handle = handle;
this.uuid = uuid;
- this.instance = instance;
this.serviceHandle = serviceHandle;
}
@@ -78,7 +77,6 @@ class HandleMap {
this.type = type;
this.handle = handle;
this.uuid = uuid;
- this.instance = instance;
this.serviceHandle = serviceHandle;
this.charHandle = charHandle;
}
diff --git a/src/com/android/bluetooth/gatt/ScanManager.java b/src/com/android/bluetooth/gatt/ScanManager.java
index b20a54f3f..621359724 100644
--- a/src/com/android/bluetooth/gatt/ScanManager.java
+++ b/src/com/android/bluetooth/gatt/ScanManager.java
@@ -40,11 +40,13 @@ import com.android.bluetooth.btservice.AdapterService;
import com.android.internal.app.IBatteryStats;
import java.util.ArrayDeque;
+import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -95,8 +97,8 @@ public class ScanManager {
private CountDownLatch mLatch;
ScanManager(GattService service) {
- mRegularScanClients = new HashSet<ScanClient>();
- mBatchClients = new HashSet<ScanClient>();
+ mRegularScanClients = Collections.newSetFromMap(new ConcurrentHashMap<ScanClient, Boolean>());
+ mBatchClients = Collections.newSetFromMap(new ConcurrentHashMap<ScanClient, Boolean>());
mService = service;
mScanNative = new ScanNative();
curUsedTrackableAdvertisements = 0;
@@ -238,11 +240,11 @@ public class ScanManager {
if (!mScanNative.isOpportunisticScanClient(client)) {
mScanNative.configureRegularScanParams();
- if (!mScanNative.isFirstMatchScanClient(client)) {
+ if (!mScanNative.isExemptFromScanDowngrade(client)) {
Message msg = mHandler.obtainMessage(MSG_SCAN_TIMEOUT);
msg.obj = client;
// Only one timeout message should exist at any time
- mHandler.removeMessages(SCAN_TIMEOUT_MS);
+ mHandler.removeMessages(MSG_SCAN_TIMEOUT);
mHandler.sendMessageDelayed(msg, SCAN_TIMEOUT_MS);
}
}
@@ -261,10 +263,6 @@ public class ScanManager {
if (client == null) return;
if (mRegularScanClients.contains(client)) {
- // The ScanClient passed in just holds the clientIf. We retrieve the real client,
- // which may have workSource set.
- client = mScanNative.getRegularScanClient(client.clientIf);
- if (client == null) return;
mScanNative.stopRegularScan(client);
@@ -278,7 +276,11 @@ public class ScanManager {
// Update BatteryStats with this workload.
try {
- mBatteryStats.noteBleScanStopped(client.workSource);
+ // The ScanClient passed in just holds the clientIf. We retrieve the real client,
+ // which may have workSource set.
+ ScanClient workClient = mScanNative.getRegularScanClient(client.clientIf);
+ if (workClient != null)
+ mBatteryStats.noteBleScanStopped(workClient.workSource);
} catch (RemoteException e) {
/* ignore */
}
@@ -534,6 +536,12 @@ public class ScanManager {
}
}
+ private boolean isExemptFromScanDowngrade(ScanClient client) {
+ return isOpportunisticScanClient(client)
+ || isFirstMatchScanClient(client)
+ || !shouldUseAllPassFilter(client);
+ }
+
private boolean isOpportunisticScanClient(ScanClient client) {
return client.settings.getScanMode() == ScanSettings.SCAN_MODE_OPPORTUNISTIC;
}
@@ -683,8 +691,9 @@ public class ScanManager {
void regularScanTimeout() {
for (ScanClient client : mRegularScanClients) {
- if (!isOpportunisticScanClient(client) && !isFirstMatchScanClient(client)) {
- logd("clientIf set to scan opportunisticly: " + client.clientIf);
+ if (!isExemptFromScanDowngrade(client)) {
+ Log.w(TAG, "Moving scan client to opportunistic (clientIf "
+ + client.clientIf + ")");
setOpportunisticScanClient(client);
client.stats.setScanTimeout();
}
diff --git a/src/com/android/bluetooth/hfp/HeadsetHalConstants.java b/src/com/android/bluetooth/hfp/HeadsetHalConstants.java
index 0742917c1..dee633f2d 100644
--- a/src/com/android/bluetooth/hfp/HeadsetHalConstants.java
+++ b/src/com/android/bluetooth/hfp/HeadsetHalConstants.java
@@ -64,4 +64,8 @@ final public class HeadsetHalConstants {
final static int CALL_STATE_INCOMING = 4;
final static int CALL_STATE_WAITING = 5;
final static int CALL_STATE_IDLE = 6;
+
+ // Match up with bthf_hf_ind_type_t of bt_hf.h
+ final static int HF_INDICATOR_ENHANCED_DRIVER_SAFETY = 1;
+ final static int HF_INDICATOR_BATTERY_LEVEL_STATUS = 2;
}
diff --git a/src/com/android/bluetooth/hfp/HeadsetService.java b/src/com/android/bluetooth/hfp/HeadsetService.java
index c61cb3cb6..09d2e32f1 100644
--- a/src/com/android/bluetooth/hfp/HeadsetService.java
+++ b/src/com/android/bluetooth/hfp/HeadsetService.java
@@ -331,6 +331,12 @@ public class HeadsetService extends ProfileService {
if (service == null) return false;
return service.disableWBS();
}
+
+ public void bindResponse(int ind_id, boolean ind_status) {
+ HeadsetService service = getService();
+ if (service == null) return;
+ service.bindResponse(ind_id, ind_status);
+ }
};
//API methods
@@ -639,6 +645,24 @@ public class HeadsetService extends ProfileService {
return true;
}
+ private boolean bindResponse(int ind_id, boolean ind_status) {
+ for (BluetoothDevice device: getConnectedDevices()) {
+ int connectionState = mStateMachine.getConnectionState(device);
+ if (connectionState != BluetoothProfile.STATE_CONNECTED &&
+ connectionState != BluetoothProfile.STATE_CONNECTING) {
+ continue;
+ }
+ if (DBG) Log.d("Bind Response sent for", device.getAddress());
+ Message msg = mStateMachine.obtainMessage(HeadsetStateMachine.BIND_RESPONSE);
+ msg.obj = device;
+ msg.arg1 = ind_id;
+ msg.arg2 = (ind_status == true) ? 1 : 0;
+ mStateMachine.sendMessage(msg);
+ return true;
+ }
+ return false;
+ }
+
@Override
public void dump(StringBuilder sb) {
super.dump(sb);
diff --git a/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java b/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java
index 05806fa59..76ef46301 100644..100755
--- a/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java
+++ b/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java
@@ -339,6 +339,7 @@ final class HeadsetClientStateMachine extends StateMachine {
Log.d(TAG, "Enter sendCallChangedIntent()");
Log.d(TAG, "sendCallChangedIntent " + c);
Intent intent = new Intent(BluetoothHeadsetClient.ACTION_CALL_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(BluetoothHeadsetClient.EXTRA_CALL, c);
mService.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
Log.d(TAG, "Exit sendCallChangedIntent()");
diff --git a/src/com/android/bluetooth/map/BluetoothMapContent.java b/src/com/android/bluetooth/map/BluetoothMapContent.java
index 2370a4d35..4f42bfb58 100755
--- a/src/com/android/bluetooth/map/BluetoothMapContent.java
+++ b/src/com/android/bluetooth/map/BluetoothMapContent.java
@@ -950,10 +950,14 @@ public class BluetoothMapContent {
address = c.getString(c.getColumnIndex(Sms.ADDRESS));
}
if ((address == null) && msgType == Sms.MESSAGE_TYPE_DRAFT) {
- //Fetch address for Drafts folder from "canonical_address" table
+ // Fetch address for Drafts folder from "canonical_address" table
int threadIdInd = c.getColumnIndex(Sms.THREAD_ID);
String threadIdStr = c.getString(threadIdInd);
- address = getCanonicalAddressSms(mResolver, Integer.valueOf(threadIdStr));
+ // If a draft message has no recipient, it has no thread ID
+ // hence threadIdStr could possibly be null
+ if (threadIdStr != null) {
+ address = getCanonicalAddressSms(mResolver, Integer.valueOf(threadIdStr));
+ }
if(V) Log.v(TAG, "threadId = " + threadIdStr + " adress:" + address +"\n");
}
} else if (fi.mMsgType == FilterInfo.TYPE_MMS) {
@@ -961,7 +965,7 @@ public class BluetoothMapContent {
address = getAddressMms(mResolver, id, MMS_TO);
} else if (fi.mMsgType == FilterInfo.TYPE_EMAIL) {
/* Might be another way to handle addresses */
- address = getRecipientAddressingEmail(e, c,fi);
+ address = getRecipientAddressingEmail(e, c, fi);
}
if (V) Log.v(TAG, "setRecipientAddressing: " + address);
if(address == null)
@@ -1603,7 +1607,8 @@ public class BluetoothMapContent {
} else if (BluetoothMapContract.FOLDER_NAME_SENT.equalsIgnoreCase(folder)) {
where = Sms.TYPE + " = 2 AND " + Sms.THREAD_ID + " <> -1";
} else if (BluetoothMapContract.FOLDER_NAME_DRAFT.equalsIgnoreCase(folder)) {
- where = Sms.TYPE + " = 3 AND " + Sms.THREAD_ID + " <> -1";
+ where = Sms.TYPE + " = 3 AND " +
+ "(" + Sms.THREAD_ID + " IS NULL OR " + Sms.THREAD_ID + " <> -1 )";
} else if (BluetoothMapContract.FOLDER_NAME_DELETED.equalsIgnoreCase(folder)) {
where = Sms.THREAD_ID + " = -1";
}
@@ -1620,7 +1625,8 @@ public class BluetoothMapContent {
} else if (BluetoothMapContract.FOLDER_NAME_SENT.equalsIgnoreCase(folder)) {
where = Mms.MESSAGE_BOX + " = 2 AND " + Mms.THREAD_ID + " <> -1";
} else if (BluetoothMapContract.FOLDER_NAME_DRAFT.equalsIgnoreCase(folder)) {
- where = Mms.MESSAGE_BOX + " = 3 AND " + Mms.THREAD_ID + " <> -1";
+ where = Mms.MESSAGE_BOX + " = 3 AND " +
+ "(" + Mms.THREAD_ID + " IS NULL OR " + Mms.THREAD_ID + " <> -1 )";
} else if (BluetoothMapContract.FOLDER_NAME_DELETED.equalsIgnoreCase(folder)) {
where = Mms.THREAD_ID + " = -1";
}
diff --git a/src/com/android/bluetooth/map/BluetoothMapContentObserver.java b/src/com/android/bluetooth/map/BluetoothMapContentObserver.java
index 878f5bedf..c70408ccb 100755
--- a/src/com/android/bluetooth/map/BluetoothMapContentObserver.java
+++ b/src/com/android/bluetooth/map/BluetoothMapContentObserver.java
@@ -37,6 +37,7 @@ import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
+import android.os.UserManager;
import android.provider.Telephony;
import android.provider.Telephony.Mms;
import android.provider.Telephony.MmsSms;
@@ -172,7 +173,9 @@ public class BluetoothMapContentObserver {
public static final String EXTRA_MESSAGE_SENT_TIMESTAMP = "timestamp";
private SmsBroadcastReceiver mSmsBroadcastReceiver = new SmsBroadcastReceiver();
+ private CeBroadcastReceiver mCeBroadcastReceiver = new CeBroadcastReceiver();
+ private boolean mStorageUnlocked = false;
private boolean mInitialized = false;
@@ -480,6 +483,12 @@ public class BluetoothMapContentObserver {
Log.w(TAG, "onChange() with URI == null - not handled.");
return;
}
+
+ if (!mStorageUnlocked) {
+ Log.v(TAG, "Ignore events until storage is completely unlocked");
+ return;
+ }
+
if (V) Log.d(TAG, "onChange on thread: " + Thread.currentThread().getId()
+ " Uri: " + uri.toString() + " selfchange: " + selfChange);
@@ -1184,9 +1193,10 @@ public class BluetoothMapContentObserver {
private void initMsgList() throws RemoteException {
if (V) Log.d(TAG, "initMsgList");
+ UserManager manager = UserManager.get(mContext);
+ if (manager == null || !manager.isUserUnlocked()) return;
- if(mEnableSmsMms) {
-
+ if (mEnableSmsMms) {
HashMap<Long, Msg> msgListSms = new HashMap<Long, Msg>();
Cursor c = mResolver.query(Sms.CONTENT_URI,
@@ -2361,21 +2371,19 @@ public class BluetoothMapContentObserver {
/* Approved MAP spec errata 3445 states that read status initiated
* by the MCE shall change the MSE read status. */
if (type == TYPE.SMS_GSM || type == TYPE.SMS_CDMA) {
- Uri uri = Sms.Inbox.CONTENT_URI;
+ Uri uri = ContentUris.withAppendedId(Sms.CONTENT_URI, handle);
ContentValues contentValues = new ContentValues();
contentValues.put(Sms.READ, statusValue);
contentValues.put(Sms.SEEN, statusValue);
- String where = Sms._ID+"="+handle;
String values = contentValues.toString();
- if (D) Log.d(TAG, " -> SMS Uri: " + uri.toString() +
- " Where " + where + " values " + values);
+ if (D) Log.d(TAG, " -> SMS Uri: " + uri.toString() + " values " + values);
synchronized(getMsgListSms()) {
Msg msg = getMsgListSms().get(handle);
if(msg != null) { // This will always be the case
msg.flagRead = statusValue;
}
}
- count = mResolver.update(uri, contentValues, where, null);
+ count = mResolver.update(uri, contentValues, null, null);
if (D) Log.d(TAG, " -> "+count +" rows updated!");
} else if (type == TYPE.MMS) {
@@ -2455,8 +2463,16 @@ public class BluetoothMapContentObserver {
long folderId = -1;
if (recipientList == null) {
- if (D) Log.d(TAG, "empty recipient list");
- return -1;
+ if (folderElement.getName().equalsIgnoreCase(BluetoothMapContract.FOLDER_NAME_DRAFT)) {
+ BluetoothMapbMessage.vCard empty =
+ new BluetoothMapbMessage.vCard("", "", null, null, 0);
+ recipientList = new ArrayList<BluetoothMapbMessage.vCard>();
+ recipientList.add(empty);
+ Log.w(TAG, "Added empty recipient to draft message");
+ } else {
+ Log.e(TAG, "Trying to send a message with no recipients");
+ return -1;
+ }
}
if ( msg.getType().equals(TYPE.EMAIL) ) {
@@ -3190,6 +3206,52 @@ public class BluetoothMapContentObserver {
}
}
+ private class CeBroadcastReceiver extends BroadcastReceiver {
+ public void register() {
+ UserManager manager = UserManager.get(mContext);
+ if (manager == null || manager.isUserUnlocked()) {
+ mStorageUnlocked = true;
+ return;
+ }
+
+ Handler handler = new Handler(Looper.getMainLooper());
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
+ mContext.registerReceiver(this, intentFilter, null, handler);
+ }
+
+ public void unregister() {
+ try {
+ mContext.unregisterReceiver(this);
+ } catch (IllegalArgumentException e) {
+ /* do nothing */
+ }
+ }
+
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ Log.d(TAG, "onReceive: action" + action);
+
+ if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
+ try {
+ initMsgList();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error initializing SMS/MMS message lists.");
+ }
+
+ for (String folder : FOLDER_SMS_MAP.values()) {
+ Event evt = new Event(EVENT_TYPE_NEW, -1, folder, mSmsType);
+ sendEvent(evt);
+ }
+ mStorageUnlocked = true;
+ /* After unlock this BroadcastReceiver is never needed */
+ unregister();
+ } else {
+ Log.d(TAG, "onReceive: Unknown action " + action);
+ }
+ }
+ }
+
/**
* Handle MMS sent intents in disconnected(MNS) state, where we do not need to send any
* notifications.
@@ -3331,6 +3393,8 @@ public class BluetoothMapContentObserver {
private void resendPendingMessages() {
/* Send pending messages in outbox */
String where = "type = " + Sms.MESSAGE_TYPE_OUTBOX;
+ UserManager manager = UserManager.get(mContext);
+ if (manager == null || !manager.isUserUnlocked()) return;
Cursor c = mResolver.query(Sms.CONTENT_URI, SMS_PROJECTION, where, null,
null);
try {
@@ -3398,6 +3462,11 @@ public class BluetoothMapContentObserver {
if (mSmsBroadcastReceiver != null) {
mSmsBroadcastReceiver.register();
}
+
+ if (mCeBroadcastReceiver != null) {
+ mCeBroadcastReceiver.register();
+ }
+
registerPhoneServiceStateListener();
mInitialized = true;
}
diff --git a/src/com/android/bluetooth/map/BluetoothMapMessageListingElement.java b/src/com/android/bluetooth/map/BluetoothMapMessageListingElement.java
index 88e5605de..832060e86 100644
--- a/src/com/android/bluetooth/map/BluetoothMapMessageListingElement.java
+++ b/src/com/android/bluetooth/map/BluetoothMapMessageListingElement.java
@@ -27,6 +27,7 @@ import android.util.Log;
import android.util.Xml;
import com.android.bluetooth.map.BluetoothMapUtils.TYPE;
+import com.android.bluetooth.util.Interop;
public class BluetoothMapMessageListingElement
implements Comparable<BluetoothMapMessageListingElement> {
@@ -276,9 +277,17 @@ public class BluetoothMapMessageListingElement
BluetoothMapUtils.getMapHandle(mCpHandle, mType));
if(mSubject != null){
String stripped = BluetoothMapUtils.stripInvalidChars(mSubject);
+
+ if (Interop.matchByAddress(Interop.INTEROP_MAP_ASCIIONLY,
+ BluetoothMapService.getRemoteDevice().getAddress())) {
+ stripped = stripped.replaceAll("[\\P{ASCII}&\"><]", "");
+ if (stripped.isEmpty()) stripped = "---";
+ }
+
xmlMsgElement.attribute(null, "subject",
stripped.substring(0, stripped.length() < 256 ? stripped.length() : 256));
}
+
if(mDateTime != 0)
xmlMsgElement.attribute(null, "datetime", this.getDateTimeString());
if(mSenderName != null)
diff --git a/src/com/android/bluetooth/map/BluetoothMapObexServer.java b/src/com/android/bluetooth/map/BluetoothMapObexServer.java
index f0c26b0de..00b290215 100644
--- a/src/com/android/bluetooth/map/BluetoothMapObexServer.java
+++ b/src/com/android/bluetooth/map/BluetoothMapObexServer.java
@@ -24,6 +24,7 @@ import android.os.Handler;
import android.os.Message;
import android.os.ParcelUuid;
import android.os.RemoteException;
+import android.os.UserManager;
import android.text.format.DateUtils;
import android.util.Log;
@@ -402,6 +403,11 @@ public class BluetoothMapObexServer extends ServerRequestHandler {
return ResponseCodes.OBEX_HTTP_OK;
}
+ private boolean isUserUnlocked() {
+ UserManager manager = UserManager.get(mContext);
+ return (manager == null || manager.isUserUnlocked());
+ }
+
@Override
public int onPut(final Operation op) {
if (D) Log.d(TAG, "onPut(): enter");
@@ -431,26 +437,34 @@ public class BluetoothMapObexServer extends ServerRequestHandler {
return ResponseCodes.OBEX_HTTP_OK;
}
return updateInbox();
- }else if(type.equals(TYPE_SET_NOTIFICATION_REGISTRATION)) {
+ } else if (type.equals(TYPE_SET_NOTIFICATION_REGISTRATION)) {
if(V) {
Log.d(TAG,"TYPE_SET_NOTIFICATION_REGISTRATION: NotificationStatus: "
+ appParams.getNotificationStatus());
}
return mObserver.setNotificationRegistration(appParams.getNotificationStatus());
- }else if(type.equals(TYPE_SET_NOTIFICATION_FILTER)) {
+ } else if (type.equals(TYPE_SET_NOTIFICATION_FILTER)) {
if(V) {
Log.d(TAG,"TYPE_SET_NOTIFICATION_FILTER: NotificationFilter: "
+ appParams.getNotificationFilter());
}
+ if (!isUserUnlocked()) {
+ Log.e(TAG, "Storage locked, " + type + " failed");
+ return ResponseCodes.OBEX_HTTP_UNAVAILABLE;
+ }
mObserver.setNotificationFilter(appParams.getNotificationFilter());
return ResponseCodes.OBEX_HTTP_OK;
- } else if(type.equals(TYPE_SET_MESSAGE_STATUS)) {
+ } else if (type.equals(TYPE_SET_MESSAGE_STATUS)) {
if(V) {
Log.d(TAG,"TYPE_SET_MESSAGE_STATUS: " +
"StatusIndicator: " + appParams.getStatusIndicator()
+ ", StatusValue: " + appParams.getStatusValue()
+ ", ExtentedData: " + "" ); // TODO: appParams.getExtendedImData());
}
+ if (!isUserUnlocked()) {
+ Log.e(TAG, "Storage locked, " + type + " failed");
+ return ResponseCodes.OBEX_HTTP_UNAVAILABLE;
+ }
return setMessageStatus(name, appParams);
} else if (type.equals(TYPE_MESSAGE)) {
if(V) {
@@ -458,6 +472,10 @@ public class BluetoothMapObexServer extends ServerRequestHandler {
+ ", retry: " + appParams.getRetry()
+ ", charset: " + appParams.getCharset());
}
+ if (!isUserUnlocked()) {
+ Log.e(TAG, "Storage locked, " + type + " failed");
+ return ResponseCodes.OBEX_HTTP_UNAVAILABLE;
+ }
return pushMessage(op, name, appParams, mMessageVersion);
} else if (type.equals(TYPE_SET_OWNER_STATUS)) {
if(V) {
@@ -916,6 +934,10 @@ public class BluetoothMapObexServer extends ServerRequestHandler {
Log.d(TAG,"FilterConvoId = " + ((tmpLongLong == null) ? "" :
Long.toHexString(tmpLongLong.getLeastSignificantBits()) ) );
}
+ if (!isUserUnlocked()) {
+ Log.e(TAG, "Storage locked, " + type + " failed");
+ return ResponseCodes.OBEX_HTTP_UNAVAILABLE;
+ }
// Block until all packets have been send.
return sendMessageListingRsp(op, appParams, name);
@@ -930,6 +952,10 @@ public class BluetoothMapObexServer extends ServerRequestHandler {
Log.d(TAG,"FilterReadStatus = " + appParams.getFilterReadStatus());
Log.d(TAG,"FilterRecipient = " + appParams.getFilterRecipient());
}
+ if (!isUserUnlocked()) {
+ Log.e(TAG, "Storage locked, " + type + " failed");
+ return ResponseCodes.OBEX_HTTP_UNAVAILABLE;
+ }
// Block until all packets have been send.
return sendConvoListingRsp(op, appParams,name);
} else if (type.equals(TYPE_GET_MAS_INSTANCE_INFORMATION)) {
@@ -947,6 +973,10 @@ public class BluetoothMapObexServer extends ServerRequestHandler {
", Charset = " + appParams.getCharset() +
", FractionRequest = " + appParams.getFractionRequest());
}
+ if (!isUserUnlocked()) {
+ Log.e(TAG, "Storage locked, " + type + " failed");
+ return ResponseCodes.OBEX_HTTP_UNAVAILABLE;
+ }
// Block until all packets have been send.
return sendGetMessageRsp(op, name, appParams, mMessageVersion);
} else {
@@ -1028,8 +1058,8 @@ public class BluetoothMapObexServer extends ServerRequestHandler {
return ResponseCodes.OBEX_HTTP_BAD_REQUEST;
}
Log.v(TAG,"sendMessageListingRsp: has sms " + folderToList.hasSmsMmsContent() +
- "has email " + folderToList.hasEmailContent() +
- "has IM " + folderToList.hasImContent() );
+ ", has email " + folderToList.hasEmailContent() +
+ ", has IM " + folderToList.hasImContent() );
}
try {
diff --git a/src/com/android/bluetooth/map/BluetoothMapService.java b/src/com/android/bluetooth/map/BluetoothMapService.java
index 552bb09eb..addebf0c5 100755
--- a/src/com/android/bluetooth/map/BluetoothMapService.java
+++ b/src/com/android/bluetooth/map/BluetoothMapService.java
@@ -867,6 +867,7 @@ public class BluetoothMapService extends ProfileService {
sendShutdownMessage();
}
mStartError = true;
+ setState(BluetoothMap.STATE_DISCONNECTED, BluetoothMap.RESULT_CANCELED);
return true;
}
diff --git a/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiver.java b/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiver.java
index 2a51aa067..38873da12 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiver.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiver.java
@@ -42,31 +42,31 @@ public class BluetoothOppHandoverReceiver extends BroadcastReceiver {
if (D) Log.d(TAG, "No device attached to handover intent.");
return;
}
+
+ String mimeType = intent.getType();
+ ArrayList<Uri> uris = new ArrayList<Uri>();
if (action.equals(Constants.ACTION_HANDOVER_SEND)) {
- String type = intent.getType();
Uri stream = (Uri)intent.getParcelableExtra(Intent.EXTRA_STREAM);
- if (stream != null && type != null) {
- // Save type/stream, will be used when adding transfer
- // session to DB.
- BluetoothOppManager.getInstance(context).saveSendingFileInfo(type,
- stream.toString(), true);
- } else {
- if (D) Log.d(TAG, "No mimeType or stream attached to handover request");
- }
+ if (stream != null) uris.add(stream);
} else if (action.equals(Constants.ACTION_HANDOVER_SEND_MULTIPLE)) {
- ArrayList<Uri> uris = new ArrayList<Uri>();
- String mimeType = intent.getType();
uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
- if (mimeType != null && uris != null) {
- BluetoothOppManager.getInstance(context).saveSendingFileInfo(mimeType,
- uris, true);
- } else {
- if (D) Log.d(TAG, "No mimeType or stream attached to handover request");
- return;
- }
}
- // we already know where to send to
- BluetoothOppManager.getInstance(context).startTransfer(device);
+
+ if (mimeType != null && uris != null && !uris.isEmpty()) {
+ final String finalType = mimeType;
+ final ArrayList<Uri> finalUris = uris;
+ Thread t = new Thread(new Runnable() {
+ public void run() {
+ BluetoothOppManager.getInstance(context).saveSendingFileInfo(finalType,
+ finalUris, true);
+ BluetoothOppManager.getInstance(context).startTransfer(device);
+ }
+ });
+ t.start();
+ } else {
+ if (D) Log.d(TAG, "No mimeType or stream attached to handover request");
+ return;
+ }
} else if (action.equals(Constants.ACTION_WHITELIST_DEVICE)) {
BluetoothDevice device =
(BluetoothDevice)intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
diff --git a/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java b/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java
index 0f23bd382..59e7848b6 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java
@@ -476,13 +476,13 @@ public class BluetoothOppObexClientSession implements BluetoothOppObexSession {
outputStream.write(buffer, 0, readLength);
position += readLength;
+ /* check remote accept or reject */
+ responseCode = putOperation.getResponseCode();
mCallback.removeMessages(BluetoothOppObexSession.MSG_CONNECT_TIMEOUT);
synchronized (this) {
mWaitingForRemote = false;
}
- /* check remote accept or reject */
- responseCode = putOperation.getResponseCode();
if (responseCode == ResponseCodes.OBEX_HTTP_CONTINUE
|| responseCode == ResponseCodes.OBEX_HTTP_OK) {
@@ -595,7 +595,7 @@ public class BluetoothOppObexClientSession implements BluetoothOppObexSession {
} finally {
try {
if (outputStream != null) {
- outputStream.close();
+ outputStream.close();
}
// Close InputStream and remove SendFileInfo from map
diff --git a/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java b/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java
index 2a9cadb8b..f60f06cab 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java
@@ -123,6 +123,7 @@ public class BluetoothOppSendFileInfo {
Log.e(TAG, "generateFileInfo: " + e);
return new BluetoothOppSendFileInfo(fileName, contentType, length, null, 0);
}
+
if (metadataCursor != null) {
try {
if (metadataCursor.moveToFirst()) {
diff --git a/src/com/android/bluetooth/opp/BluetoothOppUtility.java b/src/com/android/bluetooth/opp/BluetoothOppUtility.java
index 8294246f0..99777a5ae 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppUtility.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppUtility.java
@@ -367,6 +367,9 @@ public class BluetoothOppUtility {
static void putSendFileInfo(Uri uri, BluetoothOppSendFileInfo sendFileInfo) {
if (D) Log.d(TAG, "putSendFileInfo: uri=" + uri + " sendFileInfo=" + sendFileInfo);
+ if (sendFileInfo == BluetoothOppSendFileInfo.SEND_FILE_INFO_ERROR) {
+ Log.e(TAG, "putSendFileInfo: bad sendFileInfo, URI: " + uri);
+ }
sSendFileMap.put(uri, sendFileInfo);
}
diff --git a/src/com/android/bluetooth/pan/PanService.java b/src/com/android/bluetooth/pan/PanService.java
index 05f92ffe0..6a43b9342 100755
--- a/src/com/android/bluetooth/pan/PanService.java
+++ b/src/com/android/bluetooth/pan/PanService.java
@@ -440,8 +440,8 @@ public class PanService extends ProfileService {
if (prevState == state) return;
if (remote_role == BluetoothPan.LOCAL_PANU_ROLE) {
if (state == BluetoothProfile.STATE_CONNECTED) {
- if((!mTetherOn)||(local_role == BluetoothPan.LOCAL_PANU_ROLE)){
- if(DBG) Log.d(TAG, "handlePanDeviceStateChange BT tethering is off/Local role"
+ if ((!mTetherOn) || (local_role == BluetoothPan.LOCAL_PANU_ROLE)) {
+ if (DBG) Log.d(TAG, "handlePanDeviceStateChange BT tethering is off/Local role"
+ " is PANU drop the connection");
mPanDevices.remove(device);
disconnectPanNative(Utils.getByteAddress(device));
diff --git a/src/com/android/bluetooth/pbap/BluetoothPbapReceiver.java b/src/com/android/bluetooth/pbap/BluetoothPbapReceiver.java
index a35ae5659..75388ee64 100644
--- a/src/com/android/bluetooth/pbap/BluetoothPbapReceiver.java
+++ b/src/com/android/bluetooth/pbap/BluetoothPbapReceiver.java
@@ -42,6 +42,8 @@ public class BluetoothPbapReceiver extends BroadcastReceiver {
private static final String TAG = "BluetoothPbapReceiver";
+ private static final boolean D = BluetoothPbapService.DEBUG;
+
private static final boolean V = Log.isLoggable(BluetoothPbapService.LOG_TAG, Log.VERBOSE);
@Override
@@ -52,12 +54,13 @@ public class BluetoothPbapReceiver extends BroadcastReceiver {
in.setClass(context, BluetoothPbapService.class);
String action = intent.getAction();
in.putExtra("action", action);
- Log.i(TAG, "Enter - onReceive for intent:" + action);
+ if (D) Log.d(TAG, "PbapReceiver onReceive action = " + action);
+
boolean startService = true;
if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
in.putExtra(BluetoothAdapter.EXTRA_STATE, state);
- Log.i(TAG, "State :" + state);
+ if (D) Log.d(TAG, "state = " + state);
if ((state == BluetoothAdapter.STATE_TURNING_ON)
|| (state == BluetoothAdapter.STATE_OFF)) {
//FIX: We turn on PBAP after BluetoothAdapter.STATE_ON,
@@ -68,11 +71,13 @@ public class BluetoothPbapReceiver extends BroadcastReceiver {
// Don't forward intent unless device has bluetooth and bluetooth is enabled.
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter == null || !adapter.isEnabled()) {
+ if (D) Log.d(TAG, "BluetoothAdapter is not enabled (" +
+ adapter + "). Would not start service.");
startService = false;
}
}
if (startService) {
- if (V) Log.v(TAG, "Calling start service!!!! with action = " + in.getAction());
+ if (D) Log.d(TAG, "Calling start service with action = " + in.getAction());
context.startService(in);
}
Log.i(TAG, "Exit - onReceive for intent:" + action);
diff --git a/src/com/android/bluetooth/util/Interop.java b/src/com/android/bluetooth/util/Interop.java
new file mode 100644
index 000000000..4861c154e
--- /dev/null
+++ b/src/com/android/bluetooth/util/Interop.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2016 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 java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Centralized Bluetooth Interoperability workaround utilities and database.
+ * This is the Java version. An analagous native version can be found
+ * in /system/bt/devices/include/interop_database.h.
+ */
+public class Interop {
+
+ /**
+ * Simple interop entry consisting of a workarond id (see below)
+ * and a (partial or complete) Bluetooth device address string
+ * to match against.
+ */
+ private static class Entry {
+ String address;
+ int workaround_id;
+
+ public Entry(int workaround_id, String address) {
+ this.workaround_id = workaround_id;
+ this.address = address;
+ }
+ }
+
+ /**
+ * The actual "database" of interop entries.
+ */
+ private static List<Entry> entries = null;
+
+ /**
+ * Workaround ID for deivces which do not accept non-ASCII
+ * characters in SMS messages.
+ */
+ public static final int INTEROP_MAP_ASCIIONLY = 1;
+
+ /**
+ * Initializes the interop datbase with the relevant workaround
+ * entries.
+ * When adding entries, please provide a description for each
+ * device as to what problem the workaround addresses.
+ */
+ private static void lazyInitInteropDatabase() {
+ if (entries != null) return;
+ entries = new ArrayList<Entry>();
+
+ /** Mercedes Benz NTG 4.5 does not handle non-ASCII characters in SMS */
+ entries.add(new Entry(INTEROP_MAP_ASCIIONLY, "00:26:e8"));
+ }
+
+ /**
+ * Checks wheter a given device identified by |address| is a match
+ * for a given workaround identified by |workaround_id|.
+ * Return true if the address matches, false otherwise.
+ */
+ public static boolean matchByAddress(int workaround_id, String address) {
+ if (address == null || address.isEmpty()) return false;
+
+ lazyInitInteropDatabase();
+ for (Entry entry : entries) {
+ if (entry.workaround_id == workaround_id &&
+ entry.address.startsWith(address.toLowerCase())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}