diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 6de6114759a..99272a426b9 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -58,7 +58,6 @@ - @@ -227,9 +226,6 @@ android:excludeFromRecents="true" android:theme="@android:style/Theme.Material.Light.Dialog.Alert" android:enabled="@bool/profile_supported_pbap"> - - - prepareCodecPreferences( static void initNative(JNIEnv* env, jobject object, jint maxConnectedAudioDevices, - jobjectArray codecConfigArray) { + jobjectArray codecConfigArray, + jobjectArray codecConfigOffload) { std::unique_lock interface_lock(interface_mutex); std::unique_lock callbacks_lock(callbacks_mutex); @@ -306,8 +307,10 @@ static void initNative(JNIEnv* env, jobject object, std::vector codec_priorities = prepareCodecPreferences(env, object, codecConfigArray); + std::vector offload_codec_supported = + prepareCodecPreferences(env, object, codecConfigOffload); bt_status_t status = sBluetoothA2dpInterface->init( - &sBluetoothA2dpCallbacks, maxConnectedAudioDevices, codec_priorities); + &sBluetoothA2dpCallbacks, maxConnectedAudioDevices, codec_priorities, offload_codec_supported); if (status != BT_STATUS_SUCCESS) { ALOGE("%s: Failed to initialize Bluetooth A2DP, status: %d", __func__, status); @@ -475,7 +478,7 @@ static jboolean setCodecConfigPreferenceNative(JNIEnv* env, jobject object, static JNINativeMethod sMethods[] = { {"classInitNative", "()V", (void*)classInitNative}, - {"initNative", "(I[Landroid/bluetooth/BluetoothCodecConfig;)V", + {"initNative", "(I[Landroid/bluetooth/BluetoothCodecConfig;[Landroid/bluetooth/BluetoothCodecConfig;)V", (void*)initNative}, {"cleanupNative", "()V", (void*)cleanupNative}, {"connectA2dpNative", "([B)Z", (void*)connectA2dpNative}, diff --git a/jni/com_android_bluetooth_gatt.cpp b/jni/com_android_bluetooth_gatt.cpp index 452151547fd..6e16cc113bc 100644 --- a/jni/com_android_bluetooth_gatt.cpp +++ b/jni/com_android_bluetooth_gatt.cpp @@ -1166,11 +1166,24 @@ void set_scan_params_cmpl_cb(int client_if, uint8_t status) { } static void gattSetScanParametersNative(JNIEnv* env, jobject object, - jint client_if, jint scan_interval_unit, - jint scan_window_unit) { + jint client_if, jint scan_phy, + jintArray scan_interval_unit, + jintArray scan_window_unit) { + std::vector scan_interval = {0,0}; + std::vector scan_window = {0,0}; if (!sGattIf) return; + + int scan_int_cnt = env->GetArrayLength(scan_interval_unit); + if(scan_int_cnt > 0) { + env->GetIntArrayRegion(scan_interval_unit, 0, scan_int_cnt, (jint *)&scan_interval[0]); + } + + int scan_window_cnt = env->GetArrayLength(scan_window_unit); + if(scan_window_cnt > 0) { + env->GetIntArrayRegion(scan_window_unit, 0, scan_window_cnt, (jint *)&scan_window[0]); + } sGattIf->scanner->SetScanParameters( - scan_interval_unit, scan_window_unit, + scan_phy, scan_interval, scan_window, base::Bind(&set_scan_params_cmpl_cb, client_if)); } @@ -2129,7 +2142,7 @@ static JNINativeMethod sScanMethods[] = { (void*)gattClientScanFilterClearNative}, {"gattClientScanFilterEnableNative", "(IZ)V", (void*)gattClientScanFilterEnableNative}, - {"gattSetScanParametersNative", "(III)V", + {"gattSetScanParametersNative", "(II[I[I)V", (void*)gattSetScanParametersNative}, }; diff --git a/res/values-az/strings_map.xml b/res/values-az/strings_map.xml deleted file mode 100644 index 0b8584e1207..00000000000 --- a/res/values-az/strings_map.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - "%1$s üçün seans açarı daxil edin" - "Bluetooth seans açarı tələb olunur" - "%1$s ilə bağlantı qəbul edərkən fasilə yarandı" - "%1$s ilə seans açarını daxil edərkən fasilə yarandı" - "Obex təsdiqləmə sorğusu" - "Seans Açarı" - "%1$s üçün seans açarı daxil edin" - "Maşın dəsti" - "Naməlum ad" - "Mənim adım" - "000000" - diff --git a/res/values-et/strings_map.xml b/res/values-et/strings_map.xml deleted file mode 100644 index 8fe16424b2b..00000000000 --- a/res/values-et/strings_map.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - "Sisestage seansivõti seadmele %1$s" - "Vajalik Bluetoothi seansivõti" - "Esines ajalõpp ühenduse aktsepteerimiseks seadmega %1$s" - "Esines ajalõpp seansivõtme sisestamiseks seadmele %1$s" - "Obexi autentimise taotlus" - "Seansivõti" - "Sisestage seansivõti seadmele %1$s" - "Autokomplekt" - "Tundmatu nimi" - "Minu nimi" - "000000" - diff --git a/res/values-hy/strings_map.xml b/res/values-hy/strings_map.xml deleted file mode 100644 index 91f2078be59..00000000000 --- a/res/values-hy/strings_map.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - "Մուտքագրեք աշխատաշրջանի բանալին %1$s-ի համար" - "Պահանջվում է Bluetooth-ի աշխատաշրջանի բանալի" - "%1$s-ի հետ կապի ընդունման ժամանակը սպառվեց" - "%1$s-ով աշխատաշրջանի բանալու մուտքագրման ժամանակը սպառվեց" - "Կասեցնել նույնականացման հարցումը" - "Աշխատաշրջանի բանալի" - "Մուտքագրեք աշխատաշրջանի բանալին %1$s-ի համար" - "Carkit" - "Անհայտ անուն" - "Իմ անունը" - "000000" - diff --git a/res/values-ka/strings_map.xml b/res/values-ka/strings_map.xml deleted file mode 100644 index 8e645c4f64a..00000000000 --- a/res/values-ka/strings_map.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - "სესიის გასაღები %1$s-ისთვის" - "აუცილებელია Bluetooth სესიის გასაღები" - "%1$s-თან კავშირის მიღების დრო ამოიწურა" - "%1$s-თან სესიის გასაღების შეყვანის დრო ამოიწურა" - "Obex ავთენტიფიკაციის მოთხოვნა" - "სესიის გასაღები" - "სესიის გასაღები %1$s-ისთვის" - "მანქანის ნაკრები" - "უცნობი სახელი" - "ჩემი სახელი" - "000000" - diff --git a/res/values-km/strings_map.xml b/res/values-km/strings_map.xml deleted file mode 100644 index 8118669863b..00000000000 --- a/res/values-km/strings_map.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - "បញ្ចូល​សោ​សម័យ​សម្រាប់ %1$s" - "បាន​ទាមទារ​សោ​សម័យ​ប៊្លូធូស" - "អស់​ពេល​វេលា​ក្នុង​ការ​ទទួល​យក​ការ​តភ្ជាប់​ជាមួយ %1$s" - "អស់​ពេល​​ដើម្បី​បញ្ចូល​សោ​សម័យ​ជាមួយ %1$s" - "សំណើ​ការ​ផ្ទៀងផ្ទាត់ Obex" - "សោ​សម័យ" - "បញ្ចូល​សោ​សម័យ​សម្រាប់ %1$s" - "Carkit" - "មិន​ស្គាល់​ឈ្មោះ" - "ឈ្មោះ​របស់​ខ្ញុំ" - "000000" - diff --git a/res/values-lo/strings_map.xml b/res/values-lo/strings_map.xml deleted file mode 100644 index dd3a2889ebf..00000000000 --- a/res/values-lo/strings_map.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - "ພິມລະຫັດເຊສຊັນສຳລັບ %1$s" - "ຕ້ອງມີ Bluetooth ລະຫັດເຊສຊັນ" - "ໝົດເວລາທີ່ຈະຮັບການເຊື່ອມຕໍ່ກັບ %1$s" - "ເກີດໝົດເວລາກ່ອນທີ່ຈະໃສ່ລະຫັດເຊສຊັນກັບ %1$s" - "ການຮ້ອງຂໍພິສູດຢືນຢັນໂຕ Obex" - "ກະແຈເຊສຊັສ" - "ພິມລະຫັດເຊສຊັນສຳລັບ %1$s" - "Carkit" - "ບໍ່ຮູ້ຊື່" - "ຊື່ຂອງຂ້ອຍ" - "000000" - diff --git a/res/values-mn/strings_map.xml b/res/values-mn/strings_map.xml deleted file mode 100644 index 45fc07dd457..00000000000 --- a/res/values-mn/strings_map.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - "%1$s-н горимын түлхүүрийг оруулна уу" - "Блютүүт горимын түлхүүр шаардлагатай" - "%1$s-тай холболт хийхийг зөвшөөрөх явцад хугацаа хэтэрсэн байна" - "%1$s-д горимын түлхүүр оруулах явцад хугацаа хэтэрсэн байна" - "Obex гэрчлэлтийн хүсэлт" - "Горимын Түлхүүр" - "%1$s-н горимын түлхүүрийг оруулна уу" - "Carkit" - "Тодорхойгүй нэр" - "Миний нэр" - "000000" - diff --git a/res/values-ms/strings_map.xml b/res/values-ms/strings_map.xml deleted file mode 100644 index afc98d73cfe..00000000000 --- a/res/values-ms/strings_map.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - "Taipkan kunci sesi untuk %1$s" - "Kunci sesi Bluetooth diperlukan" - "Berlaku tamat masa semasa menerima sambungan dengan %1$s" - "Tamat masa berlaku semasa memasukkan kunci sesi dengan %1$s" - "Permintaan pengesahan Obex" - "Kunci Sesi" - "Taipkan kunci sesi untuk %1$s" - "Kit kereta" - "Nama tidak diketahui" - "Nama saya" - "000000" - diff --git a/res/values-ne/strings_map.xml b/res/values-ne/strings_map.xml deleted file mode 100644 index 7584c1ec350..00000000000 --- a/res/values-ne/strings_map.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - "%1$s का लागि सत्र कुञ्जी टाइप गर्नुहोस्" - "ब्लूटूथ सत्र कुञ्जी आवश्यक" - "%1$s सँग जडान स्वीकार गर्न समय सकियो" - "%1$s का साथ सत्र कुञ्जी इनपुट गर्ने समय सकियो" - "Obex प्रमाणिकरण अनुरोध" - "सत्र कुञ्जी" - "%1$s का लागि सत्र कुञ्जी टाइप गर्नुहोस्" - "Carkit" - "अज्ञात नाम" - "मेरो नाम" - "००००००" - diff --git a/res/values-si/strings_map.xml b/res/values-si/strings_map.xml deleted file mode 100644 index 31c2febc809..00000000000 --- a/res/values-si/strings_map.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - "%1$s සඳහා සැසි යතුර ටයිප් කරන්න" - "බ්ලූටූත් සැසි යතුර අවශ්‍යයි" - "%1$s හා සම්බන්ධය පිළිගැනීමට කාල නිමාවක් විය" - "%1$s හා සැසි යතුර ආදානය කිරීමට කාල නිමාවක් විය" - "Obex සත්‍යාපන ඉල්ලීම" - "සැසි යතුර" - "%1$s සඳහා සැසි යතුර ටයිප් කරන්න" - "Carkit" - "නොදන්නා නමකි" - "මගේ නම" - "000000" - diff --git a/res/values/strings.xml b/res/values/strings.xml index 0204f983064..b7dcaf2a99c 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -178,9 +178,9 @@ Stopped sending file to \u0022%1$s\u0022 - There isn\'t enough space in USB storage to save the file from \u0022%1$s\u0022 + There isn\'t enough space in USB storage to save the file. - There isn\'t enough space on the SD card to save the file from \u0022%1$s\u0022 + There isn\'t enough space on the SD card to save the file. Space needed: %1$s Too many requests are being processed. Try again later. @@ -228,13 +228,13 @@ Clear - bluetooth_content_share + bluetooth_content_share - + - + Now Playing diff --git a/src/com/android/bluetooth/a2dp/A2dpCodecConfig.java b/src/com/android/bluetooth/a2dp/A2dpCodecConfig.java index 8127e766b95..5db50f3845a 100644 --- a/src/com/android/bluetooth/a2dp/A2dpCodecConfig.java +++ b/src/com/android/bluetooth/a2dp/A2dpCodecConfig.java @@ -22,6 +22,7 @@ import android.content.Context; import android.content.res.Resources; import android.content.res.Resources.NotFoundException; +import android.provider.Settings; import android.util.Log; import com.android.bluetooth.R; @@ -104,11 +105,22 @@ void enableOptionalCodecs(BluetoothDevice device, BluetoothCodecConfig currentCo return; } + boolean sbc_priority = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.SBC_HD_PRIORITY, 0) != 0; + // Set the mandatory codec's priority to default, and remove the rest for (int i = 0; i < codecConfigArray.length; i++) { BluetoothCodecConfig codecConfig = codecConfigArray[i]; - if (!codecConfig.isMandatoryCodec()) { + if (codecConfig != null && !codecConfig.isMandatoryCodec()) { codecConfigArray[i] = null; + } else if (sbc_priority) { + // Rebuild SBC selectable codec with Dual Channel (SBC HD audio) + codecConfigArray[i] = new BluetoothCodecConfig( + BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC, mA2dpSourceCodecPrioritySbc, + BluetoothCodecConfig.SAMPLE_RATE_NONE, + BluetoothCodecConfig.BITS_PER_SAMPLE_NONE, + BluetoothCodecConfig.CHANNEL_MODE_DUAL_CHANNEL, 0 /* codecSpecific1 */, + 0 /* codecSpecific2 */, 0 /* codecSpecific3 */, 0 /* codecSpecific4 */); } } @@ -128,7 +140,7 @@ void disableOptionalCodecs(BluetoothDevice device, BluetoothCodecConfig currentC // Set the mandatory codec's priority to highest, and remove the rest for (int i = 0; i < codecConfigArray.length; i++) { BluetoothCodecConfig codecConfig = codecConfigArray[i]; - if (codecConfig.isMandatoryCodec()) { + if (codecConfig != null && codecConfig.isMandatoryCodec()) { codecConfig.setCodecPriority(BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST); } else { codecConfigArray[i] = null; @@ -210,6 +222,31 @@ private BluetoothCodecConfig[] assignCodecConfigPriorities() { mA2dpSourceCodecPriorityLdac = value; } + // Set highest codec priority in the end, so that it can override xml values + int codec_priority = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.A2DP_SOURCE_CODEC_PRIORITY, 0); + + switch (codec_priority) { + case 0: + default: + break; + case 1: + mA2dpSourceCodecPrioritySbc = BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST; + break; + case 2: + mA2dpSourceCodecPriorityAac = BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST; + break; + case 3: + mA2dpSourceCodecPriorityAptx = BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST; + break; + case 4: + mA2dpSourceCodecPriorityAptxHd = BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST; + break; + case 5: + mA2dpSourceCodecPriorityLdac = BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST; + break; + } + BluetoothCodecConfig codecConfig; BluetoothCodecConfig[] codecConfigArray = new BluetoothCodecConfig[BluetoothCodecConfig.SOURCE_CODEC_TYPE_MAX]; diff --git a/src/com/android/bluetooth/a2dp/A2dpNativeInterface.java b/src/com/android/bluetooth/a2dp/A2dpNativeInterface.java index cbdc28a6061..fc08032bbd8 100644 --- a/src/com/android/bluetooth/a2dp/A2dpNativeInterface.java +++ b/src/com/android/bluetooth/a2dp/A2dpNativeInterface.java @@ -75,8 +75,9 @@ public static A2dpNativeInterface getInstance() { * @param codecConfigPriorities an array with the codec configuration * priorities to configure. */ - public void init(int maxConnectedAudioDevices, BluetoothCodecConfig[] codecConfigPriorities) { - initNative(maxConnectedAudioDevices, codecConfigPriorities); + public void init(int maxConnectedAudioDevices, BluetoothCodecConfig[] codecConfigPriorities, + BluetoothCodecConfig[] codecConfigOffload) { + initNative(maxConnectedAudioDevices, codecConfigPriorities, codecConfigOffload); } /** @@ -205,7 +206,8 @@ private void onCodecConfigChanged(byte[] address, // Native methods that call into the JNI interface private static native void classInitNative(); private native void initNative(int maxConnectedAudioDevices, - BluetoothCodecConfig[] codecConfigPriorities); + BluetoothCodecConfig[] codecConfigPriorities, + BluetoothCodecConfig[] codecConfigOffload); private native void cleanupNative(); private native boolean connectA2dpNative(byte[] address); private native boolean disconnectA2dpNative(byte[] address); diff --git a/src/com/android/bluetooth/a2dp/A2dpService.java b/src/com/android/bluetooth/a2dp/A2dpService.java index cebf7676be1..e18656a21aa 100644 --- a/src/com/android/bluetooth/a2dp/A2dpService.java +++ b/src/com/android/bluetooth/a2dp/A2dpService.java @@ -122,8 +122,12 @@ protected boolean start() { mA2dpCodecConfig = new A2dpCodecConfig(this, mA2dpNativeInterface); // Step 5: Initialize native interface + List codecConfigOffload = mAudioManager.getHwOffloadEncodingFormatsSupportedForA2DP(); + BluetoothCodecConfig[] offloadCodecConfig = new BluetoothCodecConfig[codecConfigOffload.size()]; + offloadCodecConfig = codecConfigOffload.toArray(offloadCodecConfig); mA2dpNativeInterface.init(mMaxConnectedAudioDevices, - mA2dpCodecConfig.codecConfigPriorities()); + mA2dpCodecConfig.codecConfigPriorities(), + offloadCodecConfig); // Step 6: Check if A2DP is in offload mode mA2dpOffloadEnabled = mAdapterService.isA2dpOffloadEnabled(); @@ -1035,7 +1039,13 @@ public void updateOptionalCodecsSupport(BluetoothDevice device) { BluetoothCodecStatus codecStatus = sm.getCodecStatus(); if (codecStatus != null) { for (BluetoothCodecConfig config : codecStatus.getCodecsSelectableCapabilities()) { - if (config.isMandatoryCodec()) { + boolean isMandatoryCodecWithDualChannel = (config.isMandatoryCodec() + && (config.getChannelMode() & config.CHANNEL_MODE_DUAL_CHANNEL) + == config.CHANNEL_MODE_DUAL_CHANNEL); + if (isMandatoryCodecWithDualChannel) { + hasMandatoryCodec = true; + supportsOptional = true; + } else if (config.isMandatoryCodec()) { hasMandatoryCodec = true; } else { supportsOptional = true; @@ -1052,11 +1062,11 @@ public void updateOptionalCodecsSupport(BluetoothDevice device) { } if (previousSupport == BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN - || supportsOptional != (previousSupport - == BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED)) { + || previousSupport == BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED) { setSupportsOptionalCodecs(device, supportsOptional); } - if (supportsOptional) { + if (supportsOptional + || previousSupport == BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED) { int enabled = getOptionalCodecsEnabled(device); switch (enabled) { case BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN: diff --git a/src/com/android/bluetooth/avrcp/AvrcpTargetService.java b/src/com/android/bluetooth/avrcp/AvrcpTargetService.java index e2ae494a62a..91d577c7547 100644 --- a/src/com/android/bluetooth/avrcp/AvrcpTargetService.java +++ b/src/com/android/bluetooth/avrcp/AvrcpTargetService.java @@ -68,6 +68,8 @@ class ListCallback implements MediaPlayerList.MediaUpdateCallback, MediaPlayerList.FolderUpdateCallback { @Override public void run(MediaData data) { + if (mNativeInterface == null) return; + boolean metadata = !Objects.equals(mCurrentData.metadata, data.metadata); boolean state = !MediaPlayerWrapper.playstateEquals(mCurrentData.state, data.state); boolean queue = !Objects.equals(mCurrentData.queue, data.queue); @@ -84,6 +86,8 @@ public void run(MediaData data) { @Override public void run(boolean availablePlayers, boolean addressedPlayers, boolean uids) { + if (mNativeInterface == null) return; + mNativeInterface.sendFolderUpdate(availablePlayers, addressedPlayers, uids); } } diff --git a/src/com/android/bluetooth/btservice/AdapterService.java b/src/com/android/bluetooth/btservice/AdapterService.java index a65bcfdf97f..418f79f0206 100644 --- a/src/com/android/bluetooth/btservice/AdapterService.java +++ b/src/com/android/bluetooth/btservice/AdapterService.java @@ -1215,6 +1215,17 @@ public boolean isBondingInitiatedLocally(BluetoothDevice device) { return service.isBondingInitiatedLocally(device); } + @Override + public void setBondingInitiatedLocally(BluetoothDevice device, boolean localInitiated) { + // don't check caller, may be called from system UI + AdapterService service = getService(); + if (service == null) { + return; + } + service.setBondingInitiatedLocally(device,localInitiated); + return; + } + @Override public long getSupportedProfiles() { AdapterService service = getService(); @@ -1519,6 +1530,14 @@ public boolean sdpSearch(BluetoothDevice device, ParcelUuid uuid) { return service.sdpSearch(device, uuid); } + public boolean isTwsPlusDevice(BluetoothDevice device) { + return false; + } + + public String getTwsPlusPeerAddress(BluetoothDevice device) { + return null; + } + @Override public int getBatteryLevel(BluetoothDevice device) { if (!Utils.checkCaller()) { @@ -1726,6 +1745,16 @@ public void onLeServiceUp() { service.onLeServiceUp(); } + @Override + public void updateQuietModeStatus(boolean quietMode) { + AdapterService service = getService(); + if (service == null) { + return; + } + service.updateQuietModeStatus(quietMode); + } + + @Override public void onBrEdrDown() { AdapterService service = getService(); @@ -1735,6 +1764,15 @@ public void onBrEdrDown() { service.onBrEdrDown(); } + public int setSocketOpt(int type, int channel, int optionName, byte [] optionVal, + int optionLen) { + return -1; + } + + public int getSocketOpt(int type, int channel, int optionName, byte [] optionVal) { + return -1; + } + @Override public void dump(FileDescriptor fd, String[] args) { PrintWriter writer = new PrintWriter(new FileOutputStream(fd)); @@ -2126,6 +2164,17 @@ boolean isBondingInitiatedLocally(BluetoothDevice device) { return deviceProp.isBondingInitiatedLocally(); } + void setBondingInitiatedLocally(BluetoothDevice device, boolean localInitiated) { + enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); + DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); + if (deviceProp == null) { + return; + } + Log.w(TAG," localInitiated " + localInitiated); + deviceProp.setBondingInitiatedLocally(localInitiated); + return; + } + long getSupportedProfiles() { return Config.getSupportedProfilesBitMask(); } @@ -2548,6 +2597,12 @@ public int getTotalNumOfTrackableAdvertisements() { return mAdapterProperties.getTotalNumOfTrackableAdvertisements(); } + void updateQuietModeStatus(boolean quietMode) { + debugLog("updateQuietModeStatus()-updateQuietModeStatus called with quiet mode status:" + + quietMode); + mQuietmode = quietMode; + } + void onLeServiceUp() { mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_ON); } diff --git a/src/com/android/bluetooth/gatt/ScanManager.java b/src/com/android/bluetooth/gatt/ScanManager.java index 073697821c2..5adb8945ec2 100644 --- a/src/com/android/bluetooth/gatt/ScanManager.java +++ b/src/com/android/bluetooth/gatt/ScanManager.java @@ -20,6 +20,7 @@ import android.app.AlarmManager; import android.app.PendingIntent; import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; import android.bluetooth.le.ScanCallback; import android.bluetooth.le.ScanFilter; import android.bluetooth.le.ScanSettings; @@ -83,7 +84,8 @@ public class ScanManager { // Timeout for each controller operation. private static final int OPERATION_TIME_OUT_MILLIS = 500; - private int mLastConfiguredScanSetting = Integer.MIN_VALUE; + private int mLastConfiguredScanSettingLE1M = Integer.MIN_VALUE; + private int mLastConfiguredScanSettingLECoded = Integer.MIN_VALUE; // Scan parameters for batch scan. private BatchScanParams mBatchScanParms; @@ -117,6 +119,18 @@ private class UidImportance { } } + private class PhyInfo { + public int scanPhy; + public int scanModeLE1M; + public int scanModeLECoded; + + PhyInfo(int scanPhy, int scanModeLE1M, int scanModeLECoded) { + this.scanPhy = scanPhy; + this.scanModeLE1M = scanModeLE1M; + this.scanModeLECoded = scanModeLECoded; + } + }; + ScanManager(GattService service) { mRegularScanClients = Collections.newSetFromMap(new ConcurrentHashMap()); @@ -576,40 +590,85 @@ void configureRegularScanParams() { if (DBG) { Log.d(TAG, "configureRegularScanParams() - queue=" + mRegularScanClients.size()); } - int curScanSetting = Integer.MIN_VALUE; + int curScanSettingLE1M = Integer.MIN_VALUE; + int curScanSettingLECoded = Integer.MIN_VALUE; + int scanPhy = BluetoothDevice.PHY_LE_1M; ScanClient client = getAggressiveClient(mRegularScanClients); + PhyInfo phyInfoResult = getPhyInfo(mRegularScanClients); + boolean scanModeChanged = false; + int scanWindowLE1M = Integer.MIN_VALUE; + int scanIntervalLE1M = Integer.MIN_VALUE; + int scanWindowLECoded = Integer.MIN_VALUE; + int scanIntervalLECoded = Integer.MIN_VALUE; + int[] scanInterval = new int[2]; + int[] scanWindow = new int[2]; + int phyCnt = 0; + + if (client != null) { - curScanSetting = client.settings.getScanMode(); + curScanSettingLE1M = phyInfoResult.scanModeLE1M; + curScanSettingLECoded = phyInfoResult.scanModeLECoded; + scanPhy = phyInfoResult.scanPhy; } if (DBG) { - Log.d(TAG, "configureRegularScanParams() - ScanSetting Scan mode=" + curScanSetting - + " mLastConfiguredScanSetting=" + mLastConfiguredScanSetting); + Log.d(TAG, "configureRegularScanParams() - ScanSetting LE 1M Scan mode=" + curScanSettingLE1M + + "ScanSetting LE Coded Scan mode=" + curScanSettingLECoded + + " mLastConfiguredScanSettingLE1M=" + mLastConfiguredScanSettingLE1M + + " mLastConfiguredScanSettingLECoded=" + mLastConfiguredScanSettingLECoded + + "scanPhy=" + scanPhy); + } + + if ((curScanSettingLE1M != Integer.MIN_VALUE + && curScanSettingLE1M != ScanSettings.SCAN_MODE_OPPORTUNISTIC)) { + if (curScanSettingLE1M != mLastConfiguredScanSettingLE1M) { + scanModeChanged = true; + ScanSettings settings = new ScanSettings.Builder().setScanMode(curScanSettingLE1M).build(); + scanWindowLE1M = getScanWindowMillis(settings); + scanIntervalLE1M = getScanIntervalMillis(settings); + // convert scanWindow and scanInterval from ms to LE scan units(0.625ms) + scanWindow[phyCnt] = Utils.millsToUnit(scanWindowLE1M); + scanInterval[phyCnt] = Utils.millsToUnit(scanIntervalLE1M); + phyCnt++; + } } - - if (curScanSetting != Integer.MIN_VALUE - && curScanSetting != ScanSettings.SCAN_MODE_OPPORTUNISTIC) { - if (curScanSetting != mLastConfiguredScanSetting) { - int scanWindow = getScanWindowMillis(client.settings); - int scanInterval = getScanIntervalMillis(client.settings); + else { + mLastConfiguredScanSettingLE1M = curScanSettingLE1M; + if (DBG) { + Log.d(TAG, "configureRegularScanParams() - queue emtpy, scan stopped"); + } + } + if((curScanSettingLECoded != Integer.MIN_VALUE + && curScanSettingLECoded != ScanSettings.SCAN_MODE_OPPORTUNISTIC)) { + if (curScanSettingLECoded != mLastConfiguredScanSettingLECoded) { + scanModeChanged = true; + ScanSettings settings = new ScanSettings.Builder().setScanMode(curScanSettingLECoded).build(); + scanWindowLECoded = getScanWindowMillis(settings); + scanIntervalLECoded = getScanIntervalMillis(settings); // convert scanWindow and scanInterval from ms to LE scan units(0.625ms) - scanWindow = Utils.millsToUnit(scanWindow); - scanInterval = Utils.millsToUnit(scanInterval); - gattClientScanNative(false); - if (DBG) { - Log.d(TAG, "configureRegularScanParams - scanInterval = " + scanInterval - + "configureRegularScanParams - scanWindow = " + scanWindow); - } - gattSetScanParametersNative(client.scannerId, scanInterval, scanWindow); - gattClientScanNative(true); - mLastConfiguredScanSetting = curScanSetting; + scanWindow[phyCnt] = Utils.millsToUnit(scanWindowLECoded); + scanInterval[phyCnt] = Utils.millsToUnit(scanIntervalLECoded); } - } else { - mLastConfiguredScanSetting = curScanSetting; + } + else { + mLastConfiguredScanSettingLECoded = curScanSettingLECoded; if (DBG) { Log.d(TAG, "configureRegularScanParams() - queue emtpy, scan stopped"); } } + if(scanModeChanged) { + gattClientScanNative(false); + if (DBG) { + Log.d(TAG, "configureRegularScanParams - scanInterval LE 1M = " + scanIntervalLE1M + + "configureRegularScanParams - scanWindow LE 1M= " + scanWindowLE1M + + "configureRegularScanParams - scanWindow LE Coded= " + scanWindowLECoded + + "configureRegularScanParams - scanWindow LE Coded= " + scanWindowLECoded); + } + gattSetScanParametersNative(client.scannerId, scanPhy, scanInterval, scanWindow); + gattClientScanNative(true); + mLastConfiguredScanSettingLE1M = curScanSettingLE1M; + mLastConfiguredScanSettingLECoded = curScanSettingLECoded; + } } ScanClient getAggressiveClient(Set cList) { @@ -626,6 +685,29 @@ ScanClient getAggressiveClient(Set cList) { return result; } + PhyInfo getPhyInfo(Set cList) { + PhyInfo result = null; + int curScanSettingLE1M = Integer.MIN_VALUE; + int curScanSettingLECoded = Integer.MIN_VALUE; + int curScanPhy = BluetoothDevice.PHY_LE_1M; + int aggregateScanPhy = BluetoothDevice.PHY_LE_1M; + for (ScanClient client : cList) { + // Get the most aggresive scan mode for each PHY + curScanPhy = client.settings.getPhy(); + if (((curScanPhy & BluetoothDevice.PHY_LE_1M)== BluetoothDevice.PHY_LE_1M) && + (client.settings.getScanMode() > curScanSettingLE1M)) { + curScanSettingLE1M = client.settings.getScanMode(); + } + if (((curScanPhy & BluetoothDevice.PHY_LE_CODED)== BluetoothDevice.PHY_LE_CODED) && + (client.settings.getScanMode() > curScanSettingLECoded)) { + curScanSettingLECoded = client.settings.getScanMode(); + } + aggregateScanPhy |= client.settings.getPhy(); + } + result = new PhyInfo(aggregateScanPhy, curScanSettingLE1M, curScanSettingLECoded); + return result; + } + void startRegularScan(ScanClient client) { if (isFilteringSupported() && mFilterIndexStack.isEmpty() && mClientFilterIndexMap.isEmpty()) { @@ -1266,8 +1348,8 @@ private boolean manageAllocationOfTrackingAdvertisement(int numOfTrackableAdvert private native void gattClientScanNative(boolean start); - private native void gattSetScanParametersNative(int clientIf, int scanInterval, - int scanWindow); + private native void gattSetScanParametersNative(int clientIf, int scan_phy, int[] scanInterval, + int[] scanWindow); /************************** Filter related native methods ********************************/ private native void gattClientScanFilterAddNative(int clientId, diff --git a/tests/unit/Android.mk b/tests/unit/Android.mk index 98c88d403f0..df666874e2c 100644 --- a/tests/unit/Android.mk +++ b/tests/unit/Android.mk @@ -14,7 +14,7 @@ LOCAL_JAVA_LIBRARIES := \ android.test.mock LOCAL_STATIC_JAVA_LIBRARIES := \ - com.android.emailcommon \ + #com.android.emailcommon \ androidx.test.rules \ mockito-target \ androidx.test.espresso.intents