Loading src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java +2 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java +35 −22 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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(); } Loading Loading @@ -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(); Loading Loading @@ -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( Loading Loading @@ -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()) Loading src/com/android/settings/homepage/contextualcards/slices/BluetoothUpdateWorker.java +86 −9 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading Loading @@ -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 Loading
src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java +2 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading
src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java +35 −22 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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(); } Loading Loading @@ -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(); Loading Loading @@ -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( Loading Loading @@ -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()) Loading
src/com/android/settings/homepage/contextualcards/slices/BluetoothUpdateWorker.java +86 −9 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading Loading @@ -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