[Audiosharing] Set visibility by active device.
Also created header and button controller for detail page. Bug: 305620450 Test: manual Change-Id: I5e468a0fb9ce49ef0fd9a0b00b51084cfd416ce0
This commit is contained in:
@@ -25,10 +25,12 @@
|
|||||||
android:layout="@layout/settings_entity_header"
|
android:layout="@layout/settings_entity_header"
|
||||||
android:selectable="false"
|
android:selectable="false"
|
||||||
settings:allowDividerBelow="true"
|
settings:allowDividerBelow="true"
|
||||||
settings:searchable="false" />
|
settings:searchable="false"
|
||||||
|
settings:controller="com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamHeaderController" />
|
||||||
|
|
||||||
<com.android.settingslib.widget.ActionButtonsPreference
|
<com.android.settingslib.widget.ActionButtonsPreference
|
||||||
android:key="audio_stream_button"
|
android:key="audio_stream_button"
|
||||||
settings:allowDividerBelow="true" />
|
settings:allowDividerBelow="true"
|
||||||
|
settings:controller="com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamButtonController" />
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
@@ -41,6 +41,8 @@ import java.util.Map;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class AudioSharingUtils {
|
public class AudioSharingUtils {
|
||||||
private static final String TAG = "AudioSharingUtils";
|
private static final String TAG = "AudioSharingUtils";
|
||||||
private static final boolean DEBUG = BluetoothUtils.D;
|
private static final boolean DEBUG = BluetoothUtils.D;
|
||||||
@@ -237,7 +239,7 @@ public class AudioSharingUtils {
|
|||||||
* @return An Optional containing the active LE Audio device, or an empty Optional if not found.
|
* @return An Optional containing the active LE Audio device, or an empty Optional if not found.
|
||||||
*/
|
*/
|
||||||
public static Optional<CachedBluetoothDevice> getActiveSinkOnAssistant(
|
public static Optional<CachedBluetoothDevice> getActiveSinkOnAssistant(
|
||||||
LocalBluetoothManager manager) {
|
@Nullable LocalBluetoothManager manager) {
|
||||||
if (manager == null) {
|
if (manager == null) {
|
||||||
Log.w(TAG, "getActiveSinksOnAssistant(): LocalBluetoothManager is null!");
|
Log.w(TAG, "getActiveSinksOnAssistant(): LocalBluetoothManager is null!");
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
|
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 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.content.Context;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.lifecycle.DefaultLifecycleObserver;
|
||||||
|
import androidx.preference.PreferenceScreen;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.core.BasePreferenceController;
|
||||||
|
import com.android.settingslib.widget.ActionButtonsPreference;
|
||||||
|
|
||||||
|
public class AudioStreamButtonController extends BasePreferenceController
|
||||||
|
implements DefaultLifecycleObserver {
|
||||||
|
private static final String KEY = "audio_stream_button";
|
||||||
|
private @Nullable ActionButtonsPreference mPreference;
|
||||||
|
private int mBroadcastId = -1;
|
||||||
|
|
||||||
|
public AudioStreamButtonController(Context context, String preferenceKey) {
|
||||||
|
super(context, preferenceKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
super.displayPreference(screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAvailabilityStatus() {
|
||||||
|
return AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPreferenceKey() {
|
||||||
|
return KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Initialize with broadcast id */
|
||||||
|
void init(int broadcastId) {
|
||||||
|
mBroadcastId = broadcastId;
|
||||||
|
}
|
||||||
|
}
|
@@ -17,16 +17,28 @@
|
|||||||
package com.android.settings.connecteddevice.audiosharing.audiostreams;
|
package com.android.settings.connecteddevice.audiosharing.audiostreams;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.dashboard.DashboardFragment;
|
import com.android.settings.dashboard.DashboardFragment;
|
||||||
|
|
||||||
public class AudioStreamDetailsFragment extends DashboardFragment {
|
public class AudioStreamDetailsFragment extends DashboardFragment {
|
||||||
|
static final String BROADCAST_NAME_ARG = "broadcast_name";
|
||||||
|
static final String BROADCAST_ID_ARG = "broadcast_id";
|
||||||
private static final String TAG = "AudioStreamDetailsFragment";
|
private static final String TAG = "AudioStreamDetailsFragment";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAttach(Context context) {
|
public void onAttach(Context context) {
|
||||||
super.onAttach(context);
|
super.onAttach(context);
|
||||||
|
Bundle arguments = getArguments();
|
||||||
|
if (arguments != null) {
|
||||||
|
use(AudioStreamHeaderController.class)
|
||||||
|
.init(
|
||||||
|
this,
|
||||||
|
arguments.getString(BROADCAST_NAME_ARG),
|
||||||
|
arguments.getInt(BROADCAST_ID_ARG));
|
||||||
|
use(AudioStreamButtonController.class).init(arguments.getInt(BROADCAST_ID_ARG));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 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.content.Context;
|
||||||
|
|
||||||
|
import androidx.lifecycle.DefaultLifecycleObserver;
|
||||||
|
import androidx.preference.PreferenceScreen;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.core.BasePreferenceController;
|
||||||
|
import com.android.settings.dashboard.DashboardFragment;
|
||||||
|
import com.android.settings.widget.EntityHeaderController;
|
||||||
|
import com.android.settingslib.widget.LayoutPreference;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public class AudioStreamHeaderController extends BasePreferenceController
|
||||||
|
implements DefaultLifecycleObserver {
|
||||||
|
private static final String KEY = "audio_stream_header";
|
||||||
|
private @Nullable EntityHeaderController mHeaderController;
|
||||||
|
private @Nullable DashboardFragment mFragment;
|
||||||
|
private String mBroadcastName = "";
|
||||||
|
private int mBroadcastId = -1;
|
||||||
|
|
||||||
|
public AudioStreamHeaderController(Context context, String preferenceKey) {
|
||||||
|
super(context, preferenceKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void displayPreference(PreferenceScreen screen) {
|
||||||
|
LayoutPreference headerPreference = screen.findPreference(KEY);
|
||||||
|
if (headerPreference != null && mFragment != null) {
|
||||||
|
mHeaderController =
|
||||||
|
EntityHeaderController.newInstance(
|
||||||
|
mFragment.getActivity(),
|
||||||
|
mFragment,
|
||||||
|
headerPreference.findViewById(R.id.entity_header));
|
||||||
|
if (mBroadcastName != null) {
|
||||||
|
mHeaderController.setLabel(mBroadcastName);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
super.displayPreference(screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAvailabilityStatus() {
|
||||||
|
return AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPreferenceKey() {
|
||||||
|
return KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Initialize with {@link AudioStreamDetailsFragment} and broadcast name and id */
|
||||||
|
void init(
|
||||||
|
AudioStreamDetailsFragment audioStreamDetailsFragment,
|
||||||
|
String broadcastName,
|
||||||
|
int broadcastId) {
|
||||||
|
mFragment = audioStreamDetailsFragment;
|
||||||
|
mBroadcastName = broadcastName;
|
||||||
|
mBroadcastId = broadcastId;
|
||||||
|
}
|
||||||
|
}
|
@@ -80,8 +80,8 @@ class AudioStreamsHelper {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Removes all sources from LE broadcasts associated for all active sinks. */
|
/** Removes sources from LE broadcasts associated for all active sinks based on broadcast Id. */
|
||||||
void removeSource() {
|
void removeSource(int broadcastId) {
|
||||||
if (mLeBroadcastAssistant == null) {
|
if (mLeBroadcastAssistant == null) {
|
||||||
Log.w(TAG, "removeSource(): LeBroadcastAssistant is null!");
|
Log.w(TAG, "removeSource(): LeBroadcastAssistant is null!");
|
||||||
return;
|
return;
|
||||||
@@ -93,14 +93,17 @@ class AudioStreamsHelper {
|
|||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(
|
Log.d(
|
||||||
TAG,
|
TAG,
|
||||||
"removeSource(): remove all sources from sink : "
|
"removeSource(): remove all sources with broadcast id :"
|
||||||
|
+ broadcastId
|
||||||
|
+ " from sink : "
|
||||||
+ sink.getAddress());
|
+ sink.getAddress());
|
||||||
}
|
}
|
||||||
var sources = mLeBroadcastAssistant.getAllSources(sink);
|
mLeBroadcastAssistant.getAllSources(sink).stream()
|
||||||
if (!sources.isEmpty()) {
|
.filter(state -> state.getBroadcastId() == broadcastId)
|
||||||
mLeBroadcastAssistant.removeSource(
|
.forEach(
|
||||||
sink, sources.get(0).getSourceId());
|
state ->
|
||||||
}
|
mLeBroadcastAssistant.removeSource(
|
||||||
|
sink, state.getSourceId()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -121,6 +124,12 @@ class AudioStreamsHelper {
|
|||||||
return mLeBroadcastAssistant;
|
return mLeBroadcastAssistant;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static boolean isConnected(BluetoothLeBroadcastReceiveState state) {
|
||||||
|
return state.getPaSyncState() == BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED
|
||||||
|
&& state.getBigEncryptionState()
|
||||||
|
== BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_DECRYPTING;
|
||||||
|
}
|
||||||
|
|
||||||
private static List<BluetoothDevice> getActiveSinksOnAssistant(
|
private static List<BluetoothDevice> getActiveSinksOnAssistant(
|
||||||
@Nullable LocalBluetoothManager manager) {
|
@Nullable LocalBluetoothManager manager) {
|
||||||
if (manager == null) {
|
if (manager == null) {
|
||||||
|
@@ -22,9 +22,9 @@ import android.app.AlertDialog;
|
|||||||
import android.app.settings.SettingsEnums;
|
import android.app.settings.SettingsEnums;
|
||||||
import android.bluetooth.BluetoothLeBroadcastMetadata;
|
import android.bluetooth.BluetoothLeBroadcastMetadata;
|
||||||
import android.bluetooth.BluetoothLeBroadcastReceiveState;
|
import android.bluetooth.BluetoothLeBroadcastReceiveState;
|
||||||
|
import android.bluetooth.BluetoothProfile;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.provider.Settings;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -42,8 +42,11 @@ import com.android.settings.bluetooth.Utils;
|
|||||||
import com.android.settings.connecteddevice.audiosharing.AudioSharingUtils;
|
import com.android.settings.connecteddevice.audiosharing.AudioSharingUtils;
|
||||||
import com.android.settings.core.BasePreferenceController;
|
import com.android.settings.core.BasePreferenceController;
|
||||||
import com.android.settings.core.SubSettingLauncher;
|
import com.android.settings.core.SubSettingLauncher;
|
||||||
|
import com.android.settingslib.bluetooth.BluetoothCallback;
|
||||||
import com.android.settingslib.bluetooth.BluetoothUtils;
|
import com.android.settingslib.bluetooth.BluetoothUtils;
|
||||||
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
||||||
|
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||||
import com.android.settingslib.utils.ThreadUtils;
|
import com.android.settingslib.utils.ThreadUtils;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
@@ -57,11 +60,22 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
|
|||||||
implements DefaultLifecycleObserver {
|
implements DefaultLifecycleObserver {
|
||||||
private static final String TAG = "AudioStreamsProgressCategoryController";
|
private static final String TAG = "AudioStreamsProgressCategoryController";
|
||||||
private static final boolean DEBUG = BluetoothUtils.D;
|
private static final boolean DEBUG = BluetoothUtils.D;
|
||||||
|
private final BluetoothCallback mBluetoothCallback =
|
||||||
|
new BluetoothCallback() {
|
||||||
|
@Override
|
||||||
|
public void onActiveDeviceChanged(
|
||||||
|
@Nullable CachedBluetoothDevice activeDevice, int bluetoothProfile) {
|
||||||
|
if (bluetoothProfile == BluetoothProfile.LE_AUDIO) {
|
||||||
|
mExecutor.execute(() -> init(activeDevice != null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private final Executor mExecutor;
|
private final Executor mExecutor;
|
||||||
private final AudioStreamsBroadcastAssistantCallback mBroadcastAssistantCallback;
|
private final AudioStreamsBroadcastAssistantCallback mBroadcastAssistantCallback;
|
||||||
private final AudioStreamsHelper mAudioStreamsHelper;
|
private final AudioStreamsHelper mAudioStreamsHelper;
|
||||||
private final @Nullable LocalBluetoothLeBroadcastAssistant mLeBroadcastAssistant;
|
private final @Nullable LocalBluetoothLeBroadcastAssistant mLeBroadcastAssistant;
|
||||||
|
private final @Nullable LocalBluetoothManager mBluetoothManager;
|
||||||
private final ConcurrentHashMap<Integer, AudioStreamPreference> mBroadcastIdToPreferenceMap =
|
private final ConcurrentHashMap<Integer, AudioStreamPreference> mBroadcastIdToPreferenceMap =
|
||||||
new ConcurrentHashMap<>();
|
new ConcurrentHashMap<>();
|
||||||
private AudioStreamsProgressCategoryPreference mCategoryPreference;
|
private AudioStreamsProgressCategoryPreference mCategoryPreference;
|
||||||
@@ -69,7 +83,8 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
|
|||||||
public AudioStreamsProgressCategoryController(Context context, String preferenceKey) {
|
public AudioStreamsProgressCategoryController(Context context, String preferenceKey) {
|
||||||
super(context, preferenceKey);
|
super(context, preferenceKey);
|
||||||
mExecutor = Executors.newSingleThreadExecutor();
|
mExecutor = Executors.newSingleThreadExecutor();
|
||||||
mAudioStreamsHelper = new AudioStreamsHelper(Utils.getLocalBtManager(mContext));
|
mBluetoothManager = Utils.getLocalBtManager(mContext);
|
||||||
|
mAudioStreamsHelper = new AudioStreamsHelper(mBluetoothManager);
|
||||||
mLeBroadcastAssistant = mAudioStreamsHelper.getLeBroadcastAssistant();
|
mLeBroadcastAssistant = mAudioStreamsHelper.getLeBroadcastAssistant();
|
||||||
mBroadcastAssistantCallback = new AudioStreamsBroadcastAssistantCallback(this);
|
mBroadcastAssistantCallback = new AudioStreamsBroadcastAssistantCallback(this);
|
||||||
}
|
}
|
||||||
@@ -87,48 +102,24 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStart(@NonNull LifecycleOwner owner) {
|
public void onStart(@NonNull LifecycleOwner owner) {
|
||||||
if (mLeBroadcastAssistant == null) {
|
if (mBluetoothManager != null) {
|
||||||
Log.w(TAG, "onStart(): LeBroadcastAssistant is null!");
|
mBluetoothManager.getEventManager().registerCallback(mBluetoothCallback);
|
||||||
return;
|
|
||||||
}
|
|
||||||
mBroadcastIdToPreferenceMap.clear();
|
|
||||||
if (mCategoryPreference != null) {
|
|
||||||
mCategoryPreference.removeAll();
|
|
||||||
}
|
}
|
||||||
mExecutor.execute(
|
mExecutor.execute(
|
||||||
() -> {
|
() -> {
|
||||||
mLeBroadcastAssistant.registerServiceCallBack(
|
boolean hasActive =
|
||||||
mExecutor, mBroadcastAssistantCallback);
|
AudioSharingUtils.getActiveSinkOnAssistant(mBluetoothManager)
|
||||||
if (DEBUG) {
|
.isPresent();
|
||||||
Log.d(TAG, "scanAudioStreamsStart()");
|
init(hasActive);
|
||||||
}
|
|
||||||
mLeBroadcastAssistant.startSearchingForSources(emptyList());
|
|
||||||
// Display currently connected streams
|
|
||||||
var unused =
|
|
||||||
ThreadUtils.postOnBackgroundThread(
|
|
||||||
() ->
|
|
||||||
mAudioStreamsHelper
|
|
||||||
.getAllSources()
|
|
||||||
.forEach(this::handleSourceConnected));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStop(@NonNull LifecycleOwner owner) {
|
public void onStop(@NonNull LifecycleOwner owner) {
|
||||||
if (mLeBroadcastAssistant == null) {
|
if (mBluetoothManager != null) {
|
||||||
Log.w(TAG, "onStop(): LeBroadcastAssistant is null!");
|
mBluetoothManager.getEventManager().unregisterCallback(mBluetoothCallback);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
mExecutor.execute(
|
mExecutor.execute(this::stopScanning);
|
||||||
() -> {
|
|
||||||
if (mLeBroadcastAssistant.isSearchInProgress()) {
|
|
||||||
if (DEBUG) {
|
|
||||||
Log.d(TAG, "scanAudioStreamsStop()");
|
|
||||||
}
|
|
||||||
mLeBroadcastAssistant.stopSearchingForSources();
|
|
||||||
}
|
|
||||||
mLeBroadcastAssistant.unregisterServiceCallBack(mBroadcastAssistantCallback);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setScanning(boolean isScanning) {
|
void setScanning(boolean isScanning) {
|
||||||
@@ -142,7 +133,10 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
|
|||||||
Preference.OnPreferenceClickListener addSourceOrShowDialog =
|
Preference.OnPreferenceClickListener addSourceOrShowDialog =
|
||||||
preference -> {
|
preference -> {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "preferenceClicked(): attempt to join broadcast");
|
Log.d(
|
||||||
|
TAG,
|
||||||
|
"preferenceClicked(): attempt to join broadcast id : "
|
||||||
|
+ source.getBroadcastId());
|
||||||
}
|
}
|
||||||
if (source.isEncrypted()) {
|
if (source.isEncrypted()) {
|
||||||
ThreadUtils.postOnMainThread(
|
ThreadUtils.postOnMainThread(
|
||||||
@@ -177,11 +171,13 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
mAudioStreamsHelper.removeSource();
|
mAudioStreamsHelper.removeSource(broadcastId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleSourceConnected(BluetoothLeBroadcastReceiveState state) {
|
void handleSourceConnected(BluetoothLeBroadcastReceiveState state) {
|
||||||
// TODO(chelseahao): only continue when the state indicates a successful connection
|
if (!AudioStreamsHelper.isConnected(state)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
mBroadcastIdToPreferenceMap.compute(
|
mBroadcastIdToPreferenceMap.compute(
|
||||||
state.getBroadcastId(),
|
state.getBroadcastId(),
|
||||||
(k, v) -> {
|
(k, v) -> {
|
||||||
@@ -194,7 +190,7 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
|
|||||||
ThreadUtils.postOnMainThread(
|
ThreadUtils.postOnMainThread(
|
||||||
() -> {
|
() -> {
|
||||||
preference.setIsConnected(
|
preference.setIsConnected(
|
||||||
true, p -> launchDetailFragment((AudioStreamPreference) p));
|
true, p -> launchDetailFragment(state.getBroadcastId()));
|
||||||
if (mCategoryPreference != null && !existed) {
|
if (mCategoryPreference != null && !existed) {
|
||||||
mCategoryPreference.addPreference(preference);
|
mCategoryPreference.addPreference(preference);
|
||||||
}
|
}
|
||||||
@@ -208,11 +204,73 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
|
|||||||
AudioSharingUtils.toastMessage(mContext, msg);
|
AudioSharingUtils.toastMessage(mContext, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean launchDetailFragment(AudioStreamPreference preference) {
|
private void init(boolean hasActive) {
|
||||||
|
mBroadcastIdToPreferenceMap.clear();
|
||||||
|
ThreadUtils.postOnMainThread(
|
||||||
|
() -> {
|
||||||
|
if (mCategoryPreference != null) {
|
||||||
|
mCategoryPreference.removeAll();
|
||||||
|
mCategoryPreference.setVisible(hasActive);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (hasActive) {
|
||||||
|
startScanning();
|
||||||
|
} else {
|
||||||
|
stopScanning();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startScanning() {
|
||||||
|
if (mLeBroadcastAssistant == null) {
|
||||||
|
Log.w(TAG, "startScanning(): LeBroadcastAssistant is null!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mLeBroadcastAssistant.isSearchInProgress()) {
|
||||||
|
showToast("Failed to start scanning, please try again.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "startScanning()");
|
||||||
|
}
|
||||||
|
mLeBroadcastAssistant.registerServiceCallBack(mExecutor, mBroadcastAssistantCallback);
|
||||||
|
mLeBroadcastAssistant.startSearchingForSources(emptyList());
|
||||||
|
|
||||||
|
// Display currently connected streams
|
||||||
|
var unused =
|
||||||
|
ThreadUtils.postOnBackgroundThread(
|
||||||
|
() ->
|
||||||
|
mAudioStreamsHelper
|
||||||
|
.getAllSources()
|
||||||
|
.forEach(this::handleSourceConnected));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopScanning() {
|
||||||
|
if (mLeBroadcastAssistant == null) {
|
||||||
|
Log.w(TAG, "stopScanning(): LeBroadcastAssistant is null!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mLeBroadcastAssistant.isSearchInProgress()) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "stopScanning()");
|
||||||
|
}
|
||||||
|
mLeBroadcastAssistant.stopSearchingForSources();
|
||||||
|
}
|
||||||
|
mLeBroadcastAssistant.unregisterServiceCallBack(mBroadcastAssistantCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean launchDetailFragment(int broadcastId) {
|
||||||
|
if (!mBroadcastIdToPreferenceMap.containsKey(broadcastId)) {
|
||||||
|
Log.w(
|
||||||
|
TAG,
|
||||||
|
"launchDetailFragment(): broadcastId not exist in BroadcastIdToPreferenceMap!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
AudioStreamPreference preference = mBroadcastIdToPreferenceMap.get(broadcastId);
|
||||||
|
|
||||||
Bundle broadcast = new Bundle();
|
Bundle broadcast = new Bundle();
|
||||||
broadcast.putString(
|
broadcast.putString(
|
||||||
Settings.Secure.BLUETOOTH_LE_BROADCAST_PROGRAM_INFO,
|
AudioStreamDetailsFragment.BROADCAST_NAME_ARG, (String) preference.getTitle());
|
||||||
(String) preference.getTitle());
|
broadcast.putInt(AudioStreamDetailsFragment.BROADCAST_ID_ARG, broadcastId);
|
||||||
|
|
||||||
new SubSettingLauncher(mContext)
|
new SubSettingLauncher(mContext)
|
||||||
.setTitleText("Audio stream details")
|
.setTitleText("Audio stream details")
|
||||||
@@ -240,8 +298,8 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
|
|||||||
(dialog, which) -> {
|
(dialog, which) -> {
|
||||||
var code =
|
var code =
|
||||||
((EditText)
|
((EditText)
|
||||||
layout.requireViewById(
|
layout.requireViewById(
|
||||||
R.id.broadcast_edit_text))
|
R.id.broadcast_edit_text))
|
||||||
.getText()
|
.getText()
|
||||||
.toString();
|
.toString();
|
||||||
mAudioStreamsHelper.addSource(
|
mAudioStreamsHelper.addSource(
|
||||||
|
Reference in New Issue
Block a user