PageRenderTime 32ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/src/com/android/bluetooth/avrcp/Avrcp.java

https://gitlab.com/Atomic-ROM/packages_apps_Bluetooth
Java | 1089 lines | 960 code | 89 blank | 40 comment | 107 complexity | 47ae9468a0645137fce30d2872ea6349 MD5 | raw file
  1. /*
  2. * Copyright (C) 2013-2014, The Linux Foundation. All rights reserved.
  3. * Not a Contribution.
  4. *
  5. * Copyright (C) 2012 The Android Open Source Project
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. */
  19. package com.android.bluetooth.avrcp;
  20. import java.util.Timer;
  21. import java.util.TimerTask;
  22. import android.app.PendingIntent;
  23. import android.bluetooth.BluetoothAdapter;
  24. import android.bluetooth.BluetoothA2dp;
  25. import android.bluetooth.BluetoothAvrcp;
  26. import android.bluetooth.BluetoothDevice;
  27. import android.content.Context;
  28. import android.content.Intent;
  29. import android.content.IntentFilter;
  30. import android.graphics.Bitmap;
  31. import android.media.AudioManager;
  32. import android.media.IRemoteControlDisplay;
  33. import android.media.MediaMetadataRetriever;
  34. import android.media.RemoteControlClient;
  35. import android.media.RemoteController;
  36. import android.media.RemoteController.MetadataEditor;
  37. import android.os.Bundle;
  38. import android.os.Handler;
  39. import android.os.HandlerThread;
  40. import android.os.Looper;
  41. import android.os.Message;
  42. import android.os.ParcelUuid;
  43. import android.os.PowerManager;
  44. import android.os.PowerManager.WakeLock;
  45. import android.os.RemoteException;
  46. import android.os.ServiceManager;
  47. import android.os.SystemClock;
  48. import android.util.Log;
  49. import android.view.KeyEvent;
  50. import android.content.BroadcastReceiver;
  51. import com.android.bluetooth.a2dp.A2dpService;
  52. import com.android.bluetooth.btservice.AdapterService;
  53. import com.android.bluetooth.btservice.ProfileService;
  54. import com.android.bluetooth.Utils;
  55. import com.android.internal.util.IState;
  56. import com.android.internal.util.State;
  57. import com.android.internal.util.StateMachine;
  58. import java.lang.ref.WeakReference;
  59. import java.util.ArrayList;
  60. import java.util.List;
  61. import java.util.Set;
  62. import java.util.Iterator;
  63. import android.provider.MediaStore;
  64. import android.content.ContentResolver;
  65. import android.database.Cursor;
  66. import android.database.sqlite.SQLiteException;
  67. import android.net.Uri;
  68. import android.app.Notification;
  69. import android.app.NotificationManager;
  70. /**
  71. * support Bluetooth AVRCP profile.
  72. * support metadata, play status and event notification
  73. */
  74. public final class Avrcp {
  75. private static final boolean DEBUG = false;
  76. private static final String TAG = "Avrcp";
  77. private Context mContext;
  78. private final AudioManager mAudioManager;
  79. private A2dpService mA2dpService;
  80. private AvrcpMessageHandler mHandler;
  81. private RemoteController mRemoteController;
  82. private RemoteControllerWeak mRemoteControllerCb;
  83. private AvrcpRemoteControllerWeak mAvrcpRemoteControllerCb;
  84. private Metadata mMetadata;
  85. private int mTransportControlFlags;
  86. private int mCurrentPlayerState;
  87. private int mPlayStatusChangedNT;
  88. private int mTrackChangedNT;
  89. private long mCurrentPosMs;
  90. private long mPlayStartTimeMs;
  91. private long mTrackNumber;
  92. private long mSongLengthMs;
  93. private long mPlaybackIntervalMs;
  94. private int mPlayPosChangedNT;
  95. private long mSkipStartTime;
  96. private final int mVolumeStep;
  97. private final int mAudioStreamMax;
  98. private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
  99. private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
  100. private int mSkipAmount;
  101. private final BluetoothAdapter mAdapter;
  102. private static Uri mMediaUriStatic;
  103. private static long currentTrackPos;
  104. private static boolean updatePlayTime;
  105. private static boolean updateValues;
  106. private int mAddressedPlayerId;
  107. /* BTRC features */
  108. public static final int BTRC_FEAT_METADATA = 0x01;
  109. public static final int BTRC_FEAT_ABSOLUTE_VOLUME = 0x02;
  110. public static final int BTRC_FEAT_BROWSE = 0x04;
  111. public static final int BTRC_FEAT_AVRC_UI_UPDATE = 0x08;
  112. /* AVRC response codes, from avrc_defs */
  113. private static final int AVRC_RSP_NOT_IMPL = 8;
  114. private static final int AVRC_RSP_ACCEPT = 9;
  115. private static final int AVRC_RSP_REJ = 10;
  116. private static final int AVRC_RSP_IN_TRANS = 11;
  117. private static final int AVRC_RSP_IMPL_STBL = 12;
  118. private static final int AVRC_RSP_CHANGED = 13;
  119. private static final int AVRC_RSP_INTERIM = 15;
  120. private static final int MESSAGE_GET_RC_FEATURES = 1;
  121. private static final int MESSAGE_GET_PLAY_STATUS = 2;
  122. private static final int MESSAGE_GET_ELEM_ATTRS = 3;
  123. private static final int MESSAGE_REGISTER_NOTIFICATION = 4;
  124. private static final int MESSAGE_PLAY_INTERVAL_TIMEOUT = 5;
  125. private static final int MESSAGE_VOLUME_CHANGED = 6;
  126. private static final int MESSAGE_ADJUST_VOLUME = 7;
  127. private static final int MESSAGE_SET_ABSOLUTE_VOLUME = 8;
  128. private static final int MESSAGE_ABS_VOL_TIMEOUT = 9;
  129. private static final int MESSAGE_FAST_FORWARD = 10;
  130. private static final int MESSAGE_REWIND = 11;
  131. private static final int MESSAGE_CHANGE_PLAY_POS = 12;
  132. private static final int MESSAGE_SET_A2DP_AUDIO_STATE = 13;
  133. private static final int MESSAGE_SET_ADDR_PLAYER_REQ_TIMEOUT = 14;
  134. private static final int AVRCP_BR_RSP_TIMEOUT = 2000;
  135. private static final int MESSAGE_SEND_PASS_THROUGH_CMD = 2001;
  136. private static final int MESSAGE_SET_ADDR_PLAYER = 2002;
  137. private static final int MESSAGE_GET_FOLDER_ITEMS = 2003;
  138. private static final int MESSAGE_SET_BROWSED_PLAYER = 2004;
  139. private static final int MESSAGE_CHANGE_PATH = 2005;
  140. private static final int MESSAGE_PLAY_ITEM = 2006;
  141. private static final int MESSAGE_GET_ITEM_ATTRS = 2007;
  142. private CachedRequest mCachedRequest = null;
  143. private static final int MSG_UPDATE_STATE = 100;
  144. private static final int MSG_SET_METADATA = 101;
  145. private static final int MSG_SET_TRANSPORT_CONTROLS = 102;
  146. private static final int MSG_SET_GENERATION_ID = 104;
  147. private static final int MSG_UPDATE_AVAILABLE_PLAYERS = 201;
  148. private static final int MSG_UPDATE_ADDRESSED_PLAYER = 202;
  149. private static final int MSG_UPDATE_RCC_CHANGE = 203;
  150. private static final int MSG_UPDATE_BROWSED_PLAYER_FOLDER = 204;
  151. private static final int MSG_UPDATE_NOW_PLAYING_CONTENT_CHANGED = 205;
  152. private static final int MSG_PLAY_ITEM_RESPONSE = 206;
  153. private static final int MSG_NOW_PLAYING_ENTRIES_RECEIVED = 207;
  154. private MediaPlayerInfo mediaPlayerInfo1;
  155. private static final int BUTTON_TIMEOUT_TIME = 2000;
  156. private static final int BASE_SKIP_AMOUNT = 2000;
  157. private static final int KEY_STATE_PRESS = 1;
  158. private static final int KEY_STATE_RELEASE = 0;
  159. private static final int SKIP_PERIOD = 400;
  160. private static final int SKIP_DOUBLE_INTERVAL = 3000;
  161. private static final long MAX_MULTIPLIER_VALUE = 128L;
  162. private static final int CMD_TIMEOUT_DELAY = 2000;
  163. private static final int MAX_ERROR_RETRY_TIMES = 3;
  164. private static final int AVRCP_MAX_VOL = 127;
  165. private static final int AVRCP_BASE_VOLUME_STEP = 1;
  166. private final static int MESSAGE_PLAYERSETTINGS_TIMEOUT = 602;
  167. private static final int AVRCP_CONNECTED = 1;
  168. public static final int KEY_STATE_PRESSED = 0;
  169. public static final int KEY_STATE_RELEASED = 1;
  170. private final static int TYPE_MEDIA_PLAYER_ITEM = 0x01;
  171. private final static int TYPE_FOLDER_ITEM = 0x02;
  172. private final static int TYPE_MEDIA_ELEMENT_ITEM = 0x03;
  173. private final static int FOLDER_UP = 0x00;
  174. private final static int FOLDER_DOWN = 0x01;
  175. private static final String PATH_INVALID = "invalid";
  176. private static final String PATH_ROOT = "root";
  177. private static final String PATH_TITLES = "titles";
  178. private static final String PATH_ALBUMS = "albums";
  179. private static final String PATH_ARTISTS = "artists";
  180. private static final String PATH_PLAYLISTS = "playlists";
  181. private final static long UID_TITLES = 0x01;
  182. private final static long UID_ALBUM = 0x02;
  183. private final static long UID_ARTIST = 0x03;
  184. private final static long UID_PLAYLIST = 0x04;
  185. private final static int NUM_ROOT_ELEMENTS = 0x04;
  186. private static final int INTERNAL_ERROR = 0x03;
  187. private static final int OPERATION_SUCCESSFUL = 0x04;
  188. private static final int INVALID_DIRECTION = 0x07;
  189. private static final int NOT_A_DIRECTORY = 0x08;
  190. private static final int DOES_NOT_EXIST = 0x09;
  191. private static final int INVALID_SCOPE = 0x0a;
  192. private static final int RANGE_OUT_OF_BOUNDS = 0x0b;
  193. private static final int UID_A_DIRECTORY = 0x0c;
  194. private static final int MEDIA_IN_USE = 0x0d;
  195. private static final int INVALID_PLAYER_ID = 0x11;
  196. private static final int PLAYER_NOT_BROWSABLE = 0x12;
  197. private static final int PLAYER_NOT_ADDRESSED = 0x13;
  198. private static final int FOLDER_TYPE_MIXED = 0x00;
  199. private static final int FOLDER_TYPE_TITLES = 0x01;
  200. private static final int FOLDER_TYPE_ALBUMS = 0x02;
  201. private static final int FOLDER_TYPE_ARTISTS = 0x03;
  202. private static final int FOLDER_TYPE_GENRES = 0x04;
  203. private static final int FOLDER_TYPE_PLAYLISTS = 0x05;
  204. private static final int MEDIA_TYPE_AUDIO = 0X00;
  205. private static final int MEDIA_TYPE_VIDEO = 0X01;
  206. private static final int MAX_BROWSE_ITEM_TO_SEND = 0x03;
  207. private static final int MAX_ATTRIB_COUNT = 0x07;
  208. private final static int ALBUMS_ITEM_INDEX = 0;
  209. private final static int ARTISTS_ITEM_INDEX = 1;
  210. private final static int PLAYLISTS_ITEM_INDEX = 2;
  211. private final static int TITLES_ITEM_INDEX = 3;
  212. //Intents for PlayerApplication Settings
  213. private static final String PLAYERSETTINGS_REQUEST =
  214. "org.codeaurora.music.playersettingsrequest";
  215. private static final String PLAYERSETTINGS_RESPONSE =
  216. "org.codeaurora.music.playersettingsresponse";
  217. // Max number of Avrcp connections at any time
  218. private int maxAvrcpConnections = 1;
  219. BluetoothDevice mBrowserDevice = null;
  220. private static final int INVALID_DEVICE_INDEX = 0xFF;
  221. // codes for reset of of notifications
  222. private static final int PLAY_POSITION_CHANGE_NOTIFICATION = 101;
  223. private static final int PLAY_STATUS_CHANGE_NOTIFICATION = 102;
  224. private static final int TRACK_CHANGE_NOTIFICATION = 103;
  225. private static final int NOW_PALYING_CONTENT_CHANGED_NOTIFICATION = 104;
  226. private static final int INVALID_ADDRESSED_PLAYER_ID = -1;
  227. // Device dependent registered Notification & Variables
  228. private class DeviceDependentFeature {
  229. private BluetoothDevice mCurrentDevice;
  230. private int mCurrentPlayState;
  231. private int mPlayStatusChangedNT;
  232. private int mPlayerStatusChangeNT;
  233. private int mTrackChangedNT;
  234. private long mNextPosMs;
  235. private long mPrevPosMs;
  236. private long mPlaybackIntervalMs;
  237. private int mPlayPosChangedNT;
  238. private int mFeatures;
  239. private int mAbsoluteVolume;
  240. private int mLastSetVolume;
  241. private int mLastDirection;
  242. private boolean mVolCmdInProgress;
  243. private int mAbsVolRetryTimes;
  244. private int keyPressState;
  245. private int mAddressedPlayerChangedNT;
  246. private int mAvailablePlayersChangedNT;
  247. private int mNowPlayingContentChangedNT;
  248. private String mRequestedAddressedPlayerPackageName;
  249. private String mCurrentPath;
  250. private String mCurrentPathUid;
  251. private Uri mMediaUri;
  252. private boolean isMusicAppResponsePending;
  253. private boolean isBrowsingSupported;
  254. private boolean isAbsoluteVolumeSupportingDevice;
  255. public DeviceDependentFeature() {
  256. mCurrentDevice = null;
  257. mCurrentPlayState = RemoteControlClient.PLAYSTATE_NONE;
  258. mPlayStatusChangedNT = NOTIFICATION_TYPE_CHANGED;
  259. mPlayerStatusChangeNT = NOTIFICATION_TYPE_CHANGED;
  260. mTrackChangedNT = NOTIFICATION_TYPE_CHANGED;
  261. mPlaybackIntervalMs = 0L;
  262. mPlayPosChangedNT = NOTIFICATION_TYPE_CHANGED;
  263. mFeatures = 0;
  264. mAbsoluteVolume = -1;
  265. mLastSetVolume = -1;
  266. mLastDirection = 0;
  267. mVolCmdInProgress = false;
  268. mAbsVolRetryTimes = 0;
  269. mSkipAmount = 0;
  270. keyPressState = KEY_STATE_RELEASE; //Key release state
  271. mAddressedPlayerChangedNT = NOTIFICATION_TYPE_CHANGED;
  272. mAvailablePlayersChangedNT = NOTIFICATION_TYPE_CHANGED;
  273. mNowPlayingContentChangedNT = NOTIFICATION_TYPE_CHANGED;
  274. mRequestedAddressedPlayerPackageName = null;
  275. mCurrentPath = PATH_INVALID;
  276. mCurrentPathUid = null;
  277. mMediaUri = Uri.EMPTY;
  278. isMusicAppResponsePending = false;
  279. isBrowsingSupported = false;
  280. isAbsoluteVolumeSupportingDevice = false;
  281. }
  282. };
  283. private class PlayerSettings {
  284. public byte attr;
  285. public byte [] attrIds;
  286. public String path;
  287. };
  288. private PlayerSettings mPlayerSettings = new PlayerSettings();
  289. private class localPlayerSettings {
  290. public byte eq_value = 0x01;
  291. public byte repeat_value = 0x01;
  292. public byte shuffle_value = 0x01;
  293. public byte scan_value = 0x01;
  294. };
  295. private localPlayerSettings settingValues = new localPlayerSettings();
  296. private static final String COMMAND = "command";
  297. private static final String CMDGET = "get";
  298. private static final String CMDSET = "set";
  299. private static final String EXTRA_GET_COMMAND = "commandExtra";
  300. private static final String EXTRA_GET_RESPONSE = "Response";
  301. private static final int GET_ATTRIBUTE_IDS = 0;
  302. private static final int GET_VALUE_IDS = 1;
  303. private static final int GET_ATTRIBUTE_TEXT = 2;
  304. private static final int GET_VALUE_TEXT = 3;
  305. private static final int GET_ATTRIBUTE_VALUES = 4;
  306. private static final int NOTIFY_ATTRIBUTE_VALUES = 5;
  307. private static final int SET_ATTRIBUTE_VALUES = 6;
  308. private static final int GET_INVALID = 0xff;
  309. private static final String EXTRA_ATTRIBUTE_ID = "Attribute";
  310. private static final String EXTRA_VALUE_STRING_ARRAY = "ValueStrings";
  311. private static final String EXTRA_ATTRIB_VALUE_PAIRS = "AttribValuePairs";
  312. private static final String EXTRA_ATTRIBUTE_STRING_ARRAY = "AttributeStrings";
  313. private static final String EXTRA_VALUE_ID_ARRAY = "Values";
  314. private static final String EXTRA_ATTIBUTE_ID_ARRAY = "Attributes";
  315. public static final int VALUE_SHUFFLEMODE_OFF = 1;
  316. public static final int VALUE_SHUFFLEMODE_ALL = 2;
  317. public static final int VALUE_REPEATMODE_OFF = 1;
  318. public static final int VALUE_REPEATMODE_SINGLE = 2;
  319. public static final int VALUE_REPEATMODE_ALL = 3;
  320. public static final int VALUE_INVALID = 0;
  321. public static final int ATTRIBUTE_NOTSUPPORTED = -1;
  322. public static final int ATTRIBUTE_EQUALIZER = 1;
  323. public static final int ATTRIBUTE_REPEATMODE = 2;
  324. public static final int ATTRIBUTE_SHUFFLEMODE = 3;
  325. public static final int ATTRIBUTE_SCANMODE = 4;
  326. public static final int NUMPLAYER_ATTRIBUTE = 2;
  327. private byte [] def_attrib = new byte [] {ATTRIBUTE_REPEATMODE, ATTRIBUTE_SHUFFLEMODE};
  328. private byte [] value_repmode = new byte [] { VALUE_REPEATMODE_OFF,
  329. VALUE_REPEATMODE_SINGLE,
  330. VALUE_REPEATMODE_ALL };
  331. private byte [] value_shufmode = new byte [] { VALUE_SHUFFLEMODE_OFF,
  332. VALUE_SHUFFLEMODE_ALL };
  333. private byte [] value_default = new byte [] {0};
  334. private final String UPDATE_ATTRIBUTES = "UpdateSupportedAttributes";
  335. private final String UPDATE_VALUES = "UpdateSupportedValues";
  336. private final String UPDATE_ATTRIB_VALUE = "UpdateCurrentValues";
  337. private final String UPDATE_ATTRIB_TEXT = "UpdateAttributesText";
  338. private final String UPDATE_VALUE_TEXT = "UpdateValuesText";
  339. private ArrayList <Integer> mPendingCmds;
  340. private ArrayList <Integer> mPendingSetAttributes;
  341. DeviceDependentFeature[] deviceFeatures;
  342. static {
  343. classInitNative();
  344. }
  345. private Avrcp(Context context, A2dpService svc, int maxConnections ) {
  346. if (DEBUG)
  347. Log.v(TAG, "Avrcp");
  348. mAdapter = BluetoothAdapter.getDefaultAdapter();
  349. mMetadata = new Metadata();
  350. mTrackNumber = -1L;
  351. mCurrentPosMs = -1L;
  352. mPlayStartTimeMs = -1L;
  353. mSongLengthMs = 0L;
  354. mA2dpService = svc;
  355. maxAvrcpConnections = maxConnections;
  356. deviceFeatures = new DeviceDependentFeature[maxAvrcpConnections];
  357. mAddressedPlayerId = INVALID_ADDRESSED_PLAYER_ID;
  358. mCurrentPlayerState = RemoteControlClient.PLAYSTATE_NONE;
  359. for(int i = 0; i < maxAvrcpConnections; i++) {
  360. deviceFeatures[i] = new DeviceDependentFeature();
  361. }
  362. mContext = context;
  363. initNative(maxConnections);
  364. mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
  365. mAudioStreamMax = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
  366. mVolumeStep = Math.max(AVRCP_BASE_VOLUME_STEP, AVRCP_MAX_VOL/mAudioStreamMax);
  367. }
  368. private void start() {
  369. if (DEBUG)
  370. Log.v(TAG, "start");
  371. HandlerThread thread = new HandlerThread("BluetoothAvrcpHandler");
  372. thread.start();
  373. Looper looper = thread.getLooper();
  374. mHandler = new AvrcpMessageHandler(looper);
  375. mPendingCmds = new ArrayList<Integer>();
  376. mPendingSetAttributes = new ArrayList<Integer>();
  377. // clear path for all devices
  378. for (int i = 0; i < maxAvrcpConnections; i++) {
  379. deviceFeatures[i].mCurrentPath = PATH_INVALID;
  380. deviceFeatures[i].mCurrentPathUid = null;
  381. deviceFeatures[i].mMediaUri = Uri.EMPTY;
  382. }
  383. IntentFilter intentFilter = new IntentFilter();
  384. intentFilter.addAction(AudioManager.RCC_CHANGED_ACTION);
  385. intentFilter.addAction(PLAYERSETTINGS_RESPONSE);
  386. try {
  387. mContext.registerReceiver(mIntentReceiver, intentFilter);
  388. }catch (Exception e) {
  389. Log.e(TAG,"Unable to register Avrcp receiver", e);
  390. }
  391. registerMediaPlayers();
  392. mRemoteControllerCb = new RemoteControllerWeak(mHandler);
  393. mAvrcpRemoteControllerCb = new AvrcpRemoteControllerWeak(mHandler);
  394. mRemoteController = new RemoteController(mContext, mRemoteControllerCb,
  395. null, mAvrcpRemoteControllerCb);
  396. mAudioManager.registerRemoteController(mRemoteController);
  397. mRemoteController.setSynchronizationMode(RemoteController.POSITION_SYNCHRONIZATION_CHECK);
  398. }
  399. //Listen to intents from MediaPlayer and Audio Manager and update data structures
  400. private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
  401. @Override
  402. public void onReceive(Context context, Intent intent) {
  403. String action = intent.getAction();
  404. if (action.equals(AudioManager.RCC_CHANGED_ACTION)) {
  405. Log.v(TAG, "received RCC_CHANGED_ACTION");
  406. int isRCCFocussed = 0;
  407. int isRCCAvailable = 0;
  408. String callingPackageName =
  409. intent.getStringExtra(AudioManager.EXTRA_CALLING_PACKAGE_NAME);
  410. boolean isFocussed =
  411. intent.getBooleanExtra(AudioManager.EXTRA_FOCUS_CHANGED_VALUE,
  412. false);
  413. boolean isAvailable =
  414. intent.getBooleanExtra(AudioManager.EXTRA_AVAILABLITY_CHANGED_VALUE,
  415. false);
  416. if (isFocussed)
  417. isRCCFocussed = 1;
  418. if (isAvailable)
  419. isRCCAvailable = 1;
  420. Log.v(TAG, "focus: " + isFocussed + " , availability: " + isAvailable);
  421. if (mHandler != null) {
  422. mHandler.obtainMessage(MSG_UPDATE_RCC_CHANGE, isRCCFocussed,
  423. isRCCAvailable, callingPackageName).sendToTarget();
  424. }
  425. } else if (action.equals(PLAYERSETTINGS_RESPONSE)) {
  426. int getResponse = intent.getIntExtra(EXTRA_GET_RESPONSE,
  427. GET_INVALID);
  428. byte [] data;
  429. String [] text;
  430. boolean isSetAttrValRsp = false;
  431. BluetoothDevice device = null;
  432. synchronized (mPendingCmds) {
  433. Integer val = new Integer(getResponse);
  434. if (mPendingCmds.contains(val)) {
  435. if (getResponse == SET_ATTRIBUTE_VALUES) {
  436. isSetAttrValRsp = true;
  437. if (DEBUG) Log.v(TAG,"Response received for SET_ATTRIBUTE_VALUES");
  438. }
  439. mHandler.removeMessages(MESSAGE_PLAYERSETTINGS_TIMEOUT);
  440. mPendingCmds.remove(val);
  441. }
  442. }
  443. for (int i = 0; i < maxAvrcpConnections; i++) {
  444. if (deviceFeatures[i].isMusicAppResponsePending ==
  445. true) {
  446. device = deviceFeatures[i].mCurrentDevice;
  447. deviceFeatures[i].isMusicAppResponsePending = false;
  448. break;
  449. }
  450. }
  451. if (DEBUG)
  452. Log.v(TAG,"getResponse" + getResponse);
  453. switch (getResponse) {
  454. case GET_ATTRIBUTE_IDS:
  455. if (device == null) {
  456. Log.e(TAG,"ERROR!!! device is null");
  457. return;
  458. }
  459. data = intent.getByteArrayExtra(EXTRA_ATTIBUTE_ID_ARRAY);
  460. byte numAttr = (byte) data.length;
  461. if (DEBUG)
  462. Log.v(TAG,"GET_ATTRIBUTE_IDS");
  463. getListPlayerappAttrRspNative(numAttr ,
  464. data ,getByteAddress(device));
  465. break;
  466. case GET_VALUE_IDS:
  467. if (device == null) {
  468. Log.e(TAG,"ERROR!!! device is null");
  469. return;
  470. }
  471. data = intent.getByteArrayExtra(EXTRA_VALUE_ID_ARRAY);
  472. numAttr = (byte) data.length;
  473. if (DEBUG)
  474. Log.v(TAG,"GET_VALUE_IDS" + numAttr);
  475. getPlayerAppValueRspNative(numAttr, data,
  476. getByteAddress(device));
  477. break;
  478. case GET_ATTRIBUTE_VALUES:
  479. if (device == null) {
  480. Log.e(TAG,"ERROR!!! device is null");
  481. return;
  482. }
  483. data = intent.getByteArrayExtra(EXTRA_ATTRIB_VALUE_PAIRS);
  484. updateLocalPlayerSettings(data);
  485. numAttr = (byte) data.length;
  486. if (DEBUG)
  487. Log.v(TAG,"GET_ATTRIBUTE_VALUES" + numAttr);
  488. SendCurrentPlayerValueRspNative(numAttr ,
  489. data, getByteAddress(device));
  490. break;
  491. case SET_ATTRIBUTE_VALUES:
  492. data = intent.getByteArrayExtra(EXTRA_ATTRIB_VALUE_PAIRS);
  493. updateLocalPlayerSettings(data);
  494. if (isSetAttrValRsp) {
  495. isSetAttrValRsp = false;
  496. for (int i = 0; i < maxAvrcpConnections; i++) {
  497. if (deviceFeatures[i].mCurrentDevice != null) {
  498. Log.v(TAG,"Respond to SET_ATTRIBUTE_VALUES request");
  499. if (checkPlayerAttributeResponse(data)) {
  500. SendSetPlayerAppRspNative(OPERATION_SUCCESSFUL,
  501. getByteAddress(deviceFeatures[i].mCurrentDevice));
  502. } else {
  503. SendSetPlayerAppRspNative(INTERNAL_ERROR,
  504. getByteAddress(deviceFeatures[i].mCurrentDevice));
  505. }
  506. }
  507. }
  508. mPendingSetAttributes.clear();
  509. }
  510. for (int i = 0; i < maxAvrcpConnections; i++) {
  511. if (deviceFeatures[i].mPlayerStatusChangeNT ==
  512. NOTIFICATION_TYPE_INTERIM) {
  513. Log.v(TAG,"device has registered for"+
  514. "mPlayerStatusChangeNT");
  515. deviceFeatures[i].mPlayerStatusChangeNT =
  516. NOTIFICATION_TYPE_CHANGED;
  517. sendPlayerAppChangedRsp(deviceFeatures[i].mPlayerStatusChangeNT,
  518. deviceFeatures[i].mCurrentDevice);
  519. } else {
  520. Log.v(TAG,"Drop Set Attr Val update from media player");
  521. }
  522. }
  523. break;
  524. case GET_ATTRIBUTE_TEXT:
  525. text = intent.getStringArrayExtra(EXTRA_ATTRIBUTE_STRING_ARRAY);
  526. if (device == null) {
  527. Log.e(TAG,"ERROR!!! device is null");
  528. return;
  529. }
  530. sendSettingsTextRspNative(mPlayerSettings.attrIds.length ,
  531. mPlayerSettings.attrIds ,text.length,
  532. text, getByteAddress(device));
  533. if (DEBUG)
  534. Log.v(TAG,"mPlayerSettings.attrIds"
  535. + mPlayerSettings.attrIds.length);
  536. break;
  537. case GET_VALUE_TEXT:
  538. text = intent.getStringArrayExtra(EXTRA_VALUE_STRING_ARRAY);
  539. if (device == null) {
  540. Log.e(TAG,"ERROR!!! device is null");
  541. return;
  542. }
  543. sendValueTextRspNative(mPlayerSettings.attrIds.length ,
  544. mPlayerSettings.attrIds,
  545. text.length, text,
  546. getByteAddress(device));
  547. break;
  548. }
  549. }
  550. }
  551. };
  552. /* This method is used for create entries of existing media players on RCD start
  553. * Later when media players become avaialable corresponding entries
  554. * are marked accordingly and similarly when media players changes focus
  555. * the corresponding fields are modified */
  556. private void registerMediaPlayers () {
  557. if (DEBUG)
  558. Log.v(TAG, "registerMediaPlayers");
  559. int[] featureMasks = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  560. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  561. byte[] playerName1 = {0x4d, 0x75, 0x73, 0x69, 0x63}/*Music*/;
  562. featureMasks[FEATURE_MASK_PLAY_OFFSET] =
  563. featureMasks[FEATURE_MASK_PLAY_OFFSET] | FEATURE_MASK_PLAY_MASK;
  564. featureMasks[FEATURE_MASK_PAUSE_OFFSET] =
  565. featureMasks[FEATURE_MASK_PAUSE_OFFSET] | FEATURE_MASK_PAUSE_MASK;
  566. featureMasks[FEATURE_MASK_STOP_OFFSET] =
  567. featureMasks[FEATURE_MASK_STOP_OFFSET] | FEATURE_MASK_STOP_MASK;
  568. featureMasks[FEATURE_MASK_PAGE_UP_OFFSET] =
  569. featureMasks[FEATURE_MASK_PAGE_UP_OFFSET] | FEATURE_MASK_PAGE_UP_MASK;
  570. featureMasks[FEATURE_MASK_PAGE_DOWN_OFFSET] =
  571. featureMasks[FEATURE_MASK_PAGE_DOWN_OFFSET] | FEATURE_MASK_PAGE_DOWN_MASK;
  572. featureMasks[FEATURE_MASK_REWIND_OFFSET] =
  573. featureMasks[FEATURE_MASK_REWIND_OFFSET] | FEATURE_MASK_REWIND_MASK;
  574. featureMasks[FEATURE_MASK_FAST_FWD_OFFSET] =
  575. featureMasks[FEATURE_MASK_FAST_FWD_OFFSET] | FEATURE_MASK_FAST_FWD_MASK;
  576. featureMasks[FEATURE_MASK_VENDOR_OFFSET] =
  577. featureMasks[FEATURE_MASK_VENDOR_OFFSET] | FEATURE_MASK_VENDOR_MASK;
  578. featureMasks[FEATURE_MASK_ADV_CTRL_OFFSET] =
  579. featureMasks[FEATURE_MASK_ADV_CTRL_OFFSET] | FEATURE_MASK_ADV_CTRL_MASK;
  580. featureMasks[FEATURE_MASK_BROWSE_OFFSET] =
  581. featureMasks[FEATURE_MASK_BROWSE_OFFSET] | FEATURE_MASK_BROWSE_MASK;
  582. featureMasks[FEATURE_MASK_NOW_PLAY_OFFSET] =
  583. featureMasks[FEATURE_MASK_NOW_PLAY_OFFSET] | FEATURE_MASK_NOW_PLAY_MASK;
  584. featureMasks[FEATURE_MASK_BR_WH_ADDR_OFFSET] =
  585. featureMasks[FEATURE_MASK_BR_WH_ADDR_OFFSET] | FEATURE_MASK_BR_WH_ADDR_MASK;
  586. mediaPlayerInfo1 = new MediaPlayerInfo ((short)0x0001,
  587. MAJOR_TYPE_AUDIO,
  588. SUB_TYPE_NONE,
  589. (byte)RemoteControlClient.PLAYSTATE_PAUSED,
  590. CHAR_SET_UTF8,
  591. (short)0x05,
  592. playerName1,
  593. "com.android.music",
  594. true,
  595. featureMasks);
  596. mMediaPlayers.add(mediaPlayerInfo1);
  597. }
  598. public static Avrcp make(Context context, A2dpService svc,
  599. int maxConnections) {
  600. if (DEBUG)
  601. Log.v(TAG, "make");
  602. Avrcp ar = new Avrcp(context, svc, maxConnections);
  603. ar.start();
  604. return ar;
  605. }
  606. public void doQuit() {
  607. if (DEBUG)
  608. Log.v(TAG, "doQuit");
  609. mHandler.removeCallbacksAndMessages(null);
  610. Looper looper = mHandler.getLooper();
  611. if (looper != null) {
  612. looper.quit();
  613. }
  614. mAudioManager.unregisterRemoteController(mRemoteController);
  615. clearDeviceDependentFeature();
  616. for (int i = 0; i < maxAvrcpConnections; i++) {
  617. cleanupDeviceFeaturesIndex(i);
  618. }
  619. try {
  620. mContext.unregisterReceiver(mIntentReceiver);
  621. }catch (Exception e) {
  622. Log.e(TAG,"Unable to unregister Avrcp receiver", e);
  623. }
  624. mMediaPlayers.clear();
  625. if (mHandler.hasMessages(MESSAGE_SET_ADDR_PLAYER_REQ_TIMEOUT)) {
  626. mHandler.removeMessages(MESSAGE_SET_ADDR_PLAYER_REQ_TIMEOUT);
  627. if (DEBUG)
  628. Log.v(TAG, "Addressed player message cleanup as part of doQuit");
  629. }
  630. }
  631. public void clearDeviceDependentFeature() {
  632. for (int i = 0; i < maxAvrcpConnections; i++) {
  633. deviceFeatures[i].keyPressState = KEY_STATE_RELEASE; //Key release state
  634. deviceFeatures[i].mCurrentPath = PATH_INVALID;
  635. deviceFeatures[i].mMediaUri = Uri.EMPTY;
  636. deviceFeatures[i].mCurrentPathUid = null;
  637. deviceFeatures[i].mRequestedAddressedPlayerPackageName = null;
  638. }
  639. }
  640. public void cleanup() {
  641. if (DEBUG)
  642. Log.v(TAG, "cleanup");
  643. cleanupNative();
  644. }
  645. private static class RemoteControllerWeak implements RemoteController.OnClientUpdateListener {
  646. private final WeakReference<Handler> mLocalHandler;
  647. public RemoteControllerWeak(Handler handler) {
  648. mLocalHandler = new WeakReference<Handler>(handler);
  649. }
  650. @Override
  651. public void onClientChange(boolean clearing) {
  652. Handler handler = mLocalHandler.get();
  653. if (handler != null) {
  654. handler.obtainMessage(MSG_SET_GENERATION_ID,
  655. 0, (clearing ? 1 : 0), null).sendToTarget();
  656. }
  657. }
  658. @Override
  659. public void onClientPlaybackStateUpdate(int state) {
  660. // Should never be called with the existing code, but just in case
  661. Handler handler = mLocalHandler.get();
  662. if (handler != null) {
  663. handler.obtainMessage(MSG_UPDATE_STATE, 0, state,
  664. new Long(RemoteControlClient.PLAYBACK_POSITION_INVALID)).sendToTarget();
  665. }
  666. }
  667. @Override
  668. public void onClientPlaybackStateUpdate(int state, long stateChangeTimeMs,
  669. long currentPosMs, float speed) {
  670. Handler handler = mLocalHandler.get();
  671. if (handler != null) {
  672. handler.obtainMessage(MSG_UPDATE_STATE, 0, state,
  673. new Long(currentPosMs)).sendToTarget();
  674. }
  675. }
  676. @Override
  677. public void onClientTransportControlUpdate(int transportControlFlags) {
  678. Handler handler = mLocalHandler.get();
  679. if (handler != null) {
  680. handler.obtainMessage(MSG_SET_TRANSPORT_CONTROLS, 0, transportControlFlags)
  681. .sendToTarget();
  682. }
  683. }
  684. @Override
  685. public void onClientMetadataUpdate(MetadataEditor metadataEditor) {
  686. Handler handler = mLocalHandler.get();
  687. if (handler != null) {
  688. handler.obtainMessage(MSG_SET_METADATA, 0, 0, metadataEditor).sendToTarget();
  689. }
  690. }
  691. }
  692. private static class AvrcpRemoteControllerWeak implements
  693. RemoteController.OnClientAvrcpUpdateListener {
  694. private final WeakReference<Handler> mLocalHandler;
  695. public AvrcpRemoteControllerWeak(Handler handler) {
  696. mLocalHandler = new WeakReference<Handler>(handler);
  697. }
  698. @Override
  699. public void onClientFolderInfoBrowsedPlayer(String stringUri) {
  700. Log.v(TAG, "onClientFolderInfoBrowsedPlayer: stringUri: " + stringUri);
  701. Handler handler = mLocalHandler.get();
  702. if (stringUri != null) {
  703. String[] ExternalPath = stringUri.split("/");
  704. if (ExternalPath.length < 4) {
  705. Log.d(TAG, "Wrong entries.");
  706. handler.obtainMessage(MSG_UPDATE_BROWSED_PLAYER_FOLDER, 0, INTERNAL_ERROR,
  707. null).sendToTarget();
  708. return;
  709. }
  710. Uri uri = Uri.parse(stringUri);
  711. Log.v(TAG, "URI received: " + uri);
  712. String[] SplitPath = new String[ExternalPath.length - 3];
  713. for (int count = 2; count < (ExternalPath.length - 1); count++) {
  714. SplitPath[count - 2] = ExternalPath[count];
  715. Log.d(TAG, "SplitPath[" + (count - 2) + "] = " + SplitPath[count - 2]);
  716. }
  717. Log.v(TAG, "folderDepth: " + SplitPath.length);
  718. for (int count = 0; count < SplitPath.length; count++) {
  719. Log.v(TAG, "folderName: " + SplitPath[count]);
  720. }
  721. mMediaUriStatic = uri;
  722. if (handler != null) {
  723. // Don't send the complete path to CK as few gets confused by that
  724. // Send only the name of the root folder
  725. handler.obtainMessage(MSG_UPDATE_BROWSED_PLAYER_FOLDER, NUM_ROOT_ELEMENTS,
  726. OPERATION_SUCCESSFUL, SplitPath).sendToTarget();
  727. }
  728. } else {
  729. handler.obtainMessage(MSG_UPDATE_BROWSED_PLAYER_FOLDER, 0, INTERNAL_ERROR,
  730. null).sendToTarget();
  731. }
  732. }
  733. @Override
  734. public void onClientUpdateNowPlayingEntries(long[] playList) {
  735. Log.v(TAG, "onClientUpdateNowPlayingEntries");
  736. Handler handler = mLocalHandler.get();
  737. if (handler != null) {
  738. handler.obtainMessage(MSG_NOW_PLAYING_ENTRIES_RECEIVED, 0, 0,
  739. playList).sendToTarget();
  740. }
  741. }
  742. @Override
  743. public void onClientNowPlayingContentChange() {
  744. Log.v(TAG, "onClientNowPlayingContentChange");
  745. Handler handler = mLocalHandler.get();
  746. if (handler != null) {
  747. handler.obtainMessage(MSG_UPDATE_NOW_PLAYING_CONTENT_CHANGED).sendToTarget();
  748. }
  749. }
  750. @Override
  751. public void onClientPlayItemResponse(boolean success) {
  752. Log.v(TAG, "onClientPlayItemResponse");
  753. Handler handler = mLocalHandler.get();
  754. if (handler != null) {
  755. handler.obtainMessage(MSG_PLAY_ITEM_RESPONSE, 0, 0, new Boolean(success))
  756. .sendToTarget();
  757. }
  758. }
  759. }
  760. /* Handles Avrcp messages. */
  761. private final class AvrcpMessageHandler extends Handler {
  762. private AvrcpMessageHandler(Looper looper) {
  763. super(looper);
  764. }
  765. @Override
  766. public void handleMessage(Message msg) {
  767. int deviceIndex = INVALID_DEVICE_INDEX;
  768. switch (msg.what) {
  769. case MESSAGE_PLAYERSETTINGS_TIMEOUT:
  770. Log.e(TAG, "**MESSAGE_PLAYSTATUS_TIMEOUT: Addr: " +
  771. (String)msg.obj + " Msg: " + msg.arg1);
  772. synchronized (mPendingCmds) {
  773. Integer val = new Integer(msg.arg1);
  774. if (!mPendingCmds.contains(val)) {
  775. break;
  776. }
  777. mPendingCmds.remove(val);
  778. }
  779. switch (msg.arg1) {
  780. case GET_ATTRIBUTE_IDS:
  781. getListPlayerappAttrRspNative((byte)def_attrib.length ,
  782. def_attrib, getByteAddress(
  783. mAdapter.getRemoteDevice((String) msg.obj)));
  784. break;
  785. case GET_VALUE_IDS:
  786. switch (mPlayerSettings.attr) {
  787. case ATTRIBUTE_REPEATMODE:
  788. getPlayerAppValueRspNative((byte)value_repmode.length,
  789. value_repmode,
  790. getByteAddress(mAdapter.getRemoteDevice(
  791. (String) msg.obj)));
  792. break;
  793. case ATTRIBUTE_SHUFFLEMODE:
  794. getPlayerAppValueRspNative((byte)value_shufmode.length,
  795. value_shufmode,
  796. getByteAddress(mAdapter.getRemoteDevice(
  797. (String) msg.obj)));
  798. break;
  799. default:
  800. getPlayerAppValueRspNative((byte)value_default.length,
  801. value_default,
  802. getByteAddress(mAdapter.getRemoteDevice(
  803. (String) msg.obj)));
  804. break;
  805. }
  806. break;
  807. case GET_ATTRIBUTE_VALUES:
  808. int j = 0;
  809. byte [] retVal = new byte [mPlayerSettings.attrIds.length*2];
  810. for (int i = 0; i < mPlayerSettings.attrIds.length; i++) {
  811. retVal[j++] = mPlayerSettings.attrIds[i];
  812. if (mPlayerSettings.attrIds[i] == ATTRIBUTE_REPEATMODE) {
  813. retVal[j++] = settingValues.repeat_value;
  814. } else if (mPlayerSettings.attrIds[i] == ATTRIBUTE_SHUFFLEMODE) {
  815. retVal[j++] = settingValues.shuffle_value;
  816. } else {
  817. retVal[j++] = 0x0;
  818. }
  819. }
  820. SendCurrentPlayerValueRspNative((byte)retVal.length ,
  821. retVal, getByteAddress(mAdapter.getRemoteDevice(
  822. (String) msg.obj)));
  823. break;
  824. case SET_ATTRIBUTE_VALUES :
  825. SendSetPlayerAppRspNative(INTERNAL_ERROR, getByteAddress(
  826. mAdapter.getRemoteDevice((String) msg.obj)));
  827. break;
  828. case GET_ATTRIBUTE_TEXT:
  829. String [] attribText = new String [mPlayerSettings.attrIds.length];
  830. for (int i = 0; i < mPlayerSettings.attrIds.length; i++) {
  831. attribText[i] = "";
  832. }
  833. sendSettingsTextRspNative(mPlayerSettings.attrIds.length ,
  834. mPlayerSettings.attrIds, attribText.length,
  835. attribText, getByteAddress(mAdapter.getRemoteDevice(
  836. (String) msg.obj)));
  837. break;
  838. case GET_VALUE_TEXT:
  839. String [] valueText = new String [mPlayerSettings.attrIds.length];
  840. for (int i = 0; i < mPlayerSettings.attrIds.length; i++) {
  841. valueText[i] = "";
  842. }
  843. sendValueTextRspNative(mPlayerSettings.attrIds.length ,
  844. mPlayerSettings.attrIds, valueText.length,
  845. valueText,getByteAddress(mAdapter.getRemoteDevice(
  846. (String) msg.obj)));
  847. break;
  848. default :
  849. Log.e(TAG,"in default case");
  850. break;
  851. }
  852. break;
  853. case MSG_UPDATE_STATE:
  854. /* since we get this from music app we need to update
  855. * current playing start time */
  856. Log.i(TAG,"State change for music app");
  857. updatePlayPauseState(msg.arg2, ((Long) msg.obj).longValue(),
  858. null);
  859. break;
  860. case MSG_SET_METADATA:
  861. updateMetadata((MetadataEditor) msg.obj);
  862. break;
  863. case MSG_UPDATE_AVAILABLE_PLAYERS:
  864. updateAvailableMediaPlayers();
  865. break;
  866. case MSG_UPDATE_ADDRESSED_PLAYER:
  867. updateAddressedMediaPlayer(msg.arg1);
  868. break;
  869. case MSG_UPDATE_BROWSED_PLAYER_FOLDER:
  870. Log.v(TAG, "MSG_UPDATE_BROWSED_PLAYER_FOLDER");
  871. updateBrowsedPlayerFolder(msg.arg1, msg.arg2, (String [])msg.obj);
  872. break;
  873. case MSG_UPDATE_NOW_PLAYING_CONTENT_CHANGED:
  874. Log.v(TAG, "MSG_UPDATE_NOW_PLAYING_CONTENT_CHANGED");
  875. updateNowPlayingContentChanged();
  876. break;
  877. case MSG_PLAY_ITEM_RESPONSE:
  878. Log.v(TAG, "MSG_PLAY_ITEM_RESPONSE");
  879. boolean success = ((Boolean)msg.obj).booleanValue();
  880. Log.v(TAG, "success: " + success);
  881. updatePlayItemResponse(success);
  882. break;
  883. case MSG_NOW_PLAYING_ENTRIES_RECEIVED:
  884. Log.v(TAG, "MSG_NOW_PLAYING_ENTRIES_RECEIVED");
  885. updateNowPlayingEntriesReceived((long [])msg.obj);
  886. break;
  887. case MSG_SET_TRANSPORT_CONTROLS:
  888. updateTransportControls(msg.arg2);
  889. break;
  890. case MSG_SET_GENERATION_ID:
  891. if (DEBUG)
  892. Log.v(TAG, "New genId = " + msg.arg1 +
  893. ", clearing = " + msg.arg2);
  894. break;
  895. case MESSAGE_GET_RC_FEATURES:
  896. {
  897. String address = (String) msg.obj;
  898. if (DEBUG)
  899. Log.v(TAG, "MESSAGE_GET_RC_FEATURES: address="+address+
  900. ", features="+msg.arg1);
  901. BluetoothDevice device = mAdapter.getRemoteDevice(address);
  902. deviceIndex = getIndexForDevice(device);
  903. if (deviceIndex == INVALID_DEVICE_INDEX) {
  904. Log.v(TAG,"device entry not present, bailing out");
  905. return;
  906. }
  907. deviceFeatures[deviceIndex].mFeatures = msg.arg1;
  908. deviceFeatures[deviceIndex].isAbsoluteVolumeSupportingDevice =
  909. ((deviceFeatures[deviceIndex].mFeatures &
  910. BTRC_FEAT_ABSOLUTE_VOLUME) != 0);
  911. mAudioManager.avrcpSupportsAbsoluteVolume(device.getAddress(),
  912. isAbsoluteVolumeSupported());
  913. Log.v(TAG," update audio manager for abs vol state = "
  914. + isAbsoluteVolumeSupported());
  915. if ((deviceFeatures[deviceIndex].mFeatures &
  916. BTRC_FEAT_AVRC_UI_UPDATE) != 0)
  917. {
  918. int NOTIFICATION_ID = android.R.drawable.stat_sys_data_bluetooth;
  919. Notification notification = new Notification.Builder(mContext)
  920. .setContentTitle("Bluetooth Media Browsing")
  921. .setContentText("Peer supports advanced feature")
  922. .setSubText("Re-pair from peer to enable it")
  923. .setSmallIcon(android.R.drawable.stat_sys_data_bluetooth)
  924. .setDefaults(Notification.DEFAULT_ALL)
  925. .build();
  926. NotificationManager manager = (NotificationManager)
  927. mContext.getSystemService(Context.NOTIFICATION_SERVICE);
  928. manager.notify(NOTIFICATION_ID, notification);
  929. Log.v(TAG," update notification manager on remote repair request");
  930. }
  931. break;
  932. }
  933. case MESSAGE_GET_PLAY_STATUS:
  934. {
  935. BluetoothDevice device;
  936. int playState, position;
  937. if (DEBUG)
  938. Log.v(TAG, "MESSAGE_GET_PLAY_STATUS");
  939. Log.v(TAG, "Event for device address " + (String)msg.obj);
  940. device = mAdapter.getRemoteDevice((String) msg.obj);
  941. deviceIndex = getIndexForDevice(device);
  942. if (deviceIndex == INVALID_DEVICE_INDEX) {
  943. Log.e(TAG,"Invalid device index for play status");
  944. break;
  945. }
  946. playState = convertPlayStateToPlayStatus(deviceFeatures[deviceIndex].mCurrentPlayState);
  947. position = (int)getPlayPosition(device);
  948. Log.v(TAG, "Play Status for : " + device.getName() +
  949. " state: " + playState + " position: " + position);
  950. if (position == -1) {
  951. Log.v(TAG, "Force play postion to 0, for getPlayStatus Rsp");
  952. position = 0;
  953. }
  954. getPlayStatusRspNative(playState, (int)mSongLengthMs, position,
  955. getByteAddress(device));
  956. break;
  957. }
  958. case MESSAGE_GET_ELEM_ATTRS:
  959. {
  960. String[] textArray;
  961. int[] attrIds;
  962. byte numAttr = (byte) msg.arg1;
  963. ItemAttr itemAttr = (ItemAttr)msg.obj;
  964. Log.v(TAG, "event for device address " + itemAttr.mAddress);
  965. ArrayList<Integer> attrList = itemAttr.mAttrList;
  966. if (DEBUG)
  967. Log.v(TAG, "MESSAGE_GET_ELEM_ATTRS:numAttr=" + numAttr);
  968. attrIds = new int[numAttr];
  969. textArray = new String[numAttr];
  970. for (int i = 0; i < numAttr; ++i) {
  971. attrIds[i] = attrList.get(i).intValue();
  972. textArray[i] = getAttributeString(attrIds[i]);
  973. }
  974. getElementAttrRspNative(numAttr ,attrIds ,textArray ,
  975. getByteAddress(mAdapter.getRemoteDevice(itemAttr.mAddress)));
  976. break;
  977. }
  978. case MESSAGE_REGISTER_NOTIFICATION:
  979. if (DEBUG)
  980. Log.v(TAG, "MESSAGE_REGISTER_NOTIFICATION:event=" + msg.arg1 +
  981. " param=" + msg.arg2);
  982. processRegisterNotification(msg.arg1, msg.arg2, (String) msg.obj);
  983. break;
  984. case MESSAGE_PLAY_INTERVAL_TIMEOUT:
  985. if (DEBUG)
  986. Log.v(TAG, "MESSAGE_PLAY_INTERVAL_TIMEOUT");
  987. Log.v(TAG, "event for device address " + (BluetoothDevice)msg.obj);
  988. deviceIndex = getIndexForDevice((BluetoothDevice) msg.obj);
  989. if (deviceIndex == INVALID_DEVICE_INDEX) {
  990. Log.e(TAG,"invalid index for device");
  991. break;
  992. }
  993. deviceFeatures[deviceIndex].mPlayPosChangedNT =
  994. NOTIFICATION_TYPE_CHANGED;
  995. Log.v(TAG, "event for device address " + (BluetoothDevice) msg.obj);
  996. registerNotificationRspPlayPosNative(deviceFeatures[deviceIndex].mPlayPosChangedNT,
  997. (int)getPlayPosition((BluetoothDevice) msg.obj) ,
  998. getByteAddress((BluetoothDevice) msg.obj));
  999. break;
  1000. case MESSAGE_SET_ADDR_PLAYER_REQ_TIMEOU