Avrcp.java revision 2fc493d0ea2b504df25d783a488dfadfe301329e
1c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu/* 2c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * Copyright (C) 2012 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 19ace834feb02adabd61f628c4471147aea02d939cJohn Duimport java.util.Timer; 20ace834feb02adabd61f628c4471147aea02d939cJohn Duimport java.util.TimerTask; 21ace834feb02adabd61f628c4471147aea02d939cJohn Du 22188f205b5f093850d4cc627917a21204be36c56aZhihai Xuimport android.bluetooth.BluetoothA2dp; 23066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodimport android.bluetooth.BluetoothAvrcp; 24c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.content.Context; 25aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xuimport android.content.Intent; 2611798b011c962b602217b479130d413f3b30f19aLiejun Taoimport android.content.res.Resources; 2711798b011c962b602217b479130d413f3b30f19aLiejun Taoimport android.content.SharedPreferences; 28c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.graphics.Bitmap; 29c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.media.AudioManager; 30c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.media.MediaMetadataRetriever; 312fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssenimport android.media.MediaMetadata; 322fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssenimport android.media.session.MediaController; 332fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssenimport android.media.session.MediaSessionManager; 342fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssenimport android.media.session.PlaybackState; 35c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.Bundle; 36c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.Handler; 37c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.HandlerThread; 38c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.Looper; 39c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.Message; 40c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.ParcelUuid; 41c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.PowerManager; 42c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.PowerManager.WakeLock; 43c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.RemoteException; 44c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.ServiceManager; 45aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xuimport android.os.SystemClock; 46c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.util.Log; 47881675b362bde18acbbcf69c513175addca4a8baZhenye Zhuimport android.view.KeyEvent; 486e29e12add362546784126119f26f04fc760f021RoboErik 4911798b011c962b602217b479130d413f3b30f19aLiejun Taoimport com.android.bluetooth.R; 50c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport com.android.bluetooth.btservice.AdapterService; 51c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport com.android.bluetooth.btservice.ProfileService; 52aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xuimport com.android.bluetooth.Utils; 53c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport com.android.internal.util.IState; 54c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport com.android.internal.util.State; 55c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport com.android.internal.util.StateMachine; 566e29e12add362546784126119f26f04fc760f021RoboErik 57c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport java.lang.ref.WeakReference; 58c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport java.util.ArrayList; 5911798b011c962b602217b479130d413f3b30f19aLiejun Taoimport java.util.HashMap; 60c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport java.util.List; 61c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport java.util.Set; 62c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu/** 63c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * support Bluetooth AVRCP profile. 64c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * support metadata, play status and event notification 65c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu */ 66066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodpublic final class Avrcp { 678e0d927632cce4ad53df85fb7627b915c5fbd64bRoboErik private static final boolean DEBUG = false; 68c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private static final String TAG = "Avrcp"; 6911798b011c962b602217b479130d413f3b30f19aLiejun Tao private static final String ABSOLUTE_VOLUME_BLACKLIST = "absolute_volume_blacklist"; 70c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 71c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private Context mContext; 72c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private final AudioManager mAudioManager; 73c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private AvrcpMessageHandler mHandler; 742fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen private MediaSessionManager mMediaSessionManager; 752fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen private MediaSessionChangeListener mSessionChangeListener; 762fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen private MediaController mMediaController; 772fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen private MediaControllerListener mMediaControllerCb; 78c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private Metadata mMetadata; 79c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private int mTransportControlFlags; 802fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen private PlaybackState mCurrentPlayState; 81c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private int mPlayStatusChangedNT; 82c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private int mTrackChangedNT; 83c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private long mTrackNumber; 84aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mCurrentPosMs; 85aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mPlayStartTimeMs; 86aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mSongLengthMs; 87aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mPlaybackIntervalMs; 88aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private int mPlayPosChangedNT; 89aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mNextPosMs; 90aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mPrevPosMs; 91ace834feb02adabd61f628c4471147aea02d939cJohn Du private long mSkipStartTime; 9217675906064bb72fdcca75baa56cdf8bb8968d01John Du private int mFeatures; 9311798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mRemoteVolume; 9411798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mLastRemoteVolume; 9511798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mInitialRemoteVolume; 9611798b011c962b602217b479130d413f3b30f19aLiejun Tao 9711798b011c962b602217b479130d413f3b30f19aLiejun Tao /* Local volume in audio index 0-15 */ 9811798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mLocalVolume; 9911798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mLastLocalVolume; 10011798b011c962b602217b479130d413f3b30f19aLiejun Tao private int mAbsVolThreshold; 10111798b011c962b602217b479130d413f3b30f19aLiejun Tao 10211798b011c962b602217b479130d413f3b30f19aLiejun Tao private String mAddress; 10311798b011c962b602217b479130d413f3b30f19aLiejun Tao private HashMap<Integer, Integer> mVolumeMapping; 10411798b011c962b602217b479130d413f3b30f19aLiejun Tao 10517675906064bb72fdcca75baa56cdf8bb8968d01John Du private int mLastDirection; 1062e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie private final int mVolumeStep; 1072e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie private final int mAudioStreamMax; 10811798b011c962b602217b479130d413f3b30f19aLiejun Tao private boolean mVolCmdAdjustInProgress; 10911798b011c962b602217b479130d413f3b30f19aLiejun Tao private boolean mVolCmdSetInProgress; 11017675906064bb72fdcca75baa56cdf8bb8968d01John Du private int mAbsVolRetryTimes; 11119e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu private int mSkipAmount; 112ace834feb02adabd61f628c4471147aea02d939cJohn Du 11317675906064bb72fdcca75baa56cdf8bb8968d01John Du /* BTRC features */ 11417675906064bb72fdcca75baa56cdf8bb8968d01John Du public static final int BTRC_FEAT_METADATA = 0x01; 11517675906064bb72fdcca75baa56cdf8bb8968d01John Du public static final int BTRC_FEAT_ABSOLUTE_VOLUME = 0x02; 11617675906064bb72fdcca75baa56cdf8bb8968d01John Du public static final int BTRC_FEAT_BROWSE = 0x04; 11717675906064bb72fdcca75baa56cdf8bb8968d01John Du 11817675906064bb72fdcca75baa56cdf8bb8968d01John Du /* AVRC response codes, from avrc_defs */ 11917675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_NOT_IMPL = 8; 12017675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_ACCEPT = 9; 12117675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_REJ = 10; 12217675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_IN_TRANS = 11; 12317675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_IMPL_STBL = 12; 12417675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_CHANGED = 13; 12517675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_INTERIM = 15; 12617675906064bb72fdcca75baa56cdf8bb8968d01John Du 12717675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MESSAGE_GET_RC_FEATURES = 1; 12817675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MESSAGE_GET_PLAY_STATUS = 2; 12917675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MESSAGE_GET_ELEM_ATTRS = 3; 13017675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MESSAGE_REGISTER_NOTIFICATION = 4; 13117675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MESSAGE_PLAY_INTERVAL_TIMEOUT = 5; 13217675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MESSAGE_VOLUME_CHANGED = 6; 13317675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MESSAGE_ADJUST_VOLUME = 7; 13417675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MESSAGE_SET_ABSOLUTE_VOLUME = 8; 13517675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MESSAGE_ABS_VOL_TIMEOUT = 9; 13617675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MESSAGE_FAST_FORWARD = 10; 13717675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MESSAGE_REWIND = 11; 13819e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu private static final int MESSAGE_CHANGE_PLAY_POS = 12; 139188f205b5f093850d4cc627917a21204be36c56aZhihai Xu private static final int MESSAGE_SET_A2DP_AUDIO_STATE = 13; 140c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 141ace834feb02adabd61f628c4471147aea02d939cJohn Du private static final int BUTTON_TIMEOUT_TIME = 2000; 142ace834feb02adabd61f628c4471147aea02d939cJohn Du private static final int BASE_SKIP_AMOUNT = 2000; 143ace834feb02adabd61f628c4471147aea02d939cJohn Du private static final int KEY_STATE_PRESS = 1; 144ace834feb02adabd61f628c4471147aea02d939cJohn Du private static final int KEY_STATE_RELEASE = 0; 145ace834feb02adabd61f628c4471147aea02d939cJohn Du private static final int SKIP_PERIOD = 400; 146ace834feb02adabd61f628c4471147aea02d939cJohn Du private static final int SKIP_DOUBLE_INTERVAL = 3000; 14719e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu private static final long MAX_MULTIPLIER_VALUE = 128L; 14817675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int CMD_TIMEOUT_DELAY = 2000; 14917675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MAX_ERROR_RETRY_TIMES = 3; 15017675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRCP_MAX_VOL = 127; 15117675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRCP_BASE_VOLUME_STEP = 1; 152ace834feb02adabd61f628c4471147aea02d939cJohn Du 153c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu static { 154c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu classInitNative(); 155c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 156c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 157c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private Avrcp(Context context) { 158c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mMetadata = new Metadata(); 1592fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mCurrentPlayState = new PlaybackState.Builder().setState(PlaybackState.STATE_NONE, -1L, 0.0f).build(); 160c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mPlayStatusChangedNT = NOTIFICATION_TYPE_CHANGED; 161c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mTrackChangedNT = NOTIFICATION_TYPE_CHANGED; 16279d176b0f3d6cb33c7e52be6641fd4808ba87e93Zhihai Xu mTrackNumber = -1L; 1632fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mCurrentPosMs = PlaybackState.PLAYBACK_POSITION_UNKNOWN; 164aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPlayStartTimeMs = -1L; 165aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mSongLengthMs = 0L; 166aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPlaybackIntervalMs = 0L; 167aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPlayPosChangedNT = NOTIFICATION_TYPE_CHANGED; 16817675906064bb72fdcca75baa56cdf8bb8968d01John Du mFeatures = 0; 16911798b011c962b602217b479130d413f3b30f19aLiejun Tao mRemoteVolume = -1; 17011798b011c962b602217b479130d413f3b30f19aLiejun Tao mInitialRemoteVolume = -1; 17111798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastRemoteVolume = -1; 17217675906064bb72fdcca75baa56cdf8bb8968d01John Du mLastDirection = 0; 17311798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = false; 17411798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = false; 17517675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes = 0; 17611798b011c962b602217b479130d413f3b30f19aLiejun Tao mLocalVolume = -1; 17711798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = -1; 17811798b011c962b602217b479130d413f3b30f19aLiejun Tao mAbsVolThreshold = 0; 17911798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolumeMapping = new HashMap<Integer, Integer>(); 180c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 181c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mContext = context; 182c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 183c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu initNative(); 184c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1852fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mMediaSessionManager = (MediaSessionManager) context.getSystemService(Context.MEDIA_SESSION_SERVICE); 186c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 1872e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie mAudioStreamMax = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); 1882e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie mVolumeStep = Math.max(AVRCP_BASE_VOLUME_STEP, AVRCP_MAX_VOL/mAudioStreamMax); 18911798b011c962b602217b479130d413f3b30f19aLiejun Tao Resources resources = context.getResources(); 19011798b011c962b602217b479130d413f3b30f19aLiejun Tao if (resources != null) { 19111798b011c962b602217b479130d413f3b30f19aLiejun Tao mAbsVolThreshold = resources.getInteger(R.integer.a2dp_absolute_volume_initial_threshold); 19211798b011c962b602217b479130d413f3b30f19aLiejun Tao } 193c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 194c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 195c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private void start() { 196c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu HandlerThread thread = new HandlerThread("BluetoothAvrcpHandler"); 197c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu thread.start(); 198c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Looper looper = thread.getLooper(); 199c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler = new AvrcpMessageHandler(looper); 2002fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen 2012fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mSessionChangeListener = new MediaSessionChangeListener(); 2022fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mMediaSessionManager.addOnActiveSessionsChangedListener(mSessionChangeListener, null, mHandler); 2032fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen List<MediaController> sessions = mMediaSessionManager.getActiveSessions(null); 2042fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mMediaControllerCb = new MediaControllerListener(); 2052fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen if (sessions.size() > 0) { 2062fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen updateCurrentMediaController(sessions.get(0)); 2072fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen } 208c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 209c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 210066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood public static Avrcp make(Context context) { 211c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (DEBUG) Log.v(TAG, "make"); 212c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Avrcp ar = new Avrcp(context); 213c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ar.start(); 214c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return ar; 215c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 216c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 217c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public void doQuit() { 218c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.removeCallbacksAndMessages(null); 219c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Looper looper = mHandler.getLooper(); 220c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (looper != null) { 221c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu looper.quit(); 222c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 2232fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mMediaSessionManager.removeOnActiveSessionsChangedListener(mSessionChangeListener); 224c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 225c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 226c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public void cleanup() { 227c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu cleanupNative(); 22811798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolumeMapping != null) 22911798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolumeMapping.clear(); 230c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 231c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 2322fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen private class MediaControllerListener extends MediaController.Callback { 2332fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen @Override 2342fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen public void onMetadataChanged(MediaMetadata metadata) { 2352fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen Log.v(TAG, "MediaController metadata changed"); 2362fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen updateMetadata(metadata); 237c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 238c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 239bc10e7d58aa55da25c18d8056a0254a2b736146aZhihai Xu @Override 2402fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen public void onPlaybackStateChanged(PlaybackState state) { 2412fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen Log.v(TAG, "MediaController playback changed: " + state.toString()); 2422fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen updatePlayPauseState(state); 243c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 244c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 245c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu @Override 2462fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen public void onSessionDestroyed() { 2472fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen Log.v(TAG, "MediaController session destroyed"); 248c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 2492fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen } 250c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 2512fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen private class MediaSessionChangeListener implements MediaSessionManager.OnActiveSessionsChangedListener { 2522fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen public MediaSessionChangeListener() { 253c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 254c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 255c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu @Override 2562fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen public void onActiveSessionsChanged(List<MediaController> controllers) { 2572fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen Log.v(TAG, "Active sessions changed, " + controllers.size() + " sessions"); 2582fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen if (controllers.size() > 0) { 2592fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen updateCurrentMediaController(controllers.get(0)); 260c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 261c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 2622fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen } 263c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 2642fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen private void updateCurrentMediaController(MediaController controller) { 2652fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen Log.v(TAG, "Updating media controller to " + controller); 2662fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen if (mMediaController != null) { 2672fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mMediaController.unregisterCallback(mMediaControllerCb); 2682fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen } 2692fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mMediaController = controller; 2702fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen if (mMediaController == null) { 2712fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen updateMetadata(null); 2722fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen updatePlayPauseState(null); 2732fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen return; 274c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 2752fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mMediaController.registerCallback(mMediaControllerCb, mHandler); 2762fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen updateMetadata(mMediaController.getMetadata()); 2772fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen updatePlayPauseState(mMediaController.getPlaybackState()); 278c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 279c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 280c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu /** Handles Avrcp messages. */ 281c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private final class AvrcpMessageHandler extends Handler { 282c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private AvrcpMessageHandler(Looper looper) { 283c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu super(looper); 284c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 285c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 286c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu @Override 287c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public void handleMessage(Message msg) { 288c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu switch (msg.what) { 28917675906064bb72fdcca75baa56cdf8bb8968d01John Du case MESSAGE_GET_RC_FEATURES: 29017675906064bb72fdcca75baa56cdf8bb8968d01John Du String address = (String) msg.obj; 29117675906064bb72fdcca75baa56cdf8bb8968d01John Du if (DEBUG) Log.v(TAG, "MESSAGE_GET_RC_FEATURES: address="+address+ 29217675906064bb72fdcca75baa56cdf8bb8968d01John Du ", features="+msg.arg1); 29317675906064bb72fdcca75baa56cdf8bb8968d01John Du mFeatures = msg.arg1; 29411798b011c962b602217b479130d413f3b30f19aLiejun Tao mFeatures = modifyRcFeatureFromBlacklist(mFeatures, address); 29517675906064bb72fdcca75baa56cdf8bb8968d01John Du mAudioManager.avrcpSupportsAbsoluteVolume(address, isAbsoluteVolumeSupported()); 29611798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = -1; 29711798b011c962b602217b479130d413f3b30f19aLiejun Tao mRemoteVolume = -1; 29811798b011c962b602217b479130d413f3b30f19aLiejun Tao mLocalVolume = -1; 29911798b011c962b602217b479130d413f3b30f19aLiejun Tao mInitialRemoteVolume = -1; 30011798b011c962b602217b479130d413f3b30f19aLiejun Tao mAddress = address; 30111798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolumeMapping != null) 30211798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolumeMapping.clear(); 30317675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 30417675906064bb72fdcca75baa56cdf8bb8968d01John Du 305c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case MESSAGE_GET_PLAY_STATUS: 306c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (DEBUG) Log.v(TAG, "MESSAGE_GET_PLAY_STATUS"); 307aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu getPlayStatusRspNative(convertPlayStateToPlayStatus(mCurrentPlayState), 308aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu (int)mSongLengthMs, (int)getPlayPosition()); 309c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 310c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 311c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case MESSAGE_GET_ELEM_ATTRS: 312c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu String[] textArray; 313c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu int[] attrIds; 314c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu byte numAttr = (byte) msg.arg1; 315c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ArrayList<Integer> attrList = (ArrayList<Integer>) msg.obj; 31665e7943d098113c5aa56e9822b68f0c51c6dbe36Marie Janssen Log.v(TAG, "MESSAGE_GET_ELEM_ATTRS:numAttr=" + numAttr); 317c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu attrIds = new int[numAttr]; 318c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu textArray = new String[numAttr]; 319c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu for (int i = 0; i < numAttr; ++i) { 320c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu attrIds[i] = attrList.get(i).intValue(); 321c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu textArray[i] = getAttributeString(attrIds[i]); 322c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 323c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu getElementAttrRspNative(numAttr, attrIds, textArray); 324c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 32565e7943d098113c5aa56e9822b68f0c51c6dbe36Marie Janssen 326c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case MESSAGE_REGISTER_NOTIFICATION: 327c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (DEBUG) Log.v(TAG, "MESSAGE_REGISTER_NOTIFICATION:event=" + msg.arg1 + 328c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu " param=" + msg.arg2); 329c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu processRegisterNotification(msg.arg1, msg.arg2); 330c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 331c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 332aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu case MESSAGE_PLAY_INTERVAL_TIMEOUT: 333aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu if (DEBUG) Log.v(TAG, "MESSAGE_PLAY_INTERVAL_TIMEOUT"); 334aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPlayPosChangedNT = NOTIFICATION_TYPE_CHANGED; 335aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu registerNotificationRspPlayPosNative(mPlayPosChangedNT, (int)getPlayPosition()); 336aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu break; 337aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 33817675906064bb72fdcca75baa56cdf8bb8968d01John Du case MESSAGE_VOLUME_CHANGED: 33911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (!isAbsoluteVolumeSupported()) { 34011798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.v(TAG, "ignore MESSAGE_VOLUME_CHANGED"); 34111798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 34211798b011c962b602217b479130d413f3b30f19aLiejun Tao } 34311798b011c962b602217b479130d413f3b30f19aLiejun Tao 3445c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta if (DEBUG) Log.v(TAG, "MESSAGE_VOLUME_CHANGED: volume=" + ((byte)msg.arg1 & 0x7f) 3455c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta + " ctype=" + msg.arg2); 34617675906064bb72fdcca75baa56cdf8bb8968d01John Du 34711798b011c962b602217b479130d413f3b30f19aLiejun Tao 34811798b011c962b602217b479130d413f3b30f19aLiejun Tao boolean volAdj = false; 34917675906064bb72fdcca75baa56cdf8bb8968d01John Du if (msg.arg2 == AVRC_RSP_ACCEPT || msg.arg2 == AVRC_RSP_REJ) { 35011798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolCmdAdjustInProgress == false && mVolCmdSetInProgress == false) { 35117675906064bb72fdcca75baa56cdf8bb8968d01John Du Log.e(TAG, "Unsolicited response, ignored"); 35217675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 35317675906064bb72fdcca75baa56cdf8bb8968d01John Du } 35417675906064bb72fdcca75baa56cdf8bb8968d01John Du removeMessages(MESSAGE_ABS_VOL_TIMEOUT); 35511798b011c962b602217b479130d413f3b30f19aLiejun Tao 35611798b011c962b602217b479130d413f3b30f19aLiejun Tao volAdj = mVolCmdAdjustInProgress; 35711798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = false; 35811798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = false; 35917675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes = 0; 36017675906064bb72fdcca75baa56cdf8bb8968d01John Du } 36111798b011c962b602217b479130d413f3b30f19aLiejun Tao 36211798b011c962b602217b479130d413f3b30f19aLiejun Tao byte absVol = (byte)((byte)msg.arg1 & 0x7f); // discard MSB as it is RFD 36311798b011c962b602217b479130d413f3b30f19aLiejun Tao // convert remote volume to local volume 36411798b011c962b602217b479130d413f3b30f19aLiejun Tao int volIndex = convertToAudioStreamVolume(absVol); 36511798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mInitialRemoteVolume == -1) { 36611798b011c962b602217b479130d413f3b30f19aLiejun Tao mInitialRemoteVolume = absVol; 36711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mAbsVolThreshold > 0 && mAbsVolThreshold < mAudioStreamMax && volIndex > mAbsVolThreshold) { 36811798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.v(TAG, "remote inital volume too high " + volIndex + ">" + mAbsVolThreshold); 36911798b011c962b602217b479130d413f3b30f19aLiejun Tao Message msg1 = mHandler.obtainMessage(MESSAGE_SET_ABSOLUTE_VOLUME, mAbsVolThreshold , 0); 37011798b011c962b602217b479130d413f3b30f19aLiejun Tao mHandler.sendMessage(msg1); 37111798b011c962b602217b479130d413f3b30f19aLiejun Tao mRemoteVolume = absVol; 37211798b011c962b602217b479130d413f3b30f19aLiejun Tao mLocalVolume = volIndex; 37311798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 37411798b011c962b602217b479130d413f3b30f19aLiejun Tao } 37511798b011c962b602217b479130d413f3b30f19aLiejun Tao } 37611798b011c962b602217b479130d413f3b30f19aLiejun Tao 3772fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen if (mLocalVolume != volIndex && (msg.arg2 == AVRC_RSP_ACCEPT || 3782fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen msg.arg2 == AVRC_RSP_CHANGED || 3792fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen msg.arg2 == AVRC_RSP_INTERIM)) { 38011798b011c962b602217b479130d413f3b30f19aLiejun Tao /* If the volume has successfully changed */ 38111798b011c962b602217b479130d413f3b30f19aLiejun Tao mLocalVolume = volIndex; 38211798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mLastLocalVolume != -1 && msg.arg2 == AVRC_RSP_ACCEPT) { 38311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mLastLocalVolume != volIndex) { 38411798b011c962b602217b479130d413f3b30f19aLiejun Tao /* remote volume changed more than requested due to 38511798b011c962b602217b479130d413f3b30f19aLiejun Tao * local and remote has different volume steps */ 38611798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "Remote returned volume does not match desired volume " 38711798b011c962b602217b479130d413f3b30f19aLiejun Tao + mLastLocalVolume + " vs " 38811798b011c962b602217b479130d413f3b30f19aLiejun Tao + volIndex); 38911798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = mLocalVolume; 39011798b011c962b602217b479130d413f3b30f19aLiejun Tao } 39111798b011c962b602217b479130d413f3b30f19aLiejun Tao } 39211798b011c962b602217b479130d413f3b30f19aLiejun Tao // remember the remote volume value, as it's the one supported by remote 39311798b011c962b602217b479130d413f3b30f19aLiejun Tao if (volAdj) { 39411798b011c962b602217b479130d413f3b30f19aLiejun Tao synchronized (mVolumeMapping) { 39511798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolumeMapping.put(volIndex, (int)absVol); 39611798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.v(TAG, "remember volume mapping " +volIndex+ "-"+absVol); 39711798b011c962b602217b479130d413f3b30f19aLiejun Tao } 39811798b011c962b602217b479130d413f3b30f19aLiejun Tao } 39911798b011c962b602217b479130d413f3b30f19aLiejun Tao 40011798b011c962b602217b479130d413f3b30f19aLiejun Tao notifyVolumeChanged(mLocalVolume); 40111798b011c962b602217b479130d413f3b30f19aLiejun Tao mRemoteVolume = absVol; 4025c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta long pecentVolChanged = ((long)absVol * 100) / 0x7f; 4035c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta Log.e(TAG, "percent volume changed: " + pecentVolChanged + "%"); 40417675906064bb72fdcca75baa56cdf8bb8968d01John Du } else if (msg.arg2 == AVRC_RSP_REJ) { 40517675906064bb72fdcca75baa56cdf8bb8968d01John Du Log.e(TAG, "setAbsoluteVolume call rejected"); 40611798b011c962b602217b479130d413f3b30f19aLiejun Tao } else if (volAdj && mLastRemoteVolume > 0 && mLastRemoteVolume < AVRCP_MAX_VOL && 4072fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mLocalVolume == volIndex && 4082fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen (msg.arg2 == AVRC_RSP_ACCEPT )) { 40911798b011c962b602217b479130d413f3b30f19aLiejun Tao /* oops, the volume is still same, remote does not like the value 41011798b011c962b602217b479130d413f3b30f19aLiejun Tao * retry a volume one step up/down */ 41111798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "Remote device didn't tune volume, let's try one more step."); 41211798b011c962b602217b479130d413f3b30f19aLiejun Tao int retry_volume = Math.min(AVRCP_MAX_VOL, 41311798b011c962b602217b479130d413f3b30f19aLiejun Tao Math.max(0, mLastRemoteVolume + mLastDirection)); 41411798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVolumeNative(retry_volume)) { 41511798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastRemoteVolume = retry_volume; 41611798b011c962b602217b479130d413f3b30f19aLiejun Tao sendMessageDelayed(obtainMessage(MESSAGE_ABS_VOL_TIMEOUT), 41711798b011c962b602217b479130d413f3b30f19aLiejun Tao CMD_TIMEOUT_DELAY); 41811798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = true; 41911798b011c962b602217b479130d413f3b30f19aLiejun Tao } 42017675906064bb72fdcca75baa56cdf8bb8968d01John Du } 42117675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 42217675906064bb72fdcca75baa56cdf8bb8968d01John Du 42317675906064bb72fdcca75baa56cdf8bb8968d01John Du case MESSAGE_ADJUST_VOLUME: 42411798b011c962b602217b479130d413f3b30f19aLiejun Tao if (!isAbsoluteVolumeSupported()) { 42511798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.v(TAG, "ignore MESSAGE_ADJUST_VOLUME"); 42611798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 42711798b011c962b602217b479130d413f3b30f19aLiejun Tao } 42811798b011c962b602217b479130d413f3b30f19aLiejun Tao 42917675906064bb72fdcca75baa56cdf8bb8968d01John Du if (DEBUG) Log.d(TAG, "MESSAGE_ADJUST_VOLUME: direction=" + msg.arg1); 43011798b011c962b602217b479130d413f3b30f19aLiejun Tao 43111798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolCmdAdjustInProgress || mVolCmdSetInProgress) { 43217675906064bb72fdcca75baa56cdf8bb8968d01John Du if (DEBUG) Log.w(TAG, "There is already a volume command in progress."); 43317675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 43417675906064bb72fdcca75baa56cdf8bb8968d01John Du } 43511798b011c962b602217b479130d413f3b30f19aLiejun Tao 43611798b011c962b602217b479130d413f3b30f19aLiejun Tao // Remote device didn't set initial volume. Let's black list it 43711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mInitialRemoteVolume == -1) { 43811798b011c962b602217b479130d413f3b30f19aLiejun Tao Log.d(TAG, "remote " + mAddress + " never tell us initial volume, black list it."); 43911798b011c962b602217b479130d413f3b30f19aLiejun Tao blackListCurrentDevice(); 44011798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 44111798b011c962b602217b479130d413f3b30f19aLiejun Tao } 44211798b011c962b602217b479130d413f3b30f19aLiejun Tao 44317675906064bb72fdcca75baa56cdf8bb8968d01John Du // Wait on verification on volume from device, before changing the volume. 44411798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mRemoteVolume != -1 && (msg.arg1 == -1 || msg.arg1 == 1)) { 44511798b011c962b602217b479130d413f3b30f19aLiejun Tao int setVol = -1; 44611798b011c962b602217b479130d413f3b30f19aLiejun Tao int targetVolIndex = -1; 44711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mLocalVolume == 0 && msg.arg1 == -1) { 44811798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.w(TAG, "No need to Vol down from 0."); 44911798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 45011798b011c962b602217b479130d413f3b30f19aLiejun Tao } 45111798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mLocalVolume == mAudioStreamMax && msg.arg1 == 1) { 45211798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.w(TAG, "No need to Vol up from max."); 45311798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 45411798b011c962b602217b479130d413f3b30f19aLiejun Tao } 45511798b011c962b602217b479130d413f3b30f19aLiejun Tao 45611798b011c962b602217b479130d413f3b30f19aLiejun Tao targetVolIndex = mLocalVolume + msg.arg1; 45711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "Adjusting volume to " + targetVolIndex); 45811798b011c962b602217b479130d413f3b30f19aLiejun Tao 45911798b011c962b602217b479130d413f3b30f19aLiejun Tao Integer i; 46011798b011c962b602217b479130d413f3b30f19aLiejun Tao synchronized (mVolumeMapping) { 46111798b011c962b602217b479130d413f3b30f19aLiejun Tao i = mVolumeMapping.get(targetVolIndex); 46211798b011c962b602217b479130d413f3b30f19aLiejun Tao } 46311798b011c962b602217b479130d413f3b30f19aLiejun Tao 46411798b011c962b602217b479130d413f3b30f19aLiejun Tao if (i != null) { 46511798b011c962b602217b479130d413f3b30f19aLiejun Tao /* if we already know this volume mapping, use it */ 46611798b011c962b602217b479130d413f3b30f19aLiejun Tao setVol = i.byteValue(); 46711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVol == mRemoteVolume) { 46811798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "got same volume from mapping for " + targetVolIndex + ", ignore."); 46911798b011c962b602217b479130d413f3b30f19aLiejun Tao setVol = -1; 47011798b011c962b602217b479130d413f3b30f19aLiejun Tao } 47111798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "set volume from mapping " + targetVolIndex + "-" + setVol); 47211798b011c962b602217b479130d413f3b30f19aLiejun Tao } 47311798b011c962b602217b479130d413f3b30f19aLiejun Tao 47411798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVol == -1) { 47511798b011c962b602217b479130d413f3b30f19aLiejun Tao /* otherwise use phone steps */ 47611798b011c962b602217b479130d413f3b30f19aLiejun Tao setVol = Math.min(AVRCP_MAX_VOL, 47711798b011c962b602217b479130d413f3b30f19aLiejun Tao convertToAvrcpVolume(Math.max(0, targetVolIndex))); 47811798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "set volume from local volume "+ targetVolIndex+"-"+ setVol); 47911798b011c962b602217b479130d413f3b30f19aLiejun Tao } 48011798b011c962b602217b479130d413f3b30f19aLiejun Tao 48117675906064bb72fdcca75baa56cdf8bb8968d01John Du if (setVolumeNative(setVol)) { 48217675906064bb72fdcca75baa56cdf8bb8968d01John Du sendMessageDelayed(obtainMessage(MESSAGE_ABS_VOL_TIMEOUT), 48317675906064bb72fdcca75baa56cdf8bb8968d01John Du CMD_TIMEOUT_DELAY); 48411798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = true; 48517675906064bb72fdcca75baa56cdf8bb8968d01John Du mLastDirection = msg.arg1; 48611798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastRemoteVolume = setVol; 48711798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = targetVolIndex; 48811798b011c962b602217b479130d413f3b30f19aLiejun Tao } else { 48911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "setVolumeNative failed"); 49017675906064bb72fdcca75baa56cdf8bb8968d01John Du } 49117675906064bb72fdcca75baa56cdf8bb8968d01John Du } else { 49217675906064bb72fdcca75baa56cdf8bb8968d01John Du Log.e(TAG, "Unknown direction in MESSAGE_ADJUST_VOLUME"); 49317675906064bb72fdcca75baa56cdf8bb8968d01John Du } 49417675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 49517675906064bb72fdcca75baa56cdf8bb8968d01John Du 49617675906064bb72fdcca75baa56cdf8bb8968d01John Du case MESSAGE_SET_ABSOLUTE_VOLUME: 49711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (!isAbsoluteVolumeSupported()) { 49811798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.v(TAG, "ignore MESSAGE_SET_ABSOLUTE_VOLUME"); 49911798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 50011798b011c962b602217b479130d413f3b30f19aLiejun Tao } 50111798b011c962b602217b479130d413f3b30f19aLiejun Tao 50217675906064bb72fdcca75baa56cdf8bb8968d01John Du if (DEBUG) Log.v(TAG, "MESSAGE_SET_ABSOLUTE_VOLUME"); 50311798b011c962b602217b479130d413f3b30f19aLiejun Tao 50411798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mVolCmdSetInProgress || mVolCmdAdjustInProgress) { 50517675906064bb72fdcca75baa56cdf8bb8968d01John Du if (DEBUG) Log.w(TAG, "There is already a volume command in progress."); 50617675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 50717675906064bb72fdcca75baa56cdf8bb8968d01John Du } 50811798b011c962b602217b479130d413f3b30f19aLiejun Tao 50911798b011c962b602217b479130d413f3b30f19aLiejun Tao // Remote device didn't set initial volume. Let's black list it 51011798b011c962b602217b479130d413f3b30f19aLiejun Tao if (mInitialRemoteVolume == -1) { 51111798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "remote " + mAddress + " never tell us initial volume, black list it."); 51211798b011c962b602217b479130d413f3b30f19aLiejun Tao blackListCurrentDevice(); 51311798b011c962b602217b479130d413f3b30f19aLiejun Tao break; 51411798b011c962b602217b479130d413f3b30f19aLiejun Tao } 51511798b011c962b602217b479130d413f3b30f19aLiejun Tao 51611798b011c962b602217b479130d413f3b30f19aLiejun Tao int avrcpVolume = convertToAvrcpVolume(msg.arg1); 51711798b011c962b602217b479130d413f3b30f19aLiejun Tao avrcpVolume = Math.min(AVRCP_MAX_VOL, Math.max(0, avrcpVolume)); 51811798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "Setting volume to " + msg.arg1+"-"+avrcpVolume); 51911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVolumeNative(avrcpVolume)) { 52017675906064bb72fdcca75baa56cdf8bb8968d01John Du sendMessageDelayed(obtainMessage(MESSAGE_ABS_VOL_TIMEOUT), CMD_TIMEOUT_DELAY); 52111798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = true; 52211798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastRemoteVolume = avrcpVolume; 52311798b011c962b602217b479130d413f3b30f19aLiejun Tao mLastLocalVolume = msg.arg1; 52411798b011c962b602217b479130d413f3b30f19aLiejun Tao } else { 52511798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.d(TAG, "setVolumeNative failed"); 52617675906064bb72fdcca75baa56cdf8bb8968d01John Du } 52717675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 52817675906064bb72fdcca75baa56cdf8bb8968d01John Du 52917675906064bb72fdcca75baa56cdf8bb8968d01John Du case MESSAGE_ABS_VOL_TIMEOUT: 53017675906064bb72fdcca75baa56cdf8bb8968d01John Du if (DEBUG) Log.v(TAG, "MESSAGE_ABS_VOL_TIMEOUT: Volume change cmd timed out."); 53111798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdAdjustInProgress = false; 53211798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = false; 53317675906064bb72fdcca75baa56cdf8bb8968d01John Du if (mAbsVolRetryTimes >= MAX_ERROR_RETRY_TIMES) { 53417675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes = 0; 53517675906064bb72fdcca75baa56cdf8bb8968d01John Du } else { 53617675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes += 1; 53711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (setVolumeNative(mLastRemoteVolume)) { 53817675906064bb72fdcca75baa56cdf8bb8968d01John Du sendMessageDelayed(obtainMessage(MESSAGE_ABS_VOL_TIMEOUT), 53917675906064bb72fdcca75baa56cdf8bb8968d01John Du CMD_TIMEOUT_DELAY); 54011798b011c962b602217b479130d413f3b30f19aLiejun Tao mVolCmdSetInProgress = true; 54117675906064bb72fdcca75baa56cdf8bb8968d01John Du } 54217675906064bb72fdcca75baa56cdf8bb8968d01John Du } 54317675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 54417675906064bb72fdcca75baa56cdf8bb8968d01John Du 545ace834feb02adabd61f628c4471147aea02d939cJohn Du case MESSAGE_FAST_FORWARD: 546ace834feb02adabd61f628c4471147aea02d939cJohn Du case MESSAGE_REWIND: 5472fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen if (msg.what == MESSAGE_FAST_FORWARD) { 5482fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen if ((mCurrentPlayState.getActions() & 5492fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen PlaybackState.ACTION_FAST_FORWARD) != 0) { 5502fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen int keyState = msg.arg1 == KEY_STATE_PRESS ? 5512fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP; 5522fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen KeyEvent keyEvent = 5532fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen new KeyEvent(keyState, KeyEvent.KEYCODE_MEDIA_FAST_FORWARD); 5542fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mMediaController.dispatchMediaButtonEvent(keyEvent); 5552fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen break; 556881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu } 5572fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen } else if ((mCurrentPlayState.getActions() & 5582fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen PlaybackState.ACTION_REWIND) != 0) { 559881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu int keyState = msg.arg1 == KEY_STATE_PRESS ? 5602fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP; 561881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu KeyEvent keyEvent = 5622fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen new KeyEvent(keyState, KeyEvent.KEYCODE_MEDIA_REWIND); 5632fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mMediaController.dispatchMediaButtonEvent(keyEvent); 564881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu break; 565881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu } 566881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu 56719e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu int skipAmount; 568ace834feb02adabd61f628c4471147aea02d939cJohn Du if (msg.what == MESSAGE_FAST_FORWARD) { 569ace834feb02adabd61f628c4471147aea02d939cJohn Du if (DEBUG) Log.v(TAG, "MESSAGE_FAST_FORWARD"); 570881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu removeMessages(MESSAGE_FAST_FORWARD); 571ace834feb02adabd61f628c4471147aea02d939cJohn Du skipAmount = BASE_SKIP_AMOUNT; 572ace834feb02adabd61f628c4471147aea02d939cJohn Du } else { 573ace834feb02adabd61f628c4471147aea02d939cJohn Du if (DEBUG) Log.v(TAG, "MESSAGE_REWIND"); 574881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu removeMessages(MESSAGE_REWIND); 575ace834feb02adabd61f628c4471147aea02d939cJohn Du skipAmount = -BASE_SKIP_AMOUNT; 576ace834feb02adabd61f628c4471147aea02d939cJohn Du } 577ace834feb02adabd61f628c4471147aea02d939cJohn Du 57819e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu if (hasMessages(MESSAGE_CHANGE_PLAY_POS) && 57919e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu (skipAmount != mSkipAmount)) { 58019e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu Log.w(TAG, "missing release button event:" + mSkipAmount); 58119e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu } 58219e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu 58319e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu if ((!hasMessages(MESSAGE_CHANGE_PLAY_POS)) || 58419e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu (skipAmount != mSkipAmount)) { 58519e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu mSkipStartTime = SystemClock.elapsedRealtime(); 58619e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu } 58719e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu 58819e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu removeMessages(MESSAGE_CHANGE_PLAY_POS); 589ace834feb02adabd61f628c4471147aea02d939cJohn Du if (msg.arg1 == KEY_STATE_PRESS) { 59019e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu mSkipAmount = skipAmount; 59119e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu changePositionBy(mSkipAmount * getSkipMultiplier()); 59219e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu Message posMsg = obtainMessage(MESSAGE_CHANGE_PLAY_POS); 59319e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu posMsg.arg1 = 1; 59419e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu sendMessageDelayed(posMsg, SKIP_PERIOD); 595ace834feb02adabd61f628c4471147aea02d939cJohn Du } 596881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu 597ace834feb02adabd61f628c4471147aea02d939cJohn Du break; 598ace834feb02adabd61f628c4471147aea02d939cJohn Du 59919e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu case MESSAGE_CHANGE_PLAY_POS: 60019e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu if (DEBUG) Log.v(TAG, "MESSAGE_CHANGE_PLAY_POS:" + msg.arg1); 60119e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu changePositionBy(mSkipAmount * getSkipMultiplier()); 60219e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu if (msg.arg1 * SKIP_PERIOD < BUTTON_TIMEOUT_TIME) { 60319e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu Message posMsg = obtainMessage(MESSAGE_CHANGE_PLAY_POS); 60419e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu posMsg.arg1 = msg.arg1 + 1; 60519e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu sendMessageDelayed(posMsg, SKIP_PERIOD); 606ace834feb02adabd61f628c4471147aea02d939cJohn Du } 607ace834feb02adabd61f628c4471147aea02d939cJohn Du break; 608188f205b5f093850d4cc627917a21204be36c56aZhihai Xu 609188f205b5f093850d4cc627917a21204be36c56aZhihai Xu case MESSAGE_SET_A2DP_AUDIO_STATE: 610188f205b5f093850d4cc627917a21204be36c56aZhihai Xu if (DEBUG) Log.v(TAG, "MESSAGE_SET_A2DP_AUDIO_STATE:" + msg.arg1); 611188f205b5f093850d4cc627917a21204be36c56aZhihai Xu updateA2dpAudioState(msg.arg1); 612188f205b5f093850d4cc627917a21204be36c56aZhihai Xu break; 613c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 614c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 615c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 616c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 617188f205b5f093850d4cc627917a21204be36c56aZhihai Xu private void updateA2dpAudioState(int state) { 618188f205b5f093850d4cc627917a21204be36c56aZhihai Xu boolean isPlaying = (state == BluetoothA2dp.STATE_PLAYING); 619188f205b5f093850d4cc627917a21204be36c56aZhihai Xu if (isPlaying != isPlayingState(mCurrentPlayState)) { 62022bad7047263a6924423d12718738fdcc7b0352cRavi Nagarajan /* if a2dp is streaming, check to make sure music is active */ 6212fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen if (isPlaying && !mAudioManager.isMusicActive()) 62222bad7047263a6924423d12718738fdcc7b0352cRavi Nagarajan return; 6232fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen PlaybackState.Builder builder = new PlaybackState.Builder(); 6242fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen if (isPlaying) { 6252fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen builder.setState(PlaybackState.STATE_PLAYING, 6262fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen PlaybackState.PLAYBACK_POSITION_UNKNOWN, 1.0f); 6272fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen } else { 6282fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen builder.setState(PlaybackState.STATE_PAUSED, 6292fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen PlaybackState.PLAYBACK_POSITION_UNKNOWN, 0.0f); 6302fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen } 6312fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen updatePlayPauseState(builder.build()); 632188f205b5f093850d4cc627917a21204be36c56aZhihai Xu } 633188f205b5f093850d4cc627917a21204be36c56aZhihai Xu } 634188f205b5f093850d4cc627917a21204be36c56aZhihai Xu 6352fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen private void updatePlayPauseState(PlaybackState state) { 636c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (DEBUG) Log.v(TAG, 6372fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen "updatePlayPauseState: old=" + mCurrentPlayState + ", state=" + state); 6382fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen if (state == null) { 6392fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen state = new PlaybackState.Builder().setState(PlaybackState.STATE_NONE, 6402fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen PlaybackState.PLAYBACK_POSITION_UNKNOWN, 0.0f).build(); 6412fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen } 6422fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen boolean oldPosValid = (mCurrentPosMs != PlaybackState.PLAYBACK_POSITION_UNKNOWN); 643c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu int oldPlayStatus = convertPlayStateToPlayStatus(mCurrentPlayState); 644c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu int newPlayStatus = convertPlayStateToPlayStatus(state); 645f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu 6462fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen if ((mCurrentPlayState.getState() == PlaybackState.STATE_PLAYING) && 6472fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen (mCurrentPlayState != state) && oldPosValid) { 648f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu mCurrentPosMs = getPlayPosition(); 649f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu } 650f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu 6512fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen if (state.getState() == PlaybackState.STATE_NONE || 6522fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen state.getState() == PlaybackState.STATE_ERROR) { 6532fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mCurrentPosMs = PlaybackState.PLAYBACK_POSITION_UNKNOWN; 6542fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen } else { 6552fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mCurrentPosMs = state.getPosition(); 656f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu } 6572fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen 6582fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen if ((state.getState() == PlaybackState.STATE_PLAYING) && 6592fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen (mCurrentPlayState.getState() != PlaybackState.STATE_PLAYING)) { 660aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPlayStartTimeMs = SystemClock.elapsedRealtime(); 661aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 6622fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen 663aa6c1cb7f08a5d1fe2c878b587c62cf4dbb6ee8fZhihai Xu mCurrentPlayState = state; 664aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 6652fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen boolean newPosValid = mCurrentPosMs != PlaybackState.PLAYBACK_POSITION_UNKNOWN; 666f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu long playPosition = getPlayPosition(); 6672fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen 668aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mHandler.removeMessages(MESSAGE_PLAY_INTERVAL_TIMEOUT); 669aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu /* need send play position changed notification when play status is changed */ 670aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu if ((mPlayPosChangedNT == NOTIFICATION_TYPE_INTERIM) && 6712fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen ((oldPlayStatus != newPlayStatus) || (oldPosValid != newPosValid) || 6722fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen (newPosValid && ((playPosition >= mNextPosMs) || (playPosition <= mPrevPosMs))))) { 673aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPlayPosChangedNT = NOTIFICATION_TYPE_CHANGED; 674f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu registerNotificationRspPlayPosNative(mPlayPosChangedNT, (int)playPosition); 675aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 676aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu if ((mPlayPosChangedNT == NOTIFICATION_TYPE_INTERIM) && newPosValid && 6772fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen (state.getState() == PlaybackState.STATE_PLAYING)) { 678aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu Message msg = mHandler.obtainMessage(MESSAGE_PLAY_INTERVAL_TIMEOUT); 679f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu mHandler.sendMessageDelayed(msg, mNextPosMs - playPosition); 680aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 681aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 682c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if ((mPlayStatusChangedNT == NOTIFICATION_TYPE_INTERIM) && (oldPlayStatus != newPlayStatus)) { 683c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mPlayStatusChangedNT = NOTIFICATION_TYPE_CHANGED; 684c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu registerNotificationRspPlayStatusNative(mPlayStatusChangedNT, newPlayStatus); 685c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 686c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 687c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 688c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private void updateTransportControls(int transportControlFlags) { 689c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mTransportControlFlags = transportControlFlags; 690c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 691c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 692c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu class Metadata { 693c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private String artist; 694c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private String trackTitle; 695c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private String albumTitle; 696c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 697c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public Metadata() { 698c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu artist = null; 699c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu trackTitle = null; 700c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu albumTitle = null; 701c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 702c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 703c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public String toString() { 704c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return "Metadata[artist=" + artist + " trackTitle=" + trackTitle + " albumTitle=" + 7052fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen albumTitle + "]"; 706c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 707c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 708c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 7092fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen private void updateMetadata(MediaMetadata data) { 710c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu String oldMetadata = mMetadata.toString(); 7112fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen if (data == null) { 7122fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mMetadata = new Metadata(); 7132fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mSongLengthMs = 0L; 7142fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen } else { 7152fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mMetadata.artist = data.getString(MediaMetadata.METADATA_KEY_ARTIST); 7162fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mMetadata.trackTitle = data.getString(MediaMetadata.METADATA_KEY_TITLE); 7172fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mMetadata.albumTitle = data.getString(MediaMetadata.METADATA_KEY_ALBUM); 7182fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mSongLengthMs = data.getLong(MediaMetadata.METADATA_KEY_DURATION); 7192fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen } 720c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!oldMetadata.equals(mMetadata.toString())) { 72165e7943d098113c5aa56e9822b68f0c51c6dbe36Marie Janssen Log.v(TAG, "Metadata Changed to " + mMetadata.toString()); 722c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mTrackNumber++; 723c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (mTrackChangedNT == NOTIFICATION_TYPE_INTERIM) { 724c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mTrackChangedNT = NOTIFICATION_TYPE_CHANGED; 725c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sendTrackChangedRsp(); 726c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 727aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 7282fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen if (mCurrentPosMs != PlaybackState.PLAYBACK_POSITION_UNKNOWN && 7292fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen isPlayingState(mCurrentPlayState)) { 7302fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mPlayStartTimeMs = SystemClock.elapsedRealtime(); 731aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 732aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu /* need send play position changed notification when track is changed */ 733aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu if (mPlayPosChangedNT == NOTIFICATION_TYPE_INTERIM) { 734aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPlayPosChangedNT = NOTIFICATION_TYPE_CHANGED; 735aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu registerNotificationRspPlayPosNative(mPlayPosChangedNT, 7362fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen (int)getPlayPosition()); 737aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mHandler.removeMessages(MESSAGE_PLAY_INTERVAL_TIMEOUT); 738aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 73965e7943d098113c5aa56e9822b68f0c51c6dbe36Marie Janssen } else { 7402fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen Log.v(TAG, "Metadata updated but no change!"); 741c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 742aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 743c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 744c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 74517675906064bb72fdcca75baa56cdf8bb8968d01John Du private void getRcFeatures(byte[] address, int features) { 74617675906064bb72fdcca75baa56cdf8bb8968d01John Du Message msg = mHandler.obtainMessage(MESSAGE_GET_RC_FEATURES, features, 0, 74717675906064bb72fdcca75baa56cdf8bb8968d01John Du Utils.getAddressStringFromByte(address)); 74817675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 74917675906064bb72fdcca75baa56cdf8bb8968d01John Du } 75017675906064bb72fdcca75baa56cdf8bb8968d01John Du 751c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private void getPlayStatus() { 752c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Message msg = mHandler.obtainMessage(MESSAGE_GET_PLAY_STATUS); 753c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.sendMessage(msg); 754c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 755c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 756c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private void getElementAttr(byte numAttr, int[] attrs) { 757c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu int i; 758c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ArrayList<Integer> attrList = new ArrayList<Integer>(); 759c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu for (i = 0; i < numAttr; ++i) { 760c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu attrList.add(attrs[i]); 761c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 7626e29e12add362546784126119f26f04fc760f021RoboErik Message msg = mHandler.obtainMessage(MESSAGE_GET_ELEM_ATTRS, numAttr, 0, attrList); 763c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.sendMessage(msg); 764c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 765c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 766c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private void registerNotification(int eventId, int param) { 767c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_NOTIFICATION, eventId, param); 768c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.sendMessage(msg); 769c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 770c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 771c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private void processRegisterNotification(int eventId, int param) { 772c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu switch (eventId) { 773c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case EVT_PLAY_STATUS_CHANGED: 774c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mPlayStatusChangedNT = NOTIFICATION_TYPE_INTERIM; 775c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu registerNotificationRspPlayStatusNative(mPlayStatusChangedNT, 7762fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen convertPlayStateToPlayStatus(mCurrentPlayState)); 777c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 778c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 779c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case EVT_TRACK_CHANGED: 780c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mTrackChangedNT = NOTIFICATION_TYPE_INTERIM; 781c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sendTrackChangedRsp(); 782c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 783c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 784aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu case EVT_PLAY_POS_CHANGED: 785aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu long songPosition = getPlayPosition(); 786aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPlayPosChangedNT = NOTIFICATION_TYPE_INTERIM; 787aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPlaybackIntervalMs = (long)param * 1000L; 7882fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen if (mCurrentPosMs != PlaybackState.PLAYBACK_POSITION_UNKNOWN) { 789aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mNextPosMs = songPosition + mPlaybackIntervalMs; 790aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPrevPosMs = songPosition - mPlaybackIntervalMs; 7912fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen if (isPlayingState(mCurrentPlayState)) { 792aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu Message msg = mHandler.obtainMessage(MESSAGE_PLAY_INTERVAL_TIMEOUT); 793aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mHandler.sendMessageDelayed(msg, mPlaybackIntervalMs); 794aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 795aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 796aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu registerNotificationRspPlayPosNative(mPlayPosChangedNT, (int)songPosition); 797aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu break; 798aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 799c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 800c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 801c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 802ace834feb02adabd61f628c4471147aea02d939cJohn Du private void handlePassthroughCmd(int id, int keyState) { 803ace834feb02adabd61f628c4471147aea02d939cJohn Du switch (id) { 804066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood case BluetoothAvrcp.PASSTHROUGH_ID_REWIND: 805ace834feb02adabd61f628c4471147aea02d939cJohn Du rewind(keyState); 806ace834feb02adabd61f628c4471147aea02d939cJohn Du break; 807066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood case BluetoothAvrcp.PASSTHROUGH_ID_FAST_FOR: 808ace834feb02adabd61f628c4471147aea02d939cJohn Du fastForward(keyState); 809ace834feb02adabd61f628c4471147aea02d939cJohn Du break; 810ace834feb02adabd61f628c4471147aea02d939cJohn Du } 811ace834feb02adabd61f628c4471147aea02d939cJohn Du } 812ace834feb02adabd61f628c4471147aea02d939cJohn Du 813ace834feb02adabd61f628c4471147aea02d939cJohn Du private void fastForward(int keyState) { 814ace834feb02adabd61f628c4471147aea02d939cJohn Du Message msg = mHandler.obtainMessage(MESSAGE_FAST_FORWARD, keyState, 0); 815ace834feb02adabd61f628c4471147aea02d939cJohn Du mHandler.sendMessage(msg); 816ace834feb02adabd61f628c4471147aea02d939cJohn Du } 817ace834feb02adabd61f628c4471147aea02d939cJohn Du 818ace834feb02adabd61f628c4471147aea02d939cJohn Du private void rewind(int keyState) { 819ace834feb02adabd61f628c4471147aea02d939cJohn Du Message msg = mHandler.obtainMessage(MESSAGE_REWIND, keyState, 0); 820ace834feb02adabd61f628c4471147aea02d939cJohn Du mHandler.sendMessage(msg); 821ace834feb02adabd61f628c4471147aea02d939cJohn Du } 822ace834feb02adabd61f628c4471147aea02d939cJohn Du 823ace834feb02adabd61f628c4471147aea02d939cJohn Du private void changePositionBy(long amount) { 824ace834feb02adabd61f628c4471147aea02d939cJohn Du long currentPosMs = getPlayPosition(); 825ace834feb02adabd61f628c4471147aea02d939cJohn Du if (currentPosMs == -1L) return; 826ace834feb02adabd61f628c4471147aea02d939cJohn Du long newPosMs = Math.max(0L, currentPosMs + amount); 8272fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mMediaController.getTransportControls().seekTo(newPosMs); 828ace834feb02adabd61f628c4471147aea02d939cJohn Du } 829ace834feb02adabd61f628c4471147aea02d939cJohn Du 830ace834feb02adabd61f628c4471147aea02d939cJohn Du private int getSkipMultiplier() { 831ace834feb02adabd61f628c4471147aea02d939cJohn Du long currentTime = SystemClock.elapsedRealtime(); 83219e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu long multi = (long) Math.pow(2, (currentTime - mSkipStartTime)/SKIP_DOUBLE_INTERVAL); 83319e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu return (int) Math.min(MAX_MULTIPLIER_VALUE, multi); 834ace834feb02adabd61f628c4471147aea02d939cJohn Du } 835ace834feb02adabd61f628c4471147aea02d939cJohn Du 836c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private void sendTrackChangedRsp() { 837c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu byte[] track = new byte[TRACK_ID_SIZE]; 838e8e870c24930f9b687572dbb80614e5aad6fbdfaberyl hou 839e8e870c24930f9b687572dbb80614e5aad6fbdfaberyl hou /* If no track is currently selected, then return 840e8e870c24930f9b687572dbb80614e5aad6fbdfaberyl hou 0xFFFFFFFFFFFFFFFF in the interim response */ 841e8e870c24930f9b687572dbb80614e5aad6fbdfaberyl hou long trackNumberRsp = -1L; 842e8e870c24930f9b687572dbb80614e5aad6fbdfaberyl hou 8432fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen if (isPlayingState(mCurrentPlayState)) { 844e8e870c24930f9b687572dbb80614e5aad6fbdfaberyl hou trackNumberRsp = mTrackNumber; 845e8e870c24930f9b687572dbb80614e5aad6fbdfaberyl hou } 846e8e870c24930f9b687572dbb80614e5aad6fbdfaberyl hou 84779d176b0f3d6cb33c7e52be6641fd4808ba87e93Zhihai Xu /* track is stored in big endian format */ 848c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu for (int i = 0; i < TRACK_ID_SIZE; ++i) { 849e8e870c24930f9b687572dbb80614e5aad6fbdfaberyl hou track[i] = (byte) (trackNumberRsp >> (56 - 8 * i)); 850c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 851c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu registerNotificationRspTrackChangeNative(mTrackChangedNT, track); 852c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 853c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 854aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long getPlayPosition() { 855aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu long songPosition = -1L; 8562fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen if (mCurrentPosMs != PlaybackState.PLAYBACK_POSITION_UNKNOWN) { 8572fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen if (mCurrentPlayState.getState() == PlaybackState.STATE_PLAYING) { 858aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu songPosition = SystemClock.elapsedRealtime() - 8592fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen mPlayStartTimeMs + mCurrentPosMs; 860aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } else { 861aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu songPosition = mCurrentPosMs; 862aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 863aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 864aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu if (DEBUG) Log.v(TAG, "position=" + songPosition); 865aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu return songPosition; 866aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 867aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 868c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private String getAttributeString(int attrId) { 869c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu String attrStr = null; 870c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu switch (attrId) { 871c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case MEDIA_ATTR_TITLE: 872c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu attrStr = mMetadata.trackTitle; 873c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 874c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 875c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case MEDIA_ATTR_ARTIST: 876c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu attrStr = mMetadata.artist; 877c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 878c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 879c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case MEDIA_ATTR_ALBUM: 880c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu attrStr = mMetadata.albumTitle; 881c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 882c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 883aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu case MEDIA_ATTR_PLAYING_TIME: 884aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu if (mSongLengthMs != 0L) { 885aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu attrStr = Long.toString(mSongLengthMs); 886aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 887aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu break; 888aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 889c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 890c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (attrStr == null) { 891c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu attrStr = new String(); 892c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 89365e7943d098113c5aa56e9822b68f0c51c6dbe36Marie Janssen Log.v(TAG, "getAttributeString:attrId=" + attrId + " str=" + attrStr); 894c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return attrStr; 895c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 896c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 8972fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen private int convertPlayStateToPlayStatus(PlaybackState state) { 898c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu int playStatus = PLAYSTATUS_ERROR; 8992fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen switch (state.getState()) { 9002fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen case PlaybackState.STATE_PLAYING: 9012fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen case PlaybackState.STATE_BUFFERING: 902c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_PLAYING; 903c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 904c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 9052fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen case PlaybackState.STATE_STOPPED: 9062fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen case PlaybackState.STATE_NONE: 907c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_STOPPED; 908c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 909c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 9102fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen case PlaybackState.STATE_PAUSED: 911c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_PAUSED; 912c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 913c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 9142fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen case PlaybackState.STATE_FAST_FORWARDING: 9152fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen case PlaybackState.STATE_SKIPPING_TO_NEXT: 9162fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen case PlaybackState.STATE_SKIPPING_TO_QUEUE_ITEM: 917c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_FWD_SEEK; 918c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 919c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 9202fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen case PlaybackState.STATE_REWINDING: 9212fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen case PlaybackState.STATE_SKIPPING_TO_PREVIOUS: 922c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_REV_SEEK; 923c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 924c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 9252fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen case PlaybackState.STATE_ERROR: 926c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_ERROR; 927c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 928c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 929c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 930c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return playStatus; 931c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 932c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 9332fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen private boolean isPlayingState(PlaybackState state) { 9342fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen return (state.getState() == PlaybackState.STATE_PLAYING) || 9352fc493d0ea2b504df25d783a488dfadfe301329eMarie Janssen (state.getState() == PlaybackState.STATE_BUFFERING); 936188f205b5f093850d4cc627917a21204be36c56aZhihai Xu } 937188f205b5f093850d4cc627917a21204be36c56aZhihai Xu 93817675906064bb72fdcca75baa56cdf8bb8968d01John Du /** 93917675906064bb72fdcca75baa56cdf8bb8968d01John Du * This is called from AudioService. It will return whether this device supports abs volume. 94017675906064bb72fdcca75baa56cdf8bb8968d01John Du * NOT USED AT THE MOMENT. 94117675906064bb72fdcca75baa56cdf8bb8968d01John Du */ 94217675906064bb72fdcca75baa56cdf8bb8968d01John Du public boolean isAbsoluteVolumeSupported() { 94317675906064bb72fdcca75baa56cdf8bb8968d01John Du return ((mFeatures & BTRC_FEAT_ABSOLUTE_VOLUME) != 0); 94417675906064bb72fdcca75baa56cdf8bb8968d01John Du } 94517675906064bb72fdcca75baa56cdf8bb8968d01John Du 94617675906064bb72fdcca75baa56cdf8bb8968d01John Du /** 94717675906064bb72fdcca75baa56cdf8bb8968d01John Du * We get this call from AudioService. This will send a message to our handler object, 94817675906064bb72fdcca75baa56cdf8bb8968d01John Du * requesting our handler to call setVolumeNative() 94917675906064bb72fdcca75baa56cdf8bb8968d01John Du */ 95017675906064bb72fdcca75baa56cdf8bb8968d01John Du public void adjustVolume(int direction) { 95117675906064bb72fdcca75baa56cdf8bb8968d01John Du Message msg = mHandler.obtainMessage(MESSAGE_ADJUST_VOLUME, direction, 0); 95217675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 95317675906064bb72fdcca75baa56cdf8bb8968d01John Du } 95417675906064bb72fdcca75baa56cdf8bb8968d01John Du 95517675906064bb72fdcca75baa56cdf8bb8968d01John Du public void setAbsoluteVolume(int volume) { 95611798b011c962b602217b479130d413f3b30f19aLiejun Tao if (volume == mLocalVolume) { 95711798b011c962b602217b479130d413f3b30f19aLiejun Tao if (DEBUG) Log.v(TAG, "setAbsoluteVolume is setting same index, ignore "+volume); 95811798b011c962b602217b479130d413f3b30f19aLiejun Tao return; 95911798b011c962b602217b479130d413f3b30f19aLiejun Tao } 96011798b011c962b602217b479130d413f3b30f19aLiejun Tao 96117675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.removeMessages(MESSAGE_ADJUST_VOLUME); 96211798b011c962b602217b479130d413f3b30f19aLiejun Tao Message msg = mHandler.obtainMessage(MESSAGE_SET_ABSOLUTE_VOLUME, volume, 0); 96317675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 9645c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta } 9655c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta 96617675906064bb72fdcca75baa56cdf8bb8968d01John Du /* Called in the native layer as a btrc_callback to return the volume set on the carkit in the 96717675906064bb72fdcca75baa56cdf8bb8968d01John Du * case when the volume is change locally on the carkit. This notification is not called when 96817675906064bb72fdcca75baa56cdf8bb8968d01John Du * the volume is changed from the phone. 96917675906064bb72fdcca75baa56cdf8bb8968d01John Du * 97017675906064bb72fdcca75baa56cdf8bb8968d01John Du * This method will send a message to our handler to change the local stored volume and notify 97117675906064bb72fdcca75baa56cdf8bb8968d01John Du * AudioService to update the UI 97217675906064bb72fdcca75baa56cdf8bb8968d01John Du */ 97317675906064bb72fdcca75baa56cdf8bb8968d01John Du private void volumeChangeCallback(int volume, int ctype) { 97417675906064bb72fdcca75baa56cdf8bb8968d01John Du Message msg = mHandler.obtainMessage(MESSAGE_VOLUME_CHANGED, volume, ctype); 97517675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 97617675906064bb72fdcca75baa56cdf8bb8968d01John Du } 97717675906064bb72fdcca75baa56cdf8bb8968d01John Du 9782e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie private void notifyVolumeChanged(int volume) { 9792e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 9802e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_BLUETOOTH_ABS_VOLUME); 98117675906064bb72fdcca75baa56cdf8bb8968d01John Du } 98217675906064bb72fdcca75baa56cdf8bb8968d01John Du 98317675906064bb72fdcca75baa56cdf8bb8968d01John Du private int convertToAudioStreamVolume(int volume) { 98417675906064bb72fdcca75baa56cdf8bb8968d01John Du // Rescale volume to match AudioSystem's volume 98511798b011c962b602217b479130d413f3b30f19aLiejun Tao return (int) Math.floor((double) volume*mAudioStreamMax/AVRCP_MAX_VOL); 98617675906064bb72fdcca75baa56cdf8bb8968d01John Du } 98717675906064bb72fdcca75baa56cdf8bb8968d01John Du 98817675906064bb72fdcca75baa56cdf8bb8968d01John Du private int convertToAvrcpVolume(int volume) { 9892e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie return (int) Math.ceil((double) volume*AVRCP_MAX_VOL/mAudioStreamMax); 99017675906064bb72fdcca75baa56cdf8bb8968d01John Du } 99117675906064bb72fdcca75baa56cdf8bb8968d01John Du 99211798b011c962b602217b479130d413f3b30f19aLiejun Tao private void blackListCurrentDevice() { 99311798b011c962b602217b479130d413f3b30f19aLiejun Tao mFeatures &= ~BTRC_FEAT_ABSOLUTE_VOLUME; 99411798b011c962b602217b479130d413f3b30f19aLiejun Tao mAudioManager.avrcpSupportsAbsoluteVolume(mAddress, isAbsoluteVolumeSupported()); 99511798b011c962b602217b479130d413f3b30f19aLiejun Tao 99611798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences pref = mContext.getSharedPreferences(ABSOLUTE_VOLUME_BLACKLIST, 99711798b011c962b602217b479130d413f3b30f19aLiejun Tao Context.MODE_PRIVATE); 99811798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences.Editor editor = pref.edit(); 99911798b011c962b602217b479130d413f3b30f19aLiejun Tao editor.putBoolean(mAddress, true); 100011798b011c962b602217b479130d413f3b30f19aLiejun Tao editor.commit(); 100111798b011c962b602217b479130d413f3b30f19aLiejun Tao } 100211798b011c962b602217b479130d413f3b30f19aLiejun Tao 100311798b011c962b602217b479130d413f3b30f19aLiejun Tao private int modifyRcFeatureFromBlacklist(int feature, String address) { 100411798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences pref = mContext.getSharedPreferences(ABSOLUTE_VOLUME_BLACKLIST, 100511798b011c962b602217b479130d413f3b30f19aLiejun Tao Context.MODE_PRIVATE); 100611798b011c962b602217b479130d413f3b30f19aLiejun Tao if (!pref.contains(address)) { 100711798b011c962b602217b479130d413f3b30f19aLiejun Tao return feature; 100811798b011c962b602217b479130d413f3b30f19aLiejun Tao } 100911798b011c962b602217b479130d413f3b30f19aLiejun Tao if (pref.getBoolean(address, false)) { 101011798b011c962b602217b479130d413f3b30f19aLiejun Tao feature &= ~BTRC_FEAT_ABSOLUTE_VOLUME; 101111798b011c962b602217b479130d413f3b30f19aLiejun Tao } 101211798b011c962b602217b479130d413f3b30f19aLiejun Tao return feature; 101311798b011c962b602217b479130d413f3b30f19aLiejun Tao } 101411798b011c962b602217b479130d413f3b30f19aLiejun Tao 101511798b011c962b602217b479130d413f3b30f19aLiejun Tao public void resetBlackList(String address) { 101611798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences pref = mContext.getSharedPreferences(ABSOLUTE_VOLUME_BLACKLIST, 101711798b011c962b602217b479130d413f3b30f19aLiejun Tao Context.MODE_PRIVATE); 101811798b011c962b602217b479130d413f3b30f19aLiejun Tao SharedPreferences.Editor editor = pref.edit(); 101911798b011c962b602217b479130d413f3b30f19aLiejun Tao editor.remove(address); 102011798b011c962b602217b479130d413f3b30f19aLiejun Tao editor.commit(); 102111798b011c962b602217b479130d413f3b30f19aLiejun Tao } 102211798b011c962b602217b479130d413f3b30f19aLiejun Tao 1023188f205b5f093850d4cc627917a21204be36c56aZhihai Xu /** 1024188f205b5f093850d4cc627917a21204be36c56aZhihai Xu * This is called from A2dpStateMachine to set A2dp audio state. 1025188f205b5f093850d4cc627917a21204be36c56aZhihai Xu */ 1026188f205b5f093850d4cc627917a21204be36c56aZhihai Xu public void setA2dpAudioState(int state) { 1027188f205b5f093850d4cc627917a21204be36c56aZhihai Xu Message msg = mHandler.obtainMessage(MESSAGE_SET_A2DP_AUDIO_STATE, state, 0); 1028188f205b5f093850d4cc627917a21204be36c56aZhihai Xu mHandler.sendMessage(msg); 1029188f205b5f093850d4cc627917a21204be36c56aZhihai Xu } 1030188f205b5f093850d4cc627917a21204be36c56aZhihai Xu 1031838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood public void dump(StringBuilder sb) { 1032838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood sb.append("AVRCP:\n"); 1033838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mMetadata: " + mMetadata); 1034838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mTransportControlFlags: " + mTransportControlFlags); 1035838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mCurrentPlayState: " + mCurrentPlayState); 1036838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mPlayStatusChangedNT: " + mPlayStatusChangedNT); 1037838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mTrackChangedNT: " + mTrackChangedNT); 1038838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mTrackNumber: " + mTrackNumber); 1039838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mCurrentPosMs: " + mCurrentPosMs); 1040838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mPlayStartTimeMs: " + mPlayStartTimeMs); 1041838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mSongLengthMs: " + mSongLengthMs); 1042838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mPlaybackIntervalMs: " + mPlaybackIntervalMs); 1043838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mPlayPosChangedNT: " + mPlayPosChangedNT); 1044838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mNextPosMs: " + mNextPosMs); 1045838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mPrevPosMs: " + mPrevPosMs); 1046838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mSkipStartTime: " + mSkipStartTime); 1047838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mFeatures: " + mFeatures); 104811798b011c962b602217b479130d413f3b30f19aLiejun Tao ProfileService.println(sb, "mRemoteVolume: " + mRemoteVolume); 104911798b011c962b602217b479130d413f3b30f19aLiejun Tao ProfileService.println(sb, "mLastRemoteVolume: " + mLastRemoteVolume); 1050838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mLastDirection: " + mLastDirection); 1051838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mVolumeStep: " + mVolumeStep); 1052838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mAudioStreamMax: " + mAudioStreamMax); 105311798b011c962b602217b479130d413f3b30f19aLiejun Tao ProfileService.println(sb, "mVolCmdAdjustInProgress: " + mVolCmdAdjustInProgress); 105411798b011c962b602217b479130d413f3b30f19aLiejun Tao ProfileService.println(sb, "mVolCmdSetInProgress: " + mVolCmdSetInProgress); 1055838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mAbsVolRetryTimes: " + mAbsVolRetryTimes); 1056838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mSkipAmount: " + mSkipAmount); 105711798b011c962b602217b479130d413f3b30f19aLiejun Tao ProfileService.println(sb, "mVolumeMapping: " + mVolumeMapping.toString()); 1058838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood } 1059838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood 1060c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu // Do not modify without updating the HAL bt_rc.h files. 1061c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1062c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu // match up with btrc_play_status_t enum of bt_rc.h 1063c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int PLAYSTATUS_STOPPED = 0; 1064c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int PLAYSTATUS_PLAYING = 1; 1065c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int PLAYSTATUS_PAUSED = 2; 1066c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int PLAYSTATUS_FWD_SEEK = 3; 1067c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int PLAYSTATUS_REV_SEEK = 4; 1068c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int PLAYSTATUS_ERROR = 255; 1069c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1070c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu // match up with btrc_media_attr_t enum of bt_rc.h 1071c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int MEDIA_ATTR_TITLE = 1; 1072c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int MEDIA_ATTR_ARTIST = 2; 1073c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int MEDIA_ATTR_ALBUM = 3; 1074c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int MEDIA_ATTR_TRACK_NUM = 4; 1075c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int MEDIA_ATTR_NUM_TRACKS = 5; 1076c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int MEDIA_ATTR_GENRE = 6; 1077c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int MEDIA_ATTR_PLAYING_TIME = 7; 1078c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1079c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu // match up with btrc_event_id_t enum of bt_rc.h 1080c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int EVT_PLAY_STATUS_CHANGED = 1; 1081c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int EVT_TRACK_CHANGED = 2; 1082c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int EVT_TRACK_REACHED_END = 3; 1083c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int EVT_TRACK_REACHED_START = 4; 1084c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int EVT_PLAY_POS_CHANGED = 5; 1085c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int EVT_BATT_STATUS_CHANGED = 6; 1086c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int EVT_SYSTEM_STATUS_CHANGED = 7; 1087c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int EVT_APP_SETTINGS_CHANGED = 8; 1088c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1089c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu // match up with btrc_notification_type_t enum of bt_rc.h 1090c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int NOTIFICATION_TYPE_INTERIM = 0; 1091c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int NOTIFICATION_TYPE_CHANGED = 1; 1092c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1093c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu // match up with BTRC_UID_SIZE of bt_rc.h 1094c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int TRACK_ID_SIZE = 8; 1095c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 1096c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native static void classInitNative(); 1097c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native void initNative(); 1098c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native void cleanupNative(); 1099c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native boolean getPlayStatusRspNative(int playStatus, int songLen, int songPos); 1100c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native boolean getElementAttrRspNative(byte numAttr, int[] attrIds, String[] textArray); 1101c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native boolean registerNotificationRspPlayStatusNative(int type, int playStatus); 1102c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native boolean registerNotificationRspTrackChangeNative(int type, byte[] track); 1103aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private native boolean registerNotificationRspPlayPosNative(int type, int playPos); 110417675906064bb72fdcca75baa56cdf8bb8968d01John Du private native boolean setVolumeNative(int volume); 11055c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta private native boolean sendPassThroughCommandNative(int keyCode, int keyState); 11065c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta 1107c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 1108