Loading src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java +169 −73 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.settings.bluetooth; import static com.android.settings.bluetooth.Utils.preloadAndRun; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.ContentResolver; Loading Loading @@ -55,9 +57,13 @@ import com.android.settingslib.utils.StringUtil; import com.android.settingslib.utils.ThreadUtils; import com.android.settingslib.widget.LayoutPreference; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import java.io.IOException; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; Loading Loading @@ -236,24 +242,42 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont @VisibleForTesting void refresh() { if (mLayoutPreference != null && mCachedDevice != null) { final TextView title = mLayoutPreference.findViewById(R.id.entity_header_title); title.setText(mCachedDevice.getName()); final TextView summary = mLayoutPreference.findViewById(R.id.entity_header_summary); if (!mCachedDevice.isConnected() || mCachedDevice.isBusy()) { summary.setText(mCachedDevice.getConnectionSummary(true /* shortSummary */)); Supplier<String> deviceName = Suppliers.memoize(() -> mCachedDevice.getName()); Supplier<Boolean> disconnected = Suppliers.memoize(() -> !mCachedDevice.isConnected() || mCachedDevice.isBusy()); Supplier<Boolean> isUntetheredHeadset = Suppliers.memoize(() -> isUntetheredHeadset(mCachedDevice.getDevice())); Supplier<String> summaryText = Suppliers.memoize( () -> { if (disconnected.get() || isUntetheredHeadset.get()) { return mCachedDevice.getConnectionSummary( /* shortSummary= */ true); } return mCachedDevice.getConnectionSummary( BluetoothUtils.getIntMetaData( mCachedDevice.getDevice(), BluetoothDevice.METADATA_MAIN_BATTERY) != BluetoothUtils.META_INT_ERROR); }); preloadAndRun( List.of(deviceName, disconnected, isUntetheredHeadset, summaryText), () -> { final TextView title = mLayoutPreference.findViewById(R.id.entity_header_title); title.setText(deviceName.get()); final TextView summary = mLayoutPreference.findViewById(R.id.entity_header_summary); if (disconnected.get()) { summary.setText(summaryText.get()); updateDisconnectLayout(); return; } final BluetoothDevice device = mCachedDevice.getDevice(); final String deviceType = BluetoothUtils.getStringMetaData(device, BluetoothDevice.METADATA_DEVICE_TYPE); if (TextUtils.equals(deviceType, BluetoothDevice.DEVICE_TYPE_UNTETHERED_HEADSET) || BluetoothUtils.getBooleanMetaData(device, BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET)) { summary.setText(mCachedDevice.getConnectionSummary(true /* shortSummary */)); updateSubLayout(mLayoutPreference.findViewById(R.id.layout_left), if (isUntetheredHeadset.get()) { summary.setText(summaryText.get()); updateSubLayout( mLayoutPreference.findViewById(R.id.layout_left), BluetoothDevice.METADATA_UNTETHERED_LEFT_ICON, BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY, BluetoothDevice.METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD, Loading @@ -261,7 +285,8 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont R.string.bluetooth_left_name, LEFT_DEVICE_ID); updateSubLayout(mLayoutPreference.findViewById(R.id.layout_middle), updateSubLayout( mLayoutPreference.findViewById(R.id.layout_middle), BluetoothDevice.METADATA_UNTETHERED_CASE_ICON, BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY, BluetoothDevice.METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD, Loading @@ -269,7 +294,8 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont R.string.bluetooth_middle_name, CASE_DEVICE_ID); updateSubLayout(mLayoutPreference.findViewById(R.id.layout_right), updateSubLayout( mLayoutPreference.findViewById(R.id.layout_right), BluetoothDevice.METADATA_UNTETHERED_RIGHT_ICON, BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY, BluetoothDevice.METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD, Loading @@ -279,20 +305,24 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont showBothDevicesBatteryPredictionIfNecessary(); } else { mLayoutPreference.findViewById(R.id.layout_left).setVisibility(View.GONE); mLayoutPreference.findViewById(R.id.layout_right).setVisibility(View.GONE); summary.setText(mCachedDevice.getConnectionSummary( BluetoothUtils.getIntMetaData(device, BluetoothDevice.METADATA_MAIN_BATTERY) != BluetoothUtils.META_INT_ERROR)); updateSubLayout(mLayoutPreference.findViewById(R.id.layout_middle), mLayoutPreference .findViewById(R.id.layout_left) .setVisibility(View.GONE); mLayoutPreference .findViewById(R.id.layout_right) .setVisibility(View.GONE); summary.setText(summaryText.get()); updateSubLayout( mLayoutPreference.findViewById(R.id.layout_middle), BluetoothDevice.METADATA_MAIN_ICON, BluetoothDevice.METADATA_MAIN_BATTERY, BluetoothDevice.METADATA_MAIN_LOW_BATTERY_THRESHOLD, BluetoothDevice.METADATA_MAIN_CHARGING, /* titleResId */ 0, /* titleResId= */ 0, MAIN_DEVICE_ID); } }); } } Loading @@ -315,13 +345,87 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont return drawable; } private void updateSubLayout(LinearLayout linearLayout, int iconMetaKey, int batteryMetaKey, int lowBatteryMetaKey, int chargeMetaKey, int titleResId, int deviceId) { private void updateSubLayout( LinearLayout linearLayout, int iconMetaKey, int batteryMetaKey, int lowBatteryMetaKey, int chargeMetaKey, int titleResId, int deviceId) { if (linearLayout == null) { return; } BluetoothDevice bluetoothDevice = mCachedDevice.getDevice(); Supplier<String> iconUri = Suppliers.memoize( () -> BluetoothUtils.getStringMetaData(bluetoothDevice, iconMetaKey)); Supplier<Integer> batteryLevel = Suppliers.memoize( () -> BluetoothUtils.getIntMetaData(bluetoothDevice, batteryMetaKey)); Supplier<Boolean> charging = Suppliers.memoize( () -> BluetoothUtils.getBooleanMetaData(bluetoothDevice, chargeMetaKey)); Supplier<Integer> lowBatteryLevel = Suppliers.memoize( () -> { int level = BluetoothUtils.getIntMetaData( bluetoothDevice, lowBatteryMetaKey); if (level == BluetoothUtils.META_INT_ERROR) { if (batteryMetaKey == BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY) { level = CASE_LOW_BATTERY_LEVEL; } else { level = LOW_BATTERY_LEVEL; } } return level; }); Supplier<Boolean> isUntethered = Suppliers.memoize(() -> isUntetheredHeadset(bluetoothDevice)); Supplier<Integer> nativeBatteryLevel = Suppliers.memoize(bluetoothDevice::getBatteryLevel); preloadAndRun( List.of( iconUri, batteryLevel, charging, lowBatteryLevel, isUntethered, nativeBatteryLevel), () -> updateSubLayoutUi( linearLayout, iconMetaKey, batteryMetaKey, lowBatteryMetaKey, chargeMetaKey, titleResId, deviceId, iconUri, batteryLevel, charging, lowBatteryLevel, isUntethered, nativeBatteryLevel)); } private void updateSubLayoutUi( LinearLayout linearLayout, int iconMetaKey, int batteryMetaKey, int lowBatteryMetaKey, int chargeMetaKey, int titleResId, int deviceId, Supplier<String> preloadedIconUri, Supplier<Integer> preloadedBatteryLevel, Supplier<Boolean> preloadedCharging, Supplier<Integer> preloadedLowBatteryLevel, Supplier<Boolean> preloadedIsUntethered, Supplier<Integer> preloadedNativeBatteryLevel) { final BluetoothDevice bluetoothDevice = mCachedDevice.getDevice(); final String iconUri = BluetoothUtils.getStringMetaData(bluetoothDevice, iconMetaKey); final String iconUri = preloadedIconUri.get(); final ImageView imageView = linearLayout.findViewById(R.id.header_icon); if (iconUri != null) { updateIcon(imageView, iconUri); Loading @@ -331,17 +435,9 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont imageView.setImageDrawable(pair.first); imageView.setContentDescription(pair.second); } final int batteryLevel = BluetoothUtils.getIntMetaData(bluetoothDevice, batteryMetaKey); final boolean charging = BluetoothUtils.getBooleanMetaData(bluetoothDevice, chargeMetaKey); int lowBatteryLevel = BluetoothUtils.getIntMetaData(bluetoothDevice, lowBatteryMetaKey); if (lowBatteryLevel == BluetoothUtils.META_INT_ERROR) { if (batteryMetaKey == BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY) { lowBatteryLevel = CASE_LOW_BATTERY_LEVEL; } else { lowBatteryLevel = LOW_BATTERY_LEVEL; } } final int batteryLevel = preloadedBatteryLevel.get(); final boolean charging = preloadedCharging.get(); int lowBatteryLevel = preloadedLowBatteryLevel.get(); Log.d(TAG, "buletoothDevice: " + bluetoothDevice.getAnonymizedAddress() + ", updateSubLayout() icon : " + iconMetaKey + ", battery : " + batteryMetaKey Loading @@ -353,7 +449,7 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont showBatteryPredictionIfNecessary(linearLayout, deviceId, batteryLevel); } final TextView batterySummaryView = linearLayout.findViewById(R.id.bt_battery_summary); if (isUntetheredHeadset(bluetoothDevice)) { if (preloadedIsUntethered.get()) { if (batteryLevel != BluetoothUtils.META_INT_ERROR) { linearLayout.setVisibility(View.VISIBLE); batterySummaryView.setText( Loading @@ -364,7 +460,7 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont if (deviceId == MAIN_DEVICE_ID) { linearLayout.setVisibility(View.VISIBLE); linearLayout.findViewById(R.id.bt_battery_icon).setVisibility(View.GONE); int level = bluetoothDevice.getBatteryLevel(); int level = preloadedNativeBatteryLevel.get(); if (level != BluetoothDevice.BATTERY_LEVEL_UNKNOWN && level != BluetoothDevice.BATTERY_LEVEL_BLUETOOTH_OFF) { batterySummaryView.setText( Loading src/com/android/settings/bluetooth/Utils.java +22 −0 Original line number Diff line number Diff line Loading @@ -37,12 +37,16 @@ import androidx.annotation.VisibleForTesting; import androidx.appcompat.app.AlertDialog; import com.android.settings.R; import com.android.settings.flags.Flags; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.bluetooth.BluetoothUtils; import com.android.settingslib.bluetooth.BluetoothUtils.ErrorListener; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothManager.BluetoothManagerCallback; import com.android.settingslib.utils.ThreadUtils; import com.google.common.base.Supplier; import java.util.ArrayList; import java.util.List; Loading Loading @@ -272,4 +276,22 @@ public final class Utils { + " , deviceList = " + cachedBluetoothDevices); return cachedBluetoothDevices; } /** * Preloads the values and run the Runnable afterwards. * @param suppliers the value supplier, should be a memoized supplier * @param runnable the runnable to be run after value is preloaded */ public static void preloadAndRun(List<Supplier<?>> suppliers, Runnable runnable) { if (!Flags.enableOffloadBluetoothOperationsToBackgroundThread()) { runnable.run(); return; } ThreadUtils.postOnBackgroundThread(() -> { for (Supplier<?> supplier : suppliers) { supplier.get(); } ThreadUtils.postOnMainThread(runnable); }); } } Loading
src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java +169 −73 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.settings.bluetooth; import static com.android.settings.bluetooth.Utils.preloadAndRun; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.ContentResolver; Loading Loading @@ -55,9 +57,13 @@ import com.android.settingslib.utils.StringUtil; import com.android.settingslib.utils.ThreadUtils; import com.android.settingslib.widget.LayoutPreference; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import java.io.IOException; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; Loading Loading @@ -236,24 +242,42 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont @VisibleForTesting void refresh() { if (mLayoutPreference != null && mCachedDevice != null) { final TextView title = mLayoutPreference.findViewById(R.id.entity_header_title); title.setText(mCachedDevice.getName()); final TextView summary = mLayoutPreference.findViewById(R.id.entity_header_summary); if (!mCachedDevice.isConnected() || mCachedDevice.isBusy()) { summary.setText(mCachedDevice.getConnectionSummary(true /* shortSummary */)); Supplier<String> deviceName = Suppliers.memoize(() -> mCachedDevice.getName()); Supplier<Boolean> disconnected = Suppliers.memoize(() -> !mCachedDevice.isConnected() || mCachedDevice.isBusy()); Supplier<Boolean> isUntetheredHeadset = Suppliers.memoize(() -> isUntetheredHeadset(mCachedDevice.getDevice())); Supplier<String> summaryText = Suppliers.memoize( () -> { if (disconnected.get() || isUntetheredHeadset.get()) { return mCachedDevice.getConnectionSummary( /* shortSummary= */ true); } return mCachedDevice.getConnectionSummary( BluetoothUtils.getIntMetaData( mCachedDevice.getDevice(), BluetoothDevice.METADATA_MAIN_BATTERY) != BluetoothUtils.META_INT_ERROR); }); preloadAndRun( List.of(deviceName, disconnected, isUntetheredHeadset, summaryText), () -> { final TextView title = mLayoutPreference.findViewById(R.id.entity_header_title); title.setText(deviceName.get()); final TextView summary = mLayoutPreference.findViewById(R.id.entity_header_summary); if (disconnected.get()) { summary.setText(summaryText.get()); updateDisconnectLayout(); return; } final BluetoothDevice device = mCachedDevice.getDevice(); final String deviceType = BluetoothUtils.getStringMetaData(device, BluetoothDevice.METADATA_DEVICE_TYPE); if (TextUtils.equals(deviceType, BluetoothDevice.DEVICE_TYPE_UNTETHERED_HEADSET) || BluetoothUtils.getBooleanMetaData(device, BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET)) { summary.setText(mCachedDevice.getConnectionSummary(true /* shortSummary */)); updateSubLayout(mLayoutPreference.findViewById(R.id.layout_left), if (isUntetheredHeadset.get()) { summary.setText(summaryText.get()); updateSubLayout( mLayoutPreference.findViewById(R.id.layout_left), BluetoothDevice.METADATA_UNTETHERED_LEFT_ICON, BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY, BluetoothDevice.METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD, Loading @@ -261,7 +285,8 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont R.string.bluetooth_left_name, LEFT_DEVICE_ID); updateSubLayout(mLayoutPreference.findViewById(R.id.layout_middle), updateSubLayout( mLayoutPreference.findViewById(R.id.layout_middle), BluetoothDevice.METADATA_UNTETHERED_CASE_ICON, BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY, BluetoothDevice.METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD, Loading @@ -269,7 +294,8 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont R.string.bluetooth_middle_name, CASE_DEVICE_ID); updateSubLayout(mLayoutPreference.findViewById(R.id.layout_right), updateSubLayout( mLayoutPreference.findViewById(R.id.layout_right), BluetoothDevice.METADATA_UNTETHERED_RIGHT_ICON, BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY, BluetoothDevice.METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD, Loading @@ -279,20 +305,24 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont showBothDevicesBatteryPredictionIfNecessary(); } else { mLayoutPreference.findViewById(R.id.layout_left).setVisibility(View.GONE); mLayoutPreference.findViewById(R.id.layout_right).setVisibility(View.GONE); summary.setText(mCachedDevice.getConnectionSummary( BluetoothUtils.getIntMetaData(device, BluetoothDevice.METADATA_MAIN_BATTERY) != BluetoothUtils.META_INT_ERROR)); updateSubLayout(mLayoutPreference.findViewById(R.id.layout_middle), mLayoutPreference .findViewById(R.id.layout_left) .setVisibility(View.GONE); mLayoutPreference .findViewById(R.id.layout_right) .setVisibility(View.GONE); summary.setText(summaryText.get()); updateSubLayout( mLayoutPreference.findViewById(R.id.layout_middle), BluetoothDevice.METADATA_MAIN_ICON, BluetoothDevice.METADATA_MAIN_BATTERY, BluetoothDevice.METADATA_MAIN_LOW_BATTERY_THRESHOLD, BluetoothDevice.METADATA_MAIN_CHARGING, /* titleResId */ 0, /* titleResId= */ 0, MAIN_DEVICE_ID); } }); } } Loading @@ -315,13 +345,87 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont return drawable; } private void updateSubLayout(LinearLayout linearLayout, int iconMetaKey, int batteryMetaKey, int lowBatteryMetaKey, int chargeMetaKey, int titleResId, int deviceId) { private void updateSubLayout( LinearLayout linearLayout, int iconMetaKey, int batteryMetaKey, int lowBatteryMetaKey, int chargeMetaKey, int titleResId, int deviceId) { if (linearLayout == null) { return; } BluetoothDevice bluetoothDevice = mCachedDevice.getDevice(); Supplier<String> iconUri = Suppliers.memoize( () -> BluetoothUtils.getStringMetaData(bluetoothDevice, iconMetaKey)); Supplier<Integer> batteryLevel = Suppliers.memoize( () -> BluetoothUtils.getIntMetaData(bluetoothDevice, batteryMetaKey)); Supplier<Boolean> charging = Suppliers.memoize( () -> BluetoothUtils.getBooleanMetaData(bluetoothDevice, chargeMetaKey)); Supplier<Integer> lowBatteryLevel = Suppliers.memoize( () -> { int level = BluetoothUtils.getIntMetaData( bluetoothDevice, lowBatteryMetaKey); if (level == BluetoothUtils.META_INT_ERROR) { if (batteryMetaKey == BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY) { level = CASE_LOW_BATTERY_LEVEL; } else { level = LOW_BATTERY_LEVEL; } } return level; }); Supplier<Boolean> isUntethered = Suppliers.memoize(() -> isUntetheredHeadset(bluetoothDevice)); Supplier<Integer> nativeBatteryLevel = Suppliers.memoize(bluetoothDevice::getBatteryLevel); preloadAndRun( List.of( iconUri, batteryLevel, charging, lowBatteryLevel, isUntethered, nativeBatteryLevel), () -> updateSubLayoutUi( linearLayout, iconMetaKey, batteryMetaKey, lowBatteryMetaKey, chargeMetaKey, titleResId, deviceId, iconUri, batteryLevel, charging, lowBatteryLevel, isUntethered, nativeBatteryLevel)); } private void updateSubLayoutUi( LinearLayout linearLayout, int iconMetaKey, int batteryMetaKey, int lowBatteryMetaKey, int chargeMetaKey, int titleResId, int deviceId, Supplier<String> preloadedIconUri, Supplier<Integer> preloadedBatteryLevel, Supplier<Boolean> preloadedCharging, Supplier<Integer> preloadedLowBatteryLevel, Supplier<Boolean> preloadedIsUntethered, Supplier<Integer> preloadedNativeBatteryLevel) { final BluetoothDevice bluetoothDevice = mCachedDevice.getDevice(); final String iconUri = BluetoothUtils.getStringMetaData(bluetoothDevice, iconMetaKey); final String iconUri = preloadedIconUri.get(); final ImageView imageView = linearLayout.findViewById(R.id.header_icon); if (iconUri != null) { updateIcon(imageView, iconUri); Loading @@ -331,17 +435,9 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont imageView.setImageDrawable(pair.first); imageView.setContentDescription(pair.second); } final int batteryLevel = BluetoothUtils.getIntMetaData(bluetoothDevice, batteryMetaKey); final boolean charging = BluetoothUtils.getBooleanMetaData(bluetoothDevice, chargeMetaKey); int lowBatteryLevel = BluetoothUtils.getIntMetaData(bluetoothDevice, lowBatteryMetaKey); if (lowBatteryLevel == BluetoothUtils.META_INT_ERROR) { if (batteryMetaKey == BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY) { lowBatteryLevel = CASE_LOW_BATTERY_LEVEL; } else { lowBatteryLevel = LOW_BATTERY_LEVEL; } } final int batteryLevel = preloadedBatteryLevel.get(); final boolean charging = preloadedCharging.get(); int lowBatteryLevel = preloadedLowBatteryLevel.get(); Log.d(TAG, "buletoothDevice: " + bluetoothDevice.getAnonymizedAddress() + ", updateSubLayout() icon : " + iconMetaKey + ", battery : " + batteryMetaKey Loading @@ -353,7 +449,7 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont showBatteryPredictionIfNecessary(linearLayout, deviceId, batteryLevel); } final TextView batterySummaryView = linearLayout.findViewById(R.id.bt_battery_summary); if (isUntetheredHeadset(bluetoothDevice)) { if (preloadedIsUntethered.get()) { if (batteryLevel != BluetoothUtils.META_INT_ERROR) { linearLayout.setVisibility(View.VISIBLE); batterySummaryView.setText( Loading @@ -364,7 +460,7 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont if (deviceId == MAIN_DEVICE_ID) { linearLayout.setVisibility(View.VISIBLE); linearLayout.findViewById(R.id.bt_battery_icon).setVisibility(View.GONE); int level = bluetoothDevice.getBatteryLevel(); int level = preloadedNativeBatteryLevel.get(); if (level != BluetoothDevice.BATTERY_LEVEL_UNKNOWN && level != BluetoothDevice.BATTERY_LEVEL_BLUETOOTH_OFF) { batterySummaryView.setText( Loading
src/com/android/settings/bluetooth/Utils.java +22 −0 Original line number Diff line number Diff line Loading @@ -37,12 +37,16 @@ import androidx.annotation.VisibleForTesting; import androidx.appcompat.app.AlertDialog; import com.android.settings.R; import com.android.settings.flags.Flags; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.bluetooth.BluetoothUtils; import com.android.settingslib.bluetooth.BluetoothUtils.ErrorListener; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothManager.BluetoothManagerCallback; import com.android.settingslib.utils.ThreadUtils; import com.google.common.base.Supplier; import java.util.ArrayList; import java.util.List; Loading Loading @@ -272,4 +276,22 @@ public final class Utils { + " , deviceList = " + cachedBluetoothDevices); return cachedBluetoothDevices; } /** * Preloads the values and run the Runnable afterwards. * @param suppliers the value supplier, should be a memoized supplier * @param runnable the runnable to be run after value is preloaded */ public static void preloadAndRun(List<Supplier<?>> suppliers, Runnable runnable) { if (!Flags.enableOffloadBluetoothOperationsToBackgroundThread()) { runnable.run(); return; } ThreadUtils.postOnBackgroundThread(() -> { for (Supplier<?> supplier : suppliers) { supplier.get(); } ThreadUtils.postOnMainThread(runnable); }); } }