blob: e470b29f0843a358654a212155e9578e46f5103e [file] [log] [blame]
/*
* Copyright (C) 2017 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.bluetooth;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BleBroadcastSourceInfo;
import android.bluetooth.BleBroadcastAudioScanAssistManager;
import android.bluetooth.BleBroadcastSourceChannel;
import android.bluetooth.BleBroadcastSourceChannel;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import java.lang.String;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
import androidx.preference.EditTextPreference;
import androidx.preference.MultiSelectListPreference;
import com.android.settingslib.widget.ActionButtonsPreference;
import com.android.settingslib.bluetooth.A2dpProfile;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.VendorCachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothProfile;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.MapProfile;
import com.android.settingslib.bluetooth.PanProfile;
import com.android.settingslib.bluetooth.PbapServerProfile;
import com.android.settingslib.core.lifecycle.Lifecycle;
import androidx.appcompat.app.AlertDialog;
import android.text.Html;
import android.text.TextUtils;
import android.content.DialogInterface;
import android.widget.Toast;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.HashSet;
import java.util.Arrays;
import java.util.Iterator;
import com.android.settings.R;
import java.util.Map;
/**
* This class Broadcast Source Info details of the given Scan delegator
*/
public class BleBroadcastSourceInfoDetailsController extends BluetoothDetailsController
implements Preference.OnPreferenceClickListener,
Preference.OnPreferenceChangeListener, CachedBluetoothDevice.Callback {
private static final String TAG = "BleBroadcastSourceInfoDetailsController";
private final String EMPTY_BD_ADDRESS = "00:00:00:00:00:00";
//Display controls
private static final String KEY_SOURCE_INFO_GROUP = "broadcast_source_details_category";
private static final String KEY_SOURCE_ID = "broadcast_si_sourceId";
private static final String KEY_SOURCE_DEVICE = "broadcast_si_source_address";
private static final String KEY_SOURCE_ENC_STATUS = "broadcast_si_encryption_state";
private static final String KEY_SOURCE_METADATA = "broadcast_si_metadata";
private static final String KEY_SOURCE_METADATA_STATE = "broadcast_si_metadata_state";
private static final String KEY_SOURCE_AUDIO_STATE = "broadcast_si_audio_state";
//Input Controls
private static final String KEY_SOURCE_METADATA_SWITCH = "broadcast_si_enable_metadata_sync";
private static final String KEY_SOURCE_AUDIOSYNC_SWITCH = "broadcast_si_enable_audio_sync";
private static final String KEY_UPDATE_BCAST_CODE = "update_broadcast_code";
private static final String KEY_UPDATE_SOURCE_INFO = "bcast_si_update_button";
private static final String KEY_REMOVE_SOURCE_INFO = "bcast_si_remove_button";
private CachedBluetoothDevice mCachedDevice;
private VendorCachedBluetoothDevice mVendorCachedDevice;
private PreferenceCategory mSourceInfoContainer;
private Preference mSourceIdPref;
private Preference mSourceDevicePref;
private Preference mSourceEncStatusPref;
private Preference mSourceMetadataPref;
private Preference mSourceMetadataSyncStatusPref;
private MultiSelectListPreference mSourceAudioSyncStatusPref;
private SwitchPreference mSourceMetadataSyncSwitchPref;
private SwitchPreference mSourceAudioSyncSwitchPref;
private EditTextPreference mSourceUpdateBcastCodePref;
private ActionButtonsPreference mSourceUpdateSourceInfoPref;
private ActionButtonsPreference mSourceRemoveSourceInfoPref;
private boolean mIsValueChanged = false;
private BleBroadcastSourceInfo mBleBroadcastSourceInfo;
private BleBroadcastAudioScanAssistManager mScanAssistanceMgr;
private boolean isBroadcastPINUpdated = false;
private String mBroadcastCode;
private int mSourceInfoIndex;
private String EMPTY_ENTRY = "EMPTY ENTRY";
private int mMetadataSyncState;
private int mAudioSyncState;
private boolean mIsButtonRefreshOnly = false;
private boolean mGroupOp = false;
private AlertDialog mScanAssistGroupOpDialog = null;
private List<BleBroadcastSourceChannel> mBisIndicies;
private boolean mPAsyncCtrlNeeded = false;
public BleBroadcastSourceInfoDetailsController(Context context,
PreferenceFragmentCompat fragment,
BleBroadcastSourceInfo bleSourceInfo, CachedBluetoothDevice device,
int sourceInfoIndex, Lifecycle lifecycle) {
super(context, fragment, device, lifecycle);
Context mContext = context;
mBleBroadcastSourceInfo = bleSourceInfo;
mCachedDevice = device;
LocalBluetoothManager mgr = Utils.getLocalBtManager(context);
LocalBluetoothProfileManager profileManager = mgr.getProfileManager();
mVendorCachedDevice = VendorCachedBluetoothDevice.getVendorCachedBluetoothDevice(device, profileManager);
mScanAssistanceMgr = mVendorCachedDevice.getScanAssistManager();
lifecycle.addObserver(this);
mSourceInfoIndex = sourceInfoIndex;
clearInputs();
mPAsyncCtrlNeeded = false;
}
private void clearInputs()
{ //Keep the default state of Metadata as ON always
mMetadataSyncState =
BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_IN_SYNC;
mAudioSyncState =
BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_INVALID;
mBroadcastCode = null;
isBroadcastPINUpdated = false;
}
private void triggerRemoveBroadcastSource() {
if (mScanAssistanceMgr != null) {
mScanAssistanceMgr.removeBroadcastSource(
mBleBroadcastSourceInfo.getSourceId(), mGroupOp);
}
}
private void onRemoveBroadcastSourceInfoPressed() {
BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":onRemoveBroadcastSourceInfoPressed:" +
mBleBroadcastSourceInfo);
///*_CSIP
if (mCachedDevice.isGroupDevice()) {
String name = mCachedDevice.getName();
if (TextUtils.isEmpty(name)) {
name = mContext.getString(R.string.bluetooth_device);
}
String message = mContext.getString(R.string.group_remove_source_message, name);
String title = mContext.getString(R.string.group_remove_source_title);
DialogInterface.OnClickListener groupOpListener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (mScanAssistGroupOpDialog != null) {
mScanAssistGroupOpDialog.dismiss();
}
mGroupOp = true;
triggerRemoveBroadcastSource();
}
};
DialogInterface.OnClickListener nonGroupOpListener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (mScanAssistGroupOpDialog != null) {
mScanAssistGroupOpDialog.dismiss();
}
mGroupOp = false;
triggerRemoveBroadcastSource();
}
};
mGroupOp = false;
mScanAssistGroupOpDialog = BroadcastScanAssistanceUtils.showAssistanceGroupOptionsDialog(mContext,
mScanAssistGroupOpDialog, groupOpListener, nonGroupOpListener, title, Html.fromHtml(message));
} else {
//_CSIP*/
mGroupOp = false;
triggerRemoveBroadcastSource();
///*_CSIP
}
//_CSIP*/
}
private int getSyncState(int metadataSyncState, int audioSyncState) {
if (audioSyncState == BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED &&
metadataSyncState == BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_IN_SYNC) {
return BleBroadcastAudioScanAssistManager.SYNC_METADATA_AUDIO;
}
if (audioSyncState == BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED &&
metadataSyncState != BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_IN_SYNC) {
return BleBroadcastAudioScanAssistManager.SYNC_AUDIO;
}
if (audioSyncState != BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED &&
metadataSyncState == BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_IN_SYNC) {
return BleBroadcastAudioScanAssistManager.SYNC_METADATA;
}
return -1;
}
private void triggerUpdateBroadcastSource() {
if (mScanAssistanceMgr != null) {
if (mIsValueChanged == true) {
int syncState = getSyncState(mMetadataSyncState, mAudioSyncState);
if (syncState == -1) {
Log.e(TAG, "triggerUpdateBroadcastSource: Invalid sync Input, Ignore");
return;
}
mScanAssistanceMgr.updateBroadcastSource(
mBleBroadcastSourceInfo.getSourceId(),
getSyncState(mMetadataSyncState, mAudioSyncState),
mBisIndicies, mGroupOp);
mIsValueChanged = false;
}
if (isBroadcastPINUpdated) {
mScanAssistanceMgr.setBroadcastCode(
mBleBroadcastSourceInfo.getSourceId(),mBroadcastCode, mGroupOp);
isBroadcastPINUpdated = false;
}
clearInputs();
}
}
private void onUpdateBroadcastSourceInfoPressed() {
BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex +
"onUpdateBroadcastSourceInfoPressed:" + mBleBroadcastSourceInfo);
///*_CSIP
if (mCachedDevice.isGroupDevice()) {
String name = mCachedDevice.getName();
if (TextUtils.isEmpty(name)) {
name = mContext.getString(R.string.bluetooth_device);
}
String message = mContext.getString(R.string.group_update_source_message, name);
String title = mContext.getString(R.string.group_update_source_title);
DialogInterface.OnClickListener groupOpListener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
mGroupOp = true;
triggerUpdateBroadcastSource();
}
};
DialogInterface.OnClickListener nonGroupOpListener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
mGroupOp = false;
triggerUpdateBroadcastSource();
}
};
mGroupOp = false;
mScanAssistGroupOpDialog = BroadcastScanAssistanceUtils.showAssistanceGroupOptionsDialog(mContext,
mScanAssistGroupOpDialog, groupOpListener, nonGroupOpListener, title, Html.fromHtml(message));
} else {
//_CSIP*/
mGroupOp = false;
triggerUpdateBroadcastSource();
///*_CSIP
}
//_CSIP*/
}
@Override
protected void init(PreferenceScreen screen) {
mSourceInfoContainer =
(PreferenceCategory)screen.findPreference(getPreferenceKey());
mSourceIdPref = (Preference)mSourceInfoContainer.findPreference(
KEY_SOURCE_ID);
mSourceDevicePref = (Preference)mSourceInfoContainer.findPreference(
KEY_SOURCE_DEVICE);
mSourceEncStatusPref = (Preference)mSourceInfoContainer.findPreference(
KEY_SOURCE_ENC_STATUS);
mSourceMetadataPref = (Preference)mSourceInfoContainer.findPreference(
KEY_SOURCE_METADATA);
mSourceMetadataSyncStatusPref = (Preference)mSourceInfoContainer.findPreference(
KEY_SOURCE_METADATA_STATE);
if (mPAsyncCtrlNeeded) {
mSourceMetadataSyncSwitchPref = (SwitchPreference)mSourceInfoContainer.findPreference(
KEY_SOURCE_METADATA_SWITCH);
if (mSourceMetadataSyncSwitchPref != null) {
mSourceMetadataSyncSwitchPref.setOnPreferenceClickListener(this);
}
}
mSourceAudioSyncStatusPref = (MultiSelectListPreference)mSourceInfoContainer.findPreference(
KEY_SOURCE_AUDIO_STATE);
if (mSourceAudioSyncStatusPref != null) {
mSourceAudioSyncStatusPref.setOnPreferenceChangeListener(this);
}
mSourceAudioSyncSwitchPref = (SwitchPreference)mSourceInfoContainer.findPreference(
KEY_SOURCE_AUDIOSYNC_SWITCH);
if (mSourceAudioSyncSwitchPref != null) {
mSourceAudioSyncSwitchPref.setOnPreferenceClickListener(this);
}
mSourceUpdateBcastCodePref =
(EditTextPreference)mSourceInfoContainer.findPreference(
KEY_UPDATE_BCAST_CODE);
if (mSourceUpdateBcastCodePref != null) {
mSourceUpdateBcastCodePref.setOnPreferenceClickListener(this);
mSourceUpdateBcastCodePref.setOnPreferenceChangeListener(this);
}
mSourceUpdateSourceInfoPref =
((ActionButtonsPreference)mSourceInfoContainer.findPreference(
KEY_UPDATE_SOURCE_INFO))
.setButton1Text(R.string.update_sourceinfo_btn_txt)
.setButton1Enabled(false)
.setButton1OnClickListener((view)->onUpdateBroadcastSourceInfoPressed())
.setButton2Text(R.string.remove_sourceinfo_btn_txt)
.setButton2Icon(R.drawable.ic_settings_close)
.setButton2Enabled(false)
.setButton2OnClickListener((view)->onRemoveBroadcastSourceInfoPressed());
refresh();
}
@Override
public void onDeviceAttributesChanged() {
//update the Local variable If the receiverState is
//updated with some values
final Map<Integer, BleBroadcastSourceInfo> srcInfos =
mVendorCachedDevice.getAllBleBroadcastreceiverStates();
if (srcInfos == null) {
return;
}
for (Map.Entry<Integer, BleBroadcastSourceInfo> entry: srcInfos.entrySet()) {
Integer index = entry.getKey();
BleBroadcastSourceInfo sourceInfo = entry.getValue();
String toastString = null;
if (index == mSourceInfoIndex) {
BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":matching source Info");
if (sourceInfo.isEmptyEntry()) {
BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":source info seem to be removed");
toastString = "Source Info Removal";
mBleBroadcastSourceInfo = sourceInfo;
}
else if (sourceInfo.equals(mBleBroadcastSourceInfo) != true) {
//toast Message
mBleBroadcastSourceInfo = sourceInfo;
BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":Update in Broadcast Source Information");
toastString = "Source Info Update";
} else {
BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":No Update to Source Information values");
}
} else {
BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":Ignore this case");
}
if (toastString != null) {
Toast toast = Toast.makeText(mContext, toastString, Toast.LENGTH_SHORT);
toast.show();
}
}
refresh();
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String key = preference.getKey();
BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":onPreferenceChange" + newValue);
if (key.equals(KEY_UPDATE_BCAST_CODE)) {
EditTextPreference pref = (EditTextPreference)preference;
String code = (String)newValue;
//Use different flag for Broadcast pin
isBroadcastPINUpdated = true;
mBroadcastCode = (String)newValue;
} else if (key.equals(KEY_SOURCE_AUDIO_STATE)) {
BroadcastScanAssistanceUtils.debug(TAG, ">>Checked:" +newValue);
CharSequence[] getEntriesSeqence =
((MultiSelectListPreference)preference).getEntries();
Set<String> valueSet = ((MultiSelectListPreference)preference).getValues();
String[] selectedStrings = new String[((Set<String>) newValue).size()];
//noinspection unchecked
int j =0;
for (String value : (Set<String>) newValue) {
selectedStrings[j] = value;
for (int i=0; i<mBisIndicies.size(); i++) {
if (value.equals(mBisIndicies.get(i).getDescription())) {
BroadcastScanAssistanceUtils.debug(TAG, "Selected: value["+ i + "]- " + value);
if (mBisIndicies.get(i).getStatus() == true) {
mBisIndicies.get(i).setStatus(false);
} else {
mBisIndicies.get(i).setStatus(true);
}
}
}
BroadcastScanAssistanceUtils.debug(TAG, "value["+ j++ + "]- " + value);
}
mIsValueChanged = true;
}
mIsButtonRefreshOnly = true;
refresh();
return true;
}
/**
* When the pref for a ble broadcast source info details is clicked on, necessary action will be
* taken and updateBroadcastSourceInfo would be called as needed
*/
@Override
public boolean onPreferenceClick(Preference preference) {
String key = preference.getKey();
BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":onPreferenceClick");
mIsValueChanged = true;
if (mPAsyncCtrlNeeded) {
if (key.equals(KEY_SOURCE_METADATA_SWITCH)) {
SwitchPreference pref = (SwitchPreference)preference;
BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":Meta data sync state: " + pref.isChecked());
if (pref.isChecked()) mMetadataSyncState = BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_IN_SYNC;
else mMetadataSyncState = BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_IDLE;
//Update the audio sync state as well
if (mSourceAudioSyncSwitchPref != null) {
if (mSourceAudioSyncSwitchPref.isChecked()) {
mAudioSyncState = BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED;
}
else {
mAudioSyncState = BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_NOT_SYNCHRONIZED;
}
}
}
}
if (key.equals(KEY_SOURCE_AUDIOSYNC_SWITCH)) {
SwitchPreference pref = (SwitchPreference)preference;
BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":Audio sync state: " + pref.isChecked());
if (pref.isChecked()) mAudioSyncState = BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED;
else mAudioSyncState = BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_NOT_SYNCHRONIZED;
if (mPAsyncCtrlNeeded) {
//Update the metadata sync state as well
if (mSourceMetadataSyncSwitchPref != null) {
if (mSourceMetadataSyncSwitchPref.isChecked()) {
mMetadataSyncState = BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED;
}
else {
mMetadataSyncState = BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_NOT_SYNCHRONIZED;
}
}
}
} else if (key.equals(KEY_UPDATE_BCAST_CODE)) {
EditTextPreference pref = (EditTextPreference)preference;
BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":>>Pin code updated: " + pref.getText());
//Use different flag for Broadcast pin
mIsValueChanged = false;
isBroadcastPINUpdated = true;
mBroadcastCode = pref.getText();
} else {
BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":unhandled preference");
mIsValueChanged = false;
}
BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":onPreferenceClick" + mBleBroadcastSourceInfo);
mIsButtonRefreshOnly = true;
refresh();
return true;
}
@Override
public void onPause() {
super.onPause();
mCachedDevice.unregisterCallback(this);
}
@Override
public void onResume() {
super.onResume();
mCachedDevice.registerCallback(this);
}
String getEncryptionStatusString(int encryptionStatus) {
switch(encryptionStatus) {
case BleBroadcastSourceInfo.BROADCAST_ASSIST_ENC_STATE_INVALID:
return "ENCRYPTION STATE UNKNOWN";
case BleBroadcastSourceInfo.BROADCAST_ASSIST_ENC_STATE_UNENCRYPTED:
return "UNENCRYPTED STREAMING";
case BleBroadcastSourceInfo.BROADCAST_ASSIST_ENC_STATE_PIN_NEEDED:
return "PIN UPDATE NEEDED";
case BleBroadcastSourceInfo.BROADCAST_ASSIST_ENC_STATE_DECRYPTING:
return "DECRYPTING SUCCESSFULLY";
case BleBroadcastSourceInfo.BROADCAST_ASSIST_ENC_STATE_BADCODE:
return "INCORRECT BROADCAST PIN";
}
return "ENCRYPTION STATE UNKNOWN";
}
String getMetadataSyncStatusString(int metadataSyncStatus) {
switch(metadataSyncStatus) {
case BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_IDLE:
return "IDLE";
case BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_INVALID:
return "UNKNOWN";
case BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_IN_SYNC:
return "IN SYNC";
case BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_NO_PAST:
return "NO PAST";
case BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_SYNCINFO_REQ:
return "SYNCINFO NEEDED";
case BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_SYNC_FAIL:
return "SYNC FAIL";
}
return "UNKNOWN";
}
String getAudioSyncStatusString(int audioSyncStatus) {
switch(audioSyncStatus) {
case BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_INVALID:
return "UNKNOWN";
case BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_NOT_SYNCHRONIZED:
return "NOT IN SYNC";
case BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED:
return "IN SYNC";
}
return "UNKNOWN";
}
private boolean isPinUpdatedNeeded() {
boolean ret = false;
if (BroadcastScanAssistanceUtils.isLocalDevice(mBleBroadcastSourceInfo.getSourceDevice())) {
BroadcastScanAssistanceUtils.debug(TAG, "Local Device, Dont allow User to update PWD");
return false;
}
if (mBleBroadcastSourceInfo.getEncryptionStatus()
== BleBroadcastSourceInfo.BROADCAST_ASSIST_ENC_STATE_PIN_NEEDED) {
ret = true;
}
BroadcastScanAssistanceUtils.debug(TAG, "isPinUpdatedNeeded return" + ret);
return ret;
}
/**
* Refreshes the state of the switches for all profiles, possibly adding or removing switches as
* needed.
*/
@Override
protected void refresh() {
BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":refresh: " + mBleBroadcastSourceInfo + " mSourceIndex" + mSourceInfoIndex);
mSourceIdPref.setSummary(
String.valueOf(mBleBroadcastSourceInfo.getSourceId()));
BluetoothDevice dev = mBleBroadcastSourceInfo.getSourceDevice();
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
String s = null;
if (dev != null && adapter != null) {
if (adapter.getAddress().equals(dev.getAddress()))
{
s = adapter.getName() + "(Self)";
} else {
s = dev.getAlias();
}
if (s == null) {
s = String.valueOf(dev.getAddress());
}
}
if (s == null || s.equals(EMPTY_BD_ADDRESS)) {
BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":NULL source device");
s = "EMPTY_ENTRY";
}
mSourceDevicePref.setSummary(s);
mSourceEncStatusPref.setSummary(
getEncryptionStatusString(
mBleBroadcastSourceInfo.getEncryptionStatus())
);
if (mBleBroadcastSourceInfo.isEmptyEntry()) {
BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":Source Information seem to be Empty");
if (mPAsyncCtrlNeeded) {
mSourceMetadataSyncSwitchPref.setEnabled(false);
}
mSourceAudioSyncSwitchPref.setEnabled(false);
mSourceUpdateBcastCodePref.setEnabled(false);
//Disable 'remove and update source Info' if It is empty entry
mSourceUpdateSourceInfoPref.setButton1Enabled(false);
mSourceUpdateSourceInfoPref.setButton2Enabled(false);
mSourceAudioSyncStatusPref.setEnabled(false);
mIsValueChanged = false;
} else {
//enable the Input controls
if (mPAsyncCtrlNeeded) {
mSourceMetadataSyncSwitchPref.setEnabled(true);
}
mSourceAudioSyncSwitchPref.setEnabled(true);
mSourceUpdateBcastCodePref.setEnabled(isPinUpdatedNeeded());
if (mIsButtonRefreshOnly != true) {
mSourceMetadataSyncStatusPref.setSummary(
getMetadataSyncStatusString(mBleBroadcastSourceInfo.getMetadataSyncState())
);
mSourceAudioSyncStatusPref.setSummary(
getAudioSyncStatusString(mBleBroadcastSourceInfo.getAudioSyncState())
);
mBisIndicies = mBleBroadcastSourceInfo.getBroadcastChannelsSyncStatus();
if (mBisIndicies != null) {
String[] bisNames = new String[mBisIndicies.size()];
boolean[] bisStatuses = new boolean[mBisIndicies.size()];
Set<String> hashSet = new HashSet<String>();
for (int i=0; i<mBisIndicies.size(); i++) {
bisNames[i] = mBisIndicies.get(i).getDescription();
bisStatuses[i] = mBisIndicies.get(i).getStatus();
}
hashSet.addAll(Arrays.asList(bisNames));
mSourceAudioSyncStatusPref.setEntries(bisNames);
mSourceAudioSyncStatusPref.setEntryValues(bisNames);
mSourceAudioSyncStatusPref.setValues(hashSet);
}
//Reflect the controls based on the status
if (mPAsyncCtrlNeeded) {
mSourceMetadataSyncSwitchPref.setChecked(mBleBroadcastSourceInfo.getMetadataSyncState() ==
BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_IN_SYNC);
}
mSourceAudioSyncSwitchPref.setChecked(mBleBroadcastSourceInfo.getAudioSyncState() ==
BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED);
int getFirstSyncedBisIndex = -1;
if (mBisIndicies != null) {
for (int i=0; i<mBisIndicies.size(); i++) {
if (mBisIndicies.get(i).getStatus() == true) {
getFirstSyncedBisIndex = i;
break;
}
}
}
byte[] metadata = null;
if (getFirstSyncedBisIndex != -1) {
metadata = mBisIndicies.get(getFirstSyncedBisIndex).getMetadata();
}
if (metadata != null) {
String metaDataStr = new String(metadata);
BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":Metadata:" + metaDataStr);
mSourceMetadataPref.setSummary(metaDataStr);
} else {
mSourceMetadataPref.setSummary("NONE");
}
if (mBleBroadcastSourceInfo != null &&
(mBleBroadcastSourceInfo.getMetadataSyncState() != BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_IN_SYNC &&
mBleBroadcastSourceInfo.getAudioSyncState() != BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED)) {
//Remove source Info button
mSourceUpdateSourceInfoPref.setButton2Enabled(true);
} else {
mSourceUpdateSourceInfoPref.setButton2Enabled(false);
}
}
//User can update OR remove only if the Source info is not an Empty Entry
if (mIsValueChanged || isBroadcastPINUpdated) {
//User can Update only if any of the entries are modified by user action
mSourceUpdateSourceInfoPref.setButton1Enabled(true);
} else {
mSourceUpdateSourceInfoPref.setButton1Enabled(false);
}
mIsButtonRefreshOnly = false;
}
}
@Override
public String getPreferenceKey() {
return KEY_SOURCE_INFO_GROUP;
}
}