diff --git a/src/com/android/settings/bluetooth/BluetoothBroadcastSourcePreference.java b/src/com/android/settings/bluetooth/BluetoothBroadcastSourcePreference.java index 17b604c58ff..733a4a96e49 100644 --- a/src/com/android/settings/bluetooth/BluetoothBroadcastSourcePreference.java +++ b/src/com/android/settings/bluetooth/BluetoothBroadcastSourcePreference.java @@ -16,7 +16,9 @@ package com.android.settings.bluetooth; +import android.bluetooth.BluetoothLeAudioContentMetadata; import android.bluetooth.BluetoothLeBroadcastMetadata; +import android.bluetooth.BluetoothLeBroadcastReceiveState; import android.bluetooth.BluetoothLeBroadcastSubgroup; import android.content.Context; import android.graphics.drawable.Drawable; @@ -43,16 +45,15 @@ class BluetoothBroadcastSourcePreference extends Preference { private static final int RESOURCE_ID_ICON = R.drawable.settings_input_antenna; private BluetoothLeBroadcastMetadata mBluetoothLeBroadcastMetadata; + private BluetoothLeBroadcastReceiveState mBluetoothLeBroadcastReceiveState; private ImageView mFrictionImageView; private String mTitle; private boolean mStatus; private boolean mIsEncrypted; - BluetoothBroadcastSourcePreference(@NonNull Context context, - @NonNull BluetoothLeBroadcastMetadata source) { + BluetoothBroadcastSourcePreference(@NonNull Context context) { super(context); initUi(); - updateMetadataAndRefreshUi(source, false); } @Override @@ -68,7 +69,7 @@ class BluetoothBroadcastSourcePreference extends Preference { private void initUi() { setLayoutResource(R.layout.preference_access_point); setWidgetLayoutResource(R.layout.access_point_friction_widget); - + mTitle = getContext().getString(RESOURCE_ID_UNKNOWN_PROGRAM_INFO); mStatus = false; final Drawable drawable = getContext().getDrawable(RESOURCE_ID_ICON); if (drawable != null) { @@ -105,9 +106,20 @@ class BluetoothBroadcastSourcePreference extends Preference { */ public void updateMetadataAndRefreshUi(BluetoothLeBroadcastMetadata source, boolean status) { mBluetoothLeBroadcastMetadata = source; - mTitle = getBroadcastMetadataProgramInfo(); + mTitle = getProgramInfo(); mIsEncrypted = mBluetoothLeBroadcastMetadata.isEncrypted(); - mStatus = status; + mStatus = status || mBluetoothLeBroadcastReceiveState != null; + + refresh(); + } + + /** + * Updates the title and status from BluetoothLeBroadcastReceiveState. + */ + public void updateReceiveStateAndRefreshUi(BluetoothLeBroadcastReceiveState receiveState) { + mBluetoothLeBroadcastReceiveState = receiveState; + mTitle = getProgramInfo(); + mStatus = true; refresh(); } @@ -124,7 +136,17 @@ class BluetoothBroadcastSourcePreference extends Preference { updateStatusButton(); } - private String getBroadcastMetadataProgramInfo() { + private String getProgramInfo() { + if (mBluetoothLeBroadcastReceiveState != null) { + List bluetoothLeAudioContentMetadata = + mBluetoothLeBroadcastReceiveState.getSubgroupMetadata(); + if (!bluetoothLeAudioContentMetadata.isEmpty()) { + return bluetoothLeAudioContentMetadata.stream() + .map(i -> i.getProgramInfo()) + .findFirst().orElse( + getContext().getString(RESOURCE_ID_UNKNOWN_PROGRAM_INFO)); + } + } if (mBluetoothLeBroadcastMetadata == null) { return getContext().getString(RESOURCE_ID_UNKNOWN_PROGRAM_INFO); } @@ -138,4 +160,24 @@ class BluetoothBroadcastSourcePreference extends Preference { .filter(i -> !TextUtils.isEmpty(i)) .findFirst().orElse(getContext().getString(RESOURCE_ID_UNKNOWN_PROGRAM_INFO)); } + + /** + * Whether the broadcast source is encrypted or not. + * @return If true, the broadcast source needs the broadcast code. If false, the broadcast + * source does not need the broadcast code. + */ + public boolean isEncrypted() { + return mIsEncrypted; + } + + /** + * Clear the BluetoothLeBroadcastReceiveState and reset the state when the user clicks the + * "leave broadcast" button. + */ + public void clearReceiveState() { + mBluetoothLeBroadcastReceiveState = null; + mTitle = getProgramInfo(); + mStatus = false; + refresh(); + } } diff --git a/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java b/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java index 07a31560d24..13388b3ecd3 100644 --- a/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java +++ b/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java @@ -86,9 +86,7 @@ public class BluetoothFindBroadcastsFragment extends RestrictedDashboardFragment @Override public void onSearchStarted(int reason) { Log.d(TAG, "onSearchStarted: " + reason); - - getActivity().runOnUiThread( - () -> cacheRemoveAllPrefs(mBroadcastSourceListCategory)); + getActivity().runOnUiThread(() -> handleSearchStarted()); } @Override @@ -109,7 +107,8 @@ public class BluetoothFindBroadcastsFragment extends RestrictedDashboardFragment @Override public void onSourceFound(@NonNull BluetoothLeBroadcastMetadata source) { Log.d(TAG, "onSourceFound:"); - getActivity().runOnUiThread(() -> updateListCategory(source, false)); + getActivity().runOnUiThread( + () -> updateListCategoryFromBroadcastMetadata(source, false)); } @Override @@ -119,7 +118,7 @@ public class BluetoothFindBroadcastsFragment extends RestrictedDashboardFragment Log.w(TAG, "onSourceAdded: mSelectedPreference == null!"); return; } - getActivity().runOnUiThread(() -> updateListCategory( + getActivity().runOnUiThread(() -> updateListCategoryFromBroadcastMetadata( mSelectedPreference.getBluetoothLeBroadcastMetadata(), true)); } @@ -144,6 +143,7 @@ public class BluetoothFindBroadcastsFragment extends RestrictedDashboardFragment public void onSourceRemoved(@NonNull BluetoothDevice sink, int sourceId, int reason) { Log.d(TAG, "onSourceRemoved:"); + getActivity().runOnUiThread(() -> handleSourceRemoved()); } @Override @@ -215,6 +215,8 @@ public class BluetoothFindBroadcastsFragment extends RestrictedDashboardFragment //check assistant status. Start searching... if (mLeBroadcastAssistant != null && !mLeBroadcastAssistant.isSearchInProgress()) { mLeBroadcastAssistant.startSearchingForSources(getScanFilter()); + } else { + addConnectedSourcePreference(); } } @@ -310,11 +312,13 @@ public class BluetoothFindBroadcastsFragment extends RestrictedDashboardFragment return Collections.emptyList(); } - private void updateListCategory(BluetoothLeBroadcastMetadata source, boolean isConnected) { + private void updateListCategoryFromBroadcastMetadata(BluetoothLeBroadcastMetadata source, + boolean isConnected) { BluetoothBroadcastSourcePreference item = mBroadcastSourceListCategory.findPreference( Integer.toString(source.getBroadcastId())); if (item == null) { - item = createBluetoothBroadcastSourcePreference(source); + item = createBluetoothBroadcastSourcePreference(); + item.setKey(Integer.toString(source.getBroadcastId())); mBroadcastSourceListCategory.addPreference(item); } item.updateMetadataAndRefreshUi(source, isConnected); @@ -326,13 +330,36 @@ public class BluetoothFindBroadcastsFragment extends RestrictedDashboardFragment } } - private BluetoothBroadcastSourcePreference createBluetoothBroadcastSourcePreference( - BluetoothLeBroadcastMetadata source) { + private void updateListCategoryFromBroadcastReceiveState( + BluetoothLeBroadcastReceiveState receiveState) { + BluetoothBroadcastSourcePreference item = mBroadcastSourceListCategory.findPreference( + Integer.toString(receiveState.getBroadcastId())); + if (item == null) { + item = createBluetoothBroadcastSourcePreference(); + item.setKey(Integer.toString(receiveState.getBroadcastId())); + mBroadcastSourceListCategory.addPreference(item); + } + item.updateReceiveStateAndRefreshUi(receiveState); + item.setOrder(0); + + setSourceId(receiveState.getSourceId()); + mSelectedPreference = item; + + //refresh the header + if (mBluetoothFindBroadcastsHeaderController != null) { + mBluetoothFindBroadcastsHeaderController.refreshUi(); + } + } + + private BluetoothBroadcastSourcePreference createBluetoothBroadcastSourcePreference() { BluetoothBroadcastSourcePreference pref = new BluetoothBroadcastSourcePreference( - getContext(), source); - pref.setKey(Integer.toString(source.getBroadcastId())); + getContext()); pref.setOnPreferenceClickListener(preference -> { - if (source.isEncrypted()) { + if (pref.getBluetoothLeBroadcastMetadata() == null) { + Log.d(TAG, "BluetoothLeBroadcastMetadata is null, do nothing."); + return false; + } + if (pref.isEncrypted()) { launchBroadcastCodeDialog(pref); } else { addSource(pref); @@ -383,6 +410,10 @@ public class BluetoothFindBroadcastsFragment extends RestrictedDashboardFragment .setPositiveButton(R.string.bluetooth_connect_access_dialog_positive, (d, w) -> { Log.d(TAG, "setPositiveButton: clicked"); + if (pref.getBluetoothLeBroadcastMetadata() == null) { + Log.d(TAG, "BluetoothLeBroadcastMetadata is null, do nothing."); + return; + } addBroadcastCodeIntoPreference(pref, editText.getText().toString()); addSource(pref); }) @@ -392,6 +423,30 @@ public class BluetoothFindBroadcastsFragment extends RestrictedDashboardFragment alertDialog.show(); } + private void handleSearchStarted() { + cacheRemoveAllPrefs(mBroadcastSourceListCategory); + addConnectedSourcePreference(); + } + + private void handleSourceRemoved() { + if (mSelectedPreference != null) { + if (mSelectedPreference.getBluetoothLeBroadcastMetadata() == null) { + mBroadcastSourceListCategory.removePreference(mSelectedPreference); + } else { + mSelectedPreference.clearReceiveState(); + } + } + mSelectedPreference = null; + } + + private void addConnectedSourcePreference() { + List receiveStateList = + mLeBroadcastAssistant.getAllSources(mCachedDevice.getDevice()); + if (!receiveStateList.isEmpty()) { + updateListCategoryFromBroadcastReceiveState(receiveStateList.get(0)); + } + } + public int getSourceId() { return mSourceId; }