Avrcp.java revision 8ac88214fdbf5e5197033b89ba82a6bf728706a4
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 1929174eb9ad6e255d7ec216ab9a2ce8d20e2fe13cMarie Janssenimport android.annotation.NonNull; 2078d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie 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; 363b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssenimport android.media.MediaDescription; 370e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssenimport android.media.MediaMetadata; 383843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssenimport android.media.browse.MediaBrowser; 39e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.media.session.MediaSession; 40e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.media.session.MediaSession.QueueItem; 410e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssenimport android.media.session.MediaSessionManager; 420e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssenimport android.media.session.PlaybackState; 43e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.os.Bundle; 44c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.Handler; 45c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.HandlerThread; 46c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.Looper; 47c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.Message; 48aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xuimport android.os.SystemClock; 490427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panickerimport android.os.UserManager; 50c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.util.Log; 51881675b362bde18acbbcf69c513175addca4a8baZhenye Zhuimport android.view.KeyEvent; 526e29e12add362546784126119f26f04fc760f021RoboErik 53c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport com.android.bluetooth.btservice.ProfileService; 54e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport com.android.bluetooth.R; 55aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xuimport com.android.bluetooth.Utils; 566e29e12add362546784126119f26f04fc760f021RoboErik 57c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport java.util.ArrayList; 5878d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssenimport java.util.Collections; 5911798b011c962b602217b479130d413f3b30f19aLiejun Taoimport java.util.HashMap; 60e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport java.util.Iterator; 61c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport java.util.List; 62e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport java.util.Map; 63eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssenimport java.util.SortedMap; 64eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssenimport java.util.TreeMap; 65e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 66e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah/****************************************************************************** 67e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * support Bluetooth AVRCP profile. support metadata, play status, event 68e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * notifications, address player selection and browse feature implementation. 69e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ******************************************************************************/ 70eb7b90f5b93db1230a5b64caa3d8d05a642e33a6Marie Janssen 71066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodpublic final class Avrcp { 721b70ec148be773651d5ad00e3ce0d28b3a63306dAjay Panicker private static final boolean DEBUG = true; 73c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private static final String TAG = "Avrcp"; 7411798b011c962b602217b479130d413f3b30f19aLiejun Tao private static final String ABSOLUTE_VOLUME_BLACKLIST = "absolute_volume_blacklist"; 75c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 76c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private Context mContext; 77c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private final AudioManager mAudioManager; 78c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private AvrcpMessageHandler mHandler; 790e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen private MediaSessionManager mMediaSessionManager; 8029174eb9ad6e255d7ec216ab9a2ce8d20e2fe13cMarie Janssen private @Nullable MediaController mMediaController; 810e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen private MediaControllerListener mMediaControllerCb; 823b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private MediaAttributes mMediaAttributes; 83e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private PackageManager mPackageManager; 84c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private int mTransportControlFlags; 8529174eb9ad6e255d7ec216ab9a2ce8d20e2fe13cMarie Janssen private @NonNull PlaybackState mCurrentPlayState; 860a429916782c20980e7f0893c503c633b8341f88Marie Janssen private int mA2dpState; 87c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private int mPlayStatusChangedNT; 88c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private int mTrackChangedNT; 89f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen private int mPlayPosChangedNT; 90aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mPlaybackIntervalMs; 91fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen private long mLastReportedPosition; 92aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mNextPosMs; 93aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mPrevPosMs; 9417675906064bb72fdcca75baa56cdf8bb8968d01John Du private int mFeatures; 9511798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mRemoteVolume; 9611798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mLastRemoteVolume; 9711798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mInitialRemoteVolume; 98be66a1bf5584a2a7985666ab20c5e9b54053e17dMarie Janssen private BrowsablePlayerListBuilder mBrowsableListBuilder; 9911798b011c962b602217b479130d413f3b30f19aLiejun Tao 10011798b011c962b602217b479130d413f3b30f19aLiejun Tao /* Local volume in audio index 0-15 */ 10111798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mLocalVolume; 10211798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mLastLocalVolume; 10311798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mAbsVolThreshold; 10411798b011c962b602217b479130d413f3b30f19aLiejun Tao 10511798b011c962b602217b479130d413f3b30f19aLiejun Tao private String mAddress; 10611798b011c962b602217b479130d413f3b30f19aLiejun Tao private HashMap<Integer, Integer> mVolumeMapping; 10711798b011c962b602217b479130d413f3b30f19aLiejun Tao 10817675906064bb72fdcca75baa56cdf8bb8968d01John Du private int mLastDirection; 1092e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie private final int mVolumeStep; 1102e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie private final int mAudioStreamMax; 11111798b011c962b602217b479130d413f3b30f19aLiejun Tao private boolean mVolCmdAdjustInProgress; 11211798b011c962b602217b479130d413f3b30f19aLiejun Tao private boolean mVolCmdSetInProgress; 11317675906064bb72fdcca75baa56cdf8bb8968d01John Du private int mAbsVolRetryTimes; 114eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 115384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen private static final int NO_PLAYER_ID = 0; 116384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen 117e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private int mCurrAddrPlayerID; 118e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private int mCurrBrowsePlayerID; 119eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen private int mLastUsedPlayerID; 120e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private AvrcpMediaRsp mAvrcpMediaRsp; 121e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 122e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* UID counter to be shared across different files. */ 123e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah static short sUIDCounter; 124ace834feb02adabd61f628c4471147aea02d939cJohn Du 12517675906064bb72fdcca75baa56cdf8bb8968d01John Du /* BTRC features */ 12617675906064bb72fdcca75baa56cdf8bb8968d01John Du public static final int BTRC_FEAT_METADATA = 0x01; 12717675906064bb72fdcca75baa56cdf8bb8968d01John Du public static final int BTRC_FEAT_ABSOLUTE_VOLUME = 0x02; 12817675906064bb72fdcca75baa56cdf8bb8968d01John Du public static final int BTRC_FEAT_BROWSE = 0x04; 12917675906064bb72fdcca75baa56cdf8bb8968d01John Du 13017675906064bb72fdcca75baa56cdf8bb8968d01John Du /* AVRC response codes, from avrc_defs */ 13117675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_NOT_IMPL = 8; 13217675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_ACCEPT = 9; 13317675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_REJ = 10; 13417675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_IN_TRANS = 11; 13517675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_IMPL_STBL = 12; 13617675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_CHANGED = 13; 13717675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_INTERIM = 15; 13817675906064bb72fdcca75baa56cdf8bb8968d01John Du 139e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* AVRC request commands from Native */ 140e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_GET_RC_FEATURES = 1; 141e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_GET_PLAY_STATUS = 2; 142e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_GET_ELEM_ATTRS = 3; 143e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_REGISTER_NOTIFICATION = 4; 144e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_VOLUME_CHANGE = 5; 145e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_GET_FOLDER_ITEMS = 6; 146e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_SET_ADDR_PLAYER = 7; 147e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_SET_BR_PLAYER = 8; 148e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_CHANGE_PATH = 9; 149e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_PLAY_ITEM = 10; 150e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_GET_ITEM_ATTR = 11; 151e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_GET_TOTAL_NUM_OF_ITEMS = 12; 152e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_PASS_THROUGH = 13; 153e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 154e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* other AVRC messages */ 155e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_PLAY_INTERVAL_TIMEOUT = 14; 156e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_ADJUST_VOLUME = 15; 157e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_SET_ABSOLUTE_VOLUME = 16; 158e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_ABS_VOL_TIMEOUT = 17; 159e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_FAST_FORWARD = 18; 160e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_REWIND = 19; 16105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private static final int MSG_SET_A2DP_AUDIO_STATE = 20; 16205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private static final int MSG_ADDRESSED_PLAYER_CHANGED_RSP = 21; 16305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private static final int MSG_AVAILABLE_PLAYERS_CHANGED_RSP = 22; 16405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private static final int MSG_NOW_PLAYING_CHANGED_RSP = 23; 16505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 16617675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int CMD_TIMEOUT_DELAY = 2000; 167f8201e1c6bf7fadc0a332151a652325a7f31255aLiejun Tao private static final int MAX_ERROR_RETRY_TIMES = 6; 16817675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRCP_MAX_VOL = 127; 16917675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRCP_BASE_VOLUME_STEP = 1; 170ace834feb02adabd61f628c4471147aea02d939cJohn Du 171e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Communicates with MediaPlayer to fetch media content */ 172e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private BrowsedMediaPlayer mBrowsedMediaPlayer; 173e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 17405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen /* Addressed player handling */ 175e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private AddressedMediaPlayer mAddressedMediaPlayer; 176e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 177e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* List of Media player instances, useful for retrieving MediaPlayerList or MediaPlayerInfo */ 178eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen private SortedMap<Integer, MediaPlayerInfo> mMediaPlayerInfoList; 179e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 180e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* List of media players which supports browse */ 1815146bd27869df5473aa53e6271266f51733971efMarie Janssen private List<BrowsePlayerInfo> mBrowsePlayerInfoList; 182e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 183e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Manage browsed players */ 184e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private AvrcpBrowseManager mAvrcpBrowseManager; 185e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 186e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Broadcast receiver for device connections intent broadcasts */ 187e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private final BroadcastReceiver mAvrcpReceiver = new AvrcpServiceBroadcastReceiver(); 1880427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker private final BroadcastReceiver mBootReceiver = new AvrcpServiceBootReceiver(); 189e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 19005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen /* Recording passthrough key dispatches */ 19105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen static private final int PASSTHROUGH_LOG_MAX_SIZE = DEBUG ? 50 : 10; 19205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private EvictingQueue<MediaKeyLog> mPassthroughLogs; // Passthorugh keys dispatched 19378d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen private List<MediaKeyLog> mPassthroughPending; // Passthrough keys sent not dispatched yet 19405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private int mPassthroughDispatched; // Number of keys dispatched 19505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 19605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private class MediaKeyLog { 19705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private long mTimeSent; 19805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private long mTimeProcessed; 19905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private String mPackage; 20005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private KeyEvent mEvent; 20105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 20205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public MediaKeyLog(long time, KeyEvent event) { 20305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mEvent = event; 20405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mTimeSent = time; 20505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 20605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 20705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public boolean addDispatch(long time, KeyEvent event, String packageName) { 20805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (mPackage != null) return false; 20905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (event.getAction() != mEvent.getAction()) return false; 21005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (event.getKeyCode() != mEvent.getKeyCode()) return false; 21105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mPackage = packageName; 21205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mTimeProcessed = time; 21305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return true; 21405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 21505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 21605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public String toString() { 21705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen StringBuilder sb = new StringBuilder(); 21805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen sb.append(android.text.format.DateFormat.format("MM-dd HH:mm:ss", mTimeSent)); 21905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen sb.append(" " + mEvent.toString()); 22005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (mPackage == null) { 22105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen sb.append(" (undispatched)"); 22205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } else { 22305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen sb.append(" to " + mPackage); 22405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen sb.append(" in " + (mTimeProcessed - mTimeSent) + "ms"); 22505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 22605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return sb.toString(); 22705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 22805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 22905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 230c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu static { 231c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu classInitNative(); 232c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 233c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 234c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private Avrcp(Context context) { 2353b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen mMediaAttributes = new MediaAttributes(null); 2360e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen mCurrentPlayState = new PlaybackState.Builder().setState(PlaybackState.STATE_NONE, -1L, 0.0f).build(); 2370a429916782c20980e7f0893c503c633b8341f88Marie Janssen mA2dpState = BluetoothA2dp.STATE_NOT_PLAYING; 238e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPlayStatusChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 239e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 240aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPlaybackIntervalMs = 0L; 241e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPlayPosChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 242fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen mLastReportedPosition = -1; 2433635a926bd7316a55b288a54d409a1070a9c19e8Marie Janssen mNextPosMs = -1; 2443635a926bd7316a55b288a54d409a1070a9c19e8Marie Janssen mPrevPosMs = -1; 24517675906064bb72fdcca75baa56cdf8bb8968d01John Du mFeatures = 0; 24611798b011c962b602217b479130d413f3b30f19aLiejun Tao mRemoteVolume = -1; 24711798b011c962b602217b479130d413f3b30f19aLiejun Tao mInitialRemoteVolume = -1; 24811798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastRemoteVolume = -1; 24917675906064bb72fdcca75baa56cdf8bb8968d01John Du mLastDirection = 0; 25011798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = false; 25111798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = false; 25217675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes = 0; 25311798b011c962b602217b479130d413f3b30f19aLiejun Tao mLocalVolume = -1; 25411798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = -1; 25511798b011c962b602217b479130d413f3b30f19aLiejun Tao mAbsVolThreshold = 0; 25611798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolumeMapping = new HashMap<Integer, Integer>(); 257e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah sUIDCounter = AvrcpConstants.DEFAULT_UID_COUNTER; 258384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen mCurrAddrPlayerID = NO_PLAYER_ID; 259294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen mCurrBrowsePlayerID = 0; 260c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mContext = context; 261eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen mLastUsedPlayerID = 0; 262e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAddressedMediaPlayer = null; 263c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 264c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu initNative(); 265c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 266e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mMediaSessionManager = (MediaSessionManager) context.getSystemService( 267e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Context.MEDIA_SESSION_SERVICE); 268c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 2692e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie mAudioStreamMax = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); 2702e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie mVolumeStep = Math.max(AVRCP_BASE_VOLUME_STEP, AVRCP_MAX_VOL/mAudioStreamMax); 271e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 27211798b011c962b602217b479130d413f3b30f19aLiejun Tao Resources resources = context.getResources(); 27311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (resources != null) { 27411798b011c962b602217b479130d413f3b30f19aLiejun Tao mAbsVolThreshold = resources.getInteger(R.integer.a2dp_absolute_volume_initial_threshold); 27511798b011c962b602217b479130d413f3b30f19aLiejun Tao } 276e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 277be66a1bf5584a2a7985666ab20c5e9b54053e17dMarie Janssen mBrowsableListBuilder = new BrowsablePlayerListBuilder(); 278be66a1bf5584a2a7985666ab20c5e9b54053e17dMarie Janssen 279e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // Register for package removal intent broadcasts for media button receiver persistence 280e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah IntentFilter pkgFilter = new IntentFilter(); 281e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah pkgFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 282e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah pkgFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 283e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah pkgFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); 284e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah pkgFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED); 285e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah pkgFilter.addDataScheme("package"); 286e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah context.registerReceiver(mAvrcpReceiver, pkgFilter); 2870427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker 2880427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker IntentFilter bootFilter = new IntentFilter(); 2890427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker bootFilter.addAction(Intent.ACTION_BOOT_COMPLETED); 2900427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker context.registerReceiver(mBootReceiver, bootFilter); 291c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 292c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 293c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private void start() { 294c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu HandlerThread thread = new HandlerThread("BluetoothAvrcpHandler"); 295c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu thread.start(); 296c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Looper looper = thread.getLooper(); 297c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler = new AvrcpMessageHandler(looper); 2989d4035307b85e78f10fba961e225ca09bfb7d0c7Jakub Pawlowski mMediaControllerCb = new MediaControllerListener(); 299e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpMediaRsp = new AvrcpMediaRsp(); 300eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen mMediaPlayerInfoList = new TreeMap<Integer, MediaPlayerInfo>(); 3015146bd27869df5473aa53e6271266f51733971efMarie Janssen mBrowsePlayerInfoList = Collections.synchronizedList(new ArrayList<BrowsePlayerInfo>()); 30205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mPassthroughDispatched = 0; 30305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mPassthroughLogs = new EvictingQueue<MediaKeyLog>(PASSTHROUGH_LOG_MAX_SIZE); 30478d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen mPassthroughPending = Collections.synchronizedList(new ArrayList<MediaKeyLog>()); 305f65765e71b2a6552c319eb5199914045a1ecdb04Marie Janssen if (mMediaSessionManager != null) { 306f65765e71b2a6552c319eb5199914045a1ecdb04Marie Janssen mMediaSessionManager.addOnActiveSessionsChangedListener(mActiveSessionListener, null, 307f65765e71b2a6552c319eb5199914045a1ecdb04Marie Janssen mHandler); 30805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mMediaSessionManager.setCallback(mButtonDispatchCallback, null); 309f65765e71b2a6552c319eb5199914045a1ecdb04Marie Janssen } 310e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPackageManager = mContext.getApplicationContext().getPackageManager(); 311e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 312e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* create object to communicate with addressed player */ 313e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAddressedMediaPlayer = new AddressedMediaPlayer(mAvrcpMediaRsp); 314e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 315e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* initialize BrowseMananger which manages Browse commands and response */ 316e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager = new AvrcpBrowseManager(mContext, mAvrcpMediaRsp); 3170427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker 31805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen initMediaPlayersList(); 31911bf73ff614f48a41dc379763bc007f271197b26Ajay Panicker 3200427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker UserManager manager = UserManager.get(mContext); 3210427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker if (manager == null || manager.isUserUnlocked()) { 3220427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker if (DEBUG) Log.d(TAG, "User already unlocked, initializing player lists"); 3233843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen // initialize browsable player list and build media player list 324be66a1bf5584a2a7985666ab20c5e9b54053e17dMarie Janssen mBrowsableListBuilder.start(); 3250427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker } 326c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 327c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 328066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood public static Avrcp make(Context context) { 329c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (DEBUG) Log.v(TAG, "make"); 330c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Avrcp ar = new Avrcp(context); 331c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ar.start(); 332c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return ar; 333c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 334c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 335c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public void doQuit() { 336e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "doQuit"); 337ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen synchronized (this) { 338ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen if (mMediaController != null) mMediaController.unregisterCallback(mMediaControllerCb); 339ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen } 3407c7cc128e93e7e1db8a5ed7f69583ddc6d99493eMarie Janssen if (mMediaSessionManager != null) { 3417c7cc128e93e7e1db8a5ed7f69583ddc6d99493eMarie Janssen mMediaSessionManager.setCallback(null, null); 3427c7cc128e93e7e1db8a5ed7f69583ddc6d99493eMarie Janssen mMediaSessionManager.removeOnActiveSessionsChangedListener(mActiveSessionListener); 3437c7cc128e93e7e1db8a5ed7f69583ddc6d99493eMarie Janssen } 3447c7cc128e93e7e1db8a5ed7f69583ddc6d99493eMarie Janssen 345c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.removeCallbacksAndMessages(null); 346c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Looper looper = mHandler.getLooper(); 347c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (looper != null) { 348c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu looper.quit(); 349c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 350e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 351e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler = null; 352e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mContext.unregisterReceiver(mAvrcpReceiver); 3530427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker mContext.unregisterReceiver(mBootReceiver); 354e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 355be66a1bf5584a2a7985666ab20c5e9b54053e17dMarie Janssen mBrowsableListBuilder.cleanup(); 356e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAddressedMediaPlayer.cleanup(); 357e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager.cleanup(); 358c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 359c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 360c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public void cleanup() { 361e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "cleanup"); 362c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu cleanupNative(); 36311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolumeMapping != null) 36411798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolumeMapping.clear(); 365c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 366c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 3670e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen private class MediaControllerListener extends MediaController.Callback { 3680e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen @Override 3690e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen public void onMetadataChanged(MediaMetadata metadata) { 37029174eb9ad6e255d7ec216ab9a2ce8d20e2fe13cMarie Janssen if (DEBUG) Log.v(TAG, "onMetadataChanged"); 3710a429916782c20980e7f0893c503c633b8341f88Marie Janssen updateCurrentMediaState(); 372c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 373bc10e7d58aa55da25c18d8056a0254a2b736146aZhihai Xu @Override 374e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public synchronized void onPlaybackStateChanged(PlaybackState state) { 375eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen if (DEBUG) Log.v(TAG, "onPlaybackStateChanged: state " + state.toString()); 3760a429916782c20980e7f0893c503c633b8341f88Marie Janssen updateCurrentMediaState(); 377c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 378c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 379c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu @Override 3800e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen public void onSessionDestroyed() { 3810e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen Log.v(TAG, "MediaController session destroyed"); 382ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen synchronized (Avrcp.this) { 383ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen if (mMediaController != null) 384ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen removeMediaController(mMediaController.getWrappedInstance()); 385384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } 386c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 387c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 388c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu @Override 389e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void onQueueChanged(List<MediaSession.QueueItem> queue) { 390e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (queue == null) { 391e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.v(TAG, "onQueueChanged: received null queue"); 392e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return; 393e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 3942b903c7262c9b8c0493e36b93b37831e7e075bfcMarie Janssen 395e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.v(TAG, "onQueueChanged: NowPlaying list changed, Queue Size = "+ queue.size()); 396e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAddressedMediaPlayer.updateNowPlayingList(queue); 397e2619781c799435cf0273d381069c754c5f89a20Marie Janssen mHandler.sendEmptyMessage(MSG_NOW_PLAYING_CHANGED_RSP); 398c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 399c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 400c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 401c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu /** Handles Avrcp messages. */ 402c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private final class AvrcpMessageHandler extends Handler { 403c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private AvrcpMessageHandler(Looper looper) { 404c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu super(looper); 405c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 406c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 407c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu @Override 408c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public void handleMessage(Message msg) { 409c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu switch (msg.what) { 410e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_RC_FEATURES: 411e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah { 41217675906064bb72fdcca75baa56cdf8bb8968d01John Du String address = (String) msg.obj; 413e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_GET_RC_FEATURES: address="+address+ 414e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ", features="+msg.arg1); 41517675906064bb72fdcca75baa56cdf8bb8968d01John Du mFeatures = msg.arg1; 41611798b011c962b602217b479130d413f3b30f19aLiejun Tao mFeatures = modifyRcFeatureFromBlacklist(mFeatures, address); 41717675906064bb72fdcca75baa56cdf8bb8968d01John Du mAudioManager.avrcpSupportsAbsoluteVolume(address, isAbsoluteVolumeSupported()); 41811798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = -1; 41911798b011c962b602217b479130d413f3b30f19aLiejun Tao mRemoteVolume = -1; 42011798b011c962b602217b479130d413f3b30f19aLiejun Tao mLocalVolume = -1; 42111798b011c962b602217b479130d413f3b30f19aLiejun Tao mInitialRemoteVolume = -1; 42211798b011c962b602217b479130d413f3b30f19aLiejun Tao mAddress = address; 42311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolumeMapping != null) 42411798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolumeMapping.clear(); 42517675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 426e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 42717675906064bb72fdcca75baa56cdf8bb8968d01John Du 428e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_PLAY_STATUS: 429e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah { 430e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] address = (byte[]) msg.obj; 431e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen int btstate = convertPlayStateToPlayStatus(mCurrentPlayState); 432e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen int length = (int) mMediaAttributes.getLength(); 433e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen int position = (int) getPlayPosition(); 434e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen if (DEBUG) 435e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen Log.v(TAG, "MSG_NATIVE_REQ_GET_PLAY_STATUS, responding with state " + btstate 436e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen + " len " + length + " pos " + position); 437e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen getPlayStatusRspNative(address, btstate, length, position); 438c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 439e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 440c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 441e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_ELEM_ATTRS: 442e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah { 443c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu String[] textArray; 444e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd.ElementAttrCmd elem = (AvrcpCmd.ElementAttrCmd) msg.obj; 445e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte numAttr = elem.mNumAttr; 446e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int[] attrIds = elem.mAttrIDs; 447e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_GET_ELEM_ATTRS:numAttr=" + numAttr); 448c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu textArray = new String[numAttr]; 449e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen StringBuilder responseDebug = new StringBuilder(); 450e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen responseDebug.append("getElementAttr response: "); 451c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu for (int i = 0; i < numAttr; ++i) { 4523b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen textArray[i] = mMediaAttributes.getString(attrIds[i]); 453e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen responseDebug.append("[" + attrIds[i] + "=" + textArray[i] + "] "); 454c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 455e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen Log.v(TAG, responseDebug.toString()); 456e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] bdaddr = elem.mAddress; 457e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah getElementAttrRspNative(bdaddr, numAttr, attrIds, textArray); 458c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 459e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 460c1124a7c6679f612b80926a19084655f9a71580aMarie Janssen 461e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_REGISTER_NOTIFICATION: 462e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_REGISTER_NOTIFICATION:event=" + msg.arg1 + 463e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah " param=" + msg.arg2); 464e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah processRegisterNotification((byte[]) msg.obj, msg.arg1, msg.arg2); 465c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 466c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 467e2619781c799435cf0273d381069c754c5f89a20Marie Janssen case MSG_AVAILABLE_PLAYERS_CHANGED_RSP: 468e2619781c799435cf0273d381069c754c5f89a20Marie Janssen if (DEBUG) Log.v(TAG, "MSG_AVAILABLE_PLAYERS_CHANGED_RSP"); 469e2619781c799435cf0273d381069c754c5f89a20Marie Janssen removeMessages(MSG_AVAILABLE_PLAYERS_CHANGED_RSP); 470e2619781c799435cf0273d381069c754c5f89a20Marie Janssen registerNotificationRspAvalPlayerChangedNative( 471e2619781c799435cf0273d381069c754c5f89a20Marie Janssen AvrcpConstants.NOTIFICATION_TYPE_CHANGED); 472e2619781c799435cf0273d381069c754c5f89a20Marie Janssen break; 473e2619781c799435cf0273d381069c754c5f89a20Marie Janssen 474e2619781c799435cf0273d381069c754c5f89a20Marie Janssen case MSG_NOW_PLAYING_CHANGED_RSP: 475e2619781c799435cf0273d381069c754c5f89a20Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NOW_PLAYING_CHANGED_RSP"); 476e2619781c799435cf0273d381069c754c5f89a20Marie Janssen removeMessages(MSG_NOW_PLAYING_CHANGED_RSP); 477e2619781c799435cf0273d381069c754c5f89a20Marie Janssen registerNotificationRspNowPlayingChangedNative( 478e2619781c799435cf0273d381069c754c5f89a20Marie Janssen AvrcpConstants.NOTIFICATION_TYPE_CHANGED); 479e2619781c799435cf0273d381069c754c5f89a20Marie Janssen break; 480e2619781c799435cf0273d381069c754c5f89a20Marie Janssen 481e2619781c799435cf0273d381069c754c5f89a20Marie Janssen case MSG_ADDRESSED_PLAYER_CHANGED_RSP: 482e2619781c799435cf0273d381069c754c5f89a20Marie Janssen // Later addressed players override earlier ones. 483e2619781c799435cf0273d381069c754c5f89a20Marie Janssen if (hasMessages(MSG_ADDRESSED_PLAYER_CHANGED_RSP)) { 484e2619781c799435cf0273d381069c754c5f89a20Marie Janssen Log.i(TAG, "MSG_ADDRESSED_PLAYER_CHANGED_RSP: skip, more changes in queue"); 485e2619781c799435cf0273d381069c754c5f89a20Marie Janssen break; 486e2619781c799435cf0273d381069c754c5f89a20Marie Janssen } 487e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen if (DEBUG) 488e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen Log.v(TAG, "MSG_ADDRESSED_PLAYER_CHANGED_RSP: newAddrPlayer = " + msg.arg1); 489e2619781c799435cf0273d381069c754c5f89a20Marie Janssen registerNotificationRspAddrPlayerChangedNative( 490e2619781c799435cf0273d381069c754c5f89a20Marie Janssen AvrcpConstants.NOTIFICATION_TYPE_CHANGED, msg.arg1, sUIDCounter); 491e2619781c799435cf0273d381069c754c5f89a20Marie Janssen break; 492e2619781c799435cf0273d381069c754c5f89a20Marie Janssen 493e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_PLAY_INTERVAL_TIMEOUT: 494e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_PLAY_INTERVAL_TIMEOUT"); 495f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen sendPlayPosNotificationRsp(false); 496aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu break; 497aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 498e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_VOLUME_CHANGE: 49911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (!isAbsoluteVolumeSupported()) { 500e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_VOLUME_CHANGE ignored, not supported"); 50111798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 50211798b011c962b602217b479130d413f3b30f19aLiejun Tao } 503e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen byte absVol = (byte) ((byte) msg.arg1 & 0x7f); // discard MSB as it is RFD 504e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen if (DEBUG) 505e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen Log.v(TAG, "MSG_NATIVE_REQ_VOLUME_CHANGE: volume=" + absVol + " ctype=" 506e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen + msg.arg2); 50711798b011c962b602217b479130d413f3b30f19aLiejun Tao 50811798b011c962b602217b479130d413f3b30f19aLiejun Tao boolean volAdj = false; 50917675906064bb72fdcca75baa56cdf8bb8968d01John Du if (msg.arg2 == AVRC_RSP_ACCEPT || msg.arg2 == AVRC_RSP_REJ) { 51011798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolCmdAdjustInProgress == false && mVolCmdSetInProgress == false) { 51117675906064bb72fdcca75baa56cdf8bb8968d01John Du Log.e(TAG, "Unsolicited response, ignored"); 51217675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 51317675906064bb72fdcca75baa56cdf8bb8968d01John Du } 514e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah removeMessages(MSG_ABS_VOL_TIMEOUT); 51511798b011c962b602217b479130d413f3b30f19aLiejun Tao 51611798b011c962b602217b479130d413f3b30f19aLiejun Tao volAdj = mVolCmdAdjustInProgress; 51711798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = false; 51811798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = false; 51917675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes = 0; 52017675906064bb72fdcca75baa56cdf8bb8968d01John Du } 52111798b011c962b602217b479130d413f3b30f19aLiejun Tao 52211798b011c962b602217b479130d413f3b30f19aLiejun Tao // convert remote volume to local volume 52311798b011c962b602217b479130d413f3b30f19aLiejun Tao int volIndex = convertToAudioStreamVolume(absVol); 52411798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mInitialRemoteVolume == -1) { 52511798b011c962b602217b479130d413f3b30f19aLiejun Tao mInitialRemoteVolume = absVol; 52611798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mAbsVolThreshold > 0 && mAbsVolThreshold < mAudioStreamMax && volIndex > mAbsVolThreshold) { 52711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.v(TAG, "remote inital volume too high " + volIndex + ">" + mAbsVolThreshold); 528e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg1 = mHandler.obtainMessage(MSG_SET_ABSOLUTE_VOLUME, mAbsVolThreshold , 0); 52911798b011c962b602217b479130d413f3b30f19aLiejun Tao mHandler.sendMessage(msg1); 53011798b011c962b602217b479130d413f3b30f19aLiejun Tao mRemoteVolume = absVol; 53111798b011c962b602217b479130d413f3b30f19aLiejun Tao mLocalVolume = volIndex; 53211798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 53311798b011c962b602217b479130d413f3b30f19aLiejun Tao } 53411798b011c962b602217b479130d413f3b30f19aLiejun Tao } 53511798b011c962b602217b479130d413f3b30f19aLiejun Tao 5360e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen if (mLocalVolume != volIndex && (msg.arg2 == AVRC_RSP_ACCEPT || 5370e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen msg.arg2 == AVRC_RSP_CHANGED || 5380e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen msg.arg2 == AVRC_RSP_INTERIM)) { 53911798b011c962b602217b479130d413f3b30f19aLiejun Tao /* If the volume has successfully changed */ 54011798b011c962b602217b479130d413f3b30f19aLiejun Tao mLocalVolume = volIndex; 54111798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mLastLocalVolume != -1 && msg.arg2 == AVRC_RSP_ACCEPT) { 54211798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mLastLocalVolume != volIndex) { 54311798b011c962b602217b479130d413f3b30f19aLiejun Tao /* remote volume changed more than requested due to 54411798b011c962b602217b479130d413f3b30f19aLiejun Tao * local and remote has different volume steps */ 54511798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "Remote returned volume does not match desired volume " 546e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + mLastLocalVolume + " vs " + volIndex); 54711798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = mLocalVolume; 54811798b011c962b602217b479130d413f3b30f19aLiejun Tao } 54911798b011c962b602217b479130d413f3b30f19aLiejun Tao } 55011798b011c962b602217b479130d413f3b30f19aLiejun Tao // remember the remote volume value, as it's the one supported by remote 55111798b011c962b602217b479130d413f3b30f19aLiejun Tao if (volAdj) { 55211798b011c962b602217b479130d413f3b30f19aLiejun Tao synchronized (mVolumeMapping) { 553e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mVolumeMapping.put(volIndex, (int) absVol); 55411798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.v(TAG, "remember volume mapping " +volIndex+ "-"+absVol); 55511798b011c962b602217b479130d413f3b30f19aLiejun Tao } 55611798b011c962b602217b479130d413f3b30f19aLiejun Tao } 55711798b011c962b602217b479130d413f3b30f19aLiejun Tao 55811798b011c962b602217b479130d413f3b30f19aLiejun Tao notifyVolumeChanged(mLocalVolume); 55911798b011c962b602217b479130d413f3b30f19aLiejun Tao mRemoteVolume = absVol; 560e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah long pecentVolChanged = ((long) absVol * 100) / 0x7f; 5615c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta Log.e(TAG, "percent volume changed: " + pecentVolChanged + "%"); 56217675906064bb72fdcca75baa56cdf8bb8968d01John Du } else if (msg.arg2 == AVRC_RSP_REJ) { 56317675906064bb72fdcca75baa56cdf8bb8968d01John Du Log.e(TAG, "setAbsoluteVolume call rejected"); 56411798b011c962b602217b479130d413f3b30f19aLiejun Tao } else if (volAdj && mLastRemoteVolume > 0 && mLastRemoteVolume < AVRCP_MAX_VOL && 5650e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen mLocalVolume == volIndex && 566e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah (msg.arg2 == AVRC_RSP_ACCEPT)) { 56711798b011c962b602217b479130d413f3b30f19aLiejun Tao /* oops, the volume is still same, remote does not like the value 56811798b011c962b602217b479130d413f3b30f19aLiejun Tao * retry a volume one step up/down */ 56911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "Remote device didn't tune volume, let's try one more step."); 57011798b011c962b602217b479130d413f3b30f19aLiejun Tao int retry_volume = Math.min(AVRCP_MAX_VOL, 57111798b011c962b602217b479130d413f3b30f19aLiejun Tao Math.max(0, mLastRemoteVolume + mLastDirection)); 57211798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVolumeNative(retry_volume)) { 57311798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastRemoteVolume = retry_volume; 574e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah sendMessageDelayed(obtainMessage(MSG_ABS_VOL_TIMEOUT), CMD_TIMEOUT_DELAY); 57511798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = true; 57611798b011c962b602217b479130d413f3b30f19aLiejun Tao } 57717675906064bb72fdcca75baa56cdf8bb8968d01John Du } 57817675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 57917675906064bb72fdcca75baa56cdf8bb8968d01John Du 580e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_ADJUST_VOLUME: 58111798b011c962b602217b479130d413f3b30f19aLiejun Tao if (!isAbsoluteVolumeSupported()) { 582e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "ignore MSG_ADJUST_VOLUME"); 58311798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 58411798b011c962b602217b479130d413f3b30f19aLiejun Tao } 58511798b011c962b602217b479130d413f3b30f19aLiejun Tao 586e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "MSG_ADJUST_VOLUME: direction=" + msg.arg1); 58711798b011c962b602217b479130d413f3b30f19aLiejun Tao 58811798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolCmdAdjustInProgress || mVolCmdSetInProgress) { 58917675906064bb72fdcca75baa56cdf8bb8968d01John Du if (DEBUG) Log.w(TAG, "There is already a volume command in progress."); 59017675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 59117675906064bb72fdcca75baa56cdf8bb8968d01John Du } 59211798b011c962b602217b479130d413f3b30f19aLiejun Tao 59311798b011c962b602217b479130d413f3b30f19aLiejun Tao // Remote device didn't set initial volume. Let's black list it 59411798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mInitialRemoteVolume == -1) { 59511798b011c962b602217b479130d413f3b30f19aLiejun Tao Log.d(TAG, "remote " + mAddress + " never tell us initial volume, black list it."); 59611798b011c962b602217b479130d413f3b30f19aLiejun Tao blackListCurrentDevice(); 59711798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 59811798b011c962b602217b479130d413f3b30f19aLiejun Tao } 59911798b011c962b602217b479130d413f3b30f19aLiejun Tao 60017675906064bb72fdcca75baa56cdf8bb8968d01John Du // Wait on verification on volume from device, before changing the volume. 60111798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mRemoteVolume != -1 && (msg.arg1 == -1 || msg.arg1 == 1)) { 60211798b011c962b602217b479130d413f3b30f19aLiejun Tao int setVol = -1; 60311798b011c962b602217b479130d413f3b30f19aLiejun Tao int targetVolIndex = -1; 60411798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mLocalVolume == 0 && msg.arg1 == -1) { 60511798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.w(TAG, "No need to Vol down from 0."); 60611798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 60711798b011c962b602217b479130d413f3b30f19aLiejun Tao } 60811798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mLocalVolume == mAudioStreamMax && msg.arg1 == 1) { 60911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.w(TAG, "No need to Vol up from max."); 61011798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 61111798b011c962b602217b479130d413f3b30f19aLiejun Tao } 61211798b011c962b602217b479130d413f3b30f19aLiejun Tao 61311798b011c962b602217b479130d413f3b30f19aLiejun Tao targetVolIndex = mLocalVolume + msg.arg1; 61411798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "Adjusting volume to " + targetVolIndex); 61511798b011c962b602217b479130d413f3b30f19aLiejun Tao 61611798b011c962b602217b479130d413f3b30f19aLiejun Tao Integer i; 61711798b011c962b602217b479130d413f3b30f19aLiejun Tao synchronized (mVolumeMapping) { 61811798b011c962b602217b479130d413f3b30f19aLiejun Tao i = mVolumeMapping.get(targetVolIndex); 61911798b011c962b602217b479130d413f3b30f19aLiejun Tao } 62011798b011c962b602217b479130d413f3b30f19aLiejun Tao 62111798b011c962b602217b479130d413f3b30f19aLiejun Tao if (i != null) { 62211798b011c962b602217b479130d413f3b30f19aLiejun Tao /* if we already know this volume mapping, use it */ 62311798b011c962b602217b479130d413f3b30f19aLiejun Tao setVol = i.byteValue(); 62411798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVol == mRemoteVolume) { 62511798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "got same volume from mapping for " + targetVolIndex + ", ignore."); 62611798b011c962b602217b479130d413f3b30f19aLiejun Tao setVol = -1; 62711798b011c962b602217b479130d413f3b30f19aLiejun Tao } 62811798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "set volume from mapping " + targetVolIndex + "-" + setVol); 62911798b011c962b602217b479130d413f3b30f19aLiejun Tao } 63011798b011c962b602217b479130d413f3b30f19aLiejun Tao 63111798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVol == -1) { 63211798b011c962b602217b479130d413f3b30f19aLiejun Tao /* otherwise use phone steps */ 63311798b011c962b602217b479130d413f3b30f19aLiejun Tao setVol = Math.min(AVRCP_MAX_VOL, 634e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah convertToAvrcpVolume(Math.max(0, targetVolIndex))); 63511798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "set volume from local volume "+ targetVolIndex+"-"+ setVol); 63611798b011c962b602217b479130d413f3b30f19aLiejun Tao } 63711798b011c962b602217b479130d413f3b30f19aLiejun Tao 63817675906064bb72fdcca75baa56cdf8bb8968d01John Du if (setVolumeNative(setVol)) { 639e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah sendMessageDelayed(obtainMessage(MSG_ABS_VOL_TIMEOUT), CMD_TIMEOUT_DELAY); 64011798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = true; 64117675906064bb72fdcca75baa56cdf8bb8968d01John Du mLastDirection = msg.arg1; 64211798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastRemoteVolume = setVol; 64311798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = targetVolIndex; 64411798b011c962b602217b479130d413f3b30f19aLiejun Tao } else { 64511798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "setVolumeNative failed"); 64617675906064bb72fdcca75baa56cdf8bb8968d01John Du } 64717675906064bb72fdcca75baa56cdf8bb8968d01John Du } else { 648e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "Unknown direction in MSG_ADJUST_VOLUME"); 64917675906064bb72fdcca75baa56cdf8bb8968d01John Du } 65017675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 65117675906064bb72fdcca75baa56cdf8bb8968d01John Du 652e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_SET_ABSOLUTE_VOLUME: 65311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (!isAbsoluteVolumeSupported()) { 654e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "ignore MSG_SET_ABSOLUTE_VOLUME"); 65511798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 65611798b011c962b602217b479130d413f3b30f19aLiejun Tao } 65711798b011c962b602217b479130d413f3b30f19aLiejun Tao 658e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_SET_ABSOLUTE_VOLUME"); 65911798b011c962b602217b479130d413f3b30f19aLiejun Tao 66011798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolCmdSetInProgress || mVolCmdAdjustInProgress) { 66117675906064bb72fdcca75baa56cdf8bb8968d01John Du if (DEBUG) Log.w(TAG, "There is already a volume command in progress."); 66217675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 66317675906064bb72fdcca75baa56cdf8bb8968d01John Du } 66411798b011c962b602217b479130d413f3b30f19aLiejun Tao 66511798b011c962b602217b479130d413f3b30f19aLiejun Tao // Remote device didn't set initial volume. Let's black list it 66611798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mInitialRemoteVolume == -1) { 66711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "remote " + mAddress + " never tell us initial volume, black list it."); 66811798b011c962b602217b479130d413f3b30f19aLiejun Tao blackListCurrentDevice(); 66911798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 67011798b011c962b602217b479130d413f3b30f19aLiejun Tao } 67111798b011c962b602217b479130d413f3b30f19aLiejun Tao 67211798b011c962b602217b479130d413f3b30f19aLiejun Tao int avrcpVolume = convertToAvrcpVolume(msg.arg1); 67311798b011c962b602217b479130d413f3b30f19aLiejun Tao avrcpVolume = Math.min(AVRCP_MAX_VOL, Math.max(0, avrcpVolume)); 6743b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (DEBUG) Log.d(TAG, "Setting volume to " + msg.arg1 + "-" + avrcpVolume); 67511798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVolumeNative(avrcpVolume)) { 676e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah sendMessageDelayed(obtainMessage(MSG_ABS_VOL_TIMEOUT), CMD_TIMEOUT_DELAY); 67711798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = true; 67811798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastRemoteVolume = avrcpVolume; 67911798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = msg.arg1; 68011798b011c962b602217b479130d413f3b30f19aLiejun Tao } else { 68111798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "setVolumeNative failed"); 68217675906064bb72fdcca75baa56cdf8bb8968d01John Du } 68317675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 68417675906064bb72fdcca75baa56cdf8bb8968d01John Du 685e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_ABS_VOL_TIMEOUT: 686e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_ABS_VOL_TIMEOUT: Volume change cmd timed out."); 68711798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = false; 68811798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = false; 68917675906064bb72fdcca75baa56cdf8bb8968d01John Du if (mAbsVolRetryTimes >= MAX_ERROR_RETRY_TIMES) { 69017675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes = 0; 691f8201e1c6bf7fadc0a332151a652325a7f31255aLiejun Tao /* too many volume change failures, black list the device */ 692f8201e1c6bf7fadc0a332151a652325a7f31255aLiejun Tao blackListCurrentDevice(); 69317675906064bb72fdcca75baa56cdf8bb8968d01John Du } else { 69417675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes += 1; 69511798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVolumeNative(mLastRemoteVolume)) { 696e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah sendMessageDelayed(obtainMessage(MSG_ABS_VOL_TIMEOUT), CMD_TIMEOUT_DELAY); 69711798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = true; 69817675906064bb72fdcca75baa56cdf8bb8968d01John Du } 69917675906064bb72fdcca75baa56cdf8bb8968d01John Du } 70017675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 70117675906064bb72fdcca75baa56cdf8bb8968d01John Du 702e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_SET_A2DP_AUDIO_STATE: 703e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_SET_A2DP_AUDIO_STATE:" + msg.arg1); 7040a429916782c20980e7f0893c503c633b8341f88Marie Janssen mA2dpState = msg.arg1; 7050a429916782c20980e7f0893c503c633b8341f88Marie Janssen updateCurrentMediaState(); 706188f205b5f093850d4cc627917a21204be36c56aZhihai Xu break; 707e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 708e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_FOLDER_ITEMS: { 709e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd.FolderItemsCmd folderObj = (AvrcpCmd.FolderItemsCmd) msg.obj; 71089728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_GET_FOLDER_ITEMS " + folderObj); 711e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah switch (folderObj.mScope) { 712e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case AvrcpConstants.BTRC_SCOPE_PLAYER_LIST: 713e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handleMediaPlayerListRsp(folderObj); 714e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 715e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case AvrcpConstants.BTRC_SCOPE_FILE_SYSTEM: 716e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case AvrcpConstants.BTRC_SCOPE_NOW_PLAYING: 717e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handleGetFolderItemBrowseResponse(folderObj, folderObj.mAddress); 718e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 719e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah default: 720e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "unknown scope for getfolderitems. scope = " 721e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + folderObj.mScope); 722e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah getFolderItemsRspNative(folderObj.mAddress, 723e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpConstants.RSP_INV_SCOPE, (short) 0, (byte) 0, 0, 724e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah null, null, null, null, null, null, null, null); 725e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 726e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 727e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 728e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 729e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_SET_ADDR_PLAYER: 730e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // object is bdaddr, argument 1 is the selected player id 731294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_SET_ADDR_PLAYER id=" + msg.arg1); 732e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah setAddressedPlayer((byte[]) msg.obj, msg.arg1); 733e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 734e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 735e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_ITEM_ATTR: 736e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // msg object contains the item attribute object 73789728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen AvrcpCmd.ItemAttrCmd cmd = (AvrcpCmd.ItemAttrCmd) msg.obj; 73889728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_GET_ITEM_ATTR " + cmd); 73989728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen handleGetItemAttr(cmd); 740e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 741e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 742e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_SET_BR_PLAYER: 743e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // argument 1 is the selected player id 744294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_SET_BR_PLAYER id=" + msg.arg1); 745e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah setBrowsedPlayer((byte[]) msg.obj, msg.arg1); 746e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 747e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 748e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_CHANGE_PATH: 749e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah { 750294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_CHANGE_PATH"); 751e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = msg.getData(); 752e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] bdaddr = data.getByteArray("BdAddress"); 753e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] folderUid = data.getByteArray("folderUid"); 754e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte direction = data.getByte("direction"); 755e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr) != null) { 756e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr).changePath(folderUid, 757e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah direction); 758e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 759e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "Remote requesting change path before setbrowsedplayer"); 760e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah changePathRspNative(bdaddr, AvrcpConstants.RSP_BAD_CMD, 0); 761e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 762e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 763e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 764e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 765e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_PLAY_ITEM: 766e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah { 767e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = msg.getData(); 768e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] bdaddr = data.getByteArray("BdAddress"); 769e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] uid = data.getByteArray("uid"); 770e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte scope = data.getByte("scope"); 77189728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen if (DEBUG) 77289728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen Log.v(TAG, "MSG_NATIVE_REQ_PLAY_ITEM scope=" + scope + " id=" 77389728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen + Utils.byteArrayToString(uid)); 774e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handlePlayItemResponse(bdaddr, uid, scope); 775e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 776e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 777e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 778e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_TOTAL_NUM_OF_ITEMS: 779294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_GET_TOTAL_NUM_OF_ITEMS scope=" + msg.arg1); 780e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // argument 1 is scope, object is bdaddr 781e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handleGetTotalNumOfItemsResponse((byte[]) msg.obj, (byte) msg.arg1); 782e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 783e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 784e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_PASS_THROUGH: 785294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen if (DEBUG) 78605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.v(TAG, "MSG_NATIVE_REQ_PASS_THROUGH: id=" + msg.arg1 + " st=" + msg.arg2); 78705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen // argument 1 is id, argument 2 is keyState 78805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen handlePassthroughCmd(msg.arg1, msg.arg2); 789e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 790e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 791e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah default: 792e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "unknown message! msg.what=" + msg.what); 793e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 794c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 795c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 796c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 797c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 798f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen private void updatePlaybackState(PlaybackState state) { 7990e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen if (state == null) { 8000e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen state = new PlaybackState.Builder().setState(PlaybackState.STATE_NONE, 801e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah PlaybackState.PLAYBACK_POSITION_UNKNOWN, 0.0f).build(); 8020e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen } 803f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 8040a429916782c20980e7f0893c503c633b8341f88Marie Janssen byte stateBytes = (byte) convertPlayStateToBytes(state.getState()); 8050a429916782c20980e7f0893c503c633b8341f88Marie Janssen 8060a429916782c20980e7f0893c503c633b8341f88Marie Janssen /* updating play status in global media player list */ 8070a429916782c20980e7f0893c503c633b8341f88Marie Janssen MediaPlayerInfo player = getAddressedPlayerInfo(); 8080a429916782c20980e7f0893c503c633b8341f88Marie Janssen if (player != null) { 8090a429916782c20980e7f0893c503c633b8341f88Marie Janssen player.setPlayStatus(stateBytes); 8100a429916782c20980e7f0893c503c633b8341f88Marie Janssen } else { 8110a429916782c20980e7f0893c503c633b8341f88Marie Janssen Log.w(TAG, "onPlaybackStateChanged: no addressed player id=" + mCurrAddrPlayerID); 8120a429916782c20980e7f0893c503c633b8341f88Marie Janssen } 8130a429916782c20980e7f0893c503c633b8341f88Marie Janssen 814fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen int oldPlayStatus = convertPlayStateToPlayStatus(mCurrentPlayState); 815c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu int newPlayStatus = convertPlayStateToPlayStatus(state); 816f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu 817fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen if (DEBUG) { 818fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen Log.v(TAG, "updatePlaybackState (" + mPlayStatusChangedNT + "): "+ 819e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah "old=" + mCurrentPlayState + "(" + oldPlayStatus + "), "+ 820e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah "new=" + state + "(" + newPlayStatus + ")"); 821fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen } 822fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen 823aa6c1cb7f08a5d1fe2c878b587c62cf4dbb6ee8fZhihai Xu mCurrentPlayState = state; 824aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 825f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen sendPlayPosNotificationRsp(false); 826aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 827e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mPlayStatusChangedNT == AvrcpConstants.NOTIFICATION_TYPE_INTERIM && 828e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah (oldPlayStatus != newPlayStatus)) { 829e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPlayStatusChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 830c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu registerNotificationRspPlayStatusNative(mPlayStatusChangedNT, newPlayStatus); 831c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 832c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 833c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 834c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private void updateTransportControls(int transportControlFlags) { 835c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mTransportControlFlags = transportControlFlags; 836c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 837c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 8383b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen class MediaAttributes { 8393b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private boolean exists; 8403b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String title; 8413b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String artistName; 8423b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String albumName; 8433b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String mediaNumber; 8443b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String mediaTotalNumber; 8453b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String genre; 8460a429916782c20980e7f0893c503c633b8341f88Marie Janssen private long playingTimeMs; 8473b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 8483b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_TITLE = 1; 8493b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_ARTIST_NAME = 2; 8503b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_ALBUM_NAME = 3; 8513b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_MEDIA_NUMBER = 4; 8523b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_MEDIA_TOTAL_NUMBER = 5; 8533b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_GENRE = 6; 8543b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_PLAYING_TIME_MS = 7; 8553b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 8563b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 8573b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen public MediaAttributes(MediaMetadata data) { 8583b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen exists = data != null; 8593b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (!exists) 8603b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return; 8613b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 8623b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen artistName = stringOrBlank(data.getString(MediaMetadata.METADATA_KEY_ARTIST)); 8633b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen albumName = stringOrBlank(data.getString(MediaMetadata.METADATA_KEY_ALBUM)); 8643b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen mediaNumber = longStringOrBlank(data.getLong(MediaMetadata.METADATA_KEY_TRACK_NUMBER)); 8653b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen mediaTotalNumber = longStringOrBlank(data.getLong(MediaMetadata.METADATA_KEY_NUM_TRACKS)); 8663b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen genre = stringOrBlank(data.getString(MediaMetadata.METADATA_KEY_GENRE)); 8670a429916782c20980e7f0893c503c633b8341f88Marie Janssen playingTimeMs = data.getLong(MediaMetadata.METADATA_KEY_DURATION); 8683b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 8693b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen // Try harder for the title. 8703b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen title = data.getString(MediaMetadata.METADATA_KEY_TITLE); 8713b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 8723b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (title == null) { 8733b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen MediaDescription desc = data.getDescription(); 8743b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (desc != null) { 8753b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen CharSequence val = desc.getDescription(); 8763b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (val != null) 8773b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen title = val.toString(); 8783b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 8793b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 8803b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 8813b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (title == null) 8823b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen title = new String(); 8833b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 8843b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 8850a429916782c20980e7f0893c503c633b8341f88Marie Janssen public long getLength() { 8860a429916782c20980e7f0893c503c633b8341f88Marie Janssen if (!exists) return 0L; 8870a429916782c20980e7f0893c503c633b8341f88Marie Janssen return playingTimeMs; 8880a429916782c20980e7f0893c503c633b8341f88Marie Janssen } 8890a429916782c20980e7f0893c503c633b8341f88Marie Janssen 8903b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen public boolean equals(MediaAttributes other) { 8913b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (other == null) 8923b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return false; 8933b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 8943b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (exists != other.exists) 8953b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return false; 8963b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 8973b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (exists == false) 8983b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return true; 8993b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9000a429916782c20980e7f0893c503c633b8341f88Marie Janssen return (title.equals(other.title)) && (artistName.equals(other.artistName)) 9010a429916782c20980e7f0893c503c633b8341f88Marie Janssen && (albumName.equals(other.albumName)) 9020a429916782c20980e7f0893c503c633b8341f88Marie Janssen && (mediaNumber.equals(other.mediaNumber)) 9030a429916782c20980e7f0893c503c633b8341f88Marie Janssen && (mediaTotalNumber.equals(other.mediaTotalNumber)) 9040a429916782c20980e7f0893c503c633b8341f88Marie Janssen && (genre.equals(other.genre)) && (playingTimeMs == other.playingTimeMs); 9053b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 9063b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9073b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen public String getString(int attrId) { 9083b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (!exists) 9093b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return new String(); 9103b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9113b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen switch (attrId) { 9123b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_TITLE: 9133b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return title; 9143b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_ARTIST_NAME: 9153b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return artistName; 9163b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_ALBUM_NAME: 9173b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return albumName; 9183b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_MEDIA_NUMBER: 9193b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return mediaNumber; 9203b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_MEDIA_TOTAL_NUMBER: 9213b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return mediaTotalNumber; 9223b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_GENRE: 9233b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return genre; 9243b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_PLAYING_TIME_MS: 9250a429916782c20980e7f0893c503c633b8341f88Marie Janssen return Long.toString(playingTimeMs); 9263b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen default: 9273b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return new String(); 9283b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 9293b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 9303b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9313b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String stringOrBlank(String s) { 9323b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return s == null ? new String() : s; 9333b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 934c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 9353b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String longStringOrBlank(Long s) { 9363b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return s == null ? new String() : s.toString(); 937c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 938c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 939c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public String toString() { 940e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!exists) { 9413b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return "[MediaAttributes: none]"; 942e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 9433b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9440a429916782c20980e7f0893c503c633b8341f88Marie Janssen return "[MediaAttributes: " + title + " - " + albumName + " by " + artistName + " (" 9450a429916782c20980e7f0893c503c633b8341f88Marie Janssen + playingTimeMs + " " + mediaNumber + "/" + mediaTotalNumber + ") " + genre 9460a429916782c20980e7f0893c503c633b8341f88Marie Janssen + "]"; 947c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 948c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 949c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 9500a429916782c20980e7f0893c503c633b8341f88Marie Janssen private void updateCurrentMediaState() { 951384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen MediaAttributes currentAttributes = mMediaAttributes; 952c9f4e0d24e39b372452fa809b12f9c588b29abd9Marie Janssen PlaybackState newState = null; 953ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen synchronized (this) { 954ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen if (mMediaController == null) { 955ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen // Use A2DP state if we don't have a MediaControlller 956ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen boolean isPlaying = (mA2dpState == BluetoothA2dp.STATE_PLAYING) 957ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen && mAudioManager.isMusicActive(); 958ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen PlaybackState.Builder builder = new PlaybackState.Builder(); 959ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen if (isPlaying) { 960ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen builder.setState(PlaybackState.STATE_PLAYING, 961ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen PlaybackState.PLAYBACK_POSITION_UNKNOWN, 1.0f); 962ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen } else { 963ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen builder.setState(PlaybackState.STATE_PAUSED, 964ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen PlaybackState.PLAYBACK_POSITION_UNKNOWN, 0.0f); 965ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen } 966ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen newState = builder.build(); 967ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen mMediaAttributes = new MediaAttributes(null); 968c9f4e0d24e39b372452fa809b12f9c588b29abd9Marie Janssen } else { 969ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen newState = mMediaController.getPlaybackState(); 970ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen mMediaAttributes = new MediaAttributes(mMediaController.getMetadata()); 9710a429916782c20980e7f0893c503c633b8341f88Marie Janssen } 9720e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen } 973e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 97429174eb9ad6e255d7ec216ab9a2ce8d20e2fe13cMarie Janssen long oldQueueId = mCurrentPlayState.getActiveQueueItemId(); 97529174eb9ad6e255d7ec216ab9a2ce8d20e2fe13cMarie Janssen long newQueueId = MediaSession.QueueItem.UNKNOWN_ID; 97629174eb9ad6e255d7ec216ab9a2ce8d20e2fe13cMarie Janssen if (newState != null) newQueueId = newState.getActiveQueueItemId(); 9778ac88214fdbf5e5197033b89ba82a6bf728706a4Marie Janssen Log.v(TAG, "Media update: id " + oldQueueId + "➡" + newQueueId + ":" 9788ac88214fdbf5e5197033b89ba82a6bf728706a4Marie Janssen + mMediaAttributes.toString()); 9798ac88214fdbf5e5197033b89ba82a6bf728706a4Marie Janssen if (oldQueueId != newQueueId || !currentAttributes.equals(mMediaAttributes)) { 9800a429916782c20980e7f0893c503c633b8341f88Marie Janssen sendTrackChangedRsp(false); 981c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 982aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 983384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen updatePlaybackState(newState); 984c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 985c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 986e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void getRcFeaturesRequestFromNative(byte[] address, int features) { 987e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_RC_FEATURES, features, 0, 988e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Utils.getAddressStringFromByte(address)); 98917675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 99017675906064bb72fdcca75baa56cdf8bb8968d01John Du } 99117675906064bb72fdcca75baa56cdf8bb8968d01John Du 992e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void getPlayStatusRequestFromNative(byte[] address) { 993e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_PLAY_STATUS); 994e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = address; 995c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.sendMessage(msg); 996c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 997c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 99889728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen private void getElementAttrRequestFromNative(byte[] address, byte numAttr, int[] attrs) { 999e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd avrcpCmdobj = new AvrcpCmd(); 1000e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd.ElementAttrCmd elemAttr = avrcpCmdobj.new ElementAttrCmd(address, numAttr, attrs); 1001e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_ELEM_ATTRS); 1002e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = elemAttr; 1003c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.sendMessage(msg); 1004c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1005c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1006e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void registerNotificationRequestFromNative(byte[] address,int eventId, int param) { 1007e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_REGISTER_NOTIFICATION, eventId, param); 1008e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = address; 1009c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.sendMessage(msg); 1010c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1011c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1012e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void processRegisterNotification(byte[] address, int eventId, int param) { 1013c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu switch (eventId) { 1014c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case EVT_PLAY_STATUS_CHANGED: 1015e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPlayStatusChangedNT = AvrcpConstants.NOTIFICATION_TYPE_INTERIM; 1016c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu registerNotificationRspPlayStatusNative(mPlayStatusChangedNT, 10170e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen convertPlayStateToPlayStatus(mCurrentPlayState)); 1018c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 1019c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1020c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case EVT_TRACK_CHANGED: 10210e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen Log.v(TAG, "Track changed notification enabled"); 1022e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_INTERIM; 10230a429916782c20980e7f0893c503c633b8341f88Marie Janssen sendTrackChangedRsp(true); 1024c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 1025c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1026aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu case EVT_PLAY_POS_CHANGED: 1027e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPlayPosChangedNT = AvrcpConstants.NOTIFICATION_TYPE_INTERIM; 1028e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPlaybackIntervalMs = (long) param * 1000L; 1029fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen sendPlayPosNotificationRsp(true); 1030aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu break; 1031aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 1032e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case EVT_AVBL_PLAYERS_CHANGED: 1033e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Notify remote available players changed */ 1034e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d (TAG, "sending availablePlayersChanged to remote "); 1035e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah registerNotificationRspAvalPlayerChangedNative( 1036e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpConstants.NOTIFICATION_TYPE_INTERIM); 1037e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 1038e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1039e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case EVT_ADDR_PLAYER_CHANGED: 1040e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Notify remote addressed players changed */ 1041e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d (TAG, "sending addressedPlayersChanged to remote "); 1042e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah registerNotificationRspAddrPlayerChangedNative( 1043e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpConstants.NOTIFICATION_TYPE_INTERIM, 1044e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mCurrAddrPlayerID, sUIDCounter); 1045e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 1046e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1047e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case EVENT_UIDS_CHANGED: 1048e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "sending UIDs changed to remote"); 1049e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah registerNotificationRspUIDsChangedNative( 1050e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpConstants.NOTIFICATION_TYPE_INTERIM, sUIDCounter); 1051e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 1052e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1053e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case EVENT_NOW_PLAYING_CONTENT_CHANGED: 1054e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "sending NowPlayingList changed to remote"); 1055e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* send interim response to remote device */ 1056e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspNowPlayingChangedNative( 1057e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpConstants.NOTIFICATION_TYPE_INTERIM)) { 1058e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "EVENT_NOW_PLAYING_CONTENT_CHANGED: " + 1059e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah "registerNotificationRspNowPlayingChangedNative for Interim rsp failed!"); 1060e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1061e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 1062c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1063c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1064c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1065e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handlePassthroughCmdRequestFromNative(byte[] address, int id, int keyState) { 106605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_PASS_THROUGH, id, keyState); 1067e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1068ace834feb02adabd61f628c4471147aea02d939cJohn Du } 1069ace834feb02adabd61f628c4471147aea02d939cJohn Du 10700a429916782c20980e7f0893c503c633b8341f88Marie Janssen private void sendTrackChangedRsp(boolean requested) { 1071eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen MediaPlayerInfo info = getAddressedPlayerInfo(); 10728ac88214fdbf5e5197033b89ba82a6bf728706a4Marie Janssen if (!requested && mTrackChangedNT != AvrcpConstants.NOTIFICATION_TYPE_INTERIM) { 10738ac88214fdbf5e5197033b89ba82a6bf728706a4Marie Janssen if (DEBUG) Log.d(TAG, "sendTrackChangedRsp: Not registered or requesting."); 10748ac88214fdbf5e5197033b89ba82a6bf728706a4Marie Janssen return; 10758ac88214fdbf5e5197033b89ba82a6bf728706a4Marie Janssen } 1076eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen if (info != null && !info.isBrowseSupported()) { 1077eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen // for players which does not support Browse or when no track is currently selected 10780a429916782c20980e7f0893c503c633b8341f88Marie Janssen trackChangeRspForBrowseUnsupported(requested); 1079e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 10800a429916782c20980e7f0893c503c633b8341f88Marie Janssen boolean changed = 10810a429916782c20980e7f0893c503c633b8341f88Marie Janssen mAddressedMediaPlayer.sendTrackChangeWithId(requested, mMediaController); 1082e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // for players which support browsing 10830a429916782c20980e7f0893c503c633b8341f88Marie Janssen if (changed) mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 1084e8e870c24930f9b687572dbb80614e5aad6fbdfaberyl hou } 1085e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1086e8e870c24930f9b687572dbb80614e5aad6fbdfaberyl hou 10870a429916782c20980e7f0893c503c633b8341f88Marie Janssen private void trackChangeRspForBrowseUnsupported(boolean requested) { 1088e23a886e79f60a3f7f5b8e87f8c5ffc26134bd32Marie Janssen byte[] track = AvrcpConstants.TRACK_IS_SELECTED; 10890a429916782c20980e7f0893c503c633b8341f88Marie Janssen if (requested && !mMediaAttributes.exists) { 1090e23a886e79f60a3f7f5b8e87f8c5ffc26134bd32Marie Janssen track = AvrcpConstants.NO_TRACK_SELECTED; 10910a429916782c20980e7f0893c503c633b8341f88Marie Janssen } else if (!requested) { 10920a429916782c20980e7f0893c503c633b8341f88Marie Janssen mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 1093c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1094c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu registerNotificationRspTrackChangeNative(mTrackChangedNT, track); 1095c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1096c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1097aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long getPlayPosition() { 1098e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mCurrentPlayState == null) { 1099f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen return -1L; 1100e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1101f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 1102e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mCurrentPlayState.getPosition() == PlaybackState.PLAYBACK_POSITION_UNKNOWN) { 1103f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen return -1L; 1104e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1105f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 1106f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen if (isPlayingState(mCurrentPlayState)) { 11070a429916782c20980e7f0893c503c633b8341f88Marie Janssen long sinceUpdate = 11080a429916782c20980e7f0893c503c633b8341f88Marie Janssen (SystemClock.elapsedRealtime() - mCurrentPlayState.getLastPositionUpdateTime()); 11090a429916782c20980e7f0893c503c633b8341f88Marie Janssen return sinceUpdate + mCurrentPlayState.getPosition(); 1110aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 1111f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 11123635a926bd7316a55b288a54d409a1070a9c19e8Marie Janssen return mCurrentPlayState.getPosition(); 1113aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 1114aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 11150e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen private int convertPlayStateToPlayStatus(PlaybackState state) { 1116c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu int playStatus = PLAYSTATUS_ERROR; 11170e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen switch (state.getState()) { 11180e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen case PlaybackState.STATE_PLAYING: 11190e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen case PlaybackState.STATE_BUFFERING: 1120c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_PLAYING; 1121c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 1122c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 11230e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen case PlaybackState.STATE_STOPPED: 11240e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen case PlaybackState.STATE_NONE: 1125c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_STOPPED; 1126c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 1127c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 11280e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen case PlaybackState.STATE_PAUSED: 1129c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_PAUSED; 1130c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 1131c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 11320e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen case PlaybackState.STATE_FAST_FORWARDING: 11330e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen case PlaybackState.STATE_SKIPPING_TO_NEXT: 11340e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen case PlaybackState.STATE_SKIPPING_TO_QUEUE_ITEM: 1135c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_FWD_SEEK; 1136c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 1137c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 11380e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen case PlaybackState.STATE_REWINDING: 11390e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen case PlaybackState.STATE_SKIPPING_TO_PREVIOUS: 1140c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_REV_SEEK; 1141c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 1142c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 11430e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen case PlaybackState.STATE_ERROR: 1144c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_ERROR; 1145c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 1146c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1147c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1148c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return playStatus; 1149c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1150c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 11510e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen private boolean isPlayingState(PlaybackState state) { 11520e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen return (state.getState() == PlaybackState.STATE_PLAYING) || 1153e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah (state.getState() == PlaybackState.STATE_BUFFERING); 1154188f205b5f093850d4cc627917a21204be36c56aZhihai Xu } 1155188f205b5f093850d4cc627917a21204be36c56aZhihai Xu 115617675906064bb72fdcca75baa56cdf8bb8968d01John Du /** 1157f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen * Sends a play position notification, or schedules one to be 1158f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen * sent later at an appropriate time. If |requested| is true, 1159f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen * does both because this was called in reponse to a request from the 1160f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen * TG. 1161f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen */ 1162f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen private void sendPlayPosNotificationRsp(boolean requested) { 1163e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!requested && mPlayPosChangedNT != AvrcpConstants.NOTIFICATION_TYPE_INTERIM) { 1164fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen if (DEBUG) Log.d(TAG, "sendPlayPosNotificationRsp: Not registered or requesting."); 1165fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen return; 1166fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen } 1167fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen 1168f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen long playPositionMs = getPlayPosition(); 1169f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 1170f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen // mNextPosMs is set to -1 when the previous position was invalid 1171f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen // so this will be true if the new position is valid & old was invalid. 1172f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen // mPlayPositionMs is set to -1 when the new position is invalid, 1173f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen // and the old mPrevPosMs is >= 0 so this is true when the new is invalid 1174f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen // and the old was valid. 1175fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen if (DEBUG) Log.d(TAG, "sendPlayPosNotificationRsp: (" + requested + ") " 1176e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + mPrevPosMs + " <=? " + playPositionMs + " <=? " + mNextPosMs); 117705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (DEBUG) Log.d(TAG, "sendPlayPosNotificationRsp: currentPlayState " + mCurrentPlayState); 1178fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen if (requested || ((mLastReportedPosition != playPositionMs) && 1179e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah (playPositionMs >= mNextPosMs) || (playPositionMs <= mPrevPosMs))) { 1180e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!requested) mPlayPosChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 1181e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah registerNotificationRspPlayPosNative(mPlayPosChangedNT, (int) playPositionMs); 1182fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen mLastReportedPosition = playPositionMs; 1183f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen if (playPositionMs != PlaybackState.PLAYBACK_POSITION_UNKNOWN) { 1184f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen mNextPosMs = playPositionMs + mPlaybackIntervalMs; 1185f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen mPrevPosMs = playPositionMs - mPlaybackIntervalMs; 1186f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } else { 1187f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen mNextPosMs = -1; 1188f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen mPrevPosMs = -1; 1189f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } 1190f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } 1191f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 1192e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.removeMessages(MSG_PLAY_INTERVAL_TIMEOUT); 1193e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mPlayPosChangedNT == AvrcpConstants.NOTIFICATION_TYPE_INTERIM && isPlayingState(mCurrentPlayState)) { 1194e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_PLAY_INTERVAL_TIMEOUT); 1195f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen long delay = mPlaybackIntervalMs; 1196f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen if (mNextPosMs != -1) { 1197f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen delay = mNextPosMs - (playPositionMs > 0 ? playPositionMs : 0); 1198f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } 1199fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen if (DEBUG) Log.d(TAG, "PLAY_INTERVAL_TIMEOUT set for " + delay + "ms from now"); 1200f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen mHandler.sendMessageDelayed(msg, delay); 1201f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } 1202f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } 1203f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 1204f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen /** 120517675906064bb72fdcca75baa56cdf8bb8968d01John Du * This is called from AudioService. It will return whether this device supports abs volume. 120617675906064bb72fdcca75baa56cdf8bb8968d01John Du * NOT USED AT THE MOMENT. 120717675906064bb72fdcca75baa56cdf8bb8968d01John Du */ 120817675906064bb72fdcca75baa56cdf8bb8968d01John Du public boolean isAbsoluteVolumeSupported() { 120917675906064bb72fdcca75baa56cdf8bb8968d01John Du return ((mFeatures & BTRC_FEAT_ABSOLUTE_VOLUME) != 0); 121017675906064bb72fdcca75baa56cdf8bb8968d01John Du } 121117675906064bb72fdcca75baa56cdf8bb8968d01John Du 121217675906064bb72fdcca75baa56cdf8bb8968d01John Du /** 121317675906064bb72fdcca75baa56cdf8bb8968d01John Du * We get this call from AudioService. This will send a message to our handler object, 121417675906064bb72fdcca75baa56cdf8bb8968d01John Du * requesting our handler to call setVolumeNative() 121517675906064bb72fdcca75baa56cdf8bb8968d01John Du */ 121617675906064bb72fdcca75baa56cdf8bb8968d01John Du public void adjustVolume(int direction) { 1217e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_ADJUST_VOLUME, direction, 0); 121817675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 121917675906064bb72fdcca75baa56cdf8bb8968d01John Du } 122017675906064bb72fdcca75baa56cdf8bb8968d01John Du 122117675906064bb72fdcca75baa56cdf8bb8968d01John Du public void setAbsoluteVolume(int volume) { 122211798b011c962b602217b479130d413f3b30f19aLiejun Tao if (volume == mLocalVolume) { 122311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.v(TAG, "setAbsoluteVolume is setting same index, ignore "+volume); 122411798b011c962b602217b479130d413f3b30f19aLiejun Tao return; 122511798b011c962b602217b479130d413f3b30f19aLiejun Tao } 122611798b011c962b602217b479130d413f3b30f19aLiejun Tao 1227e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.removeMessages(MSG_ADJUST_VOLUME); 1228e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_SET_ABSOLUTE_VOLUME, volume, 0); 122917675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 12305c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta } 12315c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta 123217675906064bb72fdcca75baa56cdf8bb8968d01John Du /* Called in the native layer as a btrc_callback to return the volume set on the carkit in the 123317675906064bb72fdcca75baa56cdf8bb8968d01John Du * case when the volume is change locally on the carkit. This notification is not called when 123417675906064bb72fdcca75baa56cdf8bb8968d01John Du * the volume is changed from the phone. 123517675906064bb72fdcca75baa56cdf8bb8968d01John Du * 123617675906064bb72fdcca75baa56cdf8bb8968d01John Du * This method will send a message to our handler to change the local stored volume and notify 123717675906064bb72fdcca75baa56cdf8bb8968d01John Du * AudioService to update the UI 123817675906064bb72fdcca75baa56cdf8bb8968d01John Du */ 1239e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void volumeChangeRequestFromNative(byte[] address, int volume, int ctype) { 1240e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_VOLUME_CHANGE, volume, ctype); 1241e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = new Bundle(); 1242e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByteArray("BdAddress" , address); 1243e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.setData(data); 1244e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1245e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1246e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 124719a05f008446506069b34265d57bcf421447e7e3Marie Janssen private void getFolderItemsRequestFromNative( 124819a05f008446506069b34265d57bcf421447e7e3Marie Janssen byte[] address, byte scope, long startItem, long endItem, byte numAttr, int[] attrIds) { 1249e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd avrcpCmdobj = new AvrcpCmd(); 1250e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd.FolderItemsCmd folderObj = avrcpCmdobj.new FolderItemsCmd(address, scope, 1251e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah startItem, endItem, numAttr, attrIds); 1252e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_FOLDER_ITEMS, 0, 0); 1253e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = folderObj; 1254e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1255e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1256e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1257e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void setAddressedPlayerRequestFromNative(byte[] address, int playerId) { 1258e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_SET_ADDR_PLAYER, playerId, 0); 1259e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = address; 1260e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1261e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1262e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1263e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void setBrowsedPlayerRequestFromNative(byte[] address, int playerId) { 1264e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_SET_BR_PLAYER, playerId, 0); 1265e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = address; 1266e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1267e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1268e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1269e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void changePathRequestFromNative(byte[] address, byte direction, byte[] folderUid) { 1270e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = new Bundle(); 1271e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_CHANGE_PATH); 1272e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByteArray("BdAddress" , address); 1273e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByteArray("folderUid" , folderUid); 1274e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByte("direction" , direction); 1275e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.setData(data); 1276e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1277e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1278e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1279e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void getItemAttrRequestFromNative(byte[] address, byte scope, byte[] itemUid, int uidCounter, 1280e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte numAttr, int[] attrs) { 1281e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd avrcpCmdobj = new AvrcpCmd(); 1282e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd.ItemAttrCmd itemAttr = avrcpCmdobj.new ItemAttrCmd(address, scope, 1283e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah itemUid, uidCounter, numAttr, attrs); 1284e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_ITEM_ATTR); 1285e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = itemAttr; 1286e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1287e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1288e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1289e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void searchRequestFromNative(byte[] address, int charsetId, byte[] searchStr) { 1290e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Search is not supported */ 1291e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen Log.w(TAG, "searchRequestFromNative: search is not supported"); 1292e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah searchRspNative(address, AvrcpConstants.RSP_SRCH_NOT_SPRTD, 0, 0); 1293e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1294e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1295e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void playItemRequestFromNative(byte[] address, byte scope, int uidCounter, byte[] uid) { 1296e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = new Bundle(); 1297e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_PLAY_ITEM); 1298e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByteArray("BdAddress" , address); 1299e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByteArray("uid" , uid); 1300e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putInt("uidCounter" , uidCounter); 1301e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByte("scope" , scope); 1302e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.setData(data); 1303e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1304e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1305e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1306e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void addToPlayListRequestFromNative(byte[] address, byte scope, byte[] uid, int uidCounter) { 1307e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* add to NowPlaying not supported */ 1308e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen Log.w(TAG, "addToPlayListRequestFromNative: not supported! scope=" + scope); 1309e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah addToNowPlayingRspNative(address, AvrcpConstants.RSP_INTERNAL_ERR); 1310e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1311e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1312e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void getTotalNumOfItemsRequestFromNative(byte[] address, byte scope) { 1313e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = new Bundle(); 1314e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_TOTAL_NUM_OF_ITEMS); 1315e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.arg1 = scope; 1316e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = address; 131717675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 131817675906064bb72fdcca75baa56cdf8bb8968d01John Du } 131917675906064bb72fdcca75baa56cdf8bb8968d01John Du 13202e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie private void notifyVolumeChanged(int volume) { 13212e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 13222e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_BLUETOOTH_ABS_VOLUME); 132317675906064bb72fdcca75baa56cdf8bb8968d01John Du } 132417675906064bb72fdcca75baa56cdf8bb8968d01John Du 132517675906064bb72fdcca75baa56cdf8bb8968d01John Du private int convertToAudioStreamVolume(int volume) { 132617675906064bb72fdcca75baa56cdf8bb8968d01John Du // Rescale volume to match AudioSystem's volume 132711798b011c962b602217b479130d413f3b30f19aLiejun Tao return (int) Math.floor((double) volume*mAudioStreamMax/AVRCP_MAX_VOL); 132817675906064bb72fdcca75baa56cdf8bb8968d01John Du } 132917675906064bb72fdcca75baa56cdf8bb8968d01John Du 133017675906064bb72fdcca75baa56cdf8bb8968d01John Du private int convertToAvrcpVolume(int volume) { 13312e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie return (int) Math.ceil((double) volume*AVRCP_MAX_VOL/mAudioStreamMax); 133217675906064bb72fdcca75baa56cdf8bb8968d01John Du } 133317675906064bb72fdcca75baa56cdf8bb8968d01John Du 133411798b011c962b602217b479130d413f3b30f19aLiejun Tao private void blackListCurrentDevice() { 133511798b011c962b602217b479130d413f3b30f19aLiejun Tao mFeatures &= ~BTRC_FEAT_ABSOLUTE_VOLUME; 133611798b011c962b602217b479130d413f3b30f19aLiejun Tao mAudioManager.avrcpSupportsAbsoluteVolume(mAddress, isAbsoluteVolumeSupported()); 133711798b011c962b602217b479130d413f3b30f19aLiejun Tao 133811798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences pref = mContext.getSharedPreferences(ABSOLUTE_VOLUME_BLACKLIST, 133911798b011c962b602217b479130d413f3b30f19aLiejun Tao Context.MODE_PRIVATE); 134011798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences.Editor editor = pref.edit(); 134111798b011c962b602217b479130d413f3b30f19aLiejun Tao editor.putBoolean(mAddress, true); 13427eeb95b6f29a6f55e117e329468168d4bcbec0c8Jack He editor.apply(); 134311798b011c962b602217b479130d413f3b30f19aLiejun Tao } 134411798b011c962b602217b479130d413f3b30f19aLiejun Tao 134511798b011c962b602217b479130d413f3b30f19aLiejun Tao private int modifyRcFeatureFromBlacklist(int feature, String address) { 134611798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences pref = mContext.getSharedPreferences(ABSOLUTE_VOLUME_BLACKLIST, 134711798b011c962b602217b479130d413f3b30f19aLiejun Tao Context.MODE_PRIVATE); 134811798b011c962b602217b479130d413f3b30f19aLiejun Tao if (!pref.contains(address)) { 134911798b011c962b602217b479130d413f3b30f19aLiejun Tao return feature; 135011798b011c962b602217b479130d413f3b30f19aLiejun Tao } 135111798b011c962b602217b479130d413f3b30f19aLiejun Tao if (pref.getBoolean(address, false)) { 135211798b011c962b602217b479130d413f3b30f19aLiejun Tao feature &= ~BTRC_FEAT_ABSOLUTE_VOLUME; 135311798b011c962b602217b479130d413f3b30f19aLiejun Tao } 135411798b011c962b602217b479130d413f3b30f19aLiejun Tao return feature; 135511798b011c962b602217b479130d413f3b30f19aLiejun Tao } 135611798b011c962b602217b479130d413f3b30f19aLiejun Tao 135711798b011c962b602217b479130d413f3b30f19aLiejun Tao public void resetBlackList(String address) { 135811798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences pref = mContext.getSharedPreferences(ABSOLUTE_VOLUME_BLACKLIST, 135911798b011c962b602217b479130d413f3b30f19aLiejun Tao Context.MODE_PRIVATE); 136011798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences.Editor editor = pref.edit(); 136111798b011c962b602217b479130d413f3b30f19aLiejun Tao editor.remove(address); 13627eeb95b6f29a6f55e117e329468168d4bcbec0c8Jack He editor.apply(); 136311798b011c962b602217b479130d413f3b30f19aLiejun Tao } 136411798b011c962b602217b479130d413f3b30f19aLiejun Tao 1365188f205b5f093850d4cc627917a21204be36c56aZhihai Xu /** 1366188f205b5f093850d4cc627917a21204be36c56aZhihai Xu * This is called from A2dpStateMachine to set A2dp audio state. 1367188f205b5f093850d4cc627917a21204be36c56aZhihai Xu */ 1368188f205b5f093850d4cc627917a21204be36c56aZhihai Xu public void setA2dpAudioState(int state) { 1369e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_SET_A2DP_AUDIO_STATE, state, 0); 1370188f205b5f093850d4cc627917a21204be36c56aZhihai Xu mHandler.sendMessage(msg); 1371188f205b5f093850d4cc627917a21204be36c56aZhihai Xu } 1372188f205b5f093850d4cc627917a21204be36c56aZhihai Xu 13730427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker private class AvrcpServiceBootReceiver extends BroadcastReceiver { 13740427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker @Override 13750427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker public void onReceive(Context context, Intent intent) { 13760427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker String action = intent.getAction(); 13770427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker if (action.equals(Intent.ACTION_BOOT_COMPLETED)) { 13780427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker if (DEBUG) Log.d(TAG, "Boot completed, initializing player lists"); 13790427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker /* initializing media player's list */ 1380be66a1bf5584a2a7985666ab20c5e9b54053e17dMarie Janssen mBrowsableListBuilder.start(); 13810427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker } 13820427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker } 13830427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker } 13840427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker 1385e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private class AvrcpServiceBroadcastReceiver extends BroadcastReceiver { 1386e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah @Override 1387e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void onReceive(Context context, Intent intent) { 1388e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String action = intent.getAction(); 1389e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "AvrcpServiceBroadcastReceiver-> Action: " + action); 1390e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1391e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (action.equals(Intent.ACTION_PACKAGE_REMOVED) 1392e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah || action.equals(Intent.ACTION_PACKAGE_DATA_CLEARED)) { 1393e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { 1394e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // a package is being removed, not replaced 1395e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String packageName = intent.getData().getSchemeSpecificPart(); 1396e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (packageName != null) { 1397e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handlePackageModified(packageName, true); 1398e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1399e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1400e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1401e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else if (action.equals(Intent.ACTION_PACKAGE_ADDED) 1402e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah || action.equals(Intent.ACTION_PACKAGE_CHANGED)) { 1403e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String packageName = intent.getData().getSchemeSpecificPart(); 1404e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG,"AvrcpServiceBroadcastReceiver-> packageName: " 1405e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + packageName); 1406e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (packageName != null) { 1407e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handlePackageModified(packageName, false); 1408e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1409e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1410e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1411838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood } 1412838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood 1413e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handlePackageModified(String packageName, boolean removed) { 1414e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "packageName: " + packageName + " removed: " + removed); 1415c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1416e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (removed) { 1417384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen removeMediaPlayerInfo(packageName); 1418e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // old package is removed, updating local browsable player's list 1419e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (isBrowseSupported(packageName)) { 1420e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah removePackageFromBrowseList(packageName); 1421e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1422e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 1423e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // new package has been added. 1424e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (isBrowsableListUpdated(packageName)) { 1425e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // Rebuilding browsable players list 1426be66a1bf5584a2a7985666ab20c5e9b54053e17dMarie Janssen mBrowsableListBuilder.start(); 1427e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1428e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1429e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1430c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1431e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean isBrowsableListUpdated(String newPackageName) { 1432e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // getting the browsable media players list from package manager 1433e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Intent intent = new Intent("android.media.browse.MediaBrowserService"); 14340427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker List<ResolveInfo> resInfos = mPackageManager.queryIntentServices(intent, 14350427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker PackageManager.MATCH_ALL); 1436e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah for (ResolveInfo resolveInfo : resInfos) { 14373843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen if (resolveInfo.serviceInfo.packageName.equals(newPackageName)) { 14383843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen if (DEBUG) 14393843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen Log.d(TAG, 14403843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen "isBrowsableListUpdated: package includes MediaBrowserService, true"); 14413843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen return true; 14423843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen } 1443e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1444c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 14453843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen // if list has different size 14463843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen if (resInfos.size() != mBrowsePlayerInfoList.size()) { 14473843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen if (DEBUG) Log.d(TAG, "isBrowsableListUpdated: browsable list size mismatch, true"); 14483843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen return true; 1449e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 14503843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen 14513843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen Log.d(TAG, "isBrowsableListUpdated: false"); 14523843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen return false; 1453e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1454e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1455511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private void removePackageFromBrowseList(String packageName) { 1456e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "removePackageFromBrowseList: " + packageName); 1457511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mBrowsePlayerInfoList) { 1458511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int browseInfoID = getBrowseId(packageName); 1459511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (browseInfoID != -1) { 1460511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mBrowsePlayerInfoList.remove(browseInfoID); 1461511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1462e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1463e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1464e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1465e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* 1466e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * utility function to get the browse player index from global browsable 1467e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * list. It may return -1 if specified package name is not in the list. 1468e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 1469511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private int getBrowseId(String packageName) { 1470e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah boolean response = false; 1471e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int browseInfoID = 0; 1472511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mBrowsePlayerInfoList) { 1473511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (BrowsePlayerInfo info : mBrowsePlayerInfoList) { 1474511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (info.packageName.equals(packageName)) { 1475511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen response = true; 1476511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen break; 1477511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1478511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen browseInfoID++; 1479e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1480e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1481e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1482e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!response) { 1483e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah browseInfoID = -1; 1484e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1485e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1486e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "getBrowseId for packageName: " + packageName + 1487e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah " , browseInfoID: " + browseInfoID); 1488e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return browseInfoID; 1489e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1490e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1491e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void setAddressedPlayer(byte[] bdaddr, int selectedId) { 1492eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen String functionTag = "setAddressedPlayer(" + selectedId + "): "; 1493e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1494511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 1495511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (mMediaPlayerInfoList.isEmpty()) { 1496eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen Log.w(TAG, functionTag + "no players, send no available players"); 1497eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen setAddressedPlayerRspNative(bdaddr, AvrcpConstants.RSP_NO_AVBL_PLAY); 1498eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen return; 1499eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen } 1500eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen if (!mMediaPlayerInfoList.containsKey(selectedId)) { 1501eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen Log.w(TAG, functionTag + "invalid id, sending response back "); 1502eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen setAddressedPlayerRspNative(bdaddr, AvrcpConstants.RSP_INV_PLAYER); 1503eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen return; 1504eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen } 1505eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen 1506eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen if (isPlayerAlreadyAddressed(selectedId)) { 1507511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen MediaPlayerInfo info = getAddressedPlayerInfo(); 1508eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen Log.i(TAG, functionTag + "player already addressed: " + info); 1509eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen setAddressedPlayerRspNative(bdaddr, AvrcpConstants.RSP_NO_ERROR); 1510eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen return; 1511eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen } 1512eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen // register new Media Controller Callback and update the current IDs 1513eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen if (!updateCurrentController(selectedId, mCurrBrowsePlayerID)) { 1514eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen Log.e(TAG, functionTag + "updateCurrentController failed!"); 1515eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen setAddressedPlayerRspNative(bdaddr, AvrcpConstants.RSP_INTERNAL_ERR); 1516eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen return; 1517eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen } 1518eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen // If we don't have a controller, try to launch the player 1519eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen MediaPlayerInfo info = getAddressedPlayerInfo(); 1520eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen if (info.getMediaController() == null) { 1521eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen Intent launch = mPackageManager.getLaunchIntentForPackage(info.getPackageName()); 1522eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen Log.i(TAG, functionTag + "launching player " + launch); 1523eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen mContext.startActivity(launch); 1524e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1525e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1526eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen setAddressedPlayerRspNative(bdaddr, AvrcpConstants.RSP_NO_ERROR); 1527e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1528e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1529e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void setBrowsedPlayer(byte[] bdaddr, int selectedId) { 1530e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int status = AvrcpConstants.RSP_NO_ERROR; 1531e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1532e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // checking for error cases 1533511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (mMediaPlayerInfoList.isEmpty()) { 1534e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah status = AvrcpConstants.RSP_NO_AVBL_PLAY; 1535e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, " No Available Players to set, sending response back "); 1536e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 1537e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // update current browse player id and start browsing service 1538e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah updateNewIds(mCurrAddrPlayerID, selectedId); 1539e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String browsedPackage = getPackageName(selectedId); 1540e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1541e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!isPackageNameValid(browsedPackage)) { 1542e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, " Invalid package for id:" + mCurrBrowsePlayerID); 1543e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah status = AvrcpConstants.RSP_INV_PLAYER; 1544e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else if (!isBrowseSupported(browsedPackage)) { 1545e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, "Browse unsupported for id:" + mCurrBrowsePlayerID 1546e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + ", packagename : " + browsedPackage); 1547e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah status = AvrcpConstants.RSP_PLAY_NOT_BROW; 1548e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else if (!startBrowseService(bdaddr, browsedPackage)) { 1549e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "service cannot be started for browse player id:" + mCurrBrowsePlayerID 1550e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + ", packagename : " + browsedPackage); 1551e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah status = AvrcpConstants.RSP_INTERNAL_ERR; 1552e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1553e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1554e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1555e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (status != AvrcpConstants.RSP_NO_ERROR) { 1556e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah setBrowsedPlayerRspNative(bdaddr, status, (byte) 0x00, 0, null); 1557e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1558e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1559e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "setBrowsedPlayer for selectedId: " + selectedId + 1560e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah " , status: " + status); 1561e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1562e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 156305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private MediaSessionManager.OnActiveSessionsChangedListener mActiveSessionListener = 156405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen new MediaSessionManager.OnActiveSessionsChangedListener() { 1565e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 156605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen @Override 156705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public void onActiveSessionsChanged( 156805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen List<android.media.session.MediaController> newControllers) { 156905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen boolean playersChanged = false; 157005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 157105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen // Update the current players 157205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen for (android.media.session.MediaController controller : newControllers) { 157305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen addMediaPlayerController(controller); 157405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen playersChanged = true; 1575eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1576d996f17ea97b2c592338bcfbc93056d0224da1cdAjay Panicker 157705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (playersChanged) { 157805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mHandler.sendEmptyMessage(MSG_AVAILABLE_PLAYERS_CHANGED_RSP); 1579384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen if (newControllers.size() > 0 && getAddressedPlayerInfo() == null) { 158005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (DEBUG) 158105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.v(TAG, 158205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen "No addressed player but active sessions, taking first."); 158305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen setAddressedMediaSessionPackage(newControllers.get(0).getPackageName()); 1584eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1585eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1586e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 158705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen }; 158805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 158978d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen private void setAddressedMediaSessionPackage(@Nullable String packageName) { 159041527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen if (packageName == null) { 159141527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen // Should only happen when there's no media players, reset to no available player. 159241527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen updateCurrentController(0, mCurrBrowsePlayerID); 159341527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen return; 159441527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen } 159505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen // No change. 159605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (getPackageName(mCurrAddrPlayerID).equals(packageName)) return; 159778d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen if (DEBUG) Log.v(TAG, "Changing addressed media session to " + packageName); 159805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen // If the player doesn't exist, we need to add it. 159905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (getMediaPlayerInfo(packageName) == null) { 160005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen addMediaPlayerPackage(packageName); 160105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mHandler.sendEmptyMessage(MSG_AVAILABLE_PLAYERS_CHANGED_RSP); 160205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 1603511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 1604511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) { 1605511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (entry.getValue().getPackageName().equals(packageName)) { 1606511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int newAddrID = entry.getKey(); 1607511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.v(TAG, "Set addressed #" + newAddrID + " " + entry.getValue()); 1608511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen updateCurrentController(newAddrID, mCurrBrowsePlayerID); 1609511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mHandler.obtainMessage(MSG_ADDRESSED_PLAYER_CHANGED_RSP, newAddrID, 0) 1610511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen .sendToTarget(); 1611511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return; 1612511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1613e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1614e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 161505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen // We shouldn't ever get here. 161605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.e(TAG, "Player info for " + packageName + " doesn't exist!"); 161705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 1618e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 161905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private void setActiveMediaSession(MediaSession.Token token) { 162005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen android.media.session.MediaController activeController = 162105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen new android.media.session.MediaController(mContext, token); 162205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (DEBUG) Log.v(TAG, "Set active media session " + activeController.getPackageName()); 162305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen addMediaPlayerController(activeController); 162405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen setAddressedMediaSessionPackage(activeController.getPackageName()); 162505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 1626e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1627e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean startBrowseService(byte[] bdaddr, String packageName) { 1628e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah boolean status = true; 1629e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1630e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* creating new instance for Browse Media Player */ 1631e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String browseService = getBrowseServiceName(packageName); 1632e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!browseService.isEmpty()) { 1633e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr).setBrowsed( 1634e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah packageName, browseService); 1635e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 1636e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, "No Browser service available for " + packageName); 1637e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah status = false; 1638e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1639e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1640e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "startBrowseService for packageName: " + packageName + 1641e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ", status = " + status); 1642e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return status; 1643e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1644e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1645511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private String getBrowseServiceName(String packageName) { 1646e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String browseServiceName = ""; 1647e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1648e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // getting the browse service name from browse player info 1649511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mBrowsePlayerInfoList) { 1650511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int browseInfoID = getBrowseId(packageName); 1651511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (browseInfoID != -1) { 1652511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen browseServiceName = mBrowsePlayerInfoList.get(browseInfoID).serviceClass; 1653511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1654e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1655e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1656e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "getBrowseServiceName for packageName: " + packageName + 1657e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ", browseServiceName = " + browseServiceName); 1658e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return browseServiceName; 1659e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1660e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 16613843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen private class BrowsablePlayerListBuilder extends MediaBrowser.ConnectionCallback { 16623843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen List<ResolveInfo> mWaiting; 16633843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen BrowsePlayerInfo mCurrentPlayer; 16643843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen MediaBrowser mCurrentBrowser; 1665eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen boolean mPlayersChanged; 1666e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 16673843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen public BrowsablePlayerListBuilder() {} 1668e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 16693843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen public void start() { 16703843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen mBrowsePlayerInfoList.clear(); 1671be66a1bf5584a2a7985666ab20c5e9b54053e17dMarie Janssen cleanup(); 16723843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen Intent intent = new Intent(android.service.media.MediaBrowserService.SERVICE_INTERFACE); 16733843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen mWaiting = mPackageManager.queryIntentServices(intent, PackageManager.MATCH_ALL); 16743843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen connectNextPlayer(); 16753843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen } 1676e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1677be66a1bf5584a2a7985666ab20c5e9b54053e17dMarie Janssen public void cleanup() { 1678be66a1bf5584a2a7985666ab20c5e9b54053e17dMarie Janssen if (mWaiting != null) mWaiting.clear(); 1679be66a1bf5584a2a7985666ab20c5e9b54053e17dMarie Janssen mPlayersChanged = false; 1680be66a1bf5584a2a7985666ab20c5e9b54053e17dMarie Janssen if (mCurrentBrowser != null) mCurrentBrowser.disconnect(); 1681be66a1bf5584a2a7985666ab20c5e9b54053e17dMarie Janssen } 1682be66a1bf5584a2a7985666ab20c5e9b54053e17dMarie Janssen 16833843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen private void connectNextPlayer() { 16843843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen if (mWaiting.isEmpty()) { 1685eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen // Done. Send players changed if needed. 1686eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen if (mPlayersChanged) { 1687eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen registerNotificationRspAvalPlayerChangedNative( 1688eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen AvrcpConstants.NOTIFICATION_TYPE_CHANGED); 1689eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 16903843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen return; 16913843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen } 16923843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen ResolveInfo info = mWaiting.remove(0); 16933843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen String displayableName = info.loadLabel(mPackageManager).toString(); 16943843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen String serviceName = info.serviceInfo.name; 16953843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen String packageName = info.serviceInfo.packageName; 1696e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 16973843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen mCurrentPlayer = new BrowsePlayerInfo(packageName, displayableName, serviceName); 16983843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen mCurrentBrowser = new MediaBrowser( 16993843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen mContext, new ComponentName(packageName, serviceName), this, null); 17003843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen if (DEBUG) Log.d(TAG, "Trying to connect to " + serviceName); 17013843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen mCurrentBrowser.connect(); 17023843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen } 17033843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen 17043843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen @Override 17053843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen public void onConnected() { 17063843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen Log.d(TAG, "BrowsablePlayerListBuilder: " + mCurrentPlayer.packageName + " OK"); 1707be66a1bf5584a2a7985666ab20c5e9b54053e17dMarie Janssen mCurrentBrowser.disconnect(); 1708be66a1bf5584a2a7985666ab20c5e9b54053e17dMarie Janssen mCurrentBrowser = null; 17093843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen mBrowsePlayerInfoList.add(mCurrentPlayer); 1710eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen MediaPlayerInfo info = getMediaPlayerInfo(mCurrentPlayer.packageName); 17115146bd27869df5473aa53e6271266f51733971efMarie Janssen MediaController controller = (info == null) ? null : info.getMediaController(); 17125146bd27869df5473aa53e6271266f51733971efMarie Janssen // Refresh the media player entry so it notices we can browse 17135146bd27869df5473aa53e6271266f51733971efMarie Janssen if (controller != null) { 17145146bd27869df5473aa53e6271266f51733971efMarie Janssen addMediaPlayerController(controller.getWrappedInstance()); 1715eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } else { 171605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen addMediaPlayerPackage(mCurrentPlayer.packageName); 1717eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1718eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen mPlayersChanged = true; 17193843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen connectNextPlayer(); 17203843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen } 17213843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen 17223843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen @Override 17233843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen public void onConnectionFailed() { 17243843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen Log.d(TAG, "BrowsablePlayerListBuilder: " + mCurrentPlayer.packageName + " FAIL"); 17253843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen connectNextPlayer(); 1726e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1727e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1728e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 172905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen /* Initializes list of media players identified from session manager active sessions */ 1730511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private void initMediaPlayersList() { 1731511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 1732511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen // Clearing old browsable player's list 1733511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mMediaPlayerInfoList.clear(); 173405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 1735511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (mMediaSessionManager == null) { 1736511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.w(TAG, "initMediaPlayersList: no media session manager!"); 1737511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return; 1738511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 173905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 1740511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen List<android.media.session.MediaController> controllers = 1741511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mMediaSessionManager.getActiveSessions(null); 1742511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) 1743511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen Log.v(TAG, "initMediaPlayerInfoList: " + controllers.size() + " controllers"); 1744511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen /* Initializing all media players */ 1745511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (android.media.session.MediaController controller : controllers) { 1746511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen addMediaPlayerController(controller); 1747511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1748511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (controllers.size() > 0) { 1749511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mHandler.sendEmptyMessage(MSG_AVAILABLE_PLAYERS_CHANGED_RSP); 1750511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1751e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1752511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (mMediaPlayerInfoList.size() > 0) { 1753511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen // Set the first one as the Addressed Player 1754511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen updateCurrentController(mMediaPlayerInfoList.firstKey(), -1); 1755511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1756e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1757e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1758e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1759eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen private List<android.media.session.MediaController> getMediaControllers() { 1760eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen List<android.media.session.MediaController> controllers = 1761eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen new ArrayList<android.media.session.MediaController>(); 1762511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 1763511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (MediaPlayerInfo info : mMediaPlayerInfoList.values()) { 1764a1e42e29b15323e1a4d0559235a0987200663b2fMarie Janssen MediaController controller = info.getMediaController(); 1765a1e42e29b15323e1a4d0559235a0987200663b2fMarie Janssen if (controller != null) { 1766a1e42e29b15323e1a4d0559235a0987200663b2fMarie Janssen controllers.add(controller.getWrappedInstance()); 1767511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1768eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1769eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1770eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen return controllers; 1771eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1772eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 1773eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen /** Add (or update) a player to the media player list without a controller */ 1774511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private boolean addMediaPlayerPackage(String packageName) { 1775eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen MediaPlayerInfo info = new MediaPlayerInfo(null, AvrcpConstants.PLAYER_TYPE_AUDIO, 1776eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen AvrcpConstants.PLAYER_SUBTYPE_NONE, getPlayStateBytes(null), 1777b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen getFeatureBitMask(packageName), packageName, getAppLabel(packageName)); 177805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return addMediaPlayerInfo(info); 1779eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1780eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 1781eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen /** Add (or update) a player to the media player list given an active controller */ 1782511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private boolean addMediaPlayerController(android.media.session.MediaController controller) { 1783eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen String packageName = controller.getPackageName(); 1784eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen MediaPlayerInfo info = new MediaPlayerInfo(MediaController.wrap(controller), 1785eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen AvrcpConstants.PLAYER_TYPE_AUDIO, AvrcpConstants.PLAYER_SUBTYPE_NONE, 1786eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen getPlayStateBytes(controller.getPlaybackState()), getFeatureBitMask(packageName), 1787b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen controller.getPackageName(), getAppLabel(packageName)); 178805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return addMediaPlayerInfo(info); 1789eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1790eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 179105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen /** Add or update a player to the media player list given the MediaPlayerInfo object. 179205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen * @return true if an item was updated, false if it was added instead 179305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen */ 1794511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private boolean addMediaPlayerInfo(MediaPlayerInfo info) { 1795b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen int updateId = -1; 179605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen boolean updated = false; 1797511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 1798511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) { 1799511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (info.getPackageName().equals(entry.getValue().getPackageName())) { 1800511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen updateId = entry.getKey(); 1801511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen updated = true; 1802511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen break; 1803511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1804b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen } 1805511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (updateId == -1) { 1806511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen // New player 1807511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mLastUsedPlayerID++; 1808511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen updateId = mLastUsedPlayerID; 1809511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1810511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mMediaPlayerInfoList.put(updateId, info); 1811384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen if (DEBUG) 1812384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen Log.d(TAG, (updated ? "update #" : "add #") + updateId + ":" + info.toString()); 1813384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen if (updateId == mCurrAddrPlayerID) { 1814384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen updateCurrentController(mCurrAddrPlayerID, mCurrBrowsePlayerID); 1815384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } 1816b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen } 181705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return updated; 1818eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1819eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 1820eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen /** Remove all players related to |packageName| from the media player info list */ 1821511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private MediaPlayerInfo removeMediaPlayerInfo(String packageName) { 1822511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 1823511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int removeKey = -1; 1824511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) { 1825511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (entry.getValue().getPackageName().equals(packageName)) { 1826511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen removeKey = entry.getKey(); 1827511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen break; 1828511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1829511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1830511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (removeKey != -1) { 1831384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen if (DEBUG) 1832384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen Log.d(TAG, "remove #" + removeKey + ":" + mMediaPlayerInfoList.get(removeKey)); 1833511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return mMediaPlayerInfoList.remove(removeKey); 1834eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1835b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen 1836511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return null; 1837511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1838eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1839eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 1840384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen /** Remove the controller referenced by |controller| from any player in the list */ 1841f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen private void removeMediaController(@Nullable android.media.session.MediaController controller) { 1842f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen if (controller == null) return; 1843384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen synchronized (mMediaPlayerInfoList) { 1844f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) { 1845f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen MediaPlayerInfo info = entry.getValue(); 1846a1e42e29b15323e1a4d0559235a0987200663b2fMarie Janssen MediaController c = info.getMediaController(); 1847f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen if (c != null && c.equals(controller)) { 1848f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen info.setMediaController(null); 1849f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen if (entry.getKey() == mCurrAddrPlayerID) { 1850f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen updateCurrentController(mCurrAddrPlayerID, mCurrBrowsePlayerID); 1851f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen } 1852f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen } 1853384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } 1854384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } 1855384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } 1856384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen 1857e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* 1858e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * utility function to get the playback state of any media player through 1859e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * media controller APIs. 1860e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 1861eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen private byte getPlayStateBytes(PlaybackState pbState) { 1862e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte playStateBytes = PLAYSTATUS_STOPPED; 1863e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1864e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (pbState != null) { 1865e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah playStateBytes = (byte)convertPlayStateToBytes(pbState.getState()); 1866e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.v(TAG, "getPlayBackState: playStateBytes = " + playStateBytes); 1867e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 1868e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, "playState object null, sending playStateBytes = " + playStateBytes); 1869e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1870e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1871e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return playStateBytes; 1872e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1873e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1874e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* 1875e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * utility function to map framework's play state values to AVRCP spec 1876e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * defined play status values 1877e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 1878e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private int convertPlayStateToBytes(int playState) { 1879e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah switch (playState) { 1880e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_PLAYING: 1881e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_BUFFERING: 1882e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_PLAYING; 1883e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1884e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_STOPPED: 1885e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_NONE: 1886e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_CONNECTING: 1887e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_STOPPED; 1888e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1889e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_PAUSED: 1890e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_PAUSED; 1891e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1892e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_FAST_FORWARDING: 1893e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_SKIPPING_TO_NEXT: 1894e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_SKIPPING_TO_QUEUE_ITEM: 1895e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_FWD_SEEK; 1896e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1897e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_REWINDING: 1898e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_SKIPPING_TO_PREVIOUS: 1899e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_REV_SEEK; 1900e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1901e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_ERROR: 1902e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah default: 1903e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_ERROR; 1904e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1905e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1906e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1907e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* 1908e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * utility function to get the feature bit mask of any media player through 1909e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * package name 1910e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 1911e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private short[] getFeatureBitMask(String packageName) { 1912e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1913e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ArrayList<Short> featureBitsList = new ArrayList<Short>(); 1914e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1915e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* adding default feature bits */ 1916e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_PLAY_BIT_NO); 1917e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_STOP_BIT_NO); 1918e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_PAUSE_BIT_NO); 1919e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_REWIND_BIT_NO); 1920e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_FAST_FWD_BIT_NO); 1921e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_FORWARD_BIT_NO); 1922e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_BACKWARD_BIT_NO); 1923e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_ADV_CTRL_BIT_NO); 1924e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1925e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Add/Modify browse player supported features. */ 1926e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (isBrowseSupported(packageName)) { 1927e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_BROWSE_BIT_NO); 1928e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_UID_UNIQUE_BIT_NO); 1929e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_NOW_PLAY_BIT_NO); 1930e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_GET_NUM_OF_ITEMS_BIT_NO); 1931e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1932e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1933e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // converting arraylist to array for response 1934e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah short[] featureBitsArray = new short[featureBitsList.size()]; 1935e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1936e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah for (int i = 0; i < featureBitsList.size(); i++) { 1937e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsArray[i] = featureBitsList.get(i).shortValue(); 1938e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1939e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1940e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return featureBitsArray; 1941e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1942e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1943e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /** 1944e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * Checks the Package name if it supports Browsing or not. 1945e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * 1946e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * @param packageName - name of the package to get the Id. 1947e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * @return true if it supports browsing, else false. 1948e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 1949511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private boolean isBrowseSupported(String packageName) { 1950511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mBrowsePlayerInfoList) { 1951511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen /* check if Browsable Player's list contains this package name */ 1952511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (BrowsePlayerInfo info : mBrowsePlayerInfoList) { 1953511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (info.packageName.equals(packageName)) { 1954511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.v(TAG, "isBrowseSupported for " + packageName + ": true"); 1955511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return true; 1956511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1957e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1958e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1959e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1960b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen if (DEBUG) Log.v(TAG, "isBrowseSupported for " + packageName + ": false"); 19611b70ec148be773651d5ad00e3ce0d28b3a63306dAjay Panicker return false; 1962e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1963e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1964e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private String getPackageName(int id) { 1965511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen MediaPlayerInfo player = null; 1966511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 1967511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen player = mMediaPlayerInfoList.getOrDefault(id, null); 1968511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1969e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1970eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen if (player == null) { 1971eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen Log.w(TAG, "No package name for player (" + id + " not valid)"); 1972eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen return ""; 1973e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1974eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 1975eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen String packageName = player.getPackageName(); 1976eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen if (DEBUG) Log.v(TAG, "Player " + id + " package: " + packageName); 1977e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return packageName; 1978e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1979e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1980e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* from the global object, getting the current browsed player's package name */ 1981e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private String getCurrentBrowsedPlayer(byte[] bdaddr) { 1982e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String browsedPlayerPackage = ""; 1983e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1984e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Map<String, BrowsedMediaPlayer> connList = mAvrcpBrowseManager.getConnList(); 1985e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String bdaddrStr = new String(bdaddr); 1986e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if(connList.containsKey(bdaddrStr)){ 1987e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah browsedPlayerPackage = connList.get(bdaddrStr).getPackageName(); 1988e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1989e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "getCurrentBrowsedPlayerPackage: " + browsedPlayerPackage); 1990e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return browsedPlayerPackage; 1991e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1992e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1993eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen /* Returns the MediaPlayerInfo for the currently addressed media player */ 1994511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private MediaPlayerInfo getAddressedPlayerInfo() { 1995511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 1996511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return mMediaPlayerInfoList.getOrDefault(mCurrAddrPlayerID, null); 1997511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1998e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1999e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2000e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* 2001e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * Utility function to get the Media player info from package name returns 2002e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * null if package name not found in media players list 2003e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 2004511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private MediaPlayerInfo getMediaPlayerInfo(String packageName) { 2005511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 2006511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (mMediaPlayerInfoList.isEmpty()) { 2007511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.v(TAG, "getMediaPlayerInfo: Media players list empty"); 2008511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return null; 2009511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2010eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 2011511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (MediaPlayerInfo info : mMediaPlayerInfoList.values()) { 2012511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (packageName.equals(info.getPackageName())) { 2013511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.v(TAG, "getMediaPlayerInfo: Found " + packageName); 2014511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return info; 2015511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2016e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2017511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.w(TAG, "getMediaPlayerInfo: " + packageName + " not found"); 2018511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return null; 2019e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2020e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2021e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2022e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* prepare media list & return the media player list response object */ 2023511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private MediaPlayerListRsp prepareMediaPlayerRspObj() { 2024511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 2025511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int numPlayers = mMediaPlayerInfoList.size(); 2026511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen 2027511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int[] playerIds = new int[numPlayers]; 2028511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen byte[] playerTypes = new byte[numPlayers]; 2029511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int[] playerSubTypes = new int[numPlayers]; 2030511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen String[] displayableNameArray = new String[numPlayers]; 2031511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen byte[] playStatusValues = new byte[numPlayers]; 2032511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen short[] featureBitMaskValues = 2033511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen new short[numPlayers * AvrcpConstants.AVRC_FEATURE_MASK_SIZE]; 2034511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen 2035511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int players = 0; 2036511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) { 2037511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen MediaPlayerInfo info = entry.getValue(); 2038511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen playerIds[players] = entry.getKey(); 2039511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen playerTypes[players] = info.getMajorType(); 2040511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen playerSubTypes[players] = info.getSubType(); 2041511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen displayableNameArray[players] = info.getDisplayableName(); 2042511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen playStatusValues[players] = info.getPlayStatus(); 2043511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen 2044511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen short[] featureBits = info.getFeatureBitMask(); 2045511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (int numBit = 0; numBit < featureBits.length; numBit++) { 2046511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen /* gives which octet this belongs to */ 2047511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen byte octet = (byte) (featureBits[numBit] / 8); 2048511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen /* gives the bit position within the octet */ 2049511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen byte bit = (byte) (featureBits[numBit] % 8); 2050511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen featureBitMaskValues[(players * AvrcpConstants.AVRC_FEATURE_MASK_SIZE) 2051511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen + octet] |= (1 << bit); 2052511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2053e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2054511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen /* printLogs */ 2055511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) { 2056511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen Log.d(TAG, "Player " + playerIds[players] + ": " + displayableNameArray[players] 2057511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen + " type: " + playerTypes[players] + ", " 2058511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen + playerSubTypes[players] + " status: " 2059511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen + playStatusValues[players]); 2060511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2061e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2062511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen players++; 2063511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2064e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2065511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.d(TAG, "prepareMediaPlayerRspObj: numPlayers = " + numPlayers); 2066e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2067511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return new MediaPlayerListRsp(AvrcpConstants.RSP_NO_ERROR, sUIDCounter, numPlayers, 2068511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen AvrcpConstants.BTRC_ITEM_PLAYER, playerIds, playerTypes, playerSubTypes, 2069511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen playStatusValues, featureBitMaskValues, displayableNameArray); 2070511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2071e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2072e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2073e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* build media player list and send it to remote. */ 2074e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handleMediaPlayerListRsp(AvrcpCmd.FolderItemsCmd folderObj) { 2075511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen MediaPlayerListRsp rspObj = null; 2076511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 2077511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int numPlayers = mMediaPlayerInfoList.size(); 2078511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (numPlayers == 0) { 2079511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mediaPlayerListRspNative(folderObj.mAddress, AvrcpConstants.RSP_NO_AVBL_PLAY, 2080511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen (short) 0, (byte) 0, 0, null, null, null, null, null, null); 2081511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return; 2082511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2083511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (folderObj.mStartItem >= numPlayers) { 2084511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen Log.i(TAG, "handleMediaPlayerListRsp: start = " + folderObj.mStartItem 2085511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen + " > num of items = " + numPlayers); 2086511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mediaPlayerListRspNative(folderObj.mAddress, AvrcpConstants.RSP_INV_RANGE, 2087511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen (short) 0, (byte) 0, 0, null, null, null, null, null, null); 2088511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return; 2089511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2090511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen rspObj = prepareMediaPlayerRspObj(); 2091e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2092511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.d(TAG, "handleMediaPlayerListRsp: sending " + rspObj.mNumItems + " players"); 2093eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen mediaPlayerListRspNative(folderObj.mAddress, rspObj.mStatus, rspObj.mUIDCounter, 2094eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen rspObj.itemType, rspObj.mNumItems, rspObj.mPlayerIds, rspObj.mPlayerTypes, 2095eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen rspObj.mPlayerSubTypes, rspObj.mPlayStatusValues, rspObj.mFeatureBitMaskValues, 2096eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen rspObj.mPlayerNameList); 2097e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2098e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2099e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* unregister to the old controller, update new IDs and register to the new controller */ 2100e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean updateCurrentController(int addrId, int browseId) { 2101e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah boolean registerRsp = true; 2102e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2103e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah updateNewIds(addrId, browseId); 2104e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2105eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen MediaController newController = null; 2106eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen MediaPlayerInfo info = getAddressedPlayerInfo(); 210778d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen if (info != null) newController = info.getMediaController(); 2108eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 2109eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen if (DEBUG) 2110eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen Log.d(TAG, "updateCurrentController: " + mMediaController + " to " + newController); 2111ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen synchronized (this) { 2112ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen if (mMediaController == null || (!mMediaController.equals(newController))) { 2113f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen if (mMediaController != null) { 2114f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen mMediaController.unregisterCallback(mMediaControllerCb); 2115f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen } 2116f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen mMediaController = newController; 2117f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen if (mMediaController != null) { 2118f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen mMediaController.registerCallback(mMediaControllerCb, mHandler); 2119f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen mAddressedMediaPlayer.updateNowPlayingList(mMediaController.getQueue()); 2120f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen } else { 2121f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen mAddressedMediaPlayer.updateNowPlayingList(null); 2122f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen registerRsp = false; 2123f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen } 2124eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 2125e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2126ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen updateCurrentMediaState(); 2127eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen return registerRsp; 2128e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2129e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2130e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Handle getfolderitems for scope = VFS, Search, NowPlayingList */ 2131e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handleGetFolderItemBrowseResponse(AvrcpCmd.FolderItemsCmd folderObj, byte[] bdaddr) { 2132e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int status = AvrcpConstants.RSP_NO_ERROR; 2133e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2134e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Browsed player is already set */ 213505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (folderObj.mScope == AvrcpConstants.BTRC_SCOPE_FILE_SYSTEM) { 213605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr) == null) { 213705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.e(TAG, "handleGetFolderItemBrowseResponse: no browsed player set for " 213805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen + Utils.getAddressStringFromByte(bdaddr)); 213905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen getFolderItemsRspNative(bdaddr, AvrcpConstants.RSP_INTERNAL_ERR, (short) 0, 214005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen (byte) 0x00, 0, null, null, null, null, null, null, null, null); 214105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return; 214205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 214305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr).getFolderItemsVFS(folderObj); 214405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return; 2145e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 214605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (folderObj.mScope == AvrcpConstants.BTRC_SCOPE_NOW_PLAYING) { 214705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mAddressedMediaPlayer.getFolderItemsNowPlaying(bdaddr, folderObj, mMediaController); 214805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return; 2149e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2150e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 215105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen /* invalid scope */ 215205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.e(TAG, "handleGetFolderItemBrowseResponse: unknown scope " + folderObj.mScope); 215305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen getFolderItemsRspNative(bdaddr, AvrcpConstants.RSP_INV_SCOPE, (short) 0, (byte) 0x00, 0, 215405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen null, null, null, null, null, null, null, null); 2155e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2156e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2157e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* utility function to update the global values of current Addressed and browsed player */ 2158511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private void updateNewIds(int addrId, int browseId) { 215978d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen if (DEBUG) 216078d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen Log.v(TAG, "updateNewIds: Addressed:" + mCurrAddrPlayerID + " to " + addrId 216178d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen + ", Browse:" + mCurrBrowsePlayerID + " to " + browseId); 2162e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mCurrAddrPlayerID = addrId; 2163e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mCurrBrowsePlayerID = browseId; 2164e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2165e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2166e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Getting the application's displayable name from package name */ 2167e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private String getAppLabel(String packageName) { 2168e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ApplicationInfo appInfo = null; 2169e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah try { 2170e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah appInfo = mPackageManager.getApplicationInfo(packageName, 0); 2171e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } catch (NameNotFoundException e) { 2172e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah e.printStackTrace(); 2173e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2174e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2175e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return (String) (appInfo != null ? mPackageManager 2176e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah .getApplicationLabel(appInfo) : "Unknown"); 2177e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2178e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2179e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handlePlayItemResponse(byte[] bdaddr, byte[] uid, byte scope) { 2180294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen if (scope == AvrcpConstants.BTRC_SCOPE_NOW_PLAYING) { 2181294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen mAddressedMediaPlayer.playItem(bdaddr, uid, mMediaController); 2182e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2183e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah else { 2184e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if(!isAddrPlayerSameAsBrowsed(bdaddr)) { 2185e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, "Remote requesting play item on uid which may not be recognized by" + 2186e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah "current addressed player"); 2187e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah playItemRspNative(bdaddr, AvrcpConstants.RSP_INV_ITEM); 2188e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2189e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2190e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr) != null) { 2191e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr).playItem(uid, scope); 2192e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2193e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "handlePlayItemResponse: Remote requested playitem " + 2194e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah "before setbrowsedplayer"); 2195e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah playItemRspNative(bdaddr, AvrcpConstants.RSP_INTERNAL_ERR); 2196e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2197e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2198e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2199e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2200e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handleGetItemAttr(AvrcpCmd.ItemAttrCmd itemAttr) { 2201384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen if (itemAttr.mScope == AvrcpConstants.BTRC_SCOPE_NOW_PLAYING) { 2202384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen if (mCurrAddrPlayerID == NO_PLAYER_ID) { 2203384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen getItemAttrRspNative( 2204384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen itemAttr.mAddress, AvrcpConstants.RSP_NO_AVBL_PLAY, (byte) 0, null, null); 2205c1267074b7df0d6e42cefea0ac40b584fdb1430fMarie Janssen return; 2206384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } 2207c1267074b7df0d6e42cefea0ac40b584fdb1430fMarie Janssen mAddressedMediaPlayer.getItemAttr(itemAttr.mAddress, itemAttr, mMediaController); 2208c1267074b7df0d6e42cefea0ac40b584fdb1430fMarie Janssen return; 2209c1267074b7df0d6e42cefea0ac40b584fdb1430fMarie Janssen } 2210c1267074b7df0d6e42cefea0ac40b584fdb1430fMarie Janssen // All other scopes use browsed player 2211c1267074b7df0d6e42cefea0ac40b584fdb1430fMarie Janssen if (mAvrcpBrowseManager.getBrowsedMediaPlayer(itemAttr.mAddress) != null) { 2212c1267074b7df0d6e42cefea0ac40b584fdb1430fMarie Janssen mAvrcpBrowseManager.getBrowsedMediaPlayer(itemAttr.mAddress).getItemAttr(itemAttr); 2213384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } else { 2214c1267074b7df0d6e42cefea0ac40b584fdb1430fMarie Janssen Log.e(TAG, "Could not get attributes. mBrowsedMediaPlayer is null"); 2215c1267074b7df0d6e42cefea0ac40b584fdb1430fMarie Janssen getItemAttrRspNative( 2216c1267074b7df0d6e42cefea0ac40b584fdb1430fMarie Janssen itemAttr.mAddress, AvrcpConstants.RSP_INTERNAL_ERR, (byte) 0, null, null); 2217e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2218e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2219e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2220e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handleGetTotalNumOfItemsResponse(byte[] bdaddr, byte scope) { 2221e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // for scope as media player list 2222e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (scope == AvrcpConstants.BTRC_SCOPE_PLAYER_LIST) { 2223511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int numPlayers = 0; 2224511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 2225511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen numPlayers = mMediaPlayerInfoList.size(); 2226511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2227511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.d(TAG, "handleGetTotalNumOfItemsResponse: " + numPlayers + " players."); 2228511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen getTotalNumOfItemsRspNative(bdaddr, AvrcpConstants.RSP_NO_ERROR, 0, numPlayers); 2229511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } else if (scope == AvrcpConstants.BTRC_SCOPE_NOW_PLAYING) { 2230294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen mAddressedMediaPlayer.getTotalNumOfItems(bdaddr, mMediaController); 2231e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2232e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // for FileSystem browsing scopes as VFS, Now Playing 2233e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr) != null) { 2234e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr).getTotalNumOfItems(scope); 2235e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2236e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "Could not get Total NumOfItems. mBrowsedMediaPlayer is null"); 2237e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah getTotalNumOfItemsRspNative(bdaddr, AvrcpConstants.RSP_INTERNAL_ERR, 0, 0); 2238e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2239e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2240e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2241e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2242e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2243e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* check if browsed player and addressed player are same */ 2244e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean isAddrPlayerSameAsBrowsed(byte[] bdaddr) { 2245e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String browsedPlayer = getCurrentBrowsedPlayer(bdaddr); 2246e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2247e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!isPackageNameValid(browsedPlayer)) { 2248e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, "Browsed player name empty"); 2249eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen return false; 2250e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2251e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2252b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen MediaPlayerInfo info = getAddressedPlayerInfo(); 2253db2d487ba559f0e4de02bc2ad4cc7e275878b2fcMarie Janssen String packageName = (info == null) ? "<none>" : info.getPackageName(); 2254db2d487ba559f0e4de02bc2ad4cc7e275878b2fcMarie Janssen if (info == null || !packageName.equals(browsedPlayer)) { 2255db2d487ba559f0e4de02bc2ad4cc7e275878b2fcMarie Janssen if (DEBUG) Log.d(TAG, browsedPlayer + " is not addressed player " + packageName); 2256eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen return false; 2257eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 2258eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen return true; 2259e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2260e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2261e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* checks if package name is not null or empty */ 2262e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean isPackageNameValid(String browsedPackage) { 2263e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah boolean isValid = (browsedPackage != null && browsedPackage.length() > 0); 2264e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "isPackageNameValid: browsedPackage = " + browsedPackage + 2265e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah "isValid = " + isValid); 2266e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return isValid; 2267e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2268e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2269e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* checks if selected addressed player is already addressed */ 2270e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean isPlayerAlreadyAddressed(int selectedId) { 2271e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // checking if selected ID is same as the current addressed player id 2272e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah boolean isAddressed = (mCurrAddrPlayerID == selectedId); 2273e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "isPlayerAlreadyAddressed: isAddressed = " + isAddressed); 2274e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return isAddressed; 2275e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2276e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2277e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void dump(StringBuilder sb) { 2278e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah sb.append("AVRCP:\n"); 2279e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mMediaAttributes: " + mMediaAttributes); 2280e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mTransportControlFlags: " + mTransportControlFlags); 2281e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mCurrentPlayState: " + mCurrentPlayState); 2282e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mPlayStatusChangedNT: " + mPlayStatusChangedNT); 2283e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mTrackChangedNT: " + mTrackChangedNT); 2284e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mPlaybackIntervalMs: " + mPlaybackIntervalMs); 2285e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mPlayPosChangedNT: " + mPlayPosChangedNT); 2286e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mNextPosMs: " + mNextPosMs); 2287e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mPrevPosMs: " + mPrevPosMs); 2288e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mFeatures: " + mFeatures); 2289e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mRemoteVolume: " + mRemoteVolume); 2290e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mLastRemoteVolume: " + mLastRemoteVolume); 2291e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mLastDirection: " + mLastDirection); 2292e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mVolumeStep: " + mVolumeStep); 2293e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mAudioStreamMax: " + mAudioStreamMax); 2294e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mVolCmdAdjustInProgress: " + mVolCmdAdjustInProgress); 2295e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mVolCmdSetInProgress: " + mVolCmdSetInProgress); 2296e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mAbsVolRetryTimes: " + mAbsVolRetryTimes); 2297e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mVolumeMapping: " + mVolumeMapping.toString()); 2298ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen synchronized (this) { 2299ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen if (mMediaController != null) 2300ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen ProfileService.println(sb, "mMediaController: " 2301ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen + mMediaController.getWrappedInstance() + " pkg " 2302ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen + mMediaController.getPackageName()); 2303ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen } 230478d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen ProfileService.println(sb, ""); 230578d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen ProfileService.println(sb, "Media Players:"); 2306511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 2307511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) { 2308511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int key = entry.getKey(); 2309511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen ProfileService.println(sb, ((mCurrAddrPlayerID == key) ? " *#" : " #") 2310511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen + entry.getKey() + ": " + entry.getValue()); 2311511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 231205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 231305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 2314e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen ProfileService.println(sb, ""); 2315e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen mAddressedMediaPlayer.dump(sb, mMediaController); 2316e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen 2317e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen ProfileService.println(sb, ""); 231878d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen ProfileService.println(sb, mPassthroughDispatched + " passthrough operations: "); 231978d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen if (mPassthroughDispatched > mPassthroughLogs.size()) 232078d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen ProfileService.println(sb, " (last " + mPassthroughLogs.size() + ")"); 232178d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen synchronized (mPassthroughLogs) { 232278d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen for (MediaKeyLog log : mPassthroughLogs) { 232378d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen ProfileService.println(sb, " " + log); 232478d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen } 232505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 232678d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen synchronized (mPassthroughPending) { 232778d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen for (MediaKeyLog log : mPassthroughPending) { 232878d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen ProfileService.println(sb, " " + log); 232978d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen } 2330b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen } 2331e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2332e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2333e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public class AvrcpBrowseManager { 2334e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Map<String, BrowsedMediaPlayer> connList = new HashMap<String, BrowsedMediaPlayer>(); 2335e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private AvrcpMediaRspInterface mMediaInterface; 2336e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private Context mContext; 2337e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2338e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public AvrcpBrowseManager(Context context, AvrcpMediaRspInterface mediaInterface) { 2339e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mContext = context; 2340e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mMediaInterface = mediaInterface; 2341e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2342e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2343e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void cleanup() { 2344e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Iterator entries = connList.entrySet().iterator(); 2345e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah while (entries.hasNext()) { 2346e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Map.Entry entry = (Map.Entry) entries.next(); 2347e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah BrowsedMediaPlayer browsedMediaPlayer = (BrowsedMediaPlayer) entry.getValue(); 2348e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (browsedMediaPlayer != null) { 2349e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah browsedMediaPlayer.cleanup(); 2350e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2351e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2352e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // clean up the map 2353e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah connList.clear(); 2354e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2355e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2356e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // get the a free media player interface based on the passed bd address 2357e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // if the no items is found for the passed media player then it assignes a 2358e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // available media player interface 2359e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public BrowsedMediaPlayer getBrowsedMediaPlayer(byte[] bdaddr) { 2360e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah BrowsedMediaPlayer mediaPlayer; 2361e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String bdaddrStr = new String(bdaddr); 236205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (connList.containsKey(bdaddrStr)) { 2363e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mediaPlayer = connList.get(bdaddrStr); 2364e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2365e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mediaPlayer = new BrowsedMediaPlayer(bdaddr, mContext, mMediaInterface); 2366e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah connList.put(bdaddrStr, mediaPlayer); 2367e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2368e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return mediaPlayer; 2369e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2370e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2371e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // clears the details pertaining to passed bdaddres 2372e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public boolean clearBrowsedMediaPlayer(byte[] bdaddr) { 2373e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String bdaddrStr = new String(bdaddr); 237405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (connList.containsKey(bdaddrStr)) { 2375e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah connList.remove(bdaddrStr); 2376e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return true; 2377e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2378e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return false; 2379e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2380e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2381e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public Map<String, BrowsedMediaPlayer> getConnList() { 2382e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return connList; 2383e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2384e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2385e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Helper function to convert colon separated bdaddr to byte string */ 2386e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private byte[] hexStringToByteArray(String s) { 2387e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int len = s.length(); 2388e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] data = new byte[len / 2]; 2389e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah for (int i = 0; i < len; i += 2) { 2390e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) 2391e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + Character.digit(s.charAt(i+1), 16)); 2392e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2393e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return data; 2394e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2395e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2396e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2397e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* 2398e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * private class which handles responses from AvrcpMediaManager. Maps responses to native 2399e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * responses. This class implements the AvrcpMediaRspInterface interface. 2400e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 2401e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private class AvrcpMediaRsp implements AvrcpMediaRspInterface { 2402e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final String TAG = "AvrcpMediaRsp"; 2403e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2404e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void setAddrPlayerRsp(byte[] address, int rspStatus) { 2405e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!setAddressedPlayerRspNative(address, rspStatus)) { 2406e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "setAddrPlayerRsp failed!"); 2407e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2408e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2409e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2410e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void setBrowsedPlayerRsp(byte[] address, int rspStatus, byte depth, int numItems, 2411e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String[] textArray) { 2412e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!setBrowsedPlayerRspNative(address, rspStatus, depth, numItems, textArray)) { 2413e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "setBrowsedPlayerRsp failed!"); 2414e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2415e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2416e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2417e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void mediaPlayerListRsp(byte[] address, int rspStatus, MediaPlayerListRsp rspObj) { 2418e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (rspObj != null && rspStatus == AvrcpConstants.RSP_NO_ERROR) { 2419e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!mediaPlayerListRspNative(address, rspStatus, sUIDCounter, rspObj.itemType, 2420eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen rspObj.mNumItems, rspObj.mPlayerIds, rspObj.mPlayerTypes, 2421eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen rspObj.mPlayerSubTypes, rspObj.mPlayStatusValues, 2422eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen rspObj.mFeatureBitMaskValues, rspObj.mPlayerNameList)) 2423eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen Log.e(TAG, "mediaPlayerListRsp failed!"); 2424e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2425e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "mediaPlayerListRsp: rspObj is null"); 2426eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen if (!mediaPlayerListRspNative(address, rspStatus, sUIDCounter, (byte) 0x00, 0, null, 2427eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen null, null, null, null, null)) 2428eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen Log.e(TAG, "mediaPlayerListRsp failed!"); 2429e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2430e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2431e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2432e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void folderItemsRsp(byte[] address, int rspStatus, FolderItemsRsp rspObj) { 2433e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (rspObj != null && rspStatus == AvrcpConstants.RSP_NO_ERROR) { 2434e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!getFolderItemsRspNative(address, rspStatus, sUIDCounter, rspObj.mScope, 2435e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah rspObj.mNumItems, rspObj.mFolderTypes, rspObj.mPlayable, rspObj.mItemTypes, 2436e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah rspObj.mItemUid, rspObj.mDisplayNames, rspObj.mAttributesNum, 2437e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah rspObj.mAttrIds, rspObj.mAttrValues)) 2438e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getFolderItemsRspNative failed!"); 2439e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2440e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "folderItemsRsp: rspObj is null or rspStatus is error:" + rspStatus); 2441e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!getFolderItemsRspNative(address, rspStatus, sUIDCounter, (byte) 0x00, 0, 2442e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah null, null, null, null, null, null, null, null)) 2443e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getFolderItemsRspNative failed!"); 2444e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2445e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2446e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2447e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2448e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void changePathRsp(byte[] address, int rspStatus, int numItems) { 2449e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!changePathRspNative(address, rspStatus, numItems)) 2450e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "changePathRspNative failed!"); 2451e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2452e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2453e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void getItemAttrRsp(byte[] address, int rspStatus, ItemAttrRsp rspObj) { 2454e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (rspObj != null && rspStatus == AvrcpConstants.RSP_NO_ERROR) { 2455e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!getItemAttrRspNative(address, rspStatus, rspObj.mNumAttr, 2456e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah rspObj.mAttributesIds, rspObj.mAttributesArray)) 2457e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getItemAttrRspNative failed!"); 2458e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2459e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getItemAttrRsp: rspObj is null or rspStatus is error:" + rspStatus); 2460e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!getItemAttrRspNative(address, rspStatus, (byte) 0x00, null, null)) 2461e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getItemAttrRspNative failed!"); 2462e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2463e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2464e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2465e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void playItemRsp(byte[] address, int rspStatus) { 2466e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!playItemRspNative(address, rspStatus)) { 2467e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "playItemRspNative failed!"); 2468e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2469e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2470e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2471e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void getTotalNumOfItemsRsp(byte[] address, int rspStatus, int uidCounter, 2472e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int numItems) { 2473e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!getTotalNumOfItemsRspNative(address, rspStatus, sUIDCounter, numItems)) { 2474e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getTotalNumOfItemsRspNative failed!"); 2475e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2476e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2477e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 247805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public void addrPlayerChangedRsp(int type, int playerId, int uidCounter) { 2479e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspAddrPlayerChangedNative(type, playerId, sUIDCounter)) { 2480e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "registerNotificationRspAddrPlayerChangedNative failed!"); 2481e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2482e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2483e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2484e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void avalPlayerChangedRsp(byte[] address, int type) { 2485e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspAvalPlayerChangedNative(type)) { 2486e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "registerNotificationRspAvalPlayerChangedNative failed!"); 2487e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2488e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2489e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2490e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void uidsChangedRsp(byte[] address, int type, int uidCounter) { 2491e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspUIDsChangedNative(type, sUIDCounter)) { 2492e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "registerNotificationRspUIDsChangedNative failed!"); 2493e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2494e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2495e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2496e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void nowPlayingChangedRsp(int type) { 2497e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspNowPlayingChangedNative(type)) { 2498e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "registerNotificationRspNowPlayingChangedNative failed!"); 2499e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2500e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2501e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2502e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void trackChangedRsp(int type, byte[] uid) { 2503e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspTrackChangeNative(type, uid)) { 2504e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "registerNotificationRspTrackChangeNative failed!"); 2505e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2506e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2507e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2508e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2509e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* getters for some private variables */ 2510e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public AvrcpBrowseManager getAvrcpBrowseManager() { 2511e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return mAvrcpBrowseManager; 2512e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2513e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 251405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen /* PASSTHROUGH COMMAND MANAGEMENT */ 251505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 251605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen void handlePassthroughCmd(int op, int state) { 251705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen int code = avrcpPassthroughToKeyCode(op); 251805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (code == KeyEvent.KEYCODE_UNKNOWN) { 251905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.w(TAG, "Ignoring passthrough of unknown key " + op + " state " + state); 252005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return; 252105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 252205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen int action = KeyEvent.ACTION_DOWN; 252305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (state == AvrcpConstants.KEY_STATE_RELEASE) action = KeyEvent.ACTION_UP; 252405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen KeyEvent event = new KeyEvent(action, code); 252505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (!KeyEvent.isMediaKey(code)) { 252605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.w(TAG, "Passthrough non-media key " + op + " (code " + code + ") state " + state); 252705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 252805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mMediaSessionManager.dispatchMediaKeyEvent(event); 252905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen addKeyPending(event); 253005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 253105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 253205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private int avrcpPassthroughToKeyCode(int operation) { 253305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen switch (operation) { 253405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_UP: 253505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_UP; 253605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_DOWN: 253705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_DOWN; 253805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_LEFT: 253905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_LEFT; 254005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_RIGHT: 254105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_RIGHT; 254205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_RIGHT_UP: 254305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_UP_RIGHT; 254405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_RIGHT_DOWN: 254505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_DOWN_RIGHT; 254605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_LEFT_UP: 254705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_UP_LEFT; 254805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_LEFT_DOWN: 254905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_DOWN_LEFT; 255005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_0: 255105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_0; 255205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_1: 255305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_1; 255405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_2: 255505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_2; 255605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_3: 255705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_3; 255805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_4: 255905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_4; 256005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_5: 256105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_5; 256205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_6: 256305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_6; 256405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_7: 256505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_7; 256605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_8: 256705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_8; 256805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_9: 256905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_9; 257005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_DOT: 257105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_DOT; 257205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_ENTER: 257305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_ENTER; 257405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_CLEAR: 257505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_CLEAR; 257605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_CHAN_UP: 257705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_CHANNEL_UP; 257805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_CHAN_DOWN: 257905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_CHANNEL_DOWN; 258005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_PREV_CHAN: 258105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_LAST_CHANNEL; 258205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_INPUT_SEL: 258305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_TV_INPUT; 258405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_DISP_INFO: 258505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_INFO; 258605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_HELP: 258705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_HELP; 258805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_PAGE_UP: 258905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_PAGE_UP; 259005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_PAGE_DOWN: 259105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_PAGE_DOWN; 259205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_POWER: 259305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_POWER; 259405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_VOL_UP: 259505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_VOLUME_UP; 259605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_VOL_DOWN: 259705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_VOLUME_DOWN; 259805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_MUTE: 259905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MUTE; 260005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_PLAY: 260105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_PLAY; 260205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_STOP: 260305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_STOP; 260405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_PAUSE: 260505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_PAUSE; 260605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_RECORD: 260705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_RECORD; 260805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_REWIND: 260905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_REWIND; 261005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_FAST_FOR: 261105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_FAST_FORWARD; 261205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_EJECT: 261305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_EJECT; 261405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_FORWARD: 261505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_NEXT; 261605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_BACKWARD: 261705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_PREVIOUS; 261805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_F1: 261905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_F1; 262005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_F2: 262105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_F2; 262205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_F3: 262305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_F3; 262405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_F4: 262505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_F4; 262605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_F5: 262705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_F5; 262805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen // Fallthrough for all unknown key mappings 262905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_SELECT: 263005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_ROOT_MENU: 263105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_SETUP_MENU: 263205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_CONT_MENU: 263305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_FAV_MENU: 263405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_EXIT: 263505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_SOUND_SEL: 263605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_ANGLE: 263705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_SUBPICT: 263805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_VENDOR: 263905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen default: 264005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_UNKNOWN; 264105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 264205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 264305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 264405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private void addKeyPending(KeyEvent event) { 264578d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen mPassthroughPending.add(new MediaKeyLog(System.currentTimeMillis(), event)); 264605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 264705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 264805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private void recordKeyDispatched(KeyEvent event, String packageName) { 264905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen long time = System.currentTimeMillis(); 265005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.v(TAG, "recordKeyDispatched: " + event + " dispatched to " + packageName); 265178d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen setAddressedMediaSessionPackage(packageName); 265205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen synchronized (mPassthroughPending) { 265305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Iterator<MediaKeyLog> pending = mPassthroughPending.iterator(); 265405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen while (pending.hasNext()) { 265505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen MediaKeyLog log = pending.next(); 265605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (log.addDispatch(time, event, packageName)) { 265705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mPassthroughDispatched++; 265805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mPassthroughLogs.add(log); 265905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen pending.remove(); 266005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return; 266105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 266205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 266378d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen Log.w(TAG, "recordKeyDispatch: can't find matching log!"); 266405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 266505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 266605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 266705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private final MediaSessionManager.Callback mButtonDispatchCallback = 266805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen new MediaSessionManager.Callback() { 266905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen @Override 267005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public void onMediaKeyEventDispatched(KeyEvent event, MediaSession.Token token) { 267105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen // Get the package name 267205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen android.media.session.MediaController controller = 267305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen new android.media.session.MediaController(mContext, token); 267405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen String targetPackage = controller.getPackageName(); 267505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen recordKeyDispatched(event, targetPackage); 267605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 267705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 267805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen @Override 267905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public void onMediaKeyEventDispatched(KeyEvent event, ComponentName receiver) { 268005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen recordKeyDispatched(event, receiver.getPackageName()); 268105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 268205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 268305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen @Override 268405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public void onAddressedPlayerChanged(MediaSession.Token token) { 268505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen setActiveMediaSession(token); 268605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 268705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 268805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen @Override 268905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public void onAddressedPlayerChanged(ComponentName receiver) { 269041527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen if (receiver == null) { 269141527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen // No active sessions, and no session to revive, give up. 269241527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen setAddressedMediaSessionPackage(null); 269341527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen return; 269441527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen } 269541527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen // We can still get a passthrough which will revive this player. 269605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen setAddressedMediaSessionPackage(receiver.getPackageName()); 269705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 269805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen }; 269905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 2700e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // Do not modify without updating the HAL bt_rc.h files. 2701e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2702e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // match up with btrc_play_status_t enum of bt_rc.h 2703e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int PLAYSTATUS_STOPPED = 0; 2704e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int PLAYSTATUS_PLAYING = 1; 2705e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int PLAYSTATUS_PAUSED = 2; 2706e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int PLAYSTATUS_FWD_SEEK = 3; 2707e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int PLAYSTATUS_REV_SEEK = 4; 2708e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int PLAYSTATUS_ERROR = 255; 2709e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2710e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // match up with btrc_media_attr_t enum of bt_rc.h 2711e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_TITLE = 1; 2712e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_ARTIST = 2; 2713e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_ALBUM = 3; 2714e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_TRACK_NUM = 4; 2715e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_NUM_TRACKS = 5; 2716e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_GENRE = 6; 2717e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_PLAYING_TIME = 7; 2718e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2719e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // match up with btrc_event_id_t enum of bt_rc.h 2720e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_PLAY_STATUS_CHANGED = 1; 2721e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_TRACK_CHANGED = 2; 2722e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_TRACK_REACHED_END = 3; 2723e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_TRACK_REACHED_START = 4; 2724e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_PLAY_POS_CHANGED = 5; 2725e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_BATT_STATUS_CHANGED = 6; 2726e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_SYSTEM_STATUS_CHANGED = 7; 2727e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_APP_SETTINGS_CHANGED = 8; 2728e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVENT_NOW_PLAYING_CONTENT_CHANGED = 9; 2729e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_AVBL_PLAYERS_CHANGED = 0xa; 2730e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_ADDR_PLAYER_CHANGED = 0xb; 2731e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVENT_UIDS_CHANGED = 0x0c; 2732c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 2733c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native static void classInitNative(); 2734c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native void initNative(); 2735c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native void cleanupNative(); 2736e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean getPlayStatusRspNative(byte[] address, int playStatus, int songLen, 2737e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int songPos); 2738e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean getElementAttrRspNative(byte[] address, byte numAttr, int[] attrIds, 2739e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String[] textArray); 2740c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native boolean registerNotificationRspPlayStatusNative(int type, int playStatus); 2741c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native boolean registerNotificationRspTrackChangeNative(int type, byte[] track); 2742aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private native boolean registerNotificationRspPlayPosNative(int type, int playPos); 274317675906064bb72fdcca75baa56cdf8bb8968d01John Du private native boolean setVolumeNative(int volume); 27445c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta private native boolean sendPassThroughCommandNative(int keyCode, int keyState); 2745e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean setAddressedPlayerRspNative(byte[] address, int rspStatus); 2746e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean setBrowsedPlayerRspNative(byte[] address, int rspStatus, byte depth, 2747e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int numItems, String[] textArray); 2748e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean mediaPlayerListRspNative(byte[] address, int rsStatus, int uidCounter, 2749eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen byte item_type, int numItems, int[] playerIds, byte[] playerTypes, int[] playerSubTypes, 2750eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen byte[] playStatusValues, short[] featureBitMaskValues, String[] textArray); 2751e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean getFolderItemsRspNative(byte[] address, int rspStatus, short uidCounter, 2752e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte scope, int numItems, byte[] folderTypes, byte[] playable, byte[] itemTypes, 2753e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] itemUidArray, String[] textArray, int[] AttributesNum, int[] AttributesIds, 2754e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String[] attributesArray); 2755e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean changePathRspNative(byte[] address, int rspStatus, int numItems); 2756e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean getItemAttrRspNative(byte[] address, int rspStatus, byte numAttr, 2757e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int[] attrIds, String[] textArray); 2758e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean playItemRspNative(byte[] address, int rspStatus); 2759e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean getTotalNumOfItemsRspNative(byte[] address, int rspStatus, 2760e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int uidCounter, int numItems); 2761e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean searchRspNative(byte[] address, int rspStatus, int uidCounter, 2762e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int numItems); 2763e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean addToNowPlayingRspNative(byte[] address, int rspStatus); 2764e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean registerNotificationRspAddrPlayerChangedNative(int type, 2765e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int playerId, int uidCounter); 2766e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean registerNotificationRspAvalPlayerChangedNative(int type); 2767e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean registerNotificationRspUIDsChangedNative(int type, int uidCounter); 2768e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean registerNotificationRspNowPlayingChangedNative(int type); 27695c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta 2770c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 2771