Avrcp.java revision a24231afabc31d1e7c903441108e19931d52a599
1c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu/* 2e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * Copyright (C) 2016 The Android Open Source Project 3c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * 4c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * Licensed under the Apache License, Version 2.0 (the "License"); 5c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * you may not use this file except in compliance with the License. 6c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * You may obtain a copy of the License at 7c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * 8c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * http://www.apache.org/licenses/LICENSE-2.0 9c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * 10c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * Unless required by applicable law or agreed to in writing, software 11c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * distributed under the License is distributed on an "AS IS" BASIS, 12c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * See the License for the specific language governing permissions and 14c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * limitations under the License. 15c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu */ 16c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 17066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodpackage com.android.bluetooth.avrcp; 18c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1929174eb9ad6e255d7ec216ab9a2ce8d20e2fe13cMarie Janssenimport android.annotation.NonNull; 2078d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssenimport android.annotation.Nullable; 21188f205b5f093850d4cc627917a21204be36c56aZhihai Xuimport android.bluetooth.BluetoothA2dp; 22066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodimport android.bluetooth.BluetoothAvrcp; 23e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.bluetooth.BluetoothDevice; 24e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.BroadcastReceiver; 25e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.ComponentName; 26c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.content.Context; 27e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.Intent; 28e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.IntentFilter; 29e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.pm.ApplicationInfo; 30e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.pm.PackageManager; 31e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.pm.PackageManager.NameNotFoundException; 32e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.content.pm.ResolveInfo; 3311798b011c962b602217b479130d413f3b30f19aLiejun Taoimport android.content.res.Resources; 3411798b011c962b602217b479130d413f3b30f19aLiejun Taoimport android.content.SharedPreferences; 35c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.media.AudioManager; 36a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavovimport android.media.AudioPlaybackConfiguration; 373b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssenimport android.media.MediaDescription; 380e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssenimport android.media.MediaMetadata; 393843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssenimport android.media.browse.MediaBrowser; 40e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.media.session.MediaSession; 41e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.media.session.MediaSession.QueueItem; 420e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssenimport android.media.session.MediaSessionManager; 430e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssenimport android.media.session.PlaybackState; 44e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport android.os.Bundle; 45c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.Handler; 46c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.HandlerThread; 47c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.Looper; 48c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.Message; 49aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xuimport android.os.SystemClock; 500427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panickerimport android.os.UserManager; 51c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.util.Log; 52881675b362bde18acbbcf69c513175addca4a8baZhenye Zhuimport android.view.KeyEvent; 536e29e12add362546784126119f26f04fc760f021RoboErik 54c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport com.android.bluetooth.btservice.ProfileService; 55e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport com.android.bluetooth.R; 56aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xuimport com.android.bluetooth.Utils; 576e29e12add362546784126119f26f04fc760f021RoboErik 58c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport java.util.ArrayList; 5978d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssenimport java.util.Collections; 6011798b011c962b602217b479130d413f3b30f19aLiejun Taoimport java.util.HashMap; 61bc5aacf160c5cc7ff5a196c7c3c1cf62f322fc14Marie Janssenimport java.util.HashSet; 62e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport java.util.Iterator; 63c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport java.util.List; 64e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shahimport java.util.Map; 65bc5aacf160c5cc7ff5a196c7c3c1cf62f322fc14Marie Janssenimport java.util.Set; 66eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssenimport java.util.SortedMap; 67eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssenimport java.util.TreeMap; 68e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 69e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah/****************************************************************************** 70e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * support Bluetooth AVRCP profile. support metadata, play status, event 71e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * notifications, address player selection and browse feature implementation. 72e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ******************************************************************************/ 73eb7b90f5b93db1230a5b64caa3d8d05a642e33a6Marie Janssen 74066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodpublic final class Avrcp { 751b70ec148be773651d5ad00e3ce0d28b3a63306dAjay Panicker private static final boolean DEBUG = true; 76c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private static final String TAG = "Avrcp"; 7711798b011c962b602217b479130d413f3b30f19aLiejun Tao private static final String ABSOLUTE_VOLUME_BLACKLIST = "absolute_volume_blacklist"; 78c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 79c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private Context mContext; 80c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private final AudioManager mAudioManager; 81c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private AvrcpMessageHandler mHandler; 82a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov private Handler mAudioManagerPlaybackHandler; 83a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov private AudioManagerPlaybackListener mAudioManagerPlaybackCb; 840e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen private MediaSessionManager mMediaSessionManager; 8529174eb9ad6e255d7ec216ab9a2ce8d20e2fe13cMarie Janssen private @Nullable MediaController mMediaController; 860e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen private MediaControllerListener mMediaControllerCb; 873b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private MediaAttributes mMediaAttributes; 885aca05c1d79f3412b6964b3b6335ad6f2d558756Marie Janssen private long mLastQueueId; 89e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private PackageManager mPackageManager; 90c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private int mTransportControlFlags; 9129174eb9ad6e255d7ec216ab9a2ce8d20e2fe13cMarie Janssen private @NonNull PlaybackState mCurrentPlayState; 920a429916782c20980e7f0893c503c633b8341f88Marie Janssen private int mA2dpState; 93a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov private boolean mAudioManagerIsPlaying; 94c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private int mPlayStatusChangedNT; 95cb00f2feb8405508707e41e463a79bf77eac7bc7Ajay Panicker private byte mReportedPlayStatus; 96c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private int mTrackChangedNT; 97f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen private int mPlayPosChangedNT; 9859b1c77f883bd97816332046a3a98be4431cceddMarie Janssen private int mAddrPlayerChangedNT; 9959b1c77f883bd97816332046a3a98be4431cceddMarie Janssen private int mReportedPlayerID; 10005723ee9e6619814876a6cce5004d11b38c3f648Ajay Panicker private int mNowPlayingListChangedNT; 101aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mPlaybackIntervalMs; 102fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen private long mLastReportedPosition; 103aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mNextPosMs; 104aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mPrevPosMs; 10517675906064bb72fdcca75baa56cdf8bb8968d01John Du private int mFeatures; 10611798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mRemoteVolume; 10711798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mLastRemoteVolume; 10811798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mInitialRemoteVolume; 10911798b011c962b602217b479130d413f3b30f19aLiejun Tao 11011798b011c962b602217b479130d413f3b30f19aLiejun Tao /* Local volume in audio index 0-15 */ 11111798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mLocalVolume; 11211798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mLastLocalVolume; 11311798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mAbsVolThreshold; 11411798b011c962b602217b479130d413f3b30f19aLiejun Tao 11511798b011c962b602217b479130d413f3b30f19aLiejun Tao private String mAddress; 11611798b011c962b602217b479130d413f3b30f19aLiejun Tao private HashMap<Integer, Integer> mVolumeMapping; 11711798b011c962b602217b479130d413f3b30f19aLiejun Tao 11817675906064bb72fdcca75baa56cdf8bb8968d01John Du private int mLastDirection; 1192e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie private final int mVolumeStep; 1202e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie private final int mAudioStreamMax; 12111798b011c962b602217b479130d413f3b30f19aLiejun Tao private boolean mVolCmdAdjustInProgress; 12211798b011c962b602217b479130d413f3b30f19aLiejun Tao private boolean mVolCmdSetInProgress; 12317675906064bb72fdcca75baa56cdf8bb8968d01John Du private int mAbsVolRetryTimes; 124eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 125384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen private static final int NO_PLAYER_ID = 0; 126384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen 127e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private int mCurrAddrPlayerID; 128e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private int mCurrBrowsePlayerID; 129eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen private int mLastUsedPlayerID; 130e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private AvrcpMediaRsp mAvrcpMediaRsp; 131e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 132e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* UID counter to be shared across different files. */ 13359b1c77f883bd97816332046a3a98be4431cceddMarie Janssen static short sUIDCounter = AvrcpConstants.DEFAULT_UID_COUNTER; 134ace834feb02adabd61f628c4471147aea02d939cJohn Du 13517675906064bb72fdcca75baa56cdf8bb8968d01John Du /* BTRC features */ 13617675906064bb72fdcca75baa56cdf8bb8968d01John Du public static final int BTRC_FEAT_METADATA = 0x01; 13717675906064bb72fdcca75baa56cdf8bb8968d01John Du public static final int BTRC_FEAT_ABSOLUTE_VOLUME = 0x02; 13817675906064bb72fdcca75baa56cdf8bb8968d01John Du public static final int BTRC_FEAT_BROWSE = 0x04; 13917675906064bb72fdcca75baa56cdf8bb8968d01John Du 14017675906064bb72fdcca75baa56cdf8bb8968d01John Du /* AVRC response codes, from avrc_defs */ 14117675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_NOT_IMPL = 8; 14217675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_ACCEPT = 9; 14317675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_REJ = 10; 14417675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_IN_TRANS = 11; 14517675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_IMPL_STBL = 12; 14617675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_CHANGED = 13; 14717675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_INTERIM = 15; 14817675906064bb72fdcca75baa56cdf8bb8968d01John Du 149e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* AVRC request commands from Native */ 150e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_GET_RC_FEATURES = 1; 151e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_GET_PLAY_STATUS = 2; 152e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_GET_ELEM_ATTRS = 3; 153e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_REGISTER_NOTIFICATION = 4; 154e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_VOLUME_CHANGE = 5; 155e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_GET_FOLDER_ITEMS = 6; 156e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_SET_ADDR_PLAYER = 7; 157e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_SET_BR_PLAYER = 8; 158e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_CHANGE_PATH = 9; 159e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_PLAY_ITEM = 10; 160e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_GET_ITEM_ATTR = 11; 161e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_GET_TOTAL_NUM_OF_ITEMS = 12; 162e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_NATIVE_REQ_PASS_THROUGH = 13; 163e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 164e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* other AVRC messages */ 165e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_PLAY_INTERVAL_TIMEOUT = 14; 166e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_ADJUST_VOLUME = 15; 167e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_SET_ABSOLUTE_VOLUME = 16; 168e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final int MSG_ABS_VOL_TIMEOUT = 17; 16959b1c77f883bd97816332046a3a98be4431cceddMarie Janssen private static final int MSG_SET_A2DP_AUDIO_STATE = 18; 170f2f6a4ea02e9456f71ea0490112845110ca5d975Marie Janssen private static final int MSG_NOW_PLAYING_CHANGED_RSP = 19; 17105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 17217675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int CMD_TIMEOUT_DELAY = 2000; 173f8201e1c6bf7fadc0a332151a652325a7f31255aLiejun Tao private static final int MAX_ERROR_RETRY_TIMES = 6; 17417675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRCP_MAX_VOL = 127; 17517675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRCP_BASE_VOLUME_STEP = 1; 176ace834feb02adabd61f628c4471147aea02d939cJohn Du 177e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Communicates with MediaPlayer to fetch media content */ 178e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private BrowsedMediaPlayer mBrowsedMediaPlayer; 179e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 18005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen /* Addressed player handling */ 181e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private AddressedMediaPlayer mAddressedMediaPlayer; 182e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 183e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* List of Media player instances, useful for retrieving MediaPlayerList or MediaPlayerInfo */ 184eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen private SortedMap<Integer, MediaPlayerInfo> mMediaPlayerInfoList; 185f2f6a4ea02e9456f71ea0490112845110ca5d975Marie Janssen private boolean mAvailablePlayerViewChanged; 186e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 187e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* List of media players which supports browse */ 1885146bd27869df5473aa53e6271266f51733971efMarie Janssen private List<BrowsePlayerInfo> mBrowsePlayerInfoList; 189e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 190e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Manage browsed players */ 191e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private AvrcpBrowseManager mAvrcpBrowseManager; 192e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 193e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Broadcast receiver for device connections intent broadcasts */ 194e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private final BroadcastReceiver mAvrcpReceiver = new AvrcpServiceBroadcastReceiver(); 1950427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker private final BroadcastReceiver mBootReceiver = new AvrcpServiceBootReceiver(); 196e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 19705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen /* Recording passthrough key dispatches */ 19805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen static private final int PASSTHROUGH_LOG_MAX_SIZE = DEBUG ? 50 : 10; 19905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private EvictingQueue<MediaKeyLog> mPassthroughLogs; // Passthorugh keys dispatched 20078d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen private List<MediaKeyLog> mPassthroughPending; // Passthrough keys sent not dispatched yet 20105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private int mPassthroughDispatched; // Number of keys dispatched 20205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 20305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private class MediaKeyLog { 20405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private long mTimeSent; 20505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private long mTimeProcessed; 20605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private String mPackage; 20705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private KeyEvent mEvent; 20805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 20905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public MediaKeyLog(long time, KeyEvent event) { 21005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mEvent = event; 21105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mTimeSent = time; 21205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 21305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 21405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public boolean addDispatch(long time, KeyEvent event, String packageName) { 21505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (mPackage != null) return false; 21605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (event.getAction() != mEvent.getAction()) return false; 21705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (event.getKeyCode() != mEvent.getKeyCode()) return false; 21805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mPackage = packageName; 21905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mTimeProcessed = time; 22005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return true; 22105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 22205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 22305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public String toString() { 22405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen StringBuilder sb = new StringBuilder(); 22505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen sb.append(android.text.format.DateFormat.format("MM-dd HH:mm:ss", mTimeSent)); 22605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen sb.append(" " + mEvent.toString()); 22705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (mPackage == null) { 22805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen sb.append(" (undispatched)"); 22905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } else { 23005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen sb.append(" to " + mPackage); 23105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen sb.append(" in " + (mTimeProcessed - mTimeSent) + "ms"); 23205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 23305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return sb.toString(); 23405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 23505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 23605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 237c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu static { 238c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu classInitNative(); 239c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 240c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 241c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private Avrcp(Context context) { 2423b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen mMediaAttributes = new MediaAttributes(null); 2435aca05c1d79f3412b6964b3b6335ad6f2d558756Marie Janssen mLastQueueId = MediaSession.QueueItem.UNKNOWN_ID; 2440e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen mCurrentPlayState = new PlaybackState.Builder().setState(PlaybackState.STATE_NONE, -1L, 0.0f).build(); 24559b1c77f883bd97816332046a3a98be4431cceddMarie Janssen mReportedPlayStatus = PLAYSTATUS_ERROR; 2460a429916782c20980e7f0893c503c633b8341f88Marie Janssen mA2dpState = BluetoothA2dp.STATE_NOT_PLAYING; 247a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov mAudioManagerIsPlaying = false; 248e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPlayStatusChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 249e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 250e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPlayPosChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 25159b1c77f883bd97816332046a3a98be4431cceddMarie Janssen mAddrPlayerChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 25205723ee9e6619814876a6cce5004d11b38c3f648Ajay Panicker mNowPlayingListChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 25359b1c77f883bd97816332046a3a98be4431cceddMarie Janssen mPlaybackIntervalMs = 0L; 254fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen mLastReportedPosition = -1; 2553635a926bd7316a55b288a54d409a1070a9c19e8Marie Janssen mNextPosMs = -1; 2563635a926bd7316a55b288a54d409a1070a9c19e8Marie Janssen mPrevPosMs = -1; 25717675906064bb72fdcca75baa56cdf8bb8968d01John Du mFeatures = 0; 25811798b011c962b602217b479130d413f3b30f19aLiejun Tao mRemoteVolume = -1; 25911798b011c962b602217b479130d413f3b30f19aLiejun Tao mInitialRemoteVolume = -1; 26011798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastRemoteVolume = -1; 26117675906064bb72fdcca75baa56cdf8bb8968d01John Du mLastDirection = 0; 26211798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = false; 26311798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = false; 26417675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes = 0; 26511798b011c962b602217b479130d413f3b30f19aLiejun Tao mLocalVolume = -1; 26611798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = -1; 26711798b011c962b602217b479130d413f3b30f19aLiejun Tao mAbsVolThreshold = 0; 26811798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolumeMapping = new HashMap<Integer, Integer>(); 269384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen mCurrAddrPlayerID = NO_PLAYER_ID; 27059b1c77f883bd97816332046a3a98be4431cceddMarie Janssen mReportedPlayerID = mCurrAddrPlayerID; 271294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen mCurrBrowsePlayerID = 0; 272c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mContext = context; 273eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen mLastUsedPlayerID = 0; 274e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAddressedMediaPlayer = null; 275c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 276c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu initNative(); 277c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 278e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mMediaSessionManager = (MediaSessionManager) context.getSystemService( 279e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Context.MEDIA_SESSION_SERVICE); 280c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 2812e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie mAudioStreamMax = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); 2822e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie mVolumeStep = Math.max(AVRCP_BASE_VOLUME_STEP, AVRCP_MAX_VOL/mAudioStreamMax); 283e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 28411798b011c962b602217b479130d413f3b30f19aLiejun Tao Resources resources = context.getResources(); 28511798b011c962b602217b479130d413f3b30f19aLiejun Tao if (resources != null) { 28611798b011c962b602217b479130d413f3b30f19aLiejun Tao mAbsVolThreshold = resources.getInteger(R.integer.a2dp_absolute_volume_initial_threshold); 287241337c1482c484e1a3a5fb24bc642937ab1a47cPavlin Radoslavov 288241337c1482c484e1a3a5fb24bc642937ab1a47cPavlin Radoslavov // Update the threshold if the threshold_percent is valid 289241337c1482c484e1a3a5fb24bc642937ab1a47cPavlin Radoslavov int threshold_percent = 290241337c1482c484e1a3a5fb24bc642937ab1a47cPavlin Radoslavov resources.getInteger(R.integer.a2dp_absolute_volume_initial_threshold_percent); 291241337c1482c484e1a3a5fb24bc642937ab1a47cPavlin Radoslavov if (threshold_percent >= 0 && threshold_percent <= 100) { 292241337c1482c484e1a3a5fb24bc642937ab1a47cPavlin Radoslavov mAbsVolThreshold = (threshold_percent * mAudioStreamMax) / 100; 293241337c1482c484e1a3a5fb24bc642937ab1a47cPavlin Radoslavov } 29411798b011c962b602217b479130d413f3b30f19aLiejun Tao } 295e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 296e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // Register for package removal intent broadcasts for media button receiver persistence 297e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah IntentFilter pkgFilter = new IntentFilter(); 298e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah pkgFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 299e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah pkgFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 300e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah pkgFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); 301e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah pkgFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED); 302e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah pkgFilter.addDataScheme("package"); 303e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah context.registerReceiver(mAvrcpReceiver, pkgFilter); 3040427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker 3050427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker IntentFilter bootFilter = new IntentFilter(); 3069c2ff5bb5082c653ee91d336dcd7f95e4c25e833Ajay Panicker bootFilter.addAction(Intent.ACTION_USER_UNLOCKED); 3070427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker context.registerReceiver(mBootReceiver, bootFilter); 308c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 309c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 3109a5f80a6528d76153a7e97821f114f3370df89a5Marie Janssen private synchronized void start() { 311c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu HandlerThread thread = new HandlerThread("BluetoothAvrcpHandler"); 312c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu thread.start(); 313c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Looper looper = thread.getLooper(); 314c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler = new AvrcpMessageHandler(looper); 315a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov mAudioManagerPlaybackHandler = new Handler(looper); 316a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov mAudioManagerPlaybackCb = new AudioManagerPlaybackListener(); 3179d4035307b85e78f10fba961e225ca09bfb7d0c7Jakub Pawlowski mMediaControllerCb = new MediaControllerListener(); 318e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpMediaRsp = new AvrcpMediaRsp(); 319eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen mMediaPlayerInfoList = new TreeMap<Integer, MediaPlayerInfo>(); 320f2f6a4ea02e9456f71ea0490112845110ca5d975Marie Janssen mAvailablePlayerViewChanged = false; 3215146bd27869df5473aa53e6271266f51733971efMarie Janssen mBrowsePlayerInfoList = Collections.synchronizedList(new ArrayList<BrowsePlayerInfo>()); 32205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mPassthroughDispatched = 0; 32305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mPassthroughLogs = new EvictingQueue<MediaKeyLog>(PASSTHROUGH_LOG_MAX_SIZE); 32478d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen mPassthroughPending = Collections.synchronizedList(new ArrayList<MediaKeyLog>()); 325f65765e71b2a6552c319eb5199914045a1ecdb04Marie Janssen if (mMediaSessionManager != null) { 326f65765e71b2a6552c319eb5199914045a1ecdb04Marie Janssen mMediaSessionManager.addOnActiveSessionsChangedListener(mActiveSessionListener, null, 327f65765e71b2a6552c319eb5199914045a1ecdb04Marie Janssen mHandler); 32805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mMediaSessionManager.setCallback(mButtonDispatchCallback, null); 329f65765e71b2a6552c319eb5199914045a1ecdb04Marie Janssen } 330e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPackageManager = mContext.getApplicationContext().getPackageManager(); 331e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 332e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* create object to communicate with addressed player */ 333e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAddressedMediaPlayer = new AddressedMediaPlayer(mAvrcpMediaRsp); 334e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 335e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* initialize BrowseMananger which manages Browse commands and response */ 336e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager = new AvrcpBrowseManager(mContext, mAvrcpMediaRsp); 3370427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker 33805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen initMediaPlayersList(); 33911bf73ff614f48a41dc379763bc007f271197b26Ajay Panicker 3400427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker UserManager manager = UserManager.get(mContext); 3410427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker if (manager == null || manager.isUserUnlocked()) { 3420427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker if (DEBUG) Log.d(TAG, "User already unlocked, initializing player lists"); 3433843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen // initialize browsable player list and build media player list 344754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker buildBrowsablePlayerList(); 3450427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker } 346a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov 347a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov mAudioManager.registerAudioPlaybackCallback( 348a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov mAudioManagerPlaybackCb, mAudioManagerPlaybackHandler); 349c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 350c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 351066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood public static Avrcp make(Context context) { 352c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (DEBUG) Log.v(TAG, "make"); 353c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Avrcp ar = new Avrcp(context); 354c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ar.start(); 355c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return ar; 356c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 357c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 3589a5f80a6528d76153a7e97821f114f3370df89a5Marie Janssen public synchronized void doQuit() { 359e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "doQuit"); 360a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov if (mAudioManager != null) { 361a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov mAudioManager.unregisterAudioPlaybackCallback(mAudioManagerPlaybackCb); 362a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov } 3639a5f80a6528d76153a7e97821f114f3370df89a5Marie Janssen if (mMediaController != null) mMediaController.unregisterCallback(mMediaControllerCb); 3647c7cc128e93e7e1db8a5ed7f69583ddc6d99493eMarie Janssen if (mMediaSessionManager != null) { 3657c7cc128e93e7e1db8a5ed7f69583ddc6d99493eMarie Janssen mMediaSessionManager.setCallback(null, null); 3667c7cc128e93e7e1db8a5ed7f69583ddc6d99493eMarie Janssen mMediaSessionManager.removeOnActiveSessionsChangedListener(mActiveSessionListener); 3677c7cc128e93e7e1db8a5ed7f69583ddc6d99493eMarie Janssen } 3687c7cc128e93e7e1db8a5ed7f69583ddc6d99493eMarie Janssen 369a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov mAudioManagerPlaybackHandler.removeCallbacksAndMessages(null); 370c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.removeCallbacksAndMessages(null); 371c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Looper looper = mHandler.getLooper(); 372c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (looper != null) { 373c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu looper.quit(); 374c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 375e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 376a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov mAudioManagerPlaybackHandler = null; 377e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler = null; 378e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mContext.unregisterReceiver(mAvrcpReceiver); 3790427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker mContext.unregisterReceiver(mBootReceiver); 380e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 381e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAddressedMediaPlayer.cleanup(); 382e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager.cleanup(); 383c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 384c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 385c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public void cleanup() { 386e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "cleanup"); 387c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu cleanupNative(); 38811798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolumeMapping != null) 38911798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolumeMapping.clear(); 390c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 391c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 392a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov private class AudioManagerPlaybackListener extends AudioManager.AudioPlaybackCallback { 393a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov @Override 394a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov public void onPlaybackConfigChanged(List<AudioPlaybackConfiguration> configs) { 395a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov super.onPlaybackConfigChanged(configs); 396a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov boolean isPlaying = false; 397a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov for (AudioPlaybackConfiguration config : configs) { 398a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov if (DEBUG) { 399a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov Log.d(TAG, 400a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov "AudioManager Player: " 401a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov + AudioPlaybackConfiguration.toLogFriendlyString(config)); 402a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov } 403a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov if (config.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) { 404a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov isPlaying = true; 405a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov break; 406a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov } 407a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov } 408a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov if (DEBUG) Log.d(TAG, "AudioManager isPlaying: " + isPlaying); 409a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov if (mAudioManagerIsPlaying != isPlaying) { 410a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov mAudioManagerIsPlaying = isPlaying; 411a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov updateCurrentMediaState(); 412a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov } 413a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov } 414a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov } 415a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov 4160e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen private class MediaControllerListener extends MediaController.Callback { 4170e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen @Override 4180e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen public void onMetadataChanged(MediaMetadata metadata) { 41929174eb9ad6e255d7ec216ab9a2ce8d20e2fe13cMarie Janssen if (DEBUG) Log.v(TAG, "onMetadataChanged"); 42085aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker updateCurrentMediaState(); 421c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 422bc10e7d58aa55da25c18d8056a0254a2b736146aZhihai Xu @Override 423e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public synchronized void onPlaybackStateChanged(PlaybackState state) { 424eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen if (DEBUG) Log.v(TAG, "onPlaybackStateChanged: state " + state.toString()); 425cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker 42685aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker updateCurrentMediaState(); 427c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 428c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 429c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu @Override 4300e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen public void onSessionDestroyed() { 4310e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen Log.v(TAG, "MediaController session destroyed"); 432ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen synchronized (Avrcp.this) { 433ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen if (mMediaController != null) 434ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen removeMediaController(mMediaController.getWrappedInstance()); 435384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } 436c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 437c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 438c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu @Override 439e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void onQueueChanged(List<MediaSession.QueueItem> queue) { 440e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (queue == null) { 441e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.v(TAG, "onQueueChanged: received null queue"); 442e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return; 443e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 4442b903c7262c9b8c0493e36b93b37831e7e075bfcMarie Janssen 445e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.v(TAG, "onQueueChanged: NowPlaying list changed, Queue Size = "+ queue.size()); 446e2619781c799435cf0273d381069c754c5f89a20Marie Janssen mHandler.sendEmptyMessage(MSG_NOW_PLAYING_CHANGED_RSP); 447c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 448c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 449c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 450c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu /** Handles Avrcp messages. */ 451c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private final class AvrcpMessageHandler extends Handler { 452c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private AvrcpMessageHandler(Looper looper) { 453c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu super(looper); 454c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 455c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 456c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu @Override 457c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public void handleMessage(Message msg) { 458c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu switch (msg.what) { 459e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_RC_FEATURES: 460e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah { 46117675906064bb72fdcca75baa56cdf8bb8968d01John Du String address = (String) msg.obj; 46217675906064bb72fdcca75baa56cdf8bb8968d01John Du mFeatures = msg.arg1; 46311798b011c962b602217b479130d413f3b30f19aLiejun Tao mFeatures = modifyRcFeatureFromBlacklist(mFeatures, address); 464414480de643b551c1d2dd7db971cc24cff29a605Pavlin Radoslavov if (DEBUG) { 465414480de643b551c1d2dd7db971cc24cff29a605Pavlin Radoslavov Log.v(TAG, 466414480de643b551c1d2dd7db971cc24cff29a605Pavlin Radoslavov "MSG_NATIVE_REQ_GET_RC_FEATURES: address=" + address 467414480de643b551c1d2dd7db971cc24cff29a605Pavlin Radoslavov + ", features=" + msg.arg1 + ", mFeatures=" + mFeatures); 468414480de643b551c1d2dd7db971cc24cff29a605Pavlin Radoslavov } 46917675906064bb72fdcca75baa56cdf8bb8968d01John Du mAudioManager.avrcpSupportsAbsoluteVolume(address, isAbsoluteVolumeSupported()); 47011798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = -1; 47111798b011c962b602217b479130d413f3b30f19aLiejun Tao mRemoteVolume = -1; 47211798b011c962b602217b479130d413f3b30f19aLiejun Tao mLocalVolume = -1; 47311798b011c962b602217b479130d413f3b30f19aLiejun Tao mInitialRemoteVolume = -1; 47411798b011c962b602217b479130d413f3b30f19aLiejun Tao mAddress = address; 47511798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolumeMapping != null) 47611798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolumeMapping.clear(); 47717675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 478e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 47917675906064bb72fdcca75baa56cdf8bb8968d01John Du 480e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_PLAY_STATUS: 481e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah { 482e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] address = (byte[]) msg.obj; 48359b1c77f883bd97816332046a3a98be4431cceddMarie Janssen int btstate = getBluetoothPlayState(mCurrentPlayState); 484e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen int length = (int) mMediaAttributes.getLength(); 485e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen int position = (int) getPlayPosition(); 486e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen if (DEBUG) 487e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen Log.v(TAG, "MSG_NATIVE_REQ_GET_PLAY_STATUS, responding with state " + btstate 488e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen + " len " + length + " pos " + position); 489e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen getPlayStatusRspNative(address, btstate, length, position); 490c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 491e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 492c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 493e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_ELEM_ATTRS: 494e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah { 495c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu String[] textArray; 496e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd.ElementAttrCmd elem = (AvrcpCmd.ElementAttrCmd) msg.obj; 497e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte numAttr = elem.mNumAttr; 498e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int[] attrIds = elem.mAttrIDs; 499e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_GET_ELEM_ATTRS:numAttr=" + numAttr); 500c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu textArray = new String[numAttr]; 501e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen StringBuilder responseDebug = new StringBuilder(); 502e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen responseDebug.append("getElementAttr response: "); 503c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu for (int i = 0; i < numAttr; ++i) { 5043b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen textArray[i] = mMediaAttributes.getString(attrIds[i]); 505cc07ee436d00418ecc69ae3aace986f7fbf0823aMarie Janssen responseDebug.append("[" + attrIds[i] + "="); 506cc07ee436d00418ecc69ae3aace986f7fbf0823aMarie Janssen if (attrIds[i] == AvrcpConstants.ATTRID_TITLE 507cc07ee436d00418ecc69ae3aace986f7fbf0823aMarie Janssen || attrIds[i] == AvrcpConstants.ATTRID_ARTIST 508cc07ee436d00418ecc69ae3aace986f7fbf0823aMarie Janssen || attrIds[i] == AvrcpConstants.ATTRID_ALBUM) { 509cc07ee436d00418ecc69ae3aace986f7fbf0823aMarie Janssen responseDebug.append(Utils.ellipsize(textArray[i]) + "] "); 510cc07ee436d00418ecc69ae3aace986f7fbf0823aMarie Janssen } else { 511cc07ee436d00418ecc69ae3aace986f7fbf0823aMarie Janssen responseDebug.append(textArray[i] + "] "); 512cc07ee436d00418ecc69ae3aace986f7fbf0823aMarie Janssen } 513c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 514e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen Log.v(TAG, responseDebug.toString()); 515e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] bdaddr = elem.mAddress; 516e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah getElementAttrRspNative(bdaddr, numAttr, attrIds, textArray); 517c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 518e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 519c1124a7c6679f612b80926a19084655f9a71580aMarie Janssen 520e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_REGISTER_NOTIFICATION: 521e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_REGISTER_NOTIFICATION:event=" + msg.arg1 + 522e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah " param=" + msg.arg2); 523e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah processRegisterNotification((byte[]) msg.obj, msg.arg1, msg.arg2); 524c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 525c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 526e2619781c799435cf0273d381069c754c5f89a20Marie Janssen case MSG_NOW_PLAYING_CHANGED_RSP: 527e2619781c799435cf0273d381069c754c5f89a20Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NOW_PLAYING_CHANGED_RSP"); 528e2619781c799435cf0273d381069c754c5f89a20Marie Janssen removeMessages(MSG_NOW_PLAYING_CHANGED_RSP); 52985aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker updateCurrentMediaState(); 530e2619781c799435cf0273d381069c754c5f89a20Marie Janssen break; 531e2619781c799435cf0273d381069c754c5f89a20Marie Janssen 532e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_PLAY_INTERVAL_TIMEOUT: 533f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen sendPlayPosNotificationRsp(false); 534aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu break; 535aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 536e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_VOLUME_CHANGE: 53711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (!isAbsoluteVolumeSupported()) { 538e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_VOLUME_CHANGE ignored, not supported"); 53911798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 54011798b011c962b602217b479130d413f3b30f19aLiejun Tao } 541e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen byte absVol = (byte) ((byte) msg.arg1 & 0x7f); // discard MSB as it is RFD 542e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen if (DEBUG) 543e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen Log.v(TAG, "MSG_NATIVE_REQ_VOLUME_CHANGE: volume=" + absVol + " ctype=" 544e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen + msg.arg2); 54511798b011c962b602217b479130d413f3b30f19aLiejun Tao 54611798b011c962b602217b479130d413f3b30f19aLiejun Tao boolean volAdj = false; 54717675906064bb72fdcca75baa56cdf8bb8968d01John Du if (msg.arg2 == AVRC_RSP_ACCEPT || msg.arg2 == AVRC_RSP_REJ) { 54811798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolCmdAdjustInProgress == false && mVolCmdSetInProgress == false) { 54917675906064bb72fdcca75baa56cdf8bb8968d01John Du Log.e(TAG, "Unsolicited response, ignored"); 55017675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 55117675906064bb72fdcca75baa56cdf8bb8968d01John Du } 552e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah removeMessages(MSG_ABS_VOL_TIMEOUT); 55311798b011c962b602217b479130d413f3b30f19aLiejun Tao 55411798b011c962b602217b479130d413f3b30f19aLiejun Tao volAdj = mVolCmdAdjustInProgress; 55511798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = false; 55611798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = false; 55717675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes = 0; 55817675906064bb72fdcca75baa56cdf8bb8968d01John Du } 55911798b011c962b602217b479130d413f3b30f19aLiejun Tao 56011798b011c962b602217b479130d413f3b30f19aLiejun Tao // convert remote volume to local volume 56111798b011c962b602217b479130d413f3b30f19aLiejun Tao int volIndex = convertToAudioStreamVolume(absVol); 56211798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mInitialRemoteVolume == -1) { 56311798b011c962b602217b479130d413f3b30f19aLiejun Tao mInitialRemoteVolume = absVol; 56411798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mAbsVolThreshold > 0 && mAbsVolThreshold < mAudioStreamMax && volIndex > mAbsVolThreshold) { 56511798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.v(TAG, "remote inital volume too high " + volIndex + ">" + mAbsVolThreshold); 566e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg1 = mHandler.obtainMessage(MSG_SET_ABSOLUTE_VOLUME, mAbsVolThreshold , 0); 56711798b011c962b602217b479130d413f3b30f19aLiejun Tao mHandler.sendMessage(msg1); 56811798b011c962b602217b479130d413f3b30f19aLiejun Tao mRemoteVolume = absVol; 56911798b011c962b602217b479130d413f3b30f19aLiejun Tao mLocalVolume = volIndex; 57011798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 57111798b011c962b602217b479130d413f3b30f19aLiejun Tao } 57211798b011c962b602217b479130d413f3b30f19aLiejun Tao } 57311798b011c962b602217b479130d413f3b30f19aLiejun Tao 5740e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen if (mLocalVolume != volIndex && (msg.arg2 == AVRC_RSP_ACCEPT || 5750e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen msg.arg2 == AVRC_RSP_CHANGED || 5760e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen msg.arg2 == AVRC_RSP_INTERIM)) { 57711798b011c962b602217b479130d413f3b30f19aLiejun Tao /* If the volume has successfully changed */ 57811798b011c962b602217b479130d413f3b30f19aLiejun Tao mLocalVolume = volIndex; 57911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mLastLocalVolume != -1 && msg.arg2 == AVRC_RSP_ACCEPT) { 58011798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mLastLocalVolume != volIndex) { 58111798b011c962b602217b479130d413f3b30f19aLiejun Tao /* remote volume changed more than requested due to 58211798b011c962b602217b479130d413f3b30f19aLiejun Tao * local and remote has different volume steps */ 58311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "Remote returned volume does not match desired volume " 584e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + mLastLocalVolume + " vs " + volIndex); 58511798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = mLocalVolume; 58611798b011c962b602217b479130d413f3b30f19aLiejun Tao } 58711798b011c962b602217b479130d413f3b30f19aLiejun Tao } 58811798b011c962b602217b479130d413f3b30f19aLiejun Tao // remember the remote volume value, as it's the one supported by remote 58911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (volAdj) { 59011798b011c962b602217b479130d413f3b30f19aLiejun Tao synchronized (mVolumeMapping) { 591e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mVolumeMapping.put(volIndex, (int) absVol); 59211798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.v(TAG, "remember volume mapping " +volIndex+ "-"+absVol); 59311798b011c962b602217b479130d413f3b30f19aLiejun Tao } 59411798b011c962b602217b479130d413f3b30f19aLiejun Tao } 59511798b011c962b602217b479130d413f3b30f19aLiejun Tao 59611798b011c962b602217b479130d413f3b30f19aLiejun Tao notifyVolumeChanged(mLocalVolume); 59711798b011c962b602217b479130d413f3b30f19aLiejun Tao mRemoteVolume = absVol; 598e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah long pecentVolChanged = ((long) absVol * 100) / 0x7f; 5995c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta Log.e(TAG, "percent volume changed: " + pecentVolChanged + "%"); 60017675906064bb72fdcca75baa56cdf8bb8968d01John Du } else if (msg.arg2 == AVRC_RSP_REJ) { 60117675906064bb72fdcca75baa56cdf8bb8968d01John Du Log.e(TAG, "setAbsoluteVolume call rejected"); 60211798b011c962b602217b479130d413f3b30f19aLiejun Tao } else if (volAdj && mLastRemoteVolume > 0 && mLastRemoteVolume < AVRCP_MAX_VOL && 6030e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen mLocalVolume == volIndex && 604e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah (msg.arg2 == AVRC_RSP_ACCEPT)) { 60511798b011c962b602217b479130d413f3b30f19aLiejun Tao /* oops, the volume is still same, remote does not like the value 60611798b011c962b602217b479130d413f3b30f19aLiejun Tao * retry a volume one step up/down */ 60711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "Remote device didn't tune volume, let's try one more step."); 60811798b011c962b602217b479130d413f3b30f19aLiejun Tao int retry_volume = Math.min(AVRCP_MAX_VOL, 60911798b011c962b602217b479130d413f3b30f19aLiejun Tao Math.max(0, mLastRemoteVolume + mLastDirection)); 61011798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVolumeNative(retry_volume)) { 61111798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastRemoteVolume = retry_volume; 612e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah sendMessageDelayed(obtainMessage(MSG_ABS_VOL_TIMEOUT), CMD_TIMEOUT_DELAY); 61311798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = true; 61411798b011c962b602217b479130d413f3b30f19aLiejun Tao } 61517675906064bb72fdcca75baa56cdf8bb8968d01John Du } 61617675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 61717675906064bb72fdcca75baa56cdf8bb8968d01John Du 618e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_ADJUST_VOLUME: 61911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (!isAbsoluteVolumeSupported()) { 620e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "ignore MSG_ADJUST_VOLUME"); 62111798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 62211798b011c962b602217b479130d413f3b30f19aLiejun Tao } 62311798b011c962b602217b479130d413f3b30f19aLiejun Tao 624e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "MSG_ADJUST_VOLUME: direction=" + msg.arg1); 62511798b011c962b602217b479130d413f3b30f19aLiejun Tao 62611798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolCmdAdjustInProgress || mVolCmdSetInProgress) { 62717675906064bb72fdcca75baa56cdf8bb8968d01John Du if (DEBUG) Log.w(TAG, "There is already a volume command in progress."); 62817675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 62917675906064bb72fdcca75baa56cdf8bb8968d01John Du } 63011798b011c962b602217b479130d413f3b30f19aLiejun Tao 63111798b011c962b602217b479130d413f3b30f19aLiejun Tao // Remote device didn't set initial volume. Let's black list it 63211798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mInitialRemoteVolume == -1) { 63311798b011c962b602217b479130d413f3b30f19aLiejun Tao Log.d(TAG, "remote " + mAddress + " never tell us initial volume, black list it."); 63411798b011c962b602217b479130d413f3b30f19aLiejun Tao blackListCurrentDevice(); 63511798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 63611798b011c962b602217b479130d413f3b30f19aLiejun Tao } 63711798b011c962b602217b479130d413f3b30f19aLiejun Tao 63817675906064bb72fdcca75baa56cdf8bb8968d01John Du // Wait on verification on volume from device, before changing the volume. 63911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mRemoteVolume != -1 && (msg.arg1 == -1 || msg.arg1 == 1)) { 64011798b011c962b602217b479130d413f3b30f19aLiejun Tao int setVol = -1; 64111798b011c962b602217b479130d413f3b30f19aLiejun Tao int targetVolIndex = -1; 64211798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mLocalVolume == 0 && msg.arg1 == -1) { 64311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.w(TAG, "No need to Vol down from 0."); 64411798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 64511798b011c962b602217b479130d413f3b30f19aLiejun Tao } 64611798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mLocalVolume == mAudioStreamMax && msg.arg1 == 1) { 64711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.w(TAG, "No need to Vol up from max."); 64811798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 64911798b011c962b602217b479130d413f3b30f19aLiejun Tao } 65011798b011c962b602217b479130d413f3b30f19aLiejun Tao 65111798b011c962b602217b479130d413f3b30f19aLiejun Tao targetVolIndex = mLocalVolume + msg.arg1; 65211798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "Adjusting volume to " + targetVolIndex); 65311798b011c962b602217b479130d413f3b30f19aLiejun Tao 65411798b011c962b602217b479130d413f3b30f19aLiejun Tao Integer i; 65511798b011c962b602217b479130d413f3b30f19aLiejun Tao synchronized (mVolumeMapping) { 65611798b011c962b602217b479130d413f3b30f19aLiejun Tao i = mVolumeMapping.get(targetVolIndex); 65711798b011c962b602217b479130d413f3b30f19aLiejun Tao } 65811798b011c962b602217b479130d413f3b30f19aLiejun Tao 65911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (i != null) { 66011798b011c962b602217b479130d413f3b30f19aLiejun Tao /* if we already know this volume mapping, use it */ 66111798b011c962b602217b479130d413f3b30f19aLiejun Tao setVol = i.byteValue(); 66211798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVol == mRemoteVolume) { 66311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "got same volume from mapping for " + targetVolIndex + ", ignore."); 66411798b011c962b602217b479130d413f3b30f19aLiejun Tao setVol = -1; 66511798b011c962b602217b479130d413f3b30f19aLiejun Tao } 66611798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "set volume from mapping " + targetVolIndex + "-" + setVol); 66711798b011c962b602217b479130d413f3b30f19aLiejun Tao } 66811798b011c962b602217b479130d413f3b30f19aLiejun Tao 66911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVol == -1) { 67011798b011c962b602217b479130d413f3b30f19aLiejun Tao /* otherwise use phone steps */ 67111798b011c962b602217b479130d413f3b30f19aLiejun Tao setVol = Math.min(AVRCP_MAX_VOL, 672e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah convertToAvrcpVolume(Math.max(0, targetVolIndex))); 67311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "set volume from local volume "+ targetVolIndex+"-"+ setVol); 67411798b011c962b602217b479130d413f3b30f19aLiejun Tao } 67511798b011c962b602217b479130d413f3b30f19aLiejun Tao 67617675906064bb72fdcca75baa56cdf8bb8968d01John Du if (setVolumeNative(setVol)) { 677e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah sendMessageDelayed(obtainMessage(MSG_ABS_VOL_TIMEOUT), CMD_TIMEOUT_DELAY); 67811798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = true; 67917675906064bb72fdcca75baa56cdf8bb8968d01John Du mLastDirection = msg.arg1; 68011798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastRemoteVolume = setVol; 68111798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = targetVolIndex; 68211798b011c962b602217b479130d413f3b30f19aLiejun Tao } else { 68311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "setVolumeNative failed"); 68417675906064bb72fdcca75baa56cdf8bb8968d01John Du } 68517675906064bb72fdcca75baa56cdf8bb8968d01John Du } else { 686e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "Unknown direction in MSG_ADJUST_VOLUME"); 68717675906064bb72fdcca75baa56cdf8bb8968d01John Du } 68817675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 68917675906064bb72fdcca75baa56cdf8bb8968d01John Du 690e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_SET_ABSOLUTE_VOLUME: 69111798b011c962b602217b479130d413f3b30f19aLiejun Tao if (!isAbsoluteVolumeSupported()) { 692e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "ignore MSG_SET_ABSOLUTE_VOLUME"); 69311798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 69411798b011c962b602217b479130d413f3b30f19aLiejun Tao } 69511798b011c962b602217b479130d413f3b30f19aLiejun Tao 696e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_SET_ABSOLUTE_VOLUME"); 69711798b011c962b602217b479130d413f3b30f19aLiejun Tao 69811798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolCmdSetInProgress || mVolCmdAdjustInProgress) { 69917675906064bb72fdcca75baa56cdf8bb8968d01John Du if (DEBUG) Log.w(TAG, "There is already a volume command in progress."); 70017675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 70117675906064bb72fdcca75baa56cdf8bb8968d01John Du } 70211798b011c962b602217b479130d413f3b30f19aLiejun Tao 70311798b011c962b602217b479130d413f3b30f19aLiejun Tao // Remote device didn't set initial volume. Let's black list it 70411798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mInitialRemoteVolume == -1) { 70511798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "remote " + mAddress + " never tell us initial volume, black list it."); 70611798b011c962b602217b479130d413f3b30f19aLiejun Tao blackListCurrentDevice(); 70711798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 70811798b011c962b602217b479130d413f3b30f19aLiejun Tao } 70911798b011c962b602217b479130d413f3b30f19aLiejun Tao 71011798b011c962b602217b479130d413f3b30f19aLiejun Tao int avrcpVolume = convertToAvrcpVolume(msg.arg1); 71111798b011c962b602217b479130d413f3b30f19aLiejun Tao avrcpVolume = Math.min(AVRCP_MAX_VOL, Math.max(0, avrcpVolume)); 7123b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (DEBUG) Log.d(TAG, "Setting volume to " + msg.arg1 + "-" + avrcpVolume); 71311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVolumeNative(avrcpVolume)) { 714e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah sendMessageDelayed(obtainMessage(MSG_ABS_VOL_TIMEOUT), CMD_TIMEOUT_DELAY); 71511798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = true; 71611798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastRemoteVolume = avrcpVolume; 71711798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = msg.arg1; 71811798b011c962b602217b479130d413f3b30f19aLiejun Tao } else { 71911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "setVolumeNative failed"); 72017675906064bb72fdcca75baa56cdf8bb8968d01John Du } 72117675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 72217675906064bb72fdcca75baa56cdf8bb8968d01John Du 723e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_ABS_VOL_TIMEOUT: 724e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_ABS_VOL_TIMEOUT: Volume change cmd timed out."); 72511798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = false; 72611798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = false; 72717675906064bb72fdcca75baa56cdf8bb8968d01John Du if (mAbsVolRetryTimes >= MAX_ERROR_RETRY_TIMES) { 72817675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes = 0; 729f8201e1c6bf7fadc0a332151a652325a7f31255aLiejun Tao /* too many volume change failures, black list the device */ 730f8201e1c6bf7fadc0a332151a652325a7f31255aLiejun Tao blackListCurrentDevice(); 73117675906064bb72fdcca75baa56cdf8bb8968d01John Du } else { 73217675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes += 1; 73311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVolumeNative(mLastRemoteVolume)) { 734e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah sendMessageDelayed(obtainMessage(MSG_ABS_VOL_TIMEOUT), CMD_TIMEOUT_DELAY); 73511798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = true; 73617675906064bb72fdcca75baa56cdf8bb8968d01John Du } 73717675906064bb72fdcca75baa56cdf8bb8968d01John Du } 73817675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 73917675906064bb72fdcca75baa56cdf8bb8968d01John Du 740e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_SET_A2DP_AUDIO_STATE: 741e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "MSG_SET_A2DP_AUDIO_STATE:" + msg.arg1); 7420a429916782c20980e7f0893c503c633b8341f88Marie Janssen mA2dpState = msg.arg1; 74385aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker updateCurrentMediaState(); 744188f205b5f093850d4cc627917a21204be36c56aZhihai Xu break; 745e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 746e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_FOLDER_ITEMS: { 747e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd.FolderItemsCmd folderObj = (AvrcpCmd.FolderItemsCmd) msg.obj; 74889728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_GET_FOLDER_ITEMS " + folderObj); 749e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah switch (folderObj.mScope) { 750e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case AvrcpConstants.BTRC_SCOPE_PLAYER_LIST: 751e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handleMediaPlayerListRsp(folderObj); 752e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 753e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case AvrcpConstants.BTRC_SCOPE_FILE_SYSTEM: 754e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case AvrcpConstants.BTRC_SCOPE_NOW_PLAYING: 755e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handleGetFolderItemBrowseResponse(folderObj, folderObj.mAddress); 756e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 757e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah default: 758e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "unknown scope for getfolderitems. scope = " 759e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + folderObj.mScope); 760e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah getFolderItemsRspNative(folderObj.mAddress, 761e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpConstants.RSP_INV_SCOPE, (short) 0, (byte) 0, 0, 762e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah null, null, null, null, null, null, null, null); 763e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 764e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 765e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 766e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 767e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_SET_ADDR_PLAYER: 768e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // object is bdaddr, argument 1 is the selected player id 769294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_SET_ADDR_PLAYER id=" + msg.arg1); 770e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah setAddressedPlayer((byte[]) msg.obj, msg.arg1); 771e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 772e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 773e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_ITEM_ATTR: 774e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // msg object contains the item attribute object 77589728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen AvrcpCmd.ItemAttrCmd cmd = (AvrcpCmd.ItemAttrCmd) msg.obj; 77689728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_GET_ITEM_ATTR " + cmd); 77789728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen handleGetItemAttr(cmd); 778e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 779e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 780e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_SET_BR_PLAYER: 781e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // argument 1 is the selected player id 782294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_SET_BR_PLAYER id=" + msg.arg1); 783e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah setBrowsedPlayer((byte[]) msg.obj, msg.arg1); 784e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 785e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 786e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_CHANGE_PATH: 787e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah { 788294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_CHANGE_PATH"); 789e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = msg.getData(); 790e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] bdaddr = data.getByteArray("BdAddress"); 791e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] folderUid = data.getByteArray("folderUid"); 792e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte direction = data.getByte("direction"); 793e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr) != null) { 794e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr).changePath(folderUid, 795e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah direction); 796e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 797e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "Remote requesting change path before setbrowsedplayer"); 798e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah changePathRspNative(bdaddr, AvrcpConstants.RSP_BAD_CMD, 0); 799e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 800e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 801e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 802e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 803e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_PLAY_ITEM: 804e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah { 805e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = msg.getData(); 806e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] bdaddr = data.getByteArray("BdAddress"); 807e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] uid = data.getByteArray("uid"); 808e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte scope = data.getByte("scope"); 80989728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen if (DEBUG) 81089728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen Log.v(TAG, "MSG_NATIVE_REQ_PLAY_ITEM scope=" + scope + " id=" 81189728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen + Utils.byteArrayToString(uid)); 812e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handlePlayItemResponse(bdaddr, uid, scope); 813e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 814e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 815e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 816e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_GET_TOTAL_NUM_OF_ITEMS: 817294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_GET_TOTAL_NUM_OF_ITEMS scope=" + msg.arg1); 818e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // argument 1 is scope, object is bdaddr 819e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handleGetTotalNumOfItemsResponse((byte[]) msg.obj, (byte) msg.arg1); 820e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 821e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 822e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case MSG_NATIVE_REQ_PASS_THROUGH: 823294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen if (DEBUG) 82405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.v(TAG, "MSG_NATIVE_REQ_PASS_THROUGH: id=" + msg.arg1 + " st=" + msg.arg2); 82505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen // argument 1 is id, argument 2 is keyState 82605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen handlePassthroughCmd(msg.arg1, msg.arg2); 827e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 828e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 829e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah default: 830e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "unknown message! msg.what=" + msg.what); 831e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 832c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 833c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 834c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 835c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 83659b1c77f883bd97816332046a3a98be4431cceddMarie Janssen private PlaybackState updatePlaybackState() { 83759b1c77f883bd97816332046a3a98be4431cceddMarie Janssen PlaybackState newState = new PlaybackState.Builder() 83859b1c77f883bd97816332046a3a98be4431cceddMarie Janssen .setState(PlaybackState.STATE_NONE, 83959b1c77f883bd97816332046a3a98be4431cceddMarie Janssen PlaybackState.PLAYBACK_POSITION_UNKNOWN, 0.0f) 84059b1c77f883bd97816332046a3a98be4431cceddMarie Janssen .build(); 84159b1c77f883bd97816332046a3a98be4431cceddMarie Janssen synchronized (this) { 84259b1c77f883bd97816332046a3a98be4431cceddMarie Janssen PlaybackState controllerState = null; 84359b1c77f883bd97816332046a3a98be4431cceddMarie Janssen if (mMediaController != null) { 84459b1c77f883bd97816332046a3a98be4431cceddMarie Janssen controllerState = mMediaController.getPlaybackState(); 84559b1c77f883bd97816332046a3a98be4431cceddMarie Janssen } 84659b1c77f883bd97816332046a3a98be4431cceddMarie Janssen 84759b1c77f883bd97816332046a3a98be4431cceddMarie Janssen if (controllerState != null) { 84859b1c77f883bd97816332046a3a98be4431cceddMarie Janssen newState = controllerState; 849a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov } 850a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov // Use the AudioManager to update the playback state. 851a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov // NOTE: We cannot use the 852a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov // (mA2dpState == BluetoothA2dp.STATE_PLAYING) 853a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov // check, because after Pause, the A2DP state remains in 854a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov // STATE_PLAYING for 3 more seconds. 855a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov // As a result of that, if we pause the music, on carkits the 856a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov // Play status indicator will continue to display "Playing" 857a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov // for 3 more seconds which can be confusing. 858a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov if (mAudioManagerIsPlaying 859a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov || (controllerState == null && mAudioManager != null 860a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov && mAudioManager.isMusicActive())) { 861a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov // Use AudioManager playback state if we don't have the state 862a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov // from MediaControlller 86359b1c77f883bd97816332046a3a98be4431cceddMarie Janssen PlaybackState.Builder builder = new PlaybackState.Builder(); 864a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov if (mAudioManagerIsPlaying) { 86559b1c77f883bd97816332046a3a98be4431cceddMarie Janssen builder.setState(PlaybackState.STATE_PLAYING, 86659b1c77f883bd97816332046a3a98be4431cceddMarie Janssen PlaybackState.PLAYBACK_POSITION_UNKNOWN, 1.0f); 86759b1c77f883bd97816332046a3a98be4431cceddMarie Janssen } else { 86859b1c77f883bd97816332046a3a98be4431cceddMarie Janssen builder.setState(PlaybackState.STATE_PAUSED, 86959b1c77f883bd97816332046a3a98be4431cceddMarie Janssen PlaybackState.PLAYBACK_POSITION_UNKNOWN, 0.0f); 87059b1c77f883bd97816332046a3a98be4431cceddMarie Janssen } 87159b1c77f883bd97816332046a3a98be4431cceddMarie Janssen newState = builder.build(); 87259b1c77f883bd97816332046a3a98be4431cceddMarie Janssen } 8730e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen } 874f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 87559b1c77f883bd97816332046a3a98be4431cceddMarie Janssen byte newPlayStatus = getBluetoothPlayState(newState); 8760a429916782c20980e7f0893c503c633b8341f88Marie Janssen 87759b1c77f883bd97816332046a3a98be4431cceddMarie Janssen /* update play status in global media player list */ 8780a429916782c20980e7f0893c503c633b8341f88Marie Janssen MediaPlayerInfo player = getAddressedPlayerInfo(); 8790a429916782c20980e7f0893c503c633b8341f88Marie Janssen if (player != null) { 88059b1c77f883bd97816332046a3a98be4431cceddMarie Janssen player.setPlayStatus(newPlayStatus); 8810a429916782c20980e7f0893c503c633b8341f88Marie Janssen } 8820a429916782c20980e7f0893c503c633b8341f88Marie Janssen 883fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen if (DEBUG) { 88459b1c77f883bd97816332046a3a98be4431cceddMarie Janssen Log.v(TAG, "updatePlaybackState (" + mPlayStatusChangedNT + "): " + mReportedPlayStatus 88559b1c77f883bd97816332046a3a98be4431cceddMarie Janssen + "➡" + newPlayStatus + "(" + newState + ")"); 886fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen } 887fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen 88859b1c77f883bd97816332046a3a98be4431cceddMarie Janssen if (newState != null) mCurrentPlayState = newState; 889aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 89059b1c77f883bd97816332046a3a98be4431cceddMarie Janssen return mCurrentPlayState; 89159b1c77f883bd97816332046a3a98be4431cceddMarie Janssen } 89259b1c77f883bd97816332046a3a98be4431cceddMarie Janssen 89359b1c77f883bd97816332046a3a98be4431cceddMarie Janssen private void sendPlaybackStatus(int playStatusChangedNT, byte playbackState) { 89459b1c77f883bd97816332046a3a98be4431cceddMarie Janssen registerNotificationRspPlayStatusNative(playStatusChangedNT, playbackState); 89559b1c77f883bd97816332046a3a98be4431cceddMarie Janssen mPlayStatusChangedNT = playStatusChangedNT; 89659b1c77f883bd97816332046a3a98be4431cceddMarie Janssen mReportedPlayStatus = playbackState; 897c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 898c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 899c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private void updateTransportControls(int transportControlFlags) { 900c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mTransportControlFlags = transportControlFlags; 901c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 902c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 9033b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen class MediaAttributes { 9043b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private boolean exists; 9053b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String title; 9063b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String artistName; 9073b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String albumName; 9083b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String mediaNumber; 9093b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String mediaTotalNumber; 9103b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String genre; 9110a429916782c20980e7f0893c503c633b8341f88Marie Janssen private long playingTimeMs; 9123b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9133b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_TITLE = 1; 9143b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_ARTIST_NAME = 2; 9153b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_ALBUM_NAME = 3; 9163b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_MEDIA_NUMBER = 4; 9173b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_MEDIA_TOTAL_NUMBER = 5; 9183b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_GENRE = 6; 9193b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private static final int ATTR_PLAYING_TIME_MS = 7; 9203b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9213b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9223b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen public MediaAttributes(MediaMetadata data) { 9233b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen exists = data != null; 9243b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (!exists) 9253b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return; 9263b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9273b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen artistName = stringOrBlank(data.getString(MediaMetadata.METADATA_KEY_ARTIST)); 9283b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen albumName = stringOrBlank(data.getString(MediaMetadata.METADATA_KEY_ALBUM)); 9293b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen mediaNumber = longStringOrBlank(data.getLong(MediaMetadata.METADATA_KEY_TRACK_NUMBER)); 9303b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen mediaTotalNumber = longStringOrBlank(data.getLong(MediaMetadata.METADATA_KEY_NUM_TRACKS)); 9313b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen genre = stringOrBlank(data.getString(MediaMetadata.METADATA_KEY_GENRE)); 9320a429916782c20980e7f0893c503c633b8341f88Marie Janssen playingTimeMs = data.getLong(MediaMetadata.METADATA_KEY_DURATION); 9333b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9343b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen // Try harder for the title. 9353b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen title = data.getString(MediaMetadata.METADATA_KEY_TITLE); 9363b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9373b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (title == null) { 9383b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen MediaDescription desc = data.getDescription(); 9393b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (desc != null) { 9403b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen CharSequence val = desc.getDescription(); 9413b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (val != null) 9423b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen title = val.toString(); 9433b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 9443b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 9453b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9463b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (title == null) 9473b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen title = new String(); 9483b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 9493b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9500a429916782c20980e7f0893c503c633b8341f88Marie Janssen public long getLength() { 9510a429916782c20980e7f0893c503c633b8341f88Marie Janssen if (!exists) return 0L; 9520a429916782c20980e7f0893c503c633b8341f88Marie Janssen return playingTimeMs; 9530a429916782c20980e7f0893c503c633b8341f88Marie Janssen } 9540a429916782c20980e7f0893c503c633b8341f88Marie Janssen 9553b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen public boolean equals(MediaAttributes other) { 9563b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (other == null) 9573b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return false; 9583b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9593b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (exists != other.exists) 9603b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return false; 9613b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9623b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (exists == false) 9633b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return true; 9643b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9650a429916782c20980e7f0893c503c633b8341f88Marie Janssen return (title.equals(other.title)) && (artistName.equals(other.artistName)) 9660a429916782c20980e7f0893c503c633b8341f88Marie Janssen && (albumName.equals(other.albumName)) 9670a429916782c20980e7f0893c503c633b8341f88Marie Janssen && (mediaNumber.equals(other.mediaNumber)) 9680a429916782c20980e7f0893c503c633b8341f88Marie Janssen && (mediaTotalNumber.equals(other.mediaTotalNumber)) 9690a429916782c20980e7f0893c503c633b8341f88Marie Janssen && (genre.equals(other.genre)) && (playingTimeMs == other.playingTimeMs); 9703b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 9713b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9723b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen public String getString(int attrId) { 9733b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen if (!exists) 9743b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return new String(); 9753b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9763b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen switch (attrId) { 9773b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_TITLE: 9783b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return title; 9793b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_ARTIST_NAME: 9803b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return artistName; 9813b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_ALBUM_NAME: 9823b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return albumName; 9833b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_MEDIA_NUMBER: 9843b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return mediaNumber; 9853b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_MEDIA_TOTAL_NUMBER: 9863b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return mediaTotalNumber; 9873b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_GENRE: 9883b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return genre; 9893b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen case ATTR_PLAYING_TIME_MS: 9900a429916782c20980e7f0893c503c633b8341f88Marie Janssen return Long.toString(playingTimeMs); 9913b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen default: 9923b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return new String(); 9933b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 9943b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 9953b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 9963b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String stringOrBlank(String s) { 9973b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return s == null ? new String() : s; 9983b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen } 999c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 10003b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen private String longStringOrBlank(Long s) { 10013b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return s == null ? new String() : s.toString(); 1002c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1003c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1004c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public String toString() { 1005e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!exists) { 10063b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen return "[MediaAttributes: none]"; 1007e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 10083b9b0ca02d74a95c3f1f5b0d7bc58a8a1f9c44dfMarie Janssen 10090a429916782c20980e7f0893c503c633b8341f88Marie Janssen return "[MediaAttributes: " + title + " - " + albumName + " by " + artistName + " (" 10100a429916782c20980e7f0893c503c633b8341f88Marie Janssen + playingTimeMs + " " + mediaNumber + "/" + mediaTotalNumber + ") " + genre 10110a429916782c20980e7f0893c503c633b8341f88Marie Janssen + "]"; 1012c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1013cc07ee436d00418ecc69ae3aace986f7fbf0823aMarie Janssen 1014cc07ee436d00418ecc69ae3aace986f7fbf0823aMarie Janssen public String toRedactedString() { 1015cc07ee436d00418ecc69ae3aace986f7fbf0823aMarie Janssen if (!exists) { 1016cc07ee436d00418ecc69ae3aace986f7fbf0823aMarie Janssen return "[MediaAttributes: none]"; 1017cc07ee436d00418ecc69ae3aace986f7fbf0823aMarie Janssen } 1018cc07ee436d00418ecc69ae3aace986f7fbf0823aMarie Janssen 1019cc07ee436d00418ecc69ae3aace986f7fbf0823aMarie Janssen return "[MediaAttributes: " + Utils.ellipsize(title) + " - " 1020cc07ee436d00418ecc69ae3aace986f7fbf0823aMarie Janssen + Utils.ellipsize(albumName) + " by " + Utils.ellipsize(artistName) + " (" 1021cc07ee436d00418ecc69ae3aace986f7fbf0823aMarie Janssen + playingTimeMs + " " + mediaNumber + "/" + mediaTotalNumber + ") " + genre 1022cc07ee436d00418ecc69ae3aace986f7fbf0823aMarie Janssen + "]"; 1023cc07ee436d00418ecc69ae3aace986f7fbf0823aMarie Janssen } 1024c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1025c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 102685aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker private void updateCurrentMediaState() { 1027f2f6a4ea02e9456f71ea0490112845110ca5d975Marie Janssen // Only do player updates when we aren't registering for track changes. 10285aca05c1d79f3412b6964b3b6335ad6f2d558756Marie Janssen MediaAttributes currentAttributes; 102959b1c77f883bd97816332046a3a98be4431cceddMarie Janssen PlaybackState newState = updatePlaybackState(); 103059b1c77f883bd97816332046a3a98be4431cceddMarie Janssen 1031ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen synchronized (this) { 1032ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen if (mMediaController == null) { 10335aca05c1d79f3412b6964b3b6335ad6f2d558756Marie Janssen currentAttributes = new MediaAttributes(null); 1034c9f4e0d24e39b372452fa809b12f9c588b29abd9Marie Janssen } else { 10355aca05c1d79f3412b6964b3b6335ad6f2d558756Marie Janssen currentAttributes = new MediaAttributes(mMediaController.getMetadata()); 10360a429916782c20980e7f0893c503c633b8341f88Marie Janssen } 10370e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen } 1038e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1039cb00f2feb8405508707e41e463a79bf77eac7bc7Ajay Panicker byte newPlayStatus = getBluetoothPlayState(newState); 1040cb00f2feb8405508707e41e463a79bf77eac7bc7Ajay Panicker 1041cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker if (newState.getState() != PlaybackState.STATE_BUFFERING 1042cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker && newState.getState() != PlaybackState.STATE_NONE) { 1043cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker long newQueueId = MediaSession.QueueItem.UNKNOWN_ID; 1044cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker if (newState != null) newQueueId = newState.getActiveQueueItemId(); 1045cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker Log.v(TAG, "Media update: id " + mLastQueueId + "➡" + newQueueId + "? " 1046cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker + currentAttributes.toRedactedString() + " : " 1047cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker + mMediaAttributes.toRedactedString()); 1048cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker 104985aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker if (mAvailablePlayerViewChanged) { 105085aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker registerNotificationRspAvalPlayerChangedNative( 105185aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker AvrcpConstants.NOTIFICATION_TYPE_CHANGED); 105285aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker mAvailablePlayerViewChanged = false; 105385aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker return; 105485aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker } 105585aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker 105685aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker if (mAddrPlayerChangedNT == AvrcpConstants.NOTIFICATION_TYPE_INTERIM 105785aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker && mReportedPlayerID != mCurrAddrPlayerID) { 105885aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker registerNotificationRspAvalPlayerChangedNative( 105985aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker AvrcpConstants.NOTIFICATION_TYPE_CHANGED); 106085aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker registerNotificationRspAddrPlayerChangedNative( 106185aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker AvrcpConstants.NOTIFICATION_TYPE_CHANGED, mCurrAddrPlayerID, sUIDCounter); 106285aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker 106385aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker mAvailablePlayerViewChanged = false; 106485aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker mAddrPlayerChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 106585aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker mReportedPlayerID = mCurrAddrPlayerID; 106685aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker 106785aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker // Update the now playing list without sending the notification 106885aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker mNowPlayingListChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 106985aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker mAddressedMediaPlayer.updateNowPlayingList(mMediaController); 107085aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker mNowPlayingListChangedNT = AvrcpConstants.NOTIFICATION_TYPE_INTERIM; 107185aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker } 107285aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker 1073cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker // Dont send now playing list changed if the player doesn't support browsing 1074cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker MediaPlayerInfo info = getAddressedPlayerInfo(); 1075cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker if (info != null && info.isBrowseSupported()) { 1076cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker Log.v(TAG, "Check if NowPlayingList is updated"); 1077cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker mAddressedMediaPlayer.updateNowPlayingList(mMediaController); 1078cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker } 1079cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker 1080cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker // Notify track changed if: 108185aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker // - The CT is registered for the notification 1082cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker // - Queue ID is UNKNOWN and MediaMetadata is different 108385aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker // - Queue ID is valid and different from last Queue ID sent 108485aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker if ((newQueueId == -1 || newQueueId != mLastQueueId) 108585aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker && mTrackChangedNT == AvrcpConstants.NOTIFICATION_TYPE_INTERIM 108685aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker && !currentAttributes.equals(mMediaAttributes) 108785aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker && newPlayStatus == PLAYSTATUS_PLAYING) { 1088cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker Log.v(TAG, "Send track changed"); 1089cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker mMediaAttributes = currentAttributes; 1090cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker mLastQueueId = newQueueId; 109185aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker sendTrackChangedRsp(false); 1092cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker } 1093cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker } else { 1094cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker Log.i(TAG, "Skipping update due to invalid playback state"); 1095c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1096cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker 1097cb00f2feb8405508707e41e463a79bf77eac7bc7Ajay Panicker // still send the updated play state if the playback state is none or buffering 1098a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov Log.e(TAG, 1099a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov "play status change " + mReportedPlayStatus + "➡" + newPlayStatus 1100a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov + " mPlayStatusChangedNT: " + mPlayStatusChangedNT); 1101cb00f2feb8405508707e41e463a79bf77eac7bc7Ajay Panicker if (mPlayStatusChangedNT == AvrcpConstants.NOTIFICATION_TYPE_INTERIM 1102a24231afabc31d1e7c903441108e19931d52a599Pavlin Radoslavov || (mReportedPlayStatus != newPlayStatus)) { 1103cb00f2feb8405508707e41e463a79bf77eac7bc7Ajay Panicker sendPlaybackStatus(AvrcpConstants.NOTIFICATION_TYPE_CHANGED, newPlayStatus); 1104cb00f2feb8405508707e41e463a79bf77eac7bc7Ajay Panicker } 1105cb00f2feb8405508707e41e463a79bf77eac7bc7Ajay Panicker 110659b1c77f883bd97816332046a3a98be4431cceddMarie Janssen sendPlayPosNotificationRsp(false); 1107c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1108c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1109e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void getRcFeaturesRequestFromNative(byte[] address, int features) { 1110e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_RC_FEATURES, features, 0, 1111e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Utils.getAddressStringFromByte(address)); 111217675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 111317675906064bb72fdcca75baa56cdf8bb8968d01John Du } 111417675906064bb72fdcca75baa56cdf8bb8968d01John Du 1115e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void getPlayStatusRequestFromNative(byte[] address) { 1116e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_PLAY_STATUS); 1117e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = address; 1118c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.sendMessage(msg); 1119c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1120c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 112189728a4d50001ac76d05efa1c916711ef9f9c2b4Marie Janssen private void getElementAttrRequestFromNative(byte[] address, byte numAttr, int[] attrs) { 1122e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd avrcpCmdobj = new AvrcpCmd(); 1123e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd.ElementAttrCmd elemAttr = avrcpCmdobj.new ElementAttrCmd(address, numAttr, attrs); 1124e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_ELEM_ATTRS); 1125e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = elemAttr; 1126c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.sendMessage(msg); 1127c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1128c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1129e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void registerNotificationRequestFromNative(byte[] address,int eventId, int param) { 1130e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_REGISTER_NOTIFICATION, eventId, param); 1131e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = address; 1132c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.sendMessage(msg); 1133c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1134c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1135e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void processRegisterNotification(byte[] address, int eventId, int param) { 1136c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu switch (eventId) { 1137c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case EVT_PLAY_STATUS_CHANGED: 113859b1c77f883bd97816332046a3a98be4431cceddMarie Janssen mPlayStatusChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 113959b1c77f883bd97816332046a3a98be4431cceddMarie Janssen updatePlaybackState(); 1140cb00f2feb8405508707e41e463a79bf77eac7bc7Ajay Panicker sendPlaybackStatus(AvrcpConstants.NOTIFICATION_TYPE_INTERIM, mReportedPlayStatus); 1141c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 1142c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1143c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case EVT_TRACK_CHANGED: 11440e949676c5097e1f259caa2e549ecedf0c09269dMarie Janssen Log.v(TAG, "Track changed notification enabled"); 1145e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_INTERIM; 1146cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker sendTrackChangedRsp(true); 1147c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 1148c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1149aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu case EVT_PLAY_POS_CHANGED: 1150e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPlayPosChangedNT = AvrcpConstants.NOTIFICATION_TYPE_INTERIM; 1151e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mPlaybackIntervalMs = (long) param * 1000L; 1152fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen sendPlayPosNotificationRsp(true); 1153aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu break; 1154aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 1155e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case EVT_AVBL_PLAYERS_CHANGED: 1156e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Notify remote available players changed */ 11575aca05c1d79f3412b6964b3b6335ad6f2d558756Marie Janssen if (DEBUG) Log.d(TAG, "Available Players notification enabled"); 1158e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah registerNotificationRspAvalPlayerChangedNative( 1159e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpConstants.NOTIFICATION_TYPE_INTERIM); 1160e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 1161e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1162e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case EVT_ADDR_PLAYER_CHANGED: 1163e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Notify remote addressed players changed */ 11645aca05c1d79f3412b6964b3b6335ad6f2d558756Marie Janssen if (DEBUG) Log.d(TAG, "Addressed Player notification enabled"); 1165e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah registerNotificationRspAddrPlayerChangedNative( 1166e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpConstants.NOTIFICATION_TYPE_INTERIM, 1167e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mCurrAddrPlayerID, sUIDCounter); 116859b1c77f883bd97816332046a3a98be4431cceddMarie Janssen mAddrPlayerChangedNT = AvrcpConstants.NOTIFICATION_TYPE_INTERIM; 116959b1c77f883bd97816332046a3a98be4431cceddMarie Janssen mReportedPlayerID = mCurrAddrPlayerID; 1170e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 1171e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1172e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case EVENT_UIDS_CHANGED: 11735aca05c1d79f3412b6964b3b6335ad6f2d558756Marie Janssen if (DEBUG) Log.d(TAG, "UIDs changed notification enabled"); 1174e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah registerNotificationRspUIDsChangedNative( 1175e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpConstants.NOTIFICATION_TYPE_INTERIM, sUIDCounter); 1176e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 1177e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1178e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case EVENT_NOW_PLAYING_CONTENT_CHANGED: 11795aca05c1d79f3412b6964b3b6335ad6f2d558756Marie Janssen if (DEBUG) Log.d(TAG, "Now Playing List changed notification enabled"); 1180e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* send interim response to remote device */ 118105723ee9e6619814876a6cce5004d11b38c3f648Ajay Panicker mNowPlayingListChangedNT = AvrcpConstants.NOTIFICATION_TYPE_INTERIM; 1182e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspNowPlayingChangedNative( 1183e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpConstants.NOTIFICATION_TYPE_INTERIM)) { 1184e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "EVENT_NOW_PLAYING_CONTENT_CHANGED: " + 1185e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah "registerNotificationRspNowPlayingChangedNative for Interim rsp failed!"); 1186e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1187e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah break; 1188c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1189c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1190c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1191e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handlePassthroughCmdRequestFromNative(byte[] address, int id, int keyState) { 119205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_PASS_THROUGH, id, keyState); 1193e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1194ace834feb02adabd61f628c4471147aea02d939cJohn Du } 1195ace834feb02adabd61f628c4471147aea02d939cJohn Du 11965aca05c1d79f3412b6964b3b6335ad6f2d558756Marie Janssen private void sendTrackChangedRsp(boolean registering) { 11975aca05c1d79f3412b6964b3b6335ad6f2d558756Marie Janssen if (!registering && mTrackChangedNT != AvrcpConstants.NOTIFICATION_TYPE_INTERIM) { 11985aca05c1d79f3412b6964b3b6335ad6f2d558756Marie Janssen if (DEBUG) Log.d(TAG, "sendTrackChangedRsp: Not registered or registering."); 11998ac88214fdbf5e5197033b89ba82a6bf728706a4Marie Janssen return; 12008ac88214fdbf5e5197033b89ba82a6bf728706a4Marie Janssen } 12015aca05c1d79f3412b6964b3b6335ad6f2d558756Marie Janssen 12025aca05c1d79f3412b6964b3b6335ad6f2d558756Marie Janssen mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 12035aca05c1d79f3412b6964b3b6335ad6f2d558756Marie Janssen if (registering) mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_INTERIM; 12045aca05c1d79f3412b6964b3b6335ad6f2d558756Marie Janssen 12055aca05c1d79f3412b6964b3b6335ad6f2d558756Marie Janssen MediaPlayerInfo info = getAddressedPlayerInfo(); 12065aca05c1d79f3412b6964b3b6335ad6f2d558756Marie Janssen // for non-browsable players or no player 1207eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen if (info != null && !info.isBrowseSupported()) { 12085aca05c1d79f3412b6964b3b6335ad6f2d558756Marie Janssen byte[] track = AvrcpConstants.TRACK_IS_SELECTED; 12095aca05c1d79f3412b6964b3b6335ad6f2d558756Marie Janssen if (!mMediaAttributes.exists) track = AvrcpConstants.NO_TRACK_SELECTED; 12105aca05c1d79f3412b6964b3b6335ad6f2d558756Marie Janssen registerNotificationRspTrackChangeNative(mTrackChangedNT, track); 12115aca05c1d79f3412b6964b3b6335ad6f2d558756Marie Janssen return; 1212e8e870c24930f9b687572dbb80614e5aad6fbdfaberyl hou } 1213e8e870c24930f9b687572dbb80614e5aad6fbdfaberyl hou 12145aca05c1d79f3412b6964b3b6335ad6f2d558756Marie Janssen mAddressedMediaPlayer.sendTrackChangeWithId(mTrackChangedNT, mMediaController); 1215c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1216c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1217aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long getPlayPosition() { 1218e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mCurrentPlayState == null) { 1219f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen return -1L; 1220e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1221f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 1222e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mCurrentPlayState.getPosition() == PlaybackState.PLAYBACK_POSITION_UNKNOWN) { 1223f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen return -1L; 1224e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1225f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 1226f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen if (isPlayingState(mCurrentPlayState)) { 12270a429916782c20980e7f0893c503c633b8341f88Marie Janssen long sinceUpdate = 12280a429916782c20980e7f0893c503c633b8341f88Marie Janssen (SystemClock.elapsedRealtime() - mCurrentPlayState.getLastPositionUpdateTime()); 12290a429916782c20980e7f0893c503c633b8341f88Marie Janssen return sinceUpdate + mCurrentPlayState.getPosition(); 1230aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 1231f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 12323635a926bd7316a55b288a54d409a1070a9c19e8Marie Janssen return mCurrentPlayState.getPosition(); 1233aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 1234aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 123559b1c77f883bd97816332046a3a98be4431cceddMarie Janssen private boolean isPlayingState(@Nullable PlaybackState state) { 123659b1c77f883bd97816332046a3a98be4431cceddMarie Janssen if (state == null) return false; 1237cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker return (state != null) && (state.getState() == PlaybackState.STATE_PLAYING); 1238188f205b5f093850d4cc627917a21204be36c56aZhihai Xu } 1239188f205b5f093850d4cc627917a21204be36c56aZhihai Xu 124017675906064bb72fdcca75baa56cdf8bb8968d01John Du /** 1241f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen * Sends a play position notification, or schedules one to be 1242f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen * sent later at an appropriate time. If |requested| is true, 1243f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen * does both because this was called in reponse to a request from the 1244f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen * TG. 1245f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen */ 1246f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen private void sendPlayPosNotificationRsp(boolean requested) { 1247e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!requested && mPlayPosChangedNT != AvrcpConstants.NOTIFICATION_TYPE_INTERIM) { 1248fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen if (DEBUG) Log.d(TAG, "sendPlayPosNotificationRsp: Not registered or requesting."); 1249fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen return; 1250fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen } 1251fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen 1252f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen long playPositionMs = getPlayPosition(); 12530ace2d5941549e466ada4258c6c6fbb1debdf48dMarie Janssen String debugLine = "sendPlayPosNotificationRsp: "; 1254f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 1255f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen // mNextPosMs is set to -1 when the previous position was invalid 1256f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen // so this will be true if the new position is valid & old was invalid. 1257f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen // mPlayPositionMs is set to -1 when the new position is invalid, 1258f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen // and the old mPrevPosMs is >= 0 so this is true when the new is invalid 1259f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen // and the old was valid. 12600ace2d5941549e466ada4258c6c6fbb1debdf48dMarie Janssen if (DEBUG) { 12610ace2d5941549e466ada4258c6c6fbb1debdf48dMarie Janssen debugLine += "(" + requested + ") " + mPrevPosMs + " <=? " + playPositionMs + " <=? " 12620ace2d5941549e466ada4258c6c6fbb1debdf48dMarie Janssen + mNextPosMs; 12630ace2d5941549e466ada4258c6c6fbb1debdf48dMarie Janssen if (isPlayingState(mCurrentPlayState)) debugLine += " Playing"; 12640ace2d5941549e466ada4258c6c6fbb1debdf48dMarie Janssen debugLine += " State: " + mCurrentPlayState.getState(); 12650ace2d5941549e466ada4258c6c6fbb1debdf48dMarie Janssen } 1266fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen if (requested || ((mLastReportedPosition != playPositionMs) && 1267e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah (playPositionMs >= mNextPosMs) || (playPositionMs <= mPrevPosMs))) { 1268e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!requested) mPlayPosChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 1269e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah registerNotificationRspPlayPosNative(mPlayPosChangedNT, (int) playPositionMs); 1270fa81085f6cda571d56c62eb1d646ae4a52cb90eeMarie Janssen mLastReportedPosition = playPositionMs; 1271f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen if (playPositionMs != PlaybackState.PLAYBACK_POSITION_UNKNOWN) { 1272f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen mNextPosMs = playPositionMs + mPlaybackIntervalMs; 1273f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen mPrevPosMs = playPositionMs - mPlaybackIntervalMs; 1274f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } else { 1275f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen mNextPosMs = -1; 1276f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen mPrevPosMs = -1; 1277f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } 1278f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } 1279f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 1280e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.removeMessages(MSG_PLAY_INTERVAL_TIMEOUT); 1281e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mPlayPosChangedNT == AvrcpConstants.NOTIFICATION_TYPE_INTERIM && isPlayingState(mCurrentPlayState)) { 1282e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_PLAY_INTERVAL_TIMEOUT); 1283f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen long delay = mPlaybackIntervalMs; 1284f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen if (mNextPosMs != -1) { 1285f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen delay = mNextPosMs - (playPositionMs > 0 ? playPositionMs : 0); 1286f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } 12870ace2d5941549e466ada4258c6c6fbb1debdf48dMarie Janssen if (DEBUG) debugLine += " Timeout " + delay + "ms"; 1288f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen mHandler.sendMessageDelayed(msg, delay); 1289f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } 12900ace2d5941549e466ada4258c6c6fbb1debdf48dMarie Janssen if (DEBUG) Log.d(TAG, debugLine); 1291f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen } 1292f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen 1293f7942360dd9d807bea087c4ef42773f5e800c0c4Marie Janssen /** 129417675906064bb72fdcca75baa56cdf8bb8968d01John Du * This is called from AudioService. It will return whether this device supports abs volume. 129517675906064bb72fdcca75baa56cdf8bb8968d01John Du * NOT USED AT THE MOMENT. 129617675906064bb72fdcca75baa56cdf8bb8968d01John Du */ 129717675906064bb72fdcca75baa56cdf8bb8968d01John Du public boolean isAbsoluteVolumeSupported() { 129817675906064bb72fdcca75baa56cdf8bb8968d01John Du return ((mFeatures & BTRC_FEAT_ABSOLUTE_VOLUME) != 0); 129917675906064bb72fdcca75baa56cdf8bb8968d01John Du } 130017675906064bb72fdcca75baa56cdf8bb8968d01John Du 130117675906064bb72fdcca75baa56cdf8bb8968d01John Du /** 130217675906064bb72fdcca75baa56cdf8bb8968d01John Du * We get this call from AudioService. This will send a message to our handler object, 130317675906064bb72fdcca75baa56cdf8bb8968d01John Du * requesting our handler to call setVolumeNative() 130417675906064bb72fdcca75baa56cdf8bb8968d01John Du */ 130517675906064bb72fdcca75baa56cdf8bb8968d01John Du public void adjustVolume(int direction) { 1306e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_ADJUST_VOLUME, direction, 0); 130717675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 130817675906064bb72fdcca75baa56cdf8bb8968d01John Du } 130917675906064bb72fdcca75baa56cdf8bb8968d01John Du 131017675906064bb72fdcca75baa56cdf8bb8968d01John Du public void setAbsoluteVolume(int volume) { 131111798b011c962b602217b479130d413f3b30f19aLiejun Tao if (volume == mLocalVolume) { 131211798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.v(TAG, "setAbsoluteVolume is setting same index, ignore "+volume); 131311798b011c962b602217b479130d413f3b30f19aLiejun Tao return; 131411798b011c962b602217b479130d413f3b30f19aLiejun Tao } 131511798b011c962b602217b479130d413f3b30f19aLiejun Tao 1316e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.removeMessages(MSG_ADJUST_VOLUME); 1317e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_SET_ABSOLUTE_VOLUME, volume, 0); 131817675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 13195c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta } 13205c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta 132117675906064bb72fdcca75baa56cdf8bb8968d01John Du /* Called in the native layer as a btrc_callback to return the volume set on the carkit in the 132217675906064bb72fdcca75baa56cdf8bb8968d01John Du * case when the volume is change locally on the carkit. This notification is not called when 132317675906064bb72fdcca75baa56cdf8bb8968d01John Du * the volume is changed from the phone. 132417675906064bb72fdcca75baa56cdf8bb8968d01John Du * 132517675906064bb72fdcca75baa56cdf8bb8968d01John Du * This method will send a message to our handler to change the local stored volume and notify 132617675906064bb72fdcca75baa56cdf8bb8968d01John Du * AudioService to update the UI 132717675906064bb72fdcca75baa56cdf8bb8968d01John Du */ 1328e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void volumeChangeRequestFromNative(byte[] address, int volume, int ctype) { 1329e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_VOLUME_CHANGE, volume, ctype); 1330e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = new Bundle(); 1331e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByteArray("BdAddress" , address); 1332e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.setData(data); 1333e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1334e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1335e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 133619a05f008446506069b34265d57bcf421447e7e3Marie Janssen private void getFolderItemsRequestFromNative( 133719a05f008446506069b34265d57bcf421447e7e3Marie Janssen byte[] address, byte scope, long startItem, long endItem, byte numAttr, int[] attrIds) { 1338e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd avrcpCmdobj = new AvrcpCmd(); 1339e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd.FolderItemsCmd folderObj = avrcpCmdobj.new FolderItemsCmd(address, scope, 1340e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah startItem, endItem, numAttr, attrIds); 1341e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_FOLDER_ITEMS, 0, 0); 1342e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = folderObj; 1343e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1344e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1345e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1346e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void setAddressedPlayerRequestFromNative(byte[] address, int playerId) { 1347e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_SET_ADDR_PLAYER, playerId, 0); 1348e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = address; 1349e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1350e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1351e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1352e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void setBrowsedPlayerRequestFromNative(byte[] address, int playerId) { 1353e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_SET_BR_PLAYER, playerId, 0); 1354e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = address; 1355e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1356e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1357e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1358e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void changePathRequestFromNative(byte[] address, byte direction, byte[] folderUid) { 1359e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = new Bundle(); 1360e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_CHANGE_PATH); 1361e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByteArray("BdAddress" , address); 1362e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByteArray("folderUid" , folderUid); 1363e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByte("direction" , direction); 1364e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.setData(data); 1365e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1366e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1367e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1368e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void getItemAttrRequestFromNative(byte[] address, byte scope, byte[] itemUid, int uidCounter, 1369e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte numAttr, int[] attrs) { 1370e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd avrcpCmdobj = new AvrcpCmd(); 1371e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah AvrcpCmd.ItemAttrCmd itemAttr = avrcpCmdobj.new ItemAttrCmd(address, scope, 1372e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah itemUid, uidCounter, numAttr, attrs); 1373e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_ITEM_ATTR); 1374e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = itemAttr; 1375e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1376e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1377e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1378e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void searchRequestFromNative(byte[] address, int charsetId, byte[] searchStr) { 1379e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Search is not supported */ 1380e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen Log.w(TAG, "searchRequestFromNative: search is not supported"); 1381e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah searchRspNative(address, AvrcpConstants.RSP_SRCH_NOT_SPRTD, 0, 0); 1382e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1383e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1384e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void playItemRequestFromNative(byte[] address, byte scope, int uidCounter, byte[] uid) { 1385e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = new Bundle(); 1386e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_PLAY_ITEM); 1387e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByteArray("BdAddress" , address); 1388e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByteArray("uid" , uid); 1389e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putInt("uidCounter" , uidCounter); 1390e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data.putByte("scope" , scope); 1391e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.setData(data); 1392e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mHandler.sendMessage(msg); 1393e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1394e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1395e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void addToPlayListRequestFromNative(byte[] address, byte scope, byte[] uid, int uidCounter) { 1396e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* add to NowPlaying not supported */ 1397e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen Log.w(TAG, "addToPlayListRequestFromNative: not supported! scope=" + scope); 1398e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah addToNowPlayingRspNative(address, AvrcpConstants.RSP_INTERNAL_ERR); 1399e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1400e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1401e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void getTotalNumOfItemsRequestFromNative(byte[] address, byte scope) { 1402e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Bundle data = new Bundle(); 1403e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_NATIVE_REQ_GET_TOTAL_NUM_OF_ITEMS); 1404e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.arg1 = scope; 1405e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah msg.obj = address; 140617675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 140717675906064bb72fdcca75baa56cdf8bb8968d01John Du } 140817675906064bb72fdcca75baa56cdf8bb8968d01John Du 14092e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie private void notifyVolumeChanged(int volume) { 14102e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 14112e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_BLUETOOTH_ABS_VOLUME); 141217675906064bb72fdcca75baa56cdf8bb8968d01John Du } 141317675906064bb72fdcca75baa56cdf8bb8968d01John Du 141417675906064bb72fdcca75baa56cdf8bb8968d01John Du private int convertToAudioStreamVolume(int volume) { 141517675906064bb72fdcca75baa56cdf8bb8968d01John Du // Rescale volume to match AudioSystem's volume 141611798b011c962b602217b479130d413f3b30f19aLiejun Tao return (int) Math.floor((double) volume*mAudioStreamMax/AVRCP_MAX_VOL); 141717675906064bb72fdcca75baa56cdf8bb8968d01John Du } 141817675906064bb72fdcca75baa56cdf8bb8968d01John Du 141917675906064bb72fdcca75baa56cdf8bb8968d01John Du private int convertToAvrcpVolume(int volume) { 14202e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie return (int) Math.ceil((double) volume*AVRCP_MAX_VOL/mAudioStreamMax); 142117675906064bb72fdcca75baa56cdf8bb8968d01John Du } 142217675906064bb72fdcca75baa56cdf8bb8968d01John Du 142311798b011c962b602217b479130d413f3b30f19aLiejun Tao private void blackListCurrentDevice() { 142411798b011c962b602217b479130d413f3b30f19aLiejun Tao mFeatures &= ~BTRC_FEAT_ABSOLUTE_VOLUME; 142511798b011c962b602217b479130d413f3b30f19aLiejun Tao mAudioManager.avrcpSupportsAbsoluteVolume(mAddress, isAbsoluteVolumeSupported()); 142611798b011c962b602217b479130d413f3b30f19aLiejun Tao 142711798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences pref = mContext.getSharedPreferences(ABSOLUTE_VOLUME_BLACKLIST, 142811798b011c962b602217b479130d413f3b30f19aLiejun Tao Context.MODE_PRIVATE); 142911798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences.Editor editor = pref.edit(); 143011798b011c962b602217b479130d413f3b30f19aLiejun Tao editor.putBoolean(mAddress, true); 14317eeb95b6f29a6f55e117e329468168d4bcbec0c8Jack He editor.apply(); 143211798b011c962b602217b479130d413f3b30f19aLiejun Tao } 143311798b011c962b602217b479130d413f3b30f19aLiejun Tao 143411798b011c962b602217b479130d413f3b30f19aLiejun Tao private int modifyRcFeatureFromBlacklist(int feature, String address) { 143511798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences pref = mContext.getSharedPreferences(ABSOLUTE_VOLUME_BLACKLIST, 143611798b011c962b602217b479130d413f3b30f19aLiejun Tao Context.MODE_PRIVATE); 143711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (!pref.contains(address)) { 143811798b011c962b602217b479130d413f3b30f19aLiejun Tao return feature; 143911798b011c962b602217b479130d413f3b30f19aLiejun Tao } 144011798b011c962b602217b479130d413f3b30f19aLiejun Tao if (pref.getBoolean(address, false)) { 144111798b011c962b602217b479130d413f3b30f19aLiejun Tao feature &= ~BTRC_FEAT_ABSOLUTE_VOLUME; 144211798b011c962b602217b479130d413f3b30f19aLiejun Tao } 144311798b011c962b602217b479130d413f3b30f19aLiejun Tao return feature; 144411798b011c962b602217b479130d413f3b30f19aLiejun Tao } 144511798b011c962b602217b479130d413f3b30f19aLiejun Tao 144611798b011c962b602217b479130d413f3b30f19aLiejun Tao public void resetBlackList(String address) { 144711798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences pref = mContext.getSharedPreferences(ABSOLUTE_VOLUME_BLACKLIST, 144811798b011c962b602217b479130d413f3b30f19aLiejun Tao Context.MODE_PRIVATE); 144911798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences.Editor editor = pref.edit(); 145011798b011c962b602217b479130d413f3b30f19aLiejun Tao editor.remove(address); 14517eeb95b6f29a6f55e117e329468168d4bcbec0c8Jack He editor.apply(); 145211798b011c962b602217b479130d413f3b30f19aLiejun Tao } 145311798b011c962b602217b479130d413f3b30f19aLiejun Tao 1454188f205b5f093850d4cc627917a21204be36c56aZhihai Xu /** 1455188f205b5f093850d4cc627917a21204be36c56aZhihai Xu * This is called from A2dpStateMachine to set A2dp audio state. 1456188f205b5f093850d4cc627917a21204be36c56aZhihai Xu */ 1457188f205b5f093850d4cc627917a21204be36c56aZhihai Xu public void setA2dpAudioState(int state) { 1458e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Message msg = mHandler.obtainMessage(MSG_SET_A2DP_AUDIO_STATE, state, 0); 1459188f205b5f093850d4cc627917a21204be36c56aZhihai Xu mHandler.sendMessage(msg); 1460188f205b5f093850d4cc627917a21204be36c56aZhihai Xu } 1461188f205b5f093850d4cc627917a21204be36c56aZhihai Xu 14620427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker private class AvrcpServiceBootReceiver extends BroadcastReceiver { 14630427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker @Override 14640427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker public void onReceive(Context context, Intent intent) { 14650427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker String action = intent.getAction(); 14669c2ff5bb5082c653ee91d336dcd7f95e4c25e833Ajay Panicker if (action.equals(Intent.ACTION_USER_UNLOCKED)) { 14679c2ff5bb5082c653ee91d336dcd7f95e4c25e833Ajay Panicker if (DEBUG) Log.d(TAG, "User unlocked, initializing player lists"); 14680427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker /* initializing media player's list */ 1469754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker buildBrowsablePlayerList(); 14700427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker } 14710427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker } 14720427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker } 14730427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker 1474e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private class AvrcpServiceBroadcastReceiver extends BroadcastReceiver { 1475e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah @Override 1476e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void onReceive(Context context, Intent intent) { 1477e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String action = intent.getAction(); 1478e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "AvrcpServiceBroadcastReceiver-> Action: " + action); 1479e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1480e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (action.equals(Intent.ACTION_PACKAGE_REMOVED) 1481e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah || action.equals(Intent.ACTION_PACKAGE_DATA_CLEARED)) { 1482e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { 1483e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // a package is being removed, not replaced 1484e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String packageName = intent.getData().getSchemeSpecificPart(); 1485e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (packageName != null) { 1486e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handlePackageModified(packageName, true); 1487e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1488e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1489e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1490e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else if (action.equals(Intent.ACTION_PACKAGE_ADDED) 1491e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah || action.equals(Intent.ACTION_PACKAGE_CHANGED)) { 1492e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String packageName = intent.getData().getSchemeSpecificPart(); 1493e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG,"AvrcpServiceBroadcastReceiver-> packageName: " 1494e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + packageName); 1495e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (packageName != null) { 1496e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah handlePackageModified(packageName, false); 1497e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1498e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1499e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1500838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood } 1501838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood 1502e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handlePackageModified(String packageName, boolean removed) { 1503e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "packageName: " + packageName + " removed: " + removed); 1504c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1505e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (removed) { 1506384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen removeMediaPlayerInfo(packageName); 1507e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // old package is removed, updating local browsable player's list 1508e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (isBrowseSupported(packageName)) { 1509e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah removePackageFromBrowseList(packageName); 1510e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1511e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 1512e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // new package has been added. 1513e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (isBrowsableListUpdated(packageName)) { 1514e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // Rebuilding browsable players list 1515754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker buildBrowsablePlayerList(); 1516e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1517e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1518e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1519c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1520e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean isBrowsableListUpdated(String newPackageName) { 1521e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // getting the browsable media players list from package manager 1522e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Intent intent = new Intent("android.media.browse.MediaBrowserService"); 15230427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker List<ResolveInfo> resInfos = mPackageManager.queryIntentServices(intent, 15240427c02017744a749b99230b5bd080e2d4cfa3e1Ajay Panicker PackageManager.MATCH_ALL); 1525e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah for (ResolveInfo resolveInfo : resInfos) { 15263843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen if (resolveInfo.serviceInfo.packageName.equals(newPackageName)) { 15273843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen if (DEBUG) 15283843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen Log.d(TAG, 15293843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen "isBrowsableListUpdated: package includes MediaBrowserService, true"); 15303843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen return true; 15313843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen } 1532e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1533c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 15343843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen // if list has different size 15353843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen if (resInfos.size() != mBrowsePlayerInfoList.size()) { 15363843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen if (DEBUG) Log.d(TAG, "isBrowsableListUpdated: browsable list size mismatch, true"); 15373843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen return true; 1538e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 15393843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen 15403843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen Log.d(TAG, "isBrowsableListUpdated: false"); 15413843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen return false; 1542e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1543e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1544511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private void removePackageFromBrowseList(String packageName) { 1545e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "removePackageFromBrowseList: " + packageName); 1546511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mBrowsePlayerInfoList) { 1547511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int browseInfoID = getBrowseId(packageName); 1548511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (browseInfoID != -1) { 1549511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mBrowsePlayerInfoList.remove(browseInfoID); 1550511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1551e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1552e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1553e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1554e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* 1555e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * utility function to get the browse player index from global browsable 1556e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * list. It may return -1 if specified package name is not in the list. 1557e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 1558511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private int getBrowseId(String packageName) { 1559e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah boolean response = false; 1560e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int browseInfoID = 0; 1561511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mBrowsePlayerInfoList) { 1562511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (BrowsePlayerInfo info : mBrowsePlayerInfoList) { 1563511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (info.packageName.equals(packageName)) { 1564511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen response = true; 1565511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen break; 1566511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1567511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen browseInfoID++; 1568e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1569e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1570e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1571e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!response) { 1572e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah browseInfoID = -1; 1573e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1574e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1575e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "getBrowseId for packageName: " + packageName + 1576e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah " , browseInfoID: " + browseInfoID); 1577e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return browseInfoID; 1578e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1579e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1580e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void setAddressedPlayer(byte[] bdaddr, int selectedId) { 1581eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen String functionTag = "setAddressedPlayer(" + selectedId + "): "; 1582e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1583511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 1584511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (mMediaPlayerInfoList.isEmpty()) { 1585eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen Log.w(TAG, functionTag + "no players, send no available players"); 1586eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen setAddressedPlayerRspNative(bdaddr, AvrcpConstants.RSP_NO_AVBL_PLAY); 1587eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen return; 1588eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen } 1589eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen if (!mMediaPlayerInfoList.containsKey(selectedId)) { 1590eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen Log.w(TAG, functionTag + "invalid id, sending response back "); 1591eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen setAddressedPlayerRspNative(bdaddr, AvrcpConstants.RSP_INV_PLAYER); 1592eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen return; 1593eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen } 1594eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen 1595eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen if (isPlayerAlreadyAddressed(selectedId)) { 1596511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen MediaPlayerInfo info = getAddressedPlayerInfo(); 1597eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen Log.i(TAG, functionTag + "player already addressed: " + info); 1598eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen setAddressedPlayerRspNative(bdaddr, AvrcpConstants.RSP_NO_ERROR); 1599eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen return; 1600eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen } 1601eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen // register new Media Controller Callback and update the current IDs 1602eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen if (!updateCurrentController(selectedId, mCurrBrowsePlayerID)) { 1603eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen Log.e(TAG, functionTag + "updateCurrentController failed!"); 1604eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen setAddressedPlayerRspNative(bdaddr, AvrcpConstants.RSP_INTERNAL_ERR); 1605eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen return; 1606eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen } 1607eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen // If we don't have a controller, try to launch the player 1608eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen MediaPlayerInfo info = getAddressedPlayerInfo(); 1609eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen if (info.getMediaController() == null) { 1610eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen Intent launch = mPackageManager.getLaunchIntentForPackage(info.getPackageName()); 1611eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen Log.i(TAG, functionTag + "launching player " + launch); 1612eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen mContext.startActivity(launch); 1613e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1614e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1615eb3c55797d3ba16916327effa6b36acec5f1de36Marie Janssen setAddressedPlayerRspNative(bdaddr, AvrcpConstants.RSP_NO_ERROR); 1616e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1617e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1618e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void setBrowsedPlayer(byte[] bdaddr, int selectedId) { 1619e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int status = AvrcpConstants.RSP_NO_ERROR; 1620e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1621e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // checking for error cases 1622511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (mMediaPlayerInfoList.isEmpty()) { 1623e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah status = AvrcpConstants.RSP_NO_AVBL_PLAY; 1624819122df0eff426a43d175b14098339fa9f8f648Marie Janssen Log.w(TAG, "setBrowsedPlayer: No available players! "); 1625e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 1626819122df0eff426a43d175b14098339fa9f8f648Marie Janssen // Workaround for broken controllers selecting ID 0 1627819122df0eff426a43d175b14098339fa9f8f648Marie Janssen // Seen at least on Ford, Chevrolet MyLink 1628819122df0eff426a43d175b14098339fa9f8f648Marie Janssen if (selectedId == 0) { 1629819122df0eff426a43d175b14098339fa9f8f648Marie Janssen Log.w(TAG, "setBrowsedPlayer: workaround invalid id 0"); 1630819122df0eff426a43d175b14098339fa9f8f648Marie Janssen selectedId = mCurrAddrPlayerID; 1631819122df0eff426a43d175b14098339fa9f8f648Marie Janssen } 1632819122df0eff426a43d175b14098339fa9f8f648Marie Janssen 1633e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // update current browse player id and start browsing service 1634e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah updateNewIds(mCurrAddrPlayerID, selectedId); 1635e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String browsedPackage = getPackageName(selectedId); 1636e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1637e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!isPackageNameValid(browsedPackage)) { 1638e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, " Invalid package for id:" + mCurrBrowsePlayerID); 1639e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah status = AvrcpConstants.RSP_INV_PLAYER; 1640e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else if (!isBrowseSupported(browsedPackage)) { 1641e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, "Browse unsupported for id:" + mCurrBrowsePlayerID 1642e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + ", packagename : " + browsedPackage); 1643e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah status = AvrcpConstants.RSP_PLAY_NOT_BROW; 1644e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else if (!startBrowseService(bdaddr, browsedPackage)) { 1645e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "service cannot be started for browse player id:" + mCurrBrowsePlayerID 1646e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + ", packagename : " + browsedPackage); 1647e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah status = AvrcpConstants.RSP_INTERNAL_ERR; 1648e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1649e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1650e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1651e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (status != AvrcpConstants.RSP_NO_ERROR) { 1652e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah setBrowsedPlayerRspNative(bdaddr, status, (byte) 0x00, 0, null); 1653e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1654e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1655e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "setBrowsedPlayer for selectedId: " + selectedId + 1656e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah " , status: " + status); 1657e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1658e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 165905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private MediaSessionManager.OnActiveSessionsChangedListener mActiveSessionListener = 166005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen new MediaSessionManager.OnActiveSessionsChangedListener() { 1661e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 166205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen @Override 166305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public void onActiveSessionsChanged( 166405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen List<android.media.session.MediaController> newControllers) { 1665bc5aacf160c5cc7ff5a196c7c3c1cf62f322fc14Marie Janssen Set<String> updatedPackages = new HashSet<String>(); 166605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen // Update the current players 166705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen for (android.media.session.MediaController controller : newControllers) { 1668bc5aacf160c5cc7ff5a196c7c3c1cf62f322fc14Marie Janssen String packageName = controller.getPackageName(); 1669bc5aacf160c5cc7ff5a196c7c3c1cf62f322fc14Marie Janssen if (DEBUG) Log.v(TAG, "ActiveSession: " + MediaController.wrap(controller)); 1670bc5aacf160c5cc7ff5a196c7c3c1cf62f322fc14Marie Janssen // Only use the first (highest priority) controller from each package 1671bc5aacf160c5cc7ff5a196c7c3c1cf62f322fc14Marie Janssen if (updatedPackages.contains(packageName)) continue; 167205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen addMediaPlayerController(controller); 1673bc5aacf160c5cc7ff5a196c7c3c1cf62f322fc14Marie Janssen updatedPackages.add(packageName); 1674eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1675d996f17ea97b2c592338bcfbc93056d0224da1cdAjay Panicker 1676f2f6a4ea02e9456f71ea0490112845110ca5d975Marie Janssen if (newControllers.size() > 0 && getAddressedPlayerInfo() == null) { 1677f2f6a4ea02e9456f71ea0490112845110ca5d975Marie Janssen if (DEBUG) 1678f2f6a4ea02e9456f71ea0490112845110ca5d975Marie Janssen Log.v(TAG, "No addressed player but active sessions, taking first."); 1679f2f6a4ea02e9456f71ea0490112845110ca5d975Marie Janssen setAddressedMediaSessionPackage(newControllers.get(0).getPackageName()); 1680eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 168185aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker updateCurrentMediaState(); 1682e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 168305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen }; 168405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 168578d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen private void setAddressedMediaSessionPackage(@Nullable String packageName) { 168641527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen if (packageName == null) { 168741527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen // Should only happen when there's no media players, reset to no available player. 168841527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen updateCurrentController(0, mCurrBrowsePlayerID); 168941527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen return; 169041527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen } 16915e5cfd5f5e651367111c5553230e066fc6817942Ajay Panicker if (packageName.equals("com.android.server.telecom")) { 16925e5cfd5f5e651367111c5553230e066fc6817942Ajay Panicker Log.d(TAG, "Ignore addressed media session change to telecom"); 16935e5cfd5f5e651367111c5553230e066fc6817942Ajay Panicker return; 16945e5cfd5f5e651367111c5553230e066fc6817942Ajay Panicker } 169505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen // No change. 169605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (getPackageName(mCurrAddrPlayerID).equals(packageName)) return; 169778d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen if (DEBUG) Log.v(TAG, "Changing addressed media session to " + packageName); 169805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen // If the player doesn't exist, we need to add it. 169905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (getMediaPlayerInfo(packageName) == null) { 170005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen addMediaPlayerPackage(packageName); 170185aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker updateCurrentMediaState(); 170205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 1703511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 1704511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) { 1705511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (entry.getValue().getPackageName().equals(packageName)) { 1706511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int newAddrID = entry.getKey(); 1707511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.v(TAG, "Set addressed #" + newAddrID + " " + entry.getValue()); 1708511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen updateCurrentController(newAddrID, mCurrBrowsePlayerID); 170985aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker updateCurrentMediaState(); 1710511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return; 1711511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1712e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1713e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 171405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen // We shouldn't ever get here. 171505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.e(TAG, "Player info for " + packageName + " doesn't exist!"); 171605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 1717e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 171805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private void setActiveMediaSession(MediaSession.Token token) { 171905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen android.media.session.MediaController activeController = 172005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen new android.media.session.MediaController(mContext, token); 17215e5cfd5f5e651367111c5553230e066fc6817942Ajay Panicker if (activeController.getPackageName().equals("com.android.server.telecom")) { 17225e5cfd5f5e651367111c5553230e066fc6817942Ajay Panicker Log.d(TAG, "Ignore active media session change to telecom"); 17235e5cfd5f5e651367111c5553230e066fc6817942Ajay Panicker return; 17245e5cfd5f5e651367111c5553230e066fc6817942Ajay Panicker } 172505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (DEBUG) Log.v(TAG, "Set active media session " + activeController.getPackageName()); 172605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen addMediaPlayerController(activeController); 172705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen setAddressedMediaSessionPackage(activeController.getPackageName()); 172805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 1729e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1730e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean startBrowseService(byte[] bdaddr, String packageName) { 1731e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah boolean status = true; 1732e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1733e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* creating new instance for Browse Media Player */ 1734e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String browseService = getBrowseServiceName(packageName); 1735e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!browseService.isEmpty()) { 1736e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr).setBrowsed( 1737e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah packageName, browseService); 1738e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 1739e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, "No Browser service available for " + packageName); 1740e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah status = false; 1741e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1742e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1743e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "startBrowseService for packageName: " + packageName + 1744e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ", status = " + status); 1745e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return status; 1746e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1747e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1748511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private String getBrowseServiceName(String packageName) { 1749e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String browseServiceName = ""; 1750e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1751e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // getting the browse service name from browse player info 1752511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mBrowsePlayerInfoList) { 1753511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int browseInfoID = getBrowseId(packageName); 1754511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (browseInfoID != -1) { 1755511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen browseServiceName = mBrowsePlayerInfoList.get(browseInfoID).serviceClass; 1756511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1757e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1758e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1759e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "getBrowseServiceName for packageName: " + packageName + 1760e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ", browseServiceName = " + browseServiceName); 1761e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return browseServiceName; 1762e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1763e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1764754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker void buildBrowsablePlayerList() { 1765754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker synchronized (mBrowsePlayerInfoList) { 17663843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen mBrowsePlayerInfoList.clear(); 17673843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen Intent intent = new Intent(android.service.media.MediaBrowserService.SERVICE_INTERFACE); 1768754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker List<ResolveInfo> playerList = 1769754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker mPackageManager.queryIntentServices(intent, PackageManager.MATCH_ALL); 1770754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker 1771754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker for (ResolveInfo info : playerList) { 1772754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker String displayableName = info.loadLabel(mPackageManager).toString(); 1773754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker String serviceName = info.serviceInfo.name; 1774754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker String packageName = info.serviceInfo.packageName; 1775754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker 1776754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker if (DEBUG) Log.d(TAG, "Adding " + serviceName + " to list of browsable players"); 1777754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker BrowsePlayerInfo currentPlayer = 1778754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker new BrowsePlayerInfo(packageName, displayableName, serviceName); 1779754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker mBrowsePlayerInfoList.add(currentPlayer); 1780754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker MediaPlayerInfo playerInfo = getMediaPlayerInfo(packageName); 1781754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker MediaController controller = 1782754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker (playerInfo == null) ? null : playerInfo.getMediaController(); 1783754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker // Refresh the media player entry so it notices we can browse 1784754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker if (controller != null) { 1785754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker addMediaPlayerController(controller.getWrappedInstance()); 1786754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker } else { 1787754c469a24029e5b9a1c921fb91e3799937eb918Ajay Panicker addMediaPlayerPackage(packageName); 1788eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 17893843256f294cfd3e9b1d883e71ed7306738b6ca1Marie Janssen } 179085aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker updateCurrentMediaState(); 1791e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1792e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1793e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 179405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen /* Initializes list of media players identified from session manager active sessions */ 1795511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private void initMediaPlayersList() { 1796511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 1797511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen // Clearing old browsable player's list 1798511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mMediaPlayerInfoList.clear(); 179905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 1800511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (mMediaSessionManager == null) { 1801511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.w(TAG, "initMediaPlayersList: no media session manager!"); 1802511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return; 1803511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 180405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 1805511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen List<android.media.session.MediaController> controllers = 1806511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mMediaSessionManager.getActiveSessions(null); 1807511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) 1808511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen Log.v(TAG, "initMediaPlayerInfoList: " + controllers.size() + " controllers"); 1809511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen /* Initializing all media players */ 1810511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (android.media.session.MediaController controller : controllers) { 1811511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen addMediaPlayerController(controller); 1812511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1813f2f6a4ea02e9456f71ea0490112845110ca5d975Marie Janssen 181485aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker updateCurrentMediaState(); 1815e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1816511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (mMediaPlayerInfoList.size() > 0) { 1817511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen // Set the first one as the Addressed Player 1818511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen updateCurrentController(mMediaPlayerInfoList.firstKey(), -1); 1819511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1820e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1821e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1822e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1823eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen private List<android.media.session.MediaController> getMediaControllers() { 1824eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen List<android.media.session.MediaController> controllers = 1825eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen new ArrayList<android.media.session.MediaController>(); 1826511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 1827511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (MediaPlayerInfo info : mMediaPlayerInfoList.values()) { 1828a1e42e29b15323e1a4d0559235a0987200663b2fMarie Janssen MediaController controller = info.getMediaController(); 1829a1e42e29b15323e1a4d0559235a0987200663b2fMarie Janssen if (controller != null) { 1830a1e42e29b15323e1a4d0559235a0987200663b2fMarie Janssen controllers.add(controller.getWrappedInstance()); 1831511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1832eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1833eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1834eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen return controllers; 1835eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1836eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 1837eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen /** Add (or update) a player to the media player list without a controller */ 1838511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private boolean addMediaPlayerPackage(String packageName) { 1839eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen MediaPlayerInfo info = new MediaPlayerInfo(null, AvrcpConstants.PLAYER_TYPE_AUDIO, 184059b1c77f883bd97816332046a3a98be4431cceddMarie Janssen AvrcpConstants.PLAYER_SUBTYPE_NONE, PLAYSTATUS_STOPPED, 1841b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen getFeatureBitMask(packageName), packageName, getAppLabel(packageName)); 184205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return addMediaPlayerInfo(info); 1843eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1844eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 1845eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen /** Add (or update) a player to the media player list given an active controller */ 1846511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private boolean addMediaPlayerController(android.media.session.MediaController controller) { 1847eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen String packageName = controller.getPackageName(); 1848eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen MediaPlayerInfo info = new MediaPlayerInfo(MediaController.wrap(controller), 1849eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen AvrcpConstants.PLAYER_TYPE_AUDIO, AvrcpConstants.PLAYER_SUBTYPE_NONE, 185059b1c77f883bd97816332046a3a98be4431cceddMarie Janssen getBluetoothPlayState(controller.getPlaybackState()), 185159b1c77f883bd97816332046a3a98be4431cceddMarie Janssen getFeatureBitMask(packageName), controller.getPackageName(), 185259b1c77f883bd97816332046a3a98be4431cceddMarie Janssen getAppLabel(packageName)); 185305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return addMediaPlayerInfo(info); 1854eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1855eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 185605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen /** Add or update a player to the media player list given the MediaPlayerInfo object. 185705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen * @return true if an item was updated, false if it was added instead 185805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen */ 1859511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private boolean addMediaPlayerInfo(MediaPlayerInfo info) { 1860b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen int updateId = -1; 186105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen boolean updated = false; 1862f2f6a4ea02e9456f71ea0490112845110ca5d975Marie Janssen boolean currentRemoved = false; 18635e5cfd5f5e651367111c5553230e066fc6817942Ajay Panicker if (info.getPackageName().equals("com.android.server.telecom")) { 18645e5cfd5f5e651367111c5553230e066fc6817942Ajay Panicker Log.d(TAG, "Skip adding telecom to the media player info list"); 18655e5cfd5f5e651367111c5553230e066fc6817942Ajay Panicker return updated; 18665e5cfd5f5e651367111c5553230e066fc6817942Ajay Panicker } 1867511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 1868511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) { 1869f2f6a4ea02e9456f71ea0490112845110ca5d975Marie Janssen MediaPlayerInfo current = entry.getValue(); 1870f2f6a4ea02e9456f71ea0490112845110ca5d975Marie Janssen int id = entry.getKey(); 1871f2f6a4ea02e9456f71ea0490112845110ca5d975Marie Janssen if (info.getPackageName().equals(current.getPackageName())) { 1872f2f6a4ea02e9456f71ea0490112845110ca5d975Marie Janssen if (!current.equalView(info)) { 1873f2f6a4ea02e9456f71ea0490112845110ca5d975Marie Janssen // If we would present a different player, make it a new player 1874f2f6a4ea02e9456f71ea0490112845110ca5d975Marie Janssen // so that controllers know whether a player is browsable or not. 1875f2f6a4ea02e9456f71ea0490112845110ca5d975Marie Janssen mMediaPlayerInfoList.remove(id); 1876f2f6a4ea02e9456f71ea0490112845110ca5d975Marie Janssen currentRemoved = (mCurrAddrPlayerID == id); 1877f2f6a4ea02e9456f71ea0490112845110ca5d975Marie Janssen break; 1878f2f6a4ea02e9456f71ea0490112845110ca5d975Marie Janssen } 1879f2f6a4ea02e9456f71ea0490112845110ca5d975Marie Janssen updateId = id; 1880511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen updated = true; 1881511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen break; 1882511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1883b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen } 1884511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (updateId == -1) { 1885511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen // New player 1886511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mLastUsedPlayerID++; 1887511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen updateId = mLastUsedPlayerID; 1888f2f6a4ea02e9456f71ea0490112845110ca5d975Marie Janssen mAvailablePlayerViewChanged = true; 1889511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1890511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mMediaPlayerInfoList.put(updateId, info); 1891fecc92279a01e377962b9b33b02d5db0ff3d1440Jack He } 1892fecc92279a01e377962b9b33b02d5db0ff3d1440Jack He if (DEBUG) Log.d(TAG, (updated ? "update #" : "add #") + updateId + ":" + info.toString()); 1893fecc92279a01e377962b9b33b02d5db0ff3d1440Jack He if (currentRemoved || updateId == mCurrAddrPlayerID) { 1894fecc92279a01e377962b9b33b02d5db0ff3d1440Jack He updateCurrentController(updateId, mCurrBrowsePlayerID); 1895b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen } 189605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return updated; 1897eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1898eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 1899eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen /** Remove all players related to |packageName| from the media player info list */ 1900511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private MediaPlayerInfo removeMediaPlayerInfo(String packageName) { 1901511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 1902511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int removeKey = -1; 1903511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) { 1904511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (entry.getValue().getPackageName().equals(packageName)) { 1905511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen removeKey = entry.getKey(); 1906511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen break; 1907511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1908511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1909511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (removeKey != -1) { 1910384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen if (DEBUG) 1911384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen Log.d(TAG, "remove #" + removeKey + ":" + mMediaPlayerInfoList.get(removeKey)); 1912f2f6a4ea02e9456f71ea0490112845110ca5d975Marie Janssen mAvailablePlayerViewChanged = true; 1913511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return mMediaPlayerInfoList.remove(removeKey); 1914eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1915b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen 1916511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return null; 1917511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 1918eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 1919eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 1920384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen /** Remove the controller referenced by |controller| from any player in the list */ 1921f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen private void removeMediaController(@Nullable android.media.session.MediaController controller) { 1922f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen if (controller == null) return; 1923384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen synchronized (mMediaPlayerInfoList) { 1924f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) { 1925f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen MediaPlayerInfo info = entry.getValue(); 1926a1e42e29b15323e1a4d0559235a0987200663b2fMarie Janssen MediaController c = info.getMediaController(); 1927f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen if (c != null && c.equals(controller)) { 1928f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen info.setMediaController(null); 1929f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen if (entry.getKey() == mCurrAddrPlayerID) { 1930f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen updateCurrentController(mCurrAddrPlayerID, mCurrBrowsePlayerID); 1931f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen } 1932f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen } 1933384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } 1934384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } 1935384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } 1936384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen 1937e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* 1938e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * utility function to get the playback state of any media player through 1939e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * media controller APIs. 1940e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 194159b1c77f883bd97816332046a3a98be4431cceddMarie Janssen private byte getBluetoothPlayState(PlaybackState pbState) { 194259b1c77f883bd97816332046a3a98be4431cceddMarie Janssen if (pbState == null) { 194359b1c77f883bd97816332046a3a98be4431cceddMarie Janssen Log.w(TAG, "playState object null, sending STOPPED"); 194459b1c77f883bd97816332046a3a98be4431cceddMarie Janssen return PLAYSTATUS_STOPPED; 1945e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1946e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 194759b1c77f883bd97816332046a3a98be4431cceddMarie Janssen switch (pbState.getState()) { 1948e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_PLAYING: 1949e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_PLAYING; 1950e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1951cd1345961b7211ef6d130bd88b672835b52b3f60Ajay Panicker case PlaybackState.STATE_BUFFERING: 1952e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_STOPPED: 1953e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_NONE: 1954e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_CONNECTING: 1955e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_STOPPED; 1956e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1957e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_PAUSED: 1958e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_PAUSED; 1959e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1960e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_FAST_FORWARDING: 1961e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_SKIPPING_TO_NEXT: 1962e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_SKIPPING_TO_QUEUE_ITEM: 1963e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_FWD_SEEK; 1964e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1965e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_REWINDING: 1966e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_SKIPPING_TO_PREVIOUS: 1967e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_REV_SEEK; 1968e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1969e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah case PlaybackState.STATE_ERROR: 1970e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah default: 1971e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return PLAYSTATUS_ERROR; 1972e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1973e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 1974e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1975e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* 1976e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * utility function to get the feature bit mask of any media player through 1977e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * package name 1978e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 1979e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private short[] getFeatureBitMask(String packageName) { 1980e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1981e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ArrayList<Short> featureBitsList = new ArrayList<Short>(); 1982e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1983e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* adding default feature bits */ 1984e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_PLAY_BIT_NO); 1985e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_STOP_BIT_NO); 1986e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_PAUSE_BIT_NO); 1987e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_REWIND_BIT_NO); 1988e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_FAST_FWD_BIT_NO); 1989e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_FORWARD_BIT_NO); 1990e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_BACKWARD_BIT_NO); 1991e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_ADV_CTRL_BIT_NO); 1992e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 1993e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Add/Modify browse player supported features. */ 1994e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (isBrowseSupported(packageName)) { 1995e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_BROWSE_BIT_NO); 1996e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_UID_UNIQUE_BIT_NO); 1997e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_NOW_PLAY_BIT_NO); 1998e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsList.add(AvrcpConstants.AVRC_PF_GET_NUM_OF_ITEMS_BIT_NO); 1999e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2000e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2001e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // converting arraylist to array for response 2002e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah short[] featureBitsArray = new short[featureBitsList.size()]; 2003e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2004e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah for (int i = 0; i < featureBitsList.size(); i++) { 2005e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah featureBitsArray[i] = featureBitsList.get(i).shortValue(); 2006e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2007e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2008e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return featureBitsArray; 2009e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2010e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2011e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /** 2012e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * Checks the Package name if it supports Browsing or not. 2013e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * 2014e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * @param packageName - name of the package to get the Id. 2015e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * @return true if it supports browsing, else false. 2016e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 2017511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private boolean isBrowseSupported(String packageName) { 2018511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mBrowsePlayerInfoList) { 2019511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen /* check if Browsable Player's list contains this package name */ 2020511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (BrowsePlayerInfo info : mBrowsePlayerInfoList) { 2021511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (info.packageName.equals(packageName)) { 2022511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.v(TAG, "isBrowseSupported for " + packageName + ": true"); 2023511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return true; 2024511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2025e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2026e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2027e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2028b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen if (DEBUG) Log.v(TAG, "isBrowseSupported for " + packageName + ": false"); 20291b70ec148be773651d5ad00e3ce0d28b3a63306dAjay Panicker return false; 2030e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2031e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2032e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private String getPackageName(int id) { 2033511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen MediaPlayerInfo player = null; 2034511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 2035511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen player = mMediaPlayerInfoList.getOrDefault(id, null); 2036511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2037e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2038eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen if (player == null) { 2039eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen Log.w(TAG, "No package name for player (" + id + " not valid)"); 2040eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen return ""; 2041e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2042eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 2043eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen String packageName = player.getPackageName(); 2044eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen if (DEBUG) Log.v(TAG, "Player " + id + " package: " + packageName); 2045e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return packageName; 2046e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2047e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2048e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* from the global object, getting the current browsed player's package name */ 2049e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private String getCurrentBrowsedPlayer(byte[] bdaddr) { 2050e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String browsedPlayerPackage = ""; 2051e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2052e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Map<String, BrowsedMediaPlayer> connList = mAvrcpBrowseManager.getConnList(); 2053e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String bdaddrStr = new String(bdaddr); 2054e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if(connList.containsKey(bdaddrStr)){ 2055e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah browsedPlayerPackage = connList.get(bdaddrStr).getPackageName(); 2056e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2057e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.v(TAG, "getCurrentBrowsedPlayerPackage: " + browsedPlayerPackage); 2058e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return browsedPlayerPackage; 2059e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2060e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2061eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen /* Returns the MediaPlayerInfo for the currently addressed media player */ 2062511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private MediaPlayerInfo getAddressedPlayerInfo() { 2063511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 2064511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return mMediaPlayerInfoList.getOrDefault(mCurrAddrPlayerID, null); 2065511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2066e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2067e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2068e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* 2069e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * Utility function to get the Media player info from package name returns 2070e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * null if package name not found in media players list 2071e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 2072511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private MediaPlayerInfo getMediaPlayerInfo(String packageName) { 2073511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 2074511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (mMediaPlayerInfoList.isEmpty()) { 2075511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.v(TAG, "getMediaPlayerInfo: Media players list empty"); 2076511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return null; 2077511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2078eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 2079511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (MediaPlayerInfo info : mMediaPlayerInfoList.values()) { 2080511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (packageName.equals(info.getPackageName())) { 2081511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.v(TAG, "getMediaPlayerInfo: Found " + packageName); 2082511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return info; 2083511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2084e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2085511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.w(TAG, "getMediaPlayerInfo: " + packageName + " not found"); 2086511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return null; 2087e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2088e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2089e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2090e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* prepare media list & return the media player list response object */ 2091511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private MediaPlayerListRsp prepareMediaPlayerRspObj() { 2092511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 209342b19bc308e155b52e735e38efca42d5c7c6a699Ajay Panicker // TODO(apanicke): This hack will go away as soon as a developer 209442b19bc308e155b52e735e38efca42d5c7c6a699Ajay Panicker // option to enable or disable player selection is created. Right 209542b19bc308e155b52e735e38efca42d5c7c6a699Ajay Panicker // now this is needed to fix BMW i3 carkits and any other carkits 209642b19bc308e155b52e735e38efca42d5c7c6a699Ajay Panicker // that might try to connect to a player that isnt the current 209742b19bc308e155b52e735e38efca42d5c7c6a699Ajay Panicker // player based on this list 209842b19bc308e155b52e735e38efca42d5c7c6a699Ajay Panicker int numPlayers = 1; 2099511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen 2100511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int[] playerIds = new int[numPlayers]; 2101511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen byte[] playerTypes = new byte[numPlayers]; 2102511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int[] playerSubTypes = new int[numPlayers]; 2103511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen String[] displayableNameArray = new String[numPlayers]; 2104511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen byte[] playStatusValues = new byte[numPlayers]; 2105511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen short[] featureBitMaskValues = 2106511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen new short[numPlayers * AvrcpConstants.AVRC_FEATURE_MASK_SIZE]; 2107511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen 21087a44bb23aadc107c369d230fb96f4ce3374f3f5bAjay Panicker // Reserve the first spot for the currently addressed player if 21097a44bb23aadc107c369d230fb96f4ce3374f3f5bAjay Panicker // we have one 21107a44bb23aadc107c369d230fb96f4ce3374f3f5bAjay Panicker int players = mMediaPlayerInfoList.containsKey(mCurrAddrPlayerID) ? 1 : 0; 2111511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) { 21122a9aba641d081621a373b56171938994447040e3Ajay Panicker int idx = players; 211342b19bc308e155b52e735e38efca42d5c7c6a699Ajay Panicker if (entry.getKey() == mCurrAddrPlayerID) 211442b19bc308e155b52e735e38efca42d5c7c6a699Ajay Panicker idx = 0; 211542b19bc308e155b52e735e38efca42d5c7c6a699Ajay Panicker else 211642b19bc308e155b52e735e38efca42d5c7c6a699Ajay Panicker continue; // TODO(apanicke): Remove, see above note 2117511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen MediaPlayerInfo info = entry.getValue(); 21182a9aba641d081621a373b56171938994447040e3Ajay Panicker playerIds[idx] = entry.getKey(); 21192a9aba641d081621a373b56171938994447040e3Ajay Panicker playerTypes[idx] = info.getMajorType(); 21202a9aba641d081621a373b56171938994447040e3Ajay Panicker playerSubTypes[idx] = info.getSubType(); 21212a9aba641d081621a373b56171938994447040e3Ajay Panicker displayableNameArray[idx] = info.getDisplayableName(); 21222a9aba641d081621a373b56171938994447040e3Ajay Panicker playStatusValues[idx] = info.getPlayStatus(); 2123511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen 2124511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen short[] featureBits = info.getFeatureBitMask(); 2125511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (int numBit = 0; numBit < featureBits.length; numBit++) { 2126511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen /* gives which octet this belongs to */ 2127511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen byte octet = (byte) (featureBits[numBit] / 8); 2128511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen /* gives the bit position within the octet */ 2129511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen byte bit = (byte) (featureBits[numBit] % 8); 21302a9aba641d081621a373b56171938994447040e3Ajay Panicker featureBitMaskValues[(idx * AvrcpConstants.AVRC_FEATURE_MASK_SIZE) + octet] |= 21312a9aba641d081621a373b56171938994447040e3Ajay Panicker (1 << bit); 2132511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2133e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2134511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen /* printLogs */ 2135511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) { 21362a9aba641d081621a373b56171938994447040e3Ajay Panicker Log.d(TAG, "Player " + playerIds[idx] + ": " + displayableNameArray[idx] 21372a9aba641d081621a373b56171938994447040e3Ajay Panicker + " type: " + playerTypes[idx] + ", " + playerSubTypes[idx] 21382a9aba641d081621a373b56171938994447040e3Ajay Panicker + " status: " + playStatusValues[idx]); 2139511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2140e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 21412a9aba641d081621a373b56171938994447040e3Ajay Panicker if (idx != 0) players++; 2142511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2143e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2144511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.d(TAG, "prepareMediaPlayerRspObj: numPlayers = " + numPlayers); 2145e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2146511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return new MediaPlayerListRsp(AvrcpConstants.RSP_NO_ERROR, sUIDCounter, numPlayers, 2147511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen AvrcpConstants.BTRC_ITEM_PLAYER, playerIds, playerTypes, playerSubTypes, 2148511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen playStatusValues, featureBitMaskValues, displayableNameArray); 2149511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2150e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2151e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2152e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* build media player list and send it to remote. */ 2153e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handleMediaPlayerListRsp(AvrcpCmd.FolderItemsCmd folderObj) { 2154511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen MediaPlayerListRsp rspObj = null; 2155511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 2156511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int numPlayers = mMediaPlayerInfoList.size(); 2157511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (numPlayers == 0) { 2158511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mediaPlayerListRspNative(folderObj.mAddress, AvrcpConstants.RSP_NO_AVBL_PLAY, 2159511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen (short) 0, (byte) 0, 0, null, null, null, null, null, null); 2160511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return; 2161511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2162511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (folderObj.mStartItem >= numPlayers) { 2163511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen Log.i(TAG, "handleMediaPlayerListRsp: start = " + folderObj.mStartItem 2164511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen + " > num of items = " + numPlayers); 2165511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen mediaPlayerListRspNative(folderObj.mAddress, AvrcpConstants.RSP_INV_RANGE, 2166511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen (short) 0, (byte) 0, 0, null, null, null, null, null, null); 2167511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen return; 2168511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2169511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen rspObj = prepareMediaPlayerRspObj(); 2170e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2171511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.d(TAG, "handleMediaPlayerListRsp: sending " + rspObj.mNumItems + " players"); 2172eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen mediaPlayerListRspNative(folderObj.mAddress, rspObj.mStatus, rspObj.mUIDCounter, 2173eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen rspObj.itemType, rspObj.mNumItems, rspObj.mPlayerIds, rspObj.mPlayerTypes, 2174eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen rspObj.mPlayerSubTypes, rspObj.mPlayStatusValues, rspObj.mFeatureBitMaskValues, 2175eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen rspObj.mPlayerNameList); 2176e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2177e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2178e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* unregister to the old controller, update new IDs and register to the new controller */ 2179e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean updateCurrentController(int addrId, int browseId) { 2180e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah boolean registerRsp = true; 2181e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2182e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah updateNewIds(addrId, browseId); 2183e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2184eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen MediaController newController = null; 2185eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen MediaPlayerInfo info = getAddressedPlayerInfo(); 218678d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen if (info != null) newController = info.getMediaController(); 2187eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen 2188eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen if (DEBUG) 2189eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen Log.d(TAG, "updateCurrentController: " + mMediaController + " to " + newController); 2190ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen synchronized (this) { 2191ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen if (mMediaController == null || (!mMediaController.equals(newController))) { 2192f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen if (mMediaController != null) { 2193f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen mMediaController.unregisterCallback(mMediaControllerCb); 2194f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen } 2195f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen mMediaController = newController; 2196f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen if (mMediaController != null) { 2197f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen mMediaController.registerCallback(mMediaControllerCb, mHandler); 21983a80469f095e51f9be3965d67fff595eabc00293Marie Janssen mAddressedMediaPlayer.updateNowPlayingList(mMediaController); 2199f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen } else { 2200f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen mAddressedMediaPlayer.updateNowPlayingList(null); 2201f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen registerRsp = false; 2202f6521ba818df22d8a853d25f7c6adc1e724875e6Marie Janssen } 2203eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 2204e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 220585aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker updateCurrentMediaState(); 2206eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen return registerRsp; 2207e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2208e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2209e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Handle getfolderitems for scope = VFS, Search, NowPlayingList */ 2210e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handleGetFolderItemBrowseResponse(AvrcpCmd.FolderItemsCmd folderObj, byte[] bdaddr) { 2211e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int status = AvrcpConstants.RSP_NO_ERROR; 2212e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2213e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Browsed player is already set */ 221405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (folderObj.mScope == AvrcpConstants.BTRC_SCOPE_FILE_SYSTEM) { 221505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr) == null) { 221605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.e(TAG, "handleGetFolderItemBrowseResponse: no browsed player set for " 221705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen + Utils.getAddressStringFromByte(bdaddr)); 221805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen getFolderItemsRspNative(bdaddr, AvrcpConstants.RSP_INTERNAL_ERR, (short) 0, 221905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen (byte) 0x00, 0, null, null, null, null, null, null, null, null); 222005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return; 222105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 222205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr).getFolderItemsVFS(folderObj); 222305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return; 2224e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 222505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (folderObj.mScope == AvrcpConstants.BTRC_SCOPE_NOW_PLAYING) { 222605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mAddressedMediaPlayer.getFolderItemsNowPlaying(bdaddr, folderObj, mMediaController); 222705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return; 2228e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2229e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 223005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen /* invalid scope */ 223105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.e(TAG, "handleGetFolderItemBrowseResponse: unknown scope " + folderObj.mScope); 223205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen getFolderItemsRspNative(bdaddr, AvrcpConstants.RSP_INV_SCOPE, (short) 0, (byte) 0x00, 0, 223305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen null, null, null, null, null, null, null, null); 2234e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2235e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2236e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* utility function to update the global values of current Addressed and browsed player */ 2237511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen private void updateNewIds(int addrId, int browseId) { 223878d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen if (DEBUG) 223978d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen Log.v(TAG, "updateNewIds: Addressed:" + mCurrAddrPlayerID + " to " + addrId 224078d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen + ", Browse:" + mCurrBrowsePlayerID + " to " + browseId); 2241e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mCurrAddrPlayerID = addrId; 2242e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mCurrBrowsePlayerID = browseId; 2243e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2244e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2245e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Getting the application's displayable name from package name */ 2246e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private String getAppLabel(String packageName) { 2247e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ApplicationInfo appInfo = null; 2248e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah try { 2249e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah appInfo = mPackageManager.getApplicationInfo(packageName, 0); 2250e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } catch (NameNotFoundException e) { 2251e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah e.printStackTrace(); 2252e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2253e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2254e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return (String) (appInfo != null ? mPackageManager 2255e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah .getApplicationLabel(appInfo) : "Unknown"); 2256e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2257e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2258e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handlePlayItemResponse(byte[] bdaddr, byte[] uid, byte scope) { 2259294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen if (scope == AvrcpConstants.BTRC_SCOPE_NOW_PLAYING) { 2260294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen mAddressedMediaPlayer.playItem(bdaddr, uid, mMediaController); 2261e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2262e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah else { 2263e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if(!isAddrPlayerSameAsBrowsed(bdaddr)) { 2264e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, "Remote requesting play item on uid which may not be recognized by" + 2265e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah "current addressed player"); 2266e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah playItemRspNative(bdaddr, AvrcpConstants.RSP_INV_ITEM); 2267e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2268e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2269e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr) != null) { 2270e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr).playItem(uid, scope); 2271e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2272e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "handlePlayItemResponse: Remote requested playitem " + 2273e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah "before setbrowsedplayer"); 2274e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah playItemRspNative(bdaddr, AvrcpConstants.RSP_INTERNAL_ERR); 2275e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2276e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2277e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2278e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2279e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handleGetItemAttr(AvrcpCmd.ItemAttrCmd itemAttr) { 228045551315d39fd0bc1c5a118b4728c728ce42b412koh.changseok if (itemAttr.mUidCounter != sUIDCounter) { 228145551315d39fd0bc1c5a118b4728c728ce42b412koh.changseok Log.e(TAG, "handleGetItemAttr: invaild uid counter."); 228245551315d39fd0bc1c5a118b4728c728ce42b412koh.changseok getItemAttrRspNative( 228345551315d39fd0bc1c5a118b4728c728ce42b412koh.changseok itemAttr.mAddress, AvrcpConstants.RSP_UID_CHANGED, (byte) 0, null, null); 228445551315d39fd0bc1c5a118b4728c728ce42b412koh.changseok return; 228545551315d39fd0bc1c5a118b4728c728ce42b412koh.changseok } 2286384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen if (itemAttr.mScope == AvrcpConstants.BTRC_SCOPE_NOW_PLAYING) { 2287384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen if (mCurrAddrPlayerID == NO_PLAYER_ID) { 2288384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen getItemAttrRspNative( 2289384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen itemAttr.mAddress, AvrcpConstants.RSP_NO_AVBL_PLAY, (byte) 0, null, null); 2290c1267074b7df0d6e42cefea0ac40b584fdb1430fMarie Janssen return; 2291384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } 2292c1267074b7df0d6e42cefea0ac40b584fdb1430fMarie Janssen mAddressedMediaPlayer.getItemAttr(itemAttr.mAddress, itemAttr, mMediaController); 2293c1267074b7df0d6e42cefea0ac40b584fdb1430fMarie Janssen return; 2294c1267074b7df0d6e42cefea0ac40b584fdb1430fMarie Janssen } 2295c1267074b7df0d6e42cefea0ac40b584fdb1430fMarie Janssen // All other scopes use browsed player 2296c1267074b7df0d6e42cefea0ac40b584fdb1430fMarie Janssen if (mAvrcpBrowseManager.getBrowsedMediaPlayer(itemAttr.mAddress) != null) { 2297c1267074b7df0d6e42cefea0ac40b584fdb1430fMarie Janssen mAvrcpBrowseManager.getBrowsedMediaPlayer(itemAttr.mAddress).getItemAttr(itemAttr); 2298384011244f5a62ed34f198b8ba91341b4efb4fb6Marie Janssen } else { 2299c1267074b7df0d6e42cefea0ac40b584fdb1430fMarie Janssen Log.e(TAG, "Could not get attributes. mBrowsedMediaPlayer is null"); 2300c1267074b7df0d6e42cefea0ac40b584fdb1430fMarie Janssen getItemAttrRspNative( 2301c1267074b7df0d6e42cefea0ac40b584fdb1430fMarie Janssen itemAttr.mAddress, AvrcpConstants.RSP_INTERNAL_ERR, (byte) 0, null, null); 2302e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2303e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2304e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2305e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private void handleGetTotalNumOfItemsResponse(byte[] bdaddr, byte scope) { 2306e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // for scope as media player list 2307e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (scope == AvrcpConstants.BTRC_SCOPE_PLAYER_LIST) { 2308511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int numPlayers = 0; 2309511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 2310511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen numPlayers = mMediaPlayerInfoList.size(); 2311511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 2312511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen if (DEBUG) Log.d(TAG, "handleGetTotalNumOfItemsResponse: " + numPlayers + " players."); 2313511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen getTotalNumOfItemsRspNative(bdaddr, AvrcpConstants.RSP_NO_ERROR, 0, numPlayers); 2314511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } else if (scope == AvrcpConstants.BTRC_SCOPE_NOW_PLAYING) { 2315294ff299ca4837fd7f56861941b274fadee97ec4Marie Janssen mAddressedMediaPlayer.getTotalNumOfItems(bdaddr, mMediaController); 2316e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2317e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // for FileSystem browsing scopes as VFS, Now Playing 2318e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr) != null) { 2319e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mAvrcpBrowseManager.getBrowsedMediaPlayer(bdaddr).getTotalNumOfItems(scope); 2320e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2321e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "Could not get Total NumOfItems. mBrowsedMediaPlayer is null"); 2322e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah getTotalNumOfItemsRspNative(bdaddr, AvrcpConstants.RSP_INTERNAL_ERR, 0, 0); 2323e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2324e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2325e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2326e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2327e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2328e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* check if browsed player and addressed player are same */ 2329e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean isAddrPlayerSameAsBrowsed(byte[] bdaddr) { 2330e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String browsedPlayer = getCurrentBrowsedPlayer(bdaddr); 2331e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2332e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!isPackageNameValid(browsedPlayer)) { 2333e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.w(TAG, "Browsed player name empty"); 2334eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen return false; 2335e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2336e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2337b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen MediaPlayerInfo info = getAddressedPlayerInfo(); 2338db2d487ba559f0e4de02bc2ad4cc7e275878b2fcMarie Janssen String packageName = (info == null) ? "<none>" : info.getPackageName(); 2339db2d487ba559f0e4de02bc2ad4cc7e275878b2fcMarie Janssen if (info == null || !packageName.equals(browsedPlayer)) { 2340db2d487ba559f0e4de02bc2ad4cc7e275878b2fcMarie Janssen if (DEBUG) Log.d(TAG, browsedPlayer + " is not addressed player " + packageName); 2341eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen return false; 2342eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen } 2343eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen return true; 2344e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2345e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2346e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* checks if package name is not null or empty */ 2347e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean isPackageNameValid(String browsedPackage) { 2348e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah boolean isValid = (browsedPackage != null && browsedPackage.length() > 0); 2349e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "isPackageNameValid: browsedPackage = " + browsedPackage + 2350e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah "isValid = " + isValid); 2351e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return isValid; 2352e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2353e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2354e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* checks if selected addressed player is already addressed */ 2355e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private boolean isPlayerAlreadyAddressed(int selectedId) { 2356e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // checking if selected ID is same as the current addressed player id 2357e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah boolean isAddressed = (mCurrAddrPlayerID == selectedId); 2358e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (DEBUG) Log.d(TAG, "isPlayerAlreadyAddressed: isAddressed = " + isAddressed); 2359e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return isAddressed; 2360e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2361e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2362e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void dump(StringBuilder sb) { 2363e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah sb.append("AVRCP:\n"); 2364cc07ee436d00418ecc69ae3aace986f7fbf0823aMarie Janssen ProfileService.println(sb, "mMediaAttributes: " + mMediaAttributes.toRedactedString()); 2365e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mTransportControlFlags: " + mTransportControlFlags); 2366e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mCurrentPlayState: " + mCurrentPlayState); 2367e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mPlayStatusChangedNT: " + mPlayStatusChangedNT); 2368e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mTrackChangedNT: " + mTrackChangedNT); 2369e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mPlaybackIntervalMs: " + mPlaybackIntervalMs); 2370e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mPlayPosChangedNT: " + mPlayPosChangedNT); 2371e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mNextPosMs: " + mNextPosMs); 2372e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mPrevPosMs: " + mPrevPosMs); 2373e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mFeatures: " + mFeatures); 2374e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mRemoteVolume: " + mRemoteVolume); 2375e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mLastRemoteVolume: " + mLastRemoteVolume); 2376e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mLastDirection: " + mLastDirection); 2377e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mVolumeStep: " + mVolumeStep); 2378e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mAudioStreamMax: " + mAudioStreamMax); 2379e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mVolCmdAdjustInProgress: " + mVolCmdAdjustInProgress); 2380e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mVolCmdSetInProgress: " + mVolCmdSetInProgress); 2381e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mAbsVolRetryTimes: " + mAbsVolRetryTimes); 2382e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah ProfileService.println(sb, "mVolumeMapping: " + mVolumeMapping.toString()); 2383ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen synchronized (this) { 2384ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen if (mMediaController != null) 2385ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen ProfileService.println(sb, "mMediaController: " 2386ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen + mMediaController.getWrappedInstance() + " pkg " 2387ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen + mMediaController.getPackageName()); 2388ad7a50ece55752b9b7e47cd86dc45de368c8c6d5Marie Janssen } 238978d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen ProfileService.println(sb, ""); 239078d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen ProfileService.println(sb, "Media Players:"); 2391511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen synchronized (mMediaPlayerInfoList) { 2392511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) { 2393511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen int key = entry.getKey(); 2394511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen ProfileService.println(sb, ((mCurrAddrPlayerID == key) ? " *#" : " #") 2395511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen + entry.getKey() + ": " + entry.getValue()); 2396511ebf9e8dfa9f39315de93ad9a5dcf72556676eMarie Janssen } 239705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 239805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 2399e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen ProfileService.println(sb, ""); 2400e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen mAddressedMediaPlayer.dump(sb, mMediaController); 2401e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen 2402e5384f02ec837a8f274ed59548cb6879849239f5Marie Janssen ProfileService.println(sb, ""); 240378d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen ProfileService.println(sb, mPassthroughDispatched + " passthrough operations: "); 240478d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen if (mPassthroughDispatched > mPassthroughLogs.size()) 240578d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen ProfileService.println(sb, " (last " + mPassthroughLogs.size() + ")"); 240678d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen synchronized (mPassthroughLogs) { 240778d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen for (MediaKeyLog log : mPassthroughLogs) { 240878d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen ProfileService.println(sb, " " + log); 240978d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen } 241005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 241178d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen synchronized (mPassthroughPending) { 241278d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen for (MediaKeyLog log : mPassthroughPending) { 241378d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen ProfileService.println(sb, " " + log); 241478d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen } 2415b8faaf4863cfae62c32af644765a9190512925c9Marie Janssen } 2416aad52567f7c3d4b88868f4dab95c148675c91816Pavlin Radoslavov 2417aad52567f7c3d4b88868f4dab95c148675c91816Pavlin Radoslavov // Print the blacklisted devices (for absolute volume control) 2418aad52567f7c3d4b88868f4dab95c148675c91816Pavlin Radoslavov SharedPreferences pref = 2419aad52567f7c3d4b88868f4dab95c148675c91816Pavlin Radoslavov mContext.getSharedPreferences(ABSOLUTE_VOLUME_BLACKLIST, Context.MODE_PRIVATE); 2420aad52567f7c3d4b88868f4dab95c148675c91816Pavlin Radoslavov Map<String, ?> allKeys = pref.getAll(); 2421aad52567f7c3d4b88868f4dab95c148675c91816Pavlin Radoslavov ProfileService.println(sb, ""); 2422aad52567f7c3d4b88868f4dab95c148675c91816Pavlin Radoslavov ProfileService.println(sb, "Runtime Blacklisted Devices (absolute volume):"); 2423aad52567f7c3d4b88868f4dab95c148675c91816Pavlin Radoslavov if (allKeys.isEmpty()) { 2424aad52567f7c3d4b88868f4dab95c148675c91816Pavlin Radoslavov ProfileService.println(sb, " None"); 2425aad52567f7c3d4b88868f4dab95c148675c91816Pavlin Radoslavov } else { 2426aad52567f7c3d4b88868f4dab95c148675c91816Pavlin Radoslavov for (String key : allKeys.keySet()) { 2427aad52567f7c3d4b88868f4dab95c148675c91816Pavlin Radoslavov ProfileService.println(sb, " " + key); 2428aad52567f7c3d4b88868f4dab95c148675c91816Pavlin Radoslavov } 2429aad52567f7c3d4b88868f4dab95c148675c91816Pavlin Radoslavov } 2430e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2431e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2432e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public class AvrcpBrowseManager { 2433e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Map<String, BrowsedMediaPlayer> connList = new HashMap<String, BrowsedMediaPlayer>(); 2434e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private AvrcpMediaRspInterface mMediaInterface; 2435e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private Context mContext; 2436e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2437e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public AvrcpBrowseManager(Context context, AvrcpMediaRspInterface mediaInterface) { 2438e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mContext = context; 2439e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mMediaInterface = mediaInterface; 2440e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2441e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2442e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void cleanup() { 2443e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Iterator entries = connList.entrySet().iterator(); 2444e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah while (entries.hasNext()) { 2445e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Map.Entry entry = (Map.Entry) entries.next(); 2446e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah BrowsedMediaPlayer browsedMediaPlayer = (BrowsedMediaPlayer) entry.getValue(); 2447e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (browsedMediaPlayer != null) { 2448e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah browsedMediaPlayer.cleanup(); 2449e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2450e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2451e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // clean up the map 2452e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah connList.clear(); 2453e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2454e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2455e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // get the a free media player interface based on the passed bd address 2456e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // if the no items is found for the passed media player then it assignes a 2457e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // available media player interface 2458e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public BrowsedMediaPlayer getBrowsedMediaPlayer(byte[] bdaddr) { 2459e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah BrowsedMediaPlayer mediaPlayer; 2460e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String bdaddrStr = new String(bdaddr); 246105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (connList.containsKey(bdaddrStr)) { 2462e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mediaPlayer = connList.get(bdaddrStr); 2463e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2464e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah mediaPlayer = new BrowsedMediaPlayer(bdaddr, mContext, mMediaInterface); 2465e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah connList.put(bdaddrStr, mediaPlayer); 2466e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2467e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return mediaPlayer; 2468e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2469e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2470e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // clears the details pertaining to passed bdaddres 2471e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public boolean clearBrowsedMediaPlayer(byte[] bdaddr) { 2472e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String bdaddrStr = new String(bdaddr); 247305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (connList.containsKey(bdaddrStr)) { 2474e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah connList.remove(bdaddrStr); 2475e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return true; 2476e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2477e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return false; 2478e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2479e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2480e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public Map<String, BrowsedMediaPlayer> getConnList() { 2481e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return connList; 2482e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2483e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2484e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* Helper function to convert colon separated bdaddr to byte string */ 2485e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private byte[] hexStringToByteArray(String s) { 2486e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int len = s.length(); 2487e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] data = new byte[len / 2]; 2488e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah for (int i = 0; i < len; i += 2) { 2489e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) 2490e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah + Character.digit(s.charAt(i+1), 16)); 2491e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2492e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return data; 2493e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2494e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2495e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2496e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* 2497e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * private class which handles responses from AvrcpMediaManager. Maps responses to native 2498e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah * responses. This class implements the AvrcpMediaRspInterface interface. 2499e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah */ 2500e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private class AvrcpMediaRsp implements AvrcpMediaRspInterface { 2501e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private static final String TAG = "AvrcpMediaRsp"; 2502e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2503e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void setAddrPlayerRsp(byte[] address, int rspStatus) { 2504e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!setAddressedPlayerRspNative(address, rspStatus)) { 2505e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "setAddrPlayerRsp failed!"); 2506e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2507e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2508e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2509e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void setBrowsedPlayerRsp(byte[] address, int rspStatus, byte depth, int numItems, 2510e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String[] textArray) { 2511e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!setBrowsedPlayerRspNative(address, rspStatus, depth, numItems, textArray)) { 2512e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "setBrowsedPlayerRsp failed!"); 2513e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2514e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2515e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2516e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void mediaPlayerListRsp(byte[] address, int rspStatus, MediaPlayerListRsp rspObj) { 2517e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (rspObj != null && rspStatus == AvrcpConstants.RSP_NO_ERROR) { 2518e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!mediaPlayerListRspNative(address, rspStatus, sUIDCounter, rspObj.itemType, 2519eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen rspObj.mNumItems, rspObj.mPlayerIds, rspObj.mPlayerTypes, 2520eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen rspObj.mPlayerSubTypes, rspObj.mPlayStatusValues, 2521eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen rspObj.mFeatureBitMaskValues, rspObj.mPlayerNameList)) 2522eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen Log.e(TAG, "mediaPlayerListRsp failed!"); 2523e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2524e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "mediaPlayerListRsp: rspObj is null"); 2525eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen if (!mediaPlayerListRspNative(address, rspStatus, sUIDCounter, (byte) 0x00, 0, null, 2526eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen null, null, null, null, null)) 2527eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen Log.e(TAG, "mediaPlayerListRsp failed!"); 2528e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2529e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2530e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2531e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void folderItemsRsp(byte[] address, int rspStatus, FolderItemsRsp rspObj) { 2532e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (rspObj != null && rspStatus == AvrcpConstants.RSP_NO_ERROR) { 2533e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!getFolderItemsRspNative(address, rspStatus, sUIDCounter, rspObj.mScope, 2534e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah rspObj.mNumItems, rspObj.mFolderTypes, rspObj.mPlayable, rspObj.mItemTypes, 2535e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah rspObj.mItemUid, rspObj.mDisplayNames, rspObj.mAttributesNum, 2536e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah rspObj.mAttrIds, rspObj.mAttrValues)) 2537e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getFolderItemsRspNative failed!"); 2538e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2539e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "folderItemsRsp: rspObj is null or rspStatus is error:" + rspStatus); 2540e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!getFolderItemsRspNative(address, rspStatus, sUIDCounter, (byte) 0x00, 0, 2541e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah null, null, null, null, null, null, null, null)) 2542e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getFolderItemsRspNative failed!"); 2543e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2544e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2545e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2546e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2547e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void changePathRsp(byte[] address, int rspStatus, int numItems) { 2548e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!changePathRspNative(address, rspStatus, numItems)) 2549e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "changePathRspNative failed!"); 2550e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2551e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2552e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void getItemAttrRsp(byte[] address, int rspStatus, ItemAttrRsp rspObj) { 2553e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (rspObj != null && rspStatus == AvrcpConstants.RSP_NO_ERROR) { 2554e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!getItemAttrRspNative(address, rspStatus, rspObj.mNumAttr, 2555e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah rspObj.mAttributesIds, rspObj.mAttributesArray)) 2556e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getItemAttrRspNative failed!"); 2557e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } else { 2558e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getItemAttrRsp: rspObj is null or rspStatus is error:" + rspStatus); 2559e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!getItemAttrRspNative(address, rspStatus, (byte) 0x00, null, null)) 2560e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getItemAttrRspNative failed!"); 2561e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2562e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2563e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2564e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void playItemRsp(byte[] address, int rspStatus) { 2565e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!playItemRspNative(address, rspStatus)) { 2566e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "playItemRspNative failed!"); 2567e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2568e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2569e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2570e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void getTotalNumOfItemsRsp(byte[] address, int rspStatus, int uidCounter, 2571e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int numItems) { 2572e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!getTotalNumOfItemsRspNative(address, rspStatus, sUIDCounter, numItems)) { 2573e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "getTotalNumOfItemsRspNative failed!"); 2574e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2575e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2576e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 257705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public void addrPlayerChangedRsp(int type, int playerId, int uidCounter) { 2578e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspAddrPlayerChangedNative(type, playerId, sUIDCounter)) { 2579e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "registerNotificationRspAddrPlayerChangedNative failed!"); 2580e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2581e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2582e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2583e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void avalPlayerChangedRsp(byte[] address, int type) { 2584e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspAvalPlayerChangedNative(type)) { 2585e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "registerNotificationRspAvalPlayerChangedNative failed!"); 2586e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2587e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2588e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2589c960943641d79069f2f8177c0a3c378d8337b9c2Ajay Panicker public void uidsChangedRsp(int type) { 2590e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspUIDsChangedNative(type, sUIDCounter)) { 2591e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "registerNotificationRspUIDsChangedNative failed!"); 2592e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2593e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2594e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2595e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void nowPlayingChangedRsp(int type) { 259605723ee9e6619814876a6cce5004d11b38c3f648Ajay Panicker if (mNowPlayingListChangedNT != AvrcpConstants.NOTIFICATION_TYPE_INTERIM) { 259705723ee9e6619814876a6cce5004d11b38c3f648Ajay Panicker if (DEBUG) Log.d(TAG, "NowPlayingListChanged: Not registered or requesting."); 259805723ee9e6619814876a6cce5004d11b38c3f648Ajay Panicker return; 259905723ee9e6619814876a6cce5004d11b38c3f648Ajay Panicker } 260005723ee9e6619814876a6cce5004d11b38c3f648Ajay Panicker 2601e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspNowPlayingChangedNative(type)) { 2602e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "registerNotificationRspNowPlayingChangedNative failed!"); 2603e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 260405723ee9e6619814876a6cce5004d11b38c3f648Ajay Panicker mNowPlayingListChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; 2605e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2606e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2607e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public void trackChangedRsp(int type, byte[] uid) { 2608e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah if (!registerNotificationRspTrackChangeNative(type, uid)) { 2609e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah Log.e(TAG, "registerNotificationRspTrackChangeNative failed!"); 2610e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2611e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2612e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2613e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2614e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah /* getters for some private variables */ 2615e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah public AvrcpBrowseManager getAvrcpBrowseManager() { 2616e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah return mAvrcpBrowseManager; 2617e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah } 2618e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 261905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen /* PASSTHROUGH COMMAND MANAGEMENT */ 262005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 262105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen void handlePassthroughCmd(int op, int state) { 262205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen int code = avrcpPassthroughToKeyCode(op); 262305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (code == KeyEvent.KEYCODE_UNKNOWN) { 262405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.w(TAG, "Ignoring passthrough of unknown key " + op + " state " + state); 262505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return; 262605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 262705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen int action = KeyEvent.ACTION_DOWN; 262805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (state == AvrcpConstants.KEY_STATE_RELEASE) action = KeyEvent.ACTION_UP; 262905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen KeyEvent event = new KeyEvent(action, code); 263005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (!KeyEvent.isMediaKey(code)) { 263105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.w(TAG, "Passthrough non-media key " + op + " (code " + code + ") state " + state); 263205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 263385aee8a39e8ca855b1b42724bca710aa1bfa6a7fAjay Panicker 263405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mMediaSessionManager.dispatchMediaKeyEvent(event); 263505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen addKeyPending(event); 263605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 263705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 263805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private int avrcpPassthroughToKeyCode(int operation) { 263905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen switch (operation) { 264005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_UP: 264105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_UP; 264205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_DOWN: 264305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_DOWN; 264405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_LEFT: 264505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_LEFT; 264605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_RIGHT: 264705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_RIGHT; 264805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_RIGHT_UP: 264905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_UP_RIGHT; 265005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_RIGHT_DOWN: 265105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_DOWN_RIGHT; 265205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_LEFT_UP: 265305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_UP_LEFT; 265405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_LEFT_DOWN: 265505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_DPAD_DOWN_LEFT; 265605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_0: 265705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_0; 265805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_1: 265905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_1; 266005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_2: 266105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_2; 266205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_3: 266305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_3; 266405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_4: 266505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_4; 266605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_5: 266705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_5; 266805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_6: 266905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_6; 267005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_7: 267105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_7; 267205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_8: 267305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_8; 267405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_9: 267505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_9; 267605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_DOT: 267705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_DOT; 267805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_ENTER: 267905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_NUMPAD_ENTER; 268005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_CLEAR: 268105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_CLEAR; 268205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_CHAN_UP: 268305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_CHANNEL_UP; 268405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_CHAN_DOWN: 268505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_CHANNEL_DOWN; 268605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_PREV_CHAN: 268705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_LAST_CHANNEL; 268805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_INPUT_SEL: 268905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_TV_INPUT; 269005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_DISP_INFO: 269105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_INFO; 269205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_HELP: 269305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_HELP; 269405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_PAGE_UP: 269505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_PAGE_UP; 269605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_PAGE_DOWN: 269705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_PAGE_DOWN; 269805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_POWER: 269905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_POWER; 270005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_VOL_UP: 270105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_VOLUME_UP; 270205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_VOL_DOWN: 270305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_VOLUME_DOWN; 270405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_MUTE: 270505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MUTE; 270605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_PLAY: 270705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_PLAY; 270805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_STOP: 270905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_STOP; 271005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_PAUSE: 271105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_PAUSE; 271205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_RECORD: 271305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_RECORD; 271405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_REWIND: 271505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_REWIND; 271605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_FAST_FOR: 271705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_FAST_FORWARD; 271805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_EJECT: 271905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_EJECT; 272005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_FORWARD: 272105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_NEXT; 272205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_BACKWARD: 272305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_MEDIA_PREVIOUS; 272405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_F1: 272505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_F1; 272605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_F2: 272705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_F2; 272805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_F3: 272905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_F3; 273005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_F4: 273105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_F4; 273205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_F5: 273305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_F5; 273405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen // Fallthrough for all unknown key mappings 273505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_SELECT: 273605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_ROOT_MENU: 273705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_SETUP_MENU: 273805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_CONT_MENU: 273905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_FAV_MENU: 274005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_EXIT: 274105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_SOUND_SEL: 274205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_ANGLE: 274305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_SUBPICT: 274405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen case BluetoothAvrcp.PASSTHROUGH_ID_VENDOR: 274505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen default: 274605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return KeyEvent.KEYCODE_UNKNOWN; 274705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 274805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 274905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 275005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private void addKeyPending(KeyEvent event) { 275178d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen mPassthroughPending.add(new MediaKeyLog(System.currentTimeMillis(), event)); 275205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 275305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 275405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private void recordKeyDispatched(KeyEvent event, String packageName) { 275505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen long time = System.currentTimeMillis(); 275605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Log.v(TAG, "recordKeyDispatched: " + event + " dispatched to " + packageName); 275778d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen setAddressedMediaSessionPackage(packageName); 275805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen synchronized (mPassthroughPending) { 275905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen Iterator<MediaKeyLog> pending = mPassthroughPending.iterator(); 276005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen while (pending.hasNext()) { 276105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen MediaKeyLog log = pending.next(); 276205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen if (log.addDispatch(time, event, packageName)) { 276305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mPassthroughDispatched++; 276405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen mPassthroughLogs.add(log); 276505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen pending.remove(); 276605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen return; 276705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 276805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 276978d53f7d7133cb5a32e1160e1c1a23f2e8174978Marie Janssen Log.w(TAG, "recordKeyDispatch: can't find matching log!"); 277005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 277105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 277205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 277305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen private final MediaSessionManager.Callback mButtonDispatchCallback = 277405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen new MediaSessionManager.Callback() { 277505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen @Override 277605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public void onMediaKeyEventDispatched(KeyEvent event, MediaSession.Token token) { 277705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen // Get the package name 277805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen android.media.session.MediaController controller = 277905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen new android.media.session.MediaController(mContext, token); 278005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen String targetPackage = controller.getPackageName(); 278105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen recordKeyDispatched(event, targetPackage); 278205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 278305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 278405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen @Override 278505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public void onMediaKeyEventDispatched(KeyEvent event, ComponentName receiver) { 278605df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen recordKeyDispatched(event, receiver.getPackageName()); 278705df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 278805df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 278905df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen @Override 279005df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public void onAddressedPlayerChanged(MediaSession.Token token) { 279105df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen setActiveMediaSession(token); 279205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 279305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 279405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen @Override 279505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen public void onAddressedPlayerChanged(ComponentName receiver) { 279641527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen if (receiver == null) { 279741527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen // No active sessions, and no session to revive, give up. 279841527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen setAddressedMediaSessionPackage(null); 279941527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen return; 280041527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen } 280141527b2493a4ea59933c7cd4f8d1c761598509d8Marie Janssen // We can still get a passthrough which will revive this player. 280205df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen setAddressedMediaSessionPackage(receiver.getPackageName()); 280305df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen } 280405df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen }; 280505df242b454cbe62dab2bfaa07ab2b236ed00f67Marie Janssen 2806e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // Do not modify without updating the HAL bt_rc.h files. 2807e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2808e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // match up with btrc_play_status_t enum of bt_rc.h 280959b1c77f883bd97816332046a3a98be4431cceddMarie Janssen final static byte PLAYSTATUS_STOPPED = 0; 281059b1c77f883bd97816332046a3a98be4431cceddMarie Janssen final static byte PLAYSTATUS_PLAYING = 1; 281159b1c77f883bd97816332046a3a98be4431cceddMarie Janssen final static byte PLAYSTATUS_PAUSED = 2; 281259b1c77f883bd97816332046a3a98be4431cceddMarie Janssen final static byte PLAYSTATUS_FWD_SEEK = 3; 281359b1c77f883bd97816332046a3a98be4431cceddMarie Janssen final static byte PLAYSTATUS_REV_SEEK = 4; 281459b1c77f883bd97816332046a3a98be4431cceddMarie Janssen final static byte PLAYSTATUS_ERROR = (byte) 255; 2815e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2816e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // match up with btrc_media_attr_t enum of bt_rc.h 2817e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_TITLE = 1; 2818e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_ARTIST = 2; 2819e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_ALBUM = 3; 2820e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_TRACK_NUM = 4; 2821e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_NUM_TRACKS = 5; 2822e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_GENRE = 6; 2823e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int MEDIA_ATTR_PLAYING_TIME = 7; 2824e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah 2825e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah // match up with btrc_event_id_t enum of bt_rc.h 2826e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_PLAY_STATUS_CHANGED = 1; 2827e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_TRACK_CHANGED = 2; 2828e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_TRACK_REACHED_END = 3; 2829e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_TRACK_REACHED_START = 4; 2830e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_PLAY_POS_CHANGED = 5; 2831e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_BATT_STATUS_CHANGED = 6; 2832e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_SYSTEM_STATUS_CHANGED = 7; 2833e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_APP_SETTINGS_CHANGED = 8; 2834e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVENT_NOW_PLAYING_CONTENT_CHANGED = 9; 2835e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_AVBL_PLAYERS_CHANGED = 0xa; 2836e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVT_ADDR_PLAYER_CHANGED = 0xb; 2837e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah final static int EVENT_UIDS_CHANGED = 0x0c; 2838c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 2839c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native static void classInitNative(); 2840c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native void initNative(); 2841c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native void cleanupNative(); 2842e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean getPlayStatusRspNative(byte[] address, int playStatus, int songLen, 2843e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int songPos); 2844e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean getElementAttrRspNative(byte[] address, byte numAttr, int[] attrIds, 2845e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String[] textArray); 2846c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native boolean registerNotificationRspPlayStatusNative(int type, int playStatus); 2847c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native boolean registerNotificationRspTrackChangeNative(int type, byte[] track); 2848aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private native boolean registerNotificationRspPlayPosNative(int type, int playPos); 284917675906064bb72fdcca75baa56cdf8bb8968d01John Du private native boolean setVolumeNative(int volume); 28505c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta private native boolean sendPassThroughCommandNative(int keyCode, int keyState); 2851e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean setAddressedPlayerRspNative(byte[] address, int rspStatus); 2852e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean setBrowsedPlayerRspNative(byte[] address, int rspStatus, byte depth, 2853e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int numItems, String[] textArray); 2854e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean mediaPlayerListRspNative(byte[] address, int rsStatus, int uidCounter, 2855eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen byte item_type, int numItems, int[] playerIds, byte[] playerTypes, int[] playerSubTypes, 2856eef486e7e3145cc7b302ee1b00bbd317481cdabdMarie Janssen byte[] playStatusValues, short[] featureBitMaskValues, String[] textArray); 2857e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean getFolderItemsRspNative(byte[] address, int rspStatus, short uidCounter, 2858e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte scope, int numItems, byte[] folderTypes, byte[] playable, byte[] itemTypes, 2859e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah byte[] itemUidArray, String[] textArray, int[] AttributesNum, int[] AttributesIds, 2860e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah String[] attributesArray); 2861e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean changePathRspNative(byte[] address, int rspStatus, int numItems); 2862e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean getItemAttrRspNative(byte[] address, int rspStatus, byte numAttr, 2863e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int[] attrIds, String[] textArray); 2864e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean playItemRspNative(byte[] address, int rspStatus); 2865e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean getTotalNumOfItemsRspNative(byte[] address, int rspStatus, 2866e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int uidCounter, int numItems); 2867e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean searchRspNative(byte[] address, int rspStatus, int uidCounter, 2868e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int numItems); 2869e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean addToNowPlayingRspNative(byte[] address, int rspStatus); 2870e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean registerNotificationRspAddrPlayerChangedNative(int type, 2871e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah int playerId, int uidCounter); 2872e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean registerNotificationRspAvalPlayerChangedNative(int type); 2873e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean registerNotificationRspUIDsChangedNative(int type, int uidCounter); 2874e90c830b72f97189935e99e9e4f5a0c4f216ba72Avish Shah private native boolean registerNotificationRspNowPlayingChangedNative(int type); 28755c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta 2876c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 2877