Merge "Improve BT slice card loading performance" into rvc-dev am: 85f03668a5
am: 42a725039a
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Settings/+/11833854 Change-Id: If95d439f1767415ac1c23d5c62eb6731529c6f34
This commit is contained in:
@@ -37,6 +37,7 @@ import androidx.recyclerview.widget.ItemTouchHelper;
|
|||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.core.InstrumentedFragment;
|
import com.android.settings.core.InstrumentedFragment;
|
||||||
|
import com.android.settings.homepage.contextualcards.slices.BluetoothUpdateWorker;
|
||||||
import com.android.settings.homepage.contextualcards.slices.SwipeDismissalDelegate;
|
import com.android.settings.homepage.contextualcards.slices.SwipeDismissalDelegate;
|
||||||
import com.android.settings.overlay.FeatureFactory;
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
import com.android.settings.wifi.slice.ContextualWifiScanWorker;
|
import com.android.settings.wifi.slice.ContextualWifiScanWorker;
|
||||||
@@ -67,6 +68,7 @@ public class ContextualCardsFragment extends InstrumentedFragment implements
|
|||||||
final Context context = getContext();
|
final Context context = getContext();
|
||||||
if (savedInstanceState == null) {
|
if (savedInstanceState == null) {
|
||||||
FeatureFactory.getFactory(context).getSlicesFeatureProvider().newUiSession();
|
FeatureFactory.getFactory(context).getSlicesFeatureProvider().newUiSession();
|
||||||
|
BluetoothUpdateWorker.initLocalBtManager(getContext());
|
||||||
}
|
}
|
||||||
mContextualCardManager = new ContextualCardManager(context, getSettingsLifecycle(),
|
mContextualCardManager = new ContextualCardManager(context, getSettingsLifecycle(),
|
||||||
savedInstanceState);
|
savedInstanceState);
|
||||||
|
@@ -81,15 +81,12 @@ public class BluetoothDevicesSlice implements CustomSliceable {
|
|||||||
private static boolean sBluetoothEnabling;
|
private static boolean sBluetoothEnabling;
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final AvailableMediaBluetoothDeviceUpdater mAvailableMediaBtDeviceUpdater;
|
private AvailableMediaBluetoothDeviceUpdater mAvailableMediaBtDeviceUpdater;
|
||||||
private final SavedBluetoothDeviceUpdater mSavedBtDeviceUpdater;
|
private SavedBluetoothDeviceUpdater mSavedBtDeviceUpdater;
|
||||||
|
|
||||||
public BluetoothDevicesSlice(Context context) {
|
public BluetoothDevicesSlice(Context context) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mAvailableMediaBtDeviceUpdater = new AvailableMediaBluetoothDeviceUpdater(mContext,
|
BluetoothUpdateWorker.initLocalBtManager(context);
|
||||||
null /* fragment */, null /* devicePreferenceCallback */);
|
|
||||||
mSavedBtDeviceUpdater = new SavedBluetoothDeviceUpdater(mContext,
|
|
||||||
null /* fragment */, null /* devicePreferenceCallback */);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -119,16 +116,8 @@ public class BluetoothDevicesSlice implements CustomSliceable {
|
|||||||
// Add the header of Bluetooth on
|
// Add the header of Bluetooth on
|
||||||
listBuilder.addRow(getBluetoothOnHeader());
|
listBuilder.addRow(getBluetoothOnHeader());
|
||||||
|
|
||||||
// Get row builders of Bluetooth devices.
|
// Add row builders of Bluetooth devices.
|
||||||
final List<ListBuilder.RowBuilder> rows = getBluetoothRowBuilders();
|
getBluetoothRowBuilders().forEach(row -> listBuilder.addRow(row));
|
||||||
|
|
||||||
// Determine the displayable row count.
|
|
||||||
final int displayableCount = Math.min(rows.size(), DEFAULT_EXPANDED_ROW_COUNT);
|
|
||||||
|
|
||||||
// Add device rows up to the count.
|
|
||||||
for (int i = 0; i < displayableCount; i++) {
|
|
||||||
listBuilder.addRow(rows.get(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
return listBuilder.build();
|
return listBuilder.build();
|
||||||
}
|
}
|
||||||
@@ -181,19 +170,18 @@ public class BluetoothDevicesSlice implements CustomSliceable {
|
|||||||
List<CachedBluetoothDevice> getPairedBluetoothDevices() {
|
List<CachedBluetoothDevice> getPairedBluetoothDevices() {
|
||||||
final List<CachedBluetoothDevice> bluetoothDeviceList = new ArrayList<>();
|
final List<CachedBluetoothDevice> bluetoothDeviceList = new ArrayList<>();
|
||||||
|
|
||||||
// If Bluetooth is disable, skip to get the Bluetooth devices.
|
// If Bluetooth is disable, skip getting the Bluetooth devices.
|
||||||
if (!BluetoothAdapter.getDefaultAdapter().isEnabled()) {
|
if (!BluetoothAdapter.getDefaultAdapter().isEnabled()) {
|
||||||
Log.i(TAG, "Cannot get Bluetooth devices, Bluetooth is disabled.");
|
Log.i(TAG, "Cannot get Bluetooth devices, Bluetooth is disabled.");
|
||||||
return bluetoothDeviceList;
|
return bluetoothDeviceList;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the Bluetooth devices from LocalBluetoothManager.
|
final LocalBluetoothManager localBtManager = BluetoothUpdateWorker.getLocalBtManager();
|
||||||
final LocalBluetoothManager localBtManager =
|
|
||||||
com.android.settings.bluetooth.Utils.getLocalBtManager(mContext);
|
|
||||||
if (localBtManager == null) {
|
if (localBtManager == null) {
|
||||||
Log.i(TAG, "Cannot get Bluetooth devices, Bluetooth is unsupported.");
|
Log.i(TAG, "Cannot get Bluetooth devices, Bluetooth is not ready.");
|
||||||
return bluetoothDeviceList;
|
return bluetoothDeviceList;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Collection<CachedBluetoothDevice> cachedDevices =
|
final Collection<CachedBluetoothDevice> cachedDevices =
|
||||||
localBtManager.getCachedDeviceManager().getCachedDevicesCopy();
|
localBtManager.getCachedDeviceManager().getCachedDevicesCopy();
|
||||||
|
|
||||||
@@ -292,8 +280,21 @@ public class BluetoothDevicesSlice implements CustomSliceable {
|
|||||||
|
|
||||||
private List<ListBuilder.RowBuilder> getBluetoothRowBuilders() {
|
private List<ListBuilder.RowBuilder> getBluetoothRowBuilders() {
|
||||||
final List<ListBuilder.RowBuilder> bluetoothRows = new ArrayList<>();
|
final List<ListBuilder.RowBuilder> bluetoothRows = new ArrayList<>();
|
||||||
|
final List<CachedBluetoothDevice> pairedDevices = getPairedBluetoothDevices();
|
||||||
|
if (pairedDevices.isEmpty()) {
|
||||||
|
return bluetoothRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize updaters without being blocked after paired devices is available because
|
||||||
|
// LocalBluetoothManager is ready.
|
||||||
|
lazyInitUpdaters();
|
||||||
|
|
||||||
// Create row builders based on paired devices.
|
// Create row builders based on paired devices.
|
||||||
for (CachedBluetoothDevice device : getPairedBluetoothDevices()) {
|
for (CachedBluetoothDevice device : pairedDevices) {
|
||||||
|
if (bluetoothRows.size() >= DEFAULT_EXPANDED_ROW_COUNT) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
String summary = device.getConnectionSummary();
|
String summary = device.getConnectionSummary();
|
||||||
if (summary == null) {
|
if (summary == null) {
|
||||||
summary = mContext.getString(
|
summary = mContext.getString(
|
||||||
@@ -321,6 +322,18 @@ public class BluetoothDevicesSlice implements CustomSliceable {
|
|||||||
return bluetoothRows;
|
return bluetoothRows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void lazyInitUpdaters() {
|
||||||
|
if (mAvailableMediaBtDeviceUpdater == null) {
|
||||||
|
mAvailableMediaBtDeviceUpdater = new AvailableMediaBluetoothDeviceUpdater(mContext,
|
||||||
|
null /* fragment */, null /* devicePreferenceCallback */);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mSavedBtDeviceUpdater == null) {
|
||||||
|
mSavedBtDeviceUpdater = new SavedBluetoothDeviceUpdater(mContext,
|
||||||
|
null /* fragment */, null /* devicePreferenceCallback */);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
SliceAction buildPrimaryBluetoothAction(CachedBluetoothDevice bluetoothDevice) {
|
SliceAction buildPrimaryBluetoothAction(CachedBluetoothDevice bluetoothDevice) {
|
||||||
final Intent intent = new Intent(getUri().toString())
|
final Intent intent = new Intent(getUri().toString())
|
||||||
|
@@ -18,9 +18,14 @@ package com.android.settings.homepage.contextualcards.slices;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.HandlerThread;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.os.Process;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.settings.bluetooth.Utils;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.android.settings.slices.SliceBackgroundWorker;
|
import com.android.settings.slices.SliceBackgroundWorker;
|
||||||
import com.android.settingslib.bluetooth.BluetoothCallback;
|
import com.android.settingslib.bluetooth.BluetoothCallback;
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
@@ -30,29 +35,46 @@ public class BluetoothUpdateWorker extends SliceBackgroundWorker implements Blue
|
|||||||
|
|
||||||
private static final String TAG = "BluetoothUpdateWorker";
|
private static final String TAG = "BluetoothUpdateWorker";
|
||||||
|
|
||||||
private final LocalBluetoothManager mLocalBluetoothManager;
|
private static LocalBluetoothManager sLocalBluetoothManager;
|
||||||
|
|
||||||
|
private LoadBtManagerHandler mLoadBtManagerHandler;
|
||||||
|
|
||||||
public BluetoothUpdateWorker(Context context, Uri uri) {
|
public BluetoothUpdateWorker(Context context, Uri uri) {
|
||||||
super(context, uri);
|
super(context, uri);
|
||||||
mLocalBluetoothManager = Utils.getLocalBtManager(context);
|
mLoadBtManagerHandler = LoadBtManagerHandler.getInstance(context);
|
||||||
|
if (sLocalBluetoothManager == null) {
|
||||||
|
mLoadBtManagerHandler.startLoadingBtManager(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Initialize {@link LocalBluetoothManager} in the background */
|
||||||
|
public static void initLocalBtManager(Context context) {
|
||||||
|
if (sLocalBluetoothManager == null) {
|
||||||
|
LoadBtManagerHandler.getInstance(context).startLoadingBtManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
static LocalBluetoothManager getLocalBtManager() {
|
||||||
|
return sLocalBluetoothManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSlicePinned() {
|
protected void onSlicePinned() {
|
||||||
if (mLocalBluetoothManager == null) {
|
final LocalBluetoothManager localBtManager = mLoadBtManagerHandler.getLocalBtManager();
|
||||||
Log.i(TAG, "onSlicePinned() Bluetooth is unsupported.");
|
if (localBtManager == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mLocalBluetoothManager.getEventManager().registerCallback(this);
|
localBtManager.getEventManager().registerCallback(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSliceUnpinned() {
|
protected void onSliceUnpinned() {
|
||||||
if (mLocalBluetoothManager == null) {
|
final LocalBluetoothManager localBtManager = mLoadBtManagerHandler.getLocalBtManager();
|
||||||
Log.i(TAG, "onSliceUnpinned() Bluetooth is unsupported.");
|
if (localBtManager == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mLocalBluetoothManager.getEventManager().unregisterCallback(this);
|
localBtManager.getEventManager().unregisterCallback(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -84,4 +106,59 @@ public class BluetoothUpdateWorker extends SliceBackgroundWorker implements Blue
|
|||||||
int bluetoothProfile) {
|
int bluetoothProfile) {
|
||||||
notifySliceChange();
|
notifySliceChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class LoadBtManagerHandler extends Handler {
|
||||||
|
|
||||||
|
private static LoadBtManagerHandler sHandler;
|
||||||
|
|
||||||
|
private final Runnable mLoadBtManagerTask;
|
||||||
|
private final Context mContext;
|
||||||
|
private BluetoothUpdateWorker mWorker;
|
||||||
|
|
||||||
|
private static LoadBtManagerHandler getInstance(Context context) {
|
||||||
|
if (sHandler == null) {
|
||||||
|
final HandlerThread workerThread = new HandlerThread(TAG,
|
||||||
|
Process.THREAD_PRIORITY_BACKGROUND);
|
||||||
|
workerThread.start();
|
||||||
|
sHandler = new LoadBtManagerHandler(context, workerThread.getLooper());
|
||||||
|
}
|
||||||
|
return sHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LoadBtManagerHandler(Context context, Looper looper) {
|
||||||
|
super(looper);
|
||||||
|
mContext = context;
|
||||||
|
mLoadBtManagerTask = () -> {
|
||||||
|
Log.d(TAG, "LoadBtManagerHandler: start loading...");
|
||||||
|
final long startTime = System.currentTimeMillis();
|
||||||
|
sLocalBluetoothManager = getLocalBtManager();
|
||||||
|
Log.d(TAG, "LoadBtManagerHandler took " + (System.currentTimeMillis() - startTime)
|
||||||
|
+ " ms");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private LocalBluetoothManager getLocalBtManager() {
|
||||||
|
if (sLocalBluetoothManager != null) {
|
||||||
|
return sLocalBluetoothManager;
|
||||||
|
}
|
||||||
|
return LocalBluetoothManager.getInstance(mContext,
|
||||||
|
(context, btManager) -> {
|
||||||
|
if (mWorker != null) {
|
||||||
|
// notify change if the worker is ready
|
||||||
|
mWorker.notifySliceChange();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startLoadingBtManager() {
|
||||||
|
if (!hasCallbacks(mLoadBtManagerTask)) {
|
||||||
|
post(mLoadBtManagerTask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startLoadingBtManager(BluetoothUpdateWorker worker) {
|
||||||
|
mWorker = worker;
|
||||||
|
startLoadingBtManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user