1c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu/* 2e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * Copyright (C) 2016 The Android Open Source Project 3c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * 4c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * Licensed under the Apache License, Version 2.0 (the "License"); 5c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * you may not use this file except in compliance with the License. 6c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * You may obtain a copy of the License at 7c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * 8c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * http://www.apache.org/licenses/LICENSE-2.0 9c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * 10c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * Unless required by applicable law or agreed to in writing, software 11c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * distributed under the License is distributed on an "AS IS" BASIS, 12c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * See the License for the specific language governing permissions and 14c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * limitations under the License. 15c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu */ 16c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 17066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodpackage com.android.bluetooth.avrcp; 18c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 19de5340b6cbe5e8bd62658131e87c551d0fc7a182Marie Janssenimport android.annotation.NonNull; 200c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssenimport android.annotation.Nullable; 21188f205b5f093850d4cc627917a21204be36c56aZhihai Xuimport android.bluetooth.BluetoothA2dp; 22066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodimport android.bluetooth.BluetoothAvrcp; 23e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.bluetooth.BluetoothDevice; 24e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.BroadcastReceiver; 25e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.ComponentName; 26c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.content.Context; 27e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.Intent; 28e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.IntentFilter; 29e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.pm.ApplicationInfo; 30e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.pm.PackageManager; 31e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.pm.PackageManager.NameNotFoundException; 32e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.pm.ResolveInfo; 3311798b011c962b602217b479130d413f3b30f19aLiejun Taoimport android.content.res.Resources; 3411798b011c962b602217b479130d413f3b30f19aLiejun Taoimport android.content.SharedPreferences; 35c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.media.AudioManager; 3676aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavovimport android.media.AudioPlaybackConfiguration; 373b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssenimport android.media.MediaDescription; 380e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssenimport android.media.MediaMetadata; 393843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssenimport android.media.browse.MediaBrowser; 40e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.media.session.MediaSession; 41e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.media.session.MediaSession.QueueItem; 420e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssenimport android.media.session.MediaSessionManager; 430e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssenimport android.media.session.PlaybackState; 44e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.os.Bundle; 45c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.Handler; 46c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.HandlerThread; 47c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.Looper; 48c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.Message; 49aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xuimport android.os.SystemClock; 500427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panickerimport android.os.UserManager; 51c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.util.Log; 52881675b362bde18acbbcf69c513175addca4a8baZhenye Zhuimport android.view.KeyEvent; 536e29e12add362546784126119f26f04fc760f021RoboErik 54c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport com.android.bluetooth.btservice.ProfileService; 55e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport com.android.bluetooth.R; 56aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xuimport com.android.bluetooth.Utils; 576e29e12add362546784126119f26f04fc760f021RoboErik 58c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport java.util.ArrayList; 590c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssenimport java.util.Collections; 6011798b011c962b602217b479130d413f3b30f19aLiejun Taoimport java.util.HashMap; 617c12b34b98d717fdfe68f5e8c94b7a01ef372f8bMarie Janssenimport java.util.HashSet; 62e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport java.util.Iterator; 63c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport java.util.List; 64e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport java.util.Map; 657c12b34b98d717fdfe68f5e8c94b7a01ef372f8bMarie Janssenimport java.util.Set; 66351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssenimport java.util.SortedMap; 67351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssenimport java.util.TreeMap; 68e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 69e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah/****************************************************************************** 70e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * support Bluetooth AVRCP profile. support metadata, play status, event 71e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * notifications, address player selection and browse feature implementation. 72e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ******************************************************************************/ 73eb7b90f5b93db1230a5b64caa3d8d05a642e33a6Marie Janssen 74066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodpublic final class Avrcp { 751b70ec148be773651d5ad00e3ce0d28b3a63306dAjay Panicker private static final boolean DEBUG = true; 76c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private static final String TAG = "Avrcp"; 7711798b011c962b602217b479130d413f3b30f19aLiejun Tao private static final String ABSOLUTE_VOLUME_BLACKLIST = "absolute_volume_blacklist"; 78c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 79c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private Context mContext; 80c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private final AudioManager mAudioManager; 81c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private AvrcpMessageHandler mHandler; 8276aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov private Handler mAudioManagerPlaybackHandler; 8376aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov private AudioManagerPlaybackListener mAudioManagerPlaybackCb; 840e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen private MediaSessionManager mMediaSessionManager; 85de5340b6cbe5e8bd62658131e87c551d0fc7a182Marie Janssen private @Nullable MediaController mMediaController; 860e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen private MediaControllerListener mMediaControllerCb; 873b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private MediaAttributes mMediaAttributes; 88d5b2445ec7ff3809c1c90a9b20784a6a861a037cMarie Janssen private long mLastQueueId; 89e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private PackageManager mPackageManager; 90c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private int mTransportControlFlags; 91de5340b6cbe5e8bd62658131e87c551d0fc7a182Marie Janssen private @NonNull PlaybackState mCurrentPlayState; 9293f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen private int mA2dpState; 9376aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov private boolean mAudioManagerIsPlaying; 94c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private int mPlayStatusChangedNT; 953211ee063dc32e07ab00d94312637dd7c27d2bbaAjay Panicker private byte mReportedPlayStatus; 96c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private int mTrackChangedNT; 97f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen private int mPlayPosChangedNT; 98b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen private int mAddrPlayerChangedNT; 99b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen private int mReportedPlayerID; 1003616b7ce7be6abaca5eef876e055155f9e8a3b1fAjay Panicker private int mNowPlayingListChangedNT; 101aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mPlaybackIntervalMs; 102fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen private long mLastReportedPosition; 103aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mNextPosMs; 104aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mPrevPosMs; 10517675906064bb72fdcca75baa56cdf8bb8968d01John Du private int mFeatures; 10611798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mRemoteVolume; 10711798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mLastRemoteVolume; 10811798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mInitialRemoteVolume; 10911798b011c962b602217b479130d413f3b30f19aLiejun Tao 11011798b011c962b602217b479130d413f3b30f19aLiejun Tao /* Local volume in audio index 0-15 */ 11111798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mLocalVolume; 11211798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mLastLocalVolume; 11311798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mAbsVolThreshold; 11411798b011c962b602217b479130d413f3b30f19aLiejun Tao 11511798b011c962b602217b479130d413f3b30f19aLiejun Tao private String mAddress; 11611798b011c962b602217b479130d413f3b30f19aLiejun Tao private HashMap<Integer, Integer> mVolumeMapping; 11711798b011c962b602217b479130d413f3b30f19aLiejun Tao 11817675906064bb72fdcca75baa56cdf8bb8968d01John Du private int mLastDirection; 1192e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie private final int mVolumeStep; 1202e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie private final int mAudioStreamMax; 12111798b011c962b602217b479130d413f3b30f19aLiejun Tao private boolean mVolCmdAdjustInProgress; 12211798b011c962b602217b479130d413f3b30f19aLiejun Tao private boolean mVolCmdSetInProgress; 12317675906064bb72fdcca75baa56cdf8bb8968d01John Du private int mAbsVolRetryTimes; 124351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen 125d89304c6be6e1c332008dcbeab08889881064454Marie Janssen private static final int NO_PLAYER_ID = 0; 126d89304c6be6e1c332008dcbeab08889881064454Marie Janssen 127e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private int mCurrAddrPlayerID; 128e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private int mCurrBrowsePlayerID; 129351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen private int mLastUsedPlayerID; 130e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private AvrcpMediaRsp mAvrcpMediaRsp; 131e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 132e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* UID counter to be shared across different files. */ 133b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen static short sUIDCounter = AvrcpConstants.DEFAULT_UID_COUNTER; 134ace834feb02adabd61f628c4471147aea02d939cJohn Du 13517675906064bb72fdcca75baa56cdf8bb8968d01John Du /* BTRC features */ 13617675906064bb72fdcca75baa56cdf8bb8968d01John Du public static final int BTRC_FEAT_METADATA = 0x01; 13717675906064bb72fdcca75baa56cdf8bb8968d01John Du public static final int BTRC_FEAT_ABSOLUTE_VOLUME = 0x02; 13817675906064bb72fdcca75baa56cdf8bb8968d01John Du public static final int BTRC_FEAT_BROWSE = 0x04; 13917675906064bb72fdcca75baa56cdf8bb8968d01John Du 14017675906064bb72fdcca75baa56cdf8bb8968d01John Du /* AVRC response codes, from avrc_defs */ 14117675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_NOT_IMPL = 8; 14217675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_ACCEPT = 9; 14317675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_REJ = 10; 14417675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_IN_TRANS = 11; 14517675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_IMPL_STBL = 12; 14617675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_CHANGED = 13; 14717675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_INTERIM = 15; 14817675906064bb72fdcca75baa56cdf8bb8968d01John Du 149e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* AVRC request commands from Native */ 150e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_GET_RC_FEATURES = 1; 151e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_GET_PLAY_STATUS = 2; 152e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_GET_ELEM_ATTRS = 3; 153e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_REGISTER_NOTIFICATION = 4; 154e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_VOLUME_CHANGE = 5; 155e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_GET_FOLDER_ITEMS = 6; 156e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_SET_ADDR_PLAYER = 7; 157e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_SET_BR_PLAYER = 8; 158e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_CHANGE_PATH = 9; 159e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_PLAY_ITEM = 10; 160e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_GET_ITEM_ATTR = 11; 161e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_GET_TOTAL_NUM_OF_ITEMS = 12; 162e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_PASS_THROUGH = 13; 163e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 164e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* other AVRC messages */ 165e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_PLAY_INTERVAL_TIMEOUT = 14; 166e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_ADJUST_VOLUME = 15; 167e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_SET_ABSOLUTE_VOLUME = 16; 168e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_ABS_VOL_TIMEOUT = 17; 169b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen private static final int MSG_SET_A2DP_AUDIO_STATE = 18; 17085ff6903243d244d4342f390bb40aa99097a9a7cMarie Janssen private static final int MSG_NOW_PLAYING_CHANGED_RSP = 19; 171bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen 17217675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int CMD_TIMEOUT_DELAY = 2000; 173f8201e1c6bf7fadc0a332151a652325a7f31255aLiejun Tao private static final int MAX_ERROR_RETRY_TIMES = 6; 17417675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRCP_MAX_VOL = 127; 17517675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRCP_BASE_VOLUME_STEP = 1; 176ace834feb02adabd61f628c4471147aea02d939cJohn Du 177e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Communicates with MediaPlayer to fetch media content */ 178e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private BrowsedMediaPlayer mBrowsedMediaPlayer; 179e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 180bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen /* Addressed player handling */ 181e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private AddressedMediaPlayer mAddressedMediaPlayer; 182e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 183e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* List of Media player instances, useful for retrieving MediaPlayerList or MediaPlayerInfo */ 184351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen private SortedMap<Integer, MediaPlayerInfo> mMediaPlayerInfoList; 18585ff6903243d244d4342f390bb40aa99097a9a7cMarie Janssen private boolean mAvailablePlayerViewChanged; 186e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 187e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* List of media players which supports browse */ 188241af80129d66d60eea6e77e8962b7123e1c61c5Marie Janssen private List<BrowsePlayerInfo> mBrowsePlayerInfoList; 189e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 190e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Manage browsed players */ 191e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private AvrcpBrowseManager mAvrcpBrowseManager; 192e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 193e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Broadcast receiver for device connections intent broadcasts */ 194e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private final BroadcastReceiver mAvrcpReceiver = new AvrcpServiceBroadcastReceiver(); 1950427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker private final BroadcastReceiver mBootReceiver = new AvrcpServiceBootReceiver(); 196e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 197bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen /* Recording passthrough key dispatches */ 198bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen static private final int PASSTHROUGH_LOG_MAX_SIZE = DEBUG ? 50 : 10; 199bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen private EvictingQueue<MediaKeyLog> mPassthroughLogs; // Passthorugh keys dispatched 2000c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen private List<MediaKeyLog> mPassthroughPending; // Passthrough keys sent not dispatched yet 201bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen private int mPassthroughDispatched; // Number of keys dispatched 202bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen 203bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen private class MediaKeyLog { 204bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen private long mTimeSent; 205bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen private long mTimeProcessed; 206bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen private String mPackage; 207bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen private KeyEvent mEvent; 208bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen 209bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen public MediaKeyLog(long time, KeyEvent event) { 210bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen mEvent = event; 211bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen mTimeSent = time; 212bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 213bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen 214bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen public boolean addDispatch(long time, KeyEvent event, String packageName) { 215bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen if (mPackage != null) return false; 216bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen if (event.getAction() != mEvent.getAction()) return false; 217bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen if (event.getKeyCode() != mEvent.getKeyCode()) return false; 218bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen mPackage = packageName; 219bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen mTimeProcessed = time; 220bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return true; 221bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 222bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen 223bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen public String toString() { 224bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen StringBuilder sb = new StringBuilder(); 225bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen sb.append(android.text.format.DateFormat.format("MM-dd HH:mm:ss", mTimeSent)); 226bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen sb.append(" " + mEvent.toString()); 227bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen if (mPackage == null) { 228bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen sb.append(" (undispatched)"); 229bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } else { 230bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen sb.append(" to " + mPackage); 231bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen sb.append(" in " + (mTimeProcessed - mTimeSent) + "ms"); 232bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 233bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return sb.toString(); 234bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 235bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 236bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen 237c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu static { 238c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu classInitNative(); 239c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 240c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 241c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private Avrcp(Context context) { 2423b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen mMediaAttributes = new MediaAttributes(null); 243d5b2445ec7ff3809c1c90a9b20784a6a861a037cMarie Janssen mLastQueueId = MediaSession.QueueItem.UNKNOWN_ID; 2440e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen mCurrentPlayState = new PlaybackState.Builder().setState(PlaybackState.STATE_NONE, -1L, 0.0f).build(); 245b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen mReportedPlayStatus = PLAYSTATUS_ERROR; 24693f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen mA2dpState = BluetoothA2dp.STATE_NOT_PLAYING; 24776aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov mAudioManagerIsPlaying = false; 248e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPlayStatusChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 249e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 250e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPlayPosChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 251b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen mAddrPlayerChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 2523616b7ce7be6abaca5eef876e055155f9e8a3b1fAjay Panicker mNowPlayingListChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 253b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen mPlaybackIntervalMs = 0L; 254fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen mLastReportedPosition = -1; 2553635a926bd7316a55b288a54d409a1070a9c19e8Marie Janssen mNextPosMs = -1; 2563635a926bd7316a55b288a54d409a1070a9c19e8Marie Janssen mPrevPosMs = -1; 25717675906064bb72fdcca75baa56cdf8bb8968d01John Du mFeatures = 0; 25811798b011c962b602217b479130d413f3b30f19aLiejun Tao mRemoteVolume = -1; 25911798b011c962b602217b479130d413f3b30f19aLiejun Tao mInitialRemoteVolume = -1; 26011798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastRemoteVolume = -1; 26117675906064bb72fdcca75baa56cdf8bb8968d01John Du mLastDirection = 0; 26211798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = false; 26311798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = false; 26417675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes = 0; 26511798b011c962b602217b479130d413f3b30f19aLiejun Tao mLocalVolume = -1; 26611798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = -1; 26711798b011c962b602217b479130d413f3b30f19aLiejun Tao mAbsVolThreshold = 0; 26811798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolumeMapping = new HashMap<Integer, Integer>(); 269d89304c6be6e1c332008dcbeab08889881064454Marie Janssen mCurrAddrPlayerID = NO_PLAYER_ID; 270b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen mReportedPlayerID = mCurrAddrPlayerID; 271b3436e976055f684050be9afdadc73645316806aMarie Janssen mCurrBrowsePlayerID = 0; 272c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mContext = context; 273351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen mLastUsedPlayerID = 0; 274e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAddressedMediaPlayer = null; 275c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 276c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu initNative(); 277c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 278e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mMediaSessionManager = (MediaSessionManager) context.getSystemService( 279e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Context.MEDIA_SESSION_SERVICE); 280c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 2812e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie mAudioStreamMax = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); 2822e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie mVolumeStep = Math.max(AVRCP_BASE_VOLUME_STEP, AVRCP_MAX_VOL/mAudioStreamMax); 283e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 28411798b011c962b602217b479130d413f3b30f19aLiejun Tao Resources resources = context.getResources(); 28511798b011c962b602217b479130d413f3b30f19aLiejun Tao if (resources != null) { 28611798b011c962b602217b479130d413f3b30f19aLiejun Tao mAbsVolThreshold = resources.getInteger(R.integer.a2dp_absolute_volume_initial_threshold); 2879ef4a582ed78ae48b867012ea53ba3cec79a31f7Pavlin Radoslavov 2889ef4a582ed78ae48b867012ea53ba3cec79a31f7Pavlin Radoslavov // Update the threshold if the threshold_percent is valid 2899ef4a582ed78ae48b867012ea53ba3cec79a31f7Pavlin Radoslavov int threshold_percent = 2909ef4a582ed78ae48b867012ea53ba3cec79a31f7Pavlin Radoslavov resources.getInteger(R.integer.a2dp_absolute_volume_initial_threshold_percent); 2919ef4a582ed78ae48b867012ea53ba3cec79a31f7Pavlin Radoslavov if (threshold_percent >= 0 && threshold_percent <= 100) { 2929ef4a582ed78ae48b867012ea53ba3cec79a31f7Pavlin Radoslavov mAbsVolThreshold = (threshold_percent * mAudioStreamMax) / 100; 2939ef4a582ed78ae48b867012ea53ba3cec79a31f7Pavlin Radoslavov } 29411798b011c962b602217b479130d413f3b30f19aLiejun Tao } 295e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 296e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // Register for package removal intent broadcasts for media button receiver persistence 297e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah IntentFilter pkgFilter = new IntentFilter(); 298e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah pkgFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 299e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah pkgFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 300e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah pkgFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); 301e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah pkgFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED); 302e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah pkgFilter.addDataScheme("package"); 303e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah context.registerReceiver(mAvrcpReceiver, pkgFilter); 3040427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker 3050427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker IntentFilter bootFilter = new IntentFilter(); 306eb829bbfa257c84c4f8fa589b54791e3f413b486Ajay Panicker bootFilter.addAction(Intent.ACTION_USER_UNLOCKED); 3070427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker context.registerReceiver(mBootReceiver, bootFilter); 308c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 309c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 310676768272f84bc3fef9068b6286b6f38cb1e8962Marie Janssen private synchronized void start() { 311c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu HandlerThread thread = new HandlerThread("BluetoothAvrcpHandler"); 312c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu thread.start(); 313c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Looper looper = thread.getLooper(); 314c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler = new AvrcpMessageHandler(looper); 31576aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov mAudioManagerPlaybackHandler = new Handler(looper); 31676aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov mAudioManagerPlaybackCb = new AudioManagerPlaybackListener(); 3179d4035307b85e78f10fba961e225ca09bfb7d0c7Jakub Pawlowski mMediaControllerCb = new MediaControllerListener(); 318e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpMediaRsp = new AvrcpMediaRsp(); 319351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen mMediaPlayerInfoList = new TreeMap<Integer, MediaPlayerInfo>(); 32085ff6903243d244d4342f390bb40aa99097a9a7cMarie Janssen mAvailablePlayerViewChanged = false; 321241af80129d66d60eea6e77e8962b7123e1c61c5Marie Janssen mBrowsePlayerInfoList = Collections.synchronizedList(new ArrayList<BrowsePlayerInfo>()); 322bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen mPassthroughDispatched = 0; 323bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen mPassthroughLogs = new EvictingQueue<MediaKeyLog>(PASSTHROUGH_LOG_MAX_SIZE); 3240c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen mPassthroughPending = Collections.synchronizedList(new ArrayList<MediaKeyLog>()); 325f65765e71b2a6552c319eb5199914045a1ecdb04Marie Janssen if (mMediaSessionManager != null) { 326f65765e71b2a6552c319eb5199914045a1ecdb04Marie Janssen mMediaSessionManager.addOnActiveSessionsChangedListener(mActiveSessionListener, null, 327f65765e71b2a6552c319eb5199914045a1ecdb04Marie Janssen mHandler); 328bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen mMediaSessionManager.setCallback(mButtonDispatchCallback, null); 329f65765e71b2a6552c319eb5199914045a1ecdb04Marie Janssen } 330e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPackageManager = mContext.getApplicationContext().getPackageManager(); 331e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 332e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* create object to communicate with addressed player */ 333e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAddressedMediaPlayer = new AddressedMediaPlayer(mAvrcpMediaRsp); 334e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 335e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* initialize BrowseMananger which manages Browse commands and response */ 336e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager = new AvrcpBrowseManager(mContext, mAvrcpMediaRsp); 3370427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker 338bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen initMediaPlayersList(); 33911bf73ff614f48a41dc379763bc007f271197b26Ajay Panicker 3400427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker UserManager manager = UserManager.get(mContext); 3410427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker if (manager == null || manager.isUserUnlocked()) { 3420427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker if (DEBUG) Log.d(TAG, "User already unlocked, initializing player lists"); 3433843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen // initialize browsable player list and build media player list 3441111f243441532aefeadf322a9ab9800e330007bAjay Panicker buildBrowsablePlayerList(); 3450427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker } 34676aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov 34776aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov mAudioManager.registerAudioPlaybackCallback( 34876aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov mAudioManagerPlaybackCb, mAudioManagerPlaybackHandler); 349c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 350c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 351066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood public static Avrcp make(Context context) { 352c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (DEBUG) Log.v(TAG, "make"); 353c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Avrcp ar = new Avrcp(context); 354c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ar.start(); 355c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return ar; 356c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 357c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 358676768272f84bc3fef9068b6286b6f38cb1e8962Marie Janssen public synchronized void doQuit() { 359e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "doQuit"); 36076aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov if (mAudioManager != null) { 36176aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov mAudioManager.unregisterAudioPlaybackCallback(mAudioManagerPlaybackCb); 36276aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov } 363676768272f84bc3fef9068b6286b6f38cb1e8962Marie Janssen if (mMediaController != null) mMediaController.unregisterCallback(mMediaControllerCb); 364579be982d9d3ffa93c38fe27589db8eae80d1d34Marie Janssen if (mMediaSessionManager != null) { 365579be982d9d3ffa93c38fe27589db8eae80d1d34Marie Janssen mMediaSessionManager.setCallback(null, null); 366579be982d9d3ffa93c38fe27589db8eae80d1d34Marie Janssen mMediaSessionManager.removeOnActiveSessionsChangedListener(mActiveSessionListener); 367579be982d9d3ffa93c38fe27589db8eae80d1d34Marie Janssen } 368579be982d9d3ffa93c38fe27589db8eae80d1d34Marie Janssen 36976aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov mAudioManagerPlaybackHandler.removeCallbacksAndMessages(null); 370c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.removeCallbacksAndMessages(null); 371c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Looper looper = mHandler.getLooper(); 372c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (looper != null) { 373c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu looper.quit(); 374c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 375e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 37676aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov mAudioManagerPlaybackHandler = null; 377e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler = null; 378e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mContext.unregisterReceiver(mAvrcpReceiver); 3790427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker mContext.unregisterReceiver(mBootReceiver); 380e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 381e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAddressedMediaPlayer.cleanup(); 382e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager.cleanup(); 383c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 384c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 385c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public void cleanup() { 386e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "cleanup"); 387c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu cleanupNative(); 38811798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolumeMapping != null) 38911798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolumeMapping.clear(); 390c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 391c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 39276aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov private class AudioManagerPlaybackListener extends AudioManager.AudioPlaybackCallback { 39376aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov @Override 39476aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov public void onPlaybackConfigChanged(List<AudioPlaybackConfiguration> configs) { 39576aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov super.onPlaybackConfigChanged(configs); 39676aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov boolean isPlaying = false; 39776aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov for (AudioPlaybackConfiguration config : configs) { 39876aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov if (DEBUG) { 39976aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov Log.d(TAG, 40076aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov "AudioManager Player: " 40176aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov + AudioPlaybackConfiguration.toLogFriendlyString(config)); 40276aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov } 40376aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov if (config.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) { 40476aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov isPlaying = true; 40576aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov break; 40676aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov } 40776aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov } 40876aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov if (DEBUG) Log.d(TAG, "AudioManager isPlaying: " + isPlaying); 40976aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov if (mAudioManagerIsPlaying != isPlaying) { 41076aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov mAudioManagerIsPlaying = isPlaying; 41176aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov updateCurrentMediaState(); 41276aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov } 41376aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov } 41476aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov } 41576aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov 4160e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen private class MediaControllerListener extends MediaController.Callback { 4170e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen @Override 4180e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen public void onMetadataChanged(MediaMetadata metadata) { 419de5340b6cbe5e8bd62658131e87c551d0fc7a182Marie Janssen if (DEBUG) Log.v(TAG, "onMetadataChanged"); 42067c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker updateCurrentMediaState(); 421c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 422bc10e7d58aa55da25c18d8056a0254a2b736146aZhihai Xu @Override 423e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public synchronized void onPlaybackStateChanged(PlaybackState state) { 424351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen if (DEBUG) Log.v(TAG, "onPlaybackStateChanged: state " + state.toString()); 425093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker 42667c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker updateCurrentMediaState(); 427c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 428c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 429c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu @Override 4300e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen public void onSessionDestroyed() { 4310e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen Log.v(TAG, "MediaController session destroyed"); 43286582543b9cd70a617e84c049c03b466653e9641Marie Janssen synchronized (Avrcp.this) { 43386582543b9cd70a617e84c049c03b466653e9641Marie Janssen if (mMediaController != null) 43486582543b9cd70a617e84c049c03b466653e9641Marie Janssen removeMediaController(mMediaController.getWrappedInstance()); 435d89304c6be6e1c332008dcbeab08889881064454Marie Janssen } 436c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 437c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 438c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu @Override 439e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void onQueueChanged(List<MediaSession.QueueItem> queue) { 440e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (queue == null) { 441e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.v(TAG, "onQueueChanged: received null queue"); 442e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return; 443e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 4442b903c7262c9b8c0493e36b93b37831e7e075bfcMarie Janssen 445e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.v(TAG, "onQueueChanged: NowPlaying list changed, Queue Size = "+ queue.size()); 446093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker mHandler.sendEmptyMessage(MSG_NOW_PLAYING_CHANGED_RSP); 447c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 448c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 449c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 450c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu /** Handles Avrcp messages. */ 451c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private final class AvrcpMessageHandler extends Handler { 452c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private AvrcpMessageHandler(Looper looper) { 453c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu super(looper); 454c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 455c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 456c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu @Override 457c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public void handleMessage(Message msg) { 458c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu switch (msg.what) { 459e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_RC_FEATURES: 460e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah { 46117675906064bb72fdcca75baa56cdf8bb8968d01John Du String address = (String) msg.obj; 46217675906064bb72fdcca75baa56cdf8bb8968d01John Du mFeatures = msg.arg1; 46311798b011c962b602217b479130d413f3b30f19aLiejun Tao mFeatures = modifyRcFeatureFromBlacklist(mFeatures, address); 4642167443fa83241273d2ccb36b72f0906e3c5338aPavlin Radoslavov if (DEBUG) { 4652167443fa83241273d2ccb36b72f0906e3c5338aPavlin Radoslavov Log.v(TAG, 4662167443fa83241273d2ccb36b72f0906e3c5338aPavlin Radoslavov "MSG_NATIVE_REQ_GET_RC_FEATURES: address=" + address 4672167443fa83241273d2ccb36b72f0906e3c5338aPavlin Radoslavov + ", features=" + msg.arg1 + ", mFeatures=" + mFeatures); 4682167443fa83241273d2ccb36b72f0906e3c5338aPavlin Radoslavov } 46917675906064bb72fdcca75baa56cdf8bb8968d01John Du mAudioManager.avrcpSupportsAbsoluteVolume(address, isAbsoluteVolumeSupported()); 47011798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = -1; 47111798b011c962b602217b479130d413f3b30f19aLiejun Tao mRemoteVolume = -1; 47211798b011c962b602217b479130d413f3b30f19aLiejun Tao mLocalVolume = -1; 47311798b011c962b602217b479130d413f3b30f19aLiejun Tao mInitialRemoteVolume = -1; 47411798b011c962b602217b479130d413f3b30f19aLiejun Tao mAddress = address; 47511798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolumeMapping != null) 47611798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolumeMapping.clear(); 47717675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 478e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 47917675906064bb72fdcca75baa56cdf8bb8968d01John Du 480e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_PLAY_STATUS: 481e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah { 482e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] address = (byte[]) msg.obj; 483b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen int btstate = getBluetoothPlayState(mCurrentPlayState); 484303c1c67dbc142822bc37e7c5a89fba82faf2ac0Marie Janssen int length = (int) mMediaAttributes.getLength(); 485303c1c67dbc142822bc37e7c5a89fba82faf2ac0Marie Janssen int position = (int) getPlayPosition(); 486303c1c67dbc142822bc37e7c5a89fba82faf2ac0Marie Janssen if (DEBUG) 487303c1c67dbc142822bc37e7c5a89fba82faf2ac0Marie Janssen Log.v(TAG, "MSG_NATIVE_REQ_GET_PLAY_STATUS, responding with state " + btstate 488303c1c67dbc142822bc37e7c5a89fba82faf2ac0Marie Janssen + " len " + length + " pos " + position); 489303c1c67dbc142822bc37e7c5a89fba82faf2ac0Marie Janssen getPlayStatusRspNative(address, btstate, length, position); 490c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 491e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 492c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 493e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_ELEM_ATTRS: 494e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah { 495c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu String[] textArray; 496e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd.ElementAttrCmd elem = (AvrcpCmd.ElementAttrCmd) msg.obj; 497e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte numAttr = elem.mNumAttr; 498e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int[] attrIds = elem.mAttrIDs; 499e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_GET_ELEM_ATTRS:numAttr=" + numAttr); 500c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu textArray = new String[numAttr]; 501303c1c67dbc142822bc37e7c5a89fba82faf2ac0Marie Janssen StringBuilder responseDebug = new StringBuilder(); 502303c1c67dbc142822bc37e7c5a89fba82faf2ac0Marie Janssen responseDebug.append("getElementAttr response: "); 503c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu for (int i = 0; i < numAttr; ++i) { 5043b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen textArray[i] = mMediaAttributes.getString(attrIds[i]); 505029b34a866c2f4ab132412ec2814fd500813c565Marie Janssen responseDebug.append("[" + attrIds[i] + "="); 506029b34a866c2f4ab132412ec2814fd500813c565Marie Janssen if (attrIds[i] == AvrcpConstants.ATTRID_TITLE 507029b34a866c2f4ab132412ec2814fd500813c565Marie Janssen || attrIds[i] == AvrcpConstants.ATTRID_ARTIST 508029b34a866c2f4ab132412ec2814fd500813c565Marie Janssen || attrIds[i] == AvrcpConstants.ATTRID_ALBUM) { 509029b34a866c2f4ab132412ec2814fd500813c565Marie Janssen responseDebug.append(Utils.ellipsize(textArray[i]) + "] "); 510029b34a866c2f4ab132412ec2814fd500813c565Marie Janssen } else { 511029b34a866c2f4ab132412ec2814fd500813c565Marie Janssen responseDebug.append(textArray[i] + "] "); 512029b34a866c2f4ab132412ec2814fd500813c565Marie Janssen } 513c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 514303c1c67dbc142822bc37e7c5a89fba82faf2ac0Marie Janssen Log.v(TAG, responseDebug.toString()); 515e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] bdaddr = elem.mAddress; 516e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah getElementAttrRspNative(bdaddr, numAttr, attrIds, textArray); 517c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 518e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 519c1124a7c6679f612b80926a19084655f9a71580aMarie Janssen 520e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_REGISTER_NOTIFICATION: 521e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_REGISTER_NOTIFICATION:event=" + msg.arg1 + 522e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah " param=" + msg.arg2); 523e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah processRegisterNotification((byte[]) msg.obj, msg.arg1, msg.arg2); 524c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 525c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 526a7cf67c3e381792a7648b02d61b0fce75c4cc210Marie Janssen case MSG_NOW_PLAYING_CHANGED_RSP: 527a7cf67c3e381792a7648b02d61b0fce75c4cc210Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NOW_PLAYING_CHANGED_RSP"); 528a7cf67c3e381792a7648b02d61b0fce75c4cc210Marie Janssen removeMessages(MSG_NOW_PLAYING_CHANGED_RSP); 52967c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker updateCurrentMediaState(); 530a7cf67c3e381792a7648b02d61b0fce75c4cc210Marie Janssen break; 531a7cf67c3e381792a7648b02d61b0fce75c4cc210Marie Janssen 532e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_PLAY_INTERVAL_TIMEOUT: 533f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen sendPlayPosNotificationRsp(false); 534aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu break; 535aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 536e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_VOLUME_CHANGE: 53711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (!isAbsoluteVolumeSupported()) { 538303c1c67dbc142822bc37e7c5a89fba82faf2ac0Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_VOLUME_CHANGE ignored, not supported"); 53911798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 54011798b011c962b602217b479130d413f3b30f19aLiejun Tao } 541303c1c67dbc142822bc37e7c5a89fba82faf2ac0Marie Janssen byte absVol = (byte) ((byte) msg.arg1 & 0x7f); // discard MSB as it is RFD 542303c1c67dbc142822bc37e7c5a89fba82faf2ac0Marie Janssen if (DEBUG) 543303c1c67dbc142822bc37e7c5a89fba82faf2ac0Marie Janssen Log.v(TAG, "MSG_NATIVE_REQ_VOLUME_CHANGE: volume=" + absVol + " ctype=" 544303c1c67dbc142822bc37e7c5a89fba82faf2ac0Marie Janssen + msg.arg2); 54511798b011c962b602217b479130d413f3b30f19aLiejun Tao 54611798b011c962b602217b479130d413f3b30f19aLiejun Tao boolean volAdj = false; 54717675906064bb72fdcca75baa56cdf8bb8968d01John Du if (msg.arg2 == AVRC_RSP_ACCEPT || msg.arg2 == AVRC_RSP_REJ) { 54811798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolCmdAdjustInProgress == false && mVolCmdSetInProgress == false) { 54917675906064bb72fdcca75baa56cdf8bb8968d01John Du Log.e(TAG, "Unsolicited response, ignored"); 55017675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 55117675906064bb72fdcca75baa56cdf8bb8968d01John Du } 552e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah removeMessages(MSG_ABS_VOL_TIMEOUT); 55311798b011c962b602217b479130d413f3b30f19aLiejun Tao 55411798b011c962b602217b479130d413f3b30f19aLiejun Tao volAdj = mVolCmdAdjustInProgress; 55511798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = false; 55611798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = false; 55717675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes = 0; 55817675906064bb72fdcca75baa56cdf8bb8968d01John Du } 55911798b011c962b602217b479130d413f3b30f19aLiejun Tao 56011798b011c962b602217b479130d413f3b30f19aLiejun Tao // convert remote volume to local volume 56111798b011c962b602217b479130d413f3b30f19aLiejun Tao int volIndex = convertToAudioStreamVolume(absVol); 56211798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mInitialRemoteVolume == -1) { 56311798b011c962b602217b479130d413f3b30f19aLiejun Tao mInitialRemoteVolume = absVol; 56411798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mAbsVolThreshold > 0 && mAbsVolThreshold < mAudioStreamMax && volIndex > mAbsVolThreshold) { 56511798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.v(TAG, "remote inital volume too high " + volIndex + ">" + mAbsVolThreshold); 566e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg1 = mHandler.obtainMessage(MSG_SET_ABSOLUTE_VOLUME, mAbsVolThreshold , 0); 56711798b011c962b602217b479130d413f3b30f19aLiejun Tao mHandler.sendMessage(msg1); 56811798b011c962b602217b479130d413f3b30f19aLiejun Tao mRemoteVolume = absVol; 56911798b011c962b602217b479130d413f3b30f19aLiejun Tao mLocalVolume = volIndex; 57011798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 57111798b011c962b602217b479130d413f3b30f19aLiejun Tao } 57211798b011c962b602217b479130d413f3b30f19aLiejun Tao } 57311798b011c962b602217b479130d413f3b30f19aLiejun Tao 5740e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen if (mLocalVolume != volIndex && (msg.arg2 == AVRC_RSP_ACCEPT || 5750e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen msg.arg2 == AVRC_RSP_CHANGED || 5760e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen msg.arg2 == AVRC_RSP_INTERIM)) { 57711798b011c962b602217b479130d413f3b30f19aLiejun Tao /* If the volume has successfully changed */ 57811798b011c962b602217b479130d413f3b30f19aLiejun Tao mLocalVolume = volIndex; 57911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mLastLocalVolume != -1 && msg.arg2 == AVRC_RSP_ACCEPT) { 58011798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mLastLocalVolume != volIndex) { 58111798b011c962b602217b479130d413f3b30f19aLiejun Tao /* remote volume changed more than requested due to 58211798b011c962b602217b479130d413f3b30f19aLiejun Tao * local and remote has different volume steps */ 58311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "Remote returned volume does not match desired volume " 584e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + mLastLocalVolume + " vs " + volIndex); 58511798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = mLocalVolume; 58611798b011c962b602217b479130d413f3b30f19aLiejun Tao } 58711798b011c962b602217b479130d413f3b30f19aLiejun Tao } 58811798b011c962b602217b479130d413f3b30f19aLiejun Tao // remember the remote volume value, as it's the one supported by remote 58911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (volAdj) { 59011798b011c962b602217b479130d413f3b30f19aLiejun Tao synchronized (mVolumeMapping) { 591e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mVolumeMapping.put(volIndex, (int) absVol); 59211798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.v(TAG, "remember volume mapping " +volIndex+ "-"+absVol); 59311798b011c962b602217b479130d413f3b30f19aLiejun Tao } 59411798b011c962b602217b479130d413f3b30f19aLiejun Tao } 59511798b011c962b602217b479130d413f3b30f19aLiejun Tao 59611798b011c962b602217b479130d413f3b30f19aLiejun Tao notifyVolumeChanged(mLocalVolume); 59711798b011c962b602217b479130d413f3b30f19aLiejun Tao mRemoteVolume = absVol; 598e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah long pecentVolChanged = ((long) absVol * 100) / 0x7f; 5995c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta Log.e(TAG, "percent volume changed: " + pecentVolChanged + "%"); 60017675906064bb72fdcca75baa56cdf8bb8968d01John Du } else if (msg.arg2 == AVRC_RSP_REJ) { 60117675906064bb72fdcca75baa56cdf8bb8968d01John Du Log.e(TAG, "setAbsoluteVolume call rejected"); 60211798b011c962b602217b479130d413f3b30f19aLiejun Tao } else if (volAdj && mLastRemoteVolume > 0 && mLastRemoteVolume < AVRCP_MAX_VOL && 6030e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen mLocalVolume == volIndex && 604e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah (msg.arg2 == AVRC_RSP_ACCEPT)) { 60511798b011c962b602217b479130d413f3b30f19aLiejun Tao /* oops, the volume is still same, remote does not like the value 60611798b011c962b602217b479130d413f3b30f19aLiejun Tao * retry a volume one step up/down */ 60711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "Remote device didn't tune volume, let's try one more step."); 60811798b011c962b602217b479130d413f3b30f19aLiejun Tao int retry_volume = Math.min(AVRCP_MAX_VOL, 60911798b011c962b602217b479130d413f3b30f19aLiejun Tao Math.max(0, mLastRemoteVolume + mLastDirection)); 61011798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVolumeNative(retry_volume)) { 61111798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastRemoteVolume = retry_volume; 612e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah sendMessageDelayed(obtainMessage(MSG_ABS_VOL_TIMEOUT), CMD_TIMEOUT_DELAY); 61311798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = true; 61411798b011c962b602217b479130d413f3b30f19aLiejun Tao } 61517675906064bb72fdcca75baa56cdf8bb8968d01John Du } 61617675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 61717675906064bb72fdcca75baa56cdf8bb8968d01John Du 618e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_ADJUST_VOLUME: 61911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (!isAbsoluteVolumeSupported()) { 620e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "ignore MSG_ADJUST_VOLUME"); 62111798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 62211798b011c962b602217b479130d413f3b30f19aLiejun Tao } 62311798b011c962b602217b479130d413f3b30f19aLiejun Tao 624e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "MSG_ADJUST_VOLUME: direction=" + msg.arg1); 62511798b011c962b602217b479130d413f3b30f19aLiejun Tao 62611798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolCmdAdjustInProgress || mVolCmdSetInProgress) { 62717675906064bb72fdcca75baa56cdf8bb8968d01John Du if (DEBUG) Log.w(TAG, "There is already a volume command in progress."); 62817675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 62917675906064bb72fdcca75baa56cdf8bb8968d01John Du } 63011798b011c962b602217b479130d413f3b30f19aLiejun Tao 63111798b011c962b602217b479130d413f3b30f19aLiejun Tao // Remote device didn't set initial volume. Let's black list it 63211798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mInitialRemoteVolume == -1) { 63311798b011c962b602217b479130d413f3b30f19aLiejun Tao Log.d(TAG, "remote " + mAddress + " never tell us initial volume, black list it."); 63411798b011c962b602217b479130d413f3b30f19aLiejun Tao blackListCurrentDevice(); 63511798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 63611798b011c962b602217b479130d413f3b30f19aLiejun Tao } 63711798b011c962b602217b479130d413f3b30f19aLiejun Tao 63817675906064bb72fdcca75baa56cdf8bb8968d01John Du // Wait on verification on volume from device, before changing the volume. 63911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mRemoteVolume != -1 && (msg.arg1 == -1 || msg.arg1 == 1)) { 64011798b011c962b602217b479130d413f3b30f19aLiejun Tao int setVol = -1; 64111798b011c962b602217b479130d413f3b30f19aLiejun Tao int targetVolIndex = -1; 64211798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mLocalVolume == 0 && msg.arg1 == -1) { 64311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.w(TAG, "No need to Vol down from 0."); 64411798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 64511798b011c962b602217b479130d413f3b30f19aLiejun Tao } 64611798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mLocalVolume == mAudioStreamMax && msg.arg1 == 1) { 64711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.w(TAG, "No need to Vol up from max."); 64811798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 64911798b011c962b602217b479130d413f3b30f19aLiejun Tao } 65011798b011c962b602217b479130d413f3b30f19aLiejun Tao 65111798b011c962b602217b479130d413f3b30f19aLiejun Tao targetVolIndex = mLocalVolume + msg.arg1; 65211798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "Adjusting volume to " + targetVolIndex); 65311798b011c962b602217b479130d413f3b30f19aLiejun Tao 65411798b011c962b602217b479130d413f3b30f19aLiejun Tao Integer i; 65511798b011c962b602217b479130d413f3b30f19aLiejun Tao synchronized (mVolumeMapping) { 65611798b011c962b602217b479130d413f3b30f19aLiejun Tao i = mVolumeMapping.get(targetVolIndex); 65711798b011c962b602217b479130d413f3b30f19aLiejun Tao } 65811798b011c962b602217b479130d413f3b30f19aLiejun Tao 65911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (i != null) { 66011798b011c962b602217b479130d413f3b30f19aLiejun Tao /* if we already know this volume mapping, use it */ 66111798b011c962b602217b479130d413f3b30f19aLiejun Tao setVol = i.byteValue(); 66211798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVol == mRemoteVolume) { 66311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "got same volume from mapping for " + targetVolIndex + ", ignore."); 66411798b011c962b602217b479130d413f3b30f19aLiejun Tao setVol = -1; 66511798b011c962b602217b479130d413f3b30f19aLiejun Tao } 66611798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "set volume from mapping " + targetVolIndex + "-" + setVol); 66711798b011c962b602217b479130d413f3b30f19aLiejun Tao } 66811798b011c962b602217b479130d413f3b30f19aLiejun Tao 66911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVol == -1) { 67011798b011c962b602217b479130d413f3b30f19aLiejun Tao /* otherwise use phone steps */ 67111798b011c962b602217b479130d413f3b30f19aLiejun Tao setVol = Math.min(AVRCP_MAX_VOL, 672e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah convertToAvrcpVolume(Math.max(0, targetVolIndex))); 67311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "set volume from local volume "+ targetVolIndex+"-"+ setVol); 67411798b011c962b602217b479130d413f3b30f19aLiejun Tao } 67511798b011c962b602217b479130d413f3b30f19aLiejun Tao 67617675906064bb72fdcca75baa56cdf8bb8968d01John Du if (setVolumeNative(setVol)) { 677e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah sendMessageDelayed(obtainMessage(MSG_ABS_VOL_TIMEOUT), CMD_TIMEOUT_DELAY); 67811798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = true; 67917675906064bb72fdcca75baa56cdf8bb8968d01John Du mLastDirection = msg.arg1; 68011798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastRemoteVolume = setVol; 68111798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = targetVolIndex; 68211798b011c962b602217b479130d413f3b30f19aLiejun Tao } else { 68311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "setVolumeNative failed"); 68417675906064bb72fdcca75baa56cdf8bb8968d01John Du } 68517675906064bb72fdcca75baa56cdf8bb8968d01John Du } else { 686e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "Unknown direction in MSG_ADJUST_VOLUME"); 68717675906064bb72fdcca75baa56cdf8bb8968d01John Du } 68817675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 68917675906064bb72fdcca75baa56cdf8bb8968d01John Du 690e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_SET_ABSOLUTE_VOLUME: 69111798b011c962b602217b479130d413f3b30f19aLiejun Tao if (!isAbsoluteVolumeSupported()) { 692e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "ignore MSG_SET_ABSOLUTE_VOLUME"); 69311798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 69411798b011c962b602217b479130d413f3b30f19aLiejun Tao } 69511798b011c962b602217b479130d413f3b30f19aLiejun Tao 696e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_SET_ABSOLUTE_VOLUME"); 69711798b011c962b602217b479130d413f3b30f19aLiejun Tao 69811798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolCmdSetInProgress || mVolCmdAdjustInProgress) { 69917675906064bb72fdcca75baa56cdf8bb8968d01John Du if (DEBUG) Log.w(TAG, "There is already a volume command in progress."); 70017675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 70117675906064bb72fdcca75baa56cdf8bb8968d01John Du } 70211798b011c962b602217b479130d413f3b30f19aLiejun Tao 70311798b011c962b602217b479130d413f3b30f19aLiejun Tao // Remote device didn't set initial volume. Let's black list it 70411798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mInitialRemoteVolume == -1) { 70511798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "remote " + mAddress + " never tell us initial volume, black list it."); 70611798b011c962b602217b479130d413f3b30f19aLiejun Tao blackListCurrentDevice(); 70711798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 70811798b011c962b602217b479130d413f3b30f19aLiejun Tao } 70911798b011c962b602217b479130d413f3b30f19aLiejun Tao 71011798b011c962b602217b479130d413f3b30f19aLiejun Tao int avrcpVolume = convertToAvrcpVolume(msg.arg1); 71111798b011c962b602217b479130d413f3b30f19aLiejun Tao avrcpVolume = Math.min(AVRCP_MAX_VOL, Math.max(0, avrcpVolume)); 7123b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (DEBUG) Log.d(TAG, "Setting volume to " + msg.arg1 + "-" + avrcpVolume); 71311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVolumeNative(avrcpVolume)) { 714e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah sendMessageDelayed(obtainMessage(MSG_ABS_VOL_TIMEOUT), CMD_TIMEOUT_DELAY); 71511798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = true; 71611798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastRemoteVolume = avrcpVolume; 71711798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = msg.arg1; 71811798b011c962b602217b479130d413f3b30f19aLiejun Tao } else { 71911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "setVolumeNative failed"); 72017675906064bb72fdcca75baa56cdf8bb8968d01John Du } 72117675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 72217675906064bb72fdcca75baa56cdf8bb8968d01John Du 723e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_ABS_VOL_TIMEOUT: 724e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_ABS_VOL_TIMEOUT: Volume change cmd timed out."); 72511798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = false; 72611798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = false; 72717675906064bb72fdcca75baa56cdf8bb8968d01John Du if (mAbsVolRetryTimes >= MAX_ERROR_RETRY_TIMES) { 72817675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes = 0; 729f8201e1c6bf7fadc0a332151a652325a7f31255aLiejun Tao /* too many volume change failures, black list the device */ 730f8201e1c6bf7fadc0a332151a652325a7f31255aLiejun Tao blackListCurrentDevice(); 73117675906064bb72fdcca75baa56cdf8bb8968d01John Du } else { 73217675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes += 1; 73311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVolumeNative(mLastRemoteVolume)) { 734e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah sendMessageDelayed(obtainMessage(MSG_ABS_VOL_TIMEOUT), CMD_TIMEOUT_DELAY); 73511798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = true; 73617675906064bb72fdcca75baa56cdf8bb8968d01John Du } 73717675906064bb72fdcca75baa56cdf8bb8968d01John Du } 73817675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 73917675906064bb72fdcca75baa56cdf8bb8968d01John Du 740e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_SET_A2DP_AUDIO_STATE: 741e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_SET_A2DP_AUDIO_STATE:" + msg.arg1); 74293f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen mA2dpState = msg.arg1; 74367c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker updateCurrentMediaState(); 744188f205b5f093850d4cc627917a21204be36c56aZhihai Xu break; 745e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 746e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_FOLDER_ITEMS: { 747e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd.FolderItemsCmd folderObj = (AvrcpCmd.FolderItemsCmd) msg.obj; 7480f9c79e8afa3e575dfd8c80c2c58b9321e18898dMarie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_GET_FOLDER_ITEMS " + folderObj); 749e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah switch (folderObj.mScope) { 750e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case AvrcpConstants.BTRC_SCOPE_PLAYER_LIST: 751e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handleMediaPlayerListRsp(folderObj); 752e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 753e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case AvrcpConstants.BTRC_SCOPE_FILE_SYSTEM: 754e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case AvrcpConstants.BTRC_SCOPE_NOW_PLAYING: 755e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handleGetFolderItemBrowseResponse(folderObj, folderObj.mAddress); 756e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 757e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah default: 758e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "unknown scope for getfolderitems. scope = " 759e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + folderObj.mScope); 760e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah getFolderItemsRspNative(folderObj.mAddress, 761e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpConstants.RSP_INV_SCOPE, (short) 0, (byte) 0, 0, 762e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah null, null, null, null, null, null, null, null); 763e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 764e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 765e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 766e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 767e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_SET_ADDR_PLAYER: 768e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // object is bdaddr, argument 1 is the selected player id 769b3436e976055f684050be9afdadc73645316806aMarie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_SET_ADDR_PLAYER id=" + msg.arg1); 770e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah setAddressedPlayer((byte[]) msg.obj, msg.arg1); 771e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 772e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 773e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_ITEM_ATTR: 774e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // msg object contains the item attribute object 7750f9c79e8afa3e575dfd8c80c2c58b9321e18898dMarie Janssen AvrcpCmd.ItemAttrCmd cmd = (AvrcpCmd.ItemAttrCmd) msg.obj; 7760f9c79e8afa3e575dfd8c80c2c58b9321e18898dMarie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_GET_ITEM_ATTR " + cmd); 7770f9c79e8afa3e575dfd8c80c2c58b9321e18898dMarie Janssen handleGetItemAttr(cmd); 778e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 779e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 780e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_SET_BR_PLAYER: 781e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // argument 1 is the selected player id 782b3436e976055f684050be9afdadc73645316806aMarie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_SET_BR_PLAYER id=" + msg.arg1); 783e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah setBrowsedPlayer((byte[]) msg.obj, msg.arg1); 784e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 785e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 786e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_CHANGE_PATH: 787e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah { 788b3436e976055f684050be9afdadc73645316806aMarie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_CHANGE_PATH"); 789e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = msg.getData(); 790e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] bdaddr = data.getByteArray("BdAddress"); 791e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] folderUid = data.getByteArray("folderUid"); 792e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte direction = data.getByte("direction"); 793e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr) != null) { 794e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr).changePath(folderUid, 795e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah direction); 796e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 797e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "Remote requesting change path before setbrowsedplayer"); 798e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah changePathRspNative(bdaddr, AvrcpConstants.RSP_BAD_CMD, 0); 799e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 800e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 801e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 802e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 803e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_PLAY_ITEM: 804e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah { 805e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = msg.getData(); 806e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] bdaddr = data.getByteArray("BdAddress"); 807e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] uid = data.getByteArray("uid"); 808e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte scope = data.getByte("scope"); 8090f9c79e8afa3e575dfd8c80c2c58b9321e18898dMarie Janssen if (DEBUG) 8100f9c79e8afa3e575dfd8c80c2c58b9321e18898dMarie Janssen Log.v(TAG, "MSG_NATIVE_REQ_PLAY_ITEM scope=" + scope + " id=" 8110f9c79e8afa3e575dfd8c80c2c58b9321e18898dMarie Janssen + Utils.byteArrayToString(uid)); 812e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handlePlayItemResponse(bdaddr, uid, scope); 813e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 814e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 815e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 816e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_TOTAL_NUM_OF_ITEMS: 817b3436e976055f684050be9afdadc73645316806aMarie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_GET_TOTAL_NUM_OF_ITEMS scope=" + msg.arg1); 818e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // argument 1 is scope, object is bdaddr 819e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handleGetTotalNumOfItemsResponse((byte[]) msg.obj, (byte) msg.arg1); 820e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 821e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 822e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_PASS_THROUGH: 823b3436e976055f684050be9afdadc73645316806aMarie Janssen if (DEBUG) 824bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen Log.v(TAG, "MSG_NATIVE_REQ_PASS_THROUGH: id=" + msg.arg1 + " st=" + msg.arg2); 825bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen // argument 1 is id, argument 2 is keyState 826bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen handlePassthroughCmd(msg.arg1, msg.arg2); 827e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 828e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 829e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah default: 830e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "unknown message! msg.what=" + msg.what); 831e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 832c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 833c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 834c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 835c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 836b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen private PlaybackState updatePlaybackState() { 837b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen PlaybackState newState = new PlaybackState.Builder() 838b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen .setState(PlaybackState.STATE_NONE, 839b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen PlaybackState.PLAYBACK_POSITION_UNKNOWN, 0.0f) 840b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen .build(); 841b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen synchronized (this) { 842b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen PlaybackState controllerState = null; 843b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen if (mMediaController != null) { 844b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen controllerState = mMediaController.getPlaybackState(); 845b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen } 846b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen 847b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen if (controllerState != null) { 848b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen newState = controllerState; 84976aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov } 85076aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov // Use the AudioManager to update the playback state. 85176aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov // NOTE: We cannot use the 85276aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov // (mA2dpState == BluetoothA2dp.STATE_PLAYING) 85376aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov // check, because after Pause, the A2DP state remains in 85476aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov // STATE_PLAYING for 3 more seconds. 85576aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov // As a result of that, if we pause the music, on carkits the 85676aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov // Play status indicator will continue to display "Playing" 85776aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov // for 3 more seconds which can be confusing. 8585e600b2e36234f267aa2b2c171f0f4edf8fa65f1Pavlin Radoslavov if ((mAudioManagerIsPlaying && newState.getState() != PlaybackState.STATE_PLAYING) 85976aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov || (controllerState == null && mAudioManager != null 86076aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov && mAudioManager.isMusicActive())) { 86176aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov // Use AudioManager playback state if we don't have the state 86276aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov // from MediaControlller 863b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen PlaybackState.Builder builder = new PlaybackState.Builder(); 86476aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov if (mAudioManagerIsPlaying) { 865b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen builder.setState(PlaybackState.STATE_PLAYING, 866b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen PlaybackState.PLAYBACK_POSITION_UNKNOWN, 1.0f); 867b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen } else { 868b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen builder.setState(PlaybackState.STATE_PAUSED, 869b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen PlaybackState.PLAYBACK_POSITION_UNKNOWN, 0.0f); 870b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen } 871b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen newState = builder.build(); 872b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen } 8730e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen } 874f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 875b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen byte newPlayStatus = getBluetoothPlayState(newState); 87693f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen 877b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen /* update play status in global media player list */ 87893f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen MediaPlayerInfo player = getAddressedPlayerInfo(); 87993f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen if (player != null) { 880b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen player.setPlayStatus(newPlayStatus); 88193f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen } 88293f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen 883fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen if (DEBUG) { 884b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen Log.v(TAG, "updatePlaybackState (" + mPlayStatusChangedNT + "): " + mReportedPlayStatus 885b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen + "➡" + newPlayStatus + "(" + newState + ")"); 886fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen } 887fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen 888b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen if (newState != null) mCurrentPlayState = newState; 889aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 890b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen return mCurrentPlayState; 891b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen } 892b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen 893b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen private void sendPlaybackStatus(int playStatusChangedNT, byte playbackState) { 894b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen registerNotificationRspPlayStatusNative(playStatusChangedNT, playbackState); 895b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen mPlayStatusChangedNT = playStatusChangedNT; 896b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen mReportedPlayStatus = playbackState; 897c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 898c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 899c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private void updateTransportControls(int transportControlFlags) { 900c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mTransportControlFlags = transportControlFlags; 901c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 902c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 9033b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen class MediaAttributes { 9043b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private boolean exists; 9053b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String title; 9063b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String artistName; 9073b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String albumName; 9083b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String mediaNumber; 9093b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String mediaTotalNumber; 9103b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String genre; 91193f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen private long playingTimeMs; 9123b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9133b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_TITLE = 1; 9143b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_ARTIST_NAME = 2; 9153b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_ALBUM_NAME = 3; 9163b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_MEDIA_NUMBER = 4; 9173b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_MEDIA_TOTAL_NUMBER = 5; 9183b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_GENRE = 6; 9193b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_PLAYING_TIME_MS = 7; 9203b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9213b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9223b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen public MediaAttributes(MediaMetadata data) { 9233b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen exists = data != null; 9243b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (!exists) 9253b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return; 9263b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9273b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen artistName = stringOrBlank(data.getString(MediaMetadata.METADATA_KEY_ARTIST)); 9283b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen albumName = stringOrBlank(data.getString(MediaMetadata.METADATA_KEY_ALBUM)); 9293b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen mediaNumber = longStringOrBlank(data.getLong(MediaMetadata.METADATA_KEY_TRACK_NUMBER)); 9303b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen mediaTotalNumber = longStringOrBlank(data.getLong(MediaMetadata.METADATA_KEY_NUM_TRACKS)); 9313b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen genre = stringOrBlank(data.getString(MediaMetadata.METADATA_KEY_GENRE)); 93293f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen playingTimeMs = data.getLong(MediaMetadata.METADATA_KEY_DURATION); 9333b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9343b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen // Try harder for the title. 9353b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen title = data.getString(MediaMetadata.METADATA_KEY_TITLE); 9363b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9373b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (title == null) { 9383b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen MediaDescription desc = data.getDescription(); 9393b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (desc != null) { 9403b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen CharSequence val = desc.getDescription(); 9413b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (val != null) 9423b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen title = val.toString(); 9433b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 9443b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 9453b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9463b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (title == null) 9473b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen title = new String(); 9483b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 9493b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 95093f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen public long getLength() { 95193f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen if (!exists) return 0L; 95293f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen return playingTimeMs; 95393f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen } 95493f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen 9553b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen public boolean equals(MediaAttributes other) { 9563b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (other == null) 9573b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return false; 9583b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9593b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (exists != other.exists) 9603b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return false; 9613b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9623b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (exists == false) 9633b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return true; 9643b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 96593f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen return (title.equals(other.title)) && (artistName.equals(other.artistName)) 96693f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen && (albumName.equals(other.albumName)) 96793f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen && (mediaNumber.equals(other.mediaNumber)) 96893f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen && (mediaTotalNumber.equals(other.mediaTotalNumber)) 96993f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen && (genre.equals(other.genre)) && (playingTimeMs == other.playingTimeMs); 9703b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 9713b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9723b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen public String getString(int attrId) { 9733b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (!exists) 9743b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return new String(); 9753b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9763b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen switch (attrId) { 9773b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_TITLE: 9783b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return title; 9793b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_ARTIST_NAME: 9803b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return artistName; 9813b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_ALBUM_NAME: 9823b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return albumName; 9833b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_MEDIA_NUMBER: 9843b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return mediaNumber; 9853b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_MEDIA_TOTAL_NUMBER: 9863b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return mediaTotalNumber; 9873b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_GENRE: 9883b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return genre; 9893b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_PLAYING_TIME_MS: 99093f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen return Long.toString(playingTimeMs); 9913b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen default: 9923b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return new String(); 9933b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 9943b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 9953b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9963b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String stringOrBlank(String s) { 9973b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return s == null ? new String() : s; 9983b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 999c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 10003b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String longStringOrBlank(Long s) { 10013b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return s == null ? new String() : s.toString(); 1002c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1003c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1004c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public String toString() { 1005e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!exists) { 10063b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return "[MediaAttributes: none]"; 1007e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 10083b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 100993f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen return "[MediaAttributes: " + title + " - " + albumName + " by " + artistName + " (" 101093f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen + playingTimeMs + " " + mediaNumber + "/" + mediaTotalNumber + ") " + genre 101193f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen + "]"; 1012c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1013029b34a866c2f4ab132412ec2814fd500813c565Marie Janssen 1014029b34a866c2f4ab132412ec2814fd500813c565Marie Janssen public String toRedactedString() { 1015029b34a866c2f4ab132412ec2814fd500813c565Marie Janssen if (!exists) { 1016029b34a866c2f4ab132412ec2814fd500813c565Marie Janssen return "[MediaAttributes: none]"; 1017029b34a866c2f4ab132412ec2814fd500813c565Marie Janssen } 1018029b34a866c2f4ab132412ec2814fd500813c565Marie Janssen 1019029b34a866c2f4ab132412ec2814fd500813c565Marie Janssen return "[MediaAttributes: " + Utils.ellipsize(title) + " - " 1020029b34a866c2f4ab132412ec2814fd500813c565Marie Janssen + Utils.ellipsize(albumName) + " by " + Utils.ellipsize(artistName) + " (" 1021029b34a866c2f4ab132412ec2814fd500813c565Marie Janssen + playingTimeMs + " " + mediaNumber + "/" + mediaTotalNumber + ") " + genre 1022029b34a866c2f4ab132412ec2814fd500813c565Marie Janssen + "]"; 1023029b34a866c2f4ab132412ec2814fd500813c565Marie Janssen } 1024c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1025c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 102667c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker private void updateCurrentMediaState() { 102785ff6903243d244d4342f390bb40aa99097a9a7cMarie Janssen // Only do player updates when we aren't registering for track changes. 1028d5b2445ec7ff3809c1c90a9b20784a6a861a037cMarie Janssen MediaAttributes currentAttributes; 1029b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen PlaybackState newState = updatePlaybackState(); 1030b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen 103186582543b9cd70a617e84c049c03b466653e9641Marie Janssen synchronized (this) { 103286582543b9cd70a617e84c049c03b466653e9641Marie Janssen if (mMediaController == null) { 1033d5b2445ec7ff3809c1c90a9b20784a6a861a037cMarie Janssen currentAttributes = new MediaAttributes(null); 103490dcb467d4964f65bde4f847a2e8fe0fe048c3a7Marie Janssen } else { 1035d5b2445ec7ff3809c1c90a9b20784a6a861a037cMarie Janssen currentAttributes = new MediaAttributes(mMediaController.getMetadata()); 103693f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen } 10370e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen } 1038e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 10393211ee063dc32e07ab00d94312637dd7c27d2bbaAjay Panicker byte newPlayStatus = getBluetoothPlayState(newState); 10403211ee063dc32e07ab00d94312637dd7c27d2bbaAjay Panicker 1041093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker if (newState.getState() != PlaybackState.STATE_BUFFERING 1042093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker && newState.getState() != PlaybackState.STATE_NONE) { 1043093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker long newQueueId = MediaSession.QueueItem.UNKNOWN_ID; 1044093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker if (newState != null) newQueueId = newState.getActiveQueueItemId(); 1045093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker Log.v(TAG, "Media update: id " + mLastQueueId + "➡" + newQueueId + "? " 1046093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker + currentAttributes.toRedactedString() + " : " 1047093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker + mMediaAttributes.toRedactedString()); 1048093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker 104967c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker if (mAvailablePlayerViewChanged) { 105067c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker registerNotificationRspAvalPlayerChangedNative( 105167c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker AvrcpConstants.NOTIFICATION_TYPE_CHANGED); 105267c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker mAvailablePlayerViewChanged = false; 105367c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker return; 105467c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker } 105567c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker 105667c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker if (mAddrPlayerChangedNT == AvrcpConstants.NOTIFICATION_TYPE_INTERIM 105767c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker && mReportedPlayerID != mCurrAddrPlayerID) { 105867c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker registerNotificationRspAvalPlayerChangedNative( 105967c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker AvrcpConstants.NOTIFICATION_TYPE_CHANGED); 106067c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker registerNotificationRspAddrPlayerChangedNative( 106167c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker AvrcpConstants.NOTIFICATION_TYPE_CHANGED, mCurrAddrPlayerID, sUIDCounter); 106267c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker 106367c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker mAvailablePlayerViewChanged = false; 106467c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker mAddrPlayerChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 106567c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker mReportedPlayerID = mCurrAddrPlayerID; 106667c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker 106767c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker // Update the now playing list without sending the notification 106867c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker mNowPlayingListChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 106967c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker mAddressedMediaPlayer.updateNowPlayingList(mMediaController); 107067c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker mNowPlayingListChangedNT = AvrcpConstants.NOTIFICATION_TYPE_INTERIM; 107167c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker } 107267c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker 1073093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker // Dont send now playing list changed if the player doesn't support browsing 1074093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker MediaPlayerInfo info = getAddressedPlayerInfo(); 1075093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker if (info != null && info.isBrowseSupported()) { 1076093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker Log.v(TAG, "Check if NowPlayingList is updated"); 1077093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker mAddressedMediaPlayer.updateNowPlayingList(mMediaController); 1078093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker } 1079093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker 1080093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker // Notify track changed if: 108167c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker // - The CT is registered for the notification 1082093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker // - Queue ID is UNKNOWN and MediaMetadata is different 108367c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker // - Queue ID is valid and different from last Queue ID sent 108467c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker if ((newQueueId == -1 || newQueueId != mLastQueueId) 108567c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker && mTrackChangedNT == AvrcpConstants.NOTIFICATION_TYPE_INTERIM 108667c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker && !currentAttributes.equals(mMediaAttributes) 108767c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker && newPlayStatus == PLAYSTATUS_PLAYING) { 1088093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker Log.v(TAG, "Send track changed"); 1089093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker mMediaAttributes = currentAttributes; 1090093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker mLastQueueId = newQueueId; 109167c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker sendTrackChangedRsp(false); 1092093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker } 1093093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker } else { 1094093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker Log.i(TAG, "Skipping update due to invalid playback state"); 1095c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1096093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker 10973211ee063dc32e07ab00d94312637dd7c27d2bbaAjay Panicker // still send the updated play state if the playback state is none or buffering 109876aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov Log.e(TAG, 109976aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov "play status change " + mReportedPlayStatus + "➡" + newPlayStatus 110076aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov + " mPlayStatusChangedNT: " + mPlayStatusChangedNT); 11013211ee063dc32e07ab00d94312637dd7c27d2bbaAjay Panicker if (mPlayStatusChangedNT == AvrcpConstants.NOTIFICATION_TYPE_INTERIM 110276aab6dba7956b15c6daafe99b6dddab3eb028a0Pavlin Radoslavov || (mReportedPlayStatus != newPlayStatus)) { 11033211ee063dc32e07ab00d94312637dd7c27d2bbaAjay Panicker sendPlaybackStatus(AvrcpConstants.NOTIFICATION_TYPE_CHANGED, newPlayStatus); 11043211ee063dc32e07ab00d94312637dd7c27d2bbaAjay Panicker } 11053211ee063dc32e07ab00d94312637dd7c27d2bbaAjay Panicker 1106b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen sendPlayPosNotificationRsp(false); 1107c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1108c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1109e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void getRcFeaturesRequestFromNative(byte[] address, int features) { 1110e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_RC_FEATURES, features, 0, 1111e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Utils.getAddressStringFromByte(address)); 111217675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 111317675906064bb72fdcca75baa56cdf8bb8968d01John Du } 111417675906064bb72fdcca75baa56cdf8bb8968d01John Du 1115e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void getPlayStatusRequestFromNative(byte[] address) { 1116e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_PLAY_STATUS); 1117e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = address; 1118c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.sendMessage(msg); 1119c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1120c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 11210f9c79e8afa3e575dfd8c80c2c58b9321e18898dMarie Janssen private void getElementAttrRequestFromNative(byte[] address, byte numAttr, int[] attrs) { 1122e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd avrcpCmdobj = new AvrcpCmd(); 1123e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd.ElementAttrCmd elemAttr = avrcpCmdobj.new ElementAttrCmd(address, numAttr, attrs); 1124e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_ELEM_ATTRS); 1125e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = elemAttr; 1126c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.sendMessage(msg); 1127c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1128c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1129e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void registerNotificationRequestFromNative(byte[] address,int eventId, int param) { 1130e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_REGISTER_NOTIFICATION, eventId, param); 1131e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = address; 1132c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.sendMessage(msg); 1133c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1134c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1135e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void processRegisterNotification(byte[] address, int eventId, int param) { 1136c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu switch (eventId) { 1137c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case EVT_PLAY_STATUS_CHANGED: 1138b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen mPlayStatusChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 1139b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen updatePlaybackState(); 11403211ee063dc32e07ab00d94312637dd7c27d2bbaAjay Panicker sendPlaybackStatus(AvrcpConstants.NOTIFICATION_TYPE_INTERIM, mReportedPlayStatus); 1141c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 1142c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1143c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case EVT_TRACK_CHANGED: 11440e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen Log.v(TAG, "Track changed notification enabled"); 1145e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_INTERIM; 1146093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker sendTrackChangedRsp(true); 1147c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 1148c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1149aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu case EVT_PLAY_POS_CHANGED: 1150e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPlayPosChangedNT = AvrcpConstants.NOTIFICATION_TYPE_INTERIM; 1151e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPlaybackIntervalMs = (long) param * 1000L; 1152fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen sendPlayPosNotificationRsp(true); 1153aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu break; 1154aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 1155e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case EVT_AVBL_PLAYERS_CHANGED: 1156e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Notify remote available players changed */ 1157d5b2445ec7ff3809c1c90a9b20784a6a861a037cMarie Janssen if (DEBUG) Log.d(TAG, "Available Players notification enabled"); 1158e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah registerNotificationRspAvalPlayerChangedNative( 1159e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpConstants.NOTIFICATION_TYPE_INTERIM); 1160e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 1161e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1162e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case EVT_ADDR_PLAYER_CHANGED: 1163e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Notify remote addressed players changed */ 1164d5b2445ec7ff3809c1c90a9b20784a6a861a037cMarie Janssen if (DEBUG) Log.d(TAG, "Addressed Player notification enabled"); 1165e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah registerNotificationRspAddrPlayerChangedNative( 1166e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpConstants.NOTIFICATION_TYPE_INTERIM, 1167e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mCurrAddrPlayerID, sUIDCounter); 1168b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen mAddrPlayerChangedNT = AvrcpConstants.NOTIFICATION_TYPE_INTERIM; 1169b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen mReportedPlayerID = mCurrAddrPlayerID; 1170e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 1171e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1172e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case EVENT_UIDS_CHANGED: 1173d5b2445ec7ff3809c1c90a9b20784a6a861a037cMarie Janssen if (DEBUG) Log.d(TAG, "UIDs changed notification enabled"); 1174e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah registerNotificationRspUIDsChangedNative( 1175e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpConstants.NOTIFICATION_TYPE_INTERIM, sUIDCounter); 1176e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 1177e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1178e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case EVENT_NOW_PLAYING_CONTENT_CHANGED: 1179d5b2445ec7ff3809c1c90a9b20784a6a861a037cMarie Janssen if (DEBUG) Log.d(TAG, "Now Playing List changed notification enabled"); 1180e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* send interim response to remote device */ 11813616b7ce7be6abaca5eef876e055155f9e8a3b1fAjay Panicker mNowPlayingListChangedNT = AvrcpConstants.NOTIFICATION_TYPE_INTERIM; 1182e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspNowPlayingChangedNative( 1183e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpConstants.NOTIFICATION_TYPE_INTERIM)) { 1184e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "EVENT_NOW_PLAYING_CONTENT_CHANGED: " + 1185e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah "registerNotificationRspNowPlayingChangedNative for Interim rsp failed!"); 1186e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1187e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 1188c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1189c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1190c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1191e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handlePassthroughCmdRequestFromNative(byte[] address, int id, int keyState) { 1192bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_PASS_THROUGH, id, keyState); 1193e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1194ace834feb02adabd61f628c4471147aea02d939cJohn Du } 1195ace834feb02adabd61f628c4471147aea02d939cJohn Du 1196d5b2445ec7ff3809c1c90a9b20784a6a861a037cMarie Janssen private void sendTrackChangedRsp(boolean registering) { 1197d5b2445ec7ff3809c1c90a9b20784a6a861a037cMarie Janssen if (!registering && mTrackChangedNT != AvrcpConstants.NOTIFICATION_TYPE_INTERIM) { 1198d5b2445ec7ff3809c1c90a9b20784a6a861a037cMarie Janssen if (DEBUG) Log.d(TAG, "sendTrackChangedRsp: Not registered or registering."); 1199827c417f70082918b965a5213c38395398389811Marie Janssen return; 1200827c417f70082918b965a5213c38395398389811Marie Janssen } 1201d5b2445ec7ff3809c1c90a9b20784a6a861a037cMarie Janssen 1202d5b2445ec7ff3809c1c90a9b20784a6a861a037cMarie Janssen mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 1203d5b2445ec7ff3809c1c90a9b20784a6a861a037cMarie Janssen if (registering) mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_INTERIM; 1204d5b2445ec7ff3809c1c90a9b20784a6a861a037cMarie Janssen 1205d5b2445ec7ff3809c1c90a9b20784a6a861a037cMarie Janssen MediaPlayerInfo info = getAddressedPlayerInfo(); 1206d5b2445ec7ff3809c1c90a9b20784a6a861a037cMarie Janssen // for non-browsable players or no player 1207351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen if (info != null && !info.isBrowseSupported()) { 1208d5b2445ec7ff3809c1c90a9b20784a6a861a037cMarie Janssen byte[] track = AvrcpConstants.TRACK_IS_SELECTED; 1209d5b2445ec7ff3809c1c90a9b20784a6a861a037cMarie Janssen if (!mMediaAttributes.exists) track = AvrcpConstants.NO_TRACK_SELECTED; 1210d5b2445ec7ff3809c1c90a9b20784a6a861a037cMarie Janssen registerNotificationRspTrackChangeNative(mTrackChangedNT, track); 1211d5b2445ec7ff3809c1c90a9b20784a6a861a037cMarie Janssen return; 1212e8e870c24930f9b687572dbb80614e5aad6fbdfaberyl hou } 1213e8e870c24930f9b687572dbb80614e5aad6fbdfaberyl hou 1214d5b2445ec7ff3809c1c90a9b20784a6a861a037cMarie Janssen mAddressedMediaPlayer.sendTrackChangeWithId(mTrackChangedNT, mMediaController); 1215c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1216c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1217aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long getPlayPosition() { 1218e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mCurrentPlayState == null) { 1219f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen return -1L; 1220e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1221f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 1222e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mCurrentPlayState.getPosition() == PlaybackState.PLAYBACK_POSITION_UNKNOWN) { 1223f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen return -1L; 1224e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1225f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 1226f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen if (isPlayingState(mCurrentPlayState)) { 122793f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen long sinceUpdate = 122893f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen (SystemClock.elapsedRealtime() - mCurrentPlayState.getLastPositionUpdateTime()); 122993f177151f5b96ce3e06888884da3cd7f7858ecfMarie Janssen return sinceUpdate + mCurrentPlayState.getPosition(); 1230aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 1231f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 12323635a926bd7316a55b288a54d409a1070a9c19e8Marie Janssen return mCurrentPlayState.getPosition(); 1233aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 1234aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 1235b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen private boolean isPlayingState(@Nullable PlaybackState state) { 1236b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen if (state == null) return false; 1237093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker return (state != null) && (state.getState() == PlaybackState.STATE_PLAYING); 1238188f205b5f093850d4cc627917a21204be36c56aZhihai Xu } 1239188f205b5f093850d4cc627917a21204be36c56aZhihai Xu 124017675906064bb72fdcca75baa56cdf8bb8968d01John Du /** 1241f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen * Sends a play position notification, or schedules one to be 1242f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen * sent later at an appropriate time. If |requested| is true, 1243f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen * does both because this was called in reponse to a request from the 1244f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen * TG. 1245f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen */ 1246f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen private void sendPlayPosNotificationRsp(boolean requested) { 1247e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!requested && mPlayPosChangedNT != AvrcpConstants.NOTIFICATION_TYPE_INTERIM) { 1248fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen if (DEBUG) Log.d(TAG, "sendPlayPosNotificationRsp: Not registered or requesting."); 1249fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen return; 1250fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen } 1251fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen 1252f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen long playPositionMs = getPlayPosition(); 1253a06a7e90bac455c4bc440a1e03117dd6ae41a653Marie Janssen String debugLine = "sendPlayPosNotificationRsp: "; 1254f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 1255f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen // mNextPosMs is set to -1 when the previous position was invalid 1256f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen // so this will be true if the new position is valid & old was invalid. 1257f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen // mPlayPositionMs is set to -1 when the new position is invalid, 1258f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen // and the old mPrevPosMs is >= 0 so this is true when the new is invalid 1259f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen // and the old was valid. 1260a06a7e90bac455c4bc440a1e03117dd6ae41a653Marie Janssen if (DEBUG) { 1261a06a7e90bac455c4bc440a1e03117dd6ae41a653Marie Janssen debugLine += "(" + requested + ") " + mPrevPosMs + " <=? " + playPositionMs + " <=? " 1262a06a7e90bac455c4bc440a1e03117dd6ae41a653Marie Janssen + mNextPosMs; 1263a06a7e90bac455c4bc440a1e03117dd6ae41a653Marie Janssen if (isPlayingState(mCurrentPlayState)) debugLine += " Playing"; 1264a06a7e90bac455c4bc440a1e03117dd6ae41a653Marie Janssen debugLine += " State: " + mCurrentPlayState.getState(); 1265a06a7e90bac455c4bc440a1e03117dd6ae41a653Marie Janssen } 1266fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen if (requested || ((mLastReportedPosition != playPositionMs) && 1267e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah (playPositionMs >= mNextPosMs) || (playPositionMs <= mPrevPosMs))) { 1268e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!requested) mPlayPosChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 1269e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah registerNotificationRspPlayPosNative(mPlayPosChangedNT, (int) playPositionMs); 1270fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen mLastReportedPosition = playPositionMs; 1271f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen if (playPositionMs != PlaybackState.PLAYBACK_POSITION_UNKNOWN) { 1272f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen mNextPosMs = playPositionMs + mPlaybackIntervalMs; 1273f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen mPrevPosMs = playPositionMs - mPlaybackIntervalMs; 1274f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } else { 1275f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen mNextPosMs = -1; 1276f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen mPrevPosMs = -1; 1277f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } 1278f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } 1279f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 1280e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.removeMessages(MSG_PLAY_INTERVAL_TIMEOUT); 1281e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mPlayPosChangedNT == AvrcpConstants.NOTIFICATION_TYPE_INTERIM && isPlayingState(mCurrentPlayState)) { 1282e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_PLAY_INTERVAL_TIMEOUT); 1283f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen long delay = mPlaybackIntervalMs; 1284f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen if (mNextPosMs != -1) { 1285f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen delay = mNextPosMs - (playPositionMs > 0 ? playPositionMs : 0); 1286f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } 1287a06a7e90bac455c4bc440a1e03117dd6ae41a653Marie Janssen if (DEBUG) debugLine += " Timeout " + delay + "ms"; 1288f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen mHandler.sendMessageDelayed(msg, delay); 1289f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } 1290a06a7e90bac455c4bc440a1e03117dd6ae41a653Marie Janssen if (DEBUG) Log.d(TAG, debugLine); 1291f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } 1292f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 1293f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen /** 129417675906064bb72fdcca75baa56cdf8bb8968d01John Du * This is called from AudioService. It will return whether this device supports abs volume. 129517675906064bb72fdcca75baa56cdf8bb8968d01John Du * NOT USED AT THE MOMENT. 129617675906064bb72fdcca75baa56cdf8bb8968d01John Du */ 129717675906064bb72fdcca75baa56cdf8bb8968d01John Du public boolean isAbsoluteVolumeSupported() { 129817675906064bb72fdcca75baa56cdf8bb8968d01John Du return ((mFeatures & BTRC_FEAT_ABSOLUTE_VOLUME) != 0); 129917675906064bb72fdcca75baa56cdf8bb8968d01John Du } 130017675906064bb72fdcca75baa56cdf8bb8968d01John Du 130117675906064bb72fdcca75baa56cdf8bb8968d01John Du /** 130217675906064bb72fdcca75baa56cdf8bb8968d01John Du * We get this call from AudioService. This will send a message to our handler object, 130317675906064bb72fdcca75baa56cdf8bb8968d01John Du * requesting our handler to call setVolumeNative() 130417675906064bb72fdcca75baa56cdf8bb8968d01John Du */ 130517675906064bb72fdcca75baa56cdf8bb8968d01John Du public void adjustVolume(int direction) { 1306e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_ADJUST_VOLUME, direction, 0); 130717675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 130817675906064bb72fdcca75baa56cdf8bb8968d01John Du } 130917675906064bb72fdcca75baa56cdf8bb8968d01John Du 131017675906064bb72fdcca75baa56cdf8bb8968d01John Du public void setAbsoluteVolume(int volume) { 131111798b011c962b602217b479130d413f3b30f19aLiejun Tao if (volume == mLocalVolume) { 131211798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.v(TAG, "setAbsoluteVolume is setting same index, ignore "+volume); 131311798b011c962b602217b479130d413f3b30f19aLiejun Tao return; 131411798b011c962b602217b479130d413f3b30f19aLiejun Tao } 131511798b011c962b602217b479130d413f3b30f19aLiejun Tao 1316e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.removeMessages(MSG_ADJUST_VOLUME); 1317e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_SET_ABSOLUTE_VOLUME, volume, 0); 131817675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 13195c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta } 13205c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta 132117675906064bb72fdcca75baa56cdf8bb8968d01John Du /* Called in the native layer as a btrc_callback to return the volume set on the carkit in the 132217675906064bb72fdcca75baa56cdf8bb8968d01John Du * case when the volume is change locally on the carkit. This notification is not called when 132317675906064bb72fdcca75baa56cdf8bb8968d01John Du * the volume is changed from the phone. 132417675906064bb72fdcca75baa56cdf8bb8968d01John Du * 132517675906064bb72fdcca75baa56cdf8bb8968d01John Du * This method will send a message to our handler to change the local stored volume and notify 132617675906064bb72fdcca75baa56cdf8bb8968d01John Du * AudioService to update the UI 132717675906064bb72fdcca75baa56cdf8bb8968d01John Du */ 1328e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void volumeChangeRequestFromNative(byte[] address, int volume, int ctype) { 1329e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_VOLUME_CHANGE, volume, ctype); 1330e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = new Bundle(); 1331e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByteArray("BdAddress" , address); 1332e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.setData(data); 1333e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1334e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1335e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1336ce0f15c8598a1e570faf80bbc60e0568d2d20d45Marie Janssen private void getFolderItemsRequestFromNative( 1337ce0f15c8598a1e570faf80bbc60e0568d2d20d45Marie Janssen byte[] address, byte scope, long startItem, long endItem, byte numAttr, int[] attrIds) { 1338e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd avrcpCmdobj = new AvrcpCmd(); 1339e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd.FolderItemsCmd folderObj = avrcpCmdobj.new FolderItemsCmd(address, scope, 1340e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah startItem, endItem, numAttr, attrIds); 1341e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_FOLDER_ITEMS, 0, 0); 1342e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = folderObj; 1343e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1344e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1345e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1346e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void setAddressedPlayerRequestFromNative(byte[] address, int playerId) { 1347e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_SET_ADDR_PLAYER, playerId, 0); 1348e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = address; 1349e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1350e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1351e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1352e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void setBrowsedPlayerRequestFromNative(byte[] address, int playerId) { 1353e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_SET_BR_PLAYER, playerId, 0); 1354e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = address; 1355e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1356e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1357e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1358e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void changePathRequestFromNative(byte[] address, byte direction, byte[] folderUid) { 1359e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = new Bundle(); 1360e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_CHANGE_PATH); 1361e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByteArray("BdAddress" , address); 1362e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByteArray("folderUid" , folderUid); 1363e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByte("direction" , direction); 1364e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.setData(data); 1365e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1366e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1367e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1368e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void getItemAttrRequestFromNative(byte[] address, byte scope, byte[] itemUid, int uidCounter, 1369e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte numAttr, int[] attrs) { 1370e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd avrcpCmdobj = new AvrcpCmd(); 1371e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd.ItemAttrCmd itemAttr = avrcpCmdobj.new ItemAttrCmd(address, scope, 1372e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah itemUid, uidCounter, numAttr, attrs); 1373e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_ITEM_ATTR); 1374e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = itemAttr; 1375e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1376e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1377e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1378e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void searchRequestFromNative(byte[] address, int charsetId, byte[] searchStr) { 1379e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Search is not supported */ 1380303c1c67dbc142822bc37e7c5a89fba82faf2ac0Marie Janssen Log.w(TAG, "searchRequestFromNative: search is not supported"); 1381e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah searchRspNative(address, AvrcpConstants.RSP_SRCH_NOT_SPRTD, 0, 0); 1382e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1383e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1384e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void playItemRequestFromNative(byte[] address, byte scope, int uidCounter, byte[] uid) { 1385e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = new Bundle(); 1386e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_PLAY_ITEM); 1387e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByteArray("BdAddress" , address); 1388e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByteArray("uid" , uid); 1389e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putInt("uidCounter" , uidCounter); 1390e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByte("scope" , scope); 1391e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.setData(data); 1392e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1393e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1394e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1395e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void addToPlayListRequestFromNative(byte[] address, byte scope, byte[] uid, int uidCounter) { 1396e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* add to NowPlaying not supported */ 1397303c1c67dbc142822bc37e7c5a89fba82faf2ac0Marie Janssen Log.w(TAG, "addToPlayListRequestFromNative: not supported! scope=" + scope); 1398e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah addToNowPlayingRspNative(address, AvrcpConstants.RSP_INTERNAL_ERR); 1399e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1400e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1401e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void getTotalNumOfItemsRequestFromNative(byte[] address, byte scope) { 1402e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = new Bundle(); 1403e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_TOTAL_NUM_OF_ITEMS); 1404e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.arg1 = scope; 1405e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = address; 140617675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 140717675906064bb72fdcca75baa56cdf8bb8968d01John Du } 140817675906064bb72fdcca75baa56cdf8bb8968d01John Du 14092e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie private void notifyVolumeChanged(int volume) { 14102e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 14112e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_BLUETOOTH_ABS_VOLUME); 141217675906064bb72fdcca75baa56cdf8bb8968d01John Du } 141317675906064bb72fdcca75baa56cdf8bb8968d01John Du 141417675906064bb72fdcca75baa56cdf8bb8968d01John Du private int convertToAudioStreamVolume(int volume) { 141517675906064bb72fdcca75baa56cdf8bb8968d01John Du // Rescale volume to match AudioSystem's volume 141611798b011c962b602217b479130d413f3b30f19aLiejun Tao return (int) Math.floor((double) volume*mAudioStreamMax/AVRCP_MAX_VOL); 141717675906064bb72fdcca75baa56cdf8bb8968d01John Du } 141817675906064bb72fdcca75baa56cdf8bb8968d01John Du 141917675906064bb72fdcca75baa56cdf8bb8968d01John Du private int convertToAvrcpVolume(int volume) { 14202e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie return (int) Math.ceil((double) volume*AVRCP_MAX_VOL/mAudioStreamMax); 142117675906064bb72fdcca75baa56cdf8bb8968d01John Du } 142217675906064bb72fdcca75baa56cdf8bb8968d01John Du 142311798b011c962b602217b479130d413f3b30f19aLiejun Tao private void blackListCurrentDevice() { 142411798b011c962b602217b479130d413f3b30f19aLiejun Tao mFeatures &= ~BTRC_FEAT_ABSOLUTE_VOLUME; 142511798b011c962b602217b479130d413f3b30f19aLiejun Tao mAudioManager.avrcpSupportsAbsoluteVolume(mAddress, isAbsoluteVolumeSupported()); 142611798b011c962b602217b479130d413f3b30f19aLiejun Tao 142711798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences pref = mContext.getSharedPreferences(ABSOLUTE_VOLUME_BLACKLIST, 142811798b011c962b602217b479130d413f3b30f19aLiejun Tao Context.MODE_PRIVATE); 142911798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences.Editor editor = pref.edit(); 143011798b011c962b602217b479130d413f3b30f19aLiejun Tao editor.putBoolean(mAddress, true); 14317eeb95b6f29a6f55e117e329468168d4bcbec0c8Jack He editor.apply(); 143211798b011c962b602217b479130d413f3b30f19aLiejun Tao } 143311798b011c962b602217b479130d413f3b30f19aLiejun Tao 143411798b011c962b602217b479130d413f3b30f19aLiejun Tao private int modifyRcFeatureFromBlacklist(int feature, String address) { 143511798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences pref = mContext.getSharedPreferences(ABSOLUTE_VOLUME_BLACKLIST, 143611798b011c962b602217b479130d413f3b30f19aLiejun Tao Context.MODE_PRIVATE); 143711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (!pref.contains(address)) { 143811798b011c962b602217b479130d413f3b30f19aLiejun Tao return feature; 143911798b011c962b602217b479130d413f3b30f19aLiejun Tao } 144011798b011c962b602217b479130d413f3b30f19aLiejun Tao if (pref.getBoolean(address, false)) { 144111798b011c962b602217b479130d413f3b30f19aLiejun Tao feature &= ~BTRC_FEAT_ABSOLUTE_VOLUME; 144211798b011c962b602217b479130d413f3b30f19aLiejun Tao } 144311798b011c962b602217b479130d413f3b30f19aLiejun Tao return feature; 144411798b011c962b602217b479130d413f3b30f19aLiejun Tao } 144511798b011c962b602217b479130d413f3b30f19aLiejun Tao 144611798b011c962b602217b479130d413f3b30f19aLiejun Tao public void resetBlackList(String address) { 144711798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences pref = mContext.getSharedPreferences(ABSOLUTE_VOLUME_BLACKLIST, 144811798b011c962b602217b479130d413f3b30f19aLiejun Tao Context.MODE_PRIVATE); 144911798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences.Editor editor = pref.edit(); 145011798b011c962b602217b479130d413f3b30f19aLiejun Tao editor.remove(address); 14517eeb95b6f29a6f55e117e329468168d4bcbec0c8Jack He editor.apply(); 145211798b011c962b602217b479130d413f3b30f19aLiejun Tao } 145311798b011c962b602217b479130d413f3b30f19aLiejun Tao 1454188f205b5f093850d4cc627917a21204be36c56aZhihai Xu /** 1455188f205b5f093850d4cc627917a21204be36c56aZhihai Xu * This is called from A2dpStateMachine to set A2dp audio state. 1456188f205b5f093850d4cc627917a21204be36c56aZhihai Xu */ 1457188f205b5f093850d4cc627917a21204be36c56aZhihai Xu public void setA2dpAudioState(int state) { 1458e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_SET_A2DP_AUDIO_STATE, state, 0); 1459188f205b5f093850d4cc627917a21204be36c56aZhihai Xu mHandler.sendMessage(msg); 1460188f205b5f093850d4cc627917a21204be36c56aZhihai Xu } 1461188f205b5f093850d4cc627917a21204be36c56aZhihai Xu 14620427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker private class AvrcpServiceBootReceiver extends BroadcastReceiver { 14630427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker @Override 14640427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker public void onReceive(Context context, Intent intent) { 14650427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker String action = intent.getAction(); 1466eb829bbfa257c84c4f8fa589b54791e3f413b486Ajay Panicker if (action.equals(Intent.ACTION_USER_UNLOCKED)) { 1467eb829bbfa257c84c4f8fa589b54791e3f413b486Ajay Panicker if (DEBUG) Log.d(TAG, "User unlocked, initializing player lists"); 14680427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker /* initializing media player's list */ 14691111f243441532aefeadf322a9ab9800e330007bAjay Panicker buildBrowsablePlayerList(); 14700427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker } 14710427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker } 14720427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker } 14730427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker 1474e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private class AvrcpServiceBroadcastReceiver extends BroadcastReceiver { 1475e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah @Override 1476e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void onReceive(Context context, Intent intent) { 1477e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String action = intent.getAction(); 1478e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "AvrcpServiceBroadcastReceiver-> Action: " + action); 1479e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1480e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (action.equals(Intent.ACTION_PACKAGE_REMOVED) 1481e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah || action.equals(Intent.ACTION_PACKAGE_DATA_CLEARED)) { 1482e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { 1483e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // a package is being removed, not replaced 1484e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String packageName = intent.getData().getSchemeSpecificPart(); 1485e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (packageName != null) { 1486e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handlePackageModified(packageName, true); 1487e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1488e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1489e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1490e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else if (action.equals(Intent.ACTION_PACKAGE_ADDED) 1491e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah || action.equals(Intent.ACTION_PACKAGE_CHANGED)) { 1492e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String packageName = intent.getData().getSchemeSpecificPart(); 1493e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG,"AvrcpServiceBroadcastReceiver-> packageName: " 1494e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + packageName); 1495e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (packageName != null) { 1496e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handlePackageModified(packageName, false); 1497e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1498e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1499e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1500838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood } 1501838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood 1502e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handlePackageModified(String packageName, boolean removed) { 1503e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "packageName: " + packageName + " removed: " + removed); 1504c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1505e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (removed) { 1506d89304c6be6e1c332008dcbeab08889881064454Marie Janssen removeMediaPlayerInfo(packageName); 1507e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // old package is removed, updating local browsable player's list 1508e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (isBrowseSupported(packageName)) { 1509e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah removePackageFromBrowseList(packageName); 1510e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1511e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 1512e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // new package has been added. 1513e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (isBrowsableListUpdated(packageName)) { 1514e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // Rebuilding browsable players list 15151111f243441532aefeadf322a9ab9800e330007bAjay Panicker buildBrowsablePlayerList(); 1516e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1517e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1518e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1519c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1520e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean isBrowsableListUpdated(String newPackageName) { 1521e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // getting the browsable media players list from package manager 1522e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Intent intent = new Intent("android.media.browse.MediaBrowserService"); 15230427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker List<ResolveInfo> resInfos = mPackageManager.queryIntentServices(intent, 15240427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker PackageManager.MATCH_ALL); 1525e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah for (ResolveInfo resolveInfo : resInfos) { 15263843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen if (resolveInfo.serviceInfo.packageName.equals(newPackageName)) { 15273843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen if (DEBUG) 15283843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen Log.d(TAG, 15293843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen "isBrowsableListUpdated: package includes MediaBrowserService, true"); 15303843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen return true; 15313843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen } 1532e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1533c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 15343843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen // if list has different size 15353843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen if (resInfos.size() != mBrowsePlayerInfoList.size()) { 15363843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen if (DEBUG) Log.d(TAG, "isBrowsableListUpdated: browsable list size mismatch, true"); 15373843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen return true; 1538e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 15393843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen 15403843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen Log.d(TAG, "isBrowsableListUpdated: false"); 15413843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen return false; 1542e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1543e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 15448cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen private void removePackageFromBrowseList(String packageName) { 1545e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "removePackageFromBrowseList: " + packageName); 15468cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen synchronized (mBrowsePlayerInfoList) { 15478cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen int browseInfoID = getBrowseId(packageName); 15488cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (browseInfoID != -1) { 15498cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen mBrowsePlayerInfoList.remove(browseInfoID); 15508cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 1551e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1552e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1553e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1554e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* 1555e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * utility function to get the browse player index from global browsable 1556e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * list. It may return -1 if specified package name is not in the list. 1557e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 15588cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen private int getBrowseId(String packageName) { 1559e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah boolean response = false; 1560e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int browseInfoID = 0; 15618cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen synchronized (mBrowsePlayerInfoList) { 15628cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen for (BrowsePlayerInfo info : mBrowsePlayerInfoList) { 15638cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (info.packageName.equals(packageName)) { 15648cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen response = true; 15658cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen break; 15668cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 15678cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen browseInfoID++; 1568e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1569e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1570e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1571e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!response) { 1572e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah browseInfoID = -1; 1573e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1574e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1575e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "getBrowseId for packageName: " + packageName + 1576e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah " , browseInfoID: " + browseInfoID); 1577e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return browseInfoID; 1578e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1579e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1580e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void setAddressedPlayer(byte[] bdaddr, int selectedId) { 158107331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen String functionTag = "setAddressedPlayer(" + selectedId + "): "; 1582e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 15838cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen synchronized (mMediaPlayerInfoList) { 15848cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (mMediaPlayerInfoList.isEmpty()) { 158507331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen Log.w(TAG, functionTag + "no players, send no available players"); 158607331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen setAddressedPlayerRspNative(bdaddr, AvrcpConstants.RSP_NO_AVBL_PLAY); 158707331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen return; 158807331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen } 158907331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen if (!mMediaPlayerInfoList.containsKey(selectedId)) { 159007331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen Log.w(TAG, functionTag + "invalid id, sending response back "); 159107331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen setAddressedPlayerRspNative(bdaddr, AvrcpConstants.RSP_INV_PLAYER); 159207331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen return; 159307331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen } 159407331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen 159507331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen if (isPlayerAlreadyAddressed(selectedId)) { 15968cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen MediaPlayerInfo info = getAddressedPlayerInfo(); 159707331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen Log.i(TAG, functionTag + "player already addressed: " + info); 159807331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen setAddressedPlayerRspNative(bdaddr, AvrcpConstants.RSP_NO_ERROR); 159907331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen return; 160007331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen } 160107331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen // register new Media Controller Callback and update the current IDs 160207331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen if (!updateCurrentController(selectedId, mCurrBrowsePlayerID)) { 160307331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen Log.e(TAG, functionTag + "updateCurrentController failed!"); 160407331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen setAddressedPlayerRspNative(bdaddr, AvrcpConstants.RSP_INTERNAL_ERR); 160507331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen return; 160607331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen } 160707331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen // If we don't have a controller, try to launch the player 160807331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen MediaPlayerInfo info = getAddressedPlayerInfo(); 160907331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen if (info.getMediaController() == null) { 161007331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen Intent launch = mPackageManager.getLaunchIntentForPackage(info.getPackageName()); 161107331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen Log.i(TAG, functionTag + "launching player " + launch); 161207331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen mContext.startActivity(launch); 1613e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1614e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 161507331cbd302f65c1cc72be3f7f20004127cdd1fbMarie Janssen setAddressedPlayerRspNative(bdaddr, AvrcpConstants.RSP_NO_ERROR); 1616e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1617e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1618e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void setBrowsedPlayer(byte[] bdaddr, int selectedId) { 1619e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int status = AvrcpConstants.RSP_NO_ERROR; 1620e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1621e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // checking for error cases 16228cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (mMediaPlayerInfoList.isEmpty()) { 1623e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah status = AvrcpConstants.RSP_NO_AVBL_PLAY; 1624cb63ca088b6657757fdf6bb8f3cdb58aaee9e4c3Marie Janssen Log.w(TAG, "setBrowsedPlayer: No available players! "); 1625e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 1626cb63ca088b6657757fdf6bb8f3cdb58aaee9e4c3Marie Janssen // Workaround for broken controllers selecting ID 0 1627cb63ca088b6657757fdf6bb8f3cdb58aaee9e4c3Marie Janssen // Seen at least on Ford, Chevrolet MyLink 1628cb63ca088b6657757fdf6bb8f3cdb58aaee9e4c3Marie Janssen if (selectedId == 0) { 1629cb63ca088b6657757fdf6bb8f3cdb58aaee9e4c3Marie Janssen Log.w(TAG, "setBrowsedPlayer: workaround invalid id 0"); 1630cb63ca088b6657757fdf6bb8f3cdb58aaee9e4c3Marie Janssen selectedId = mCurrAddrPlayerID; 1631cb63ca088b6657757fdf6bb8f3cdb58aaee9e4c3Marie Janssen } 1632cb63ca088b6657757fdf6bb8f3cdb58aaee9e4c3Marie Janssen 1633e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // update current browse player id and start browsing service 1634e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah updateNewIds(mCurrAddrPlayerID, selectedId); 1635e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String browsedPackage = getPackageName(selectedId); 1636e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1637e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!isPackageNameValid(browsedPackage)) { 1638e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, " Invalid package for id:" + mCurrBrowsePlayerID); 1639e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah status = AvrcpConstants.RSP_INV_PLAYER; 1640e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else if (!isBrowseSupported(browsedPackage)) { 1641e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, "Browse unsupported for id:" + mCurrBrowsePlayerID 1642e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + ", packagename : " + browsedPackage); 1643e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah status = AvrcpConstants.RSP_PLAY_NOT_BROW; 1644e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else if (!startBrowseService(bdaddr, browsedPackage)) { 1645e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "service cannot be started for browse player id:" + mCurrBrowsePlayerID 1646e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + ", packagename : " + browsedPackage); 1647e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah status = AvrcpConstants.RSP_INTERNAL_ERR; 1648e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1649e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1650e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1651e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (status != AvrcpConstants.RSP_NO_ERROR) { 1652e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah setBrowsedPlayerRspNative(bdaddr, status, (byte) 0x00, 0, null); 1653e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1654e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1655e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "setBrowsedPlayer for selectedId: " + selectedId + 1656e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah " , status: " + status); 1657e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1658e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1659bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen private MediaSessionManager.OnActiveSessionsChangedListener mActiveSessionListener = 1660bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen new MediaSessionManager.OnActiveSessionsChangedListener() { 1661e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1662bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen @Override 1663bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen public void onActiveSessionsChanged( 1664bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen List<android.media.session.MediaController> newControllers) { 16657c12b34b98d717fdfe68f5e8c94b7a01ef372f8bMarie Janssen Set<String> updatedPackages = new HashSet<String>(); 1666bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen // Update the current players 1667bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen for (android.media.session.MediaController controller : newControllers) { 16687c12b34b98d717fdfe68f5e8c94b7a01ef372f8bMarie Janssen String packageName = controller.getPackageName(); 16697c12b34b98d717fdfe68f5e8c94b7a01ef372f8bMarie Janssen if (DEBUG) Log.v(TAG, "ActiveSession: " + MediaController.wrap(controller)); 16707c12b34b98d717fdfe68f5e8c94b7a01ef372f8bMarie Janssen // Only use the first (highest priority) controller from each package 16717c12b34b98d717fdfe68f5e8c94b7a01ef372f8bMarie Janssen if (updatedPackages.contains(packageName)) continue; 1672bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen addMediaPlayerController(controller); 16737c12b34b98d717fdfe68f5e8c94b7a01ef372f8bMarie Janssen updatedPackages.add(packageName); 1674351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen } 1675d996f17ea97b2c592338bcfbc93056d0224da1cdAjay Panicker 167685ff6903243d244d4342f390bb40aa99097a9a7cMarie Janssen if (newControllers.size() > 0 && getAddressedPlayerInfo() == null) { 167785ff6903243d244d4342f390bb40aa99097a9a7cMarie Janssen if (DEBUG) 167885ff6903243d244d4342f390bb40aa99097a9a7cMarie Janssen Log.v(TAG, "No addressed player but active sessions, taking first."); 167985ff6903243d244d4342f390bb40aa99097a9a7cMarie Janssen setAddressedMediaSessionPackage(newControllers.get(0).getPackageName()); 1680351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen } 168167c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker updateCurrentMediaState(); 1682e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1683bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen }; 1684bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen 16850c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen private void setAddressedMediaSessionPackage(@Nullable String packageName) { 16861107f9516bf8866640247044deb9f780bb89e55cMarie Janssen if (packageName == null) { 16871107f9516bf8866640247044deb9f780bb89e55cMarie Janssen // Should only happen when there's no media players, reset to no available player. 16881107f9516bf8866640247044deb9f780bb89e55cMarie Janssen updateCurrentController(0, mCurrBrowsePlayerID); 16891107f9516bf8866640247044deb9f780bb89e55cMarie Janssen return; 16901107f9516bf8866640247044deb9f780bb89e55cMarie Janssen } 1691c833de68eb3f5a82db6e83166e18504e83e5d035Ajay Panicker if (packageName.equals("com.android.server.telecom")) { 1692c833de68eb3f5a82db6e83166e18504e83e5d035Ajay Panicker Log.d(TAG, "Ignore addressed media session change to telecom"); 1693c833de68eb3f5a82db6e83166e18504e83e5d035Ajay Panicker return; 1694c833de68eb3f5a82db6e83166e18504e83e5d035Ajay Panicker } 1695bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen // No change. 1696bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen if (getPackageName(mCurrAddrPlayerID).equals(packageName)) return; 16970c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen if (DEBUG) Log.v(TAG, "Changing addressed media session to " + packageName); 1698bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen // If the player doesn't exist, we need to add it. 1699bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen if (getMediaPlayerInfo(packageName) == null) { 1700bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen addMediaPlayerPackage(packageName); 170167c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker updateCurrentMediaState(); 1702bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 17038cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen synchronized (mMediaPlayerInfoList) { 17048cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) { 17058cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (entry.getValue().getPackageName().equals(packageName)) { 17068cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen int newAddrID = entry.getKey(); 17078cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (DEBUG) Log.v(TAG, "Set addressed #" + newAddrID + " " + entry.getValue()); 17088cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen updateCurrentController(newAddrID, mCurrBrowsePlayerID); 170967c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker updateCurrentMediaState(); 17108cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen return; 17118cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 1712e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1713e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1714bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen // We shouldn't ever get here. 1715bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen Log.e(TAG, "Player info for " + packageName + " doesn't exist!"); 1716bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 1717e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1718bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen private void setActiveMediaSession(MediaSession.Token token) { 1719bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen android.media.session.MediaController activeController = 1720bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen new android.media.session.MediaController(mContext, token); 1721c833de68eb3f5a82db6e83166e18504e83e5d035Ajay Panicker if (activeController.getPackageName().equals("com.android.server.telecom")) { 1722c833de68eb3f5a82db6e83166e18504e83e5d035Ajay Panicker Log.d(TAG, "Ignore active media session change to telecom"); 1723c833de68eb3f5a82db6e83166e18504e83e5d035Ajay Panicker return; 1724c833de68eb3f5a82db6e83166e18504e83e5d035Ajay Panicker } 1725bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen if (DEBUG) Log.v(TAG, "Set active media session " + activeController.getPackageName()); 1726bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen addMediaPlayerController(activeController); 1727bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen setAddressedMediaSessionPackage(activeController.getPackageName()); 1728bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 1729e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1730e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean startBrowseService(byte[] bdaddr, String packageName) { 1731e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah boolean status = true; 1732e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1733e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* creating new instance for Browse Media Player */ 1734e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String browseService = getBrowseServiceName(packageName); 1735e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!browseService.isEmpty()) { 1736e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr).setBrowsed( 1737e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah packageName, browseService); 1738e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 1739e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, "No Browser service available for " + packageName); 1740e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah status = false; 1741e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1742e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1743e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "startBrowseService for packageName: " + packageName + 1744e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ", status = " + status); 1745e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return status; 1746e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1747e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 17488cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen private String getBrowseServiceName(String packageName) { 1749e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String browseServiceName = ""; 1750e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1751e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // getting the browse service name from browse player info 17528cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen synchronized (mBrowsePlayerInfoList) { 17538cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen int browseInfoID = getBrowseId(packageName); 17548cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (browseInfoID != -1) { 17558cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen browseServiceName = mBrowsePlayerInfoList.get(browseInfoID).serviceClass; 17568cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 1757e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1758e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1759e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "getBrowseServiceName for packageName: " + packageName + 1760e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ", browseServiceName = " + browseServiceName); 1761e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return browseServiceName; 1762e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1763e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 17641111f243441532aefeadf322a9ab9800e330007bAjay Panicker void buildBrowsablePlayerList() { 17651111f243441532aefeadf322a9ab9800e330007bAjay Panicker synchronized (mBrowsePlayerInfoList) { 17663843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen mBrowsePlayerInfoList.clear(); 17673843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen Intent intent = new Intent(android.service.media.MediaBrowserService.SERVICE_INTERFACE); 17681111f243441532aefeadf322a9ab9800e330007bAjay Panicker List<ResolveInfo> playerList = 17691111f243441532aefeadf322a9ab9800e330007bAjay Panicker mPackageManager.queryIntentServices(intent, PackageManager.MATCH_ALL); 17701111f243441532aefeadf322a9ab9800e330007bAjay Panicker 17711111f243441532aefeadf322a9ab9800e330007bAjay Panicker for (ResolveInfo info : playerList) { 17721111f243441532aefeadf322a9ab9800e330007bAjay Panicker String displayableName = info.loadLabel(mPackageManager).toString(); 17731111f243441532aefeadf322a9ab9800e330007bAjay Panicker String serviceName = info.serviceInfo.name; 17741111f243441532aefeadf322a9ab9800e330007bAjay Panicker String packageName = info.serviceInfo.packageName; 17751111f243441532aefeadf322a9ab9800e330007bAjay Panicker 17761111f243441532aefeadf322a9ab9800e330007bAjay Panicker if (DEBUG) Log.d(TAG, "Adding " + serviceName + " to list of browsable players"); 17771111f243441532aefeadf322a9ab9800e330007bAjay Panicker BrowsePlayerInfo currentPlayer = 17781111f243441532aefeadf322a9ab9800e330007bAjay Panicker new BrowsePlayerInfo(packageName, displayableName, serviceName); 17791111f243441532aefeadf322a9ab9800e330007bAjay Panicker mBrowsePlayerInfoList.add(currentPlayer); 17801111f243441532aefeadf322a9ab9800e330007bAjay Panicker MediaPlayerInfo playerInfo = getMediaPlayerInfo(packageName); 17811111f243441532aefeadf322a9ab9800e330007bAjay Panicker MediaController controller = 17821111f243441532aefeadf322a9ab9800e330007bAjay Panicker (playerInfo == null) ? null : playerInfo.getMediaController(); 17831111f243441532aefeadf322a9ab9800e330007bAjay Panicker // Refresh the media player entry so it notices we can browse 17841111f243441532aefeadf322a9ab9800e330007bAjay Panicker if (controller != null) { 17851111f243441532aefeadf322a9ab9800e330007bAjay Panicker addMediaPlayerController(controller.getWrappedInstance()); 17861111f243441532aefeadf322a9ab9800e330007bAjay Panicker } else { 17871111f243441532aefeadf322a9ab9800e330007bAjay Panicker addMediaPlayerPackage(packageName); 1788351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen } 17893843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen } 179067c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker updateCurrentMediaState(); 1791e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1792e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1793e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1794bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen /* Initializes list of media players identified from session manager active sessions */ 17958cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen private void initMediaPlayersList() { 17968cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen synchronized (mMediaPlayerInfoList) { 17978cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen // Clearing old browsable player's list 17988cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen mMediaPlayerInfoList.clear(); 1799bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen 18008cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (mMediaSessionManager == null) { 18018cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (DEBUG) Log.w(TAG, "initMediaPlayersList: no media session manager!"); 18028cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen return; 18038cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 1804bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen 18058cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen List<android.media.session.MediaController> controllers = 18068cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen mMediaSessionManager.getActiveSessions(null); 18078cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (DEBUG) 18088cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen Log.v(TAG, "initMediaPlayerInfoList: " + controllers.size() + " controllers"); 18098cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen /* Initializing all media players */ 18108cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen for (android.media.session.MediaController controller : controllers) { 18118cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen addMediaPlayerController(controller); 18128cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 181385ff6903243d244d4342f390bb40aa99097a9a7cMarie Janssen 181467c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker updateCurrentMediaState(); 1815e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 18168cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (mMediaPlayerInfoList.size() > 0) { 18178cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen // Set the first one as the Addressed Player 18188cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen updateCurrentController(mMediaPlayerInfoList.firstKey(), -1); 18198cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 1820e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1821e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1822e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1823351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen private List<android.media.session.MediaController> getMediaControllers() { 1824351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen List<android.media.session.MediaController> controllers = 1825351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen new ArrayList<android.media.session.MediaController>(); 18268cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen synchronized (mMediaPlayerInfoList) { 18278cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen for (MediaPlayerInfo info : mMediaPlayerInfoList.values()) { 1828c721162e8198dbc1b4b3ec9d87beb083ba704307Marie Janssen MediaController controller = info.getMediaController(); 1829c721162e8198dbc1b4b3ec9d87beb083ba704307Marie Janssen if (controller != null) { 1830c721162e8198dbc1b4b3ec9d87beb083ba704307Marie Janssen controllers.add(controller.getWrappedInstance()); 18318cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 1832351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen } 1833351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen } 1834351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen return controllers; 1835351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen } 1836351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen 1837351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen /** Add (or update) a player to the media player list without a controller */ 18388cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen private boolean addMediaPlayerPackage(String packageName) { 1839351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen MediaPlayerInfo info = new MediaPlayerInfo(null, AvrcpConstants.PLAYER_TYPE_AUDIO, 1840b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen AvrcpConstants.PLAYER_SUBTYPE_NONE, PLAYSTATUS_STOPPED, 18410b6cad4a9f1ab18f6b3627ce7cf6316466cdb95aMarie Janssen getFeatureBitMask(packageName), packageName, getAppLabel(packageName)); 1842bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return addMediaPlayerInfo(info); 1843351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen } 1844351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen 1845351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen /** Add (or update) a player to the media player list given an active controller */ 18468cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen private boolean addMediaPlayerController(android.media.session.MediaController controller) { 1847351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen String packageName = controller.getPackageName(); 1848351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen MediaPlayerInfo info = new MediaPlayerInfo(MediaController.wrap(controller), 1849351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen AvrcpConstants.PLAYER_TYPE_AUDIO, AvrcpConstants.PLAYER_SUBTYPE_NONE, 1850b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen getBluetoothPlayState(controller.getPlaybackState()), 1851b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen getFeatureBitMask(packageName), controller.getPackageName(), 1852b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen getAppLabel(packageName)); 1853bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return addMediaPlayerInfo(info); 1854351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen } 1855351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen 1856bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen /** Add or update a player to the media player list given the MediaPlayerInfo object. 1857bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen * @return true if an item was updated, false if it was added instead 1858bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen */ 18598cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen private boolean addMediaPlayerInfo(MediaPlayerInfo info) { 18600b6cad4a9f1ab18f6b3627ce7cf6316466cdb95aMarie Janssen int updateId = -1; 1861bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen boolean updated = false; 186285ff6903243d244d4342f390bb40aa99097a9a7cMarie Janssen boolean currentRemoved = false; 1863c833de68eb3f5a82db6e83166e18504e83e5d035Ajay Panicker if (info.getPackageName().equals("com.android.server.telecom")) { 1864c833de68eb3f5a82db6e83166e18504e83e5d035Ajay Panicker Log.d(TAG, "Skip adding telecom to the media player info list"); 1865c833de68eb3f5a82db6e83166e18504e83e5d035Ajay Panicker return updated; 1866c833de68eb3f5a82db6e83166e18504e83e5d035Ajay Panicker } 18678cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen synchronized (mMediaPlayerInfoList) { 18688cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) { 186985ff6903243d244d4342f390bb40aa99097a9a7cMarie Janssen MediaPlayerInfo current = entry.getValue(); 187085ff6903243d244d4342f390bb40aa99097a9a7cMarie Janssen int id = entry.getKey(); 187185ff6903243d244d4342f390bb40aa99097a9a7cMarie Janssen if (info.getPackageName().equals(current.getPackageName())) { 187285ff6903243d244d4342f390bb40aa99097a9a7cMarie Janssen if (!current.equalView(info)) { 187385ff6903243d244d4342f390bb40aa99097a9a7cMarie Janssen // If we would present a different player, make it a new player 187485ff6903243d244d4342f390bb40aa99097a9a7cMarie Janssen // so that controllers know whether a player is browsable or not. 187585ff6903243d244d4342f390bb40aa99097a9a7cMarie Janssen mMediaPlayerInfoList.remove(id); 187685ff6903243d244d4342f390bb40aa99097a9a7cMarie Janssen currentRemoved = (mCurrAddrPlayerID == id); 187785ff6903243d244d4342f390bb40aa99097a9a7cMarie Janssen break; 187885ff6903243d244d4342f390bb40aa99097a9a7cMarie Janssen } 187985ff6903243d244d4342f390bb40aa99097a9a7cMarie Janssen updateId = id; 18808cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen updated = true; 18818cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen break; 18828cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 18830b6cad4a9f1ab18f6b3627ce7cf6316466cdb95aMarie Janssen } 18848cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (updateId == -1) { 18858cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen // New player 18868cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen mLastUsedPlayerID++; 18878cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen updateId = mLastUsedPlayerID; 188885ff6903243d244d4342f390bb40aa99097a9a7cMarie Janssen mAvailablePlayerViewChanged = true; 18898cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 18908cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen mMediaPlayerInfoList.put(updateId, info); 18910704743e3d020c050b7eba86f79656bb3dbd9c18Jack He } 18920704743e3d020c050b7eba86f79656bb3dbd9c18Jack He if (DEBUG) Log.d(TAG, (updated ? "update #" : "add #") + updateId + ":" + info.toString()); 18930704743e3d020c050b7eba86f79656bb3dbd9c18Jack He if (currentRemoved || updateId == mCurrAddrPlayerID) { 18940704743e3d020c050b7eba86f79656bb3dbd9c18Jack He updateCurrentController(updateId, mCurrBrowsePlayerID); 18950b6cad4a9f1ab18f6b3627ce7cf6316466cdb95aMarie Janssen } 1896bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return updated; 1897351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen } 1898351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen 1899351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen /** Remove all players related to |packageName| from the media player info list */ 19008cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen private MediaPlayerInfo removeMediaPlayerInfo(String packageName) { 19018cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen synchronized (mMediaPlayerInfoList) { 19028cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen int removeKey = -1; 19038cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) { 19048cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (entry.getValue().getPackageName().equals(packageName)) { 19058cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen removeKey = entry.getKey(); 19068cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen break; 19078cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 19088cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 19098cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (removeKey != -1) { 1910d89304c6be6e1c332008dcbeab08889881064454Marie Janssen if (DEBUG) 1911d89304c6be6e1c332008dcbeab08889881064454Marie Janssen Log.d(TAG, "remove #" + removeKey + ":" + mMediaPlayerInfoList.get(removeKey)); 191285ff6903243d244d4342f390bb40aa99097a9a7cMarie Janssen mAvailablePlayerViewChanged = true; 19138cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen return mMediaPlayerInfoList.remove(removeKey); 1914351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen } 19150b6cad4a9f1ab18f6b3627ce7cf6316466cdb95aMarie Janssen 19168cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen return null; 19178cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 1918351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen } 1919351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen 1920d89304c6be6e1c332008dcbeab08889881064454Marie Janssen /** Remove the controller referenced by |controller| from any player in the list */ 1921214b7f0b959e2fb3474d43f99136c83e4e11c843Marie Janssen private void removeMediaController(@Nullable android.media.session.MediaController controller) { 1922214b7f0b959e2fb3474d43f99136c83e4e11c843Marie Janssen if (controller == null) return; 1923d89304c6be6e1c332008dcbeab08889881064454Marie Janssen synchronized (mMediaPlayerInfoList) { 1924214b7f0b959e2fb3474d43f99136c83e4e11c843Marie Janssen for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) { 1925214b7f0b959e2fb3474d43f99136c83e4e11c843Marie Janssen MediaPlayerInfo info = entry.getValue(); 1926c721162e8198dbc1b4b3ec9d87beb083ba704307Marie Janssen MediaController c = info.getMediaController(); 1927214b7f0b959e2fb3474d43f99136c83e4e11c843Marie Janssen if (c != null && c.equals(controller)) { 1928214b7f0b959e2fb3474d43f99136c83e4e11c843Marie Janssen info.setMediaController(null); 1929214b7f0b959e2fb3474d43f99136c83e4e11c843Marie Janssen if (entry.getKey() == mCurrAddrPlayerID) { 1930214b7f0b959e2fb3474d43f99136c83e4e11c843Marie Janssen updateCurrentController(mCurrAddrPlayerID, mCurrBrowsePlayerID); 1931214b7f0b959e2fb3474d43f99136c83e4e11c843Marie Janssen } 1932214b7f0b959e2fb3474d43f99136c83e4e11c843Marie Janssen } 1933d89304c6be6e1c332008dcbeab08889881064454Marie Janssen } 1934d89304c6be6e1c332008dcbeab08889881064454Marie Janssen } 1935d89304c6be6e1c332008dcbeab08889881064454Marie Janssen } 1936d89304c6be6e1c332008dcbeab08889881064454Marie Janssen 1937e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* 1938e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * utility function to get the playback state of any media player through 1939e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * media controller APIs. 1940e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 1941b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen private byte getBluetoothPlayState(PlaybackState pbState) { 1942b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen if (pbState == null) { 1943b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen Log.w(TAG, "playState object null, sending STOPPED"); 1944b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen return PLAYSTATUS_STOPPED; 1945e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1946e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1947b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen switch (pbState.getState()) { 1948e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_PLAYING: 1949e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_PLAYING; 1950e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1951093a2e4d9aeaecb0d51d8b7c74b4466d368c31cfAjay Panicker case PlaybackState.STATE_BUFFERING: 1952e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_STOPPED: 1953e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_NONE: 1954e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_CONNECTING: 1955e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_STOPPED; 1956e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1957e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_PAUSED: 1958e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_PAUSED; 1959e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1960e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_FAST_FORWARDING: 1961e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_SKIPPING_TO_NEXT: 1962e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_SKIPPING_TO_QUEUE_ITEM: 1963e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_FWD_SEEK; 1964e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1965e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_REWINDING: 1966e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_SKIPPING_TO_PREVIOUS: 1967e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_REV_SEEK; 1968e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1969e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_ERROR: 1970e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah default: 1971e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_ERROR; 1972e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1973e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1974e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1975e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* 1976e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * utility function to get the feature bit mask of any media player through 1977e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * package name 1978e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 1979e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private short[] getFeatureBitMask(String packageName) { 1980e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1981e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ArrayList<Short> featureBitsList = new ArrayList<Short>(); 1982e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1983e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* adding default feature bits */ 1984e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_PLAY_BIT_NO); 1985e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_STOP_BIT_NO); 1986e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_PAUSE_BIT_NO); 1987e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_REWIND_BIT_NO); 1988e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_FAST_FWD_BIT_NO); 1989e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_FORWARD_BIT_NO); 1990e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_BACKWARD_BIT_NO); 1991e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_ADV_CTRL_BIT_NO); 1992e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1993e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Add/Modify browse player supported features. */ 1994e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (isBrowseSupported(packageName)) { 1995e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_BROWSE_BIT_NO); 1996e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_UID_UNIQUE_BIT_NO); 1997e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_NOW_PLAY_BIT_NO); 1998e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_GET_NUM_OF_ITEMS_BIT_NO); 1999e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2000e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2001e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // converting arraylist to array for response 2002e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah short[] featureBitsArray = new short[featureBitsList.size()]; 2003e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2004e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah for (int i = 0; i < featureBitsList.size(); i++) { 2005e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsArray[i] = featureBitsList.get(i).shortValue(); 2006e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2007e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2008e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return featureBitsArray; 2009e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2010e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2011e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /** 2012e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * Checks the Package name if it supports Browsing or not. 2013e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * 2014e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * @param packageName - name of the package to get the Id. 2015e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * @return true if it supports browsing, else false. 2016e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 20178cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen private boolean isBrowseSupported(String packageName) { 20188cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen synchronized (mBrowsePlayerInfoList) { 20198cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen /* check if Browsable Player's list contains this package name */ 20208cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen for (BrowsePlayerInfo info : mBrowsePlayerInfoList) { 20218cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (info.packageName.equals(packageName)) { 20228cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (DEBUG) Log.v(TAG, "isBrowseSupported for " + packageName + ": true"); 20238cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen return true; 20248cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 2025e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2026e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2027e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 20280b6cad4a9f1ab18f6b3627ce7cf6316466cdb95aMarie Janssen if (DEBUG) Log.v(TAG, "isBrowseSupported for " + packageName + ": false"); 20291b70ec148be773651d5ad00e3ce0d28b3a63306dAjay Panicker return false; 2030e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2031e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2032e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private String getPackageName(int id) { 20338cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen MediaPlayerInfo player = null; 20348cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen synchronized (mMediaPlayerInfoList) { 20358cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen player = mMediaPlayerInfoList.getOrDefault(id, null); 20368cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 2037e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2038351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen if (player == null) { 2039351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen Log.w(TAG, "No package name for player (" + id + " not valid)"); 2040351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen return ""; 2041e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2042351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen 2043351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen String packageName = player.getPackageName(); 2044351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen if (DEBUG) Log.v(TAG, "Player " + id + " package: " + packageName); 2045e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return packageName; 2046e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2047e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2048e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* from the global object, getting the current browsed player's package name */ 2049e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private String getCurrentBrowsedPlayer(byte[] bdaddr) { 2050e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String browsedPlayerPackage = ""; 2051e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2052e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Map<String, BrowsedMediaPlayer> connList = mAvrcpBrowseManager.getConnList(); 2053e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String bdaddrStr = new String(bdaddr); 2054e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if(connList.containsKey(bdaddrStr)){ 2055e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah browsedPlayerPackage = connList.get(bdaddrStr).getPackageName(); 2056e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2057e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "getCurrentBrowsedPlayerPackage: " + browsedPlayerPackage); 2058e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return browsedPlayerPackage; 2059e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2060e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2061351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen /* Returns the MediaPlayerInfo for the currently addressed media player */ 20628cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen private MediaPlayerInfo getAddressedPlayerInfo() { 20638cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen synchronized (mMediaPlayerInfoList) { 20648cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen return mMediaPlayerInfoList.getOrDefault(mCurrAddrPlayerID, null); 20658cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 2066e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2067e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2068e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* 2069e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * Utility function to get the Media player info from package name returns 2070e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * null if package name not found in media players list 2071e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 20728cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen private MediaPlayerInfo getMediaPlayerInfo(String packageName) { 20738cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen synchronized (mMediaPlayerInfoList) { 20748cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (mMediaPlayerInfoList.isEmpty()) { 20758cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (DEBUG) Log.v(TAG, "getMediaPlayerInfo: Media players list empty"); 20768cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen return null; 20778cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 2078351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen 20798cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen for (MediaPlayerInfo info : mMediaPlayerInfoList.values()) { 20808cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (packageName.equals(info.getPackageName())) { 20818cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (DEBUG) Log.v(TAG, "getMediaPlayerInfo: Found " + packageName); 20828cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen return info; 20838cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 2084e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 20858cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (DEBUG) Log.w(TAG, "getMediaPlayerInfo: " + packageName + " not found"); 20868cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen return null; 2087e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2088e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2089e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2090e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* prepare media list & return the media player list response object */ 20918cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen private MediaPlayerListRsp prepareMediaPlayerRspObj() { 20928cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen synchronized (mMediaPlayerInfoList) { 209382cfeee4ed9139eeb55e6823d9b721ba17db8b25Ajay Panicker // TODO(apanicke): This hack will go away as soon as a developer 209482cfeee4ed9139eeb55e6823d9b721ba17db8b25Ajay Panicker // option to enable or disable player selection is created. Right 209582cfeee4ed9139eeb55e6823d9b721ba17db8b25Ajay Panicker // now this is needed to fix BMW i3 carkits and any other carkits 209682cfeee4ed9139eeb55e6823d9b721ba17db8b25Ajay Panicker // that might try to connect to a player that isnt the current 209782cfeee4ed9139eeb55e6823d9b721ba17db8b25Ajay Panicker // player based on this list 209882cfeee4ed9139eeb55e6823d9b721ba17db8b25Ajay Panicker int numPlayers = 1; 20998cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen 21008cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen int[] playerIds = new int[numPlayers]; 21018cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen byte[] playerTypes = new byte[numPlayers]; 21028cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen int[] playerSubTypes = new int[numPlayers]; 21038cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen String[] displayableNameArray = new String[numPlayers]; 21048cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen byte[] playStatusValues = new byte[numPlayers]; 21058cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen short[] featureBitMaskValues = 21068cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen new short[numPlayers * AvrcpConstants.AVRC_FEATURE_MASK_SIZE]; 21078cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen 2108f73db9bf71badd648320cac0074169e009562d77Ajay Panicker // Reserve the first spot for the currently addressed player if 2109f73db9bf71badd648320cac0074169e009562d77Ajay Panicker // we have one 2110f73db9bf71badd648320cac0074169e009562d77Ajay Panicker int players = mMediaPlayerInfoList.containsKey(mCurrAddrPlayerID) ? 1 : 0; 21118cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) { 2112cc75e0ce509baa8e9cd27c38327c786b46b164acAjay Panicker int idx = players; 211382cfeee4ed9139eeb55e6823d9b721ba17db8b25Ajay Panicker if (entry.getKey() == mCurrAddrPlayerID) 211482cfeee4ed9139eeb55e6823d9b721ba17db8b25Ajay Panicker idx = 0; 211582cfeee4ed9139eeb55e6823d9b721ba17db8b25Ajay Panicker else 211682cfeee4ed9139eeb55e6823d9b721ba17db8b25Ajay Panicker continue; // TODO(apanicke): Remove, see above note 21178cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen MediaPlayerInfo info = entry.getValue(); 2118cc75e0ce509baa8e9cd27c38327c786b46b164acAjay Panicker playerIds[idx] = entry.getKey(); 2119cc75e0ce509baa8e9cd27c38327c786b46b164acAjay Panicker playerTypes[idx] = info.getMajorType(); 2120cc75e0ce509baa8e9cd27c38327c786b46b164acAjay Panicker playerSubTypes[idx] = info.getSubType(); 2121cc75e0ce509baa8e9cd27c38327c786b46b164acAjay Panicker displayableNameArray[idx] = info.getDisplayableName(); 2122cc75e0ce509baa8e9cd27c38327c786b46b164acAjay Panicker playStatusValues[idx] = info.getPlayStatus(); 21238cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen 21248cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen short[] featureBits = info.getFeatureBitMask(); 21258cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen for (int numBit = 0; numBit < featureBits.length; numBit++) { 21268cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen /* gives which octet this belongs to */ 21278cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen byte octet = (byte) (featureBits[numBit] / 8); 21288cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen /* gives the bit position within the octet */ 21298cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen byte bit = (byte) (featureBits[numBit] % 8); 2130cc75e0ce509baa8e9cd27c38327c786b46b164acAjay Panicker featureBitMaskValues[(idx * AvrcpConstants.AVRC_FEATURE_MASK_SIZE) + octet] |= 2131cc75e0ce509baa8e9cd27c38327c786b46b164acAjay Panicker (1 << bit); 21328cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 2133e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 21348cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen /* printLogs */ 21358cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (DEBUG) { 2136cc75e0ce509baa8e9cd27c38327c786b46b164acAjay Panicker Log.d(TAG, "Player " + playerIds[idx] + ": " + displayableNameArray[idx] 2137cc75e0ce509baa8e9cd27c38327c786b46b164acAjay Panicker + " type: " + playerTypes[idx] + ", " + playerSubTypes[idx] 2138cc75e0ce509baa8e9cd27c38327c786b46b164acAjay Panicker + " status: " + playStatusValues[idx]); 21398cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 2140e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2141cc75e0ce509baa8e9cd27c38327c786b46b164acAjay Panicker if (idx != 0) players++; 21428cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 2143e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 21448cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (DEBUG) Log.d(TAG, "prepareMediaPlayerRspObj: numPlayers = " + numPlayers); 2145e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 21468cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen return new MediaPlayerListRsp(AvrcpConstants.RSP_NO_ERROR, sUIDCounter, numPlayers, 21478cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen AvrcpConstants.BTRC_ITEM_PLAYER, playerIds, playerTypes, playerSubTypes, 21488cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen playStatusValues, featureBitMaskValues, displayableNameArray); 21498cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 2150e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2151e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2152e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* build media player list and send it to remote. */ 2153e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handleMediaPlayerListRsp(AvrcpCmd.FolderItemsCmd folderObj) { 21548cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen MediaPlayerListRsp rspObj = null; 21558cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen synchronized (mMediaPlayerInfoList) { 21568cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen int numPlayers = mMediaPlayerInfoList.size(); 21578cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (numPlayers == 0) { 21588cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen mediaPlayerListRspNative(folderObj.mAddress, AvrcpConstants.RSP_NO_AVBL_PLAY, 21598cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen (short) 0, (byte) 0, 0, null, null, null, null, null, null); 21608cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen return; 21618cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 21628cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (folderObj.mStartItem >= numPlayers) { 21638cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen Log.i(TAG, "handleMediaPlayerListRsp: start = " + folderObj.mStartItem 21648cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen + " > num of items = " + numPlayers); 21658cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen mediaPlayerListRspNative(folderObj.mAddress, AvrcpConstants.RSP_INV_RANGE, 21668cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen (short) 0, (byte) 0, 0, null, null, null, null, null, null); 21678cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen return; 21688cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 21698cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen rspObj = prepareMediaPlayerRspObj(); 2170e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 21718cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (DEBUG) Log.d(TAG, "handleMediaPlayerListRsp: sending " + rspObj.mNumItems + " players"); 2172351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen mediaPlayerListRspNative(folderObj.mAddress, rspObj.mStatus, rspObj.mUIDCounter, 2173351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen rspObj.itemType, rspObj.mNumItems, rspObj.mPlayerIds, rspObj.mPlayerTypes, 2174351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen rspObj.mPlayerSubTypes, rspObj.mPlayStatusValues, rspObj.mFeatureBitMaskValues, 2175351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen rspObj.mPlayerNameList); 2176e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2177e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2178e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* unregister to the old controller, update new IDs and register to the new controller */ 2179e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean updateCurrentController(int addrId, int browseId) { 2180e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah boolean registerRsp = true; 2181e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2182e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah updateNewIds(addrId, browseId); 2183e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2184351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen MediaController newController = null; 2185351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen MediaPlayerInfo info = getAddressedPlayerInfo(); 21860c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen if (info != null) newController = info.getMediaController(); 2187351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen 2188351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen if (DEBUG) 2189351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen Log.d(TAG, "updateCurrentController: " + mMediaController + " to " + newController); 219086582543b9cd70a617e84c049c03b466653e9641Marie Janssen synchronized (this) { 219186582543b9cd70a617e84c049c03b466653e9641Marie Janssen if (mMediaController == null || (!mMediaController.equals(newController))) { 2192214b7f0b959e2fb3474d43f99136c83e4e11c843Marie Janssen if (mMediaController != null) { 2193214b7f0b959e2fb3474d43f99136c83e4e11c843Marie Janssen mMediaController.unregisterCallback(mMediaControllerCb); 2194214b7f0b959e2fb3474d43f99136c83e4e11c843Marie Janssen } 2195214b7f0b959e2fb3474d43f99136c83e4e11c843Marie Janssen mMediaController = newController; 2196214b7f0b959e2fb3474d43f99136c83e4e11c843Marie Janssen if (mMediaController != null) { 2197214b7f0b959e2fb3474d43f99136c83e4e11c843Marie Janssen mMediaController.registerCallback(mMediaControllerCb, mHandler); 2198214b7f0b959e2fb3474d43f99136c83e4e11c843Marie Janssen } else { 2199214b7f0b959e2fb3474d43f99136c83e4e11c843Marie Janssen registerRsp = false; 2200214b7f0b959e2fb3474d43f99136c83e4e11c843Marie Janssen } 2201351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen } 2202e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 220367c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker updateCurrentMediaState(); 2204351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen return registerRsp; 2205e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2206e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2207e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Handle getfolderitems for scope = VFS, Search, NowPlayingList */ 2208e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handleGetFolderItemBrowseResponse(AvrcpCmd.FolderItemsCmd folderObj, byte[] bdaddr) { 2209e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int status = AvrcpConstants.RSP_NO_ERROR; 2210e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2211e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Browsed player is already set */ 2212bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen if (folderObj.mScope == AvrcpConstants.BTRC_SCOPE_FILE_SYSTEM) { 2213bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen if (mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr) == null) { 2214bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen Log.e(TAG, "handleGetFolderItemBrowseResponse: no browsed player set for " 2215bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen + Utils.getAddressStringFromByte(bdaddr)); 2216bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen getFolderItemsRspNative(bdaddr, AvrcpConstants.RSP_INTERNAL_ERR, (short) 0, 2217bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen (byte) 0x00, 0, null, null, null, null, null, null, null, null); 2218bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return; 2219bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 2220bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr).getFolderItemsVFS(folderObj); 2221bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return; 2222e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2223bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen if (folderObj.mScope == AvrcpConstants.BTRC_SCOPE_NOW_PLAYING) { 2224bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen mAddressedMediaPlayer.getFolderItemsNowPlaying(bdaddr, folderObj, mMediaController); 2225bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return; 2226e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2227e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2228bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen /* invalid scope */ 2229bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen Log.e(TAG, "handleGetFolderItemBrowseResponse: unknown scope " + folderObj.mScope); 2230bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen getFolderItemsRspNative(bdaddr, AvrcpConstants.RSP_INV_SCOPE, (short) 0, (byte) 0x00, 0, 2231bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen null, null, null, null, null, null, null, null); 2232e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2233e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2234e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* utility function to update the global values of current Addressed and browsed player */ 22358cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen private void updateNewIds(int addrId, int browseId) { 22360c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen if (DEBUG) 22370c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen Log.v(TAG, "updateNewIds: Addressed:" + mCurrAddrPlayerID + " to " + addrId 22380c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen + ", Browse:" + mCurrBrowsePlayerID + " to " + browseId); 2239e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mCurrAddrPlayerID = addrId; 2240e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mCurrBrowsePlayerID = browseId; 2241e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2242e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2243e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Getting the application's displayable name from package name */ 2244e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private String getAppLabel(String packageName) { 2245e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ApplicationInfo appInfo = null; 2246e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah try { 2247e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah appInfo = mPackageManager.getApplicationInfo(packageName, 0); 2248e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } catch (NameNotFoundException e) { 2249e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah e.printStackTrace(); 2250e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2251e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2252e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return (String) (appInfo != null ? mPackageManager 2253e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah .getApplicationLabel(appInfo) : "Unknown"); 2254e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2255e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2256e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handlePlayItemResponse(byte[] bdaddr, byte[] uid, byte scope) { 2257b3436e976055f684050be9afdadc73645316806aMarie Janssen if (scope == AvrcpConstants.BTRC_SCOPE_NOW_PLAYING) { 2258b3436e976055f684050be9afdadc73645316806aMarie Janssen mAddressedMediaPlayer.playItem(bdaddr, uid, mMediaController); 2259e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2260e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah else { 2261e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if(!isAddrPlayerSameAsBrowsed(bdaddr)) { 2262e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, "Remote requesting play item on uid which may not be recognized by" + 2263e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah "current addressed player"); 2264e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah playItemRspNative(bdaddr, AvrcpConstants.RSP_INV_ITEM); 2265e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2266e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2267e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr) != null) { 2268e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr).playItem(uid, scope); 2269e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2270e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "handlePlayItemResponse: Remote requested playitem " + 2271e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah "before setbrowsedplayer"); 2272e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah playItemRspNative(bdaddr, AvrcpConstants.RSP_INTERNAL_ERR); 2273e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2274e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2275e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2276e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2277e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handleGetItemAttr(AvrcpCmd.ItemAttrCmd itemAttr) { 227858e50a45b65eff899b284a3f51da781a3087bec4koh.changseok if (itemAttr.mUidCounter != sUIDCounter) { 227958e50a45b65eff899b284a3f51da781a3087bec4koh.changseok Log.e(TAG, "handleGetItemAttr: invaild uid counter."); 228058e50a45b65eff899b284a3f51da781a3087bec4koh.changseok getItemAttrRspNative( 228158e50a45b65eff899b284a3f51da781a3087bec4koh.changseok itemAttr.mAddress, AvrcpConstants.RSP_UID_CHANGED, (byte) 0, null, null); 228258e50a45b65eff899b284a3f51da781a3087bec4koh.changseok return; 228358e50a45b65eff899b284a3f51da781a3087bec4koh.changseok } 2284d89304c6be6e1c332008dcbeab08889881064454Marie Janssen if (itemAttr.mScope == AvrcpConstants.BTRC_SCOPE_NOW_PLAYING) { 2285d89304c6be6e1c332008dcbeab08889881064454Marie Janssen if (mCurrAddrPlayerID == NO_PLAYER_ID) { 2286d89304c6be6e1c332008dcbeab08889881064454Marie Janssen getItemAttrRspNative( 2287d89304c6be6e1c332008dcbeab08889881064454Marie Janssen itemAttr.mAddress, AvrcpConstants.RSP_NO_AVBL_PLAY, (byte) 0, null, null); 22880533d66ae0a334789c197cde425d3ad87a84dd7dMarie Janssen return; 2289d89304c6be6e1c332008dcbeab08889881064454Marie Janssen } 22900533d66ae0a334789c197cde425d3ad87a84dd7dMarie Janssen mAddressedMediaPlayer.getItemAttr(itemAttr.mAddress, itemAttr, mMediaController); 22910533d66ae0a334789c197cde425d3ad87a84dd7dMarie Janssen return; 22920533d66ae0a334789c197cde425d3ad87a84dd7dMarie Janssen } 22930533d66ae0a334789c197cde425d3ad87a84dd7dMarie Janssen // All other scopes use browsed player 22940533d66ae0a334789c197cde425d3ad87a84dd7dMarie Janssen if (mAvrcpBrowseManager.getBrowsedMediaPlayer(itemAttr.mAddress) != null) { 22950533d66ae0a334789c197cde425d3ad87a84dd7dMarie Janssen mAvrcpBrowseManager.getBrowsedMediaPlayer(itemAttr.mAddress).getItemAttr(itemAttr); 2296d89304c6be6e1c332008dcbeab08889881064454Marie Janssen } else { 22970533d66ae0a334789c197cde425d3ad87a84dd7dMarie Janssen Log.e(TAG, "Could not get attributes. mBrowsedMediaPlayer is null"); 22980533d66ae0a334789c197cde425d3ad87a84dd7dMarie Janssen getItemAttrRspNative( 22990533d66ae0a334789c197cde425d3ad87a84dd7dMarie Janssen itemAttr.mAddress, AvrcpConstants.RSP_INTERNAL_ERR, (byte) 0, null, null); 2300e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2301e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2302e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2303e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handleGetTotalNumOfItemsResponse(byte[] bdaddr, byte scope) { 2304e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // for scope as media player list 2305e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (scope == AvrcpConstants.BTRC_SCOPE_PLAYER_LIST) { 23068cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen int numPlayers = 0; 23078cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen synchronized (mMediaPlayerInfoList) { 23088cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen numPlayers = mMediaPlayerInfoList.size(); 23098cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 23108cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen if (DEBUG) Log.d(TAG, "handleGetTotalNumOfItemsResponse: " + numPlayers + " players."); 23118cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen getTotalNumOfItemsRspNative(bdaddr, AvrcpConstants.RSP_NO_ERROR, 0, numPlayers); 23128cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } else if (scope == AvrcpConstants.BTRC_SCOPE_NOW_PLAYING) { 2313b3436e976055f684050be9afdadc73645316806aMarie Janssen mAddressedMediaPlayer.getTotalNumOfItems(bdaddr, mMediaController); 2314e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2315e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // for FileSystem browsing scopes as VFS, Now Playing 2316e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr) != null) { 2317e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr).getTotalNumOfItems(scope); 2318e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2319e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "Could not get Total NumOfItems. mBrowsedMediaPlayer is null"); 2320e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah getTotalNumOfItemsRspNative(bdaddr, AvrcpConstants.RSP_INTERNAL_ERR, 0, 0); 2321e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2322e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2323e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2324e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2325e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2326e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* check if browsed player and addressed player are same */ 2327e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean isAddrPlayerSameAsBrowsed(byte[] bdaddr) { 2328e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String browsedPlayer = getCurrentBrowsedPlayer(bdaddr); 2329e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2330e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!isPackageNameValid(browsedPlayer)) { 2331e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, "Browsed player name empty"); 2332351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen return false; 2333e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2334e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 23350b6cad4a9f1ab18f6b3627ce7cf6316466cdb95aMarie Janssen MediaPlayerInfo info = getAddressedPlayerInfo(); 2336810d960162d74ba291a085ee2b11a37e7cbdace7Marie Janssen String packageName = (info == null) ? "<none>" : info.getPackageName(); 2337810d960162d74ba291a085ee2b11a37e7cbdace7Marie Janssen if (info == null || !packageName.equals(browsedPlayer)) { 2338810d960162d74ba291a085ee2b11a37e7cbdace7Marie Janssen if (DEBUG) Log.d(TAG, browsedPlayer + " is not addressed player " + packageName); 2339351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen return false; 2340351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen } 2341351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen return true; 2342e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2343e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2344e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* checks if package name is not null or empty */ 2345e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean isPackageNameValid(String browsedPackage) { 2346e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah boolean isValid = (browsedPackage != null && browsedPackage.length() > 0); 2347e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "isPackageNameValid: browsedPackage = " + browsedPackage + 2348e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah "isValid = " + isValid); 2349e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return isValid; 2350e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2351e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2352e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* checks if selected addressed player is already addressed */ 2353e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean isPlayerAlreadyAddressed(int selectedId) { 2354e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // checking if selected ID is same as the current addressed player id 2355e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah boolean isAddressed = (mCurrAddrPlayerID == selectedId); 2356e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "isPlayerAlreadyAddressed: isAddressed = " + isAddressed); 2357e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return isAddressed; 2358e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2359e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2360e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void dump(StringBuilder sb) { 2361e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah sb.append("AVRCP:\n"); 2362029b34a866c2f4ab132412ec2814fd500813c565Marie Janssen ProfileService.println(sb, "mMediaAttributes: " + mMediaAttributes.toRedactedString()); 2363e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mTransportControlFlags: " + mTransportControlFlags); 2364e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mCurrentPlayState: " + mCurrentPlayState); 2365e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mPlayStatusChangedNT: " + mPlayStatusChangedNT); 2366e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mTrackChangedNT: " + mTrackChangedNT); 2367e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mPlaybackIntervalMs: " + mPlaybackIntervalMs); 2368e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mPlayPosChangedNT: " + mPlayPosChangedNT); 2369e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mNextPosMs: " + mNextPosMs); 2370e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mPrevPosMs: " + mPrevPosMs); 2371e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mFeatures: " + mFeatures); 2372e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mRemoteVolume: " + mRemoteVolume); 2373e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mLastRemoteVolume: " + mLastRemoteVolume); 2374e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mLastDirection: " + mLastDirection); 2375e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mVolumeStep: " + mVolumeStep); 2376e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mAudioStreamMax: " + mAudioStreamMax); 2377e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mVolCmdAdjustInProgress: " + mVolCmdAdjustInProgress); 2378e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mVolCmdSetInProgress: " + mVolCmdSetInProgress); 2379e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mAbsVolRetryTimes: " + mAbsVolRetryTimes); 2380e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mVolumeMapping: " + mVolumeMapping.toString()); 238186582543b9cd70a617e84c049c03b466653e9641Marie Janssen synchronized (this) { 238286582543b9cd70a617e84c049c03b466653e9641Marie Janssen if (mMediaController != null) 238386582543b9cd70a617e84c049c03b466653e9641Marie Janssen ProfileService.println(sb, "mMediaController: " 238486582543b9cd70a617e84c049c03b466653e9641Marie Janssen + mMediaController.getWrappedInstance() + " pkg " 238586582543b9cd70a617e84c049c03b466653e9641Marie Janssen + mMediaController.getPackageName()); 238686582543b9cd70a617e84c049c03b466653e9641Marie Janssen } 23870c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen ProfileService.println(sb, ""); 23880c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen ProfileService.println(sb, "Media Players:"); 23898cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen synchronized (mMediaPlayerInfoList) { 23908cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) { 23918cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen int key = entry.getKey(); 23928cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen ProfileService.println(sb, ((mCurrAddrPlayerID == key) ? " *#" : " #") 23938cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen + entry.getKey() + ": " + entry.getValue()); 23948cd453176a070f0627d64fc2f3e34b8258d2e9a7Marie Janssen } 2395bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 2396bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen 2397303c1c67dbc142822bc37e7c5a89fba82faf2ac0Marie Janssen ProfileService.println(sb, ""); 2398303c1c67dbc142822bc37e7c5a89fba82faf2ac0Marie Janssen mAddressedMediaPlayer.dump(sb, mMediaController); 2399303c1c67dbc142822bc37e7c5a89fba82faf2ac0Marie Janssen 2400303c1c67dbc142822bc37e7c5a89fba82faf2ac0Marie Janssen ProfileService.println(sb, ""); 24010c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen ProfileService.println(sb, mPassthroughDispatched + " passthrough operations: "); 24020c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen if (mPassthroughDispatched > mPassthroughLogs.size()) 24030c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen ProfileService.println(sb, " (last " + mPassthroughLogs.size() + ")"); 24040c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen synchronized (mPassthroughLogs) { 24050c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen for (MediaKeyLog log : mPassthroughLogs) { 24060c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen ProfileService.println(sb, " " + log); 24070c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen } 2408bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 24090c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen synchronized (mPassthroughPending) { 24100c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen for (MediaKeyLog log : mPassthroughPending) { 24110c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen ProfileService.println(sb, " " + log); 24120c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen } 241332638175c01351b88bbbc5628825db2d62bd1a89Pavlin Radoslavov } 241432638175c01351b88bbbc5628825db2d62bd1a89Pavlin Radoslavov 241532638175c01351b88bbbc5628825db2d62bd1a89Pavlin Radoslavov // Print the blacklisted devices (for absolute volume control) 241632638175c01351b88bbbc5628825db2d62bd1a89Pavlin Radoslavov SharedPreferences pref = 241732638175c01351b88bbbc5628825db2d62bd1a89Pavlin Radoslavov mContext.getSharedPreferences(ABSOLUTE_VOLUME_BLACKLIST, Context.MODE_PRIVATE); 241832638175c01351b88bbbc5628825db2d62bd1a89Pavlin Radoslavov Map<String, ?> allKeys = pref.getAll(); 241932638175c01351b88bbbc5628825db2d62bd1a89Pavlin Radoslavov ProfileService.println(sb, ""); 242032638175c01351b88bbbc5628825db2d62bd1a89Pavlin Radoslavov ProfileService.println(sb, "Runtime Blacklisted Devices (absolute volume):"); 242132638175c01351b88bbbc5628825db2d62bd1a89Pavlin Radoslavov if (allKeys.isEmpty()) { 242232638175c01351b88bbbc5628825db2d62bd1a89Pavlin Radoslavov ProfileService.println(sb, " None"); 242332638175c01351b88bbbc5628825db2d62bd1a89Pavlin Radoslavov } else { 242432638175c01351b88bbbc5628825db2d62bd1a89Pavlin Radoslavov for (String key : allKeys.keySet()) { 242532638175c01351b88bbbc5628825db2d62bd1a89Pavlin Radoslavov ProfileService.println(sb, " " + key); 242632638175c01351b88bbbc5628825db2d62bd1a89Pavlin Radoslavov } 24270b6cad4a9f1ab18f6b3627ce7cf6316466cdb95aMarie Janssen } 2428e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2429e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2430e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public class AvrcpBrowseManager { 2431e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Map<String, BrowsedMediaPlayer> connList = new HashMap<String, BrowsedMediaPlayer>(); 2432e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private AvrcpMediaRspInterface mMediaInterface; 2433e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private Context mContext; 2434e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2435e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public AvrcpBrowseManager(Context context, AvrcpMediaRspInterface mediaInterface) { 2436e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mContext = context; 2437e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mMediaInterface = mediaInterface; 2438e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2439e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2440e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void cleanup() { 2441e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Iterator entries = connList.entrySet().iterator(); 2442e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah while (entries.hasNext()) { 2443e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Map.Entry entry = (Map.Entry) entries.next(); 2444e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah BrowsedMediaPlayer browsedMediaPlayer = (BrowsedMediaPlayer) entry.getValue(); 2445e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (browsedMediaPlayer != null) { 2446e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah browsedMediaPlayer.cleanup(); 2447e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2448e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2449e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // clean up the map 2450e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah connList.clear(); 2451e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2452e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2453e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // get the a free media player interface based on the passed bd address 2454e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // if the no items is found for the passed media player then it assignes a 2455e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // available media player interface 2456e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public BrowsedMediaPlayer getBrowsedMediaPlayer(byte[] bdaddr) { 2457e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah BrowsedMediaPlayer mediaPlayer; 2458e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String bdaddrStr = new String(bdaddr); 2459bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen if (connList.containsKey(bdaddrStr)) { 2460e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mediaPlayer = connList.get(bdaddrStr); 2461e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2462e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mediaPlayer = new BrowsedMediaPlayer(bdaddr, mContext, mMediaInterface); 2463e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah connList.put(bdaddrStr, mediaPlayer); 2464e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2465e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return mediaPlayer; 2466e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2467e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2468e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // clears the details pertaining to passed bdaddres 2469e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public boolean clearBrowsedMediaPlayer(byte[] bdaddr) { 2470e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String bdaddrStr = new String(bdaddr); 2471bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen if (connList.containsKey(bdaddrStr)) { 2472e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah connList.remove(bdaddrStr); 2473e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return true; 2474e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2475e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return false; 2476e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2477e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2478e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public Map<String, BrowsedMediaPlayer> getConnList() { 2479e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return connList; 2480e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2481e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2482e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Helper function to convert colon separated bdaddr to byte string */ 2483e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private byte[] hexStringToByteArray(String s) { 2484e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int len = s.length(); 2485e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] data = new byte[len / 2]; 2486e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah for (int i = 0; i < len; i += 2) { 2487e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) 2488e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + Character.digit(s.charAt(i+1), 16)); 2489e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2490e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return data; 2491e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2492e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2493e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2494e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* 2495e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * private class which handles responses from AvrcpMediaManager. Maps responses to native 2496e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * responses. This class implements the AvrcpMediaRspInterface interface. 2497e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 2498e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private class AvrcpMediaRsp implements AvrcpMediaRspInterface { 2499e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final String TAG = "AvrcpMediaRsp"; 2500e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2501e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void setAddrPlayerRsp(byte[] address, int rspStatus) { 2502e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!setAddressedPlayerRspNative(address, rspStatus)) { 2503e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "setAddrPlayerRsp failed!"); 2504e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2505e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2506e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2507e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void setBrowsedPlayerRsp(byte[] address, int rspStatus, byte depth, int numItems, 2508e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String[] textArray) { 2509e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!setBrowsedPlayerRspNative(address, rspStatus, depth, numItems, textArray)) { 2510e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "setBrowsedPlayerRsp failed!"); 2511e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2512e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2513e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2514e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void mediaPlayerListRsp(byte[] address, int rspStatus, MediaPlayerListRsp rspObj) { 2515e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (rspObj != null && rspStatus == AvrcpConstants.RSP_NO_ERROR) { 2516e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!mediaPlayerListRspNative(address, rspStatus, sUIDCounter, rspObj.itemType, 2517351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen rspObj.mNumItems, rspObj.mPlayerIds, rspObj.mPlayerTypes, 2518351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen rspObj.mPlayerSubTypes, rspObj.mPlayStatusValues, 2519351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen rspObj.mFeatureBitMaskValues, rspObj.mPlayerNameList)) 2520351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen Log.e(TAG, "mediaPlayerListRsp failed!"); 2521e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2522e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "mediaPlayerListRsp: rspObj is null"); 2523351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen if (!mediaPlayerListRspNative(address, rspStatus, sUIDCounter, (byte) 0x00, 0, null, 2524351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen null, null, null, null, null)) 2525351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen Log.e(TAG, "mediaPlayerListRsp failed!"); 2526e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2527e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2528e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2529e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void folderItemsRsp(byte[] address, int rspStatus, FolderItemsRsp rspObj) { 2530e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (rspObj != null && rspStatus == AvrcpConstants.RSP_NO_ERROR) { 2531e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!getFolderItemsRspNative(address, rspStatus, sUIDCounter, rspObj.mScope, 2532e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah rspObj.mNumItems, rspObj.mFolderTypes, rspObj.mPlayable, rspObj.mItemTypes, 2533e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah rspObj.mItemUid, rspObj.mDisplayNames, rspObj.mAttributesNum, 2534e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah rspObj.mAttrIds, rspObj.mAttrValues)) 2535e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getFolderItemsRspNative failed!"); 2536e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2537e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "folderItemsRsp: rspObj is null or rspStatus is error:" + rspStatus); 2538e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!getFolderItemsRspNative(address, rspStatus, sUIDCounter, (byte) 0x00, 0, 2539e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah null, null, null, null, null, null, null, null)) 2540e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getFolderItemsRspNative failed!"); 2541e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2542e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2543e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2544e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2545e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void changePathRsp(byte[] address, int rspStatus, int numItems) { 2546e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!changePathRspNative(address, rspStatus, numItems)) 2547e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "changePathRspNative failed!"); 2548e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2549e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2550e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void getItemAttrRsp(byte[] address, int rspStatus, ItemAttrRsp rspObj) { 2551e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (rspObj != null && rspStatus == AvrcpConstants.RSP_NO_ERROR) { 2552e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!getItemAttrRspNative(address, rspStatus, rspObj.mNumAttr, 2553e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah rspObj.mAttributesIds, rspObj.mAttributesArray)) 2554e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getItemAttrRspNative failed!"); 2555e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2556e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getItemAttrRsp: rspObj is null or rspStatus is error:" + rspStatus); 2557e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!getItemAttrRspNative(address, rspStatus, (byte) 0x00, null, null)) 2558e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getItemAttrRspNative failed!"); 2559e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2560e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2561e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2562e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void playItemRsp(byte[] address, int rspStatus) { 2563e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!playItemRspNative(address, rspStatus)) { 2564e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "playItemRspNative failed!"); 2565e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2566e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2567e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2568e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void getTotalNumOfItemsRsp(byte[] address, int rspStatus, int uidCounter, 2569e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int numItems) { 2570e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!getTotalNumOfItemsRspNative(address, rspStatus, sUIDCounter, numItems)) { 2571e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getTotalNumOfItemsRspNative failed!"); 2572e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2573e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2574e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2575bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen public void addrPlayerChangedRsp(int type, int playerId, int uidCounter) { 2576e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspAddrPlayerChangedNative(type, playerId, sUIDCounter)) { 2577e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "registerNotificationRspAddrPlayerChangedNative failed!"); 2578e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2579e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2580e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2581e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void avalPlayerChangedRsp(byte[] address, int type) { 2582e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspAvalPlayerChangedNative(type)) { 2583e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "registerNotificationRspAvalPlayerChangedNative failed!"); 2584e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2585e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2586e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2587d65422f9b47bff59b12162fc51032eb633f0722fAjay Panicker public void uidsChangedRsp(int type) { 2588e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspUIDsChangedNative(type, sUIDCounter)) { 2589e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "registerNotificationRspUIDsChangedNative failed!"); 2590e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2591e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2592e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2593e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void nowPlayingChangedRsp(int type) { 25943616b7ce7be6abaca5eef876e055155f9e8a3b1fAjay Panicker if (mNowPlayingListChangedNT != AvrcpConstants.NOTIFICATION_TYPE_INTERIM) { 25953616b7ce7be6abaca5eef876e055155f9e8a3b1fAjay Panicker if (DEBUG) Log.d(TAG, "NowPlayingListChanged: Not registered or requesting."); 25963616b7ce7be6abaca5eef876e055155f9e8a3b1fAjay Panicker return; 25973616b7ce7be6abaca5eef876e055155f9e8a3b1fAjay Panicker } 25983616b7ce7be6abaca5eef876e055155f9e8a3b1fAjay Panicker 2599e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspNowPlayingChangedNative(type)) { 2600e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "registerNotificationRspNowPlayingChangedNative failed!"); 2601e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 26023616b7ce7be6abaca5eef876e055155f9e8a3b1fAjay Panicker mNowPlayingListChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 2603e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2604e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2605e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void trackChangedRsp(int type, byte[] uid) { 2606e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspTrackChangeNative(type, uid)) { 2607e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "registerNotificationRspTrackChangeNative failed!"); 2608e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2609e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2610e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2611e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2612e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* getters for some private variables */ 2613e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public AvrcpBrowseManager getAvrcpBrowseManager() { 2614e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return mAvrcpBrowseManager; 2615e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2616e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2617bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen /* PASSTHROUGH COMMAND MANAGEMENT */ 2618bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen 2619bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen void handlePassthroughCmd(int op, int state) { 2620bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen int code = avrcpPassthroughToKeyCode(op); 2621bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen if (code == KeyEvent.KEYCODE_UNKNOWN) { 2622bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen Log.w(TAG, "Ignoring passthrough of unknown key " + op + " state " + state); 2623bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return; 2624bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 2625bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen int action = KeyEvent.ACTION_DOWN; 2626bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen if (state == AvrcpConstants.KEY_STATE_RELEASE) action = KeyEvent.ACTION_UP; 2627bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen KeyEvent event = new KeyEvent(action, code); 2628bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen if (!KeyEvent.isMediaKey(code)) { 2629bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen Log.w(TAG, "Passthrough non-media key " + op + " (code " + code + ") state " + state); 2630bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 263167c982aed4e67772e155f934c2055c72b83f1f22Ajay Panicker 2632bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen mMediaSessionManager.dispatchMediaKeyEvent(event); 2633bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen addKeyPending(event); 2634bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 2635bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen 2636bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen private int avrcpPassthroughToKeyCode(int operation) { 2637bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen switch (operation) { 2638bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_UP: 2639bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_DPAD_UP; 2640bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_DOWN: 2641bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_DPAD_DOWN; 2642bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_LEFT: 2643bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_DPAD_LEFT; 2644bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_RIGHT: 2645bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_DPAD_RIGHT; 2646bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_RIGHT_UP: 2647bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_DPAD_UP_RIGHT; 2648bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_RIGHT_DOWN: 2649bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_DPAD_DOWN_RIGHT; 2650bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_LEFT_UP: 2651bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_DPAD_UP_LEFT; 2652bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_LEFT_DOWN: 2653bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_DPAD_DOWN_LEFT; 2654bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_0: 2655bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_NUMPAD_0; 2656bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_1: 2657bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_NUMPAD_1; 2658bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_2: 2659bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_NUMPAD_2; 2660bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_3: 2661bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_NUMPAD_3; 2662bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_4: 2663bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_NUMPAD_4; 2664bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_5: 2665bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_NUMPAD_5; 2666bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_6: 2667bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_NUMPAD_6; 2668bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_7: 2669bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_NUMPAD_7; 2670bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_8: 2671bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_NUMPAD_8; 2672bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_9: 2673bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_NUMPAD_9; 2674bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_DOT: 2675bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_NUMPAD_DOT; 2676bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_ENTER: 2677bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_NUMPAD_ENTER; 2678bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_CLEAR: 2679bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_CLEAR; 2680bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_CHAN_UP: 2681bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_CHANNEL_UP; 2682bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_CHAN_DOWN: 2683bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_CHANNEL_DOWN; 2684bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_PREV_CHAN: 2685bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_LAST_CHANNEL; 2686bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_INPUT_SEL: 2687bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_TV_INPUT; 2688bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_DISP_INFO: 2689bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_INFO; 2690bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_HELP: 2691bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_HELP; 2692bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_PAGE_UP: 2693bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_PAGE_UP; 2694bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_PAGE_DOWN: 2695bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_PAGE_DOWN; 2696bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_POWER: 2697bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_POWER; 2698bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_VOL_UP: 2699bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_VOLUME_UP; 2700bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_VOL_DOWN: 2701bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_VOLUME_DOWN; 2702bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_MUTE: 2703bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_MUTE; 2704e85822729c985ca537d5f9943ed12f37976bfbafAndre Eisenbach case BluetoothAvrcp.PASSTHROUGH_ID_PLAY: 2705e85822729c985ca537d5f9943ed12f37976bfbafAndre Eisenbach return KeyEvent.KEYCODE_MEDIA_PLAY; 2706bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_STOP: 2707bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_MEDIA_STOP; 2708e85822729c985ca537d5f9943ed12f37976bfbafAndre Eisenbach case BluetoothAvrcp.PASSTHROUGH_ID_PAUSE: 2709e85822729c985ca537d5f9943ed12f37976bfbafAndre Eisenbach return KeyEvent.KEYCODE_MEDIA_PAUSE; 2710bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_RECORD: 2711bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_MEDIA_RECORD; 2712bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_REWIND: 2713bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_MEDIA_REWIND; 2714bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_FAST_FOR: 2715bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_MEDIA_FAST_FORWARD; 2716bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_EJECT: 2717bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_MEDIA_EJECT; 2718bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_FORWARD: 2719bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_MEDIA_NEXT; 2720bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_BACKWARD: 2721bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_MEDIA_PREVIOUS; 2722bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_F1: 2723bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_F1; 2724bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_F2: 2725bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_F2; 2726bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_F3: 2727bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_F3; 2728bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_F4: 2729bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_F4; 2730bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_F5: 2731bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_F5; 2732bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen // Fallthrough for all unknown key mappings 2733bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_SELECT: 2734bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_ROOT_MENU: 2735bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_SETUP_MENU: 2736bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_CONT_MENU: 2737bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_FAV_MENU: 2738bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_EXIT: 2739bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_SOUND_SEL: 2740bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_ANGLE: 2741bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_SUBPICT: 2742bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_VENDOR: 2743bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen default: 2744bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return KeyEvent.KEYCODE_UNKNOWN; 2745bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 2746bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 2747bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen 2748bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen private void addKeyPending(KeyEvent event) { 27490c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen mPassthroughPending.add(new MediaKeyLog(System.currentTimeMillis(), event)); 2750bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 2751bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen 2752bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen private void recordKeyDispatched(KeyEvent event, String packageName) { 2753bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen long time = System.currentTimeMillis(); 2754bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen Log.v(TAG, "recordKeyDispatched: " + event + " dispatched to " + packageName); 27550c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen setAddressedMediaSessionPackage(packageName); 2756bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen synchronized (mPassthroughPending) { 2757bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen Iterator<MediaKeyLog> pending = mPassthroughPending.iterator(); 2758bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen while (pending.hasNext()) { 2759bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen MediaKeyLog log = pending.next(); 2760bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen if (log.addDispatch(time, event, packageName)) { 2761bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen mPassthroughDispatched++; 2762bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen mPassthroughLogs.add(log); 2763bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen pending.remove(); 2764bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen return; 2765bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 2766bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 27670c3b4f4f77175b72061b356a54e2febaf1f19a6aMarie Janssen Log.w(TAG, "recordKeyDispatch: can't find matching log!"); 2768bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 2769bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 2770bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen 2771bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen private final MediaSessionManager.Callback mButtonDispatchCallback = 2772bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen new MediaSessionManager.Callback() { 2773bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen @Override 2774bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen public void onMediaKeyEventDispatched(KeyEvent event, MediaSession.Token token) { 2775bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen // Get the package name 2776bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen android.media.session.MediaController controller = 2777bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen new android.media.session.MediaController(mContext, token); 2778bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen String targetPackage = controller.getPackageName(); 2779bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen recordKeyDispatched(event, targetPackage); 2780bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 2781bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen 2782bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen @Override 2783bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen public void onMediaKeyEventDispatched(KeyEvent event, ComponentName receiver) { 2784bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen recordKeyDispatched(event, receiver.getPackageName()); 2785bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 2786bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen 2787bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen @Override 2788bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen public void onAddressedPlayerChanged(MediaSession.Token token) { 2789bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen setActiveMediaSession(token); 2790bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 2791bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen 2792bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen @Override 2793bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen public void onAddressedPlayerChanged(ComponentName receiver) { 27941107f9516bf8866640247044deb9f780bb89e55cMarie Janssen if (receiver == null) { 27951107f9516bf8866640247044deb9f780bb89e55cMarie Janssen // No active sessions, and no session to revive, give up. 27961107f9516bf8866640247044deb9f780bb89e55cMarie Janssen setAddressedMediaSessionPackage(null); 27971107f9516bf8866640247044deb9f780bb89e55cMarie Janssen return; 27981107f9516bf8866640247044deb9f780bb89e55cMarie Janssen } 27991107f9516bf8866640247044deb9f780bb89e55cMarie Janssen // We can still get a passthrough which will revive this player. 2800bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen setAddressedMediaSessionPackage(receiver.getPackageName()); 2801bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen } 2802bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen }; 2803bdcf510515b5b251b0b88ba3c05937661ca5da3fMarie Janssen 2804e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // Do not modify without updating the HAL bt_rc.h files. 2805e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2806e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // match up with btrc_play_status_t enum of bt_rc.h 2807b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen final static byte PLAYSTATUS_STOPPED = 0; 2808b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen final static byte PLAYSTATUS_PLAYING = 1; 2809b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen final static byte PLAYSTATUS_PAUSED = 2; 2810b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen final static byte PLAYSTATUS_FWD_SEEK = 3; 2811b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen final static byte PLAYSTATUS_REV_SEEK = 4; 2812b631457c5ccc472a499334f65b88848bbaf3c605Marie Janssen final static byte PLAYSTATUS_ERROR = (byte) 255; 2813e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2814e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // match up with btrc_media_attr_t enum of bt_rc.h 2815e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_TITLE = 1; 2816e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_ARTIST = 2; 2817e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_ALBUM = 3; 2818e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_TRACK_NUM = 4; 2819e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_NUM_TRACKS = 5; 2820e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_GENRE = 6; 2821e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_PLAYING_TIME = 7; 2822e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2823e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // match up with btrc_event_id_t enum of bt_rc.h 2824e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_PLAY_STATUS_CHANGED = 1; 2825e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_TRACK_CHANGED = 2; 2826e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_TRACK_REACHED_END = 3; 2827e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_TRACK_REACHED_START = 4; 2828e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_PLAY_POS_CHANGED = 5; 2829e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_BATT_STATUS_CHANGED = 6; 2830e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_SYSTEM_STATUS_CHANGED = 7; 2831e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_APP_SETTINGS_CHANGED = 8; 2832e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVENT_NOW_PLAYING_CONTENT_CHANGED = 9; 2833e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_AVBL_PLAYERS_CHANGED = 0xa; 2834e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_ADDR_PLAYER_CHANGED = 0xb; 2835e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVENT_UIDS_CHANGED = 0x0c; 2836c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 2837c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native static void classInitNative(); 2838c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native void initNative(); 2839c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native void cleanupNative(); 2840e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean getPlayStatusRspNative(byte[] address, int playStatus, int songLen, 2841e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int songPos); 2842e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean getElementAttrRspNative(byte[] address, byte numAttr, int[] attrIds, 2843e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String[] textArray); 2844c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native boolean registerNotificationRspPlayStatusNative(int type, int playStatus); 2845c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native boolean registerNotificationRspTrackChangeNative(int type, byte[] track); 2846aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private native boolean registerNotificationRspPlayPosNative(int type, int playPos); 284717675906064bb72fdcca75baa56cdf8bb8968d01John Du private native boolean setVolumeNative(int volume); 28485c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta private native boolean sendPassThroughCommandNative(int keyCode, int keyState); 2849e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean setAddressedPlayerRspNative(byte[] address, int rspStatus); 2850e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean setBrowsedPlayerRspNative(byte[] address, int rspStatus, byte depth, 2851e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int numItems, String[] textArray); 2852e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean mediaPlayerListRspNative(byte[] address, int rsStatus, int uidCounter, 2853351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen byte item_type, int numItems, int[] playerIds, byte[] playerTypes, int[] playerSubTypes, 2854351ffc02e8c395d0eabe108e5b4909e7f41ffae6Marie Janssen byte[] playStatusValues, short[] featureBitMaskValues, String[] textArray); 2855e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean getFolderItemsRspNative(byte[] address, int rspStatus, short uidCounter, 2856e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte scope, int numItems, byte[] folderTypes, byte[] playable, byte[] itemTypes, 2857e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] itemUidArray, String[] textArray, int[] AttributesNum, int[] AttributesIds, 2858e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String[] attributesArray); 2859e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean changePathRspNative(byte[] address, int rspStatus, int numItems); 2860e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean getItemAttrRspNative(byte[] address, int rspStatus, byte numAttr, 2861e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int[] attrIds, String[] textArray); 2862e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean playItemRspNative(byte[] address, int rspStatus); 2863e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean getTotalNumOfItemsRspNative(byte[] address, int rspStatus, 2864e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int uidCounter, int numItems); 2865e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean searchRspNative(byte[] address, int rspStatus, int uidCounter, 2866e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int numItems); 2867e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean addToNowPlayingRspNative(byte[] address, int rspStatus); 2868e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean registerNotificationRspAddrPlayerChangedNative(int type, 2869e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int playerId, int uidCounter); 2870e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean registerNotificationRspAvalPlayerChangedNative(int type); 2871e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean registerNotificationRspUIDsChangedNative(int type, int uidCounter); 2872e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean registerNotificationRspNowPlayingChangedNative(int type); 28735c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta 2874c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 2875