# Bluetooth survey
###### tags: `AU19` `bluetooth`
## 藍牙規格
藍牙耳機規範(HSP)– 提供手機(行動電話)與耳機之間通訊所需的基本功能。
免手持裝置規範 (HFP)– 在 HSP 的基礎上增加了某些擴充套件功能,原來只用於從固定車載擴音裝置來控制行動電話人機介面規範 (HID)
藍牙立體聲音訊傳輸規範(A2DP)– 允許傳輸立體聲音訊訊號。 (相比用於 HSP 和 HFP 的單聲道加密,質量要好得
回音暨噪音消除技術(CVC)
– 原理是通過耳機內置的消噪軟體及麥克風,來抑制多種類型的混響噪音。有了這個技術,周邊的環境雜音得以衰減,對方將能聽到更加清晰的聲音。
音訊/影片遠端控制設定檔(AVRCP) –用於從控制器(如立體聲耳機)向目標裝置(如裝有 Media Player 的電腦)發送命令(如前跳、暫停和播放)。
物件交換規範 (OPP) –為Object Push Profile的簡稱,在附件裝置與手機通訊的情景中,既有手機發起資料傳輸請求也有裝置側發起傳輸請求的需要。
-----------
`AVRCP`
在藍牙技術協定中包含了AVRCP這個協定。
中文:音訊/視訊遙控協定
英文:Audio/Video Remote Control Profile
它提供了搖控裝置一個標準的控制介面,
讓你可以用一支遙控器或耳機等遙控裝置,
搖控你所有的電視、電腦或是手機的音訊和視訊介面。
這個協定可以和A2DP(藍牙立體聲傳輸協定)共同使用,
一般來說最基本的用法就是控制裝置透過AVRCP傳輸控制指令,
然後目標裝置就會依指令透過A2DP傳回音訊結果。
除了音訊之外,
AVRCP更可以用來傳輸要求數據的指令,
目標裝置接收到指令後,
也可以透過這個協定回傳資訊,
如果你的控制裝置有顯示面板的話,
所傳回的資訊就會顯示在面板上。
目前大多的智慧型手機,
和一些音樂手機都可以完整支援AVRCP,
因此你可以很簡單地利用藍牙耳機,
接聽電話和聆聽音樂。
`A2DP`
中文:立體聲音訊傳輸協定
英文:Advenced Audio Distribution Profile
A2DP代表的意思是進階音效分配設定檔。
這是定義如何以藍牙連線,
從某個裝置串流高品質立體聲音效至另一個裝置,
(例如從行動電話串流至無線耳機)的藍牙立體聲設定檔。
雖然很多產品會有用於語音通話的藍牙功能,
但要使音樂能從某個藍牙裝置串流至另一裝置,
則這兩個裝置都必須有A2DP設定檔。
如果兩個裝置都沒有這個設定檔,
仍然可以使用標準耳機或免持設定檔連線,
但這些設定檔不支援立體聲音樂。
## 參考資料
1. https://www.jianshu.com/p/b59a5b7dca2d
2. http://cmnocsexperience.blogspot.com/2019/01/android.html
3. https://github.com/googlearchive/android-BluetoothChat
4. https://developer.android.com/guide/topics/connectivity/bluetooth?hl=zh-cn
5. http://blog.kenyang.net/2012/07/27/android-bluetooth-api
6. https://blog.csdn.net/yehui928186846/article/details/52710112
7. https://itimetraveler.github.io/2017/05/18/【Android】Audio音频输出通道切换%20-%20蓝牙、外放/
8. https://blog.csdn.net/wc0000000/article/details/82884511
9. https://segmentfault.com/a/1190000000713535
10. https://blog.csdn.net/u012545728/article/details/99462873
## Bluetooth 實作
藍芽耳機的兩種鏈路,`A2DP`及`SCO`。android的api表明:
* A2DP:是一種單向的高品質音訊資料傳輸鏈路,通常用於播放立體聲音樂;
* SCO: 則是一種雙向的音訊資料的傳輸鏈路,該鏈路只支援8K及16K單聲道的音訊資料,只能用於普通語音的傳輸,若用於播放音樂那就只能呵呵了。
連接藍牙音箱
```cpp=
public void changeToHeadset(){
mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
mAudioManager.startBluetoothSco();
mAudioManager.setBluetoothScoOn(true);
mAudioManager.setSpeakerphoneOn(false);
}
```
即使应用程序处于锁定模式,它也用于Android音乐遥控器
`RemoteControlClient`只要调用下面的方法,而您的接收器命令的行动,播放,暂停,下一个和上一个歌曲曲目。
```cpp
private void lockScreenControls() {
// Use the media button APIs (if available) to register ourselves for media button
// events
MediaButtonHelper.registerMediaButtonEventReceiverCompat(mAudioManager, mMediaButtonReceiverComponent);
// Use the remote control APIs (if available) to set the playback state
if (mRemoteControlClientCompat == null) {
Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
intent.setComponent(mMediaButtonReceiverComponent);
mRemoteControlClientCompat = new RemoteControlClientCompat(PendingIntent.getBroadcast(this /*context*/,0 /*requestCode, ignored*/, intent /*intent*/, 0 /*flags*/));
RemoteControlHelper.registerRemoteControlClient(mAudioManager,mRemoteControlClientCompat);
}
mRemoteControlClientCompat.setPlaybackState(RemoteControlClient.PLAYSTATE_PLAYING);
mRemoteControlClientCompat.setTransportControlFlags(
RemoteControlClient.FLAG_KEY_MEDIA_PAUSE |
RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS |
RemoteControlClient.FLAG_KEY_MEDIA_NEXT |
RemoteControlClient.FLAG_KEY_MEDIA_STOP);
//update remote controls
mRemoteControlClientCompat.editMetadata(true)
.putString(MediaMetadataRetriever.METADATA_KEY_ARTIST, "NombreArtista")
.putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, "Titulo Album")
.putString(MediaMetadataRetriever.METADATA_KEY_TITLE, nombreCancion)
//.putLong(MediaMetadataRetriever.METADATA_KEY_DURATION,playingItem.getDuration())
// TODO: fetch real item artwork
.putBitmap(RemoteControlClientCompat.MetadataEditorCompat.METADATA_KEY_ARTWORK, getAlbumArt())
.apply();
}
}
```
## AVRCP example
```cpp
public class A2dpTestFragment extends Fragment {
private static String TAG = A2dpTestFragment.class.getSimpleName();
private MainActivity mActivity;
private BluetoothA2dpSink mA2dpService;
private BluetoothAvrcpController mAvrcpController;
private TextView mStatusView;
private TextView tvTitle;
private TextView tvAlbum;
private TextView tvArtist;
private TextView tvDuration;
private TextView tvCurrent;
private SeekBar sbProgress;
private Button btnStop;
private Button btnConn;
private Button btnDisconn;
private ImageView imgPlayPause;
private ImageView imgPrev;
private ImageView imgNext;
private ImageView imgShuffle;
private ImageView imgRepeat;
// private ImageButton
private BluetoothDevice mDevice;
private MediaMetadata mediaMetadata;
private PlaybackState playbackState;
private BluetoothAvrcpPlayerSettings mAvrcpPlayerSettings;
private String title;
private String artist;
private long duration;
private String album;
//status control
private static boolean isA2dpPlaying = false;
private static boolean isA2dpConnected = false;
//SETTING_EQUALIZER, SETTING_REPEAT, SETTING_SHUFFLE, SETTING_SCAN
private static int[] current_avrcp_setting_value = {0, 0, 0, 0};
private SimpleDateFormat timeFormat = new SimpleDateFormat("mm:ss");
private BroadcastReceiver mA2dpReciver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, "action = " + action);
if (action.equals(BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED)) {
int preState = intent.getIntExtra(BluetoothA2dpSink.EXTRA_PREVIOUS_STATE, 0);
int state = intent.getIntExtra(BluetoothA2dpSink.EXTRA_STATE, 0);
Log.d(TAG, "action = " + action + ", state " + preState + " -> " + state);
if (state == BluetoothProfile.STATE_CONNECTED) {
isA2dpConnected = true;
} else if (state == BluetoothProfile.STATE_DISCONNECTED) {
isA2dpConnected = false;
}
} else if (action.equals(BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED)) {
int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (state == BluetoothProfile.STATE_CONNECTED) {
mStatusView.setText("AVRCP_CONTROLLER connected");
mStatusView.append("\r\nAvrcp devices: \r\n");
mStatusView.append(" - " + device.getName() + " " + device.getAddress() + "\r\n");
// FIXME:
mDevice = device;
}
if (state == BluetoothProfile.STATE_DISCONNECTED) {
mStatusView.setText("AVRCP_CONTROLLER connected");
mStatusView.append("\r\nAvrcp devices: \r\n");
mStatusView.append(" - " + "no device");
imgRepeat.setAlpha(255);
imgRepeat.setClickable(true);
imgShuffle.setAlpha(255);
imgShuffle.setClickable(true);
}
} else if (action.equals(BluetoothAvrcpController.ACTION_TRACK_EVENT)) {
mediaMetadata = intent.getParcelableExtra(BluetoothAvrcpController.EXTRA_METADATA);
playbackState = intent.getParcelableExtra(BluetoothAvrcpController.EXTRA_PLAYBACK);
if (mediaMetadata != null) {
Log.v(TAG, "Get MediaMetadata");
// TODO: 16-11-23 display the info of media
displayMediaInfo(mediaMetadata);
sbProgress.setMax((int) mediaMetadata.getLong(MediaMetadata.METADATA_KEY_DURATION));
}
// update progress bar
if (playbackState != null) {
Log.v(TAG, "Get PlaybackState");
Log.v(TAG, playbackState.toString());
// TODO: 16-11-23 change the progress
long postion = playbackState.getPosition();
Log.v(TAG, new SimpleDateFormat("HH:mm:ss").format(postion));
sbProgress.setProgress((int) postion);
tvCurrent.setText(timeFormat.format(postion));
}
//update play state
if (playbackState != null) {
int state = playbackState.getState();
if (state == PlaybackState.STATE_PLAYING) {
isA2dpPlaying = true;
imgPlayPause.setImageResource(R.drawable.music_button_pause_disable);
}
if (state == PlaybackState.STATE_PAUSED) {
isA2dpPlaying = false;
imgPlayPause.setImageResource(R.drawable.music_button_play_disable);
}
}
} else if (action.equals(BluetoothAvrcpController.ACTION_PLAYER_SETTING)) {
mAvrcpPlayerSettings = intent.getParcelableExtra(BluetoothAvrcpController.EXTRA_PLAYER_SETTING);
refreshAvrcpSettings(mAvrcpPlayerSettings);
}
}
};
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mActivity = (MainActivity) activity;
} catch (ClassCastException e) {
throw new ClassCastException(this.getClass().getSimpleName()
+ " can be only attached to " + MainActivity.class.getSimpleName());
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDevice = mActivity.mSelectedDevice;
IntentFilter it = new IntentFilter();
it.addAction(BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED);
it.addAction(BluetoothA2dpSink.ACTION_AUDIO_CONFIG_CHANGED);
it.addAction(BluetoothA2dpSink.ACTION_PLAYING_STATE_CHANGED);
it.addAction(BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED);
it.addAction(BluetoothAvrcpController.ACTION_TRACK_EVENT);
it.addAction(BluetoothAvrcpController.ACTION_PLAYER_SETTING);
mActivity.registerReceiver(mA2dpReciver, it);
}
// @Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_avrcp, null);
if (mDevice == null) {
Toast.makeText(mActivity, "Please select a device", Toast.LENGTH_SHORT).show();
return null;
} else if (!BluetoothAdapter.getDefaultAdapter().isEnabled()) {
Toast.makeText(mActivity, "Bluetooth is not enabled", Toast.LENGTH_SHORT).show();
return null;
}
findUiViewAndSetListener(view);
timeFormat.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
bluetoothAdapter.getProfileProxy(mActivity, mA2dpServiceListener, 11); //BluetoothProfile.A2DP_SINK
bluetoothAdapter.getProfileProxy(mActivity, mAvrcpServiceListener, 12); //BluetoothProfile.AVRCP_CONTROLLER
mStatusView.setText("Connecting to the AVRCP_CONTROLLER service");
return view;
}
@Override
public void onDestroy() {
super.onDestroy();
mActivity.unregisterReceiver(mA2dpReciver);
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// TODO mAvrcpController.removeCallback();
bluetoothAdapter.closeProfileProxy(11, mA2dpService); // BluetoothProfile.A2DP_SINK
bluetoothAdapter.closeProfileProxy(12, mAvrcpController); //BluetoothProfile.AVRCP_CONTROLLER
}
private BluetoothProfile.ServiceListener mA2dpServiceListener = new BluetoothProfile.ServiceListener() {
@Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
if (profile == 11) { // BluetoothProfile.A2DP_SINK
mA2dpService = (BluetoothA2dpSink) proxy;
// mA2dpService.connect(mActivity.mSelectedDevice);
}
//init the a2dp state
// if (mA2dpService.isA2dpPlaying(mDevice)) {
// isA2dpPlaying = true;
// imgPlayPause.setImageResource(R.drawable.music_button_pause_disable);
// } else {
// isA2dpPlaying = false;
// imgPlayPause.setImageResource(R.drawable.music_button_play_disable);
// }
}
@Override
public void onServiceDisconnected(int profile) {
if (profile == 11) { // BluetoothProfile.A2DP_SINK
mA2dpService = null;
}
}
};
private BluetoothProfile.ServiceListener mAvrcpServiceListener = new BluetoothProfile.ServiceListener() {
@Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
if (profile == 12) { // BluetoothProfile.AVRCP_CONTROLLER
mStatusView.setText("AVRCP_CONTROLLER connected");
Log.d(TAG, "AvrcpControllerService connected");
mAvrcpController = (BluetoothAvrcpController) proxy;
// TODO mAvrcpController.setCallback(new AvrcpControllerCallback());
mStatusView.append("\r\nAvrcp devices: \r\n");
List<BluetoothDevice> devices = mAvrcpController.getConnectedDevices();
if (devices.isEmpty()) {
mStatusView.append(" - " + "no device");
} else {
for (BluetoothDevice device : devices)
mStatusView.append(" - " + device.getName() + " " + device.getAddress() + "\r\n");
}
//init settings (for the selected device)
if (mDevice != null) {
refreshAvrcpSettings(mAvrcpController.getPlayerSettings(mDevice));
}
}
}
@Override
public void onServiceDisconnected(int profile) {
if (profile == 12) { //BluetoothProfile.AVRCP_CONTROLLER
mStatusView.setText("AVRCP_CONTROLLER disconnected");
Log.d(TAG, "AvrcpControllerService disconnected");
// TODO mAvrcpController.removeCallback();
mAvrcpController = null;
}
}
};
private View.OnClickListener listener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.play_pause_button:
onPlayPauseButtonClick();
break;
case R.id.prevButton:
onPrevButtonClick();
break;
case R.id.nextButton:
onNextButtonClick();
break;
case R.id.stopButton:
onStopButtonClick();
break;
case R.id.img_shuffle:
onShuffleClick();
break;
case R.id.img_repeat:
onRepeatClick();
break;
case R.id.btn_a2dp_conn:
onA2dpConnect();
break;
case R.id.btn_a2dp_disc:
onA2dpDisconnnect();
break;
default:
break;
}
}
};
private void findUiViewAndSetListener(View view) {
mStatusView = (TextView) view.findViewById(R.id.status);
tvTitle = (TextView) view.findViewById(R.id.tv_title);
tvAlbum = (TextView) view.findViewById(R.id.tv_album);
tvArtist = (TextView) view.findViewById(R.id.tv_artist);
tvDuration = (TextView) view.findViewById(R.id.tv_duration);
tvCurrent = (TextView) view.findViewById(R.id.tv_current);
sbProgress = (SeekBar) view.findViewById(R.id.sb_progress);
btnStop = (Button) view.findViewById(R.id.stopButton);
imgPlayPause = (ImageView) view.findViewById(R.id.play_pause_button);
imgPrev = (ImageView) view.findViewById(R.id.prevButton);
imgNext = (ImageView) view.findViewById(R.id.nextButton);
imgShuffle = (ImageView) view.findViewById(R.id.img_shuffle);
imgRepeat = (ImageView) view.findViewById(R.id.img_repeat);
btnConn = (Button) view.findViewById(R.id.btn_a2dp_conn);
btnDisconn = (Button) view.findViewById(R.id.btn_a2dp_disc);
btnStop.setOnClickListener(listener);
imgPlayPause.setOnClickListener(listener);
imgPrev.setOnClickListener(listener);
imgNext.setOnClickListener(listener);
imgShuffle.setOnClickListener(listener);
imgRepeat.setOnClickListener(listener);
btnConn.setOnClickListener(listener);
btnDisconn.setOnClickListener(listener);
}
private void sendCommand(int keyCode) {
if (mAvrcpController == null)
return;
List<BluetoothDevice> devices = mAvrcpController.getConnectedDevices();
for (BluetoothDevice device : devices) {
Log.d(TAG, "send command to device: " + device.getName() + " " + device.getAddress());
mAvrcpController.sendPassThroughCmd(device, keyCode, BluetoothAvrcp.PASSTHROUGH_STATE_PRESS);
mAvrcpController.sendPassThroughCmd(device, keyCode, BluetoothAvrcp.PASSTHROUGH_STATE_RELEASE);
}
}
public void onPlayPauseButtonClick() {
if (isA2dpPlaying) {
sendCommand(BluetoothAvrcp.PASSTHROUGH_ID_PAUSE);
} else if (!isA2dpPlaying) {
sendCommand(BluetoothAvrcp.PASSTHROUGH_ID_PLAY);
}
}
public void onStopButtonClick() {
//FIXME
sendCommand(BluetoothAvrcp.PASSTHROUGH_ID_STOP);
// int profileState = BluetoothAdapter.getDefaultAdapter().getConnectionState();
// Log.d(TAG + "FANGCX_FANGCX", "profileSate: " + profileState);
}
public void onNextButtonClick() {
sendCommand(BluetoothAvrcp.PASSTHROUGH_ID_FORWARD);
}
public void onPrevButtonClick() {
sendCommand(BluetoothAvrcp.PASSTHROUGH_ID_BACKWARD);
}
private void displayMediaInfo(MediaMetadata metaData) {
title = metaData.getString(MediaMetadata.METADATA_KEY_TITLE);
artist = metaData.getString(MediaMetadata.METADATA_KEY_ARTIST);
duration = metaData.getLong(MediaMetadata.METADATA_KEY_DURATION);
album = metaData.getString(MediaMetadata.METADATA_KEY_ALBUM);
tvTitle.setText((title == null ? "Unknown" : title));
tvArtist.setText((artist == null ? "Unknown" : artist));
tvAlbum.setText((album == null ? "Unknown" : album));
tvDuration.setText(timeFormat.format(duration));
Log.d(TAG, "duration : " + new SimpleDateFormat("HH:mm:ss").format(duration));
}
public void onGetAttrsButtonClick(View view) {
//for test
List<BluetoothDevice> devices = mAvrcpController.getConnectedDevices();
for (BluetoothDevice device : devices) {
BluetoothAvrcpPlayerSettings ps = mAvrcpController.getPlayerSettings(device);
Log.d(TAG, "PlayerSetting id:" + ps.getSettings());
refreshAvrcpSettings(ps);
}
}
//off -> shuffle -> off
public void onShuffleClick() {
int currentValue = current_avrcp_setting_value[2];
if (currentValue == BluetoothAvrcpPlayerSettings.STATE_OFF) {
if (!setAvrcpSettings(BluetoothAvrcpPlayerSettings.SETTING_SHUFFLE, BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK)) {
//TODO : if is not supported
}
}
if (currentValue == BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK) {
if (!setAvrcpSettings(BluetoothAvrcpPlayerSettings.SETTING_SHUFFLE, BluetoothAvrcpPlayerSettings.STATE_OFF)) {
// TODO: if is note supported
}
}
}
//off -> single -> all -> off
public void onRepeatClick() {
int currentValue = current_avrcp_setting_value[1];
if (currentValue == BluetoothAvrcpPlayerSettings.STATE_OFF) {
if (!setAvrcpSettings(BluetoothAvrcpPlayerSettings.SETTING_REPEAT, BluetoothAvrcpPlayerSettings.STATE_SINGLE_TRACK)) {
// TODO: if is note supported
}
}
if (currentValue == BluetoothAvrcpPlayerSettings.STATE_SINGLE_TRACK) {
if (!setAvrcpSettings(BluetoothAvrcpPlayerSettings.SETTING_REPEAT, BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK)) {
// TODO: if is note supported
}
}
if (currentValue == BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK) {
if (!setAvrcpSettings(BluetoothAvrcpPlayerSettings.SETTING_REPEAT, BluetoothAvrcpPlayerSettings.STATE_OFF)) {
// TODO: if is note supported
}
}
}
private void onA2dpConnect() {
if (mA2dpService != null) {
Toast.makeText(mActivity, "To Conn Dev : " + mDevice.getName(), Toast.LENGTH_LONG).show();
mA2dpService.connect(mDevice);
}
}
private void onA2dpDisconnnect() {
if (mA2dpService != null) {
Toast.makeText(mActivity, "To Disc Dev : " + mDevice.getName(), Toast.LENGTH_LONG).show();
mA2dpService.disconnect(mDevice);
}
}
private boolean setAvrcpSettings(int type, int value) {
BluetoothAvrcpPlayerSettings settings = new BluetoothAvrcpPlayerSettings(type);
settings.addSettingValue(type, value);
return mAvrcpController.setPlayerApplicationSetting(settings);
}
private void refreshAvrcpSettings(BluetoothAvrcpPlayerSettings ps) {
if (ps == null) {
Log.d(TAG, "playerSettings is null");
return;
}
int mSettings = ps.getSettings();
if (((byte) mSettings & BluetoothAvrcpPlayerSettings.SETTING_REPEAT) == 0) {
imgRepeat.setAlpha(50);
imgRepeat.setClickable(false);
}
if (((byte) mSettings & BluetoothAvrcpPlayerSettings.SETTING_SHUFFLE) == 0) {
imgShuffle.setAlpha(50);
imgShuffle.setClickable(false);
}
if (((byte) mSettings & BluetoothAvrcpPlayerSettings.SETTING_EQUALIZER) != 0) {
int equalizerValue = ps.getSettingValue(BluetoothAvrcpPlayerSettings.SETTING_SHUFFLE);
Log.d(TAG, "EQUALIZER value: " + equalizerValue);
switch (equalizerValue) {
case BluetoothAvrcpPlayerSettings.STATE_OFF:
break;
case BluetoothAvrcpPlayerSettings.STATE_ON:
break;
default:
return;
}
current_avrcp_setting_value[0] = equalizerValue;
}
if (((byte) mSettings & BluetoothAvrcpPlayerSettings.SETTING_REPEAT) != 0) {
int repeatValue = ps.getSettingValue(BluetoothAvrcpPlayerSettings.SETTING_REPEAT);
Log.d(TAG, "REPEAT value: " + repeatValue);
switch (repeatValue) {
case BluetoothAvrcpPlayerSettings.STATE_OFF:
imgRepeat.setImageResource(R.drawable.avrcp_setting_repeat_off);
break;
case BluetoothAvrcpPlayerSettings.STATE_SINGLE_TRACK:
imgRepeat.setImageResource(R.drawable.avrcp_setting_repeat_single);
break;
case BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK:
imgRepeat.setImageResource(R.drawable.avrcp_setting_repeat_all);
break;
case BluetoothAvrcpPlayerSettings.STATE_GROUP:
break;
default:
return;
}
current_avrcp_setting_value[1] = repeatValue;
}
if (((byte) mSettings & BluetoothAvrcpPlayerSettings.SETTING_SHUFFLE) != 0) {
int shuffleValue = ps.getSettingValue(BluetoothAvrcpPlayerSettings.SETTING_SHUFFLE);
Log.d(TAG, "SHUFFLE value: " + shuffleValue);
switch (shuffleValue) {
case BluetoothAvrcpPlayerSettings.STATE_OFF:
imgShuffle.setImageResource(R.drawable.avrcp_setting_shuffle_off);
break;
case BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK:
imgShuffle.setImageResource(R.drawable.avrcp_setting_shuffle);
break;
case BluetoothAvrcpPlayerSettings.STATE_GROUP:
break;
default:
return;
}
current_avrcp_setting_value[2] = shuffleValue;
}
if (((byte) mSettings & BluetoothAvrcpPlayerSettings.SETTING_SCAN) != 0) {
int scanValue = ps.getSettingValue(BluetoothAvrcpPlayerSettings.SETTING_SHUFFLE);
Log.d(TAG, "SCAN value: " + scanValue);
switch (scanValue) {
case BluetoothAvrcpPlayerSettings.STATE_OFF:
break;
case BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK:
break;
case BluetoothAvrcpPlayerSettings.STATE_GROUP:
break;
default:
return;
}
current_avrcp_setting_value[3] = scanValue;
}
}
}
```