PageRenderTime 100ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/src/com/android/bluetooth/avrcpcontroller/AvrcpPlayer.java

https://github.com/Evervolv/android_packages_apps_Bluetooth
Java | 375 lines | 257 code | 43 blank | 75 comment | 26 complexity | 8733de37bcad298d23f95138931e6e7a MD5 | raw file
  1. /*
  2. * Copyright (C) 2016 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.android.bluetooth.avrcpcontroller;
  17. import android.bluetooth.BluetoothDevice;
  18. import android.net.Uri;
  19. import android.os.SystemClock;
  20. import android.support.v4.media.session.MediaSessionCompat;
  21. import android.support.v4.media.session.PlaybackStateCompat;
  22. import android.util.Log;
  23. import java.util.Arrays;
  24. /*
  25. * Contains information about remote player
  26. */
  27. class AvrcpPlayer {
  28. private static final String TAG = "AvrcpPlayer";
  29. private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
  30. public static final int DEFAULT_ID = -1;
  31. public static final int TYPE_UNKNOWN = -1;
  32. public static final int TYPE_AUDIO = 0;
  33. public static final int TYPE_VIDEO = 1;
  34. public static final int TYPE_BROADCASTING_AUDIO = 2;
  35. public static final int TYPE_BROADCASTING_VIDEO = 3;
  36. public static final int SUB_TYPE_UNKNOWN = -1;
  37. public static final int SUB_TYPE_AUDIO_BOOK = 0;
  38. public static final int SUB_TYPE_PODCAST = 1;
  39. public static final int FEATURE_PLAY = 40;
  40. public static final int FEATURE_STOP = 41;
  41. public static final int FEATURE_PAUSE = 42;
  42. public static final int FEATURE_REWIND = 44;
  43. public static final int FEATURE_FAST_FORWARD = 45;
  44. public static final int FEATURE_FORWARD = 47;
  45. public static final int FEATURE_PREVIOUS = 48;
  46. public static final int FEATURE_BROWSING = 59;
  47. public static final int FEATURE_NOW_PLAYING = 65;
  48. private BluetoothDevice mDevice;
  49. private int mPlayStatus = PlaybackStateCompat.STATE_NONE;
  50. private long mPlayTime = PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN;
  51. private long mPlayTimeUpdate = 0;
  52. private float mPlaySpeed = 1;
  53. private int mId;
  54. private String mName = "";
  55. private int mPlayerType;
  56. private byte[] mPlayerFeatures = new byte[16];
  57. private long mAvailableActions = PlaybackStateCompat.ACTION_PREPARE;
  58. private AvrcpItem mCurrentTrack;
  59. private PlaybackStateCompat mPlaybackStateCompat;
  60. private PlayerApplicationSettings mSupportedPlayerApplicationSettings =
  61. new PlayerApplicationSettings();
  62. private PlayerApplicationSettings mCurrentPlayerApplicationSettings;
  63. private AvrcpPlayer(BluetoothDevice device, int id, int playerType, int playerSubType,
  64. String name, byte[] playerFeatures, int playStatus) {
  65. mDevice = device;
  66. mId = id;
  67. mName = name;
  68. mPlayerType = playerType;
  69. mPlayerFeatures = Arrays.copyOf(playerFeatures, playerFeatures.length);
  70. PlaybackStateCompat.Builder playbackStateBuilder = new PlaybackStateCompat.Builder()
  71. .setActions(mAvailableActions);
  72. mPlaybackStateCompat = playbackStateBuilder.build();
  73. updateAvailableActions();
  74. setPlayStatus(playStatus);
  75. }
  76. public BluetoothDevice getDevice() {
  77. return mDevice;
  78. }
  79. public int getId() {
  80. return mId;
  81. }
  82. public String getName() {
  83. return mName;
  84. }
  85. public void setPlayTime(int playTime) {
  86. mPlayTime = playTime;
  87. mPlayTimeUpdate = SystemClock.elapsedRealtime();
  88. mPlaybackStateCompat = new PlaybackStateCompat.Builder(mPlaybackStateCompat).setState(
  89. mPlayStatus, mPlayTime,
  90. mPlaySpeed).build();
  91. }
  92. public long getPlayTime() {
  93. return mPlayTime;
  94. }
  95. public void setPlayStatus(int playStatus) {
  96. if (mPlayTime != PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN) {
  97. mPlayTime += mPlaySpeed * (SystemClock.elapsedRealtime()
  98. - mPlaybackStateCompat.getLastPositionUpdateTime());
  99. }
  100. mPlayStatus = playStatus;
  101. switch (mPlayStatus) {
  102. case PlaybackStateCompat.STATE_STOPPED:
  103. mPlaySpeed = 0;
  104. break;
  105. case PlaybackStateCompat.STATE_PLAYING:
  106. mPlaySpeed = 1;
  107. break;
  108. case PlaybackStateCompat.STATE_PAUSED:
  109. mPlaySpeed = 0;
  110. break;
  111. case PlaybackStateCompat.STATE_FAST_FORWARDING:
  112. mPlaySpeed = 3;
  113. break;
  114. case PlaybackStateCompat.STATE_REWINDING:
  115. mPlaySpeed = -3;
  116. break;
  117. }
  118. mPlaybackStateCompat = new PlaybackStateCompat.Builder(mPlaybackStateCompat).setState(
  119. mPlayStatus, mPlayTime,
  120. mPlaySpeed).build();
  121. }
  122. public void setSupportedPlayerApplicationSettings(
  123. PlayerApplicationSettings playerApplicationSettings) {
  124. mSupportedPlayerApplicationSettings = playerApplicationSettings;
  125. updateAvailableActions();
  126. }
  127. public void setCurrentPlayerApplicationSettings(
  128. PlayerApplicationSettings playerApplicationSettings) {
  129. Log.d(TAG, "Settings changed");
  130. mCurrentPlayerApplicationSettings = playerApplicationSettings;
  131. MediaSessionCompat session = BluetoothMediaBrowserService.getSession();
  132. session.setRepeatMode(mCurrentPlayerApplicationSettings.getSetting(
  133. PlayerApplicationSettings.REPEAT_STATUS));
  134. session.setShuffleMode(mCurrentPlayerApplicationSettings.getSetting(
  135. PlayerApplicationSettings.SHUFFLE_STATUS));
  136. }
  137. public int getPlayStatus() {
  138. return mPlayStatus;
  139. }
  140. public boolean supportsFeature(int featureId) {
  141. int byteNumber = featureId / 8;
  142. byte bitMask = (byte) (1 << (featureId % 8));
  143. return (mPlayerFeatures[byteNumber] & bitMask) == bitMask;
  144. }
  145. public boolean supportsSetting(int settingType, int settingValue) {
  146. return mSupportedPlayerApplicationSettings.supportsSetting(settingType, settingValue);
  147. }
  148. public PlaybackStateCompat getPlaybackState() {
  149. if (DBG) {
  150. Log.d(TAG, "getPlayBackState state " + mPlayStatus + " time " + mPlayTime);
  151. }
  152. return mPlaybackStateCompat;
  153. }
  154. public synchronized void updateCurrentTrack(AvrcpItem update) {
  155. if (update != null) {
  156. long trackNumber = update.getTrackNumber();
  157. mPlaybackStateCompat = new PlaybackStateCompat.Builder(
  158. mPlaybackStateCompat).setActiveQueueItemId(
  159. trackNumber - 1).build();
  160. }
  161. mCurrentTrack = update;
  162. }
  163. public synchronized boolean notifyImageDownload(String uuid, Uri imageUri) {
  164. if (DBG) Log.d(TAG, "Got an image download -- uuid=" + uuid + ", uri=" + imageUri);
  165. if (uuid == null || imageUri == null || mCurrentTrack == null) return false;
  166. if (uuid.equals(mCurrentTrack.getCoverArtUuid())) {
  167. mCurrentTrack.setCoverArtLocation(imageUri);
  168. if (DBG) Log.d(TAG, "Image UUID '" + uuid + "' was added to current track.");
  169. return true;
  170. }
  171. return false;
  172. }
  173. public synchronized AvrcpItem getCurrentTrack() {
  174. return mCurrentTrack;
  175. }
  176. private void updateAvailableActions() {
  177. mAvailableActions = PlaybackStateCompat.ACTION_PREPARE;
  178. if (supportsFeature(FEATURE_PLAY)) {
  179. mAvailableActions = mAvailableActions | PlaybackStateCompat.ACTION_PLAY;
  180. }
  181. if (supportsFeature(FEATURE_STOP)) {
  182. mAvailableActions = mAvailableActions | PlaybackStateCompat.ACTION_STOP;
  183. }
  184. if (supportsFeature(FEATURE_PAUSE)) {
  185. mAvailableActions = mAvailableActions | PlaybackStateCompat.ACTION_PAUSE;
  186. }
  187. if (supportsFeature(FEATURE_REWIND)) {
  188. mAvailableActions = mAvailableActions | PlaybackStateCompat.ACTION_REWIND;
  189. }
  190. if (supportsFeature(FEATURE_FAST_FORWARD)) {
  191. mAvailableActions = mAvailableActions | PlaybackStateCompat.ACTION_FAST_FORWARD;
  192. }
  193. if (supportsFeature(FEATURE_FORWARD)) {
  194. mAvailableActions = mAvailableActions | PlaybackStateCompat.ACTION_SKIP_TO_NEXT;
  195. }
  196. if (supportsFeature(FEATURE_PREVIOUS)) {
  197. mAvailableActions = mAvailableActions | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS;
  198. }
  199. if (mSupportedPlayerApplicationSettings.supportsSetting(
  200. PlayerApplicationSettings.REPEAT_STATUS)) {
  201. mAvailableActions |= PlaybackStateCompat.ACTION_SET_REPEAT_MODE;
  202. }
  203. if (mSupportedPlayerApplicationSettings.supportsSetting(
  204. PlayerApplicationSettings.SHUFFLE_STATUS)) {
  205. mAvailableActions |= PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE;
  206. }
  207. mPlaybackStateCompat = new PlaybackStateCompat.Builder(mPlaybackStateCompat)
  208. .setActions(mAvailableActions).build();
  209. if (DBG) Log.d(TAG, "Supported Actions = " + mAvailableActions);
  210. }
  211. @Override
  212. public String toString() {
  213. return "<AvrcpPlayer id=" + mId + " name=" + mName + " track=" + mCurrentTrack
  214. + " playState=" + mPlaybackStateCompat + ">";
  215. }
  216. /**
  217. * A Builder object for an AvrcpPlayer
  218. */
  219. public static class Builder {
  220. private static final String TAG = "AvrcpPlayer.Builder";
  221. private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
  222. private BluetoothDevice mDevice = null;
  223. private int mPlayerId = AvrcpPlayer.DEFAULT_ID;
  224. private int mPlayerType = AvrcpPlayer.TYPE_UNKNOWN;
  225. private int mPlayerSubType = AvrcpPlayer.SUB_TYPE_UNKNOWN;
  226. private String mPlayerName = null;
  227. private byte[] mSupportedFeatures = new byte[16];
  228. private int mPlayStatus = PlaybackStateCompat.STATE_NONE;
  229. private long mPlayTime = PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN;
  230. private float mPlaySpeed = 1;
  231. private long mPlayTimeUpdate = 0;
  232. private AvrcpItem mTrack = null;
  233. /**
  234. * Set the device that this Player came from
  235. *
  236. * @param device The BleutoothDevice representing the remote device
  237. * @return This object, so you can continue building
  238. */
  239. public Builder setDevice(BluetoothDevice device) {
  240. mDevice = device;
  241. return this;
  242. }
  243. /**
  244. * Set the Player ID for this Player
  245. *
  246. * @param playerId The ID for this player, defined in AVRCP 6.10.2.1
  247. * @return This object, so you can continue building
  248. */
  249. public Builder setPlayerId(int playerId) {
  250. mPlayerId = playerId;
  251. return this;
  252. }
  253. /**
  254. * Set the Player Type for this Player
  255. *
  256. * @param playerType The type for this player, defined in AVRCP 6.10.2.1
  257. * @return This object, so you can continue building
  258. */
  259. public Builder setPlayerType(int playerType) {
  260. mPlayerType = playerType;
  261. return this;
  262. }
  263. /**
  264. * Set the Player Sub-type for this Player
  265. *
  266. * @param playerSubType The sub-type for this player, defined in AVRCP 6.10.2.1
  267. * @return This object, so you can continue building
  268. */
  269. public Builder setPlayerSubType(int playerSubType) {
  270. mPlayerSubType = playerSubType;
  271. return this;
  272. }
  273. /**
  274. * Set the name for this Player. This is what users will see when browsing.
  275. *
  276. * @param name The name for this player, defined in AVRCP 6.10.2.1
  277. * @return This object, so you can continue building
  278. */
  279. public Builder setName(String name) {
  280. mPlayerName = name;
  281. return this;
  282. }
  283. /**
  284. * Set the entire set of supported features for this Player.
  285. *
  286. * @param features The feature set for this player, defined in AVRCP 6.10.2.1
  287. * @return This object, so you can continue building
  288. */
  289. public Builder setSupportedFeatures(byte[] supportedFeatures) {
  290. mSupportedFeatures = supportedFeatures;
  291. return this;
  292. }
  293. /**
  294. * Set a single features as supported for this Player.
  295. *
  296. * @param feature The feature for this player, defined in AVRCP 6.10.2.1
  297. * @return This object, so you can continue building
  298. */
  299. public Builder setSupportedFeature(int feature) {
  300. int byteNumber = feature / 8;
  301. byte bitMask = (byte) (1 << (feature % 8));
  302. mSupportedFeatures[byteNumber] = (byte) (mSupportedFeatures[byteNumber] | bitMask);
  303. return this;
  304. }
  305. /**
  306. * Set the initial play status of the Player.
  307. *
  308. * @param playStatus The play state for this player as a PlaybackStateCompat.STATE_* value
  309. * @return This object, so you can continue building
  310. */
  311. public Builder setPlayStatus(int playStatus) {
  312. mPlayStatus = playStatus;
  313. return this;
  314. }
  315. /**
  316. * Set the initial play status of the Player.
  317. *
  318. * @param track The initial track for this player
  319. * @return This object, so you can continue building
  320. */
  321. public Builder setCurrentTrack(AvrcpItem track) {
  322. mTrack = track;
  323. return this;
  324. }
  325. public AvrcpPlayer build() {
  326. AvrcpPlayer player = new AvrcpPlayer(mDevice, mPlayerId, mPlayerType, mPlayerSubType,
  327. mPlayerName, mSupportedFeatures, mPlayStatus);
  328. player.updateCurrentTrack(mTrack);
  329. return player;
  330. }
  331. }
  332. }