Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 85f03668 authored by Jason Chiu's avatar Jason Chiu Committed by Android (Google) Code Review
Browse files

Merge "Improve BT slice card loading performance" into rvc-dev

parents 4b25f3f1 3c3f3621
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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);
+35 −22
Original line number Diff line number Diff line
@@ -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())
+86 −9
Original line number Diff line number Diff line
@@ -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();
        }
    }
}
 No newline at end of file