Avrcp.java revision 838949d46a4cc054985a8cfd682004f8dd6d3bbb
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 22c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.app.PendingIntent; 23188f205b5f093850d4cc627917a21204be36c56aZhihai Xuimport android.bluetooth.BluetoothA2dp; 24066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodimport android.bluetooth.BluetoothAvrcp; 25c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.content.Context; 26aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xuimport android.content.Intent; 27c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.graphics.Bitmap; 28c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.media.AudioManager; 29c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.media.IRemoteControlDisplay; 30c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.media.MediaMetadataRetriever; 31c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.media.RemoteControlClient; 326e29e12add362546784126119f26f04fc760f021RoboErikimport android.media.RemoteController; 336e29e12add362546784126119f26f04fc760f021RoboErikimport android.media.RemoteController.MetadataEditor; 34c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.Bundle; 35c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.Handler; 36c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.HandlerThread; 37c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.Looper; 38c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.Message; 39c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.ParcelUuid; 40c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.PowerManager; 41c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.PowerManager.WakeLock; 42c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.RemoteException; 43c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.os.ServiceManager; 44aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xuimport android.os.SystemClock; 45c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport android.util.Log; 46881675b362bde18acbbcf69c513175addca4a8baZhenye Zhuimport android.view.KeyEvent; 476e29e12add362546784126119f26f04fc760f021RoboErik 48c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport com.android.bluetooth.btservice.AdapterService; 49c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport com.android.bluetooth.btservice.ProfileService; 50aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xuimport com.android.bluetooth.Utils; 51c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport com.android.internal.util.IState; 52c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport com.android.internal.util.State; 53c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport com.android.internal.util.StateMachine; 546e29e12add362546784126119f26f04fc760f021RoboErik 55c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport java.lang.ref.WeakReference; 56c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport java.util.ArrayList; 57c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport java.util.List; 58c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xuimport java.util.Set; 59c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu/** 60c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * support Bluetooth AVRCP profile. 61c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu * support metadata, play status and event notification 62c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu */ 63066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodpublic final class Avrcp { 648e0d927632cce4ad53df85fb7627b915c5fbd64bRoboErik private static final boolean DEBUG = false; 65c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private static final String TAG = "Avrcp"; 66c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 67c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private Context mContext; 68c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private final AudioManager mAudioManager; 69c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private AvrcpMessageHandler mHandler; 706e29e12add362546784126119f26f04fc760f021RoboErik private RemoteController mRemoteController; 716e29e12add362546784126119f26f04fc760f021RoboErik private RemoteControllerWeak mRemoteControllerCb; 72c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private Metadata mMetadata; 73c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private int mTransportControlFlags; 74c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private int mCurrentPlayState; 75c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private int mPlayStatusChangedNT; 76c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private int mTrackChangedNT; 77c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private long mTrackNumber; 78aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mCurrentPosMs; 79aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mPlayStartTimeMs; 80aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mSongLengthMs; 81aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mPlaybackIntervalMs; 82aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private int mPlayPosChangedNT; 83aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mNextPosMs; 84aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long mPrevPosMs; 85ace834feb02adabd61f628c4471147aea02d939cJohn Du private long mSkipStartTime; 8617675906064bb72fdcca75baa56cdf8bb8968d01John Du private int mFeatures; 8717675906064bb72fdcca75baa56cdf8bb8968d01John Du private int mAbsoluteVolume; 8817675906064bb72fdcca75baa56cdf8bb8968d01John Du private int mLastSetVolume; 8917675906064bb72fdcca75baa56cdf8bb8968d01John Du private int mLastDirection; 902e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie private final int mVolumeStep; 912e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie private final int mAudioStreamMax; 9217675906064bb72fdcca75baa56cdf8bb8968d01John Du private boolean mVolCmdInProgress; 9317675906064bb72fdcca75baa56cdf8bb8968d01John Du private int mAbsVolRetryTimes; 9419e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu private int mSkipAmount; 95ace834feb02adabd61f628c4471147aea02d939cJohn Du 9617675906064bb72fdcca75baa56cdf8bb8968d01John Du /* BTRC features */ 9717675906064bb72fdcca75baa56cdf8bb8968d01John Du public static final int BTRC_FEAT_METADATA = 0x01; 9817675906064bb72fdcca75baa56cdf8bb8968d01John Du public static final int BTRC_FEAT_ABSOLUTE_VOLUME = 0x02; 9917675906064bb72fdcca75baa56cdf8bb8968d01John Du public static final int BTRC_FEAT_BROWSE = 0x04; 10017675906064bb72fdcca75baa56cdf8bb8968d01John Du 10117675906064bb72fdcca75baa56cdf8bb8968d01John Du /* AVRC response codes, from avrc_defs */ 10217675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_NOT_IMPL = 8; 10317675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_ACCEPT = 9; 10417675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_REJ = 10; 10517675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_IN_TRANS = 11; 10617675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_IMPL_STBL = 12; 10717675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_CHANGED = 13; 10817675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRC_RSP_INTERIM = 15; 10917675906064bb72fdcca75baa56cdf8bb8968d01John Du 11017675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MESSAGE_GET_RC_FEATURES = 1; 11117675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MESSAGE_GET_PLAY_STATUS = 2; 11217675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MESSAGE_GET_ELEM_ATTRS = 3; 11317675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MESSAGE_REGISTER_NOTIFICATION = 4; 11417675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MESSAGE_PLAY_INTERVAL_TIMEOUT = 5; 11517675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MESSAGE_VOLUME_CHANGED = 6; 11617675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MESSAGE_ADJUST_VOLUME = 7; 11717675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MESSAGE_SET_ABSOLUTE_VOLUME = 8; 11817675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MESSAGE_ABS_VOL_TIMEOUT = 9; 11917675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MESSAGE_FAST_FORWARD = 10; 12017675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MESSAGE_REWIND = 11; 12119e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu private static final int MESSAGE_CHANGE_PLAY_POS = 12; 122188f205b5f093850d4cc627917a21204be36c56aZhihai Xu private static final int MESSAGE_SET_A2DP_AUDIO_STATE = 13; 123c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private static final int MSG_UPDATE_STATE = 100; 124c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private static final int MSG_SET_METADATA = 101; 125c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private static final int MSG_SET_TRANSPORT_CONTROLS = 102; 126c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private static final int MSG_SET_GENERATION_ID = 104; 127c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 128ace834feb02adabd61f628c4471147aea02d939cJohn Du private static final int BUTTON_TIMEOUT_TIME = 2000; 129ace834feb02adabd61f628c4471147aea02d939cJohn Du private static final int BASE_SKIP_AMOUNT = 2000; 130ace834feb02adabd61f628c4471147aea02d939cJohn Du private static final int KEY_STATE_PRESS = 1; 131ace834feb02adabd61f628c4471147aea02d939cJohn Du private static final int KEY_STATE_RELEASE = 0; 132ace834feb02adabd61f628c4471147aea02d939cJohn Du private static final int SKIP_PERIOD = 400; 133ace834feb02adabd61f628c4471147aea02d939cJohn Du private static final int SKIP_DOUBLE_INTERVAL = 3000; 13419e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu private static final long MAX_MULTIPLIER_VALUE = 128L; 13517675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int CMD_TIMEOUT_DELAY = 2000; 13617675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int MAX_ERROR_RETRY_TIMES = 3; 13717675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRCP_MAX_VOL = 127; 13817675906064bb72fdcca75baa56cdf8bb8968d01John Du private static final int AVRCP_BASE_VOLUME_STEP = 1; 139ace834feb02adabd61f628c4471147aea02d939cJohn Du 140c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu static { 141c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu classInitNative(); 142c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 143c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 144c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private Avrcp(Context context) { 145c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mMetadata = new Metadata(); 146c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mCurrentPlayState = RemoteControlClient.PLAYSTATE_NONE; // until we get a callback 147c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mPlayStatusChangedNT = NOTIFICATION_TYPE_CHANGED; 148c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mTrackChangedNT = NOTIFICATION_TYPE_CHANGED; 14979d176b0f3d6cb33c7e52be6641fd4808ba87e93Zhihai Xu mTrackNumber = -1L; 150f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu mCurrentPosMs = 0L; 151aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPlayStartTimeMs = -1L; 152aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mSongLengthMs = 0L; 153aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPlaybackIntervalMs = 0L; 154aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPlayPosChangedNT = NOTIFICATION_TYPE_CHANGED; 15517675906064bb72fdcca75baa56cdf8bb8968d01John Du mFeatures = 0; 15617675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsoluteVolume = -1; 15717675906064bb72fdcca75baa56cdf8bb8968d01John Du mLastSetVolume = -1; 15817675906064bb72fdcca75baa56cdf8bb8968d01John Du mLastDirection = 0; 15917675906064bb72fdcca75baa56cdf8bb8968d01John Du mVolCmdInProgress = false; 16017675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes = 0; 161c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 162c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mContext = context; 163c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 164c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu initNative(); 165c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 166c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 1672e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie mAudioStreamMax = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); 1682e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie mVolumeStep = Math.max(AVRCP_BASE_VOLUME_STEP, AVRCP_MAX_VOL/mAudioStreamMax); 169c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 170c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 171c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private void start() { 172c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu HandlerThread thread = new HandlerThread("BluetoothAvrcpHandler"); 173c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu thread.start(); 174c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Looper looper = thread.getLooper(); 175c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler = new AvrcpMessageHandler(looper); 1766e29e12add362546784126119f26f04fc760f021RoboErik mRemoteControllerCb = new RemoteControllerWeak(mHandler); 1776e29e12add362546784126119f26f04fc760f021RoboErik mRemoteController = new RemoteController(mContext, mRemoteControllerCb); 1786e29e12add362546784126119f26f04fc760f021RoboErik mAudioManager.registerRemoteController(mRemoteController); 1796e29e12add362546784126119f26f04fc760f021RoboErik mRemoteController.setSynchronizationMode(RemoteController.POSITION_SYNCHRONIZATION_CHECK); 180c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 181c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 182066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood public static Avrcp make(Context context) { 183c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (DEBUG) Log.v(TAG, "make"); 184c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Avrcp ar = new Avrcp(context); 185c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ar.start(); 186c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return ar; 187c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 188c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 189c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public void doQuit() { 190c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.removeCallbacksAndMessages(null); 191c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Looper looper = mHandler.getLooper(); 192c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (looper != null) { 193c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu looper.quit(); 194c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 1956e29e12add362546784126119f26f04fc760f021RoboErik mAudioManager.unregisterRemoteController(mRemoteController); 196c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 197c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 198c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public void cleanup() { 199c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu cleanupNative(); 200c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 201c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 2026e29e12add362546784126119f26f04fc760f021RoboErik private static class RemoteControllerWeak implements RemoteController.OnClientUpdateListener { 2036e29e12add362546784126119f26f04fc760f021RoboErik private final WeakReference<Handler> mLocalHandler; 2046e29e12add362546784126119f26f04fc760f021RoboErik 2056e29e12add362546784126119f26f04fc760f021RoboErik public RemoteControllerWeak(Handler handler) { 206c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mLocalHandler = new WeakReference<Handler>(handler); 207c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 208c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 209bc10e7d58aa55da25c18d8056a0254a2b736146aZhihai Xu @Override 2106e29e12add362546784126119f26f04fc760f021RoboErik public void onClientChange(boolean clearing) { 211c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Handler handler = mLocalHandler.get(); 212c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (handler != null) { 2136e29e12add362546784126119f26f04fc760f021RoboErik handler.obtainMessage(MSG_SET_GENERATION_ID, 2146e29e12add362546784126119f26f04fc760f021RoboErik 0, (clearing ? 1 : 0), null).sendToTarget(); 215c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 216c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 217c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 218c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu @Override 2196e29e12add362546784126119f26f04fc760f021RoboErik public void onClientPlaybackStateUpdate(int state) { 2206e29e12add362546784126119f26f04fc760f021RoboErik // Should never be called with the existing code, but just in case 221c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Handler handler = mLocalHandler.get(); 222c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (handler != null) { 2236e29e12add362546784126119f26f04fc760f021RoboErik handler.obtainMessage(MSG_UPDATE_STATE, 0, state, 2246e29e12add362546784126119f26f04fc760f021RoboErik new Long(RemoteControlClient.PLAYBACK_POSITION_INVALID)).sendToTarget(); 225c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 226c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 227c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 228c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu @Override 2296e29e12add362546784126119f26f04fc760f021RoboErik public void onClientPlaybackStateUpdate(int state, long stateChangeTimeMs, 2306e29e12add362546784126119f26f04fc760f021RoboErik long currentPosMs, float speed) { 231c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Handler handler = mLocalHandler.get(); 232c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (handler != null) { 2336e29e12add362546784126119f26f04fc760f021RoboErik handler.obtainMessage(MSG_UPDATE_STATE, 0, state, 2346e29e12add362546784126119f26f04fc760f021RoboErik new Long(currentPosMs)).sendToTarget(); 235c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 236c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 237c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 238c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu @Override 2396e29e12add362546784126119f26f04fc760f021RoboErik public void onClientTransportControlUpdate(int transportControlFlags) { 240c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Handler handler = mLocalHandler.get(); 241c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (handler != null) { 2426e29e12add362546784126119f26f04fc760f021RoboErik handler.obtainMessage(MSG_SET_TRANSPORT_CONTROLS, 0, transportControlFlags) 2436e29e12add362546784126119f26f04fc760f021RoboErik .sendToTarget(); 244c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 245c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 246c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 247c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu @Override 2486e29e12add362546784126119f26f04fc760f021RoboErik public void onClientMetadataUpdate(MetadataEditor metadataEditor) { 249c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Handler handler = mLocalHandler.get(); 250c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (handler != null) { 2516e29e12add362546784126119f26f04fc760f021RoboErik handler.obtainMessage(MSG_SET_METADATA, 0, 0, metadataEditor).sendToTarget(); 252c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 253c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 254c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 255c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 256c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu /** Handles Avrcp messages. */ 257c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private final class AvrcpMessageHandler extends Handler { 258c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private AvrcpMessageHandler(Looper looper) { 259c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu super(looper); 260c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 261c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 262c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu @Override 263c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public void handleMessage(Message msg) { 264c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu switch (msg.what) { 265c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case MSG_UPDATE_STATE: 2666e29e12add362546784126119f26f04fc760f021RoboErik updatePlayPauseState(msg.arg2, ((Long) msg.obj).longValue()); 267c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 268c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 269c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case MSG_SET_METADATA: 2706e29e12add362546784126119f26f04fc760f021RoboErik updateMetadata((MetadataEditor) msg.obj); 271c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 272c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 273c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case MSG_SET_TRANSPORT_CONTROLS: 2746e29e12add362546784126119f26f04fc760f021RoboErik updateTransportControls(msg.arg2); 275c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 276c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 277c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case MSG_SET_GENERATION_ID: 278c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (DEBUG) Log.v(TAG, "New genId = " + msg.arg1 + ", clearing = " + msg.arg2); 279c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 280c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 28117675906064bb72fdcca75baa56cdf8bb8968d01John Du case MESSAGE_GET_RC_FEATURES: 28217675906064bb72fdcca75baa56cdf8bb8968d01John Du String address = (String) msg.obj; 28317675906064bb72fdcca75baa56cdf8bb8968d01John Du if (DEBUG) Log.v(TAG, "MESSAGE_GET_RC_FEATURES: address="+address+ 28417675906064bb72fdcca75baa56cdf8bb8968d01John Du ", features="+msg.arg1); 28517675906064bb72fdcca75baa56cdf8bb8968d01John Du mFeatures = msg.arg1; 28617675906064bb72fdcca75baa56cdf8bb8968d01John Du mAudioManager.avrcpSupportsAbsoluteVolume(address, isAbsoluteVolumeSupported()); 28717675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 28817675906064bb72fdcca75baa56cdf8bb8968d01John Du 289c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case MESSAGE_GET_PLAY_STATUS: 290c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (DEBUG) Log.v(TAG, "MESSAGE_GET_PLAY_STATUS"); 291aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu getPlayStatusRspNative(convertPlayStateToPlayStatus(mCurrentPlayState), 292aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu (int)mSongLengthMs, (int)getPlayPosition()); 293c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 294c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 295c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case MESSAGE_GET_ELEM_ATTRS: 296c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu { 297c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu String[] textArray; 298c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu int[] attrIds; 299c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu byte numAttr = (byte) msg.arg1; 300c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ArrayList<Integer> attrList = (ArrayList<Integer>) msg.obj; 301c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (DEBUG) Log.v(TAG, "MESSAGE_GET_ELEM_ATTRS:numAttr=" + numAttr); 302c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu attrIds = new int[numAttr]; 303c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu textArray = new String[numAttr]; 304c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu for (int i = 0; i < numAttr; ++i) { 305c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu attrIds[i] = attrList.get(i).intValue(); 306c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu textArray[i] = getAttributeString(attrIds[i]); 307c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 308c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu getElementAttrRspNative(numAttr, attrIds, textArray); 309c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 310c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 311c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case MESSAGE_REGISTER_NOTIFICATION: 312c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (DEBUG) Log.v(TAG, "MESSAGE_REGISTER_NOTIFICATION:event=" + msg.arg1 + 313c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu " param=" + msg.arg2); 314c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu processRegisterNotification(msg.arg1, msg.arg2); 315c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 316c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 317aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu case MESSAGE_PLAY_INTERVAL_TIMEOUT: 318aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu if (DEBUG) Log.v(TAG, "MESSAGE_PLAY_INTERVAL_TIMEOUT"); 319aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPlayPosChangedNT = NOTIFICATION_TYPE_CHANGED; 320aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu registerNotificationRspPlayPosNative(mPlayPosChangedNT, (int)getPlayPosition()); 321aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu break; 322aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 32317675906064bb72fdcca75baa56cdf8bb8968d01John Du case MESSAGE_VOLUME_CHANGED: 3245c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta if (DEBUG) Log.v(TAG, "MESSAGE_VOLUME_CHANGED: volume=" + ((byte)msg.arg1 & 0x7f) 3255c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta + " ctype=" + msg.arg2); 32617675906064bb72fdcca75baa56cdf8bb8968d01John Du 32717675906064bb72fdcca75baa56cdf8bb8968d01John Du if (msg.arg2 == AVRC_RSP_ACCEPT || msg.arg2 == AVRC_RSP_REJ) { 32817675906064bb72fdcca75baa56cdf8bb8968d01John Du if (mVolCmdInProgress == false) { 32917675906064bb72fdcca75baa56cdf8bb8968d01John Du Log.e(TAG, "Unsolicited response, ignored"); 33017675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 33117675906064bb72fdcca75baa56cdf8bb8968d01John Du } 33217675906064bb72fdcca75baa56cdf8bb8968d01John Du removeMessages(MESSAGE_ABS_VOL_TIMEOUT); 33317675906064bb72fdcca75baa56cdf8bb8968d01John Du mVolCmdInProgress = false; 33417675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes = 0; 33517675906064bb72fdcca75baa56cdf8bb8968d01John Du } 3362e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie if (mAbsoluteVolume != msg.arg1 && (msg.arg2 == AVRC_RSP_ACCEPT || 3372e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie msg.arg2 == AVRC_RSP_CHANGED || 3382e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie msg.arg2 == AVRC_RSP_INTERIM)) { 3395c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta byte absVol = (byte)((byte)msg.arg1 & 0x7f); // discard MSB as it is RFD 3406e29e12add362546784126119f26f04fc760f021RoboErik notifyVolumeChanged(absVol); 3415c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta mAbsoluteVolume = absVol; 3425c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta long pecentVolChanged = ((long)absVol * 100) / 0x7f; 3435c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta Log.e(TAG, "percent volume changed: " + pecentVolChanged + "%"); 34417675906064bb72fdcca75baa56cdf8bb8968d01John Du } else if (msg.arg2 == AVRC_RSP_REJ) { 34517675906064bb72fdcca75baa56cdf8bb8968d01John Du Log.e(TAG, "setAbsoluteVolume call rejected"); 34617675906064bb72fdcca75baa56cdf8bb8968d01John Du } 34717675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 34817675906064bb72fdcca75baa56cdf8bb8968d01John Du 34917675906064bb72fdcca75baa56cdf8bb8968d01John Du case MESSAGE_ADJUST_VOLUME: 35017675906064bb72fdcca75baa56cdf8bb8968d01John Du if (DEBUG) Log.d(TAG, "MESSAGE_ADJUST_VOLUME: direction=" + msg.arg1); 35117675906064bb72fdcca75baa56cdf8bb8968d01John Du if (mVolCmdInProgress) { 35217675906064bb72fdcca75baa56cdf8bb8968d01John Du if (DEBUG) Log.w(TAG, "There is already a volume command in progress."); 35317675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 35417675906064bb72fdcca75baa56cdf8bb8968d01John Du } 35517675906064bb72fdcca75baa56cdf8bb8968d01John Du // Wait on verification on volume from device, before changing the volume. 35617675906064bb72fdcca75baa56cdf8bb8968d01John Du if (mAbsoluteVolume != -1 && (msg.arg1 == -1 || msg.arg1 == 1)) { 35717675906064bb72fdcca75baa56cdf8bb8968d01John Du int setVol = Math.min(AVRCP_MAX_VOL, 35817675906064bb72fdcca75baa56cdf8bb8968d01John Du Math.max(0, mAbsoluteVolume + msg.arg1*mVolumeStep)); 35917675906064bb72fdcca75baa56cdf8bb8968d01John Du if (setVolumeNative(setVol)) { 36017675906064bb72fdcca75baa56cdf8bb8968d01John Du sendMessageDelayed(obtainMessage(MESSAGE_ABS_VOL_TIMEOUT), 36117675906064bb72fdcca75baa56cdf8bb8968d01John Du CMD_TIMEOUT_DELAY); 36217675906064bb72fdcca75baa56cdf8bb8968d01John Du mVolCmdInProgress = true; 36317675906064bb72fdcca75baa56cdf8bb8968d01John Du mLastDirection = msg.arg1; 36417675906064bb72fdcca75baa56cdf8bb8968d01John Du mLastSetVolume = setVol; 36517675906064bb72fdcca75baa56cdf8bb8968d01John Du } 36617675906064bb72fdcca75baa56cdf8bb8968d01John Du } else { 36717675906064bb72fdcca75baa56cdf8bb8968d01John Du Log.e(TAG, "Unknown direction in MESSAGE_ADJUST_VOLUME"); 36817675906064bb72fdcca75baa56cdf8bb8968d01John Du } 36917675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 37017675906064bb72fdcca75baa56cdf8bb8968d01John Du 37117675906064bb72fdcca75baa56cdf8bb8968d01John Du case MESSAGE_SET_ABSOLUTE_VOLUME: 37217675906064bb72fdcca75baa56cdf8bb8968d01John Du if (DEBUG) Log.v(TAG, "MESSAGE_SET_ABSOLUTE_VOLUME"); 37317675906064bb72fdcca75baa56cdf8bb8968d01John Du if (mVolCmdInProgress) { 37417675906064bb72fdcca75baa56cdf8bb8968d01John Du if (DEBUG) Log.w(TAG, "There is already a volume command in progress."); 37517675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 37617675906064bb72fdcca75baa56cdf8bb8968d01John Du } 37717675906064bb72fdcca75baa56cdf8bb8968d01John Du if (setVolumeNative(msg.arg1)) { 37817675906064bb72fdcca75baa56cdf8bb8968d01John Du sendMessageDelayed(obtainMessage(MESSAGE_ABS_VOL_TIMEOUT), CMD_TIMEOUT_DELAY); 37917675906064bb72fdcca75baa56cdf8bb8968d01John Du mVolCmdInProgress = true; 38017675906064bb72fdcca75baa56cdf8bb8968d01John Du mLastSetVolume = msg.arg1; 38117675906064bb72fdcca75baa56cdf8bb8968d01John Du } 38217675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 38317675906064bb72fdcca75baa56cdf8bb8968d01John Du 38417675906064bb72fdcca75baa56cdf8bb8968d01John Du case MESSAGE_ABS_VOL_TIMEOUT: 38517675906064bb72fdcca75baa56cdf8bb8968d01John Du if (DEBUG) Log.v(TAG, "MESSAGE_ABS_VOL_TIMEOUT: Volume change cmd timed out."); 38617675906064bb72fdcca75baa56cdf8bb8968d01John Du mVolCmdInProgress = false; 38717675906064bb72fdcca75baa56cdf8bb8968d01John Du if (mAbsVolRetryTimes >= MAX_ERROR_RETRY_TIMES) { 38817675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes = 0; 38917675906064bb72fdcca75baa56cdf8bb8968d01John Du } else { 39017675906064bb72fdcca75baa56cdf8bb8968d01John Du mAbsVolRetryTimes += 1; 39117675906064bb72fdcca75baa56cdf8bb8968d01John Du if (setVolumeNative(mLastSetVolume)) { 39217675906064bb72fdcca75baa56cdf8bb8968d01John Du sendMessageDelayed(obtainMessage(MESSAGE_ABS_VOL_TIMEOUT), 39317675906064bb72fdcca75baa56cdf8bb8968d01John Du CMD_TIMEOUT_DELAY); 39417675906064bb72fdcca75baa56cdf8bb8968d01John Du mVolCmdInProgress = true; 39517675906064bb72fdcca75baa56cdf8bb8968d01John Du } 39617675906064bb72fdcca75baa56cdf8bb8968d01John Du } 39717675906064bb72fdcca75baa56cdf8bb8968d01John Du break; 39817675906064bb72fdcca75baa56cdf8bb8968d01John Du 399ace834feb02adabd61f628c4471147aea02d939cJohn Du case MESSAGE_FAST_FORWARD: 400ace834feb02adabd61f628c4471147aea02d939cJohn Du case MESSAGE_REWIND: 401881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu if(msg.what == MESSAGE_FAST_FORWARD) { 402881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu if((mTransportControlFlags & 403881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu RemoteControlClient.FLAG_KEY_MEDIA_FAST_FORWARD) != 0) { 404881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu int keyState = msg.arg1 == KEY_STATE_PRESS ? 405881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP; 406881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu KeyEvent keyEvent = 407881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu new KeyEvent(keyState, KeyEvent.KEYCODE_MEDIA_FAST_FORWARD); 408881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu mRemoteController.sendMediaKeyEvent(keyEvent); 409881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu break; 410881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu } 411881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu } else if((mTransportControlFlags & 412881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu RemoteControlClient.FLAG_KEY_MEDIA_REWIND) != 0) { 413881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu int keyState = msg.arg1 == KEY_STATE_PRESS ? 414881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP; 415881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu KeyEvent keyEvent = 416881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu new KeyEvent(keyState, KeyEvent.KEYCODE_MEDIA_REWIND); 417881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu mRemoteController.sendMediaKeyEvent(keyEvent); 418881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu break; 419881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu } 420881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu 42119e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu int skipAmount; 422ace834feb02adabd61f628c4471147aea02d939cJohn Du if (msg.what == MESSAGE_FAST_FORWARD) { 423ace834feb02adabd61f628c4471147aea02d939cJohn Du if (DEBUG) Log.v(TAG, "MESSAGE_FAST_FORWARD"); 424881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu removeMessages(MESSAGE_FAST_FORWARD); 425ace834feb02adabd61f628c4471147aea02d939cJohn Du skipAmount = BASE_SKIP_AMOUNT; 426ace834feb02adabd61f628c4471147aea02d939cJohn Du } else { 427ace834feb02adabd61f628c4471147aea02d939cJohn Du if (DEBUG) Log.v(TAG, "MESSAGE_REWIND"); 428881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu removeMessages(MESSAGE_REWIND); 429ace834feb02adabd61f628c4471147aea02d939cJohn Du skipAmount = -BASE_SKIP_AMOUNT; 430ace834feb02adabd61f628c4471147aea02d939cJohn Du } 431ace834feb02adabd61f628c4471147aea02d939cJohn Du 43219e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu if (hasMessages(MESSAGE_CHANGE_PLAY_POS) && 43319e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu (skipAmount != mSkipAmount)) { 43419e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu Log.w(TAG, "missing release button event:" + mSkipAmount); 43519e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu } 43619e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu 43719e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu if ((!hasMessages(MESSAGE_CHANGE_PLAY_POS)) || 43819e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu (skipAmount != mSkipAmount)) { 43919e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu mSkipStartTime = SystemClock.elapsedRealtime(); 44019e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu } 44119e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu 44219e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu removeMessages(MESSAGE_CHANGE_PLAY_POS); 443ace834feb02adabd61f628c4471147aea02d939cJohn Du if (msg.arg1 == KEY_STATE_PRESS) { 44419e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu mSkipAmount = skipAmount; 44519e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu changePositionBy(mSkipAmount * getSkipMultiplier()); 44619e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu Message posMsg = obtainMessage(MESSAGE_CHANGE_PLAY_POS); 44719e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu posMsg.arg1 = 1; 44819e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu sendMessageDelayed(posMsg, SKIP_PERIOD); 449ace834feb02adabd61f628c4471147aea02d939cJohn Du } 450881675b362bde18acbbcf69c513175addca4a8baZhenye Zhu 451ace834feb02adabd61f628c4471147aea02d939cJohn Du break; 452ace834feb02adabd61f628c4471147aea02d939cJohn Du 45319e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu case MESSAGE_CHANGE_PLAY_POS: 45419e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu if (DEBUG) Log.v(TAG, "MESSAGE_CHANGE_PLAY_POS:" + msg.arg1); 45519e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu changePositionBy(mSkipAmount * getSkipMultiplier()); 45619e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu if (msg.arg1 * SKIP_PERIOD < BUTTON_TIMEOUT_TIME) { 45719e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu Message posMsg = obtainMessage(MESSAGE_CHANGE_PLAY_POS); 45819e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu posMsg.arg1 = msg.arg1 + 1; 45919e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu sendMessageDelayed(posMsg, SKIP_PERIOD); 460ace834feb02adabd61f628c4471147aea02d939cJohn Du } 461ace834feb02adabd61f628c4471147aea02d939cJohn Du break; 462188f205b5f093850d4cc627917a21204be36c56aZhihai Xu 463188f205b5f093850d4cc627917a21204be36c56aZhihai Xu case MESSAGE_SET_A2DP_AUDIO_STATE: 464188f205b5f093850d4cc627917a21204be36c56aZhihai Xu if (DEBUG) Log.v(TAG, "MESSAGE_SET_A2DP_AUDIO_STATE:" + msg.arg1); 465188f205b5f093850d4cc627917a21204be36c56aZhihai Xu updateA2dpAudioState(msg.arg1); 466188f205b5f093850d4cc627917a21204be36c56aZhihai Xu break; 467c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 468c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 469c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 470c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 471188f205b5f093850d4cc627917a21204be36c56aZhihai Xu private void updateA2dpAudioState(int state) { 472188f205b5f093850d4cc627917a21204be36c56aZhihai Xu boolean isPlaying = (state == BluetoothA2dp.STATE_PLAYING); 473188f205b5f093850d4cc627917a21204be36c56aZhihai Xu if (isPlaying != isPlayingState(mCurrentPlayState)) { 47422bad7047263a6924423d12718738fdcc7b0352cRavi Nagarajan /* if a2dp is streaming, check to make sure music is active */ 47522bad7047263a6924423d12718738fdcc7b0352cRavi Nagarajan if ( (isPlaying) && !mAudioManager.isMusicActive()) 47622bad7047263a6924423d12718738fdcc7b0352cRavi Nagarajan return; 477188f205b5f093850d4cc627917a21204be36c56aZhihai Xu updatePlayPauseState(isPlaying ? RemoteControlClient.PLAYSTATE_PLAYING : 478188f205b5f093850d4cc627917a21204be36c56aZhihai Xu RemoteControlClient.PLAYSTATE_PAUSED, 479188f205b5f093850d4cc627917a21204be36c56aZhihai Xu RemoteControlClient.PLAYBACK_POSITION_INVALID); 480188f205b5f093850d4cc627917a21204be36c56aZhihai Xu } 481188f205b5f093850d4cc627917a21204be36c56aZhihai Xu } 482188f205b5f093850d4cc627917a21204be36c56aZhihai Xu 483aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private void updatePlayPauseState(int state, long currentPosMs) { 484c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (DEBUG) Log.v(TAG, 485aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu "updatePlayPauseState, old=" + mCurrentPlayState + ", state=" + state); 486f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu boolean oldPosValid = (mCurrentPosMs != 487f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu RemoteControlClient.PLAYBACK_POSITION_ALWAYS_UNKNOWN); 488c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu int oldPlayStatus = convertPlayStateToPlayStatus(mCurrentPlayState); 489c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu int newPlayStatus = convertPlayStateToPlayStatus(state); 490f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu 491f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu if ((mCurrentPlayState == RemoteControlClient.PLAYSTATE_PLAYING) && 492f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu (mCurrentPlayState != state) && oldPosValid) { 493f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu mCurrentPosMs = getPlayPosition(); 494f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu } 495f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu 496f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu if (currentPosMs != RemoteControlClient.PLAYBACK_POSITION_INVALID) { 497f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu mCurrentPosMs = currentPosMs; 498f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu } 499aa6c1cb7f08a5d1fe2c878b587c62cf4dbb6ee8fZhihai Xu if ((state == RemoteControlClient.PLAYSTATE_PLAYING) && 500aa6c1cb7f08a5d1fe2c878b587c62cf4dbb6ee8fZhihai Xu ((currentPosMs != RemoteControlClient.PLAYBACK_POSITION_INVALID) || 501aa6c1cb7f08a5d1fe2c878b587c62cf4dbb6ee8fZhihai Xu (mCurrentPlayState != RemoteControlClient.PLAYSTATE_PLAYING))) { 502aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPlayStartTimeMs = SystemClock.elapsedRealtime(); 503aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 504aa6c1cb7f08a5d1fe2c878b587c62cf4dbb6ee8fZhihai Xu mCurrentPlayState = state; 505aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 506f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu boolean newPosValid = (mCurrentPosMs != 507f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu RemoteControlClient.PLAYBACK_POSITION_ALWAYS_UNKNOWN); 508f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu long playPosition = getPlayPosition(); 509aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mHandler.removeMessages(MESSAGE_PLAY_INTERVAL_TIMEOUT); 510aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu /* need send play position changed notification when play status is changed */ 511aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu if ((mPlayPosChangedNT == NOTIFICATION_TYPE_INTERIM) && 512aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu ((oldPlayStatus != newPlayStatus) || (oldPosValid != newPosValid) || 513f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu (newPosValid && ((playPosition >= mNextPosMs) || (playPosition <= mPrevPosMs))))) { 514aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPlayPosChangedNT = NOTIFICATION_TYPE_CHANGED; 515f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu registerNotificationRspPlayPosNative(mPlayPosChangedNT, (int)playPosition); 516aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 517aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu if ((mPlayPosChangedNT == NOTIFICATION_TYPE_INTERIM) && newPosValid && 518aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu (state == RemoteControlClient.PLAYSTATE_PLAYING)) { 519aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu Message msg = mHandler.obtainMessage(MESSAGE_PLAY_INTERVAL_TIMEOUT); 520f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu mHandler.sendMessageDelayed(msg, mNextPosMs - playPosition); 521aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 522aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 523c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if ((mPlayStatusChangedNT == NOTIFICATION_TYPE_INTERIM) && (oldPlayStatus != newPlayStatus)) { 524c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mPlayStatusChangedNT = NOTIFICATION_TYPE_CHANGED; 525c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu registerNotificationRspPlayStatusNative(mPlayStatusChangedNT, newPlayStatus); 526c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 527c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 528c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 529c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private void updateTransportControls(int transportControlFlags) { 530c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mTransportControlFlags = transportControlFlags; 531c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 532c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 533c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu class Metadata { 534c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private String artist; 535c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private String trackTitle; 536c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private String albumTitle; 537c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 538c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public Metadata() { 539c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu artist = null; 540c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu trackTitle = null; 541c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu albumTitle = null; 542c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 543c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 544c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu public String toString() { 545c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return "Metadata[artist=" + artist + " trackTitle=" + trackTitle + " albumTitle=" + 546c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu albumTitle + "]"; 547c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 548c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 549c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 5506e29e12add362546784126119f26f04fc760f021RoboErik private void updateMetadata(MetadataEditor data) { 551c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu String oldMetadata = mMetadata.toString(); 5526e29e12add362546784126119f26f04fc760f021RoboErik mMetadata.artist = data.getString(MediaMetadataRetriever.METADATA_KEY_ARTIST, null); 5536e29e12add362546784126119f26f04fc760f021RoboErik mMetadata.trackTitle = data.getString(MediaMetadataRetriever.METADATA_KEY_TITLE, null); 5546e29e12add362546784126119f26f04fc760f021RoboErik mMetadata.albumTitle = data.getString(MediaMetadataRetriever.METADATA_KEY_ALBUM, null); 555c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (!oldMetadata.equals(mMetadata.toString())) { 556c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mTrackNumber++; 557c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (mTrackChangedNT == NOTIFICATION_TYPE_INTERIM) { 558c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mTrackChangedNT = NOTIFICATION_TYPE_CHANGED; 559c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sendTrackChangedRsp(); 560c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 561aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 562f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu if (mCurrentPosMs != RemoteControlClient.PLAYBACK_POSITION_ALWAYS_UNKNOWN) { 563aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mCurrentPosMs = 0L; 564aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu if (mCurrentPlayState == RemoteControlClient.PLAYSTATE_PLAYING) { 565aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPlayStartTimeMs = SystemClock.elapsedRealtime(); 566aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 567aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 568aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu /* need send play position changed notification when track is changed */ 569aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu if (mPlayPosChangedNT == NOTIFICATION_TYPE_INTERIM) { 570aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPlayPosChangedNT = NOTIFICATION_TYPE_CHANGED; 571aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu registerNotificationRspPlayPosNative(mPlayPosChangedNT, 572aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu (int)getPlayPosition()); 573aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mHandler.removeMessages(MESSAGE_PLAY_INTERVAL_TIMEOUT); 574aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 575c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 576c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (DEBUG) Log.v(TAG, "mMetadata=" + mMetadata.toString()); 577aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 5786e29e12add362546784126119f26f04fc760f021RoboErik mSongLengthMs = data.getLong(MediaMetadataRetriever.METADATA_KEY_DURATION, 5796e29e12add362546784126119f26f04fc760f021RoboErik RemoteControlClient.PLAYBACK_POSITION_INVALID); 580aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu if (DEBUG) Log.v(TAG, "duration=" + mSongLengthMs); 581c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 582c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 58317675906064bb72fdcca75baa56cdf8bb8968d01John Du private void getRcFeatures(byte[] address, int features) { 58417675906064bb72fdcca75baa56cdf8bb8968d01John Du Message msg = mHandler.obtainMessage(MESSAGE_GET_RC_FEATURES, features, 0, 58517675906064bb72fdcca75baa56cdf8bb8968d01John Du Utils.getAddressStringFromByte(address)); 58617675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 58717675906064bb72fdcca75baa56cdf8bb8968d01John Du } 58817675906064bb72fdcca75baa56cdf8bb8968d01John Du 589c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private void getPlayStatus() { 590c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Message msg = mHandler.obtainMessage(MESSAGE_GET_PLAY_STATUS); 591c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.sendMessage(msg); 592c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 593c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 594c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private void getElementAttr(byte numAttr, int[] attrs) { 595c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu int i; 596c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu ArrayList<Integer> attrList = new ArrayList<Integer>(); 597c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu for (i = 0; i < numAttr; ++i) { 598c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu attrList.add(attrs[i]); 599c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 6006e29e12add362546784126119f26f04fc760f021RoboErik Message msg = mHandler.obtainMessage(MESSAGE_GET_ELEM_ATTRS, numAttr, 0, attrList); 601c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.sendMessage(msg); 602c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 603c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 604c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private void registerNotification(int eventId, int param) { 605c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_NOTIFICATION, eventId, param); 606c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mHandler.sendMessage(msg); 607c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 608c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 609c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private void processRegisterNotification(int eventId, int param) { 610c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu switch (eventId) { 611c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case EVT_PLAY_STATUS_CHANGED: 612c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mPlayStatusChangedNT = NOTIFICATION_TYPE_INTERIM; 613c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu registerNotificationRspPlayStatusNative(mPlayStatusChangedNT, 614c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu convertPlayStateToPlayStatus(mCurrentPlayState)); 615c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 616c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 617c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case EVT_TRACK_CHANGED: 618c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mTrackChangedNT = NOTIFICATION_TYPE_INTERIM; 619c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu sendTrackChangedRsp(); 620c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 621c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 622aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu case EVT_PLAY_POS_CHANGED: 623aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu long songPosition = getPlayPosition(); 624aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPlayPosChangedNT = NOTIFICATION_TYPE_INTERIM; 625aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPlaybackIntervalMs = (long)param * 1000L; 626f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu if (mCurrentPosMs != RemoteControlClient.PLAYBACK_POSITION_ALWAYS_UNKNOWN) { 627aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mNextPosMs = songPosition + mPlaybackIntervalMs; 628aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPrevPosMs = songPosition - mPlaybackIntervalMs; 629aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu if (mCurrentPlayState == RemoteControlClient.PLAYSTATE_PLAYING) { 630aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu Message msg = mHandler.obtainMessage(MESSAGE_PLAY_INTERVAL_TIMEOUT); 631aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mHandler.sendMessageDelayed(msg, mPlaybackIntervalMs); 632aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 633aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 634aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu registerNotificationRspPlayPosNative(mPlayPosChangedNT, (int)songPosition); 635aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu break; 636aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 637c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 638c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 639c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 640ace834feb02adabd61f628c4471147aea02d939cJohn Du private void handlePassthroughCmd(int id, int keyState) { 641ace834feb02adabd61f628c4471147aea02d939cJohn Du switch (id) { 642066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood case BluetoothAvrcp.PASSTHROUGH_ID_REWIND: 643ace834feb02adabd61f628c4471147aea02d939cJohn Du rewind(keyState); 644ace834feb02adabd61f628c4471147aea02d939cJohn Du break; 645066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood case BluetoothAvrcp.PASSTHROUGH_ID_FAST_FOR: 646ace834feb02adabd61f628c4471147aea02d939cJohn Du fastForward(keyState); 647ace834feb02adabd61f628c4471147aea02d939cJohn Du break; 648ace834feb02adabd61f628c4471147aea02d939cJohn Du } 649ace834feb02adabd61f628c4471147aea02d939cJohn Du } 650ace834feb02adabd61f628c4471147aea02d939cJohn Du 651ace834feb02adabd61f628c4471147aea02d939cJohn Du private void fastForward(int keyState) { 652ace834feb02adabd61f628c4471147aea02d939cJohn Du Message msg = mHandler.obtainMessage(MESSAGE_FAST_FORWARD, keyState, 0); 653ace834feb02adabd61f628c4471147aea02d939cJohn Du mHandler.sendMessage(msg); 654ace834feb02adabd61f628c4471147aea02d939cJohn Du } 655ace834feb02adabd61f628c4471147aea02d939cJohn Du 656ace834feb02adabd61f628c4471147aea02d939cJohn Du private void rewind(int keyState) { 657ace834feb02adabd61f628c4471147aea02d939cJohn Du Message msg = mHandler.obtainMessage(MESSAGE_REWIND, keyState, 0); 658ace834feb02adabd61f628c4471147aea02d939cJohn Du mHandler.sendMessage(msg); 659ace834feb02adabd61f628c4471147aea02d939cJohn Du } 660ace834feb02adabd61f628c4471147aea02d939cJohn Du 661ace834feb02adabd61f628c4471147aea02d939cJohn Du private void changePositionBy(long amount) { 662ace834feb02adabd61f628c4471147aea02d939cJohn Du long currentPosMs = getPlayPosition(); 663ace834feb02adabd61f628c4471147aea02d939cJohn Du if (currentPosMs == -1L) return; 664ace834feb02adabd61f628c4471147aea02d939cJohn Du long newPosMs = Math.max(0L, currentPosMs + amount); 6656e29e12add362546784126119f26f04fc760f021RoboErik mRemoteController.seekTo(newPosMs); 666ace834feb02adabd61f628c4471147aea02d939cJohn Du } 667ace834feb02adabd61f628c4471147aea02d939cJohn Du 668ace834feb02adabd61f628c4471147aea02d939cJohn Du private int getSkipMultiplier() { 669ace834feb02adabd61f628c4471147aea02d939cJohn Du long currentTime = SystemClock.elapsedRealtime(); 67019e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu long multi = (long) Math.pow(2, (currentTime - mSkipStartTime)/SKIP_DOUBLE_INTERVAL); 67119e4c6abe87d6c213e802ecf7af6c1d00e1f4b65Zhihai Xu return (int) Math.min(MAX_MULTIPLIER_VALUE, multi); 672ace834feb02adabd61f628c4471147aea02d939cJohn Du } 673ace834feb02adabd61f628c4471147aea02d939cJohn Du 674c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private void sendTrackChangedRsp() { 675c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu byte[] track = new byte[TRACK_ID_SIZE]; 67679d176b0f3d6cb33c7e52be6641fd4808ba87e93Zhihai Xu /* track is stored in big endian format */ 677c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu for (int i = 0; i < TRACK_ID_SIZE; ++i) { 67879d176b0f3d6cb33c7e52be6641fd4808ba87e93Zhihai Xu track[i] = (byte) (mTrackNumber >> (56 - 8 * i)); 679c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 680c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu registerNotificationRspTrackChangeNative(mTrackChangedNT, track); 681c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 682c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 683aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private long getPlayPosition() { 684aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu long songPosition = -1L; 685f56b7b37a156d9207074af80c156db5884bb8c08Zhihai Xu if (mCurrentPosMs != RemoteControlClient.PLAYBACK_POSITION_ALWAYS_UNKNOWN) { 686aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu if (mCurrentPlayState == RemoteControlClient.PLAYSTATE_PLAYING) { 687aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu songPosition = SystemClock.elapsedRealtime() - 688aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu mPlayStartTimeMs + mCurrentPosMs; 689aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } else { 690aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu songPosition = mCurrentPosMs; 691aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 692aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 693aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu if (DEBUG) Log.v(TAG, "position=" + songPosition); 694aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu return songPosition; 695aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 696aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 697c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private String getAttributeString(int attrId) { 698c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu String attrStr = null; 699c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu switch (attrId) { 700c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case MEDIA_ATTR_TITLE: 701c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu attrStr = mMetadata.trackTitle; 702c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 703c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 704c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case MEDIA_ATTR_ARTIST: 705c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu attrStr = mMetadata.artist; 706c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 707c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 708c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case MEDIA_ATTR_ALBUM: 709c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu attrStr = mMetadata.albumTitle; 710c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 711c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 712aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu case MEDIA_ATTR_PLAYING_TIME: 713aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu if (mSongLengthMs != 0L) { 714aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu attrStr = Long.toString(mSongLengthMs); 715aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu } 716aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu break; 717aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu 718c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 719c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (attrStr == null) { 720c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu attrStr = new String(); 721c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 722c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (DEBUG) Log.v(TAG, "getAttributeString:attrId=" + attrId + " str=" + attrStr); 723c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return attrStr; 724c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 725c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 726c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private int convertPlayStateToPlayStatus(int playState) { 727c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu int playStatus = PLAYSTATUS_ERROR; 728c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu switch (playState) { 729c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case RemoteControlClient.PLAYSTATE_PLAYING: 730c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case RemoteControlClient.PLAYSTATE_BUFFERING: 731c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_PLAYING; 732c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 733c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 734c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case RemoteControlClient.PLAYSTATE_STOPPED: 73579d176b0f3d6cb33c7e52be6641fd4808ba87e93Zhihai Xu case RemoteControlClient.PLAYSTATE_NONE: 736c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_STOPPED; 737c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 738c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 739c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case RemoteControlClient.PLAYSTATE_PAUSED: 740c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_PAUSED; 741c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 742c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 743c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case RemoteControlClient.PLAYSTATE_FAST_FORWARDING: 744c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case RemoteControlClient.PLAYSTATE_SKIPPING_FORWARDS: 745c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_FWD_SEEK; 746c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 747c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 748c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case RemoteControlClient.PLAYSTATE_REWINDING: 749c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS: 750c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_REV_SEEK; 751c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 752c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 753c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu case RemoteControlClient.PLAYSTATE_ERROR: 754c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu playStatus = PLAYSTATUS_ERROR; 755c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu break; 756c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 757c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 758c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu return playStatus; 759c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 760c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 761188f205b5f093850d4cc627917a21204be36c56aZhihai Xu private boolean isPlayingState(int playState) { 762188f205b5f093850d4cc627917a21204be36c56aZhihai Xu boolean isPlaying = false; 763188f205b5f093850d4cc627917a21204be36c56aZhihai Xu switch (playState) { 764188f205b5f093850d4cc627917a21204be36c56aZhihai Xu case RemoteControlClient.PLAYSTATE_PLAYING: 765188f205b5f093850d4cc627917a21204be36c56aZhihai Xu case RemoteControlClient.PLAYSTATE_BUFFERING: 766188f205b5f093850d4cc627917a21204be36c56aZhihai Xu isPlaying = true; 767188f205b5f093850d4cc627917a21204be36c56aZhihai Xu break; 768188f205b5f093850d4cc627917a21204be36c56aZhihai Xu default: 769188f205b5f093850d4cc627917a21204be36c56aZhihai Xu isPlaying = false; 770188f205b5f093850d4cc627917a21204be36c56aZhihai Xu break; 771188f205b5f093850d4cc627917a21204be36c56aZhihai Xu } 772188f205b5f093850d4cc627917a21204be36c56aZhihai Xu return isPlaying; 773188f205b5f093850d4cc627917a21204be36c56aZhihai Xu } 774188f205b5f093850d4cc627917a21204be36c56aZhihai Xu 77517675906064bb72fdcca75baa56cdf8bb8968d01John Du /** 77617675906064bb72fdcca75baa56cdf8bb8968d01John Du * This is called from AudioService. It will return whether this device supports abs volume. 77717675906064bb72fdcca75baa56cdf8bb8968d01John Du * NOT USED AT THE MOMENT. 77817675906064bb72fdcca75baa56cdf8bb8968d01John Du */ 77917675906064bb72fdcca75baa56cdf8bb8968d01John Du public boolean isAbsoluteVolumeSupported() { 78017675906064bb72fdcca75baa56cdf8bb8968d01John Du return ((mFeatures & BTRC_FEAT_ABSOLUTE_VOLUME) != 0); 78117675906064bb72fdcca75baa56cdf8bb8968d01John Du } 78217675906064bb72fdcca75baa56cdf8bb8968d01John Du 78317675906064bb72fdcca75baa56cdf8bb8968d01John Du /** 78417675906064bb72fdcca75baa56cdf8bb8968d01John Du * We get this call from AudioService. This will send a message to our handler object, 78517675906064bb72fdcca75baa56cdf8bb8968d01John Du * requesting our handler to call setVolumeNative() 78617675906064bb72fdcca75baa56cdf8bb8968d01John Du */ 78717675906064bb72fdcca75baa56cdf8bb8968d01John Du public void adjustVolume(int direction) { 78817675906064bb72fdcca75baa56cdf8bb8968d01John Du Message msg = mHandler.obtainMessage(MESSAGE_ADJUST_VOLUME, direction, 0); 78917675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 79017675906064bb72fdcca75baa56cdf8bb8968d01John Du } 79117675906064bb72fdcca75baa56cdf8bb8968d01John Du 79217675906064bb72fdcca75baa56cdf8bb8968d01John Du public void setAbsoluteVolume(int volume) { 79317675906064bb72fdcca75baa56cdf8bb8968d01John Du int avrcpVolume = convertToAvrcpVolume(volume); 79417675906064bb72fdcca75baa56cdf8bb8968d01John Du avrcpVolume = Math.min(AVRCP_MAX_VOL, Math.max(0, avrcpVolume)); 79517675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.removeMessages(MESSAGE_ADJUST_VOLUME); 79617675906064bb72fdcca75baa56cdf8bb8968d01John Du Message msg = mHandler.obtainMessage(MESSAGE_SET_ABSOLUTE_VOLUME, avrcpVolume, 0); 79717675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 7985c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta } 7995c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta 80017675906064bb72fdcca75baa56cdf8bb8968d01John Du /* Called in the native layer as a btrc_callback to return the volume set on the carkit in the 80117675906064bb72fdcca75baa56cdf8bb8968d01John Du * case when the volume is change locally on the carkit. This notification is not called when 80217675906064bb72fdcca75baa56cdf8bb8968d01John Du * the volume is changed from the phone. 80317675906064bb72fdcca75baa56cdf8bb8968d01John Du * 80417675906064bb72fdcca75baa56cdf8bb8968d01John Du * This method will send a message to our handler to change the local stored volume and notify 80517675906064bb72fdcca75baa56cdf8bb8968d01John Du * AudioService to update the UI 80617675906064bb72fdcca75baa56cdf8bb8968d01John Du */ 80717675906064bb72fdcca75baa56cdf8bb8968d01John Du private void volumeChangeCallback(int volume, int ctype) { 80817675906064bb72fdcca75baa56cdf8bb8968d01John Du Message msg = mHandler.obtainMessage(MESSAGE_VOLUME_CHANGED, volume, ctype); 80917675906064bb72fdcca75baa56cdf8bb8968d01John Du mHandler.sendMessage(msg); 81017675906064bb72fdcca75baa56cdf8bb8968d01John Du } 81117675906064bb72fdcca75baa56cdf8bb8968d01John Du 8122e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie private void notifyVolumeChanged(int volume) { 81317675906064bb72fdcca75baa56cdf8bb8968d01John Du volume = convertToAudioStreamVolume(volume); 8142e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 8152e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_BLUETOOTH_ABS_VOLUME); 81617675906064bb72fdcca75baa56cdf8bb8968d01John Du } 81717675906064bb72fdcca75baa56cdf8bb8968d01John Du 81817675906064bb72fdcca75baa56cdf8bb8968d01John Du private int convertToAudioStreamVolume(int volume) { 81917675906064bb72fdcca75baa56cdf8bb8968d01John Du // Rescale volume to match AudioSystem's volume 820e296684eab2bf622ff27cb1b3cd3008e919dfe30Christian Hanner return (int) Math.round((double) volume*mAudioStreamMax/AVRCP_MAX_VOL); 82117675906064bb72fdcca75baa56cdf8bb8968d01John Du } 82217675906064bb72fdcca75baa56cdf8bb8968d01John Du 82317675906064bb72fdcca75baa56cdf8bb8968d01John Du private int convertToAvrcpVolume(int volume) { 8242e90040ffc6f1c4cd5187338c9f708df4d380aeeMatthew Xie return (int) Math.ceil((double) volume*AVRCP_MAX_VOL/mAudioStreamMax); 82517675906064bb72fdcca75baa56cdf8bb8968d01John Du } 82617675906064bb72fdcca75baa56cdf8bb8968d01John Du 827188f205b5f093850d4cc627917a21204be36c56aZhihai Xu /** 828188f205b5f093850d4cc627917a21204be36c56aZhihai Xu * This is called from A2dpStateMachine to set A2dp audio state. 829188f205b5f093850d4cc627917a21204be36c56aZhihai Xu */ 830188f205b5f093850d4cc627917a21204be36c56aZhihai Xu public void setA2dpAudioState(int state) { 831188f205b5f093850d4cc627917a21204be36c56aZhihai Xu Message msg = mHandler.obtainMessage(MESSAGE_SET_A2DP_AUDIO_STATE, state, 0); 832188f205b5f093850d4cc627917a21204be36c56aZhihai Xu mHandler.sendMessage(msg); 833188f205b5f093850d4cc627917a21204be36c56aZhihai Xu } 834188f205b5f093850d4cc627917a21204be36c56aZhihai Xu 835838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood public void dump(StringBuilder sb) { 836838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood sb.append("AVRCP:\n"); 837838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mMetadata: " + mMetadata); 838838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mTransportControlFlags: " + mTransportControlFlags); 839838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mCurrentPlayState: " + mCurrentPlayState); 840838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mPlayStatusChangedNT: " + mPlayStatusChangedNT); 841838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mTrackChangedNT: " + mTrackChangedNT); 842838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mTrackNumber: " + mTrackNumber); 843838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mCurrentPosMs: " + mCurrentPosMs); 844838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mPlayStartTimeMs: " + mPlayStartTimeMs); 845838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mSongLengthMs: " + mSongLengthMs); 846838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mPlaybackIntervalMs: " + mPlaybackIntervalMs); 847838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mPlayPosChangedNT: " + mPlayPosChangedNT); 848838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mNextPosMs: " + mNextPosMs); 849838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mPrevPosMs: " + mPrevPosMs); 850838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mSkipStartTime: " + mSkipStartTime); 851838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mFeatures: " + mFeatures); 852838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mAbsoluteVolume: " + mAbsoluteVolume); 853838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mLastSetVolume: " + mLastSetVolume); 854838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mLastDirection: " + mLastDirection); 855838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mVolumeStep: " + mVolumeStep); 856838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mAudioStreamMax: " + mAudioStreamMax); 857838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mVolCmdInProgress: " + mVolCmdInProgress); 858838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mAbsVolRetryTimes: " + mAbsVolRetryTimes); 859838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood ProfileService.println(sb, "mSkipAmount: " + mSkipAmount); 860838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood } 861838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood 862c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu // Do not modify without updating the HAL bt_rc.h files. 863c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 864c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu // match up with btrc_play_status_t enum of bt_rc.h 865c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int PLAYSTATUS_STOPPED = 0; 866c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int PLAYSTATUS_PLAYING = 1; 867c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int PLAYSTATUS_PAUSED = 2; 868c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int PLAYSTATUS_FWD_SEEK = 3; 869c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int PLAYSTATUS_REV_SEEK = 4; 870c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int PLAYSTATUS_ERROR = 255; 871c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 872c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu // match up with btrc_media_attr_t enum of bt_rc.h 873c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int MEDIA_ATTR_TITLE = 1; 874c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int MEDIA_ATTR_ARTIST = 2; 875c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int MEDIA_ATTR_ALBUM = 3; 876c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int MEDIA_ATTR_TRACK_NUM = 4; 877c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int MEDIA_ATTR_NUM_TRACKS = 5; 878c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int MEDIA_ATTR_GENRE = 6; 879c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int MEDIA_ATTR_PLAYING_TIME = 7; 880c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 881c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu // match up with btrc_event_id_t enum of bt_rc.h 882c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int EVT_PLAY_STATUS_CHANGED = 1; 883c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int EVT_TRACK_CHANGED = 2; 884c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int EVT_TRACK_REACHED_END = 3; 885c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int EVT_TRACK_REACHED_START = 4; 886c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int EVT_PLAY_POS_CHANGED = 5; 887c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int EVT_BATT_STATUS_CHANGED = 6; 888c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int EVT_SYSTEM_STATUS_CHANGED = 7; 889c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int EVT_APP_SETTINGS_CHANGED = 8; 890c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 891c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu // match up with btrc_notification_type_t enum of bt_rc.h 892c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int NOTIFICATION_TYPE_INTERIM = 0; 893c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int NOTIFICATION_TYPE_CHANGED = 1; 894c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 895c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu // match up with BTRC_UID_SIZE of bt_rc.h 896c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu final static int TRACK_ID_SIZE = 8; 897c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu 898c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native static void classInitNative(); 899c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native void initNative(); 900c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native void cleanupNative(); 901c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native boolean getPlayStatusRspNative(int playStatus, int songLen, int songPos); 902c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native boolean getElementAttrRspNative(byte numAttr, int[] attrIds, String[] textArray); 903c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native boolean registerNotificationRspPlayStatusNative(int type, int playStatus); 904c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private native boolean registerNotificationRspTrackChangeNative(int type, byte[] track); 905aa1ffd5c6bd4f016c6ed452b3551e65872eaea8eZhihai Xu private native boolean registerNotificationRspPlayPosNative(int type, int playPos); 90617675906064bb72fdcca75baa56cdf8bb8968d01John Du private native boolean setVolumeNative(int volume); 9075c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta private native boolean sendPassThroughCommandNative(int keyCode, int keyState); 9085c86abdc7875a8fae28c57e3e36a0a8eaae5cb04Hemant Gupta 909c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu} 910