Merge "Improve BT slice card loading performance" into rvc-dev am: 85f03668a5

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Settings/+/11833854

Change-Id: Id2cfccbafd268452178ea68845286daa480924b2
This commit is contained in:
Jason Chiu
2020-06-14 17:30:12 +00:00
committed by Automerger Merge Worker
3 changed files with 123 additions and 31 deletions

View File

@@ -37,6 +37,7 @@ import androidx.recyclerview.widget.ItemTouchHelper;
import com.android.settings.R;
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.overlay.FeatureFactory;
import com.android.settings.wifi.slice.ContextualWifiScanWorker;
@@ -67,6 +68,7 @@ public class ContextualCardsFragment extends InstrumentedFragment implements
final Context context = getContext();
if (savedInstanceState == null) {
FeatureFactory.getFactory(context).getSlicesFeatureProvider().newUiSession();
BluetoothUpdateWorker.initLocalBtManager(getContext());
}
mContextualCardManager = new ContextualCardManager(context, getSettingsLifecycle(),
savedInstanceState);

View File

@@ -81,15 +81,12 @@ public class BluetoothDevicesSlice implements CustomSliceable {
private static boolean sBluetoothEnabling;
private final Context mContext;
private final AvailableMediaBluetoothDeviceUpdater mAvailableMediaBtDeviceUpdater;
private final SavedBluetoothDeviceUpdater mSavedBtDeviceUpdater;
private AvailableMediaBluetoothDeviceUpdater mAvailableMediaBtDeviceUpdater;
private SavedBluetoothDeviceUpdater mSavedBtDeviceUpdater;
public BluetoothDevicesSlice(Context context) {
mContext = context;
mAvailableMediaBtDeviceUpdater = new AvailableMediaBluetoothDeviceUpdater(mContext,
null /* fragment */, null /* devicePreferenceCallback */);
mSavedBtDeviceUpdater = new SavedBluetoothDeviceUpdater(mContext,
null /* fragment */, null /* devicePreferenceCallback */);
BluetoothUpdateWorker.initLocalBtManager(context);
}
@Override
@@ -119,16 +116,8 @@ public class BluetoothDevicesSlice implements CustomSliceable {
// Add the header of Bluetooth on
listBuilder.addRow(getBluetoothOnHeader());
// Get row builders of Bluetooth devices.
final List<ListBuilder.RowBuilder> rows = getBluetoothRowBuilders();
// 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));
}
// Add row builders of Bluetooth devices.
getBluetoothRowBuilders().forEach(row -> listBuilder.addRow(row));
return listBuilder.build();
}
@@ -181,19 +170,18 @@ public class BluetoothDevicesSlice implements CustomSliceable {
List<CachedBluetoothDevice> getPairedBluetoothDevices() {
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()) {
Log.i(TAG, "Cannot get Bluetooth devices, Bluetooth is disabled.");
return bluetoothDeviceList;
}
// Get the Bluetooth devices from LocalBluetoothManager.
final LocalBluetoothManager localBtManager =
com.android.settings.bluetooth.Utils.getLocalBtManager(mContext);
final LocalBluetoothManager localBtManager = BluetoothUpdateWorker.getLocalBtManager();
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;
}
final Collection<CachedBluetoothDevice> cachedDevices =
localBtManager.getCachedDeviceManager().getCachedDevicesCopy();
@@ -292,8 +280,21 @@ public class BluetoothDevicesSlice implements CustomSliceable {
private List<ListBuilder.RowBuilder> getBluetoothRowBuilders() {
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.
for (CachedBluetoothDevice device : getPairedBluetoothDevices()) {
for (CachedBluetoothDevice device : pairedDevices) {
if (bluetoothRows.size() >= DEFAULT_EXPANDED_ROW_COUNT) {
break;
}
String summary = device.getConnectionSummary();
if (summary == null) {
summary = mContext.getString(
@@ -321,6 +322,18 @@ public class BluetoothDevicesSlice implements CustomSliceable {
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
SliceAction buildPrimaryBluetoothAction(CachedBluetoothDevice bluetoothDevice) {
final Intent intent = new Intent(getUri().toString())

View File

@@ -18,9 +18,14 @@ package com.android.settings.homepage.contextualcards.slices;
import android.content.Context;
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 com.android.settings.bluetooth.Utils;
import androidx.annotation.Nullable;
import com.android.settings.slices.SliceBackgroundWorker;
import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -30,29 +35,46 @@ public class BluetoothUpdateWorker extends SliceBackgroundWorker implements Blue
private static final String TAG = "BluetoothUpdateWorker";
private final LocalBluetoothManager mLocalBluetoothManager;
private static LocalBluetoothManager sLocalBluetoothManager;
private LoadBtManagerHandler mLoadBtManagerHandler;
public BluetoothUpdateWorker(Context context, Uri 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
protected void onSlicePinned() {
if (mLocalBluetoothManager == null) {
Log.i(TAG, "onSlicePinned() Bluetooth is unsupported.");
final LocalBluetoothManager localBtManager = mLoadBtManagerHandler.getLocalBtManager();
if (localBtManager == null) {
return;
}
mLocalBluetoothManager.getEventManager().registerCallback(this);
localBtManager.getEventManager().registerCallback(this);
}
@Override
protected void onSliceUnpinned() {
if (mLocalBluetoothManager == null) {
Log.i(TAG, "onSliceUnpinned() Bluetooth is unsupported.");
final LocalBluetoothManager localBtManager = mLoadBtManagerHandler.getLocalBtManager();
if (localBtManager == null) {
return;
}
mLocalBluetoothManager.getEventManager().unregisterCallback(this);
localBtManager.getEventManager().unregisterCallback(this);
}
@Override
@@ -84,4 +106,59 @@ public class BluetoothUpdateWorker extends SliceBackgroundWorker implements Blue
int bluetoothProfile) {
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();
}
}
}