Fix bluetooth settings pairing page stuck
There is heavy work to do when add device to list in the DeviceListPreferenceFragment, off load these work from main thread to solve the issue. Make devicePreferenceMap a ConcurrentHashMap to avoid potential race condition. Also no longer use getCachedPreference(key) since we not put anything into the cache, the fallback flow is always used. Also in BluetoothDevicePreference.onPreferenceAttributesChanged(), move more heavy work to background thread. Using System.currentTimeMillis() to sort devices could cause flaky because System.currentTimeMillis() could be same for different device, use AtomicInteger instead. Fix: 286628533 Test: Following the step in bug Change-Id: Ia9750adb6b4c1424d084381e9d7c2ca8e7912391
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* Copyright (C) 2023 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.
|
||||
@@ -35,6 +35,8 @@ import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.preference.Preference;
|
||||
@@ -52,6 +54,7 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* BluetoothDevicePreference is the preference type used to display each remote
|
||||
@@ -79,7 +82,9 @@ public final class BluetoothDevicePreference extends GearPreference {
|
||||
@VisibleForTesting
|
||||
BluetoothAdapter mBluetoothAdapter;
|
||||
private final boolean mShowDevicesWithoutNames;
|
||||
private final long mCurrentTime;
|
||||
@NonNull
|
||||
private static final AtomicInteger sNextId = new AtomicInteger();
|
||||
private final int mId;
|
||||
private final int mType;
|
||||
|
||||
private AlertDialog mDisconnectDialog;
|
||||
@@ -127,8 +132,9 @@ public final class BluetoothDevicePreference extends GearPreference {
|
||||
|
||||
mCachedDevice = cachedDevice;
|
||||
mCallback = new BluetoothDevicePreferenceCallback();
|
||||
mCurrentTime = System.currentTimeMillis();
|
||||
mId = sNextId.getAndIncrement();
|
||||
mType = type;
|
||||
setVisible(false);
|
||||
|
||||
onPreferenceAttributesChanged();
|
||||
}
|
||||
@@ -229,35 +235,41 @@ public final class BluetoothDevicePreference extends GearPreference {
|
||||
|
||||
@SuppressWarnings("FutureReturnValueIgnored")
|
||||
void onPreferenceAttributesChanged() {
|
||||
Pair<Drawable, String> pair = mCachedDevice.getDrawableWithDescription();
|
||||
setIcon(pair.first);
|
||||
contentDescription = pair.second;
|
||||
|
||||
/*
|
||||
* The preference framework takes care of making sure the value has
|
||||
* changed before proceeding. It will also call notifyChanged() if
|
||||
* any preference info has changed from the previous value.
|
||||
*/
|
||||
setTitle(mCachedDevice.getName());
|
||||
try {
|
||||
ThreadUtils.postOnBackgroundThread(() -> {
|
||||
@Nullable String name = mCachedDevice.getName();
|
||||
// Null check is done at the framework
|
||||
ThreadUtils.postOnMainThread(() -> setSummary(getConnectionSummary()));
|
||||
@Nullable String connectionSummary = getConnectionSummary();
|
||||
@NonNull Pair<Drawable, String> pair = mCachedDevice.getDrawableWithDescription();
|
||||
boolean isBusy = mCachedDevice.isBusy();
|
||||
// Device is only visible in the UI if it has a valid name besides MAC address or
|
||||
// when user allows showing devices without user-friendly name in developer settings
|
||||
boolean isVisible =
|
||||
mShowDevicesWithoutNames || mCachedDevice.hasHumanReadableName();
|
||||
|
||||
ThreadUtils.postOnMainThread(() -> {
|
||||
/*
|
||||
* The preference framework takes care of making sure the value has
|
||||
* changed before proceeding. It will also call notifyChanged() if
|
||||
* any preference info has changed from the previous value.
|
||||
*/
|
||||
setTitle(name);
|
||||
setSummary(connectionSummary);
|
||||
setIcon(pair.first);
|
||||
contentDescription = pair.second;
|
||||
// Used to gray out the item
|
||||
setEnabled(!isBusy);
|
||||
setVisible(isVisible);
|
||||
|
||||
// This could affect ordering, so notify that
|
||||
if (mNeedNotifyHierarchyChanged) {
|
||||
notifyHierarchyChanged();
|
||||
}
|
||||
});
|
||||
});
|
||||
} catch (RejectedExecutionException e) {
|
||||
Log.w(TAG, "Handler thread unavailable, skipping getConnectionSummary!");
|
||||
}
|
||||
// Used to gray out the item
|
||||
setEnabled(!mCachedDevice.isBusy());
|
||||
|
||||
// Device is only visible in the UI if it has a valid name besides MAC address or when user
|
||||
// allows showing devices without user-friendly name in developer settings
|
||||
setVisible(mShowDevicesWithoutNames || mCachedDevice.hasHumanReadableName());
|
||||
|
||||
// This could affect ordering, so notify that
|
||||
if (mNeedNotifyHierarchyChanged) {
|
||||
notifyHierarchyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -311,7 +323,7 @@ public final class BluetoothDevicePreference extends GearPreference {
|
||||
return mCachedDevice
|
||||
.compareTo(((BluetoothDevicePreference) another).mCachedDevice);
|
||||
case SortType.TYPE_FIFO:
|
||||
return mCurrentTime > ((BluetoothDevicePreference) another).mCurrentTime ? 1 : -1;
|
||||
return mId > ((BluetoothDevicePreference) another).mId ? 1 : -1;
|
||||
default:
|
||||
return super.compareTo(another);
|
||||
}
|
||||
|
Reference in New Issue
Block a user