summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnubhavGupta <anubhavg@codeaurora.org>2015-03-04 18:10:35 +0530
committerAnubhavGupta <anubhavg@codeaurora.org>2015-08-13 20:05:39 +0530
commit08811c6a23e3137ba00ef2df4432f7a110ff6933 (patch)
tree76a801e8b16ea7731fb87cbae6b21a6f85a09126
parentfbec7160bd960dc9a98c2b924554710d3f77a411 (diff)
downloadandroid_packages_apps_BluetoothExt-08811c6a23e3137ba00ef2df4432f7a110ff6933.tar.gz
android_packages_apps_BluetoothExt-08811c6a23e3137ba00ef2df4432f7a110ff6933.tar.bz2
android_packages_apps_BluetoothExt-08811c6a23e3137ba00ef2df4432f7a110ff6933.zip
Bluetooth: Test Changes for AVRCP Controller
- Fetch changes from ContentProvider - Dispaly MetaData on UI - Support for Press and Hold Command Change-Id: I2329bfa1e080b616f64d59779917db0e89ec34dc Bluetooth: Register observer before calling getMetaData Scenario: In pause/stop state, once we kill avrcptestactivity and start it again, on pressing ON button metadata is not updated Problem: Registration for obeserver was done after calling getMetaData. By the time observer is registered notification was already triggered. Thus metadata update was missed. Change-Id: I6a2244b6f65d20f3f208581cae9a02cfa004ad16 Solution: register observer before calling getMetaData
-rw-r--r--bttestapp/AndroidManifest.xml1
-rw-r--r--bttestapp/res/layout/activity_avrcp_test.xml314
-rw-r--r--bttestapp/res/values/strings.xml27
-rw-r--r--bttestapp/src/org/codeaurora/bluetooth/bttestapp/AvrcpTestActivity.java808
4 files changed, 1061 insertions, 89 deletions
diff --git a/bttestapp/AndroidManifest.xml b/bttestapp/AndroidManifest.xml
index cc5a71a..f9fc12b 100644
--- a/bttestapp/AndroidManifest.xml
+++ b/bttestapp/AndroidManifest.xml
@@ -9,6 +9,7 @@
<uses-permission android:name="android.permission.BLUETOOTH_STACK" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.RECEIVE_BLUETOOTH_MAP" />
+ <uses-permission android:name="android.permission.ACCESS_BLUETOOTH_AVRCP_CT_DATA" />
<uses-sdk
android:minSdkVersion="17"
diff --git a/bttestapp/res/layout/activity_avrcp_test.xml b/bttestapp/res/layout/activity_avrcp_test.xml
index e203437..e5b1f59 100644
--- a/bttestapp/res/layout/activity_avrcp_test.xml
+++ b/bttestapp/res/layout/activity_avrcp_test.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,66 +28,262 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="horizontal"
android:layout_margin="5dip"
- android:baselineAligned="false">
-
- <Button
- android:id="@+id/onClickPassthruStop"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:text="@string/passthru_stop"
- android:layout_marginBottom="15dp"
- android:layout_marginRight="15dp"
- android:onClick="onClickPassthruStop" />
-
- <Button
- android:id="@+id/onClickPassthruPause"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_toLeftOf="@id/onClickPassthruStop"
- android:text="@string/passthru_pause"
- android:layout_marginBottom="15dp"
- android:layout_marginRight="15dp"
- android:onClick="onClickPassthruPause" />
-
- <Button
- android:id="@+id/onClickPassthruPlay"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_toLeftOf="@id/onClickPassthruPause"
- android:text="@string/passthru_play"
- android:layout_marginBottom="15dp"
- android:layout_marginRight="15dp"
- android:onClick="onClickPassthruPlay" />
-
- <Button
- android:id="@+id/onClickPassthruVolDown"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:text="@string/passthru_vol_down"
- android:layout_marginBottom="15dp"
- android:layout_marginRight="15dp"
- android:onClick="onClickPassthruVolDown" />
-
- <Button
- android:id="@+id/onClickPassthruVolUp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_toLeftOf="@id/onClickPassthruVolDown"
- android:text="@string/passthru_vol_up"
- android:layout_marginBottom="15dp"
- android:layout_marginRight="15dp"
- android:onClick="onClickPassthruVolUp" />
+ android:baselineAligned="false"
+ android:orientation="vertical" >
-</LinearLayout>
+ <TableLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <TableRow
+ android:id="@+id/tableRow1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" >
+
+ <Button
+ android:id="@+id/onClickPassthruPause"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="onClickPassthruPause"
+ android:text="@string/passthru_pause" />
+
+ <Button
+ android:id="@+id/onClickPassthruStop"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="onClickPassthruStop"
+ android:text="@string/passthru_stop" />
+
+ <Button
+ android:id="@+id/onClickPassthruPlay"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="onClickPassthruPlay"
+ android:text="@string/passthru_play" />
+
+ <Button
+ android:id="@+id/onClickPassthruForward"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="onClickPassthruForward"
+ android:text="@string/passthru_forward" />
+
+ <Button
+ android:id="@+id/onClickPassthruBackward"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="onClickPassthruBackward"
+ android:text="@string/passthru_backward" />
+
+ <Button
+ android:id="@+id/onClickPassthruVolUp"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="onClickPassthruVolUp"
+ android:text="@string/passthru_volup" />
+
+ </TableRow>
+
+ <TableRow
+ android:id="@+id/tableRow2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" >
+
+ <Button
+ android:id="@+id/onClickPassthruRewind"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/passthru_rewind" />
+
+ <Button
+ android:id="@+id/onClickPassthruFF"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/passthru_ff" />
+
+ <Button
+ android:id="@+id/onClickToggleRepeat"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="onClickToggleRepeat"
+ android:text="@string/toggle_repeat" />
+
+ <Button
+ android:id="@+id/onClickToggleShuffle"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="onClickToggleShuffle"
+ android:text="@string/toggle_shuffle" />
+
+ <Button
+ android:id="@+id/onClickToggleScan"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="onClickToggleScan"
+ android:text="@string/toggle_scan" />
+
+ <Button
+ android:id="@+id/onClickToggleEq"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="onClickToggleEq"
+ android:text="@string/toggle_eq" />
+
+ <Button
+ android:id="@+id/onClickPassthruVolDown"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="onClickPassthruVolDown"
+ android:text="@string/passthru_voldown" />
+ </TableRow>
+
+ <TableRow
+ android:id="@+id/tableRow3"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" >
+
+ <TextView
+ android:id="@+id/shuffle_status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/shuffle_status_default"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ </TableRow>
+
+ <TableRow
+ android:id="@+id/tableRow4"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" >
+
+ <TextView
+ android:id="@+id/repeat_status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/repeat_status_default"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+ </TableRow>
+ </TableLayout>
+ <TableLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="0.21" >
+
+ <TableRow
+ android:id="@+id/tableRow5"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" >
+
+ <TextView
+ android:id="@+id/album_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/album_name_default"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ </TableRow>
+
+ <TableRow
+ android:id="@+id/tableRow6"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" >
+
+ <TextView
+ android:id="@+id/artist_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/artist_name_default"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ </TableRow>
+
+ <TableRow
+ android:id="@+id/tableRow7"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" >
+
+ <TextView
+ android:id="@+id/genre_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/genre_name_default"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ </TableRow>
+
+ <TableRow
+ android:id="@+id/tableRow8"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" >
+
+ <TextView
+ android:id="@+id/scan_status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/scan_status_default"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ </TableRow>
+
+ <TextView
+ android:id="@+id/playing_time"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/playing_time_default"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/equalizer_status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/equalizer_status_default"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/track_number"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/track_number_default"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/title_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/title_name_default"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/play_status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/play_status_default"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <ToggleButton
+ android:id="@+id/toggleButton1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:onClick="onCTStartToggleClicked" />
+
+ </TableLayout>
+
+</LinearLayout>
diff --git a/bttestapp/res/values/strings.xml b/bttestapp/res/values/strings.xml
index 6b5ae7a..73ea04e 100644
--- a/bttestapp/res/values/strings.xml
+++ b/bttestapp/res/values/strings.xml
@@ -1,6 +1,6 @@
<!--
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013,2015, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -335,6 +335,27 @@
<string name="passthru_play">PLAY</string>
<string name="passthru_pause">PAUSE</string>
<string name="passthru_stop">STOP</string>
- <string name="passthru_vol_up">VOLUP</string>
- <string name="passthru_vol_down">VOLDOWN</string>
+ <string name="passthru_ff">FF</string>
+ <string name="passthru_rewind">RW</string>
+ <string name="passthru_forward">NEXT_TR</string>
+ <string name="passthru_backward">PREV_TR</string>
+ <string name="passthru_volup">VOL_UP</string>
+ <string name="passthru_voldown">VOL_DOWN</string>
+ <string name="track_number_default">NO_TRACK</string>
+ <string name="title_name_default">NO_TITLE</string>
+ <string name="artist_name_default">NO_ARTIST</string>
+ <string name="album_name_default">NO_ALBUM</string>
+ <string name="total_tracks_default">UNKNOWN</string>
+ <string name="genre_name_default">NO_GENRE</string>
+ <string name="playing_time_default">NO_TIME</string>
+ <string name="total_track_time_default">UNKNOWN</string>
+ <string name="play_status_default">STOPPED</string>
+ <string name="shuffle_status_default">SHUFFLE_OFF</string>
+ <string name="repeat_status_default">REPEAT_OFF</string>
+ <string name="scan_status_default">SCAN_OFF</string>
+ <string name="equalizer_status_default">EQUALIZER_OFF</string>
+ <string name="toggle_repeat">REP</string>
+ <string name="toggle_shuffle">SHUF</string>
+ <string name="toggle_scan">SCAN</string>
+ <string name="toggle_eq">EQ</string>
</resources>
diff --git a/bttestapp/src/org/codeaurora/bluetooth/bttestapp/AvrcpTestActivity.java b/bttestapp/src/org/codeaurora/bluetooth/bttestapp/AvrcpTestActivity.java
index 1f19f0c..fe1ef2c 100644
--- a/bttestapp/src/org/codeaurora/bluetooth/bttestapp/AvrcpTestActivity.java
+++ b/bttestapp/src/org/codeaurora/bluetooth/bttestapp/AvrcpTestActivity.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -33,6 +33,7 @@ import android.app.ActionBar;
import android.app.DialogFragment;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothAvrcpController;
+import android.bluetooth.BluetoothAvrcpInfo;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -41,26 +42,63 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
+import android.os.HandlerThread;
import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.SystemProperties;
+import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.widget.Button;
import android.widget.Toast;
+import android.widget.ToggleButton;
import android.view.View;
+import android.view.View.OnTouchListener;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.content.ContentResolver;
+import android.os.Handler;
+import android.os.Process;
+import android.net.Uri;
+import android.widget.TextView;
+import android.app.Activity;
+import java.util.concurrent.TimeUnit;
import org.codeaurora.bluetooth.bttestapp.R;
import org.codeaurora.bluetooth.bttestapp.util.Logger;
import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.locks.ReentrantLock;
+import android.database.CursorIndexOutOfBoundsException;
+import android.database.sqlite.SQLiteCantOpenDatabaseException;
+import android.database.sqlite.SQLiteException;
public class AvrcpTestActivity extends MonkeyActivity implements IBluetoothConnectionObserver {
private final String TAG = "AvrcpTestActivity";
+ private boolean ffPressed = false;
private ActionBar mActionBar = null;
-
+ private UpdateThread mUpdateThread;
+ private PressandHoldHandler mPressandHoldHandler;
+ private View appView;
+ private Activity mLocalActivity;
+ private final ReentrantLock mLock = new ReentrantLock();
BluetoothAvrcpController mAvrcpController;
ProfileService mProfileService = null;
BluetoothDevice mDevice;
+ BluetoothAvrcpShareContentObserver mAvrcpDataObserver = null;
+ private class PlayerSettings
+ {
+ public byte attr_Id;
+ public byte attr_val;
+ public byte [] supported_values; // app shld check these values before Setting Player Attributes.
+ };
+ ArrayList<PlayerSettings> plSetting= null;
+ int remoteSupportedFeatures = 0;
public static final int KEY_STATE_PRESSED = 0;
public static final int KEY_STATE_RELEASED = 1;
public static final int AVRC_ID_PLAY = 0x44;
@@ -68,6 +106,39 @@ public class AvrcpTestActivity extends MonkeyActivity implements IBluetoothConne
public static final int AVRC_ID_VOL_UP = 0x41;
public static final int AVRC_ID_VOL_DOWN = 0x42;
public static final int AVRC_ID_STOP = 0x45;
+ public static final int AVRC_ID_FF = 0x49;
+ public static final int AVRC_ID_REWIND = 0x48;
+ public static final int AVRC_ID_FORWARD = 0x4B;
+ public static final int AVRC_ID_BACKWARD = 0x4C;
+
+ public static final int SEND_PASS_THROUGH_CMD = 1;
+
+ private TextView mRepeatStatus;
+ private TextView mShuffleStatus;
+ private TextView mGenreStatus;
+ private TextView mArtistName;
+ private TextView mAlbumName;
+ private TextView mPlayTime;
+ private TextView mScanStatus;
+ private TextView mPlayStatus;
+ private TextView mEqualizerStatus;
+ private TextView mTrackNumber;
+ private TextView mTitleName;
+ private ToggleButton mCTStartButton;
+ private Button ffButton;
+ private Button rwButton;
+
+ private String repeatText;
+ private String shuffleText;
+ private String genreText;
+ private String artistText;
+ private String albumText;
+ private String playText;
+ private String scanText;
+ private String playStatusText;
+ private String equalizerText;
+ private String trackNumText;
+ private String titleNameText;
private final BroadcastReceiver mAvrcpControllerReceiver = new BroadcastReceiver() {
@Override
@@ -89,9 +160,306 @@ public class AvrcpTestActivity extends MonkeyActivity implements IBluetoothConne
device.getAddress() + " (" +
String.valueOf(prevState) + " -> " +
String.valueOf(state) + ")");
+ if (state == BluetoothProfile.STATE_DISCONNECTED) {
+ if (device.equals(mDevice))
+ mDevice = null;
+ if (plSetting != null)
+ plSetting.clear();
+ remoteSupportedFeatures = 0;
+ unregisterMetaDataObserver();
+ resetDisplay();
+ mCTStartButton.setChecked(false);
+ Toast.makeText(mLocalActivity, "Device " + device + " AVRCP Disconnected", Toast.LENGTH_SHORT).show();
+ }
+ else if(state == BluetoothProfile.STATE_CONNECTED) {
+ mDevice = device;
+ Toast.makeText(mLocalActivity, "Device " + device + " AVRCP Connected", Toast.LENGTH_SHORT).show();
+ }
+ }
+ };
+ private View.OnTouchListener onTouchListenerRW = new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent me) {
+ v.onTouchEvent(me);
+ Log.d(TAG," onTouch for RW " + me.getAction());
+ if (me.getAction() == MotionEvent.ACTION_UP){
+ if ((mAvrcpController != null) && mDevice != null &&
+ BluetoothProfile.STATE_DISCONNECTED != (mAvrcpController.getConnectionState(mDevice))){
+ //mAvrcpController.sendPassThroughCmd(mDevice, AVRC_ID_REWIND, KEY_STATE_RELEASED);
+ if (mPressandHoldHandler != null)
+ mPressandHoldHandler.sendMessageAtFrontOfQueue(mPressandHoldHandler.obtainMessage(SEND_PASS_THROUGH_CMD,AVRC_ID_REWIND,KEY_STATE_RELEASED));
+ } else {
+ Logger.e(TAG, "passthru command not sent, connection unavailable");
+ }
+ }
+ else if (me.getAction() == MotionEvent.ACTION_DOWN) {
+ if ((mAvrcpController != null) && mDevice != null &&
+ BluetoothProfile.STATE_DISCONNECTED != (mAvrcpController.getConnectionState(mDevice))){
+ //mAvrcpController.sendPassThroughCmd(mDevice, AVRC_ID_REWIND, KEY_STATE_PRESSED);
+ if ((mPressandHoldHandler != null)&&(!mPressandHoldHandler.hasMessages(SEND_PASS_THROUGH_CMD)))
+ mPressandHoldHandler.sendMessage(mPressandHoldHandler.obtainMessage(SEND_PASS_THROUGH_CMD,AVRC_ID_REWIND,KEY_STATE_PRESSED));
+ } else {
+ Logger.e(TAG, "passthru command not sent, connection unavailable");
+ }
+ }
+ return true;
}
};
+ private View.OnTouchListener onTouchListenerFF = new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent me) {
+ v.onTouchEvent(me);
+ Log.d(TAG," onTouch for FF " + me.getAction());
+ if (me.getAction() == MotionEvent.ACTION_UP){
+ if ((mAvrcpController != null) && mDevice != null &&
+ BluetoothProfile.STATE_DISCONNECTED != (mAvrcpController.getConnectionState(mDevice))){
+ //mAvrcpController.sendPassThroughCmd(mDevice, AVRC_ID_FF, KEY_STATE_RELEASED);
+ if (mPressandHoldHandler != null)
+ mPressandHoldHandler.sendMessageAtFrontOfQueue(mPressandHoldHandler.obtainMessage(SEND_PASS_THROUGH_CMD,AVRC_ID_FF,KEY_STATE_RELEASED));
+ } else {
+ Logger.e(TAG, "passthru command not sent, connection unavailable");
+ }
+ }
+ else if (me.getAction() == MotionEvent.ACTION_DOWN) {
+ if ((mAvrcpController != null) && mDevice != null &&
+ BluetoothProfile.STATE_DISCONNECTED != (mAvrcpController.getConnectionState(mDevice))){
+ if ((mPressandHoldHandler != null)&&(!mPressandHoldHandler.hasMessages(SEND_PASS_THROUGH_CMD)))
+ mPressandHoldHandler.sendMessage(mPressandHoldHandler.obtainMessage(SEND_PASS_THROUGH_CMD,AVRC_ID_FF,KEY_STATE_PRESSED));
+ //mAvrcpController.sendPassThroughCmd(mDevice, AVRC_ID_FF, KEY_STATE_PRESSED);
+ } else {
+ Logger.e(TAG, "passthru command not sent, connection unavailable");
+ }
+ }
+ return true;
+ }
+ };
+ private final class PressandHoldHandler extends Handler {
+ private PressandHoldHandler(Looper looper) {
+ super(looper);
+ }
+ @Override
+ public void handleMessage(Message msg) {
+ Log.d(TAG," Recvd Msg " + msg.what);
+ int keyState = msg.arg2;
+ int keyCode = msg.arg1;
+ switch(msg.what) {
+ case SEND_PASS_THROUGH_CMD:
+ if (keyState == KEY_STATE_PRESSED) {
+ Message msgsend = mPressandHoldHandler.obtainMessage(SEND_PASS_THROUGH_CMD, keyCode, keyState);
+ mPressandHoldHandler.sendMessageDelayed(msgsend, 1000);
+ if ((mAvrcpController != null) && mDevice != null &&
+ BluetoothProfile.STATE_DISCONNECTED != (mAvrcpController.getConnectionState(mDevice))){
+ mAvrcpController.sendPassThroughCmd(mDevice, keyCode, keyState);
+ }
+ }
+ else if(keyState == KEY_STATE_RELEASED) {
+ if (mPressandHoldHandler.hasMessages(SEND_PASS_THROUGH_CMD))
+ mPressandHoldHandler.removeMessages(SEND_PASS_THROUGH_CMD);
+ if ((mAvrcpController != null) && mDevice != null &&
+ BluetoothProfile.STATE_DISCONNECTED != (mAvrcpController.getConnectionState(mDevice))){
+ mAvrcpController.sendPassThroughCmd(mDevice, keyCode, keyState);
+ }
+ }
+ break;
+ }
+ }
+ }
+ private class BluetoothAvrcpShareContentObserver extends ContentObserver {
+ public BluetoothAvrcpShareContentObserver() {
+ super(new Handler());
+ }
+ @Override
+ public void onChange(boolean selfChange) {
+ updateFromAvrcpContentProvider();
+ }
+ };
+ private void updateFromAvrcpContentProvider() {
+ Logger.e(TAG," AVRCP DB updated");
+ if (mUpdateThread == null)
+ {
+ Logger.e(TAG, "Starting a new Thread ");
+ mUpdateThread = new UpdateThread();
+ mUpdateThread.start();
+ }
+ }
+ private class UpdateThread extends Thread {
+ public UpdateThread() {
+ super(" BT_TESTAPP AVRCP UpdateThread");
+ }
+ @Override
+ public void run() {
+ Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+ Uri avrcpDataUri = BluetoothAvrcpInfo.CONTENT_URI;
+ String[] mSelectionArgs = {""}; mSelectionArgs[0] = "";
+ Cursor cursor = getContentResolver().query(avrcpDataUri, null, null, null,
+ BluetoothAvrcpInfo._ID);
+
+ if (cursor != null) {
+ int num_rows = cursor.getCount();
+ int index;
+ cursor.moveToFirst();
+ int num_colums = cursor.getColumnCount();
+ Logger.e(TAG," number of rows " + num_rows + " num Col " + num_colums);
+ mLock.lock();
+ try {
+ while(num_colums > 0){
+ switch(num_colums) {
+ case 1: // Track Num
+ index = cursor.getColumnIndex(BluetoothAvrcpInfo.TRACK_NUM);
+ if (index == -1)
+ break;
+ int track_num = cursor.getInt(index);
+ if (track_num == BluetoothAvrcpInfo.TRACK_NUM_INVALID) {
+ trackNumText = "NOT_SUP";
+ break;
+ }
+ StringBuffer str = new StringBuffer();
+ str.append(String.valueOf(track_num));
+ index = cursor.getColumnIndex(BluetoothAvrcpInfo.TOTAL_TRACKS);
+ if (index > 0) {
+ str.append(" | ");
+ str.append(String.valueOf(cursor.getInt(index)));
+ }
+ trackNumText = str.toString();
+ Logger.e(TAG, " Number of Tracks " + trackNumText);
+ break;
+ case 2: // TRACK Title
+ index = cursor.getColumnIndex(BluetoothAvrcpInfo.TITLE);
+ if (index == -1)
+ break;
+ titleNameText = cursor.getString(index);
+ Logger.e(TAG, " Track Title " + titleNameText);
+ break;
+ case 3: // Artist Name
+ index = cursor.getColumnIndex(BluetoothAvrcpInfo.ARTIST_NAME);
+ if (index == -1)
+ break;
+ artistText = cursor.getString(index);
+ Logger.e(TAG, " Artist Name " + artistText);
+ break;
+ case 4: // Album Name
+ index = cursor.getColumnIndex(BluetoothAvrcpInfo.ALBUM_NAME);
+ if (index == -1)
+ break;
+ albumText = cursor.getString(index);
+ Logger.e(TAG, " album_name " + albumText);
+ break;
+ case 5: // play time
+ index = cursor.getColumnIndex(BluetoothAvrcpInfo.PLAYING_TIME);
+ if (index == -1)
+ break;
+ long playing_time = cursor.getLong(index);
+ long minutes = TimeUnit.MILLISECONDS.toMinutes(playing_time);
+ playing_time = playing_time - (60*minutes*1000);
+ long seconds = TimeUnit.MILLISECONDS.toSeconds(playing_time);
+ StringBuffer strPlayTime = new StringBuffer();
+ strPlayTime.append(String.valueOf(minutes));
+ strPlayTime.append(":");
+ strPlayTime.append(String.valueOf(seconds));
+ index = cursor.getColumnIndex(BluetoothAvrcpInfo.TOTAL_TRACK_TIME);
+ if (index > 0) {
+ strPlayTime.append(" | ");
+ long totalTrackTime = cursor.getLong(index);
+ minutes = TimeUnit.MILLISECONDS.toMinutes(totalTrackTime);
+ totalTrackTime = totalTrackTime - (60*minutes*1000);
+ seconds = TimeUnit.MILLISECONDS.toSeconds(totalTrackTime);
+ strPlayTime.append(String.valueOf(minutes));
+ strPlayTime.append(":");
+ strPlayTime.append(String.valueOf(seconds));
+ }
+ playText = strPlayTime.toString();
+ Logger.e(TAG, " playing_time " + playText);
+ break;
+ case 6: //Genre
+ index = cursor.getColumnIndex(BluetoothAvrcpInfo.GENRE);
+ if (index == -1)
+ break;
+ genreText = cursor.getString(index);
+ Logger.e(TAG, " genre " + genreText);
+ break;
+ case 7:// play Status
+ index = cursor.getColumnIndex(BluetoothAvrcpInfo.PLAY_STATUS);
+ if (index == -1)
+ break;
+ playStatusText = cursor.getString(index);
+ Logger.e(TAG, " playStatus " + playStatusText);
+ break;
+ case 8:// Repeat Status
+ index = cursor.getColumnIndex(BluetoothAvrcpInfo.REPEAT_STATUS);
+ if (index == -1)
+ break;
+ repeatText = cursor.getString(index);
+ Logger.e(TAG, " repetStatus " + repeatText);
+ break;
+ case 9:// ShuffleStatus
+ index = cursor.getColumnIndex(BluetoothAvrcpInfo.SHUFFLE_STATUS);
+ if (index == -1)
+ break;
+ shuffleText = cursor.getString(index);
+ Logger.e(TAG, " ShuffleStatus " + shuffleText);
+ break;
+ case 10:// Scan Status
+ index = cursor.getColumnIndex(BluetoothAvrcpInfo.SCAN_STATUS);
+ if (index == -1)
+ break;
+ scanText = cursor.getString(index);
+ Logger.e(TAG, " Scan Status " + scanText);
+ break;
+ case 11:// Eq Status
+ index = cursor.getColumnIndex(BluetoothAvrcpInfo.EQUALIZER_STATUS);
+ if (index == -1)
+ break;
+ equalizerText = cursor.getString(index);
+ Logger.e(TAG, " Equalizer Status " + equalizerText);
+ break;
+ }
+ num_colums --;
+ }
+ } // try end
+ catch(CursorIndexOutOfBoundsException e) {
+ Log.d(TAG," CursorIndexOutOfBoundsException happended");
+ }
+ catch(SQLiteCantOpenDatabaseException e) {
+ Log.d(TAG," SQLiteCantOpenDatabaseException happended");
+ }
+ catch(SQLiteException e) {
+ Log.d(TAG," SQLiteException happended");
+ }
+ finally {
+ if(cursor != null)
+ cursor.close();
+ mLock.unlock();
+ }
+ }
+ else {
+ Logger.v(TAG," Cursor is NULL");
+ }
+ mLocalActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mLock.lock();
+ try {
+ mTrackNumber.setText(trackNumText);
+ mTitleName.setText(titleNameText);
+ mEqualizerStatus.setText(equalizerText);
+ mArtistName.setText(artistText);
+ mScanStatus.setText(scanText);
+ mShuffleStatus.setText(shuffleText);
+ mRepeatStatus.setText(repeatText);
+ mPlayStatus.setText(playStatusText);
+ mGenreStatus.setText(genreText);
+ mPlayTime.setText(playText);
+ mAlbumName.setText(albumText);
+ }
+ finally {
+ mLock.unlock();
+ }
+ }
+ });
+ mUpdateThread = null;
+ }
+ }
private final ServiceConnection mAvrcpControllerServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
@@ -105,6 +473,13 @@ public class AvrcpTestActivity extends MonkeyActivity implements IBluetoothConne
Logger.v(TAG, "onServiceDisconnected()");
mProfileService = null;
mAvrcpController = null;
+ mDevice = null;
+ remoteSupportedFeatures = 0;
+ if (plSetting != null)
+ plSetting.clear();
+ unregisterMetaDataObserver();
+ resetDisplay();
+ mCTStartButton.setChecked(false);
}
};
@@ -116,32 +491,48 @@ public class AvrcpTestActivity extends MonkeyActivity implements IBluetoothConne
ActivityHelper.initialize(this, R.layout.activity_avrcp_test);
BluetoothConnectionReceiver.registerObserver(this);
ActivityHelper.setActionBarTitle(this, R.string.title_avrcp_test);
+ mLocalActivity = this;
+ initializeViewFragments();
// bind to app service
+ HandlerThread thread = new HandlerThread("BT-TestAppPressandHoldHandler");
+ thread.start();
+ Looper looper = thread.getLooper();
+ mPressandHoldHandler = new PressandHoldHandler(looper);
Intent intent = new Intent(this, ProfileService.class);
bindService(intent, mAvrcpControllerServiceConnection, BIND_AUTO_CREATE);
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED);
+ registerReceiver(mAvrcpControllerReceiver, filter);
}
@Override
protected void onDestroy() {
Logger.v(TAG, "onDestroy");
- super.onDestroy();
+ mDevice = null;
+ remoteSupportedFeatures = 0;
+ if (plSetting != null)
+ plSetting.clear();
+ unregisterMetaDataObserver();
+ unregisterReceiver(mAvrcpControllerReceiver);
unbindService(mAvrcpControllerServiceConnection);
BluetoothConnectionReceiver.removeObserver(this);
+ mPressandHoldHandler.removeCallbacksAndMessages(null);
+ Looper looper = mPressandHoldHandler.getLooper();
+ if (looper != null) {
+ looper.quit();
+ }
+ super.onDestroy();
}
@Override
protected void onResume() {
Logger.v(TAG, "onResume");
- IntentFilter filter = new IntentFilter();
- filter.addAction(BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED);
- registerReceiver(mAvrcpControllerReceiver, filter);
super.onResume();
}
@Override
protected void onPause() {
Logger.v(TAG, "onPause");
- unregisterReceiver(mAvrcpControllerReceiver);
super.onPause();
}
@@ -153,13 +544,15 @@ public class AvrcpTestActivity extends MonkeyActivity implements IBluetoothConne
@Override
public void onDeviceChanged(BluetoothDevice device) {
- Logger.v(TAG, "onDeviceChanged()");
+ Logger.v(TAG, "onDeviceChanged() BD = "+ device.getAddress());
mDevice = device;
}
@Override
public void onDeviceDisconected() {
Logger.v(TAG, "onDeviceDisconected");
+ mDevice = null;
+ remoteSupportedFeatures = 0;
}
private void prepareActionBar() {
@@ -171,7 +564,34 @@ public class AvrcpTestActivity extends MonkeyActivity implements IBluetoothConne
mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
}
}
-
+ public boolean isDeviceConnected() {
+ return ((mAvrcpController != null) && mDevice != null &&
+ BluetoothProfile.STATE_DISCONNECTED != (mAvrcpController.getConnectionState(mDevice)));
+ }
+ public void registerMetaDataObserver() {
+ if(!isDeviceConnected()) {
+ Logger.e(TAG," Device not Connected");
+ return;
+ }
+ if ((remoteSupportedFeatures & BluetoothAvrcpInfo.BTRC_FEAT_METADATA) == 0) {
+ Logger.e(TAG," Device does not support MetaData");
+ return;
+ }
+ /* check if DataObserver is already registered */
+ if (mAvrcpDataObserver != null)
+ return;
+ Uri avrcpDataUri = BluetoothAvrcpInfo.CONTENT_URI;
+ mAvrcpDataObserver = new BluetoothAvrcpShareContentObserver();
+ getContentResolver().registerContentObserver(avrcpDataUri, true, mAvrcpDataObserver);
+ Logger.v(TAG," Registered Content Observer");
+ }
+ public void unregisterMetaDataObserver() {
+ Logger.d(TAG," unregisterMetaDataObserver");
+ if (mAvrcpDataObserver == null)
+ return;
+ getContentResolver().unregisterContentObserver(mAvrcpDataObserver);
+ mAvrcpDataObserver = null;
+ }
public void onClickPassthruPlay(View v) {
Logger.v(TAG, "onClickPassthruPlay()");
if ((mAvrcpController != null) && mDevice != null &&
@@ -182,6 +602,250 @@ public class AvrcpTestActivity extends MonkeyActivity implements IBluetoothConne
Logger.e(TAG, "passthru command not sent, connection unavailable");
}
}
+ public void onClickPassthruVolUp(View v) {
+ Logger.v(TAG, "onClickPassthruVolUp()");
+ boolean isA2dpSinkEnabled = SystemProperties.getBoolean("persist.service.bt.a2dp.sink", false);
+ if (isA2dpSinkEnabled) {
+ Logger.v(TAG, "Sink Enabled, not sending VOL UP ");
+ return;
+ }
+ if ((mAvrcpController != null) && mDevice != null &&
+ BluetoothProfile.STATE_DISCONNECTED != (mAvrcpController.getConnectionState(mDevice))){
+ mAvrcpController.sendPassThroughCmd(mDevice, AVRC_ID_VOL_UP, KEY_STATE_PRESSED);
+ mAvrcpController.sendPassThroughCmd(mDevice, AVRC_ID_VOL_UP, KEY_STATE_RELEASED);
+ } else {
+ Logger.e(TAG, "passthru command not sent, connection unavailable");
+ }
+ }
+ public void onClickPassthruVolDown(View v) {
+ Logger.v(TAG, "onClickPassthruVolDown()");
+ boolean isA2dpSinkEnabled = SystemProperties.getBoolean("persist.service.bt.a2dp.sink", false);
+ if (isA2dpSinkEnabled) {
+ Logger.v(TAG, "Sink Enabled, not sending VOL DOWN ");
+ return;
+ }
+ if ((mAvrcpController != null) && mDevice != null &&
+ BluetoothProfile.STATE_DISCONNECTED != (mAvrcpController.getConnectionState(mDevice))){
+ mAvrcpController.sendPassThroughCmd(mDevice, AVRC_ID_VOL_DOWN, KEY_STATE_PRESSED);
+ mAvrcpController.sendPassThroughCmd(mDevice, AVRC_ID_VOL_DOWN, KEY_STATE_RELEASED);
+ } else {
+ Logger.e(TAG, "passthru command not sent, connection unavailable");
+ }
+ }
+ public void onClickPassthruForward(View v) {
+ Logger.v(TAG, "onClickPassthruForward()");
+ if ((mAvrcpController != null) && mDevice != null &&
+ BluetoothProfile.STATE_DISCONNECTED != (mAvrcpController.getConnectionState(mDevice))){
+ mAvrcpController.sendPassThroughCmd(mDevice, AVRC_ID_FORWARD, KEY_STATE_PRESSED);
+ mAvrcpController.sendPassThroughCmd(mDevice, AVRC_ID_FORWARD, KEY_STATE_RELEASED);
+ } else {
+ Logger.e(TAG, "passthru command not sent, connection unavailable");
+ }
+ }
+ public void onClickPassthruBackward(View v) {
+ Logger.v(TAG, "onClickPassthruBackward()");
+ if ((mAvrcpController != null) && mDevice != null &&
+ BluetoothProfile.STATE_DISCONNECTED != (mAvrcpController.getConnectionState(mDevice))){
+ mAvrcpController.sendPassThroughCmd(mDevice, AVRC_ID_BACKWARD, KEY_STATE_PRESSED);
+ mAvrcpController.sendPassThroughCmd(mDevice, AVRC_ID_BACKWARD, KEY_STATE_RELEASED);
+ } else {
+ Logger.e(TAG, "passthru command not sent, connection unavailable");
+ }
+ }
+ public void onClickToggleRepeat(View v) {
+ Logger.v(TAG, "onClickToggleRepeat()");
+ if ((mAvrcpController == null) ||
+ (mDevice == null)||
+ (BluetoothProfile.STATE_CONNECTED != (mAvrcpController.getConnectionState(mDevice)))) {
+ return;
+ }
+ if ((remoteSupportedFeatures & BluetoothAvrcpInfo.BTRC_FEAT_METADATA)==0) {
+ return;
+ }
+ if ((plSetting == null)||(plSetting.isEmpty())) {
+ BluetoothAvrcpInfo mMetaData = mAvrcpController.getSupportedPlayerAppSetting(mDevice);
+ updatePlayerSettings(mMetaData);
+ }
+
+ if ((plSetting == null)||(plSetting.isEmpty())||(repeatText == null)) {
+ Log.w(TAG," not supported, return");
+ return;
+ }
+ for (PlayerSettings sett: plSetting) {
+ Log.d(TAG," finding the current value " + sett.attr_Id);
+ if (sett.attr_Id == BluetoothAvrcpInfo.ATTRIB_REPEAT_STATUS) {
+ int repeat_status;
+ mLock.lock();
+ try {
+ if(repeatText.equals("REPEAT_OFF"))
+ repeat_status = BluetoothAvrcpInfo.REPEAT_STATUS_OFF;
+ else if (repeatText.equals("REPEAT_SINGLE_TRACK_REPEAT"))
+ repeat_status = BluetoothAvrcpInfo.REPEAT_STATUS_SINGLE_TRACK_REPEAT;
+ else if (repeatText.equals("REPEAT_GROUP_REPEAT"))
+ repeat_status = BluetoothAvrcpInfo.REPEAT_STATUS_GROUP_REPEAT;
+ else if (repeatText.equals("REPEAT_ALL_TRACK_REPEAT"))
+ repeat_status = BluetoothAvrcpInfo.REPEAT_STATUS_ALL_TRACK_REPEAT;
+ else {
+ Log.d(TAG," Repeat not supported ");
+ return;
+ }
+ }
+ finally {
+ mLock.unlock();
+ }
+ for (int zz = 0; zz < sett.supported_values.length; zz++) {
+ if (repeat_status == sett.supported_values[zz]) {
+ repeat_status = sett.supported_values[(zz + 1)%sett.supported_values.length];
+ break;
+ }
+ }
+ mAvrcpController.setPlayerApplicationSetting(sett.attr_Id, repeat_status);
+ break;
+ }
+ }
+ }
+ public void onClickToggleEq(View v) {
+ Logger.v(TAG, "onClickToggleEq()");
+ if ((mAvrcpController == null) ||
+ (mDevice == null)||
+ (BluetoothProfile.STATE_CONNECTED != (mAvrcpController.getConnectionState(mDevice)))) {
+ return;
+ }
+ if ((remoteSupportedFeatures & BluetoothAvrcpInfo.BTRC_FEAT_METADATA)==0) {
+ return;
+ }
+ if ((plSetting == null)||(plSetting.isEmpty())) {
+ BluetoothAvrcpInfo mMetaData = mAvrcpController.getSupportedPlayerAppSetting(mDevice);
+ updatePlayerSettings(mMetaData);
+ }
+ if ((plSetting == null)||(plSetting.isEmpty())||(equalizerText == null)) {
+ Log.w(TAG," not supported, return");
+ return;
+ }
+ for (PlayerSettings sett: plSetting) {
+ if (sett.attr_Id == BluetoothAvrcpInfo.ATTRIB_EQUALIZER_STATUS) {
+ int eq_status;
+ mLock.lock();
+ try {
+ if(equalizerText.equals("EQUALIZER_OFF"))
+ eq_status = BluetoothAvrcpInfo.EQUALIZER_STATUS_OFF;
+ else if (equalizerText.equals("EQUALIZER_ON"))
+ eq_status = BluetoothAvrcpInfo.EQUALIZER_STATUS_ON;
+ else {
+ Log.d(TAG," Equalizer not supported ");
+ return;
+ }
+ }
+ finally {
+ mLock.unlock();
+ }
+ for (int zz = 0; zz < sett.supported_values.length; zz ++) {
+ if (eq_status == sett.supported_values[zz]) {
+ eq_status = sett.supported_values[(zz + 1)%sett.supported_values.length];
+ break;
+ }
+ }
+ mAvrcpController.setPlayerApplicationSetting(sett.attr_Id, eq_status);
+ break;
+ }
+ }
+ }
+ public void onClickToggleScan(View v) {
+ Logger.v(TAG, "onClickToggleScan()");
+ if ((mAvrcpController == null) ||
+ (mDevice == null)||
+ (BluetoothProfile.STATE_CONNECTED != (mAvrcpController.getConnectionState(mDevice)))) {
+ return;
+ }
+ if ((remoteSupportedFeatures & BluetoothAvrcpInfo.BTRC_FEAT_METADATA)==0) {
+ return;
+ }
+ if ((plSetting == null)||(plSetting.isEmpty())) {
+ BluetoothAvrcpInfo mMetaData = mAvrcpController.getSupportedPlayerAppSetting(mDevice);
+ updatePlayerSettings(mMetaData);
+ }
+ if ((plSetting == null)||(plSetting.isEmpty())||(scanText == null)) {
+ Log.w(TAG," not supported, return");
+ return;
+ }
+ for (PlayerSettings sett: plSetting) {
+ if (sett.attr_Id == BluetoothAvrcpInfo.ATTRIB_SCAN_STATUS) {
+ int scan_status;
+ mLock.lock();
+ try {
+ if(scanText.equals("SCAN_OFF"))
+ scan_status = BluetoothAvrcpInfo.SCAN_STATUS_OFF;
+ else if (scanText.equals("SCAN_GROUP_SCAN"))
+ scan_status = BluetoothAvrcpInfo.SCAN_STATUS_GROUP_SCAN;
+ else if (scanText.equals("SCAN_ALL_TRACK_SCAN"))
+ scan_status = BluetoothAvrcpInfo.SCAN_STATUS_ALL_TRACK_SCAN;
+ else {
+ Log.d(TAG," Scan not supported ");
+ return;
+ }
+ }
+ finally {
+ mLock.unlock();
+ }
+ for (int zz = 0; zz < sett.supported_values.length; zz ++) {
+ if (scan_status == sett.supported_values[zz]) {
+ scan_status = sett.supported_values[(zz + 1)%sett.supported_values.length];
+ break;
+ }
+ }
+ mAvrcpController.setPlayerApplicationSetting(sett.attr_Id, scan_status);
+ break;
+ }
+ }
+ }
+ public void onClickToggleShuffle(View v) {
+ Logger.v(TAG, "onClickToggleShuffle()");
+ if ((mAvrcpController == null) ||
+ (mDevice == null)||
+ (BluetoothProfile.STATE_CONNECTED != (mAvrcpController.getConnectionState(mDevice)))) {
+ return;
+ }
+ if ((remoteSupportedFeatures & BluetoothAvrcpInfo.BTRC_FEAT_METADATA)==0) {
+ return;
+ }
+ if ((plSetting == null)||(plSetting.isEmpty())) {
+ BluetoothAvrcpInfo mMetaData = mAvrcpController.getSupportedPlayerAppSetting(mDevice);
+ updatePlayerSettings(mMetaData);
+ }
+ if ((plSetting == null)||(plSetting.isEmpty())||(shuffleText == null)) {
+ Log.w(TAG," not supported, return");
+ return;
+ }
+ for (PlayerSettings sett: plSetting) {
+ if (sett.attr_Id == BluetoothAvrcpInfo.ATTRIB_SHUFFLE_STATUS) {
+ int shuffle_status;
+ mLock.lock();
+ try {
+ if(shuffleText.equals("SHUFFLE_OFF"))
+ shuffle_status = BluetoothAvrcpInfo.SHUFFLE_STATUS_OFF;
+ else if (shuffleText.equals("SHUFFLE_GROUP_SHUFFLE"))
+ shuffle_status = BluetoothAvrcpInfo.SHUFFLE_STATUS_GROUP_SHUFFLE;
+ else if (shuffleText.equals("SHUFFLE_ALL_TRACK_SHUFFLE"))
+ shuffle_status = BluetoothAvrcpInfo.SHUFFLE_STATUS_ALL_TRACK_SHUFFLE;
+ else {
+ Log.d(TAG," Shuffle not supported ");
+ return;
+ }
+ }
+ finally {
+ mLock.unlock();
+ }
+ for (int zz = 0; zz < sett.supported_values.length; zz ++) {
+ if (shuffle_status == sett.supported_values[zz]) {
+ shuffle_status = sett.supported_values[(zz + 1)%sett.supported_values.length];
+ break;
+ }
+ }
+ mAvrcpController.setPlayerApplicationSetting(sett.attr_Id, shuffle_status);
+ break;
+ }
+ }
+ }
public void onClickPassthruPause(View v) {
Logger.v(TAG, "onClickPassthruPause()");
@@ -206,26 +870,116 @@ public class AvrcpTestActivity extends MonkeyActivity implements IBluetoothConne
}
- public void onClickPassthruVolUp(View v) {
- Logger.v(TAG, "onClickPassthruVolUp()");
- if ((mAvrcpController != null) && mDevice != null &&
- BluetoothProfile.STATE_DISCONNECTED != (mAvrcpController.getConnectionState(mDevice))){
- mAvrcpController.sendPassThroughCmd(mDevice, AVRC_ID_VOL_UP, KEY_STATE_PRESSED);
- mAvrcpController.sendPassThroughCmd(mDevice, AVRC_ID_VOL_UP, KEY_STATE_RELEASED);
- } else {
- Logger.e(TAG, "passthru command not sent, connection unavailable");
+ private void updatePlayerSettings(BluetoothAvrcpInfo mData) {
+ if (plSetting != null) {
+ plSetting.clear();
+ }
+ plSetting = new ArrayList<PlayerSettings>();
+ if (mData == null)
+ return;
+ byte[] plAttributes = mData.getSupportedPlayerAttributes();
+ for (int zz = 0; zz < plAttributes.length; zz++) {
+ PlayerSettings playerSetting = new PlayerSettings();
+ playerSetting.attr_Id = plAttributes[zz];
+ playerSetting.supported_values = new byte[mData.getNumSupportedPlayerAttributeVal(playerSetting.attr_Id)];
+ byte[] plAttribSupportedValues = mData.getSupportedPlayerAttributeVlaues(playerSetting.attr_Id);
+ for (int xx = 0; xx < playerSetting.supported_values.length; xx++) {
+ playerSetting.supported_values[xx] = plAttribSupportedValues[xx];
+ }
+ plSetting.add(playerSetting);
}
-
}
-
- public void onClickPassthruVolDown(View v) {
- Logger.v(TAG, "onClickPassthruVolDown()");
- if ((mAvrcpController != null) && mDevice != null &&
- BluetoothProfile.STATE_DISCONNECTED != (mAvrcpController.getConnectionState(mDevice))){
- mAvrcpController.sendPassThroughCmd(mDevice, AVRC_ID_VOL_DOWN, KEY_STATE_PRESSED);
- mAvrcpController.sendPassThroughCmd(mDevice, AVRC_ID_VOL_DOWN, KEY_STATE_RELEASED);
- } else {
- Logger.e(TAG, "passthru command not sent, connection unavailable");
+ private void resetDisplay() {
+ mLocalActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mLock.lock();
+ trackNumText = "NOT_SUPP";
+ titleNameText = BluetoothAvrcpInfo.TITLE_INVALID;
+ equalizerText = BluetoothAvrcpInfo.EQUALIZER_STATUS_INVALID;
+ artistText = BluetoothAvrcpInfo.ARTIST_NAME_INVALID;
+ scanText = BluetoothAvrcpInfo.SCAN_STATUS_INVALID;
+ shuffleText = BluetoothAvrcpInfo.SHUFFLE_STATUS_INVALID;
+ repeatText = BluetoothAvrcpInfo.REPEAT_STATUS_INVALID;
+ playStatusText = BluetoothAvrcpInfo.PLAY_STATUS_INVALID;
+ genreText = BluetoothAvrcpInfo.GENRE_INVALID;
+ playText = BluetoothAvrcpInfo.PLAY_STATUS_INVALID;
+ albumText = BluetoothAvrcpInfo.ALBUM_NAME_INVALID;
+ try {
+ mTrackNumber.setText(trackNumText);
+ mTitleName.setText(titleNameText);
+ mEqualizerStatus.setText(equalizerText);
+ mArtistName.setText(artistText);
+ mScanStatus.setText(scanText);
+ mShuffleStatus.setText(shuffleText);
+ mRepeatStatus.setText(repeatText);
+ mPlayStatus.setText(playStatusText);
+ mGenreStatus.setText(genreText);
+ mPlayTime.setText(playText);
+ mAlbumName.setText(albumText);
+ }
+ finally {
+ mLock.unlock();
+ }
+ }
+ });
+ }
+ private void initializeViewFragments() {
+ Log.v(TAG,"initializeViewFragments");
+ mShuffleStatus = (TextView) findViewById(R.id.shuffle_status);
+ mRepeatStatus = (TextView) findViewById(R.id.repeat_status);
+ mGenreStatus = (TextView) findViewById(R.id.genre_name);
+ mArtistName = (TextView) findViewById(R.id.artist_name);
+ mAlbumName = (TextView) findViewById(R.id.album_name);
+ mPlayTime = (TextView) findViewById(R.id.playing_time);
+ mScanStatus = (TextView) findViewById(R.id.scan_status);
+ mPlayStatus = (TextView) findViewById(R.id.play_status);
+ mEqualizerStatus = (TextView) findViewById(R.id.equalizer_status);
+ mTrackNumber = (TextView) findViewById(R.id.track_number);
+ mTitleName = (TextView) findViewById(R.id.title_name);
+ mCTStartButton = (ToggleButton) findViewById(R.id.toggleButton1);
+ ffButton = (Button) findViewById(R.id.onClickPassthruFF);
+ rwButton = (Button) findViewById(R.id.onClickPassthruRewind);
+ ffButton.setOnTouchListener(onTouchListenerFF);
+ rwButton.setOnTouchListener(onTouchListenerRW);
+ }
+ public void onCTStartToggleClicked(View view) {
+ // Is the toggle on?
+ boolean on = ((ToggleButton) view).isChecked();
+ Log.v(TAG, "onCTStartToggleClicked is_on: " + on);
+ if ((mAvrcpController != null)&&(on)) {
+ List<BluetoothDevice> deviceList = mAvrcpController.getConnectedDevices();
+ if (deviceList.size() > 0) {
+ mDevice = deviceList.get(0);
+ if (mAvrcpController.getConnectionState(mDevice) != BluetoothProfile.STATE_CONNECTED) {
+ mCTStartButton.setChecked(false);
+ Toast.makeText(mLocalActivity, "Device Not Connected", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ remoteSupportedFeatures = mAvrcpController.getSupportedFeatures(mDevice);
+ Log.d(TAG," getSupportedFeatures " + remoteSupportedFeatures);
+ if ((remoteSupportedFeatures & BluetoothAvrcpInfo.BTRC_FEAT_METADATA)!=0) {
+ BluetoothAvrcpInfo mMetaData = mAvrcpController.getSupportedPlayerAppSetting(mDevice);
+ updatePlayerSettings(mMetaData);
+ registerMetaDataObserver();
+ int[] elementAttribute = new int[1];
+ elementAttribute[0] = BluetoothAvrcpInfo.MEDIA_ATTRIBUTE_ALL;
+ mAvrcpController.getMetaData(elementAttribute);
+ }
+ else {
+ unregisterMetaDataObserver();
+ resetDisplay();
+ mCTStartButton.setChecked(false);
+ Toast.makeText(mLocalActivity, "Device Don't Support MetaData", Toast.LENGTH_SHORT).show();
+ }
+ }
+ else { // no device connected
+ mCTStartButton.setChecked(false);
+ Toast.makeText(mLocalActivity, "Device Not Connected", Toast.LENGTH_SHORT).show();
+ }
+ } else if(mAvrcpController != null){
+ unregisterMetaDataObserver();
+ resetDisplay();
}
}
}