diff options
author | AnubhavGupta <anubhavg@codeaurora.org> | 2015-03-04 18:10:35 +0530 |
---|---|---|
committer | AnubhavGupta <anubhavg@codeaurora.org> | 2015-08-13 20:05:39 +0530 |
commit | 08811c6a23e3137ba00ef2df4432f7a110ff6933 (patch) | |
tree | 76a801e8b16ea7731fb87cbae6b21a6f85a09126 | |
parent | fbec7160bd960dc9a98c2b924554710d3f77a411 (diff) | |
download | android_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.xml | 1 | ||||
-rw-r--r-- | bttestapp/res/layout/activity_avrcp_test.xml | 314 | ||||
-rw-r--r-- | bttestapp/res/values/strings.xml | 27 | ||||
-rw-r--r-- | bttestapp/src/org/codeaurora/bluetooth/bttestapp/AvrcpTestActivity.java | 808 |
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(); } } } |