1 /* 2 * Copyright (C) 2015 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 17 package com.android.bluetooth.avrcp; 18 19 import android.bluetooth.BluetoothDevice; 20 import android.bluetooth.BluetoothAvrcpPlayerSettings; 21 import com.android.bluetooth.Utils; 22 import java.util.ArrayList; 23 import java.util.Arrays; 24 import java.util.List; 25 import java.util.HashMap; 26 import android.util.Log; 27 import java.nio.charset.Charset; 28 import java.nio.ByteBuffer; 29 import android.media.session.PlaybackState; 30 import android.media.MediaMetadata; 31 /** 32 * Provides helper classes used by other AvrcpControllerClasses. 33 */ 34 class AvrcpUtils { 35 36 private static final String TAG = "AvrcpUtils"; 37 /* 38 * First 2 apis are utility functions to converts values from AvrcpPlayerSettings defined 39 * in BluetoothAvrcpPlayerSettings to BT spec defined Id and Vals. 40 */ mapAttribIdValtoAvrcpPlayerSetting( byte attribId, byte attribVal)41 public static int mapAttribIdValtoAvrcpPlayerSetting( byte attribId, byte attribVal) { 42 if(AvrcpControllerConstants.VDBG) Log.d(TAG, "attribId: " + attribId + " attribVal: " + attribVal); 43 if (attribId == AvrcpControllerConstants.ATTRIB_EQUALIZER_STATUS) { 44 switch(attribVal) { 45 case AvrcpControllerConstants.EQUALIZER_STATUS_OFF: 46 return BluetoothAvrcpPlayerSettings.STATE_OFF; 47 case AvrcpControllerConstants.EQUALIZER_STATUS_ON: 48 return BluetoothAvrcpPlayerSettings.STATE_ON; 49 } 50 } 51 else if (attribId == AvrcpControllerConstants.ATTRIB_REPEAT_STATUS) { 52 switch(attribVal) { 53 case AvrcpControllerConstants.REPEAT_STATUS_ALL_TRACK_REPEAT: 54 return BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK; 55 case AvrcpControllerConstants.REPEAT_STATUS_GROUP_REPEAT: 56 return BluetoothAvrcpPlayerSettings.STATE_GROUP; 57 case AvrcpControllerConstants.REPEAT_STATUS_OFF: 58 return BluetoothAvrcpPlayerSettings.STATE_OFF; 59 case AvrcpControllerConstants.REPEAT_STATUS_SINGLE_TRACK_REPEAT: 60 return BluetoothAvrcpPlayerSettings.STATE_SINGLE_TRACK; 61 } 62 } 63 else if (attribId == AvrcpControllerConstants.ATTRIB_SCAN_STATUS) { 64 switch(attribVal) { 65 case AvrcpControllerConstants.SCAN_STATUS_ALL_TRACK_SCAN: 66 return BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK; 67 case AvrcpControllerConstants.SCAN_STATUS_GROUP_SCAN: 68 return BluetoothAvrcpPlayerSettings.STATE_GROUP; 69 case AvrcpControllerConstants.SCAN_STATUS_OFF: 70 return BluetoothAvrcpPlayerSettings.STATE_OFF; 71 } 72 } 73 else if (attribId == AvrcpControllerConstants.ATTRIB_SHUFFLE_STATUS) { 74 switch(attribVal) { 75 case AvrcpControllerConstants.SHUFFLE_STATUS_ALL_TRACK_SHUFFLE: 76 return BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK; 77 case AvrcpControllerConstants.SHUFFLE_STATUS_GROUP_SHUFFLE: 78 return BluetoothAvrcpPlayerSettings.STATE_GROUP; 79 case AvrcpControllerConstants.SHUFFLE_STATUS_OFF: 80 return BluetoothAvrcpPlayerSettings.STATE_OFF; 81 } 82 } 83 return BluetoothAvrcpPlayerSettings.STATE_INVALID; 84 } mapAvrcpPlayerSettingstoBTAttribVal(int mSetting, int mSettingVal)85 public static int mapAvrcpPlayerSettingstoBTAttribVal(int mSetting, int mSettingVal) { 86 if (mSetting == BluetoothAvrcpPlayerSettings.SETTING_EQUALIZER) { 87 switch(mSettingVal) { 88 case BluetoothAvrcpPlayerSettings.STATE_OFF: 89 return AvrcpControllerConstants.EQUALIZER_STATUS_OFF; 90 case BluetoothAvrcpPlayerSettings.STATE_ON: 91 return AvrcpControllerConstants.EQUALIZER_STATUS_ON; 92 } 93 } 94 else if (mSetting == BluetoothAvrcpPlayerSettings.SETTING_REPEAT) { 95 switch(mSettingVal) { 96 case BluetoothAvrcpPlayerSettings.STATE_OFF: 97 return AvrcpControllerConstants.REPEAT_STATUS_OFF; 98 case BluetoothAvrcpPlayerSettings.STATE_SINGLE_TRACK: 99 return AvrcpControllerConstants.REPEAT_STATUS_SINGLE_TRACK_REPEAT; 100 case BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK: 101 return AvrcpControllerConstants.REPEAT_STATUS_ALL_TRACK_REPEAT; 102 case BluetoothAvrcpPlayerSettings.STATE_GROUP: 103 return AvrcpControllerConstants.REPEAT_STATUS_GROUP_REPEAT; 104 } 105 } 106 else if (mSetting == BluetoothAvrcpPlayerSettings.SETTING_SHUFFLE) { 107 switch(mSettingVal) { 108 case BluetoothAvrcpPlayerSettings.STATE_OFF: 109 return AvrcpControllerConstants.SHUFFLE_STATUS_OFF; 110 case BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK: 111 return AvrcpControllerConstants.SHUFFLE_STATUS_ALL_TRACK_SHUFFLE; 112 case BluetoothAvrcpPlayerSettings.STATE_GROUP: 113 return AvrcpControllerConstants.SHUFFLE_STATUS_GROUP_SHUFFLE; 114 } 115 } 116 else if (mSetting == BluetoothAvrcpPlayerSettings.SETTING_SCAN) { 117 switch(mSettingVal) { 118 case BluetoothAvrcpPlayerSettings.STATE_OFF: 119 return AvrcpControllerConstants.SCAN_STATUS_OFF; 120 case BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK: 121 return AvrcpControllerConstants.SCAN_STATUS_ALL_TRACK_SCAN; 122 case BluetoothAvrcpPlayerSettings.STATE_GROUP: 123 return AvrcpControllerConstants.SCAN_STATUS_GROUP_SCAN; 124 } 125 } 126 return AvrcpControllerConstants.STATUS_INVALID; 127 } 128 /* 129 * This api converts btPlayStatus to PlaybackState 130 */ mapBtPlayStatustoPlayBackState(byte btPlayStatus, long btPlayPos)131 public static PlaybackState mapBtPlayStatustoPlayBackState(byte btPlayStatus, long btPlayPos) { 132 int mState = PlaybackState.STATE_NONE; 133 long position = btPlayPos; 134 float speed = 1; 135 switch(btPlayStatus) { 136 case AvrcpControllerConstants.PLAY_STATUS_STOPPED: 137 mState = PlaybackState.STATE_STOPPED; 138 position = 0; 139 speed = 0; 140 break; 141 case AvrcpControllerConstants.PLAY_STATUS_PLAYING: 142 mState = PlaybackState.STATE_PLAYING; 143 break; 144 case AvrcpControllerConstants.PLAY_STATUS_PAUSED: 145 mState = PlaybackState.STATE_PAUSED; 146 speed = 0; 147 break; 148 case AvrcpControllerConstants.PLAY_STATUS_FWD_SEEK: 149 mState = PlaybackState.STATE_FAST_FORWARDING; 150 speed = 3; 151 break; 152 case AvrcpControllerConstants.PLAY_STATUS_REV_SEEK: 153 mState = PlaybackState.STATE_REWINDING; 154 speed = -3; 155 break; 156 } 157 return new PlaybackState.Builder().setState(mState, position, speed).build(); 158 } 159 /* 160 * This api converts meta info into MediaMetaData 161 */ getMediaMetaData(TrackInfo mTrackInfo)162 public static MediaMetadata getMediaMetaData(TrackInfo mTrackInfo) { 163 if(AvrcpControllerConstants.VDBG) Log.d(TAG, " TrackInfo " + mTrackInfo.toString()); 164 MediaMetadata.Builder mMetaDataBuilder = new MediaMetadata.Builder(); 165 mMetaDataBuilder.putString(MediaMetadata.METADATA_KEY_ARTIST, 166 mTrackInfo.mArtistName); 167 mMetaDataBuilder.putString(MediaMetadata.METADATA_KEY_TITLE, 168 mTrackInfo.mTrackTitle); 169 mMetaDataBuilder.putString(MediaMetadata.METADATA_KEY_ALBUM, 170 mTrackInfo.mAlbumTitle); 171 mMetaDataBuilder.putString(MediaMetadata.METADATA_KEY_GENRE, 172 mTrackInfo.mGenre); 173 mMetaDataBuilder.putLong(MediaMetadata.METADATA_KEY_TRACK_NUMBER, 174 mTrackInfo.mTrackNum); 175 mMetaDataBuilder.putLong(MediaMetadata.METADATA_KEY_NUM_TRACKS, 176 mTrackInfo.mTotalTracks); 177 mMetaDataBuilder.putLong(MediaMetadata.METADATA_KEY_DURATION, 178 mTrackInfo.mTrackLen); 179 mMetaDataBuilder.putString(MediaMetadata.METADATA_KEY_MEDIA_ID, 180 String.valueOf(mTrackInfo.mItemUid)); 181 return mMetaDataBuilder.build(); 182 } 183 /* 184 * Display Apis 185 */ displayMetaData(MediaMetadata mMetaData)186 public static String displayMetaData(MediaMetadata mMetaData) { 187 StringBuffer sb = new StringBuffer(); 188 /* this will only show artist, title and album */ 189 sb.append(mMetaData.getDescription().toString() + " "); 190 if(mMetaData.containsKey(MediaMetadata.METADATA_KEY_GENRE)) 191 sb.append(mMetaData.getString(MediaMetadata.METADATA_KEY_GENRE) + " "); 192 if(mMetaData.containsKey(MediaMetadata.METADATA_KEY_MEDIA_ID)) 193 sb.append(mMetaData.getString(MediaMetadata.METADATA_KEY_MEDIA_ID) + " "); 194 if(mMetaData.containsKey(MediaMetadata.METADATA_KEY_TRACK_NUMBER)) 195 sb.append(Long.toString(mMetaData.getLong(MediaMetadata.METADATA_KEY_TRACK_NUMBER)) + " "); 196 if(mMetaData.containsKey(MediaMetadata.METADATA_KEY_NUM_TRACKS)) 197 sb.append(Long.toString(mMetaData.getLong(MediaMetadata.METADATA_KEY_NUM_TRACKS)) + " "); 198 if(mMetaData.containsKey(MediaMetadata.METADATA_KEY_TRACK_NUMBER)) 199 sb.append(Long.toString(mMetaData.getLong(MediaMetadata.METADATA_KEY_DURATION)) + " "); 200 if(mMetaData.containsKey(MediaMetadata.METADATA_KEY_TRACK_NUMBER)) 201 sb.append(Long.toString(mMetaData.getLong(MediaMetadata.METADATA_KEY_DURATION)) + " "); 202 return sb.toString(); 203 } displayBluetoothAvrcpSettings(BluetoothAvrcpPlayerSettings mSett)204 public static String displayBluetoothAvrcpSettings(BluetoothAvrcpPlayerSettings mSett) { 205 StringBuffer sb = new StringBuffer(); 206 int supportedSetting = mSett.getSettings(); 207 if(AvrcpControllerConstants.VDBG) Log.d(TAG," setting: " + supportedSetting); 208 if((supportedSetting & BluetoothAvrcpPlayerSettings.SETTING_EQUALIZER) != 0) { 209 sb.append(" EQ : "); 210 sb.append(Integer.toString(mSett.getSettingValue(BluetoothAvrcpPlayerSettings. 211 SETTING_EQUALIZER))); 212 } 213 if((supportedSetting & BluetoothAvrcpPlayerSettings.SETTING_REPEAT) != 0) { 214 sb.append(" REPEAT : "); 215 sb.append(Integer.toString(mSett.getSettingValue(BluetoothAvrcpPlayerSettings. 216 SETTING_REPEAT))); 217 } 218 if((supportedSetting & BluetoothAvrcpPlayerSettings.SETTING_SHUFFLE) != 0) { 219 sb.append(" SHUFFLE : "); 220 sb.append(Integer.toString(mSett.getSettingValue(BluetoothAvrcpPlayerSettings. 221 SETTING_SHUFFLE))); 222 } 223 if((supportedSetting & BluetoothAvrcpPlayerSettings.SETTING_SCAN) != 0) { 224 sb.append(" SCAN : "); 225 sb.append(Integer.toString(mSett.getSettingValue(BluetoothAvrcpPlayerSettings. 226 SETTING_SCAN))); 227 } 228 return sb.toString(); 229 } 230 } 231 /* 232 * Contains information about remote device 233 */ 234 class RemoteDevice { 235 BluetoothDevice mBTDevice; 236 int mRemoteFeatures; 237 int mBatteryStatus; 238 int mSystemStatus; 239 int mAbsVolNotificationState; 240 int mNotificationLabel; 241 boolean mFirstAbsVolCmdRecvd; 242 cleanup()243 public void cleanup() { 244 mBTDevice = null; 245 mRemoteFeatures = AvrcpControllerConstants.BTRC_FEAT_NONE; 246 mBatteryStatus = AvrcpControllerConstants.BATT_POWER_UNDEFINED; 247 mSystemStatus = AvrcpControllerConstants.SYSTEM_STATUS_UNDEFINED; 248 mAbsVolNotificationState = AvrcpControllerConstants.DEFER_VOLUME_CHANGE_RSP; 249 mNotificationLabel = AvrcpControllerConstants.VOLUME_LABEL_UNDEFINED; 250 mFirstAbsVolCmdRecvd = false; 251 } 252 RemoteDevice(BluetoothDevice mDevice)253 public RemoteDevice(BluetoothDevice mDevice) { 254 mBTDevice = mDevice; 255 mRemoteFeatures = AvrcpControllerConstants.BTRC_FEAT_NONE; 256 mBatteryStatus = AvrcpControllerConstants.BATT_POWER_UNDEFINED; 257 mSystemStatus = AvrcpControllerConstants.SYSTEM_STATUS_UNDEFINED; 258 mAbsVolNotificationState = AvrcpControllerConstants.DEFER_VOLUME_CHANGE_RSP; 259 mNotificationLabel = AvrcpControllerConstants.VOLUME_LABEL_UNDEFINED; 260 mFirstAbsVolCmdRecvd = false; 261 } 262 isBrowsingSupported()263 public boolean isBrowsingSupported() { 264 if((mRemoteFeatures & AvrcpControllerConstants.BTRC_FEAT_BROWSE) != 0) 265 return true; 266 else 267 return false; 268 } isMetaDataSupported()269 public boolean isMetaDataSupported() { 270 if((mRemoteFeatures & AvrcpControllerConstants.BTRC_FEAT_METADATA) != 0) 271 return true; 272 else 273 return false; 274 } 275 } 276 277 /* 278 * Base Class for Media Item 279 */ 280 class MediaItem { 281 /* 282 * This is a combination of locaiton and item. Spec Snippet 283 * In VFS if same item is in different location it may have same uid. 284 * In Now Playing same item should have differnt UID 285 * Can never be 0, used only for GetElementAttributes 286 * TODO: UID counter, which is used for database aware player 287 */ 288 double mItemUid; 289 } 290 291 /* 292 * Contains information Player Application Setting 293 */ 294 class PlayerApplicationSettings { 295 public byte attr_Id; 296 public byte attr_val; 297 public byte [] supported_values; 298 public String attr_text; 299 public String [] supported_values_text;// This is to keep displayable text in UTF-8 300 } 301 /* 302 * Contains information about remote player 303 */ 304 class PlayerInfo { 305 private static final String TAG = "PlayerInfo"; 306 byte mPlayStatus; 307 long mPlayTime; 308 /* 309 * 2 byte player id to identify player. 310 * In 1.3 this value will be set to zero 311 */ 312 char mPlayerId; 313 ArrayList<PlayerApplicationSettings> mPlayerAppSetting; resetPlayer()314 private void resetPlayer() { 315 mPlayStatus = AvrcpControllerConstants.PLAY_STATUS_STOPPED; 316 mPlayTime = AvrcpControllerConstants.PLAYING_TIME_INVALID; 317 mPlayerId = 0; 318 mPlayerAppSetting = new ArrayList<PlayerApplicationSettings>(); 319 } PlayerInfo()320 public PlayerInfo() { 321 resetPlayer(); 322 } setSupportedPlayerAppSetting(ByteBuffer bb)323 public void setSupportedPlayerAppSetting (ByteBuffer bb) { 324 /* ByteBuffer has to be of the following format 325 * id, num_values, values[] 326 */ 327 while(bb.hasRemaining()) { 328 PlayerApplicationSettings plAppSetting = new PlayerApplicationSettings(); 329 plAppSetting.attr_Id = bb.get(); 330 byte numSupportedVals = bb.get(); 331 plAppSetting.supported_values = new byte[numSupportedVals]; 332 for (int i = 0; i<numSupportedVals; i++) { 333 plAppSetting.supported_values[i] = bb.get(); 334 } 335 mPlayerAppSetting.add(plAppSetting); 336 } 337 } updatePlayerAppSetting(ByteBuffer bb)338 public void updatePlayerAppSetting(ByteBuffer bb) { 339 /* ByteBuffer has to be of the following format 340 * <id, value> 341 */ 342 if(mPlayerAppSetting.isEmpty()) 343 return; 344 while(bb.hasRemaining()) { 345 byte attribId = bb.get(); 346 for(PlayerApplicationSettings plAppSetting: mPlayerAppSetting) { 347 if(plAppSetting.attr_Id == attribId) 348 plAppSetting.attr_val = bb.get(); 349 } 350 } 351 } 352 getSupportedPlayerAppSetting()353 public BluetoothAvrcpPlayerSettings getSupportedPlayerAppSetting() { 354 /* 355 * Here we create PlayerAppSetting 356 * based on BluetoothAvrcpPlayerSettings 357 */ 358 int supportedSettings = 0; // Player App Setting used by BluetoothAvrcpPlayerSettings. 359 for(PlayerApplicationSettings plAppSetting: mPlayerAppSetting) { 360 switch(plAppSetting.attr_Id) { 361 case AvrcpControllerConstants.ATTRIB_EQUALIZER_STATUS: 362 supportedSettings |= BluetoothAvrcpPlayerSettings.SETTING_EQUALIZER; 363 break; 364 case AvrcpControllerConstants.ATTRIB_REPEAT_STATUS: 365 supportedSettings |= BluetoothAvrcpPlayerSettings.SETTING_REPEAT; 366 break; 367 case AvrcpControllerConstants.ATTRIB_SCAN_STATUS: 368 supportedSettings |= BluetoothAvrcpPlayerSettings.SETTING_SCAN; 369 break; 370 case AvrcpControllerConstants.ATTRIB_SHUFFLE_STATUS: 371 supportedSettings |= BluetoothAvrcpPlayerSettings.SETTING_SHUFFLE; 372 break; 373 } 374 } 375 BluetoothAvrcpPlayerSettings mAvrcpPlayerAppSetting = new 376 BluetoothAvrcpPlayerSettings(supportedSettings); 377 for(PlayerApplicationSettings plAppSetting: mPlayerAppSetting) { 378 switch(plAppSetting.attr_Id) { 379 case AvrcpControllerConstants.ATTRIB_EQUALIZER_STATUS: 380 mAvrcpPlayerAppSetting.addSettingValue(BluetoothAvrcpPlayerSettings.SETTING_EQUALIZER, 381 AvrcpUtils.mapAttribIdValtoAvrcpPlayerSetting(plAppSetting.attr_Id, 382 plAppSetting.attr_val)); 383 break; 384 case AvrcpControllerConstants.ATTRIB_REPEAT_STATUS: 385 mAvrcpPlayerAppSetting.addSettingValue(BluetoothAvrcpPlayerSettings.SETTING_REPEAT, 386 AvrcpUtils.mapAttribIdValtoAvrcpPlayerSetting(plAppSetting.attr_Id, 387 plAppSetting.attr_val)); 388 break; 389 case AvrcpControllerConstants.ATTRIB_SCAN_STATUS: 390 mAvrcpPlayerAppSetting.addSettingValue(BluetoothAvrcpPlayerSettings.SETTING_SCAN, 391 AvrcpUtils.mapAttribIdValtoAvrcpPlayerSetting(plAppSetting.attr_Id, 392 plAppSetting.attr_val)); 393 break; 394 case AvrcpControllerConstants.ATTRIB_SHUFFLE_STATUS: 395 mAvrcpPlayerAppSetting.addSettingValue(BluetoothAvrcpPlayerSettings.SETTING_SHUFFLE, 396 AvrcpUtils.mapAttribIdValtoAvrcpPlayerSetting(plAppSetting.attr_Id, 397 plAppSetting.attr_val)); 398 break; 399 } 400 } 401 return mAvrcpPlayerAppSetting; 402 } getCurrentPlayerAppSettingValue(byte mPlayerAppAttrId)403 public byte getCurrentPlayerAppSettingValue(byte mPlayerAppAttrId) { 404 for(PlayerApplicationSettings plAppSetting: mPlayerAppSetting) { 405 if(mPlayerAppAttrId == plAppSetting.attr_Id) 406 return plAppSetting.attr_val; 407 } 408 return 0; 409 } 410 /* 411 * Checks if current setting is supported by remote. 412 * input would be in form of flattened strucuture <id,val> 413 */ isPlayerAppSettingSupported(byte numAttributes, byte[] playerAppSetting)414 public boolean isPlayerAppSettingSupported(byte numAttributes, byte[] playerAppSetting) { 415 for( int i = 0; (i < 2*numAttributes);) { 416 byte id = playerAppSetting[i++]; 417 byte val = playerAppSetting[i++]; 418 boolean found = false; 419 for(PlayerApplicationSettings plAppSetting: mPlayerAppSetting) { 420 if(plAppSetting.attr_Id == id) { 421 for(int j = 0; j < plAppSetting.supported_values.length; j++) { 422 if(val == plAppSetting.supported_values[j]) { 423 found = true; 424 break; 425 } 426 } 427 } 428 } 429 if(!found) 430 return false; 431 } 432 return true; 433 } 434 } 435 436 /* 437 * Contains information about track 438 */ 439 class TrackInfo extends MediaItem { 440 String mArtistName; 441 String mTrackTitle; 442 String mAlbumTitle; 443 String mGenre; 444 long mTrackNum; // number of audio file on original recording. 445 long mTotalTracks;// total number of tracks on original recording 446 long mTrackLen;// full length of AudioFile. 447 /* In case of 1.3 we have to set itemUid explicitly to 0 */ 448 449 /* reset it to default values */ resetTrackInfo()450 private void resetTrackInfo() { 451 mArtistName = AvrcpControllerConstants.ARTIST_NAME_INVALID;; 452 mTrackTitle = AvrcpControllerConstants.TITLE_INVALID;; 453 mAlbumTitle = AvrcpControllerConstants.ALBUM_NAME_INVALID; 454 mGenre = AvrcpControllerConstants.GENRE_INVALID; 455 mTrackNum = AvrcpControllerConstants.TRACK_NUM_INVALID; 456 mTotalTracks = AvrcpControllerConstants.TOTAL_TRACK_TIME_INVALID; 457 mTrackLen = AvrcpControllerConstants.TOTAL_TRACK_TIME_INVALID; 458 } TrackInfo()459 public TrackInfo() { 460 resetTrackInfo(); 461 } TrackInfo(int mTrackId, byte mNumAttributes, int[] mAttribIds, String[] mAttribs)462 public TrackInfo(int mTrackId, byte mNumAttributes, int[] mAttribIds, String[] mAttribs) { 463 mItemUid = mTrackId; 464 resetTrackInfo(); 465 for (int i = 0; i < mNumAttributes; i++) { 466 switch(mAttribIds[i]) { 467 case AvrcpControllerConstants.MEDIA_ATTRIBUTE_TITLE: 468 mTrackTitle = mAttribs[i]; 469 break; 470 case AvrcpControllerConstants.MEDIA_ATTRIBUTE_ARTIST_NAME: 471 mArtistName = mAttribs[i]; 472 break; 473 case AvrcpControllerConstants.MEDIA_ATTRIBUTE_ALBUM_NAME: 474 mAlbumTitle = mAttribs[i]; 475 break; 476 case AvrcpControllerConstants.MEDIA_ATTRIBUTE_TRACK_NUMBER: 477 if(!mAttribs[i].isEmpty()) 478 mTrackNum = Long.valueOf(mAttribs[i]); 479 break; 480 case AvrcpControllerConstants.MEDIA_ATTRIBUTE_TOTAL_TRACK_NUMBER: 481 if(!mAttribs[i].isEmpty()) 482 mTotalTracks = Long.valueOf(mAttribs[i]); 483 break; 484 case AvrcpControllerConstants.MEDIA_ATTRIBUTE_GENRE: 485 mGenre = mAttribs[i]; 486 break; 487 case AvrcpControllerConstants.MEDIA_ATTRIBUTE_PLAYING_TIME: 488 if(!mAttribs[i].isEmpty()) 489 mTrackLen = Long.valueOf(mAttribs[i]); 490 break; 491 } 492 } 493 } toString()494 public String toString() { 495 return "Metadata [artist=" + mArtistName + " trackTitle= " + mTrackTitle + 496 " albumTitle= " + mAlbumTitle + " genre= " +mGenre+" trackNum= "+ 497 Long.toString(mTrackNum) + " track_len : "+ Long.toString(mTrackLen) + 498 " TotalTracks " + Long.toString(mTotalTracks) + "]"; 499 } 500 } 501