In hysteresis mode, we will receive plenty of onReceiveStateChanged, e.g. play and pause music, system sounds... The onReceiveStateChanged with BIS >= 1, as a replacement of onSourceAdded, will trigger auto pick logic for primary headset. In some cases, when user change primary headset in Call audio section on audio sharing page under the hysteresis mode, the system sound will later trigger a onReceiveStateChanged with BIS >= 1, then the auto pick logic (always pick the earliest connected headset) is possible to override the user change. Thus here we have to save the user preferred primary headset in SettingsProvider and skip the auto pick if user has made changes. Test: atest Bug: 355222285 Flag: com.android.settingslib.flags.audio_sharing_hysteresis_mode_fix Change-Id: I5ccf743eb685509ffcc3c7a88051726c10fe2567
550 lines
23 KiB
Java
550 lines
23 KiB
Java
/*
|
|
* 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;
|
|
|
|
import static com.android.settingslib.Utils.isAudioModeOngoingCall;
|
|
import static com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast.EXTRA_BLUETOOTH_DEVICE;
|
|
|
|
import android.app.settings.SettingsEnums;
|
|
import android.bluetooth.BluetoothAdapter;
|
|
import android.bluetooth.BluetoothDevice;
|
|
import android.bluetooth.BluetoothLeBroadcastAssistant;
|
|
import android.bluetooth.BluetoothLeBroadcastMetadata;
|
|
import android.bluetooth.BluetoothLeBroadcastReceiveState;
|
|
import android.bluetooth.BluetoothProfile;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.os.Bundle;
|
|
import android.util.Log;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.annotation.VisibleForTesting;
|
|
import androidx.lifecycle.DefaultLifecycleObserver;
|
|
import androidx.lifecycle.LifecycleOwner;
|
|
import androidx.preference.Preference;
|
|
import androidx.preference.PreferenceGroup;
|
|
import androidx.preference.PreferenceScreen;
|
|
|
|
import com.android.settings.R;
|
|
import com.android.settings.SettingsActivity;
|
|
import com.android.settings.bluetooth.BluetoothDevicePreference;
|
|
import com.android.settings.bluetooth.BluetoothDeviceUpdater;
|
|
import com.android.settings.bluetooth.Utils;
|
|
import com.android.settings.connecteddevice.DevicePreferenceCallback;
|
|
import com.android.settings.core.BasePreferenceController;
|
|
import com.android.settings.dashboard.DashboardFragment;
|
|
import com.android.settings.overlay.FeatureFactory;
|
|
import com.android.settingslib.bluetooth.A2dpProfile;
|
|
import com.android.settingslib.bluetooth.BluetoothCallback;
|
|
import com.android.settingslib.bluetooth.BluetoothEventManager;
|
|
import com.android.settingslib.bluetooth.BluetoothUtils;
|
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
|
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
|
import com.android.settingslib.bluetooth.HeadsetProfile;
|
|
import com.android.settingslib.bluetooth.HearingAidProfile;
|
|
import com.android.settingslib.bluetooth.LeAudioProfile;
|
|
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
|
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
|
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
|
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
|
import com.android.settingslib.utils.ThreadUtils;
|
|
|
|
import java.util.Locale;
|
|
import java.util.concurrent.Executor;
|
|
import java.util.concurrent.Executors;
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
|
public class AudioSharingDevicePreferenceController extends BasePreferenceController
|
|
implements DefaultLifecycleObserver,
|
|
DevicePreferenceCallback,
|
|
BluetoothCallback,
|
|
LocalBluetoothProfileManager.ServiceListener {
|
|
private static final boolean DEBUG = BluetoothUtils.D;
|
|
|
|
private static final String TAG = "AudioSharingDevicePrefController";
|
|
private static final String KEY = "audio_sharing_device_list";
|
|
private static final String KEY_AUDIO_SHARING_SETTINGS =
|
|
"connected_device_audio_sharing_settings";
|
|
|
|
@Nullable private final LocalBluetoothManager mBtManager;
|
|
@Nullable private final CachedBluetoothDeviceManager mDeviceManager;
|
|
@Nullable private final BluetoothEventManager mEventManager;
|
|
@Nullable private final LocalBluetoothProfileManager mProfileManager;
|
|
@Nullable private final LocalBluetoothLeBroadcastAssistant mAssistant;
|
|
private final Executor mExecutor;
|
|
private final MetricsFeatureProvider mMetricsFeatureProvider;
|
|
@Nullable private PreferenceGroup mPreferenceGroup;
|
|
@Nullable private Preference mAudioSharingSettingsPreference;
|
|
@Nullable private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
|
|
@Nullable private DashboardFragment mFragment;
|
|
@Nullable private AudioSharingDialogHandler mDialogHandler;
|
|
private AtomicBoolean mIntentHandled = new AtomicBoolean(false);
|
|
private AtomicBoolean mIsAudioModeOngoingCall = new AtomicBoolean(false);
|
|
|
|
@VisibleForTesting
|
|
BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
|
|
new BluetoothLeBroadcastAssistant.Callback() {
|
|
@Override
|
|
public void onSearchStarted(int reason) {}
|
|
|
|
@Override
|
|
public void onSearchStartFailed(int reason) {}
|
|
|
|
@Override
|
|
public void onSearchStopped(int reason) {}
|
|
|
|
@Override
|
|
public void onSearchStopFailed(int reason) {}
|
|
|
|
@Override
|
|
public void onSourceFound(@NonNull BluetoothLeBroadcastMetadata source) {}
|
|
|
|
@Override
|
|
public void onSourceAdded(
|
|
@NonNull BluetoothDevice sink, int sourceId, int reason) {}
|
|
|
|
@Override
|
|
public void onSourceAddFailed(
|
|
@NonNull BluetoothDevice sink,
|
|
@NonNull BluetoothLeBroadcastMetadata source,
|
|
int reason) {
|
|
mMetricsFeatureProvider.action(
|
|
mContext,
|
|
SettingsEnums.ACTION_AUDIO_SHARING_JOIN_FAILED,
|
|
SettingsEnums.SETTINGS_CONNECTED_DEVICE_CATEGORY);
|
|
AudioSharingUtils.toastMessage(
|
|
mContext,
|
|
String.format(
|
|
Locale.US,
|
|
"Fail to add source to %s reason %d",
|
|
sink.getAddress(),
|
|
reason));
|
|
}
|
|
|
|
@Override
|
|
public void onSourceModified(
|
|
@NonNull BluetoothDevice sink, int sourceId, int reason) {}
|
|
|
|
@Override
|
|
public void onSourceModifyFailed(
|
|
@NonNull BluetoothDevice sink, int sourceId, int reason) {}
|
|
|
|
@Override
|
|
public void onSourceRemoved(
|
|
@NonNull BluetoothDevice sink, int sourceId, int reason) {
|
|
Log.d(TAG, "onSourceRemoved: update sharing device list.");
|
|
if (mBluetoothDeviceUpdater != null) {
|
|
mBluetoothDeviceUpdater.forceUpdate();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onSourceRemoveFailed(
|
|
@NonNull BluetoothDevice sink, int sourceId, int reason) {
|
|
mMetricsFeatureProvider.action(
|
|
mContext,
|
|
SettingsEnums.ACTION_AUDIO_SHARING_LEAVE_FAILED,
|
|
SettingsEnums.SETTINGS_CONNECTED_DEVICE_CATEGORY);
|
|
AudioSharingUtils.toastMessage(
|
|
mContext,
|
|
String.format(
|
|
Locale.US,
|
|
"Fail to remove source from %s reason %d",
|
|
sink.getAddress(),
|
|
reason));
|
|
}
|
|
|
|
@Override
|
|
public void onReceiveStateChanged(
|
|
@NonNull BluetoothDevice sink,
|
|
int sourceId,
|
|
@NonNull BluetoothLeBroadcastReceiveState state) {
|
|
if (BluetoothUtils.isConnected(state)) {
|
|
Log.d(TAG, "onSourceAdded: update sharing device list.");
|
|
if (mBluetoothDeviceUpdater != null) {
|
|
mBluetoothDeviceUpdater.forceUpdate();
|
|
}
|
|
if (mDeviceManager != null && mDialogHandler != null) {
|
|
CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(sink);
|
|
if (cachedDevice != null) {
|
|
mDialogHandler.closeOpeningDialogsForLeaDevice(cachedDevice);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
public AudioSharingDevicePreferenceController(Context context) {
|
|
super(context, KEY);
|
|
mBtManager = Utils.getLocalBtManager(mContext);
|
|
mEventManager = mBtManager == null ? null : mBtManager.getEventManager();
|
|
mDeviceManager = mBtManager == null ? null : mBtManager.getCachedDeviceManager();
|
|
mProfileManager = mBtManager == null ? null : mBtManager.getProfileManager();
|
|
mAssistant =
|
|
mProfileManager == null
|
|
? null
|
|
: mProfileManager.getLeAudioBroadcastAssistantProfile();
|
|
mExecutor = Executors.newSingleThreadExecutor();
|
|
mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
|
|
}
|
|
|
|
@Override
|
|
public void onStart(@NonNull LifecycleOwner owner) {
|
|
var unused = ThreadUtils.postOnBackgroundThread(() -> {
|
|
if (!isAvailable()) {
|
|
Log.d(TAG, "Skip onStart(), feature is not supported.");
|
|
return;
|
|
}
|
|
if (!AudioSharingUtils.isAudioSharingProfileReady(mProfileManager)
|
|
&& mProfileManager != null) {
|
|
Log.d(TAG, "Register profile service listener");
|
|
mProfileManager.addServiceListener(this);
|
|
}
|
|
if (mEventManager == null
|
|
|| mAssistant == null
|
|
|| mDialogHandler == null
|
|
|| mBluetoothDeviceUpdater == null) {
|
|
Log.d(TAG, "Skip onStart(), profile is not ready.");
|
|
return;
|
|
}
|
|
Log.d(TAG, "onStart() Register callbacks.");
|
|
mEventManager.registerCallback(this);
|
|
mAssistant.registerServiceCallBack(mExecutor, mBroadcastAssistantCallback);
|
|
mDialogHandler.registerCallbacks(mExecutor);
|
|
mBluetoothDeviceUpdater.registerCallback();
|
|
mBluetoothDeviceUpdater.refreshPreference();
|
|
mIsAudioModeOngoingCall.set(isAudioModeOngoingCall(mContext));
|
|
updateTitle();
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void onStop(@NonNull LifecycleOwner owner) {
|
|
var unused = ThreadUtils.postOnBackgroundThread(() -> {
|
|
if (!isAvailable()) {
|
|
Log.d(TAG, "Skip onStop(), feature is not supported.");
|
|
return;
|
|
}
|
|
if (mProfileManager != null) {
|
|
mProfileManager.removeServiceListener(this);
|
|
}
|
|
if (mEventManager == null
|
|
|| mAssistant == null
|
|
|| mDialogHandler == null
|
|
|| mBluetoothDeviceUpdater == null) {
|
|
Log.d(TAG, "Skip onStop(), profile is not ready.");
|
|
return;
|
|
}
|
|
Log.d(TAG, "onStop() Unregister callbacks.");
|
|
mEventManager.unregisterCallback(this);
|
|
mAssistant.unregisterServiceCallBack(mBroadcastAssistantCallback);
|
|
mDialogHandler.unregisterCallbacks();
|
|
mBluetoothDeviceUpdater.unregisterCallback();
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void onServiceConnected() {
|
|
if (AudioSharingUtils.isAudioSharingProfileReady(mProfileManager)) {
|
|
if (mProfileManager != null) {
|
|
mProfileManager.removeServiceListener(this);
|
|
}
|
|
if (!mIntentHandled.get()) {
|
|
Log.d(TAG, "onServiceConnected: handleDeviceClickFromIntent");
|
|
handleDeviceClickFromIntent();
|
|
mIntentHandled.set(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onServiceDisconnected() {
|
|
// Do nothing
|
|
}
|
|
|
|
@Override
|
|
public void displayPreference(PreferenceScreen screen) {
|
|
super.displayPreference(screen);
|
|
mPreferenceGroup = screen.findPreference(KEY);
|
|
if (mPreferenceGroup != null) {
|
|
mAudioSharingSettingsPreference =
|
|
mPreferenceGroup.findPreference(KEY_AUDIO_SHARING_SETTINGS);
|
|
mPreferenceGroup.setVisible(false);
|
|
}
|
|
if (mAudioSharingSettingsPreference != null) {
|
|
mAudioSharingSettingsPreference.setVisible(false);
|
|
}
|
|
|
|
if (isAvailable()) {
|
|
if (mBluetoothDeviceUpdater != null) {
|
|
mBluetoothDeviceUpdater.setPrefContext(screen.getContext());
|
|
mBluetoothDeviceUpdater.forceUpdate();
|
|
}
|
|
if (AudioSharingUtils.isAudioSharingProfileReady(mProfileManager)) {
|
|
if (!mIntentHandled.get()) {
|
|
Log.d(TAG, "displayPreference: profile ready, handleDeviceClickFromIntent");
|
|
var unused =
|
|
ThreadUtils.postOnBackgroundThread(() -> handleDeviceClickFromIntent());
|
|
mIntentHandled.set(true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int getAvailabilityStatus() {
|
|
return BluetoothUtils.isAudioSharingEnabled() && mBluetoothDeviceUpdater != null
|
|
? AVAILABLE_UNSEARCHABLE
|
|
: UNSUPPORTED_ON_DEVICE;
|
|
}
|
|
|
|
@Override
|
|
public String getPreferenceKey() {
|
|
return KEY;
|
|
}
|
|
|
|
@Override
|
|
public void onDeviceAdded(Preference preference) {
|
|
if (mPreferenceGroup != null) {
|
|
if (mPreferenceGroup.getPreferenceCount() == 1) {
|
|
mPreferenceGroup.setVisible(true);
|
|
if (mAudioSharingSettingsPreference != null) {
|
|
mAudioSharingSettingsPreference.setVisible(true);
|
|
}
|
|
}
|
|
mPreferenceGroup.addPreference(preference);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onDeviceRemoved(Preference preference) {
|
|
if (mPreferenceGroup != null) {
|
|
mPreferenceGroup.removePreference(preference);
|
|
if (mPreferenceGroup.getPreferenceCount() == 1) {
|
|
mPreferenceGroup.setVisible(false);
|
|
if (mAudioSharingSettingsPreference != null) {
|
|
mAudioSharingSettingsPreference.setVisible(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onProfileConnectionStateChanged(
|
|
@NonNull CachedBluetoothDevice cachedDevice,
|
|
@ConnectionState int state,
|
|
int bluetoothProfile) {
|
|
if (mDialogHandler == null || mAssistant == null || mFragment == null) {
|
|
Log.d(TAG, "Ignore onProfileConnectionStateChanged, not init correctly");
|
|
return;
|
|
}
|
|
if (!isMediaDevice(cachedDevice)) {
|
|
Log.d(TAG, "Ignore onProfileConnectionStateChanged, not a media device");
|
|
return;
|
|
}
|
|
// Close related dialogs if the BT remote device is disconnected.
|
|
if (state == BluetoothAdapter.STATE_DISCONNECTED) {
|
|
boolean isLeAudioSupported = AudioSharingUtils.isLeAudioSupported(cachedDevice);
|
|
if (isLeAudioSupported
|
|
&& bluetoothProfile == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT) {
|
|
mDialogHandler.closeOpeningDialogsForLeaDevice(cachedDevice);
|
|
return;
|
|
}
|
|
if (!isLeAudioSupported && !cachedDevice.isConnected()) {
|
|
mDialogHandler.closeOpeningDialogsForNonLeaDevice(cachedDevice);
|
|
return;
|
|
}
|
|
}
|
|
if (state != BluetoothAdapter.STATE_CONNECTED || !cachedDevice.getDevice().isConnected()) {
|
|
Log.d(TAG, "Ignore onProfileConnectionStateChanged, not connected state");
|
|
return;
|
|
}
|
|
handleOnProfileStateChanged(cachedDevice, bluetoothProfile);
|
|
}
|
|
|
|
@Override
|
|
public void onAudioModeChanged() {
|
|
mIsAudioModeOngoingCall.set(isAudioModeOngoingCall(mContext));
|
|
updateTitle();
|
|
}
|
|
|
|
@Override
|
|
public void onDeviceClick(@NonNull Preference preference) {
|
|
boolean isCallMode = mIsAudioModeOngoingCall.get();
|
|
if (isCallMode) {
|
|
Log.d(TAG, "onDeviceClick, set active in call mode");
|
|
CachedBluetoothDevice cachedDevice =
|
|
((BluetoothDevicePreference) preference).getBluetoothDevice();
|
|
AudioSharingUtils.setPrimary(mContext, cachedDevice);
|
|
}
|
|
mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_AUDIO_SHARING_DEVICE_CLICK,
|
|
isCallMode);
|
|
}
|
|
|
|
/**
|
|
* Initialize the controller.
|
|
*
|
|
* @param fragment The fragment to provide the context and metrics category for {@link
|
|
* AudioSharingBluetoothDeviceUpdater} and provide the host for dialogs.
|
|
*/
|
|
public void init(DashboardFragment fragment) {
|
|
mFragment = fragment;
|
|
mBluetoothDeviceUpdater =
|
|
new AudioSharingBluetoothDeviceUpdater(
|
|
fragment.getContext(),
|
|
AudioSharingDevicePreferenceController.this,
|
|
fragment.getMetricsCategory());
|
|
mDialogHandler = new AudioSharingDialogHandler(mContext, fragment);
|
|
}
|
|
|
|
@VisibleForTesting
|
|
void setBluetoothDeviceUpdater(@Nullable BluetoothDeviceUpdater bluetoothDeviceUpdater) {
|
|
mBluetoothDeviceUpdater = bluetoothDeviceUpdater;
|
|
}
|
|
|
|
@VisibleForTesting
|
|
void setDialogHandler(@Nullable AudioSharingDialogHandler dialogHandler) {
|
|
mDialogHandler = dialogHandler;
|
|
}
|
|
|
|
@VisibleForTesting
|
|
void setHostFragment(@Nullable DashboardFragment fragment) {
|
|
mFragment = fragment;
|
|
}
|
|
|
|
/** Test only: set intent handle state for test. */
|
|
@VisibleForTesting
|
|
void setIntentHandled(boolean handled) {
|
|
mIntentHandled.set(handled);
|
|
}
|
|
|
|
private void handleOnProfileStateChanged(
|
|
@NonNull CachedBluetoothDevice cachedDevice, int bluetoothProfile) {
|
|
boolean isLeAudioSupported = AudioSharingUtils.isLeAudioSupported(cachedDevice);
|
|
// For eligible (LE audio) remote device, we only check its connected LE audio assistant
|
|
// profile.
|
|
if (isLeAudioSupported
|
|
&& bluetoothProfile != BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT) {
|
|
Log.d(
|
|
TAG,
|
|
"Ignore onProfileConnectionStateChanged, not the le assistant profile for"
|
|
+ " le audio device");
|
|
return;
|
|
}
|
|
boolean isFirstConnectedProfile = isFirstConnectedProfile(cachedDevice, bluetoothProfile);
|
|
// For ineligible (non LE audio) remote device, we only check its first connected profile.
|
|
if (!isLeAudioSupported && !isFirstConnectedProfile) {
|
|
Log.d(
|
|
TAG,
|
|
"Ignore onProfileConnectionStateChanged, not the first connected profile for"
|
|
+ " non le audio device");
|
|
return;
|
|
}
|
|
if (DEBUG) {
|
|
Log.d(
|
|
TAG,
|
|
"Start handling onProfileConnectionStateChanged for "
|
|
+ cachedDevice.getDevice().getAnonymizedAddress());
|
|
}
|
|
// Check nullability to pass NullAway check
|
|
if (mDialogHandler != null) {
|
|
mDialogHandler.handleDeviceConnected(cachedDevice, /* userTriggered= */ false);
|
|
}
|
|
}
|
|
|
|
private boolean isMediaDevice(CachedBluetoothDevice cachedDevice) {
|
|
return cachedDevice.getUiAccessibleProfiles().stream()
|
|
.anyMatch(
|
|
profile ->
|
|
profile instanceof A2dpProfile
|
|
|| profile instanceof HearingAidProfile
|
|
|| profile instanceof LeAudioProfile
|
|
|| profile instanceof HeadsetProfile);
|
|
}
|
|
|
|
private boolean isFirstConnectedProfile(
|
|
CachedBluetoothDevice cachedDevice, int bluetoothProfile) {
|
|
return cachedDevice.getProfiles().stream()
|
|
.noneMatch(
|
|
profile ->
|
|
profile.getProfileId() != bluetoothProfile
|
|
&& profile.getConnectionStatus(cachedDevice.getDevice())
|
|
== BluetoothProfile.STATE_CONNECTED);
|
|
}
|
|
|
|
/**
|
|
* Handle device click triggered by intent.
|
|
*
|
|
* <p>When user click device from BT QS dialog, BT QS will send intent to open {@link
|
|
* com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment} and handle device
|
|
* click event under some conditions.
|
|
*
|
|
* <p>This method will be called when displayPreference if the audio sharing profiles are ready.
|
|
* If the profiles are not ready when the preference display, this method will be called when
|
|
* onServiceConnected.
|
|
*/
|
|
private void handleDeviceClickFromIntent() {
|
|
if (mFragment == null
|
|
|| mFragment.getActivity() == null
|
|
|| mFragment.getActivity().getIntent() == null) {
|
|
Log.d(TAG, "Skip handleDeviceClickFromIntent, fragment intent is null");
|
|
return;
|
|
}
|
|
Intent intent = mFragment.getActivity().getIntent();
|
|
Bundle args = intent.getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS);
|
|
BluetoothDevice device =
|
|
args == null
|
|
? null
|
|
: args.getParcelable(EXTRA_BLUETOOTH_DEVICE, BluetoothDevice.class);
|
|
CachedBluetoothDevice cachedDevice =
|
|
(device == null || mDeviceManager == null)
|
|
? null
|
|
: mDeviceManager.findDevice(device);
|
|
if (cachedDevice == null) {
|
|
Log.d(TAG, "Skip handleDeviceClickFromIntent, device is null");
|
|
return;
|
|
}
|
|
// Check nullability to pass NullAway check
|
|
if (device != null && !device.isConnected()) {
|
|
Log.d(TAG, "handleDeviceClickFromIntent: connect");
|
|
cachedDevice.connect();
|
|
} else if (mDialogHandler != null) {
|
|
Log.d(TAG, "handleDeviceClickFromIntent: trigger dialog handler");
|
|
mDialogHandler.handleDeviceConnected(cachedDevice, /* userTriggered= */ true);
|
|
}
|
|
}
|
|
|
|
private void updateTitle() {
|
|
if (mPreferenceGroup == null) return;
|
|
int titleResId;
|
|
if (mIsAudioModeOngoingCall.get()) {
|
|
// in phone call
|
|
titleResId = R.string.connected_device_call_device_title;
|
|
} else {
|
|
// without phone call
|
|
titleResId = R.string.audio_sharing_device_group_title;
|
|
}
|
|
AudioSharingUtils.postOnMainThread(mContext,
|
|
() -> {
|
|
if (mPreferenceGroup != null) {
|
|
mPreferenceGroup.setTitle(titleResId);
|
|
}
|
|
});
|
|
}
|
|
}
|