[Audiosharing] Add button action in detail page.

Bug: 308368124
Test: manual
Change-Id: I44e631cb75af432965d2221e71676146ea1537b6
This commit is contained in:
chelseahao
2024-01-19 15:43:17 +08:00
parent 911d85a9fd
commit 8a3ebe25e0
7 changed files with 528 additions and 60 deletions

View File

@@ -16,39 +16,170 @@
package com.android.settings.connecteddevice.audiosharing.audiostreams;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastAssistant;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.content.Context;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.bluetooth.Utils;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
import com.android.settingslib.utils.ThreadUtils;
import com.android.settingslib.widget.ActionButtonsPreference;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class AudioStreamButtonController extends BasePreferenceController
implements DefaultLifecycleObserver {
private static final String TAG = "AudioStreamButtonController";
private static final String KEY = "audio_stream_button";
private final BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
new AudioStreamsBroadcastAssistantCallback() {
@Override
public void onSourceRemoved(BluetoothDevice sink, int sourceId, int reason) {
super.onSourceRemoved(sink, sourceId, reason);
updateButton();
}
@Override
public void onSourceRemoveFailed(BluetoothDevice sink, int sourceId, int reason) {
super.onSourceRemoveFailed(sink, sourceId, reason);
updateButton();
}
@Override
public void onReceiveStateChanged(
BluetoothDevice sink,
int sourceId,
BluetoothLeBroadcastReceiveState state) {
super.onReceiveStateChanged(sink, sourceId, state);
if (mAudioStreamsHelper.isConnected(state)) {
updateButton();
}
}
@Override
public void onSourceAddFailed(
BluetoothDevice sink, BluetoothLeBroadcastMetadata source, int reason) {
super.onSourceAddFailed(sink, source, reason);
updateButton();
}
@Override
public void onSourceLost(int broadcastId) {
super.onSourceLost(broadcastId);
updateButton();
}
};
private final AudioStreamsRepository mAudioStreamsRepository =
AudioStreamsRepository.getInstance();
private final Executor mExecutor;
private final AudioStreamsHelper mAudioStreamsHelper;
private final @Nullable LocalBluetoothLeBroadcastAssistant mLeBroadcastAssistant;
private @Nullable ActionButtonsPreference mPreference;
private int mBroadcastId = -1;
public AudioStreamButtonController(Context context, String preferenceKey) {
super(context, preferenceKey);
mExecutor = Executors.newSingleThreadExecutor();
mAudioStreamsHelper = new AudioStreamsHelper(Utils.getLocalBtManager(context));
mLeBroadcastAssistant = mAudioStreamsHelper.getLeBroadcastAssistant();
}
@Override
public void onStart(@NonNull LifecycleOwner owner) {
if (mLeBroadcastAssistant == null) {
Log.w(TAG, "onStart(): LeBroadcastAssistant is null!");
return;
}
mLeBroadcastAssistant.registerServiceCallBack(mExecutor, mBroadcastAssistantCallback);
}
@Override
public void onStop(@NonNull LifecycleOwner owner) {
if (mLeBroadcastAssistant == null) {
Log.w(TAG, "onStop(): LeBroadcastAssistant is null!");
return;
}
mLeBroadcastAssistant.unregisterServiceCallBack(mBroadcastAssistantCallback);
}
@Override
public final void displayPreference(PreferenceScreen screen) {
mPreference = screen.findPreference(getPreferenceKey());
if (mPreference != null) {
mPreference.setButton1Enabled(true);
// TODO(chelseahao): update this based on stream connection state
mPreference
.setButton1Text(R.string.bluetooth_device_context_disconnect)
.setButton1Icon(R.drawable.ic_settings_close);
}
updateButton();
super.displayPreference(screen);
}
private void updateButton() {
if (mPreference != null) {
if (mAudioStreamsHelper.getAllConnectedSources().stream()
.map(BluetoothLeBroadcastReceiveState::getBroadcastId)
.anyMatch(connectedBroadcastId -> connectedBroadcastId == mBroadcastId)) {
ThreadUtils.postOnMainThread(
() -> {
if (mPreference != null) {
mPreference.setButton1Enabled(true);
mPreference
.setButton1Text(
R.string.bluetooth_device_context_disconnect)
.setButton1Icon(R.drawable.ic_settings_close)
.setButton1OnClickListener(
unused -> {
if (mPreference != null) {
mPreference.setButton1Enabled(false);
}
mAudioStreamsHelper.removeSource(mBroadcastId);
});
}
});
} else {
View.OnClickListener clickToRejoin =
unused ->
ThreadUtils.postOnBackgroundThread(
() -> {
var metadata =
mAudioStreamsRepository.getSavedMetadata(
mContext, mBroadcastId);
if (metadata != null) {
mAudioStreamsHelper.addSource(metadata);
ThreadUtils.postOnMainThread(
() -> {
if (mPreference != null) {
mPreference.setButton1Enabled(
false);
}
});
}
});
ThreadUtils.postOnMainThread(
() -> {
if (mPreference != null) {
mPreference.setButton1Enabled(true);
mPreference
.setButton1Text(R.string.bluetooth_device_context_connect)
.setButton1Icon(R.drawable.ic_add_24dp)
.setButton1OnClickListener(clickToRejoin);
}
});
}
} else {
Log.w(TAG, "updateButton(): preference is null!");
}
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;

View File

@@ -16,22 +16,64 @@
package com.android.settings.connecteddevice.audiosharing.audiostreams;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastAssistant;
import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.bluetooth.Utils;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
import com.android.settingslib.utils.ThreadUtils;
import com.android.settingslib.widget.LayoutPreference;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import javax.annotation.Nullable;
public class AudioStreamHeaderController extends BasePreferenceController
implements DefaultLifecycleObserver {
private static final String TAG = "AudioStreamHeaderController";
private static final String KEY = "audio_stream_header";
private final Executor mExecutor;
private final AudioStreamsHelper mAudioStreamsHelper;
@Nullable private final LocalBluetoothLeBroadcastAssistant mLeBroadcastAssistant;
private final BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
new AudioStreamsBroadcastAssistantCallback() {
@Override
public void onSourceRemoved(BluetoothDevice sink, int sourceId, int reason) {
super.onSourceRemoved(sink, sourceId, reason);
updateSummary();
}
@Override
public void onSourceLost(int broadcastId) {
super.onSourceLost(broadcastId);
updateSummary();
}
@Override
public void onReceiveStateChanged(
BluetoothDevice sink,
int sourceId,
BluetoothLeBroadcastReceiveState state) {
super.onReceiveStateChanged(sink, sourceId, state);
if (mAudioStreamsHelper.isConnected(state)) {
updateSummary();
}
}
};
private @Nullable EntityHeaderController mHeaderController;
private @Nullable DashboardFragment mFragment;
private String mBroadcastName = "";
@@ -39,6 +81,27 @@ public class AudioStreamHeaderController extends BasePreferenceController
public AudioStreamHeaderController(Context context, String preferenceKey) {
super(context, preferenceKey);
mExecutor = Executors.newSingleThreadExecutor();
mAudioStreamsHelper = new AudioStreamsHelper(Utils.getLocalBtManager(context));
mLeBroadcastAssistant = mAudioStreamsHelper.getLeBroadcastAssistant();
}
@Override
public void onStart(@NonNull LifecycleOwner owner) {
if (mLeBroadcastAssistant == null) {
Log.w(TAG, "onStart(): LeBroadcastAssistant is null!");
return;
}
mLeBroadcastAssistant.registerServiceCallBack(mExecutor, mBroadcastAssistantCallback);
}
@Override
public void onStop(@NonNull LifecycleOwner owner) {
if (mLeBroadcastAssistant == null) {
Log.w(TAG, "onStop(): LeBroadcastAssistant is null!");
return;
}
mLeBroadcastAssistant.unregisterServiceCallBack(mBroadcastAssistantCallback);
}
@Override
@@ -55,14 +118,37 @@ public class AudioStreamHeaderController extends BasePreferenceController
}
mHeaderController.setIcon(
screen.getContext().getDrawable(R.drawable.ic_bt_audio_sharing));
// TODO(chelseahao): update this based on stream connection state
mHeaderController.setSummary("Listening now");
mHeaderController.done(true);
screen.addPreference(headerPreference);
updateSummary();
}
super.displayPreference(screen);
}
private void updateSummary() {
var unused =
ThreadUtils.postOnBackgroundThread(
() -> {
var latestSummary =
mAudioStreamsHelper.getAllConnectedSources().stream()
.map(
BluetoothLeBroadcastReceiveState
::getBroadcastId)
.anyMatch(
connectedBroadcastId ->
connectedBroadcastId
== mBroadcastId)
? "Listening now"
: "";
ThreadUtils.postOnMainThread(
() -> {
if (mHeaderController != null) {
mHeaderController.setSummary(latestSummary);
mHeaderController.done(true);
}
});
});
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;

View File

@@ -24,21 +24,12 @@ import android.util.Log;
import com.android.settingslib.bluetooth.BluetoothUtils;
import java.util.Locale;
public class AudioStreamsBroadcastAssistantCallback
implements BluetoothLeBroadcastAssistant.Callback {
private static final String TAG = "AudioStreamsBroadcastAssistantCallback";
private static final boolean DEBUG = BluetoothUtils.D;
private final AudioStreamsProgressCategoryController mCategoryController;
public AudioStreamsBroadcastAssistantCallback(
AudioStreamsProgressCategoryController audioStreamsProgressCategoryController) {
mCategoryController = audioStreamsProgressCategoryController;
}
@Override
public void onReceiveStateChanged(
BluetoothDevice sink, int sourceId, BluetoothLeBroadcastReceiveState state) {
@@ -52,45 +43,30 @@ public class AudioStreamsBroadcastAssistantCallback
+ " state: "
+ state);
}
mCategoryController.handleSourceConnected(state);
}
@Override
public void onSearchStartFailed(int reason) {
Log.w(TAG, "onSearchStartFailed() reason : " + reason);
mCategoryController.showToast(
String.format(Locale.US, "Failed to start scanning, reason %d", reason));
}
@Override
public void onSearchStarted(int reason) {
if (mCategoryController == null) {
Log.w(TAG, "onSearchStarted() : mCategoryController is null!");
return;
}
if (DEBUG) {
Log.d(TAG, "onSearchStarted() reason : " + reason);
}
mCategoryController.setScanning(true);
}
@Override
public void onSearchStopFailed(int reason) {
Log.w(TAG, "onSearchStopFailed() reason : " + reason);
mCategoryController.showToast(
String.format(Locale.US, "Failed to stop scanning, reason %d", reason));
}
@Override
public void onSearchStopped(int reason) {
if (mCategoryController == null) {
Log.w(TAG, "onSearchStopped() : mCategoryController is null!");
return;
}
if (DEBUG) {
Log.d(TAG, "onSearchStopped() reason : " + reason);
}
mCategoryController.setScanning(false);
}
@Override
@@ -106,8 +82,6 @@ public class AudioStreamsBroadcastAssistantCallback
+ " reason: "
+ reason);
}
mCategoryController.showToast(
String.format(Locale.US, "Failed to join broadcast, reason %d", reason));
}
@Override
@@ -126,14 +100,9 @@ public class AudioStreamsBroadcastAssistantCallback
@Override
public void onSourceFound(BluetoothLeBroadcastMetadata source) {
if (mCategoryController == null) {
Log.w(TAG, "onSourceFound() : mCategoryController is null!");
return;
}
if (DEBUG) {
Log.d(TAG, "onSourceFound() broadcastId : " + source.getBroadcastId());
}
mCategoryController.handleSourceFound(source);
}
@Override
@@ -141,7 +110,6 @@ public class AudioStreamsBroadcastAssistantCallback
if (DEBUG) {
Log.d(TAG, "onSourceLost() broadcastId : " + broadcastId);
}
mCategoryController.handleSourceLost(broadcastId);
}
@Override
@@ -153,12 +121,6 @@ public class AudioStreamsBroadcastAssistantCallback
@Override
public void onSourceRemoveFailed(BluetoothDevice sink, int sourceId, int reason) {
Log.w(TAG, "onSourceRemoveFailed() sourceId : " + sourceId + " reason : " + reason);
mCategoryController.showToast(
String.format(
Locale.US,
"Failed to remove source %d for sink %s",
sourceId,
sink.getAddress()));
}
@Override
@@ -166,8 +128,5 @@ public class AudioStreamsBroadcastAssistantCallback
if (DEBUG) {
Log.d(TAG, "onSourceRemoved() sourceId : " + sourceId + " reason : " + reason);
}
mCategoryController.showToast(
String.format(
Locale.US, "Source %d removed for sink %s", sourceId, sink.getAddress()));
}
}

View File

@@ -0,0 +1,119 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.connecteddevice.audiosharing.audiostreams;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.util.Log;
import java.util.Locale;
public class AudioStreamsProgressCategoryCallback extends AudioStreamsBroadcastAssistantCallback {
private static final String TAG = "AudioStreamsProgressCategoryCallback";
private final AudioStreamsProgressCategoryController mCategoryController;
public AudioStreamsProgressCategoryCallback(
AudioStreamsProgressCategoryController audioStreamsProgressCategoryController) {
mCategoryController = audioStreamsProgressCategoryController;
}
@Override
public void onReceiveStateChanged(
BluetoothDevice sink, int sourceId, BluetoothLeBroadcastReceiveState state) {
super.onReceiveStateChanged(sink, sourceId, state);
mCategoryController.handleSourceConnected(state);
}
@Override
public void onSearchStartFailed(int reason) {
super.onSearchStartFailed(reason);
mCategoryController.showToast(
String.format(Locale.US, "Failed to start scanning, reason %d", reason));
}
@Override
public void onSearchStarted(int reason) {
super.onSearchStarted(reason);
if (mCategoryController == null) {
Log.w(TAG, "onSearchStarted() : mCategoryController is null!");
return;
}
mCategoryController.setScanning(true);
}
@Override
public void onSearchStopFailed(int reason) {
super.onSearchStopFailed(reason);
mCategoryController.showToast(
String.format(Locale.US, "Failed to stop scanning, reason %d", reason));
}
@Override
public void onSearchStopped(int reason) {
super.onSearchStopped(reason);
if (mCategoryController == null) {
Log.w(TAG, "onSearchStopped() : mCategoryController is null!");
return;
}
mCategoryController.setScanning(false);
}
@Override
public void onSourceAddFailed(
BluetoothDevice sink, BluetoothLeBroadcastMetadata source, int reason) {
super.onSourceAddFailed(sink, source, reason);
mCategoryController.showToast(
String.format(Locale.US, "Failed to join broadcast, reason %d", reason));
}
@Override
public void onSourceFound(BluetoothLeBroadcastMetadata source) {
super.onSourceFound(source);
if (mCategoryController == null) {
Log.w(TAG, "onSourceFound() : mCategoryController is null!");
return;
}
mCategoryController.handleSourceFound(source);
}
@Override
public void onSourceLost(int broadcastId) {
super.onSourceLost(broadcastId);
mCategoryController.handleSourceLost(broadcastId);
}
@Override
public void onSourceRemoveFailed(BluetoothDevice sink, int sourceId, int reason) {
super.onSourceRemoveFailed(sink, sourceId, reason);
mCategoryController.showToast(
String.format(
Locale.US,
"Failed to remove source %d for sink %s",
sourceId,
sink.getAddress()));
}
@Override
public void onSourceRemoved(BluetoothDevice sink, int sourceId, int reason) {
super.onSourceRemoved(sink, sourceId, reason);
mCategoryController.showToast(
String.format(
Locale.US, "Source %d removed for sink %s", sourceId, sink.getAddress()));
}
}

View File

@@ -74,6 +74,9 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
}
};
private final AudioStreamsRepository mAudioStreamsRepository =
AudioStreamsRepository.getInstance();
enum AudioStreamState {
// When mTimedSourceFromQrCode is present and this source has not been synced.
WAIT_FOR_SYNC,
@@ -86,7 +89,7 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
}
private final Executor mExecutor;
private final AudioStreamsBroadcastAssistantCallback mBroadcastAssistantCallback;
private final AudioStreamsProgressCategoryCallback mBroadcastAssistantCallback;
private final AudioStreamsHelper mAudioStreamsHelper;
private final @Nullable LocalBluetoothLeBroadcastAssistant mLeBroadcastAssistant;
private final @Nullable LocalBluetoothManager mBluetoothManager;
@@ -102,7 +105,7 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
mBluetoothManager = Utils.getLocalBtManager(mContext);
mAudioStreamsHelper = new AudioStreamsHelper(mBluetoothManager);
mLeBroadcastAssistant = mAudioStreamsHelper.getLeBroadcastAssistant();
mBroadcastAssistantCallback = new AudioStreamsBroadcastAssistantCallback(this);
mBroadcastAssistantCallback = new AudioStreamsProgressCategoryCallback(this);
}
@Override
@@ -170,6 +173,7 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
source, (AudioStreamPreference) preference));
} else {
mAudioStreamsHelper.addSource(source);
mAudioStreamsRepository.cacheMetadata(source);
((AudioStreamPreference) preference)
.setAudioStreamState(AudioStreamState.WAIT_FOR_SOURCE_ADD);
updatePreferenceConnectionState(
@@ -202,6 +206,7 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
return v;
}
mAudioStreamsHelper.addSource(pendingSource);
mAudioStreamsRepository.cacheMetadata(pendingSource);
mTimedSourceFromQrCode.consumed();
v.setAudioStreamState(AudioStreamState.WAIT_FOR_SOURCE_ADD);
updatePreferenceConnectionState(
@@ -236,6 +241,7 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
var fromState = v.getAudioStreamState();
if (fromState == AudioStreamState.SYNCED) {
mAudioStreamsHelper.addSource(metadataFromQrCode);
mAudioStreamsRepository.cacheMetadata(metadataFromQrCode);
mTimedSourceFromQrCode.consumed();
v.setAudioStreamState(AudioStreamState.WAIT_FOR_SOURCE_ADD);
updatePreferenceConnectionState(
@@ -302,6 +308,16 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
v, sourceAddedState, p -> launchDetailFragment(broadcastIdConnected));
return v;
});
// Saved connected metadata for user to re-join this broadcast later.
var unused =
ThreadUtils.postOnBackgroundThread(
() -> {
var cached =
mAudioStreamsRepository.getCachedMetadata(broadcastIdConnected);
if (cached != null) {
mAudioStreamsRepository.saveMetadata(mContext, cached);
}
});
}
private static String getPreferenceSummary(AudioStreamState state) {
@@ -457,11 +473,13 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
R.id.broadcast_edit_text))
.getText()
.toString();
mAudioStreamsHelper.addSource(
var metadata =
new BluetoothLeBroadcastMetadata.Builder(source)
.setBroadcastCode(
code.getBytes(StandardCharsets.UTF_8))
.build());
.build();
mAudioStreamsHelper.addSource(metadata);
mAudioStreamsRepository.cacheMetadata(metadata);
preference.setAudioStreamState(
AudioStreamState.WAIT_FOR_SOURCE_ADD);
updatePreferenceConnectionState(

View File

@@ -0,0 +1,160 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.connecteddevice.audiosharing.audiostreams;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import com.android.settingslib.bluetooth.BluetoothLeBroadcastMetadataExt;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.utils.ThreadUtils;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.Nullable;
/** Manages the caching and storage of Bluetooth audio stream metadata. */
public class AudioStreamsRepository {
private static final String TAG = "AudioStreamsRepository";
private static final boolean DEBUG = BluetoothUtils.D;
private static final String PREF_KEY = "bluetooth_audio_stream_pref";
private static final String METADATA_KEY = "bluetooth_audio_stream_metadata";
@Nullable
private static AudioStreamsRepository sInstance = null;
private AudioStreamsRepository() {}
/**
* Gets the single instance of AudioStreamsRepository.
*
* @return The AudioStreamsRepository instance.
*/
public static synchronized AudioStreamsRepository getInstance() {
if (sInstance == null) {
sInstance = new AudioStreamsRepository();
}
return sInstance;
}
private final ConcurrentHashMap<Integer, BluetoothLeBroadcastMetadata>
mBroadcastIdToMetadataCacheMap = new ConcurrentHashMap<>();
/**
* Caches BluetoothLeBroadcastMetadata in a local cache.
*
* @param metadata The BluetoothLeBroadcastMetadata to be cached.
*/
void cacheMetadata(BluetoothLeBroadcastMetadata metadata) {
if (DEBUG) {
Log.d(
TAG,
"cacheMetadata(): broadcastId "
+ metadata.getBroadcastId()
+ " saved in local cache.");
}
mBroadcastIdToMetadataCacheMap.put(metadata.getBroadcastId(), metadata);
}
/**
* Gets cached BluetoothLeBroadcastMetadata by broadcastId.
*
* @param broadcastId The broadcastId to look up in the cache.
* @return The cached BluetoothLeBroadcastMetadata or null if not found.
*/
@Nullable
BluetoothLeBroadcastMetadata getCachedMetadata(int broadcastId) {
var metadata = mBroadcastIdToMetadataCacheMap.get(broadcastId);
if (metadata == null) {
Log.w(
TAG,
"getCachedMetadata(): broadcastId not found in"
+ " mBroadcastIdToMetadataCacheMap.");
return null;
}
return metadata;
}
/**
* Saves metadata to SharedPreferences asynchronously.
*
* @param context The context.
* @param metadata The BluetoothLeBroadcastMetadata to be saved.
*/
void saveMetadata(Context context, BluetoothLeBroadcastMetadata metadata) {
var unused =
ThreadUtils.postOnBackgroundThread(
() -> {
SharedPreferences sharedPref =
context.getSharedPreferences(PREF_KEY, Context.MODE_PRIVATE);
if (sharedPref != null) {
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString(
METADATA_KEY,
BluetoothLeBroadcastMetadataExt.INSTANCE.toQrCodeString(
metadata));
editor.apply();
if (DEBUG) {
Log.d(
TAG,
"saveMetadata(): broadcastId "
+ metadata.getBroadcastId()
+ " metadata saved in storage.");
}
}
});
}
/**
* Gets saved metadata from SharedPreferences.
*
* @param context The context.
* @param broadcastId The broadcastId to retrieve metadata for.
* @return The saved BluetoothLeBroadcastMetadata or null if not found.
*/
@Nullable
BluetoothLeBroadcastMetadata getSavedMetadata(Context context, int broadcastId) {
SharedPreferences sharedPref = context.getSharedPreferences(PREF_KEY, Context.MODE_PRIVATE);
if (sharedPref != null) {
String savedMetadataStr = sharedPref.getString(METADATA_KEY, null);
if (savedMetadataStr == null) {
Log.w(TAG, "getSavedMetadata(): savedMetadataStr is null");
return null;
}
var savedMetadata =
BluetoothLeBroadcastMetadataExt.INSTANCE.convertToBroadcastMetadata(
savedMetadataStr);
if (savedMetadata == null || savedMetadata.getBroadcastId() != broadcastId) {
Log.w(TAG, "getSavedMetadata(): savedMetadata doesn't match broadcast Id.");
return null;
}
if (DEBUG) {
Log.d(
TAG,
"getSavedMetadata(): broadcastId "
+ savedMetadata.getBroadcastId()
+ " metadata found in storage.");
}
return savedMetadata;
}
return null;
}
}

View File

@@ -16,7 +16,6 @@
package com.android.settings.connecteddevice.audiosharing.audiostreams;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
@@ -124,10 +123,6 @@ public class AudioStreamsScanQrCodeController extends BasePreferenceController
});
}
void addSource(BluetoothLeBroadcastMetadata source) {
mAudioStreamsHelper.addSource(source);
}
private void updateVisibility() {
ThreadUtils.postOnBackgroundThread(
() -> {