Avrcp.java revision 384011244f5a62ed34f198b8ba91341b4efb4fb6
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 19188f205b5f093850d4cc627917a21204be36c56aZhihai Xuimport android.bluetooth.BluetoothA2dp; 20066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodimport android.bluetooth.BluetoothAvrcp; 21e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.bluetooth.BluetoothDevice; 22e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.BroadcastReceiver; 23e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.ComponentName; 24c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.content.Context; 25e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.Intent; 26e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.IntentFilter; 27e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.pm.ApplicationInfo; 28e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.pm.PackageManager; 29e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.pm.PackageManager.NameNotFoundException; 30e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.pm.ResolveInfo; 3111798b011c962b602217b479130d413f3b30f19aLiejun Taoimport android.content.res.Resources; 3211798b011c962b602217b479130d413f3b30f19aLiejun Taoimport android.content.SharedPreferences; 33c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.media.AudioManager; 343b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssenimport android.media.MediaDescription; 350e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssenimport android.media.MediaMetadata; 363843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssenimport android.media.browse.MediaBrowser; 37e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.media.session.MediaSession; 38e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.media.session.MediaSession.QueueItem; 390e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssenimport android.media.session.MediaSessionManager; 400e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssenimport android.media.session.PlaybackState; 41e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.os.Bundle; 42c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.Handler; 43c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.HandlerThread; 44c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.Looper; 45c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.Message; 46aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xuimport android.os.SystemClock; 470427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panickerimport android.os.UserManager; 48c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.util.Log; 49881675b362bde18acbbcf69c513175addca4a8baZhenye Zhuimport android.view.KeyEvent; 506e29e12add362546784126119f26f04fc760f021RoboErik 51c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport com.android.bluetooth.btservice.ProfileService; 52e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport com.android.bluetooth.R; 53aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xuimport com.android.bluetooth.Utils; 546e29e12add362546784126119f26f04fc760f021RoboErik 553843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssenimport java.util.concurrent.CountDownLatch; 56c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport java.util.ArrayList; 5711798b011c962b602217b479130d413f3b30f19aLiejun Taoimport java.util.HashMap; 58e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport java.util.Iterator; 59c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport java.util.List; 60e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport java.util.Map; 61eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssenimport java.util.SortedMap; 62eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssenimport java.util.TreeMap; 63e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 64e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah/****************************************************************************** 65e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * support Bluetooth AVRCP profile. support metadata, play status, event 66e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * notifications, address player selection and browse feature implementation. 67e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ******************************************************************************/ 68eb7b90f5b93db1230a5b64caa3d8d05a642e33a6Marie Janssen 69066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodpublic final class Avrcp { 701b70ec148be773651d5ad00e3ce0d28b3a63306dAjay Panicker private static final boolean DEBUG = true; 71c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private static final String TAG = "Avrcp"; 7211798b011c962b602217b479130d413f3b30f19aLiejun Tao private static final String ABSOLUTE_VOLUME_BLACKLIST = "absolute_volume_blacklist"; 73c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 74c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private Context mContext; 75c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private final AudioManager mAudioManager; 76c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private AvrcpMessageHandler mHandler; 770e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen private MediaSessionManager mMediaSessionManager; 780e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen private MediaController mMediaController; 790e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen private MediaControllerListener mMediaControllerCb; 803b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private MediaAttributes mMediaAttributes; 81e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private PackageManager mPackageManager; 82c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private int mTransportControlFlags; 830e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen private PlaybackState mCurrentPlayState; 840a429916782c20980e7f0893c503c633b8341f88Marie Janssen private int mA2dpState; 85c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private int mPlayStatusChangedNT; 86c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private int mTrackChangedNT; 87f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen private int mPlayPosChangedNT; 88e23a886e79f60a3f7f5b8e87f8c5ffc26134bd32Marie Janssen private long mTracksPlayed; 89aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mPlaybackIntervalMs; 90fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen private long mLastReportedPosition; 91aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mNextPosMs; 92aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mPrevPosMs; 93ace834feb02adabd61f628c4471147aea02d939cJohn Du private long mSkipStartTime; 9417675906064bb72fdcca75baa56cdf8bb8968d01John Du private int mFeatures; 9511798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mRemoteVolume; 9611798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mLastRemoteVolume; 9711798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mInitialRemoteVolume; 9811798b011c962b602217b479130d413f3b30f19aLiejun Tao 9911798b011c962b602217b479130d413f3b30f19aLiejun Tao /* Local volume in audio index 0-15 */ 10011798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mLocalVolume; 10111798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mLastLocalVolume; 10211798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mAbsVolThreshold; 10311798b011c962b602217b479130d413f3b30f19aLiejun Tao 10411798b011c962b602217b479130d413f3b30f19aLiejun Tao private String mAddress; 10511798b011c962b602217b479130d413f3b30f19aLiejun Tao private HashMap<Integer, Integer> mVolumeMapping; 10611798b011c962b602217b479130d413f3b30f19aLiejun Tao 10717675906064bb72fdcca75baa56cdf8bb8968d01John Du private int mLastDirection; 1082e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie private final int mVolumeStep; 1092e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie private final int mAudioStreamMax; 11011798b011c962b602217b479130d413f3b30f19aLiejun Tao private boolean mVolCmdAdjustInProgress; 11111798b011c962b602217b479130d413f3b30f19aLiejun Tao private boolean mVolCmdSetInProgress; 11217675906064bb72fdcca75baa56cdf8bb8968d01John Du private int mAbsVolRetryTimes; 11319e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu private int mSkipAmount; 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 */ 181e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private ArrayList<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 19305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private ArrayList<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 (DEBUG) 20905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.v(TAG, "addDispatch: Trying to match " + mEvent + " and record " + packageName); 21005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (mPackage != null) return false; 21105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (event.getAction() != mEvent.getAction()) return false; 21205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (event.getKeyCode() != mEvent.getKeyCode()) return false; 21305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mPackage = packageName; 21405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mTimeProcessed = time; 21505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return true; 21605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 21705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 21805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public String toString() { 21905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen StringBuilder sb = new StringBuilder(); 22005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen sb.append(android.text.format.DateFormat.format("MM-dd HH:mm:ss", mTimeSent)); 22105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen sb.append(" " + mEvent.toString()); 22205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (mPackage == null) { 22305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen sb.append(" (undispatched)"); 22405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } else { 22505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen sb.append(" to " + mPackage); 22605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen sb.append(" in " + (mTimeProcessed - mTimeSent) + "ms"); 22705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 22805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return sb.toString(); 22905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 23005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 23105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 232c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu static { 233c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu classInitNative(); 234c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 235c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 236c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private Avrcp(Context context) { 2373b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen mMediaAttributes = new MediaAttributes(null); 2380e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen mCurrentPlayState = new PlaybackState.Builder().setState(PlaybackState.STATE_NONE, -1L, 0.0f).build(); 2390a429916782c20980e7f0893c503c633b8341f88Marie Janssen mA2dpState = BluetoothA2dp.STATE_NOT_PLAYING; 240e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPlayStatusChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 241e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 242e23a886e79f60a3f7f5b8e87f8c5ffc26134bd32Marie Janssen mTracksPlayed = 0; 243aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPlaybackIntervalMs = 0L; 244e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPlayPosChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 245fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen mLastReportedPosition = -1; 2463635a926bd7316a55b288a54d409a1070a9c19e8Marie Janssen mNextPosMs = -1; 2473635a926bd7316a55b288a54d409a1070a9c19e8Marie Janssen mPrevPosMs = -1; 24817675906064bb72fdcca75baa56cdf8bb8968d01John Du mFeatures = 0; 24911798b011c962b602217b479130d413f3b30f19aLiejun Tao mRemoteVolume = -1; 25011798b011c962b602217b479130d413f3b30f19aLiejun Tao mInitialRemoteVolume = -1; 25111798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastRemoteVolume = -1; 25217675906064bb72fdcca75baa56cdf8bb8968d01John Du mLastDirection = 0; 25311798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = false; 25411798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = false; 25517675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes = 0; 25611798b011c962b602217b479130d413f3b30f19aLiejun Tao mLocalVolume = -1; 25711798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = -1; 25811798b011c962b602217b479130d413f3b30f19aLiejun Tao mAbsVolThreshold = 0; 25911798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolumeMapping = new HashMap<Integer, Integer>(); 260e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah sUIDCounter = AvrcpConstants.DEFAULT_UID_COUNTER; 261384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen mCurrAddrPlayerID = NO_PLAYER_ID; 262294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen mCurrBrowsePlayerID = 0; 263c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mContext = context; 264eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen mLastUsedPlayerID = 0; 265e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAddressedMediaPlayer = null; 266c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 267c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu initNative(); 268c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 269e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mMediaSessionManager = (MediaSessionManager) context.getSystemService( 270e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Context.MEDIA_SESSION_SERVICE); 271c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 2722e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie mAudioStreamMax = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); 2732e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie mVolumeStep = Math.max(AVRCP_BASE_VOLUME_STEP, AVRCP_MAX_VOL/mAudioStreamMax); 274e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 27511798b011c962b602217b479130d413f3b30f19aLiejun Tao Resources resources = context.getResources(); 27611798b011c962b602217b479130d413f3b30f19aLiejun Tao if (resources != null) { 27711798b011c962b602217b479130d413f3b30f19aLiejun Tao mAbsVolThreshold = resources.getInteger(R.integer.a2dp_absolute_volume_initial_threshold); 27811798b011c962b602217b479130d413f3b30f19aLiejun Tao } 279e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 280e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // Register for package removal intent broadcasts for media button receiver persistence 281e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah IntentFilter pkgFilter = new IntentFilter(); 282e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah pkgFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 283e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah pkgFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 284e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah pkgFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); 285e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah pkgFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED); 286e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah pkgFilter.addDataScheme("package"); 287e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah context.registerReceiver(mAvrcpReceiver, pkgFilter); 2880427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker 2890427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker IntentFilter bootFilter = new IntentFilter(); 2900427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker bootFilter.addAction(Intent.ACTION_BOOT_COMPLETED); 2910427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker context.registerReceiver(mBootReceiver, bootFilter); 292c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 293c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 294c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private void start() { 295c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu HandlerThread thread = new HandlerThread("BluetoothAvrcpHandler"); 296c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu thread.start(); 297c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Looper looper = thread.getLooper(); 298c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler = new AvrcpMessageHandler(looper); 2999d4035307b85e78f10fba961e225ca09bfb7d0c7Jakub Pawlowski mMediaControllerCb = new MediaControllerListener(); 300e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpMediaRsp = new AvrcpMediaRsp(); 301eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen mMediaPlayerInfoList = new TreeMap<Integer, MediaPlayerInfo>(); 302e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mBrowsePlayerInfoList = new ArrayList<BrowsePlayerInfo>(); 30305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mPassthroughDispatched = 0; 30405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mPassthroughLogs = new EvictingQueue<MediaKeyLog>(PASSTHROUGH_LOG_MAX_SIZE); 30505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mPassthroughPending = new ArrayList<MediaKeyLog>(); 306f65765e71b2a6552c319eb5199914045a1ecdb04Marie Janssen if (mMediaSessionManager != null) { 307f65765e71b2a6552c319eb5199914045a1ecdb04Marie Janssen mMediaSessionManager.addOnActiveSessionsChangedListener(mActiveSessionListener, null, 308f65765e71b2a6552c319eb5199914045a1ecdb04Marie Janssen mHandler); 30905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mMediaSessionManager.setCallback(mButtonDispatchCallback, null); 310f65765e71b2a6552c319eb5199914045a1ecdb04Marie Janssen } 311e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPackageManager = mContext.getApplicationContext().getPackageManager(); 312e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 313e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* create object to communicate with addressed player */ 314e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAddressedMediaPlayer = new AddressedMediaPlayer(mAvrcpMediaRsp); 315e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 316e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* initialize BrowseMananger which manages Browse commands and response */ 317e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager = new AvrcpBrowseManager(mContext, mAvrcpMediaRsp); 3180427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker 31905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen initMediaPlayersList(); 32011bf73ff614f48a41dc379763bc007f271197b26Ajay Panicker 3210427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker UserManager manager = UserManager.get(mContext); 3220427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker if (manager == null || manager.isUserUnlocked()) { 3230427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker if (DEBUG) Log.d(TAG, "User already unlocked, initializing player lists"); 3243843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen // initialize browsable player list and build media player list 3253843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen (new BrowsablePlayerListBuilder()).start(); 3260427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker } 327c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 328c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 329066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood public static Avrcp make(Context context) { 330c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (DEBUG) Log.v(TAG, "make"); 331c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Avrcp ar = new Avrcp(context); 332c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ar.start(); 333c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return ar; 334c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 335c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 336c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public void doQuit() { 337e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "doQuit"); 338c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.removeCallbacksAndMessages(null); 339c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Looper looper = mHandler.getLooper(); 340c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (looper != null) { 341c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu looper.quit(); 342c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 343e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 344eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen if (mMediaController != null) mMediaController.unregisterCallback(mMediaControllerCb); 345eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 346e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mMediaSessionManager.removeOnActiveSessionsChangedListener(mActiveSessionListener); 347e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 348e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler = null; 349e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mContext.unregisterReceiver(mAvrcpReceiver); 3500427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker mContext.unregisterReceiver(mBootReceiver); 351e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 352e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAddressedMediaPlayer.cleanup(); 353e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager.cleanup(); 354c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 355c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 356c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public void cleanup() { 357e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "cleanup"); 358c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu cleanupNative(); 35911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolumeMapping != null) 36011798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolumeMapping.clear(); 361c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 362c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 3630e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen private class MediaControllerListener extends MediaController.Callback { 3640e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen @Override 3650e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen public void onMetadataChanged(MediaMetadata metadata) { 3660e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen Log.v(TAG, "MediaController metadata changed"); 3670a429916782c20980e7f0893c503c633b8341f88Marie Janssen updateCurrentMediaState(); 368c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 369c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 370bc10e7d58aa55da25c18d8056a0254a2b736146aZhihai Xu @Override 371e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public synchronized void onPlaybackStateChanged(PlaybackState state) { 372eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen if (DEBUG) Log.v(TAG, "onPlaybackStateChanged: state " + state.toString()); 3730a429916782c20980e7f0893c503c633b8341f88Marie Janssen updateCurrentMediaState(); 374c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 375c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 376c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu @Override 3770e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen public void onSessionDestroyed() { 3780e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen Log.v(TAG, "MediaController session destroyed"); 379384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen if (mMediaController != null) { 380384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen removeMediaController(mMediaController.getWrappedInstance()); 381384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen mMediaController.unregisterCallback(mMediaControllerCb); 382384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen mMediaController = null; 383384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } 384c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 385c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 386c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu @Override 387e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void onQueueChanged(List<MediaSession.QueueItem> queue) { 388e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (queue == null) { 389e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.v(TAG, "onQueueChanged: received null queue"); 390e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return; 391e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 3922b903c7262c9b8c0493e36b93b37831e7e075bfcMarie Janssen 393e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.v(TAG, "onQueueChanged: NowPlaying list changed, Queue Size = "+ queue.size()); 394e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAddressedMediaPlayer.updateNowPlayingList(queue); 395e2619781c799435cf0273d381069c754c5f89a20Marie Janssen mHandler.sendEmptyMessage(MSG_NOW_PLAYING_CHANGED_RSP); 396c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 397c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 398c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 399c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu /** Handles Avrcp messages. */ 400c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private final class AvrcpMessageHandler extends Handler { 401c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private AvrcpMessageHandler(Looper looper) { 402c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu super(looper); 403c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 404c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 405c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu @Override 406c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public void handleMessage(Message msg) { 407c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu switch (msg.what) { 408e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_RC_FEATURES: 409e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah { 41017675906064bb72fdcca75baa56cdf8bb8968d01John Du String address = (String) msg.obj; 411e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_GET_RC_FEATURES: address="+address+ 412e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ", features="+msg.arg1); 41317675906064bb72fdcca75baa56cdf8bb8968d01John Du mFeatures = msg.arg1; 41411798b011c962b602217b479130d413f3b30f19aLiejun Tao mFeatures = modifyRcFeatureFromBlacklist(mFeatures, address); 41517675906064bb72fdcca75baa56cdf8bb8968d01John Du mAudioManager.avrcpSupportsAbsoluteVolume(address, isAbsoluteVolumeSupported()); 41611798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = -1; 41711798b011c962b602217b479130d413f3b30f19aLiejun Tao mRemoteVolume = -1; 41811798b011c962b602217b479130d413f3b30f19aLiejun Tao mLocalVolume = -1; 41911798b011c962b602217b479130d413f3b30f19aLiejun Tao mInitialRemoteVolume = -1; 42011798b011c962b602217b479130d413f3b30f19aLiejun Tao mAddress = address; 42111798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolumeMapping != null) 42211798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolumeMapping.clear(); 42317675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 424e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 42517675906064bb72fdcca75baa56cdf8bb8968d01John Du 426e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_PLAY_STATUS: 427e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah { 428e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] address = (byte[]) msg.obj; 429e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_GET_PLAY_STATUS"); 430e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah getPlayStatusRspNative(address, convertPlayStateToPlayStatus(mCurrentPlayState), 4310a429916782c20980e7f0893c503c633b8341f88Marie Janssen (int) mMediaAttributes.getLength(), (int) getPlayPosition()); 432c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 433e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 434c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 435e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_ELEM_ATTRS: 436e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah { 437c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu String[] textArray; 438e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd.ElementAttrCmd elem = (AvrcpCmd.ElementAttrCmd) msg.obj; 439e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte numAttr = elem.mNumAttr; 440e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int[] attrIds = elem.mAttrIDs; 441e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_GET_ELEM_ATTRS:numAttr=" + numAttr); 442c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu textArray = new String[numAttr]; 443c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu for (int i = 0; i < numAttr; ++i) { 4443b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen textArray[i] = mMediaAttributes.getString(attrIds[i]); 4453b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen Log.v(TAG, "getAttributeString:attrId=" + attrIds[i] + 446e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah " str=" + textArray[i]); 447c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 448e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] bdaddr = elem.mAddress; 449e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah getElementAttrRspNative(bdaddr, numAttr, attrIds, textArray); 450c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 451e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 452c1124a7c6679f612b80926a19084655f9a71580aMarie Janssen 453e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_REGISTER_NOTIFICATION: 454e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_REGISTER_NOTIFICATION:event=" + msg.arg1 + 455e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah " param=" + msg.arg2); 456e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah processRegisterNotification((byte[]) msg.obj, msg.arg1, msg.arg2); 457c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 458c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 459e2619781c799435cf0273d381069c754c5f89a20Marie Janssen case MSG_AVAILABLE_PLAYERS_CHANGED_RSP: 460e2619781c799435cf0273d381069c754c5f89a20Marie Janssen if (DEBUG) Log.v(TAG, "MSG_AVAILABLE_PLAYERS_CHANGED_RSP"); 461e2619781c799435cf0273d381069c754c5f89a20Marie Janssen removeMessages(MSG_AVAILABLE_PLAYERS_CHANGED_RSP); 462e2619781c799435cf0273d381069c754c5f89a20Marie Janssen registerNotificationRspAvalPlayerChangedNative( 463e2619781c799435cf0273d381069c754c5f89a20Marie Janssen AvrcpConstants.NOTIFICATION_TYPE_CHANGED); 464e2619781c799435cf0273d381069c754c5f89a20Marie Janssen break; 465e2619781c799435cf0273d381069c754c5f89a20Marie Janssen 466e2619781c799435cf0273d381069c754c5f89a20Marie Janssen case MSG_NOW_PLAYING_CHANGED_RSP: 467e2619781c799435cf0273d381069c754c5f89a20Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NOW_PLAYING_CHANGED_RSP"); 468e2619781c799435cf0273d381069c754c5f89a20Marie Janssen removeMessages(MSG_NOW_PLAYING_CHANGED_RSP); 469e2619781c799435cf0273d381069c754c5f89a20Marie Janssen registerNotificationRspNowPlayingChangedNative( 470e2619781c799435cf0273d381069c754c5f89a20Marie Janssen AvrcpConstants.NOTIFICATION_TYPE_CHANGED); 471e2619781c799435cf0273d381069c754c5f89a20Marie Janssen break; 472e2619781c799435cf0273d381069c754c5f89a20Marie Janssen 473e2619781c799435cf0273d381069c754c5f89a20Marie Janssen case MSG_ADDRESSED_PLAYER_CHANGED_RSP: 474e2619781c799435cf0273d381069c754c5f89a20Marie Janssen if (DEBUG) 475e2619781c799435cf0273d381069c754c5f89a20Marie Janssen Log.v(TAG, "MSG_ADDRESSED_PLAYER_CHANGED_RSP: newAddrPlayer = " + msg.arg1); 476e2619781c799435cf0273d381069c754c5f89a20Marie Janssen // Later addressed players override earlier ones. 477e2619781c799435cf0273d381069c754c5f89a20Marie Janssen if (hasMessages(MSG_ADDRESSED_PLAYER_CHANGED_RSP)) { 478e2619781c799435cf0273d381069c754c5f89a20Marie Janssen Log.i(TAG, "MSG_ADDRESSED_PLAYER_CHANGED_RSP: skip, more changes in queue"); 479e2619781c799435cf0273d381069c754c5f89a20Marie Janssen break; 480e2619781c799435cf0273d381069c754c5f89a20Marie Janssen } 481e2619781c799435cf0273d381069c754c5f89a20Marie Janssen registerNotificationRspAddrPlayerChangedNative( 482e2619781c799435cf0273d381069c754c5f89a20Marie Janssen AvrcpConstants.NOTIFICATION_TYPE_CHANGED, msg.arg1, sUIDCounter); 483e2619781c799435cf0273d381069c754c5f89a20Marie Janssen break; 484e2619781c799435cf0273d381069c754c5f89a20Marie Janssen 485e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_PLAY_INTERVAL_TIMEOUT: 486e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_PLAY_INTERVAL_TIMEOUT"); 487f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen sendPlayPosNotificationRsp(false); 488aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu break; 489aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 490e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_VOLUME_CHANGE: 49111798b011c962b602217b479130d413f3b30f19aLiejun Tao if (!isAbsoluteVolumeSupported()) { 492e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "ignore MSG_NATIVE_REQ_VOLUME_CHANGE"); 49311798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 49411798b011c962b602217b479130d413f3b30f19aLiejun Tao } 49511798b011c962b602217b479130d413f3b30f19aLiejun Tao 496e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_VOLUME_CHANGE: volume=" + ((byte) msg.arg1 & 0x7f) 497e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + " ctype=" + msg.arg2); 49811798b011c962b602217b479130d413f3b30f19aLiejun Tao 49911798b011c962b602217b479130d413f3b30f19aLiejun Tao boolean volAdj = false; 50017675906064bb72fdcca75baa56cdf8bb8968d01John Du if (msg.arg2 == AVRC_RSP_ACCEPT || msg.arg2 == AVRC_RSP_REJ) { 50111798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolCmdAdjustInProgress == false && mVolCmdSetInProgress == false) { 50217675906064bb72fdcca75baa56cdf8bb8968d01John Du Log.e(TAG, "Unsolicited response, ignored"); 50317675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 50417675906064bb72fdcca75baa56cdf8bb8968d01John Du } 505e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah removeMessages(MSG_ABS_VOL_TIMEOUT); 50611798b011c962b602217b479130d413f3b30f19aLiejun Tao 50711798b011c962b602217b479130d413f3b30f19aLiejun Tao volAdj = mVolCmdAdjustInProgress; 50811798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = false; 50911798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = false; 51017675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes = 0; 51117675906064bb72fdcca75baa56cdf8bb8968d01John Du } 51211798b011c962b602217b479130d413f3b30f19aLiejun Tao 513e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte absVol = (byte) ((byte) msg.arg1 & 0x7f); // discard MSB as it is RFD 51411798b011c962b602217b479130d413f3b30f19aLiejun Tao // convert remote volume to local volume 51511798b011c962b602217b479130d413f3b30f19aLiejun Tao int volIndex = convertToAudioStreamVolume(absVol); 51611798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mInitialRemoteVolume == -1) { 51711798b011c962b602217b479130d413f3b30f19aLiejun Tao mInitialRemoteVolume = absVol; 51811798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mAbsVolThreshold > 0 && mAbsVolThreshold < mAudioStreamMax && volIndex > mAbsVolThreshold) { 51911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.v(TAG, "remote inital volume too high " + volIndex + ">" + mAbsVolThreshold); 520e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg1 = mHandler.obtainMessage(MSG_SET_ABSOLUTE_VOLUME, mAbsVolThreshold , 0); 52111798b011c962b602217b479130d413f3b30f19aLiejun Tao mHandler.sendMessage(msg1); 52211798b011c962b602217b479130d413f3b30f19aLiejun Tao mRemoteVolume = absVol; 52311798b011c962b602217b479130d413f3b30f19aLiejun Tao mLocalVolume = volIndex; 52411798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 52511798b011c962b602217b479130d413f3b30f19aLiejun Tao } 52611798b011c962b602217b479130d413f3b30f19aLiejun Tao } 52711798b011c962b602217b479130d413f3b30f19aLiejun Tao 5280e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen if (mLocalVolume != volIndex && (msg.arg2 == AVRC_RSP_ACCEPT || 5290e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen msg.arg2 == AVRC_RSP_CHANGED || 5300e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen msg.arg2 == AVRC_RSP_INTERIM)) { 53111798b011c962b602217b479130d413f3b30f19aLiejun Tao /* If the volume has successfully changed */ 53211798b011c962b602217b479130d413f3b30f19aLiejun Tao mLocalVolume = volIndex; 53311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mLastLocalVolume != -1 && msg.arg2 == AVRC_RSP_ACCEPT) { 53411798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mLastLocalVolume != volIndex) { 53511798b011c962b602217b479130d413f3b30f19aLiejun Tao /* remote volume changed more than requested due to 53611798b011c962b602217b479130d413f3b30f19aLiejun Tao * local and remote has different volume steps */ 53711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "Remote returned volume does not match desired volume " 538e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + mLastLocalVolume + " vs " + volIndex); 53911798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = mLocalVolume; 54011798b011c962b602217b479130d413f3b30f19aLiejun Tao } 54111798b011c962b602217b479130d413f3b30f19aLiejun Tao } 54211798b011c962b602217b479130d413f3b30f19aLiejun Tao // remember the remote volume value, as it's the one supported by remote 54311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (volAdj) { 54411798b011c962b602217b479130d413f3b30f19aLiejun Tao synchronized (mVolumeMapping) { 545e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mVolumeMapping.put(volIndex, (int) absVol); 54611798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.v(TAG, "remember volume mapping " +volIndex+ "-"+absVol); 54711798b011c962b602217b479130d413f3b30f19aLiejun Tao } 54811798b011c962b602217b479130d413f3b30f19aLiejun Tao } 54911798b011c962b602217b479130d413f3b30f19aLiejun Tao 55011798b011c962b602217b479130d413f3b30f19aLiejun Tao notifyVolumeChanged(mLocalVolume); 55111798b011c962b602217b479130d413f3b30f19aLiejun Tao mRemoteVolume = absVol; 552e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah long pecentVolChanged = ((long) absVol * 100) / 0x7f; 5535c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta Log.e(TAG, "percent volume changed: " + pecentVolChanged + "%"); 55417675906064bb72fdcca75baa56cdf8bb8968d01John Du } else if (msg.arg2 == AVRC_RSP_REJ) { 55517675906064bb72fdcca75baa56cdf8bb8968d01John Du Log.e(TAG, "setAbsoluteVolume call rejected"); 55611798b011c962b602217b479130d413f3b30f19aLiejun Tao } else if (volAdj && mLastRemoteVolume > 0 && mLastRemoteVolume < AVRCP_MAX_VOL && 5570e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen mLocalVolume == volIndex && 558e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah (msg.arg2 == AVRC_RSP_ACCEPT)) { 55911798b011c962b602217b479130d413f3b30f19aLiejun Tao /* oops, the volume is still same, remote does not like the value 56011798b011c962b602217b479130d413f3b30f19aLiejun Tao * retry a volume one step up/down */ 56111798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "Remote device didn't tune volume, let's try one more step."); 56211798b011c962b602217b479130d413f3b30f19aLiejun Tao int retry_volume = Math.min(AVRCP_MAX_VOL, 56311798b011c962b602217b479130d413f3b30f19aLiejun Tao Math.max(0, mLastRemoteVolume + mLastDirection)); 56411798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVolumeNative(retry_volume)) { 56511798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastRemoteVolume = retry_volume; 566e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah sendMessageDelayed(obtainMessage(MSG_ABS_VOL_TIMEOUT), CMD_TIMEOUT_DELAY); 56711798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = true; 56811798b011c962b602217b479130d413f3b30f19aLiejun Tao } 56917675906064bb72fdcca75baa56cdf8bb8968d01John Du } 57017675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 57117675906064bb72fdcca75baa56cdf8bb8968d01John Du 572e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_ADJUST_VOLUME: 57311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (!isAbsoluteVolumeSupported()) { 574e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "ignore MSG_ADJUST_VOLUME"); 57511798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 57611798b011c962b602217b479130d413f3b30f19aLiejun Tao } 57711798b011c962b602217b479130d413f3b30f19aLiejun Tao 578e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "MSG_ADJUST_VOLUME: direction=" + msg.arg1); 57911798b011c962b602217b479130d413f3b30f19aLiejun Tao 58011798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolCmdAdjustInProgress || mVolCmdSetInProgress) { 58117675906064bb72fdcca75baa56cdf8bb8968d01John Du if (DEBUG) Log.w(TAG, "There is already a volume command in progress."); 58217675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 58317675906064bb72fdcca75baa56cdf8bb8968d01John Du } 58411798b011c962b602217b479130d413f3b30f19aLiejun Tao 58511798b011c962b602217b479130d413f3b30f19aLiejun Tao // Remote device didn't set initial volume. Let's black list it 58611798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mInitialRemoteVolume == -1) { 58711798b011c962b602217b479130d413f3b30f19aLiejun Tao Log.d(TAG, "remote " + mAddress + " never tell us initial volume, black list it."); 58811798b011c962b602217b479130d413f3b30f19aLiejun Tao blackListCurrentDevice(); 58911798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 59011798b011c962b602217b479130d413f3b30f19aLiejun Tao } 59111798b011c962b602217b479130d413f3b30f19aLiejun Tao 59217675906064bb72fdcca75baa56cdf8bb8968d01John Du // Wait on verification on volume from device, before changing the volume. 59311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mRemoteVolume != -1 && (msg.arg1 == -1 || msg.arg1 == 1)) { 59411798b011c962b602217b479130d413f3b30f19aLiejun Tao int setVol = -1; 59511798b011c962b602217b479130d413f3b30f19aLiejun Tao int targetVolIndex = -1; 59611798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mLocalVolume == 0 && msg.arg1 == -1) { 59711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.w(TAG, "No need to Vol down from 0."); 59811798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 59911798b011c962b602217b479130d413f3b30f19aLiejun Tao } 60011798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mLocalVolume == mAudioStreamMax && msg.arg1 == 1) { 60111798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.w(TAG, "No need to Vol up from max."); 60211798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 60311798b011c962b602217b479130d413f3b30f19aLiejun Tao } 60411798b011c962b602217b479130d413f3b30f19aLiejun Tao 60511798b011c962b602217b479130d413f3b30f19aLiejun Tao targetVolIndex = mLocalVolume + msg.arg1; 60611798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "Adjusting volume to " + targetVolIndex); 60711798b011c962b602217b479130d413f3b30f19aLiejun Tao 60811798b011c962b602217b479130d413f3b30f19aLiejun Tao Integer i; 60911798b011c962b602217b479130d413f3b30f19aLiejun Tao synchronized (mVolumeMapping) { 61011798b011c962b602217b479130d413f3b30f19aLiejun Tao i = mVolumeMapping.get(targetVolIndex); 61111798b011c962b602217b479130d413f3b30f19aLiejun Tao } 61211798b011c962b602217b479130d413f3b30f19aLiejun Tao 61311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (i != null) { 61411798b011c962b602217b479130d413f3b30f19aLiejun Tao /* if we already know this volume mapping, use it */ 61511798b011c962b602217b479130d413f3b30f19aLiejun Tao setVol = i.byteValue(); 61611798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVol == mRemoteVolume) { 61711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "got same volume from mapping for " + targetVolIndex + ", ignore."); 61811798b011c962b602217b479130d413f3b30f19aLiejun Tao setVol = -1; 61911798b011c962b602217b479130d413f3b30f19aLiejun Tao } 62011798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "set volume from mapping " + targetVolIndex + "-" + setVol); 62111798b011c962b602217b479130d413f3b30f19aLiejun Tao } 62211798b011c962b602217b479130d413f3b30f19aLiejun Tao 62311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVol == -1) { 62411798b011c962b602217b479130d413f3b30f19aLiejun Tao /* otherwise use phone steps */ 62511798b011c962b602217b479130d413f3b30f19aLiejun Tao setVol = Math.min(AVRCP_MAX_VOL, 626e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah convertToAvrcpVolume(Math.max(0, targetVolIndex))); 62711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "set volume from local volume "+ targetVolIndex+"-"+ setVol); 62811798b011c962b602217b479130d413f3b30f19aLiejun Tao } 62911798b011c962b602217b479130d413f3b30f19aLiejun Tao 63017675906064bb72fdcca75baa56cdf8bb8968d01John Du if (setVolumeNative(setVol)) { 631e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah sendMessageDelayed(obtainMessage(MSG_ABS_VOL_TIMEOUT), CMD_TIMEOUT_DELAY); 63211798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = true; 63317675906064bb72fdcca75baa56cdf8bb8968d01John Du mLastDirection = msg.arg1; 63411798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastRemoteVolume = setVol; 63511798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = targetVolIndex; 63611798b011c962b602217b479130d413f3b30f19aLiejun Tao } else { 63711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "setVolumeNative failed"); 63817675906064bb72fdcca75baa56cdf8bb8968d01John Du } 63917675906064bb72fdcca75baa56cdf8bb8968d01John Du } else { 640e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "Unknown direction in MSG_ADJUST_VOLUME"); 64117675906064bb72fdcca75baa56cdf8bb8968d01John Du } 64217675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 64317675906064bb72fdcca75baa56cdf8bb8968d01John Du 644e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_SET_ABSOLUTE_VOLUME: 64511798b011c962b602217b479130d413f3b30f19aLiejun Tao if (!isAbsoluteVolumeSupported()) { 646e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "ignore MSG_SET_ABSOLUTE_VOLUME"); 64711798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 64811798b011c962b602217b479130d413f3b30f19aLiejun Tao } 64911798b011c962b602217b479130d413f3b30f19aLiejun Tao 650e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_SET_ABSOLUTE_VOLUME"); 65111798b011c962b602217b479130d413f3b30f19aLiejun Tao 65211798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolCmdSetInProgress || mVolCmdAdjustInProgress) { 65317675906064bb72fdcca75baa56cdf8bb8968d01John Du if (DEBUG) Log.w(TAG, "There is already a volume command in progress."); 65417675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 65517675906064bb72fdcca75baa56cdf8bb8968d01John Du } 65611798b011c962b602217b479130d413f3b30f19aLiejun Tao 65711798b011c962b602217b479130d413f3b30f19aLiejun Tao // Remote device didn't set initial volume. Let's black list it 65811798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mInitialRemoteVolume == -1) { 65911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "remote " + mAddress + " never tell us initial volume, black list it."); 66011798b011c962b602217b479130d413f3b30f19aLiejun Tao blackListCurrentDevice(); 66111798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 66211798b011c962b602217b479130d413f3b30f19aLiejun Tao } 66311798b011c962b602217b479130d413f3b30f19aLiejun Tao 66411798b011c962b602217b479130d413f3b30f19aLiejun Tao int avrcpVolume = convertToAvrcpVolume(msg.arg1); 66511798b011c962b602217b479130d413f3b30f19aLiejun Tao avrcpVolume = Math.min(AVRCP_MAX_VOL, Math.max(0, avrcpVolume)); 6663b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (DEBUG) Log.d(TAG, "Setting volume to " + msg.arg1 + "-" + avrcpVolume); 66711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVolumeNative(avrcpVolume)) { 668e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah sendMessageDelayed(obtainMessage(MSG_ABS_VOL_TIMEOUT), CMD_TIMEOUT_DELAY); 66911798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = true; 67011798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastRemoteVolume = avrcpVolume; 67111798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = msg.arg1; 67211798b011c962b602217b479130d413f3b30f19aLiejun Tao } else { 67311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "setVolumeNative failed"); 67417675906064bb72fdcca75baa56cdf8bb8968d01John Du } 67517675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 67617675906064bb72fdcca75baa56cdf8bb8968d01John Du 677e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_ABS_VOL_TIMEOUT: 678e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_ABS_VOL_TIMEOUT: Volume change cmd timed out."); 67911798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = false; 68011798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = false; 68117675906064bb72fdcca75baa56cdf8bb8968d01John Du if (mAbsVolRetryTimes >= MAX_ERROR_RETRY_TIMES) { 68217675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes = 0; 683f8201e1c6bf7fadc0a332151a652325a7f31255aLiejun Tao /* too many volume change failures, black list the device */ 684f8201e1c6bf7fadc0a332151a652325a7f31255aLiejun Tao blackListCurrentDevice(); 68517675906064bb72fdcca75baa56cdf8bb8968d01John Du } else { 68617675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes += 1; 68711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVolumeNative(mLastRemoteVolume)) { 688e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah sendMessageDelayed(obtainMessage(MSG_ABS_VOL_TIMEOUT), CMD_TIMEOUT_DELAY); 68911798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = true; 69017675906064bb72fdcca75baa56cdf8bb8968d01John Du } 69117675906064bb72fdcca75baa56cdf8bb8968d01John Du } 69217675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 69317675906064bb72fdcca75baa56cdf8bb8968d01John Du 694e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_SET_A2DP_AUDIO_STATE: 695e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_SET_A2DP_AUDIO_STATE:" + msg.arg1); 6960a429916782c20980e7f0893c503c633b8341f88Marie Janssen mA2dpState = msg.arg1; 6970a429916782c20980e7f0893c503c633b8341f88Marie Janssen updateCurrentMediaState(); 698188f205b5f093850d4cc627917a21204be36c56aZhihai Xu break; 699e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 700e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_FOLDER_ITEMS: { 701e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd.FolderItemsCmd folderObj = (AvrcpCmd.FolderItemsCmd) msg.obj; 70289728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_GET_FOLDER_ITEMS " + folderObj); 703e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah switch (folderObj.mScope) { 704e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case AvrcpConstants.BTRC_SCOPE_PLAYER_LIST: 705e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handleMediaPlayerListRsp(folderObj); 706e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 707e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case AvrcpConstants.BTRC_SCOPE_FILE_SYSTEM: 708e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case AvrcpConstants.BTRC_SCOPE_NOW_PLAYING: 709e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handleGetFolderItemBrowseResponse(folderObj, folderObj.mAddress); 710e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 711e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah default: 712e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "unknown scope for getfolderitems. scope = " 713e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + folderObj.mScope); 714e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah getFolderItemsRspNative(folderObj.mAddress, 715e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpConstants.RSP_INV_SCOPE, (short) 0, (byte) 0, 0, 716e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah null, null, null, null, null, null, null, null); 717e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 718e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 719e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 720e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 721e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_SET_ADDR_PLAYER: 722e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // object is bdaddr, argument 1 is the selected player id 723294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_SET_ADDR_PLAYER id=" + msg.arg1); 724e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah setAddressedPlayer((byte[]) msg.obj, msg.arg1); 725e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 726e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 727e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_ITEM_ATTR: 728e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // msg object contains the item attribute object 72989728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen AvrcpCmd.ItemAttrCmd cmd = (AvrcpCmd.ItemAttrCmd) msg.obj; 73089728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_GET_ITEM_ATTR " + cmd); 73189728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen handleGetItemAttr(cmd); 732e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 733e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 734e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_SET_BR_PLAYER: 735e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // argument 1 is the selected player id 736294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_SET_BR_PLAYER id=" + msg.arg1); 737e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah setBrowsedPlayer((byte[]) msg.obj, msg.arg1); 738e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 739e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 740e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_CHANGE_PATH: 741e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah { 742294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_CHANGE_PATH"); 743e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = msg.getData(); 744e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] bdaddr = data.getByteArray("BdAddress"); 745e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] folderUid = data.getByteArray("folderUid"); 746e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte direction = data.getByte("direction"); 747e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr) != null) { 748e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr).changePath(folderUid, 749e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah direction); 750e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 751e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "Remote requesting change path before setbrowsedplayer"); 752e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah changePathRspNative(bdaddr, AvrcpConstants.RSP_BAD_CMD, 0); 753e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 754e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 755e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 756e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 757e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_PLAY_ITEM: 758e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah { 759e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = msg.getData(); 760e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] bdaddr = data.getByteArray("BdAddress"); 761e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] uid = data.getByteArray("uid"); 762e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte scope = data.getByte("scope"); 76389728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen if (DEBUG) 76489728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen Log.v(TAG, "MSG_NATIVE_REQ_PLAY_ITEM scope=" + scope + " id=" 76589728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen + Utils.byteArrayToString(uid)); 766e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handlePlayItemResponse(bdaddr, uid, scope); 767e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 768e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 769e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 770e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_TOTAL_NUM_OF_ITEMS: 771294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_GET_TOTAL_NUM_OF_ITEMS scope=" + msg.arg1); 772e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // argument 1 is scope, object is bdaddr 773e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handleGetTotalNumOfItemsResponse((byte[]) msg.obj, (byte) msg.arg1); 774e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 775e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 776e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_PASS_THROUGH: 777294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen if (DEBUG) 77805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.v(TAG, "MSG_NATIVE_REQ_PASS_THROUGH: id=" + msg.arg1 + " st=" + msg.arg2); 77905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen // argument 1 is id, argument 2 is keyState 78005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen handlePassthroughCmd(msg.arg1, msg.arg2); 781e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 782e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 783e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah default: 784e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "unknown message! msg.what=" + msg.what); 785e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 786c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 787c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 788c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 789c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 790f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen private void updatePlaybackState(PlaybackState state) { 7910e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen if (state == null) { 7920e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen state = new PlaybackState.Builder().setState(PlaybackState.STATE_NONE, 793e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah PlaybackState.PLAYBACK_POSITION_UNKNOWN, 0.0f).build(); 7940e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen } 795f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 7960a429916782c20980e7f0893c503c633b8341f88Marie Janssen byte stateBytes = (byte) convertPlayStateToBytes(state.getState()); 7970a429916782c20980e7f0893c503c633b8341f88Marie Janssen 7980a429916782c20980e7f0893c503c633b8341f88Marie Janssen /* updating play status in global media player list */ 7990a429916782c20980e7f0893c503c633b8341f88Marie Janssen MediaPlayerInfo player = getAddressedPlayerInfo(); 8000a429916782c20980e7f0893c503c633b8341f88Marie Janssen if (player != null) { 8010a429916782c20980e7f0893c503c633b8341f88Marie Janssen player.setPlayStatus(stateBytes); 8020a429916782c20980e7f0893c503c633b8341f88Marie Janssen } else { 8030a429916782c20980e7f0893c503c633b8341f88Marie Janssen Log.w(TAG, "onPlaybackStateChanged: no addressed player id=" + mCurrAddrPlayerID); 8040a429916782c20980e7f0893c503c633b8341f88Marie Janssen } 8050a429916782c20980e7f0893c503c633b8341f88Marie Janssen 806fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen int oldPlayStatus = convertPlayStateToPlayStatus(mCurrentPlayState); 807c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu int newPlayStatus = convertPlayStateToPlayStatus(state); 808f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu 809fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen if (DEBUG) { 810fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen Log.v(TAG, "updatePlaybackState (" + mPlayStatusChangedNT + "): "+ 811e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah "old=" + mCurrentPlayState + "(" + oldPlayStatus + "), "+ 812e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah "new=" + state + "(" + newPlayStatus + ")"); 813fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen } 814fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen 815aa6c1cb7f08a5d1fe2c878b587c62cf4dbb6ee8fZhihai Xu mCurrentPlayState = state; 816aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 817f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen sendPlayPosNotificationRsp(false); 818aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 819e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mPlayStatusChangedNT == AvrcpConstants.NOTIFICATION_TYPE_INTERIM && 820e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah (oldPlayStatus != newPlayStatus)) { 821e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPlayStatusChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 822c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu registerNotificationRspPlayStatusNative(mPlayStatusChangedNT, newPlayStatus); 823c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 824c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 825c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 826c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private void updateTransportControls(int transportControlFlags) { 827c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mTransportControlFlags = transportControlFlags; 828c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 829c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 8303b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen class MediaAttributes { 8313b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private boolean exists; 8323b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String title; 8333b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String artistName; 8343b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String albumName; 8353b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String mediaNumber; 8363b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String mediaTotalNumber; 8373b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String genre; 8380a429916782c20980e7f0893c503c633b8341f88Marie Janssen private long playingTimeMs; 8393b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 8403b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_TITLE = 1; 8413b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_ARTIST_NAME = 2; 8423b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_ALBUM_NAME = 3; 8433b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_MEDIA_NUMBER = 4; 8443b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_MEDIA_TOTAL_NUMBER = 5; 8453b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_GENRE = 6; 8463b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_PLAYING_TIME_MS = 7; 8473b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 8483b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 8493b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen public MediaAttributes(MediaMetadata data) { 8503b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen exists = data != null; 8513b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (!exists) 8523b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return; 8533b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 8543b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen artistName = stringOrBlank(data.getString(MediaMetadata.METADATA_KEY_ARTIST)); 8553b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen albumName = stringOrBlank(data.getString(MediaMetadata.METADATA_KEY_ALBUM)); 8563b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen mediaNumber = longStringOrBlank(data.getLong(MediaMetadata.METADATA_KEY_TRACK_NUMBER)); 8573b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen mediaTotalNumber = longStringOrBlank(data.getLong(MediaMetadata.METADATA_KEY_NUM_TRACKS)); 8583b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen genre = stringOrBlank(data.getString(MediaMetadata.METADATA_KEY_GENRE)); 8590a429916782c20980e7f0893c503c633b8341f88Marie Janssen playingTimeMs = data.getLong(MediaMetadata.METADATA_KEY_DURATION); 8603b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 8613b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen // Try harder for the title. 8623b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen title = data.getString(MediaMetadata.METADATA_KEY_TITLE); 8633b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 8643b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (title == null) { 8653b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen MediaDescription desc = data.getDescription(); 8663b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (desc != null) { 8673b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen CharSequence val = desc.getDescription(); 8683b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (val != null) 8693b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen title = val.toString(); 8703b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 8713b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 8723b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 8733b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (title == null) 8743b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen title = new String(); 8753b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 8763b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 8770a429916782c20980e7f0893c503c633b8341f88Marie Janssen public long getLength() { 8780a429916782c20980e7f0893c503c633b8341f88Marie Janssen if (!exists) return 0L; 8790a429916782c20980e7f0893c503c633b8341f88Marie Janssen return playingTimeMs; 8800a429916782c20980e7f0893c503c633b8341f88Marie Janssen } 8810a429916782c20980e7f0893c503c633b8341f88Marie Janssen 8823b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen public boolean equals(MediaAttributes other) { 8833b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (other == null) 8843b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return false; 8853b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 8863b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (exists != other.exists) 8873b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return false; 8883b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 8893b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (exists == false) 8903b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return true; 8913b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 8920a429916782c20980e7f0893c503c633b8341f88Marie Janssen return (title.equals(other.title)) && (artistName.equals(other.artistName)) 8930a429916782c20980e7f0893c503c633b8341f88Marie Janssen && (albumName.equals(other.albumName)) 8940a429916782c20980e7f0893c503c633b8341f88Marie Janssen && (mediaNumber.equals(other.mediaNumber)) 8950a429916782c20980e7f0893c503c633b8341f88Marie Janssen && (mediaTotalNumber.equals(other.mediaTotalNumber)) 8960a429916782c20980e7f0893c503c633b8341f88Marie Janssen && (genre.equals(other.genre)) && (playingTimeMs == other.playingTimeMs); 8973b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 8983b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 8993b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen public String getString(int attrId) { 9003b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (!exists) 9013b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return new String(); 9023b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9033b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen switch (attrId) { 9043b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_TITLE: 9053b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return title; 9063b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_ARTIST_NAME: 9073b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return artistName; 9083b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_ALBUM_NAME: 9093b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return albumName; 9103b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_MEDIA_NUMBER: 9113b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return mediaNumber; 9123b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_MEDIA_TOTAL_NUMBER: 9133b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return mediaTotalNumber; 9143b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_GENRE: 9153b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return genre; 9163b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_PLAYING_TIME_MS: 9170a429916782c20980e7f0893c503c633b8341f88Marie Janssen return Long.toString(playingTimeMs); 9183b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen default: 9193b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return new String(); 9203b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 9213b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 9223b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9233b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String stringOrBlank(String s) { 9243b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return s == null ? new String() : s; 9253b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 926c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 9273b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String longStringOrBlank(Long s) { 9283b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return s == null ? new String() : s.toString(); 929c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 930c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 931c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public String toString() { 932e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!exists) { 9333b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return "[MediaAttributes: none]"; 934e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 9353b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9360a429916782c20980e7f0893c503c633b8341f88Marie Janssen return "[MediaAttributes: " + title + " - " + albumName + " by " + artistName + " (" 9370a429916782c20980e7f0893c503c633b8341f88Marie Janssen + playingTimeMs + " " + mediaNumber + "/" + mediaTotalNumber + ") " + genre 9380a429916782c20980e7f0893c503c633b8341f88Marie Janssen + "]"; 939c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 940c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 941c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 9420a429916782c20980e7f0893c503c633b8341f88Marie Janssen private void updateCurrentMediaState() { 943384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen MediaAttributes currentAttributes = mMediaAttributes; 944384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen PlaybackState newState = mCurrentPlayState; 9450a429916782c20980e7f0893c503c633b8341f88Marie Janssen if (mMediaController == null) { 9460a429916782c20980e7f0893c503c633b8341f88Marie Janssen // Use A2DP state if we don't have a MediaControlller 947384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen boolean isPlaying = 948384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen (mA2dpState == BluetoothA2dp.STATE_PLAYING) && mAudioManager.isMusicActive(); 9490a429916782c20980e7f0893c503c633b8341f88Marie Janssen if (isPlaying != isPlayingState(mCurrentPlayState)) { 9500a429916782c20980e7f0893c503c633b8341f88Marie Janssen /* if a2dp is streaming, check to make sure music is active */ 9510a429916782c20980e7f0893c503c633b8341f88Marie Janssen PlaybackState.Builder builder = new PlaybackState.Builder(); 9520a429916782c20980e7f0893c503c633b8341f88Marie Janssen if (isPlaying) { 9530a429916782c20980e7f0893c503c633b8341f88Marie Janssen builder.setState(PlaybackState.STATE_PLAYING, 9540a429916782c20980e7f0893c503c633b8341f88Marie Janssen PlaybackState.PLAYBACK_POSITION_UNKNOWN, 1.0f); 9550a429916782c20980e7f0893c503c633b8341f88Marie Janssen } else { 9560a429916782c20980e7f0893c503c633b8341f88Marie Janssen builder.setState(PlaybackState.STATE_PAUSED, 9570a429916782c20980e7f0893c503c633b8341f88Marie Janssen PlaybackState.PLAYBACK_POSITION_UNKNOWN, 0.0f); 9580a429916782c20980e7f0893c503c633b8341f88Marie Janssen } 959384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen newState = builder.build(); 9600a429916782c20980e7f0893c503c633b8341f88Marie Janssen } 961384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen mMediaAttributes = new MediaAttributes(null); 962384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } else { 963384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen newState = mMediaController.getPlaybackState(); 964384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen mMediaAttributes = new MediaAttributes(mMediaController.getMetadata()); 9650e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen } 966e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 967384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen if (!currentAttributes.equals(mMediaAttributes)) { 9683b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen Log.v(TAG, "MediaAttributes Changed to " + mMediaAttributes.toString()); 969e23a886e79f60a3f7f5b8e87f8c5ffc26134bd32Marie Janssen mTracksPlayed++; 9700a429916782c20980e7f0893c503c633b8341f88Marie Janssen sendTrackChangedRsp(false); 971c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 972aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 973384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen updatePlaybackState(newState); 974c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 975c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 976e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void getRcFeaturesRequestFromNative(byte[] address, int features) { 977e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "getRcFeaturesRequestFromNative: address=" + address.toString()); 978e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_RC_FEATURES, features, 0, 979e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Utils.getAddressStringFromByte(address)); 98017675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 98117675906064bb72fdcca75baa56cdf8bb8968d01John Du } 98217675906064bb72fdcca75baa56cdf8bb8968d01John Du 983e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void getPlayStatusRequestFromNative(byte[] address) { 984e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "getPlayStatusRequestFromNative: address" + address.toString()); 985e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_PLAY_STATUS); 986e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = address; 987c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.sendMessage(msg); 988c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 989c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 99089728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen private void getElementAttrRequestFromNative(byte[] address, byte numAttr, int[] attrs) { 991e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "getElementAttrRequestFromNative: numAttr=" + numAttr); 992e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd avrcpCmdobj = new AvrcpCmd(); 993e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd.ElementAttrCmd elemAttr = avrcpCmdobj.new ElementAttrCmd(address, numAttr, attrs); 994e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_ELEM_ATTRS); 995e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = elemAttr; 996c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.sendMessage(msg); 997c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 998c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 999e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void registerNotificationRequestFromNative(byte[] address,int eventId, int param) { 1000e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "registerNotificationRequestFromNative: eventId=" + eventId); 1001e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_REGISTER_NOTIFICATION, eventId, param); 1002e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = address; 1003c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.sendMessage(msg); 1004c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1005c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1006e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void processRegisterNotification(byte[] address, int eventId, int param) { 1007c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu switch (eventId) { 1008c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case EVT_PLAY_STATUS_CHANGED: 1009e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPlayStatusChangedNT = AvrcpConstants.NOTIFICATION_TYPE_INTERIM; 1010c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu registerNotificationRspPlayStatusNative(mPlayStatusChangedNT, 10110e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen convertPlayStateToPlayStatus(mCurrentPlayState)); 1012c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 1013c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1014c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case EVT_TRACK_CHANGED: 10150e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen Log.v(TAG, "Track changed notification enabled"); 1016e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_INTERIM; 10170a429916782c20980e7f0893c503c633b8341f88Marie Janssen sendTrackChangedRsp(true); 1018c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 1019c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1020aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu case EVT_PLAY_POS_CHANGED: 1021e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPlayPosChangedNT = AvrcpConstants.NOTIFICATION_TYPE_INTERIM; 1022e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPlaybackIntervalMs = (long) param * 1000L; 1023fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen sendPlayPosNotificationRsp(true); 1024aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu break; 1025aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 1026e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case EVT_AVBL_PLAYERS_CHANGED: 1027e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Notify remote available players changed */ 1028e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d (TAG, "sending availablePlayersChanged to remote "); 1029e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah registerNotificationRspAvalPlayerChangedNative( 1030e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpConstants.NOTIFICATION_TYPE_INTERIM); 1031e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 1032e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1033e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case EVT_ADDR_PLAYER_CHANGED: 1034e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Notify remote addressed players changed */ 1035e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d (TAG, "sending addressedPlayersChanged to remote "); 1036e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah registerNotificationRspAddrPlayerChangedNative( 1037e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpConstants.NOTIFICATION_TYPE_INTERIM, 1038e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mCurrAddrPlayerID, sUIDCounter); 1039e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 1040e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1041e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case EVENT_UIDS_CHANGED: 1042e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "sending UIDs changed to remote"); 1043e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah registerNotificationRspUIDsChangedNative( 1044e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpConstants.NOTIFICATION_TYPE_INTERIM, sUIDCounter); 1045e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 1046e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1047e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case EVENT_NOW_PLAYING_CONTENT_CHANGED: 1048e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "sending NowPlayingList changed to remote"); 1049e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* send interim response to remote device */ 1050e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspNowPlayingChangedNative( 1051e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpConstants.NOTIFICATION_TYPE_INTERIM)) { 1052e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "EVENT_NOW_PLAYING_CONTENT_CHANGED: " + 1053e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah "registerNotificationRspNowPlayingChangedNative for Interim rsp failed!"); 1054e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1055e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 1056c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1057c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1058c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1059e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handlePassthroughCmdRequestFromNative(byte[] address, int id, int keyState) { 106005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_PASS_THROUGH, id, keyState); 1061e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1062ace834feb02adabd61f628c4471147aea02d939cJohn Du } 1063ace834feb02adabd61f628c4471147aea02d939cJohn Du 10640a429916782c20980e7f0893c503c633b8341f88Marie Janssen private void sendTrackChangedRsp(boolean requested) { 1065eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen MediaPlayerInfo info = getAddressedPlayerInfo(); 1066eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen if (info != null && !info.isBrowseSupported()) { 1067eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen // for players which does not support Browse or when no track is currently selected 10680a429916782c20980e7f0893c503c633b8341f88Marie Janssen trackChangeRspForBrowseUnsupported(requested); 1069e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 10700a429916782c20980e7f0893c503c633b8341f88Marie Janssen boolean changed = 10710a429916782c20980e7f0893c503c633b8341f88Marie Janssen mAddressedMediaPlayer.sendTrackChangeWithId(requested, mMediaController); 1072e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // for players which support browsing 10730a429916782c20980e7f0893c503c633b8341f88Marie Janssen if (changed) mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 1074e8e870c24930f9b687572dbb80614e5aad6fbdfaberyl hou } 1075e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1076e8e870c24930f9b687572dbb80614e5aad6fbdfaberyl hou 10770a429916782c20980e7f0893c503c633b8341f88Marie Janssen private void trackChangeRspForBrowseUnsupported(boolean requested) { 1078e23a886e79f60a3f7f5b8e87f8c5ffc26134bd32Marie Janssen byte[] track = AvrcpConstants.TRACK_IS_SELECTED; 10790a429916782c20980e7f0893c503c633b8341f88Marie Janssen if (requested && !mMediaAttributes.exists) { 1080e23a886e79f60a3f7f5b8e87f8c5ffc26134bd32Marie Janssen track = AvrcpConstants.NO_TRACK_SELECTED; 10810a429916782c20980e7f0893c503c633b8341f88Marie Janssen } else if (!requested) { 10820a429916782c20980e7f0893c503c633b8341f88Marie Janssen mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 1083c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1084c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu registerNotificationRspTrackChangeNative(mTrackChangedNT, track); 1085c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1086c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1087aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long getPlayPosition() { 1088e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mCurrentPlayState == null) { 1089f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen return -1L; 1090e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1091f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 1092e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mCurrentPlayState.getPosition() == PlaybackState.PLAYBACK_POSITION_UNKNOWN) { 1093f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen return -1L; 1094e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1095f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 1096f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen if (isPlayingState(mCurrentPlayState)) { 10970a429916782c20980e7f0893c503c633b8341f88Marie Janssen long sinceUpdate = 10980a429916782c20980e7f0893c503c633b8341f88Marie Janssen (SystemClock.elapsedRealtime() - mCurrentPlayState.getLastPositionUpdateTime()); 10990a429916782c20980e7f0893c503c633b8341f88Marie Janssen return sinceUpdate + mCurrentPlayState.getPosition(); 1100aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 1101f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 11023635a926bd7316a55b288a54d409a1070a9c19e8Marie Janssen return mCurrentPlayState.getPosition(); 1103aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 1104aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 11050e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen private int convertPlayStateToPlayStatus(PlaybackState state) { 1106c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu int playStatus = PLAYSTATUS_ERROR; 11070e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen switch (state.getState()) { 11080e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen case PlaybackState.STATE_PLAYING: 11090e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen case PlaybackState.STATE_BUFFERING: 1110c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_PLAYING; 1111c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 1112c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 11130e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen case PlaybackState.STATE_STOPPED: 11140e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen case PlaybackState.STATE_NONE: 1115c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_STOPPED; 1116c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 1117c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 11180e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen case PlaybackState.STATE_PAUSED: 1119c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_PAUSED; 1120c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 1121c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 11220e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen case PlaybackState.STATE_FAST_FORWARDING: 11230e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen case PlaybackState.STATE_SKIPPING_TO_NEXT: 11240e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen case PlaybackState.STATE_SKIPPING_TO_QUEUE_ITEM: 1125c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_FWD_SEEK; 1126c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 1127c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 11280e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen case PlaybackState.STATE_REWINDING: 11290e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen case PlaybackState.STATE_SKIPPING_TO_PREVIOUS: 1130c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_REV_SEEK; 1131c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 1132c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 11330e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen case PlaybackState.STATE_ERROR: 1134c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_ERROR; 1135c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 1136c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1137c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1138c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return playStatus; 1139c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1140c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 11410e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen private boolean isPlayingState(PlaybackState state) { 11420e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen return (state.getState() == PlaybackState.STATE_PLAYING) || 1143e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah (state.getState() == PlaybackState.STATE_BUFFERING); 1144188f205b5f093850d4cc627917a21204be36c56aZhihai Xu } 1145188f205b5f093850d4cc627917a21204be36c56aZhihai Xu 114617675906064bb72fdcca75baa56cdf8bb8968d01John Du /** 1147f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen * Sends a play position notification, or schedules one to be 1148f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen * sent later at an appropriate time. If |requested| is true, 1149f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen * does both because this was called in reponse to a request from the 1150f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen * TG. 1151f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen */ 1152f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen private void sendPlayPosNotificationRsp(boolean requested) { 1153e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!requested && mPlayPosChangedNT != AvrcpConstants.NOTIFICATION_TYPE_INTERIM) { 1154fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen if (DEBUG) Log.d(TAG, "sendPlayPosNotificationRsp: Not registered or requesting."); 1155fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen return; 1156fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen } 1157fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen 1158f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen long playPositionMs = getPlayPosition(); 1159f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 1160f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen // mNextPosMs is set to -1 when the previous position was invalid 1161f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen // so this will be true if the new position is valid & old was invalid. 1162f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen // mPlayPositionMs is set to -1 when the new position is invalid, 1163f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen // and the old mPrevPosMs is >= 0 so this is true when the new is invalid 1164f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen // and the old was valid. 1165fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen if (DEBUG) Log.d(TAG, "sendPlayPosNotificationRsp: (" + requested + ") " 1166e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + mPrevPosMs + " <=? " + playPositionMs + " <=? " + mNextPosMs); 116705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (DEBUG) Log.d(TAG, "sendPlayPosNotificationRsp: currentPlayState " + mCurrentPlayState); 1168fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen if (requested || ((mLastReportedPosition != playPositionMs) && 1169e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah (playPositionMs >= mNextPosMs) || (playPositionMs <= mPrevPosMs))) { 1170e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!requested) mPlayPosChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 1171e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah registerNotificationRspPlayPosNative(mPlayPosChangedNT, (int) playPositionMs); 1172fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen mLastReportedPosition = playPositionMs; 1173f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen if (playPositionMs != PlaybackState.PLAYBACK_POSITION_UNKNOWN) { 1174f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen mNextPosMs = playPositionMs + mPlaybackIntervalMs; 1175f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen mPrevPosMs = playPositionMs - mPlaybackIntervalMs; 1176f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } else { 1177f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen mNextPosMs = -1; 1178f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen mPrevPosMs = -1; 1179f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } 1180f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } 1181f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 1182e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.removeMessages(MSG_PLAY_INTERVAL_TIMEOUT); 1183e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mPlayPosChangedNT == AvrcpConstants.NOTIFICATION_TYPE_INTERIM && isPlayingState(mCurrentPlayState)) { 1184e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_PLAY_INTERVAL_TIMEOUT); 1185f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen long delay = mPlaybackIntervalMs; 1186f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen if (mNextPosMs != -1) { 1187f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen delay = mNextPosMs - (playPositionMs > 0 ? playPositionMs : 0); 1188f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } 1189fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen if (DEBUG) Log.d(TAG, "PLAY_INTERVAL_TIMEOUT set for " + delay + "ms from now"); 1190f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen mHandler.sendMessageDelayed(msg, delay); 1191f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } 1192f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } 1193f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 1194f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen /** 119517675906064bb72fdcca75baa56cdf8bb8968d01John Du * This is called from AudioService. It will return whether this device supports abs volume. 119617675906064bb72fdcca75baa56cdf8bb8968d01John Du * NOT USED AT THE MOMENT. 119717675906064bb72fdcca75baa56cdf8bb8968d01John Du */ 119817675906064bb72fdcca75baa56cdf8bb8968d01John Du public boolean isAbsoluteVolumeSupported() { 119917675906064bb72fdcca75baa56cdf8bb8968d01John Du return ((mFeatures & BTRC_FEAT_ABSOLUTE_VOLUME) != 0); 120017675906064bb72fdcca75baa56cdf8bb8968d01John Du } 120117675906064bb72fdcca75baa56cdf8bb8968d01John Du 120217675906064bb72fdcca75baa56cdf8bb8968d01John Du /** 120317675906064bb72fdcca75baa56cdf8bb8968d01John Du * We get this call from AudioService. This will send a message to our handler object, 120417675906064bb72fdcca75baa56cdf8bb8968d01John Du * requesting our handler to call setVolumeNative() 120517675906064bb72fdcca75baa56cdf8bb8968d01John Du */ 120617675906064bb72fdcca75baa56cdf8bb8968d01John Du public void adjustVolume(int direction) { 1207e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_ADJUST_VOLUME, direction, 0); 120817675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 120917675906064bb72fdcca75baa56cdf8bb8968d01John Du } 121017675906064bb72fdcca75baa56cdf8bb8968d01John Du 121117675906064bb72fdcca75baa56cdf8bb8968d01John Du public void setAbsoluteVolume(int volume) { 121211798b011c962b602217b479130d413f3b30f19aLiejun Tao if (volume == mLocalVolume) { 121311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.v(TAG, "setAbsoluteVolume is setting same index, ignore "+volume); 121411798b011c962b602217b479130d413f3b30f19aLiejun Tao return; 121511798b011c962b602217b479130d413f3b30f19aLiejun Tao } 121611798b011c962b602217b479130d413f3b30f19aLiejun Tao 1217e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.removeMessages(MSG_ADJUST_VOLUME); 1218e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_SET_ABSOLUTE_VOLUME, volume, 0); 121917675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 12205c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta } 12215c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta 122217675906064bb72fdcca75baa56cdf8bb8968d01John Du /* Called in the native layer as a btrc_callback to return the volume set on the carkit in the 122317675906064bb72fdcca75baa56cdf8bb8968d01John Du * case when the volume is change locally on the carkit. This notification is not called when 122417675906064bb72fdcca75baa56cdf8bb8968d01John Du * the volume is changed from the phone. 122517675906064bb72fdcca75baa56cdf8bb8968d01John Du * 122617675906064bb72fdcca75baa56cdf8bb8968d01John Du * This method will send a message to our handler to change the local stored volume and notify 122717675906064bb72fdcca75baa56cdf8bb8968d01John Du * AudioService to update the UI 122817675906064bb72fdcca75baa56cdf8bb8968d01John Du */ 1229e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void volumeChangeRequestFromNative(byte[] address, int volume, int ctype) { 1230e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_VOLUME_CHANGE, volume, ctype); 1231e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = new Bundle(); 1232e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByteArray("BdAddress" , address); 1233e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.setData(data); 1234e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1235e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1236e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 123719a05f008446506069b34265d57bcf421447e7e3Marie Janssen private void getFolderItemsRequestFromNative( 123819a05f008446506069b34265d57bcf421447e7e3Marie Janssen byte[] address, byte scope, long startItem, long endItem, byte numAttr, int[] attrIds) { 1239e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "getFolderItemsRequestFromNative: scope=" + scope + ", numAttr=" + numAttr); 1240e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd avrcpCmdobj = new AvrcpCmd(); 1241e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd.FolderItemsCmd folderObj = avrcpCmdobj.new FolderItemsCmd(address, scope, 1242e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah startItem, endItem, numAttr, attrIds); 1243e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_FOLDER_ITEMS, 0, 0); 1244e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = folderObj; 1245e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1246e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1247e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1248e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void setAddressedPlayerRequestFromNative(byte[] address, int playerId) { 1249e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "setAddrPlayerRequestFromNative: playerId=" + playerId); 1250e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_SET_ADDR_PLAYER, playerId, 0); 1251e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = address; 1252e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1253e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1254e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1255e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void setBrowsedPlayerRequestFromNative(byte[] address, int playerId) { 1256e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "setBrPlayerRequestFromNative: playerId=" + playerId); 1257e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_SET_BR_PLAYER, playerId, 0); 1258e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = address; 1259e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1260e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1261e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1262e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void changePathRequestFromNative(byte[] address, byte direction, byte[] folderUid) { 1263e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "changePathRequestFromNative: direction=" + direction); 1264e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = new Bundle(); 1265e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_CHANGE_PATH); 1266e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByteArray("BdAddress" , address); 1267e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByteArray("folderUid" , folderUid); 1268e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByte("direction" , direction); 1269e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.setData(data); 1270e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1271e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1272e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1273e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void getItemAttrRequestFromNative(byte[] address, byte scope, byte[] itemUid, int uidCounter, 1274e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte numAttr, int[] attrs) { 1275e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "getItemAttrRequestFromNative: scope=" + scope + ", numAttr=" + numAttr); 1276e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd avrcpCmdobj = new AvrcpCmd(); 1277e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd.ItemAttrCmd itemAttr = avrcpCmdobj.new ItemAttrCmd(address, scope, 1278e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah itemUid, uidCounter, numAttr, attrs); 1279e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_ITEM_ATTR); 1280e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = itemAttr; 1281e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1282e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1283e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1284e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void searchRequestFromNative(byte[] address, int charsetId, byte[] searchStr) { 1285e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "searchRequestFromNative"); 1286e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Search is not supported */ 1287e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "search is not supported"); 1288e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah searchRspNative(address, AvrcpConstants.RSP_SRCH_NOT_SPRTD, 0, 0); 1289e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1290e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1291e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void playItemRequestFromNative(byte[] address, byte scope, int uidCounter, byte[] uid) { 1292e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "playItemRequestFromNative: scope=" + scope); 1293e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = new Bundle(); 1294e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_PLAY_ITEM); 1295e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByteArray("BdAddress" , address); 1296e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByteArray("uid" , uid); 1297e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putInt("uidCounter" , uidCounter); 1298e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByte("scope" , scope); 1299e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.setData(data); 1300e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1301e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1302e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1303e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void addToPlayListRequestFromNative(byte[] address, byte scope, byte[] uid, int uidCounter) { 1304e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "addToPlayListRequestFromNative: scope=" + scope); 1305e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* add to NowPlaying not supported */ 1306e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, "Add to NowPlayingList is not supported"); 1307e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah addToNowPlayingRspNative(address, AvrcpConstants.RSP_INTERNAL_ERR); 1308e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1309e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1310e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void getTotalNumOfItemsRequestFromNative(byte[] address, byte scope) { 1311e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "getTotalNumOfItemsRequestFromNative: scope=" + scope); 1312e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = new Bundle(); 1313e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_TOTAL_NUM_OF_ITEMS); 1314e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.arg1 = scope; 1315e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = address; 131617675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 131717675906064bb72fdcca75baa56cdf8bb8968d01John Du } 131817675906064bb72fdcca75baa56cdf8bb8968d01John Du 13192e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie private void notifyVolumeChanged(int volume) { 13202e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 13212e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_BLUETOOTH_ABS_VOLUME); 132217675906064bb72fdcca75baa56cdf8bb8968d01John Du } 132317675906064bb72fdcca75baa56cdf8bb8968d01John Du 132417675906064bb72fdcca75baa56cdf8bb8968d01John Du private int convertToAudioStreamVolume(int volume) { 132517675906064bb72fdcca75baa56cdf8bb8968d01John Du // Rescale volume to match AudioSystem's volume 132611798b011c962b602217b479130d413f3b30f19aLiejun Tao return (int) Math.floor((double) volume*mAudioStreamMax/AVRCP_MAX_VOL); 132717675906064bb72fdcca75baa56cdf8bb8968d01John Du } 132817675906064bb72fdcca75baa56cdf8bb8968d01John Du 132917675906064bb72fdcca75baa56cdf8bb8968d01John Du private int convertToAvrcpVolume(int volume) { 13302e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie return (int) Math.ceil((double) volume*AVRCP_MAX_VOL/mAudioStreamMax); 133117675906064bb72fdcca75baa56cdf8bb8968d01John Du } 133217675906064bb72fdcca75baa56cdf8bb8968d01John Du 133311798b011c962b602217b479130d413f3b30f19aLiejun Tao private void blackListCurrentDevice() { 133411798b011c962b602217b479130d413f3b30f19aLiejun Tao mFeatures &= ~BTRC_FEAT_ABSOLUTE_VOLUME; 133511798b011c962b602217b479130d413f3b30f19aLiejun Tao mAudioManager.avrcpSupportsAbsoluteVolume(mAddress, isAbsoluteVolumeSupported()); 133611798b011c962b602217b479130d413f3b30f19aLiejun Tao 133711798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences pref = mContext.getSharedPreferences(ABSOLUTE_VOLUME_BLACKLIST, 133811798b011c962b602217b479130d413f3b30f19aLiejun Tao Context.MODE_PRIVATE); 133911798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences.Editor editor = pref.edit(); 134011798b011c962b602217b479130d413f3b30f19aLiejun Tao editor.putBoolean(mAddress, true); 13417eeb95b6f29a6f55e117e329468168d4bcbec0c8Jack He editor.apply(); 134211798b011c962b602217b479130d413f3b30f19aLiejun Tao } 134311798b011c962b602217b479130d413f3b30f19aLiejun Tao 134411798b011c962b602217b479130d413f3b30f19aLiejun Tao private int modifyRcFeatureFromBlacklist(int feature, String address) { 134511798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences pref = mContext.getSharedPreferences(ABSOLUTE_VOLUME_BLACKLIST, 134611798b011c962b602217b479130d413f3b30f19aLiejun Tao Context.MODE_PRIVATE); 134711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (!pref.contains(address)) { 134811798b011c962b602217b479130d413f3b30f19aLiejun Tao return feature; 134911798b011c962b602217b479130d413f3b30f19aLiejun Tao } 135011798b011c962b602217b479130d413f3b30f19aLiejun Tao if (pref.getBoolean(address, false)) { 135111798b011c962b602217b479130d413f3b30f19aLiejun Tao feature &= ~BTRC_FEAT_ABSOLUTE_VOLUME; 135211798b011c962b602217b479130d413f3b30f19aLiejun Tao } 135311798b011c962b602217b479130d413f3b30f19aLiejun Tao return feature; 135411798b011c962b602217b479130d413f3b30f19aLiejun Tao } 135511798b011c962b602217b479130d413f3b30f19aLiejun Tao 135611798b011c962b602217b479130d413f3b30f19aLiejun Tao public void resetBlackList(String address) { 135711798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences pref = mContext.getSharedPreferences(ABSOLUTE_VOLUME_BLACKLIST, 135811798b011c962b602217b479130d413f3b30f19aLiejun Tao Context.MODE_PRIVATE); 135911798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences.Editor editor = pref.edit(); 136011798b011c962b602217b479130d413f3b30f19aLiejun Tao editor.remove(address); 13617eeb95b6f29a6f55e117e329468168d4bcbec0c8Jack He editor.apply(); 136211798b011c962b602217b479130d413f3b30f19aLiejun Tao } 136311798b011c962b602217b479130d413f3b30f19aLiejun Tao 1364188f205b5f093850d4cc627917a21204be36c56aZhihai Xu /** 1365188f205b5f093850d4cc627917a21204be36c56aZhihai Xu * This is called from A2dpStateMachine to set A2dp audio state. 1366188f205b5f093850d4cc627917a21204be36c56aZhihai Xu */ 1367188f205b5f093850d4cc627917a21204be36c56aZhihai Xu public void setA2dpAudioState(int state) { 1368e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_SET_A2DP_AUDIO_STATE, state, 0); 1369188f205b5f093850d4cc627917a21204be36c56aZhihai Xu mHandler.sendMessage(msg); 1370188f205b5f093850d4cc627917a21204be36c56aZhihai Xu } 1371188f205b5f093850d4cc627917a21204be36c56aZhihai Xu 13720427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker private class AvrcpServiceBootReceiver extends BroadcastReceiver { 13730427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker @Override 13740427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker public void onReceive(Context context, Intent intent) { 13750427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker String action = intent.getAction(); 13760427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker if (action.equals(Intent.ACTION_BOOT_COMPLETED)) { 13770427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker if (DEBUG) Log.d(TAG, "Boot completed, initializing player lists"); 13780427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker /* initializing media player's list */ 13793843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen (new BrowsablePlayerListBuilder()).start(); 13800427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker } 13810427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker } 13820427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker } 13830427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker 1384e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private class AvrcpServiceBroadcastReceiver extends BroadcastReceiver { 1385e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah @Override 1386e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void onReceive(Context context, Intent intent) { 1387e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String action = intent.getAction(); 1388e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "AvrcpServiceBroadcastReceiver-> Action: " + action); 1389e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1390e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (action.equals(Intent.ACTION_PACKAGE_REMOVED) 1391e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah || action.equals(Intent.ACTION_PACKAGE_DATA_CLEARED)) { 1392e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { 1393e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // a package is being removed, not replaced 1394e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String packageName = intent.getData().getSchemeSpecificPart(); 1395e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (packageName != null) { 1396e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handlePackageModified(packageName, true); 1397e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1398e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1399e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1400e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else if (action.equals(Intent.ACTION_PACKAGE_ADDED) 1401e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah || action.equals(Intent.ACTION_PACKAGE_CHANGED)) { 1402e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String packageName = intent.getData().getSchemeSpecificPart(); 1403e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG,"AvrcpServiceBroadcastReceiver-> packageName: " 1404e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + packageName); 1405e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (packageName != null) { 1406e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handlePackageModified(packageName, false); 1407e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1408e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1409e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1410838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood } 1411838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood 1412e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handlePackageModified(String packageName, boolean removed) { 1413e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "packageName: " + packageName + " removed: " + removed); 1414c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1415e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (removed) { 1416384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen removeMediaPlayerInfo(packageName); 1417e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // old package is removed, updating local browsable player's list 1418e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (isBrowseSupported(packageName)) { 1419e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah removePackageFromBrowseList(packageName); 1420e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1421e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 1422e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // new package has been added. 1423e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (isBrowsableListUpdated(packageName)) { 1424e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // Rebuilding browsable players list 14253843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen (new BrowsablePlayerListBuilder()).start(); 1426e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1427e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1428e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1429c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1430e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean isBrowsableListUpdated(String newPackageName) { 1431e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // getting the browsable media players list from package manager 1432e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Intent intent = new Intent("android.media.browse.MediaBrowserService"); 14330427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker List<ResolveInfo> resInfos = mPackageManager.queryIntentServices(intent, 14340427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker PackageManager.MATCH_ALL); 1435e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah for (ResolveInfo resolveInfo : resInfos) { 14363843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen if (resolveInfo.serviceInfo.packageName.equals(newPackageName)) { 14373843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen if (DEBUG) 14383843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen Log.d(TAG, 14393843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen "isBrowsableListUpdated: package includes MediaBrowserService, true"); 14403843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen return true; 14413843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen } 1442e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1443c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 14443843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen // if list has different size 14453843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen if (resInfos.size() != mBrowsePlayerInfoList.size()) { 14463843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen if (DEBUG) Log.d(TAG, "isBrowsableListUpdated: browsable list size mismatch, true"); 14473843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen return true; 1448e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 14493843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen 14503843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen Log.d(TAG, "isBrowsableListUpdated: false"); 14513843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen return false; 1452e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1453e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1454511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private void removePackageFromBrowseList(String packageName) { 1455e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "removePackageFromBrowseList: " + packageName); 1456511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mBrowsePlayerInfoList) { 1457511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int browseInfoID = getBrowseId(packageName); 1458511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (browseInfoID != -1) { 1459511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mBrowsePlayerInfoList.remove(browseInfoID); 1460511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1461e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1462e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1463e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1464e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* 1465e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * utility function to get the browse player index from global browsable 1466e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * list. It may return -1 if specified package name is not in the list. 1467e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 1468511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private int getBrowseId(String packageName) { 1469e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah boolean response = false; 1470e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int browseInfoID = 0; 1471511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mBrowsePlayerInfoList) { 1472511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (BrowsePlayerInfo info : mBrowsePlayerInfoList) { 1473511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (info.packageName.equals(packageName)) { 1474511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen response = true; 1475511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen break; 1476511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1477511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen browseInfoID++; 1478e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1479e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1480e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1481e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!response) { 1482e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah browseInfoID = -1; 1483e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1484e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1485e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "getBrowseId for packageName: " + packageName + 1486e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah " , browseInfoID: " + browseInfoID); 1487e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return browseInfoID; 1488e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1489e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1490e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void setAddressedPlayer(byte[] bdaddr, int selectedId) { 1491e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int status = AvrcpConstants.RSP_NO_ERROR; 1492e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1493511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 1494511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (mMediaPlayerInfoList.isEmpty()) { 1495511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen status = AvrcpConstants.RSP_NO_AVBL_PLAY; 1496511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen Log.w(TAG, " No Available Players to set, sending response back "); 1497511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } else if (!mMediaPlayerInfoList.containsKey(selectedId)) { 1498511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen status = AvrcpConstants.RSP_INV_PLAYER; 1499511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen Log.w(TAG, " Invalid Player id: " + selectedId + " to set, sending response back "); 1500511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } else if (!isPlayerAlreadyAddressed(selectedId)) { 1501511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen // register new Media Controller Callback and update the current Ids 1502511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (!updateCurrentController(selectedId, mCurrBrowsePlayerID)) { 1503511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen status = AvrcpConstants.RSP_INTERNAL_ERR; 1504511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen Log.e(TAG, "register for new Address player failed: " + mCurrAddrPlayerID); 1505511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1506511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } else { 1507511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen MediaPlayerInfo info = getAddressedPlayerInfo(); 1508511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen Log.i(TAG, "addressed player " + info + "is already focused"); 1509e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1510e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1511e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1512e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "setAddressedPlayer for selectedId: " + selectedId + 1513e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah " , status: " + status); 1514e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // Sending address player response to remote 1515e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah setAddressedPlayerRspNative(bdaddr, status); 1516e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1517e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1518e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void setBrowsedPlayer(byte[] bdaddr, int selectedId) { 1519e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int status = AvrcpConstants.RSP_NO_ERROR; 1520e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1521e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // checking for error cases 1522511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (mMediaPlayerInfoList.isEmpty()) { 1523e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah status = AvrcpConstants.RSP_NO_AVBL_PLAY; 1524e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, " No Available Players to set, sending response back "); 1525e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 1526e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // update current browse player id and start browsing service 1527e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah updateNewIds(mCurrAddrPlayerID, selectedId); 1528e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String browsedPackage = getPackageName(selectedId); 1529e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1530e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!isPackageNameValid(browsedPackage)) { 1531e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, " Invalid package for id:" + mCurrBrowsePlayerID); 1532e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah status = AvrcpConstants.RSP_INV_PLAYER; 1533e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else if (!isBrowseSupported(browsedPackage)) { 1534e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, "Browse unsupported for id:" + mCurrBrowsePlayerID 1535e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + ", packagename : " + browsedPackage); 1536e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah status = AvrcpConstants.RSP_PLAY_NOT_BROW; 1537e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else if (!startBrowseService(bdaddr, browsedPackage)) { 1538e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "service cannot be started for browse player id:" + mCurrBrowsePlayerID 1539e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + ", packagename : " + browsedPackage); 1540e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah status = AvrcpConstants.RSP_INTERNAL_ERR; 1541e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1542e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1543e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1544e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (status != AvrcpConstants.RSP_NO_ERROR) { 1545e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah setBrowsedPlayerRspNative(bdaddr, status, (byte) 0x00, 0, null); 1546e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1547e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1548e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "setBrowsedPlayer for selectedId: " + selectedId + 1549e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah " , status: " + status); 1550e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1551e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 155205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private MediaSessionManager.OnActiveSessionsChangedListener mActiveSessionListener = 155305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen new MediaSessionManager.OnActiveSessionsChangedListener() { 1554e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 155505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen @Override 155605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public void onActiveSessionsChanged( 155705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen List<android.media.session.MediaController> newControllers) { 155805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen boolean playersChanged = false; 155905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 156005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen // Update the current players 156105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen for (android.media.session.MediaController controller : newControllers) { 156205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen addMediaPlayerController(controller); 156305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen playersChanged = true; 1564eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1565d996f17ea97b2c592338bcfbc93056d0224da1cdAjay Panicker 156605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen List<android.media.session.MediaController> currentControllers = 156705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen getMediaControllers(); 156805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen for (android.media.session.MediaController controller : currentControllers) { 156905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (!newControllers.contains(controller)) { 1570384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen removeMediaController(controller); 1571384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen if (mMediaController != null && mMediaController.equals(controller)) { 1572384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen if (DEBUG) Log.v(TAG, "Active Controller is gone!"); 1573384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen mMediaController.unregisterCallback(mMediaControllerCb); 1574384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen mMediaController = null; 1575384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } 157605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 157705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 1578e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 157905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (playersChanged) { 158005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mHandler.sendEmptyMessage(MSG_AVAILABLE_PLAYERS_CHANGED_RSP); 1581384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen if (newControllers.size() > 0 && getAddressedPlayerInfo() == null) { 158205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (DEBUG) 158305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.v(TAG, 158405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen "No addressed player but active sessions, taking first."); 158505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen setAddressedMediaSessionPackage(newControllers.get(0).getPackageName()); 1586eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1587eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1588e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 158905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen }; 159005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 159105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private void setAddressedMediaSessionPackage(String packageName) { 159205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (DEBUG) Log.v(TAG, "Setting addressed media session to " + packageName); 159341527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen if (packageName == null) { 159441527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen // Should only happen when there's no media players, reset to no available player. 159541527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen updateCurrentController(0, mCurrBrowsePlayerID); 159641527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen return; 159741527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen } 159805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen // No change. 159905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (getPackageName(mCurrAddrPlayerID).equals(packageName)) return; 160005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen // If the player doesn't exist, we need to add it. 160105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (getMediaPlayerInfo(packageName) == null) { 160205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen addMediaPlayerPackage(packageName); 160305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mHandler.sendEmptyMessage(MSG_AVAILABLE_PLAYERS_CHANGED_RSP); 160405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 1605511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 1606511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) { 1607511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (entry.getValue().getPackageName().equals(packageName)) { 1608511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int newAddrID = entry.getKey(); 1609511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.v(TAG, "Set addressed #" + newAddrID + " " + entry.getValue()); 1610511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen updateCurrentController(newAddrID, mCurrBrowsePlayerID); 1611511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mHandler.obtainMessage(MSG_ADDRESSED_PLAYER_CHANGED_RSP, newAddrID, 0) 1612511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen .sendToTarget(); 1613511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return; 1614511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1615e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1616e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 161705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen // We shouldn't ever get here. 161805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.e(TAG, "Player info for " + packageName + " doesn't exist!"); 161905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 1620e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 162105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private void setActiveMediaSession(MediaSession.Token token) { 162205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen android.media.session.MediaController activeController = 162305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen new android.media.session.MediaController(mContext, token); 162405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (DEBUG) Log.v(TAG, "Set active media session " + activeController.getPackageName()); 162505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen addMediaPlayerController(activeController); 162605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen setAddressedMediaSessionPackage(activeController.getPackageName()); 162705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 1628e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1629e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean startBrowseService(byte[] bdaddr, String packageName) { 1630e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah boolean status = true; 1631e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1632e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* creating new instance for Browse Media Player */ 1633e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String browseService = getBrowseServiceName(packageName); 1634e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!browseService.isEmpty()) { 1635e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr).setBrowsed( 1636e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah packageName, browseService); 1637e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 1638e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, "No Browser service available for " + packageName); 1639e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah status = false; 1640e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1641e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1642e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "startBrowseService for packageName: " + packageName + 1643e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ", status = " + status); 1644e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return status; 1645e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1646e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1647511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private String getBrowseServiceName(String packageName) { 1648e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String browseServiceName = ""; 1649e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1650e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // getting the browse service name from browse player info 1651511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mBrowsePlayerInfoList) { 1652511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int browseInfoID = getBrowseId(packageName); 1653511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (browseInfoID != -1) { 1654511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen browseServiceName = mBrowsePlayerInfoList.get(browseInfoID).serviceClass; 1655511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1656e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1657e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1658e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "getBrowseServiceName for packageName: " + packageName + 1659e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ", browseServiceName = " + browseServiceName); 1660e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return browseServiceName; 1661e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1662e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 16633843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen private class BrowsablePlayerListBuilder extends MediaBrowser.ConnectionCallback { 16643843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen List<ResolveInfo> mWaiting; 16653843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen BrowsePlayerInfo mCurrentPlayer; 16663843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen MediaBrowser mCurrentBrowser; 1667eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen boolean mPlayersChanged; 1668e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 16693843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen public BrowsablePlayerListBuilder() {} 1670e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 16713843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen public void start() { 16723843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen mBrowsePlayerInfoList.clear(); 1673eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen mPlayersChanged = false; 16743843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen Intent intent = new Intent(android.service.media.MediaBrowserService.SERVICE_INTERFACE); 16753843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen mWaiting = mPackageManager.queryIntentServices(intent, PackageManager.MATCH_ALL); 16763843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen connectNextPlayer(); 16773843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen } 1678e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 16793843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen private void connectNextPlayer() { 16803843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen if (mWaiting.isEmpty()) { 1681eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen // Done. Send players changed if needed. 1682eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen if (mPlayersChanged) { 1683eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen registerNotificationRspAvalPlayerChangedNative( 1684eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen AvrcpConstants.NOTIFICATION_TYPE_CHANGED); 1685eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 16863843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen return; 16873843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen } 16883843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen ResolveInfo info = mWaiting.remove(0); 16893843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen String displayableName = info.loadLabel(mPackageManager).toString(); 16903843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen String serviceName = info.serviceInfo.name; 16913843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen String packageName = info.serviceInfo.packageName; 1692e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 16933843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen mCurrentPlayer = new BrowsePlayerInfo(packageName, displayableName, serviceName); 16943843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen mCurrentBrowser = new MediaBrowser( 16953843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen mContext, new ComponentName(packageName, serviceName), this, null); 16963843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen if (DEBUG) Log.d(TAG, "Trying to connect to " + serviceName); 16973843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen mCurrentBrowser.connect(); 16983843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen } 16993843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen 17003843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen @Override 17013843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen public void onConnected() { 17023843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen Log.d(TAG, "BrowsablePlayerListBuilder: " + mCurrentPlayer.packageName + " OK"); 17033843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen mBrowsePlayerInfoList.add(mCurrentPlayer); 1704eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen MediaPlayerInfo info = getMediaPlayerInfo(mCurrentPlayer.packageName); 1705eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen if (info != null) { 1706b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen // Refresh the media player entry so it notices we can browse 1707b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen MediaController controller = info.getMediaController(); 1708b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen if (controller != null) { 1709b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen addMediaPlayerController(controller.getWrappedInstance()); 1710b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen } 1711b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen // If there's no controller, the entry is already browsable-only. 1712eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } else { 171305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen addMediaPlayerPackage(mCurrentPlayer.packageName); 1714eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1715eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen mPlayersChanged = true; 17163843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen mCurrentBrowser.disconnect(); 17173843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen connectNextPlayer(); 17183843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen } 17193843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen 17203843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen @Override 17213843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen public void onConnectionFailed() { 17223843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen Log.d(TAG, "BrowsablePlayerListBuilder: " + mCurrentPlayer.packageName + " FAIL"); 17233843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen connectNextPlayer(); 1724e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1725e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1726e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1727294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen private void startBrowsedPlayer(int browseId) { 172805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (browseId < 0 || browseId >= mBrowsePlayerInfoList.size()) return; 1729294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen BrowsePlayerInfo player = mBrowsePlayerInfoList.get(browseId); 173005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 1731294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen Intent intent = new Intent(); 1732294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen intent.setComponent(new ComponentName(player.packageName, player.serviceClass)); 1733294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen Log.i(TAG, "Starting service:" + player.packageName + ", " + player.serviceClass); 1734294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen try { 1735294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen mContext.startService(intent); 1736294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen } catch (SecurityException ex) { 1737294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen Log.e(TAG, "Can't start " + player.serviceClass + ": " + ex.getMessage()); 1738294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen } 1739294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen } 1740294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen 174105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen /* Initializes list of media players identified from session manager active sessions */ 1742511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private void initMediaPlayersList() { 1743511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 1744511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen // Clearing old browsable player's list 1745511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mMediaPlayerInfoList.clear(); 174605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 1747511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (mMediaSessionManager == null) { 1748511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.w(TAG, "initMediaPlayersList: no media session manager!"); 1749511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return; 1750511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 175105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 1752511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen List<android.media.session.MediaController> controllers = 1753511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mMediaSessionManager.getActiveSessions(null); 1754511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) 1755511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen Log.v(TAG, "initMediaPlayerInfoList: " + controllers.size() + " controllers"); 1756511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen /* Initializing all media players */ 1757511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (android.media.session.MediaController controller : controllers) { 1758511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen addMediaPlayerController(controller); 1759511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1760511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (controllers.size() > 0) { 1761511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mHandler.sendEmptyMessage(MSG_AVAILABLE_PLAYERS_CHANGED_RSP); 1762511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1763e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1764511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (mMediaPlayerInfoList.size() > 0) { 1765511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen // Set the first one as the Addressed Player 1766511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen updateCurrentController(mMediaPlayerInfoList.firstKey(), -1); 1767511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1768e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1769e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1770e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1771eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen private List<android.media.session.MediaController> getMediaControllers() { 1772eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen List<android.media.session.MediaController> controllers = 1773eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen new ArrayList<android.media.session.MediaController>(); 1774511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 1775511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (MediaPlayerInfo info : mMediaPlayerInfoList.values()) { 1776511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (info.getMediaController() != null) { 1777511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen controllers.add(info.getMediaController().getWrappedInstance()); 1778511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1779eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1780eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1781eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen return controllers; 1782eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1783eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 1784eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen /** Add (or update) a player to the media player list without a controller */ 1785511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private boolean addMediaPlayerPackage(String packageName) { 1786eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen MediaPlayerInfo info = new MediaPlayerInfo(null, AvrcpConstants.PLAYER_TYPE_AUDIO, 1787eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen AvrcpConstants.PLAYER_SUBTYPE_NONE, getPlayStateBytes(null), 1788b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen getFeatureBitMask(packageName), packageName, getAppLabel(packageName)); 178905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return addMediaPlayerInfo(info); 1790eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1791eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 1792eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen /** Add (or update) a player to the media player list given an active controller */ 1793511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private boolean addMediaPlayerController(android.media.session.MediaController controller) { 1794eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen String packageName = controller.getPackageName(); 1795eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen MediaPlayerInfo info = new MediaPlayerInfo(MediaController.wrap(controller), 1796eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen AvrcpConstants.PLAYER_TYPE_AUDIO, AvrcpConstants.PLAYER_SUBTYPE_NONE, 1797eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen getPlayStateBytes(controller.getPlaybackState()), getFeatureBitMask(packageName), 1798b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen controller.getPackageName(), getAppLabel(packageName)); 179905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return addMediaPlayerInfo(info); 1800eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1801eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 180205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen /** Add or update a player to the media player list given the MediaPlayerInfo object. 180305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen * @return true if an item was updated, false if it was added instead 180405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen */ 1805511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private boolean addMediaPlayerInfo(MediaPlayerInfo info) { 1806b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen int updateId = -1; 180705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen boolean updated = false; 1808511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 1809511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) { 1810511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (info.getPackageName().equals(entry.getValue().getPackageName())) { 1811511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen updateId = entry.getKey(); 1812511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen updated = true; 1813511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen break; 1814511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1815b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen } 1816511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (updateId == -1) { 1817511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen // New player 1818511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mLastUsedPlayerID++; 1819511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen updateId = mLastUsedPlayerID; 1820511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1821511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mMediaPlayerInfoList.put(updateId, info); 1822384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen if (DEBUG) 1823384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen Log.d(TAG, (updated ? "update #" : "add #") + updateId + ":" + info.toString()); 1824384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen if (updateId == mCurrAddrPlayerID) { 1825384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen updateCurrentController(mCurrAddrPlayerID, mCurrBrowsePlayerID); 1826384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } 1827b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen } 182805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return updated; 1829eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1830eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 1831eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen /** Remove all players related to |packageName| from the media player info list */ 1832511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private MediaPlayerInfo removeMediaPlayerInfo(String packageName) { 1833511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 1834511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int removeKey = -1; 1835511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) { 1836511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (entry.getValue().getPackageName().equals(packageName)) { 1837511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen removeKey = entry.getKey(); 1838511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen break; 1839511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1840511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1841511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (removeKey != -1) { 1842384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen if (DEBUG) 1843384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen Log.d(TAG, "remove #" + removeKey + ":" + mMediaPlayerInfoList.get(removeKey)); 1844511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return mMediaPlayerInfoList.remove(removeKey); 1845eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1846b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen 1847511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return null; 1848511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1849eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1850eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 1851384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen /** Remove the controller referenced by |controller| from any player in the list */ 1852384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen private void removeMediaController(android.media.session.MediaController controller) { 1853384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen synchronized (mMediaPlayerInfoList) { 1854384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen for (MediaPlayerInfo info : mMediaPlayerInfoList.values()) { 1855384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen if (info.getMediaController().equals(controller)) info.setMediaController(null); 1856384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } 1857384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } 1858384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } 1859384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen 1860e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* 1861e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * utility function to get the playback state of any media player through 1862e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * media controller APIs. 1863e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 1864eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen private byte getPlayStateBytes(PlaybackState pbState) { 1865e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte playStateBytes = PLAYSTATUS_STOPPED; 1866e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1867e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (pbState != null) { 1868e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah playStateBytes = (byte)convertPlayStateToBytes(pbState.getState()); 1869e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.v(TAG, "getPlayBackState: playStateBytes = " + playStateBytes); 1870e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 1871e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, "playState object null, sending playStateBytes = " + playStateBytes); 1872e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1873e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1874e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return playStateBytes; 1875e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1876e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1877e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* 1878e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * utility function to map framework's play state values to AVRCP spec 1879e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * defined play status values 1880e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 1881e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private int convertPlayStateToBytes(int playState) { 1882e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah switch (playState) { 1883e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_PLAYING: 1884e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_BUFFERING: 1885e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_PLAYING; 1886e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1887e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_STOPPED: 1888e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_NONE: 1889e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_CONNECTING: 1890e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_STOPPED; 1891e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1892e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_PAUSED: 1893e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_PAUSED; 1894e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1895e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_FAST_FORWARDING: 1896e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_SKIPPING_TO_NEXT: 1897e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_SKIPPING_TO_QUEUE_ITEM: 1898e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_FWD_SEEK; 1899e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1900e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_REWINDING: 1901e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_SKIPPING_TO_PREVIOUS: 1902e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_REV_SEEK; 1903e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1904e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_ERROR: 1905e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah default: 1906e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_ERROR; 1907e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1908e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1909e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1910e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* 1911e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * utility function to get the feature bit mask of any media player through 1912e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * package name 1913e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 1914e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private short[] getFeatureBitMask(String packageName) { 1915e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1916e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ArrayList<Short> featureBitsList = new ArrayList<Short>(); 1917e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1918e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* adding default feature bits */ 1919e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_PLAY_BIT_NO); 1920e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_STOP_BIT_NO); 1921e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_PAUSE_BIT_NO); 1922e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_REWIND_BIT_NO); 1923e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_FAST_FWD_BIT_NO); 1924e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_FORWARD_BIT_NO); 1925e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_BACKWARD_BIT_NO); 1926e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_ADV_CTRL_BIT_NO); 1927e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1928e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Add/Modify browse player supported features. */ 1929e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (isBrowseSupported(packageName)) { 1930e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_BROWSE_BIT_NO); 1931e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_UID_UNIQUE_BIT_NO); 1932e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_NOW_PLAY_BIT_NO); 1933e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_GET_NUM_OF_ITEMS_BIT_NO); 1934e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1935e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1936e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // converting arraylist to array for response 1937e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah short[] featureBitsArray = new short[featureBitsList.size()]; 1938e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1939e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah for (int i = 0; i < featureBitsList.size(); i++) { 1940e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsArray[i] = featureBitsList.get(i).shortValue(); 1941e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1942e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1943e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return featureBitsArray; 1944e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1945e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1946e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /** 1947e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * Checks the Package name if it supports Browsing or not. 1948e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * 1949e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * @param packageName - name of the package to get the Id. 1950e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * @return true if it supports browsing, else false. 1951e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 1952511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private boolean isBrowseSupported(String packageName) { 1953511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mBrowsePlayerInfoList) { 1954511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen /* check if Browsable Player's list contains this package name */ 1955511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (BrowsePlayerInfo info : mBrowsePlayerInfoList) { 1956511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (info.packageName.equals(packageName)) { 1957511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.v(TAG, "isBrowseSupported for " + packageName + ": true"); 1958511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return true; 1959511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1960e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1961e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1962e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1963b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen if (DEBUG) Log.v(TAG, "isBrowseSupported for " + packageName + ": false"); 19641b70ec148be773651d5ad00e3ce0d28b3a63306dAjay Panicker return false; 1965e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1966e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1967e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private String getPackageName(int id) { 1968511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen MediaPlayerInfo player = null; 1969511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 1970511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen player = mMediaPlayerInfoList.getOrDefault(id, null); 1971511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1972e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1973eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen if (player == null) { 1974eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen Log.w(TAG, "No package name for player (" + id + " not valid)"); 1975eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen return ""; 1976e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1977eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 1978eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen String packageName = player.getPackageName(); 1979eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen if (DEBUG) Log.v(TAG, "Player " + id + " package: " + packageName); 1980e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return packageName; 1981e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1982e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1983e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* from the global object, getting the current browsed player's package name */ 1984e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private String getCurrentBrowsedPlayer(byte[] bdaddr) { 1985e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String browsedPlayerPackage = ""; 1986e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1987e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Map<String, BrowsedMediaPlayer> connList = mAvrcpBrowseManager.getConnList(); 1988e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String bdaddrStr = new String(bdaddr); 1989e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if(connList.containsKey(bdaddrStr)){ 1990e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah browsedPlayerPackage = connList.get(bdaddrStr).getPackageName(); 1991e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1992e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "getCurrentBrowsedPlayerPackage: " + browsedPlayerPackage); 1993e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return browsedPlayerPackage; 1994e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1995e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1996eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen /* Returns the MediaPlayerInfo for the currently addressed media player */ 1997511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private MediaPlayerInfo getAddressedPlayerInfo() { 1998511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 1999511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return mMediaPlayerInfoList.getOrDefault(mCurrAddrPlayerID, null); 2000511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2001e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2002e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2003e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* 2004e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * Utility function to get the Media player info from package name returns 2005e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * null if package name not found in media players list 2006e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 2007511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private MediaPlayerInfo getMediaPlayerInfo(String packageName) { 2008511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 2009511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (mMediaPlayerInfoList.isEmpty()) { 2010511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.v(TAG, "getMediaPlayerInfo: Media players list empty"); 2011511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return null; 2012511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2013eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 2014511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (MediaPlayerInfo info : mMediaPlayerInfoList.values()) { 2015511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (packageName.equals(info.getPackageName())) { 2016511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.v(TAG, "getMediaPlayerInfo: Found " + packageName); 2017511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return info; 2018511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2019e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2020511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.w(TAG, "getMediaPlayerInfo: " + packageName + " not found"); 2021511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return null; 2022e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2023e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2024e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2025e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* prepare media list & return the media player list response object */ 2026511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private MediaPlayerListRsp prepareMediaPlayerRspObj() { 2027511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 2028511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int numPlayers = mMediaPlayerInfoList.size(); 2029511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen 2030511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int[] playerIds = new int[numPlayers]; 2031511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen byte[] playerTypes = new byte[numPlayers]; 2032511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int[] playerSubTypes = new int[numPlayers]; 2033511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen String[] displayableNameArray = new String[numPlayers]; 2034511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen byte[] playStatusValues = new byte[numPlayers]; 2035511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen short[] featureBitMaskValues = 2036511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen new short[numPlayers * AvrcpConstants.AVRC_FEATURE_MASK_SIZE]; 2037511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen 2038511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int players = 0; 2039511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) { 2040511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen MediaPlayerInfo info = entry.getValue(); 2041511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen playerIds[players] = entry.getKey(); 2042511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen playerTypes[players] = info.getMajorType(); 2043511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen playerSubTypes[players] = info.getSubType(); 2044511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen displayableNameArray[players] = info.getDisplayableName(); 2045511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen playStatusValues[players] = info.getPlayStatus(); 2046511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen 2047511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen short[] featureBits = info.getFeatureBitMask(); 2048511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (int numBit = 0; numBit < featureBits.length; numBit++) { 2049511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen /* gives which octet this belongs to */ 2050511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen byte octet = (byte) (featureBits[numBit] / 8); 2051511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen /* gives the bit position within the octet */ 2052511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen byte bit = (byte) (featureBits[numBit] % 8); 2053511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen featureBitMaskValues[(players * AvrcpConstants.AVRC_FEATURE_MASK_SIZE) 2054511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen + octet] |= (1 << bit); 2055511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2056e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2057511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen /* printLogs */ 2058511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) { 2059511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen Log.d(TAG, "Player " + playerIds[players] + ": " + displayableNameArray[players] 2060511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen + " type: " + playerTypes[players] + ", " 2061511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen + playerSubTypes[players] + " status: " 2062511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen + playStatusValues[players]); 2063511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2064e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2065511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen players++; 2066511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2067e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2068511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.d(TAG, "prepareMediaPlayerRspObj: numPlayers = " + numPlayers); 2069e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2070511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return new MediaPlayerListRsp(AvrcpConstants.RSP_NO_ERROR, sUIDCounter, numPlayers, 2071511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen AvrcpConstants.BTRC_ITEM_PLAYER, playerIds, playerTypes, playerSubTypes, 2072511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen playStatusValues, featureBitMaskValues, displayableNameArray); 2073511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2074e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2075e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2076e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* build media player list and send it to remote. */ 2077e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handleMediaPlayerListRsp(AvrcpCmd.FolderItemsCmd folderObj) { 2078511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen MediaPlayerListRsp rspObj = null; 2079511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 2080511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int numPlayers = mMediaPlayerInfoList.size(); 2081511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (numPlayers == 0) { 2082511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mediaPlayerListRspNative(folderObj.mAddress, AvrcpConstants.RSP_NO_AVBL_PLAY, 2083511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen (short) 0, (byte) 0, 0, null, null, null, null, null, null); 2084511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return; 2085511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2086511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (folderObj.mStartItem >= numPlayers) { 2087511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen Log.i(TAG, "handleMediaPlayerListRsp: start = " + folderObj.mStartItem 2088511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen + " > num of items = " + numPlayers); 2089511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mediaPlayerListRspNative(folderObj.mAddress, AvrcpConstants.RSP_INV_RANGE, 2090511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen (short) 0, (byte) 0, 0, null, null, null, null, null, null); 2091511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return; 2092511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2093511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen rspObj = prepareMediaPlayerRspObj(); 2094e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2095511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.d(TAG, "handleMediaPlayerListRsp: sending " + rspObj.mNumItems + " players"); 2096eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen mediaPlayerListRspNative(folderObj.mAddress, rspObj.mStatus, rspObj.mUIDCounter, 2097eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen rspObj.itemType, rspObj.mNumItems, rspObj.mPlayerIds, rspObj.mPlayerTypes, 2098eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen rspObj.mPlayerSubTypes, rspObj.mPlayStatusValues, rspObj.mFeatureBitMaskValues, 2099eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen rspObj.mPlayerNameList); 2100e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2101e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2102e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* unregister to the old controller, update new IDs and register to the new controller */ 2103e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean updateCurrentController(int addrId, int browseId) { 2104e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah boolean registerRsp = true; 2105e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2106e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah updateNewIds(addrId, browseId); 2107e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2108eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen MediaController newController = null; 2109eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen MediaPlayerInfo info = getAddressedPlayerInfo(); 2110294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen if (info != null) { 2111294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen newController = info.getMediaController(); 2112294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen if (newController == null) { 2113294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen // Browsable player, try to start it, which will trigger an update via 2114294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen // MesiaSessionManager 2115294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen startBrowsedPlayer(getBrowseId(info.getPackageName())); 2116294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen } 2117294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen } 2118eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 2119eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen if (DEBUG) 2120eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen Log.d(TAG, "updateCurrentController: " + mMediaController + " to " + newController); 2121384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen if (mMediaController == null || (!mMediaController.equals(newController))) { 2122eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen if (mMediaController != null) mMediaController.unregisterCallback(mMediaControllerCb); 2123384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen mMediaController = newController; 2124384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen if (mMediaController != null) { 2125eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen mMediaController.registerCallback(mMediaControllerCb, mHandler); 2126eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen mAddressedMediaPlayer.updateNowPlayingList(mMediaController.getQueue()); 2127eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } else { 2128eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen mAddressedMediaPlayer.updateNowPlayingList(null); 2129eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen registerRsp = false; 2130eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 21310a429916782c20980e7f0893c503c633b8341f88Marie Janssen updateCurrentMediaState(); 2132e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2133eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen return registerRsp; 2134e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2135e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2136e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Handle getfolderitems for scope = VFS, Search, NowPlayingList */ 2137e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handleGetFolderItemBrowseResponse(AvrcpCmd.FolderItemsCmd folderObj, byte[] bdaddr) { 2138e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int status = AvrcpConstants.RSP_NO_ERROR; 2139e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2140e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Browsed player is already set */ 214105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (folderObj.mScope == AvrcpConstants.BTRC_SCOPE_FILE_SYSTEM) { 214205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr) == null) { 214305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.e(TAG, "handleGetFolderItemBrowseResponse: no browsed player set for " 214405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen + Utils.getAddressStringFromByte(bdaddr)); 214505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen getFolderItemsRspNative(bdaddr, AvrcpConstants.RSP_INTERNAL_ERR, (short) 0, 214605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen (byte) 0x00, 0, null, null, null, null, null, null, null, null); 214705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return; 214805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 214905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr).getFolderItemsVFS(folderObj); 215005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return; 2151e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 215205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (folderObj.mScope == AvrcpConstants.BTRC_SCOPE_NOW_PLAYING) { 215305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mAddressedMediaPlayer.getFolderItemsNowPlaying(bdaddr, folderObj, mMediaController); 215405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return; 2155e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2156e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 215705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen /* invalid scope */ 215805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.e(TAG, "handleGetFolderItemBrowseResponse: unknown scope " + folderObj.mScope); 215905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen getFolderItemsRspNative(bdaddr, AvrcpConstants.RSP_INV_SCOPE, (short) 0, (byte) 0x00, 0, 216005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen null, null, null, null, null, null, null, null); 2161e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2162e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2163e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* utility function to update the global values of current Addressed and browsed player */ 2164511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private void updateNewIds(int addrId, int browseId) { 2165e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mCurrAddrPlayerID = addrId; 2166e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mCurrBrowsePlayerID = browseId; 2167e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2168e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "Updated CurrentIds: AddrPlayerID:" + mCurrAddrPlayerID + " to " 2169e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + addrId + ", BrowsePlayerID:" + mCurrBrowsePlayerID + " to " + browseId); 2170e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2171e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2172e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Getting the application's displayable name from package name */ 2173e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private String getAppLabel(String packageName) { 2174e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ApplicationInfo appInfo = null; 2175e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah try { 2176e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah appInfo = mPackageManager.getApplicationInfo(packageName, 0); 2177e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } catch (NameNotFoundException e) { 2178e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah e.printStackTrace(); 2179e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2180e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2181e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return (String) (appInfo != null ? mPackageManager 2182e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah .getApplicationLabel(appInfo) : "Unknown"); 2183e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2184e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2185e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handlePlayItemResponse(byte[] bdaddr, byte[] uid, byte scope) { 2186294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen if (scope == AvrcpConstants.BTRC_SCOPE_NOW_PLAYING) { 2187294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen mAddressedMediaPlayer.playItem(bdaddr, uid, mMediaController); 2188e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2189e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah else { 2190e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if(!isAddrPlayerSameAsBrowsed(bdaddr)) { 2191e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, "Remote requesting play item on uid which may not be recognized by" + 2192e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah "current addressed player"); 2193e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah playItemRspNative(bdaddr, AvrcpConstants.RSP_INV_ITEM); 2194e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2195e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2196e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr) != null) { 2197e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr).playItem(uid, scope); 2198e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2199e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "handlePlayItemResponse: Remote requested playitem " + 2200e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah "before setbrowsedplayer"); 2201e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah playItemRspNative(bdaddr, AvrcpConstants.RSP_INTERNAL_ERR); 2202e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2203e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2204e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2205e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2206e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handleGetItemAttr(AvrcpCmd.ItemAttrCmd itemAttr) { 2207384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen if (itemAttr.mScope == AvrcpConstants.BTRC_SCOPE_NOW_PLAYING) { 2208384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen if (mCurrAddrPlayerID == NO_PLAYER_ID) { 2209384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen getItemAttrRspNative( 2210384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen itemAttr.mAddress, AvrcpConstants.RSP_NO_AVBL_PLAY, (byte) 0, null, null); 2211384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } else { 2212384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen mAddressedMediaPlayer.getItemAttr(itemAttr.mAddress, itemAttr, mMediaController); 2213384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } 2214384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } else { 2215384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen if (mAvrcpBrowseManager.getBrowsedMediaPlayer(itemAttr.mAddress) != null) { 2216e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager.getBrowsedMediaPlayer(itemAttr.mAddress).getItemAttr(itemAttr); 2217384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } else { 2218e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "Could not get attributes. mBrowsedMediaPlayer is null"); 2219e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah getItemAttrRspNative(itemAttr.mAddress, AvrcpConstants.RSP_INTERNAL_ERR, 2220e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah (byte) 0, null, null); 2221e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2222e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2223e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2224e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2225e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handleGetTotalNumOfItemsResponse(byte[] bdaddr, byte scope) { 2226e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // for scope as media player list 2227e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (scope == AvrcpConstants.BTRC_SCOPE_PLAYER_LIST) { 2228511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int numPlayers = 0; 2229511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 2230511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen numPlayers = mMediaPlayerInfoList.size(); 2231511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2232511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.d(TAG, "handleGetTotalNumOfItemsResponse: " + numPlayers + " players."); 2233511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen getTotalNumOfItemsRspNative(bdaddr, AvrcpConstants.RSP_NO_ERROR, 0, numPlayers); 2234511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } else if (scope == AvrcpConstants.BTRC_SCOPE_NOW_PLAYING) { 2235294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen mAddressedMediaPlayer.getTotalNumOfItems(bdaddr, mMediaController); 2236e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2237e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // for FileSystem browsing scopes as VFS, Now Playing 2238e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr) != null) { 2239e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr).getTotalNumOfItems(scope); 2240e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2241e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "Could not get Total NumOfItems. mBrowsedMediaPlayer is null"); 2242e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah getTotalNumOfItemsRspNative(bdaddr, AvrcpConstants.RSP_INTERNAL_ERR, 0, 0); 2243e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2244e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2245e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2246e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2247e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2248e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* check if browsed player and addressed player are same */ 2249e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean isAddrPlayerSameAsBrowsed(byte[] bdaddr) { 2250e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String browsedPlayer = getCurrentBrowsedPlayer(bdaddr); 2251e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2252e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!isPackageNameValid(browsedPlayer)) { 2253e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, "Browsed player name empty"); 2254eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen return false; 2255e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2256e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2257b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen MediaPlayerInfo info = getAddressedPlayerInfo(); 2258db2d487ba559f0e4de02bc2ad4cc7e275878b2fcMarie Janssen String packageName = (info == null) ? "<none>" : info.getPackageName(); 2259db2d487ba559f0e4de02bc2ad4cc7e275878b2fcMarie Janssen if (info == null || !packageName.equals(browsedPlayer)) { 2260db2d487ba559f0e4de02bc2ad4cc7e275878b2fcMarie Janssen if (DEBUG) Log.d(TAG, browsedPlayer + " is not addressed player " + packageName); 2261eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen return false; 2262eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 2263eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen return true; 2264e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2265e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2266e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* checks if package name is not null or empty */ 2267e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean isPackageNameValid(String browsedPackage) { 2268e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah boolean isValid = (browsedPackage != null && browsedPackage.length() > 0); 2269e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "isPackageNameValid: browsedPackage = " + browsedPackage + 2270e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah "isValid = " + isValid); 2271e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return isValid; 2272e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2273e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2274e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* checks if selected addressed player is already addressed */ 2275e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean isPlayerAlreadyAddressed(int selectedId) { 2276e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // checking if selected ID is same as the current addressed player id 2277e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah boolean isAddressed = (mCurrAddrPlayerID == selectedId); 2278e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "isPlayerAlreadyAddressed: isAddressed = " + isAddressed); 2279e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return isAddressed; 2280e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2281e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2282e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void dump(StringBuilder sb) { 2283e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah sb.append("AVRCP:\n"); 2284e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mMediaAttributes: " + mMediaAttributes); 2285e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mTransportControlFlags: " + mTransportControlFlags); 2286e23a886e79f60a3f7f5b8e87f8c5ffc26134bd32Marie Janssen ProfileService.println(sb, "mTracksPlayed: " + mTracksPlayed); 2287e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mCurrentPlayState: " + mCurrentPlayState); 2288e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mPlayStatusChangedNT: " + mPlayStatusChangedNT); 2289e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mTrackChangedNT: " + mTrackChangedNT); 2290e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mPlaybackIntervalMs: " + mPlaybackIntervalMs); 2291e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mPlayPosChangedNT: " + mPlayPosChangedNT); 2292e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mNextPosMs: " + mNextPosMs); 2293e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mPrevPosMs: " + mPrevPosMs); 2294e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mSkipStartTime: " + mSkipStartTime); 2295e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mFeatures: " + mFeatures); 2296e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mRemoteVolume: " + mRemoteVolume); 2297e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mLastRemoteVolume: " + mLastRemoteVolume); 2298e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mLastDirection: " + mLastDirection); 2299e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mVolumeStep: " + mVolumeStep); 2300e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mAudioStreamMax: " + mAudioStreamMax); 2301e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mVolCmdAdjustInProgress: " + mVolCmdAdjustInProgress); 2302e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mVolCmdSetInProgress: " + mVolCmdSetInProgress); 2303e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mAbsVolRetryTimes: " + mAbsVolRetryTimes); 2304e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mSkipAmount: " + mSkipAmount); 2305e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mVolumeMapping: " + mVolumeMapping.toString()); 2306e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mMediaController != null) 2307384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen ProfileService.println(sb, "mMediaController: " + mMediaController.getWrappedInstance() 2308384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen + " pkg " + mMediaController.getPackageName()); 2309b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen 2310b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen ProfileService.println(sb, "\nMedia Players:"); 2311511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 2312511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) { 2313511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int key = entry.getKey(); 2314511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen ProfileService.println(sb, ((mCurrAddrPlayerID == key) ? " *#" : " #") 2315511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen + entry.getKey() + ": " + entry.getValue()); 2316511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 231705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 231805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 231905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen ProfileService.println(sb, "Passthrough operations: "); 232005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen for (MediaKeyLog log : mPassthroughLogs) { 232105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen ProfileService.println(sb, " " + log); 232205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 232305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen for (MediaKeyLog log : mPassthroughPending) { 232405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen ProfileService.println(sb, " " + log); 2325b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen } 2326e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2327e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2328e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public class AvrcpBrowseManager { 2329e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Map<String, BrowsedMediaPlayer> connList = new HashMap<String, BrowsedMediaPlayer>(); 2330e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private AvrcpMediaRspInterface mMediaInterface; 2331e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private Context mContext; 2332e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2333e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public AvrcpBrowseManager(Context context, AvrcpMediaRspInterface mediaInterface) { 2334e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mContext = context; 2335e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mMediaInterface = mediaInterface; 2336e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2337e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2338e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void cleanup() { 2339e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Iterator entries = connList.entrySet().iterator(); 2340e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah while (entries.hasNext()) { 2341e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Map.Entry entry = (Map.Entry) entries.next(); 2342e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah BrowsedMediaPlayer browsedMediaPlayer = (BrowsedMediaPlayer) entry.getValue(); 2343e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (browsedMediaPlayer != null) { 2344e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah browsedMediaPlayer.cleanup(); 2345e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2346e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2347e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // clean up the map 2348e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah connList.clear(); 2349e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2350e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2351e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // get the a free media player interface based on the passed bd address 2352e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // if the no items is found for the passed media player then it assignes a 2353e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // available media player interface 2354e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public BrowsedMediaPlayer getBrowsedMediaPlayer(byte[] bdaddr) { 2355e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah BrowsedMediaPlayer mediaPlayer; 2356e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String bdaddrStr = new String(bdaddr); 235705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (connList.containsKey(bdaddrStr)) { 2358e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mediaPlayer = connList.get(bdaddrStr); 2359e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2360e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mediaPlayer = new BrowsedMediaPlayer(bdaddr, mContext, mMediaInterface); 2361e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah connList.put(bdaddrStr, mediaPlayer); 2362e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2363e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return mediaPlayer; 2364e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2365e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2366e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // clears the details pertaining to passed bdaddres 2367e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public boolean clearBrowsedMediaPlayer(byte[] bdaddr) { 2368e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String bdaddrStr = new String(bdaddr); 236905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (connList.containsKey(bdaddrStr)) { 2370e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah connList.remove(bdaddrStr); 2371e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return true; 2372e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2373e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return false; 2374e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2375e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2376e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public Map<String, BrowsedMediaPlayer> getConnList() { 2377e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return connList; 2378e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2379e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2380e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Helper function to convert colon separated bdaddr to byte string */ 2381e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private byte[] hexStringToByteArray(String s) { 2382e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int len = s.length(); 2383e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] data = new byte[len / 2]; 2384e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah for (int i = 0; i < len; i += 2) { 2385e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) 2386e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + Character.digit(s.charAt(i+1), 16)); 2387e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2388e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return data; 2389e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2390e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2391e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2392e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* 2393e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * private class which handles responses from AvrcpMediaManager. Maps responses to native 2394e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * responses. This class implements the AvrcpMediaRspInterface interface. 2395e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 2396e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private class AvrcpMediaRsp implements AvrcpMediaRspInterface { 2397e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final String TAG = "AvrcpMediaRsp"; 2398e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2399e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void setAddrPlayerRsp(byte[] address, int rspStatus) { 2400e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!setAddressedPlayerRspNative(address, rspStatus)) { 2401e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "setAddrPlayerRsp failed!"); 2402e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2403e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2404e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2405e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void setBrowsedPlayerRsp(byte[] address, int rspStatus, byte depth, int numItems, 2406e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String[] textArray) { 2407e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!setBrowsedPlayerRspNative(address, rspStatus, depth, numItems, textArray)) { 2408e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "setBrowsedPlayerRsp failed!"); 2409e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2410e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2411e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2412e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void mediaPlayerListRsp(byte[] address, int rspStatus, MediaPlayerListRsp rspObj) { 2413e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (rspObj != null && rspStatus == AvrcpConstants.RSP_NO_ERROR) { 2414e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!mediaPlayerListRspNative(address, rspStatus, sUIDCounter, rspObj.itemType, 2415eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen rspObj.mNumItems, rspObj.mPlayerIds, rspObj.mPlayerTypes, 2416eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen rspObj.mPlayerSubTypes, rspObj.mPlayStatusValues, 2417eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen rspObj.mFeatureBitMaskValues, rspObj.mPlayerNameList)) 2418eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen Log.e(TAG, "mediaPlayerListRsp failed!"); 2419e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2420e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "mediaPlayerListRsp: rspObj is null"); 2421eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen if (!mediaPlayerListRspNative(address, rspStatus, sUIDCounter, (byte) 0x00, 0, null, 2422eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen null, null, null, null, null)) 2423eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen Log.e(TAG, "mediaPlayerListRsp failed!"); 2424e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2425e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2426e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2427e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void folderItemsRsp(byte[] address, int rspStatus, FolderItemsRsp rspObj) { 2428e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (rspObj != null && rspStatus == AvrcpConstants.RSP_NO_ERROR) { 2429e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!getFolderItemsRspNative(address, rspStatus, sUIDCounter, rspObj.mScope, 2430e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah rspObj.mNumItems, rspObj.mFolderTypes, rspObj.mPlayable, rspObj.mItemTypes, 2431e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah rspObj.mItemUid, rspObj.mDisplayNames, rspObj.mAttributesNum, 2432e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah rspObj.mAttrIds, rspObj.mAttrValues)) 2433e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getFolderItemsRspNative failed!"); 2434e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2435e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "folderItemsRsp: rspObj is null or rspStatus is error:" + rspStatus); 2436e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!getFolderItemsRspNative(address, rspStatus, sUIDCounter, (byte) 0x00, 0, 2437e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah null, null, null, null, null, null, null, null)) 2438e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getFolderItemsRspNative failed!"); 2439e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2440e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2441e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2442e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2443e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void changePathRsp(byte[] address, int rspStatus, int numItems) { 2444e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!changePathRspNative(address, rspStatus, numItems)) 2445e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "changePathRspNative failed!"); 2446e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2447e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2448e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void getItemAttrRsp(byte[] address, int rspStatus, ItemAttrRsp rspObj) { 2449e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (rspObj != null && rspStatus == AvrcpConstants.RSP_NO_ERROR) { 2450e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!getItemAttrRspNative(address, rspStatus, rspObj.mNumAttr, 2451e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah rspObj.mAttributesIds, rspObj.mAttributesArray)) 2452e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getItemAttrRspNative failed!"); 2453e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2454e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getItemAttrRsp: rspObj is null or rspStatus is error:" + rspStatus); 2455e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!getItemAttrRspNative(address, rspStatus, (byte) 0x00, null, null)) 2456e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getItemAttrRspNative failed!"); 2457e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2458e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2459e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2460e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void playItemRsp(byte[] address, int rspStatus) { 2461e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!playItemRspNative(address, rspStatus)) { 2462e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "playItemRspNative failed!"); 2463e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2464e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2465e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2466e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void getTotalNumOfItemsRsp(byte[] address, int rspStatus, int uidCounter, 2467e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int numItems) { 2468e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!getTotalNumOfItemsRspNative(address, rspStatus, sUIDCounter, numItems)) { 2469e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getTotalNumOfItemsRspNative failed!"); 2470e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2471e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2472e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 247305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public void addrPlayerChangedRsp(int type, int playerId, int uidCounter) { 2474e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspAddrPlayerChangedNative(type, playerId, sUIDCounter)) { 2475e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "registerNotificationRspAddrPlayerChangedNative failed!"); 2476e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2477e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2478e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2479e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void avalPlayerChangedRsp(byte[] address, int type) { 2480e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspAvalPlayerChangedNative(type)) { 2481e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "registerNotificationRspAvalPlayerChangedNative failed!"); 2482e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2483e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2484e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2485e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void uidsChangedRsp(byte[] address, int type, int uidCounter) { 2486e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspUIDsChangedNative(type, sUIDCounter)) { 2487e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "registerNotificationRspUIDsChangedNative failed!"); 2488e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2489e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2490e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2491e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void nowPlayingChangedRsp(int type) { 2492e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspNowPlayingChangedNative(type)) { 2493e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "registerNotificationRspNowPlayingChangedNative failed!"); 2494e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2495e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2496e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2497e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void trackChangedRsp(int type, byte[] uid) { 2498e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspTrackChangeNative(type, uid)) { 2499e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "registerNotificationRspTrackChangeNative failed!"); 2500e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2501e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2502e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2503e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2504e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* getters for some private variables */ 2505e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public AvrcpBrowseManager getAvrcpBrowseManager() { 2506e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return mAvrcpBrowseManager; 2507e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2508e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 250905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen /* PASSTHROUGH COMMAND MANAGEMENT */ 251005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 251105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen void handlePassthroughCmd(int op, int state) { 251205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen int code = avrcpPassthroughToKeyCode(op); 251305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (code == KeyEvent.KEYCODE_UNKNOWN) { 251405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.w(TAG, "Ignoring passthrough of unknown key " + op + " state " + state); 251505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return; 251605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 251705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen int action = KeyEvent.ACTION_DOWN; 251805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (state == AvrcpConstants.KEY_STATE_RELEASE) action = KeyEvent.ACTION_UP; 251905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen KeyEvent event = new KeyEvent(action, code); 252005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (!KeyEvent.isMediaKey(code)) { 252105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.w(TAG, "Passthrough non-media key " + op + " (code " + code + ") state " + state); 252205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 252305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mMediaSessionManager.dispatchMediaKeyEvent(event); 252405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen addKeyPending(event); 252505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 252605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 252705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private int avrcpPassthroughToKeyCode(int operation) { 252805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen switch (operation) { 252905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_UP: 253005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_UP; 253105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_DOWN: 253205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_DOWN; 253305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_LEFT: 253405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_LEFT; 253505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_RIGHT: 253605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_RIGHT; 253705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_RIGHT_UP: 253805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_UP_RIGHT; 253905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_RIGHT_DOWN: 254005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_DOWN_RIGHT; 254105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_LEFT_UP: 254205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_UP_LEFT; 254305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_LEFT_DOWN: 254405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_DOWN_LEFT; 254505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_0: 254605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_0; 254705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_1: 254805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_1; 254905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_2: 255005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_2; 255105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_3: 255205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_3; 255305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_4: 255405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_4; 255505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_5: 255605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_5; 255705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_6: 255805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_6; 255905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_7: 256005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_7; 256105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_8: 256205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_8; 256305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_9: 256405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_9; 256505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_DOT: 256605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_DOT; 256705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_ENTER: 256805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_ENTER; 256905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_CLEAR: 257005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_CLEAR; 257105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_CHAN_UP: 257205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_CHANNEL_UP; 257305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_CHAN_DOWN: 257405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_CHANNEL_DOWN; 257505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_PREV_CHAN: 257605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_LAST_CHANNEL; 257705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_INPUT_SEL: 257805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_TV_INPUT; 257905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_DISP_INFO: 258005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_INFO; 258105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_HELP: 258205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_HELP; 258305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_PAGE_UP: 258405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_PAGE_UP; 258505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_PAGE_DOWN: 258605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_PAGE_DOWN; 258705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_POWER: 258805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_POWER; 258905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_VOL_UP: 259005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_VOLUME_UP; 259105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_VOL_DOWN: 259205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_VOLUME_DOWN; 259305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_MUTE: 259405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MUTE; 259505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_PLAY: 259605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_PLAY; 259705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_STOP: 259805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_STOP; 259905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_PAUSE: 260005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_PAUSE; 260105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_RECORD: 260205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_RECORD; 260305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_REWIND: 260405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_REWIND; 260505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_FAST_FOR: 260605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_FAST_FORWARD; 260705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_EJECT: 260805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_EJECT; 260905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_FORWARD: 261005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_NEXT; 261105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_BACKWARD: 261205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_PREVIOUS; 261305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_F1: 261405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_F1; 261505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_F2: 261605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_F2; 261705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_F3: 261805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_F3; 261905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_F4: 262005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_F4; 262105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_F5: 262205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_F5; 262305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen // Fallthrough for all unknown key mappings 262405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_SELECT: 262505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_ROOT_MENU: 262605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_SETUP_MENU: 262705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_CONT_MENU: 262805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_FAV_MENU: 262905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_EXIT: 263005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_SOUND_SEL: 263105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_ANGLE: 263205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_SUBPICT: 263305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_VENDOR: 263405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen default: 263505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_UNKNOWN; 263605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 263705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 263805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 263905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private void addKeyPending(KeyEvent event) { 264005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen synchronized (mPassthroughPending) { 264105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mPassthroughPending.add(new MediaKeyLog(System.currentTimeMillis(), event)); 264205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 264305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 264405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 264505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private void recordKeyDispatched(KeyEvent event, String packageName) { 264605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen long time = System.currentTimeMillis(); 264705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.v(TAG, "recordKeyDispatched: " + event + " dispatched to " + packageName); 264805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen synchronized (mPassthroughPending) { 264905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Iterator<MediaKeyLog> pending = mPassthroughPending.iterator(); 265005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen while (pending.hasNext()) { 265105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen MediaKeyLog log = pending.next(); 265205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (log.addDispatch(time, event, packageName)) { 265305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mPassthroughDispatched++; 265405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mPassthroughLogs.add(log); 265505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen pending.remove(); 265605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return; 265705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 265805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 265905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 266005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 266105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 266205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private final MediaSessionManager.Callback mButtonDispatchCallback = 266305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen new MediaSessionManager.Callback() { 266405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen @Override 266505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public void onMediaKeyEventDispatched(KeyEvent event, MediaSession.Token token) { 266605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen // Get the package name 266705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen android.media.session.MediaController controller = 266805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen new android.media.session.MediaController(mContext, token); 266905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen String targetPackage = controller.getPackageName(); 267005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen recordKeyDispatched(event, targetPackage); 267105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 267205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 267305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen @Override 267405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public void onMediaKeyEventDispatched(KeyEvent event, ComponentName receiver) { 267505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen recordKeyDispatched(event, receiver.getPackageName()); 267605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 267705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 267805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen @Override 267905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public void onAddressedPlayerChanged(MediaSession.Token token) { 268005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen setActiveMediaSession(token); 268105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 268205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 268305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen @Override 268405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public void onAddressedPlayerChanged(ComponentName receiver) { 268541527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen if (receiver == null) { 268641527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen // No active sessions, and no session to revive, give up. 268741527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen setAddressedMediaSessionPackage(null); 268841527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen return; 268941527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen } 269041527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen // We can still get a passthrough which will revive this player. 269105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen setAddressedMediaSessionPackage(receiver.getPackageName()); 269205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 269305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen }; 269405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 2695e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // Do not modify without updating the HAL bt_rc.h files. 2696e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2697e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // match up with btrc_play_status_t enum of bt_rc.h 2698e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int PLAYSTATUS_STOPPED = 0; 2699e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int PLAYSTATUS_PLAYING = 1; 2700e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int PLAYSTATUS_PAUSED = 2; 2701e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int PLAYSTATUS_FWD_SEEK = 3; 2702e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int PLAYSTATUS_REV_SEEK = 4; 2703e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int PLAYSTATUS_ERROR = 255; 2704e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2705e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // match up with btrc_media_attr_t enum of bt_rc.h 2706e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_TITLE = 1; 2707e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_ARTIST = 2; 2708e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_ALBUM = 3; 2709e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_TRACK_NUM = 4; 2710e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_NUM_TRACKS = 5; 2711e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_GENRE = 6; 2712e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_PLAYING_TIME = 7; 2713e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2714e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // match up with btrc_event_id_t enum of bt_rc.h 2715e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_PLAY_STATUS_CHANGED = 1; 2716e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_TRACK_CHANGED = 2; 2717e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_TRACK_REACHED_END = 3; 2718e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_TRACK_REACHED_START = 4; 2719e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_PLAY_POS_CHANGED = 5; 2720e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_BATT_STATUS_CHANGED = 6; 2721e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_SYSTEM_STATUS_CHANGED = 7; 2722e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_APP_SETTINGS_CHANGED = 8; 2723e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVENT_NOW_PLAYING_CONTENT_CHANGED = 9; 2724e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_AVBL_PLAYERS_CHANGED = 0xa; 2725e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_ADDR_PLAYER_CHANGED = 0xb; 2726e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVENT_UIDS_CHANGED = 0x0c; 2727c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 2728c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native static void classInitNative(); 2729c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native void initNative(); 2730c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native void cleanupNative(); 2731e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean getPlayStatusRspNative(byte[] address, int playStatus, int songLen, 2732e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int songPos); 2733e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean getElementAttrRspNative(byte[] address, byte numAttr, int[] attrIds, 2734e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String[] textArray); 2735c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native boolean registerNotificationRspPlayStatusNative(int type, int playStatus); 2736c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native boolean registerNotificationRspTrackChangeNative(int type, byte[] track); 2737aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private native boolean registerNotificationRspPlayPosNative(int type, int playPos); 273817675906064bb72fdcca75baa56cdf8bb8968d01John Du private native boolean setVolumeNative(int volume); 27395c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta private native boolean sendPassThroughCommandNative(int keyCode, int keyState); 2740e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean setAddressedPlayerRspNative(byte[] address, int rspStatus); 2741e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean setBrowsedPlayerRspNative(byte[] address, int rspStatus, byte depth, 2742e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int numItems, String[] textArray); 2743e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean mediaPlayerListRspNative(byte[] address, int rsStatus, int uidCounter, 2744eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen byte item_type, int numItems, int[] playerIds, byte[] playerTypes, int[] playerSubTypes, 2745eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen byte[] playStatusValues, short[] featureBitMaskValues, String[] textArray); 2746e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean getFolderItemsRspNative(byte[] address, int rspStatus, short uidCounter, 2747e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte scope, int numItems, byte[] folderTypes, byte[] playable, byte[] itemTypes, 2748e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] itemUidArray, String[] textArray, int[] AttributesNum, int[] AttributesIds, 2749e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String[] attributesArray); 2750e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean changePathRspNative(byte[] address, int rspStatus, int numItems); 2751e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean getItemAttrRspNative(byte[] address, int rspStatus, byte numAttr, 2752e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int[] attrIds, String[] textArray); 2753e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean playItemRspNative(byte[] address, int rspStatus); 2754e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean getTotalNumOfItemsRspNative(byte[] address, int rspStatus, 2755e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int uidCounter, int numItems); 2756e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean searchRspNative(byte[] address, int rspStatus, int uidCounter, 2757e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int numItems); 2758e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean addToNowPlayingRspNative(byte[] address, int rspStatus); 2759e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean registerNotificationRspAddrPlayerChangedNative(int type, 2760e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int playerId, int uidCounter); 2761e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean registerNotificationRspAvalPlayerChangedNative(int type); 2762e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean registerNotificationRspUIDsChangedNative(int type, int uidCounter); 2763e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean registerNotificationRspNowPlayingChangedNative(int type); 27645c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta 2765c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 2766