Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2011 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
Jim Miller | 5ecd811 | 2013-01-09 18:50:26 -0800 | [diff] [blame] | 17 | package com.android.keyguard; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 18 | |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 19 | import android.content.Context; |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 20 | import android.content.pm.PackageManager; |
| 21 | import android.content.res.Configuration; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 22 | import android.graphics.Bitmap; |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 23 | import android.graphics.ColorMatrix; |
| 24 | import android.graphics.ColorMatrixColorFilter; |
Adam Powell | 31049d7 | 2013-10-07 12:58:42 -0700 | [diff] [blame] | 25 | import android.graphics.PorterDuff; |
| 26 | import android.graphics.PorterDuffXfermode; |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 27 | import android.graphics.drawable.Drawable; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 28 | import android.media.AudioManager; |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 29 | import android.media.MediaMetadataEditor; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 30 | import android.media.MediaMetadataRetriever; |
| 31 | import android.media.RemoteControlClient; |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 32 | import android.media.RemoteController; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 33 | import android.os.Parcel; |
| 34 | import android.os.Parcelable; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 35 | import android.text.TextUtils; |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 36 | import android.text.format.DateFormat; |
| 37 | import android.transition.ChangeBounds; |
| 38 | import android.transition.ChangeText; |
| 39 | import android.transition.Fade; |
| 40 | import android.transition.TransitionManager; |
| 41 | import android.transition.TransitionSet; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 42 | import android.util.AttributeSet; |
Adam Powell | 43a372f | 2013-09-27 17:43:53 -0700 | [diff] [blame] | 43 | import android.util.DisplayMetrics; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 44 | import android.util.Log; |
| 45 | import android.view.KeyEvent; |
| 46 | import android.view.View; |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 47 | import android.view.ViewGroup; |
Jim Miller | bdca3c0 | 2012-10-29 19:11:50 -0700 | [diff] [blame] | 48 | import android.widget.FrameLayout; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 49 | import android.widget.ImageView; |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 50 | import android.widget.SeekBar; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 51 | import android.widget.TextView; |
| 52 | |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 53 | import java.text.SimpleDateFormat; |
| 54 | import java.util.Date; |
| 55 | import java.util.TimeZone; |
| 56 | |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 57 | /** |
| 58 | * This is the widget responsible for showing music controls in keyguard. |
| 59 | */ |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 60 | public class KeyguardTransportControlView extends FrameLayout { |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 61 | |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 62 | private static final int RESET_TO_METADATA_DELAY = 5000; |
Jorim Jaggi | 5cf1787 | 2014-03-26 18:31:48 +0100 | [diff] [blame] | 63 | protected static final boolean DEBUG = KeyguardConstants.DEBUG; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 64 | protected static final String TAG = "TransportControlView"; |
| 65 | |
Chet Haase | df32aa8 | 2013-10-21 17:19:37 -0700 | [diff] [blame] | 66 | private static final boolean ANIMATE_TRANSITIONS = true; |
Jim Miller | cc747ad | 2013-10-24 19:53:09 -0700 | [diff] [blame] | 67 | protected static final long QUIESCENT_PLAYBACK_FACTOR = 1000; |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 68 | |
| 69 | private ViewGroup mMetadataContainer; |
| 70 | private ViewGroup mInfoContainer; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 71 | private TextView mTrackTitle; |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 72 | private TextView mTrackArtistAlbum; |
| 73 | |
| 74 | private View mTransientSeek; |
| 75 | private SeekBar mTransientSeekBar; |
| 76 | private TextView mTransientSeekTimeElapsed; |
Chris Wren | 6af85cc | 2013-10-29 13:19:54 -0400 | [diff] [blame] | 77 | private TextView mTransientSeekTimeTotal; |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 78 | |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 79 | private ImageView mBtnPrev; |
| 80 | private ImageView mBtnPlay; |
| 81 | private ImageView mBtnNext; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 82 | private Metadata mMetadata = new Metadata(); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 83 | private int mTransportControlFlags; |
| 84 | private int mCurrentPlayState; |
| 85 | private AudioManager mAudioManager; |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 86 | private RemoteController mRemoteController; |
| 87 | |
| 88 | private ImageView mBadge; |
| 89 | |
| 90 | private boolean mSeekEnabled; |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 91 | private java.text.DateFormat mFormat; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 92 | |
Jim Miller | cc747ad | 2013-10-24 19:53:09 -0700 | [diff] [blame] | 93 | private Date mTempDate = new Date(); |
Chris Wren | cab6965 | 2013-10-29 13:04:00 -0400 | [diff] [blame] | 94 | |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 95 | /** |
| 96 | * The metadata which should be populated into the view once we've been attached |
| 97 | */ |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 98 | private RemoteController.MetadataEditor mPopulateMetadataWhenAttached = null; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 99 | |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 100 | private RemoteController.OnClientUpdateListener mRCClientUpdateListener = |
| 101 | new RemoteController.OnClientUpdateListener() { |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 102 | @Override |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 103 | public void onClientChange(boolean clearing) { |
Craig Mautner | 8334192 | 2013-10-30 10:29:38 -0700 | [diff] [blame] | 104 | if (clearing) { |
| 105 | clearMetadata(); |
| 106 | } |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 107 | } |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 108 | |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 109 | @Override |
| 110 | public void onClientPlaybackStateUpdate(int state) { |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 111 | updatePlayPauseState(state); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 112 | } |
| 113 | |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 114 | @Override |
| 115 | public void onClientPlaybackStateUpdate(int state, long stateChangeTimeMs, |
Jean-Michel Trivi | bc43b4c | 2013-03-22 09:30:50 -0700 | [diff] [blame] | 116 | long currentPosMs, float speed) { |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 117 | updatePlayPauseState(state); |
| 118 | if (DEBUG) Log.d(TAG, "onClientPlaybackStateUpdate(state=" + state + |
| 119 | ", stateChangeTimeMs=" + stateChangeTimeMs + ", currentPosMs=" + currentPosMs + |
| 120 | ", speed=" + speed + ")"); |
Jim Miller | cc747ad | 2013-10-24 19:53:09 -0700 | [diff] [blame] | 121 | |
| 122 | removeCallbacks(mUpdateSeekBars); |
| 123 | // Since the music client may be responding to historical events that cause the |
| 124 | // playback state to change dramatically, wait until things become quiescent before |
| 125 | // resuming automatic scrub position update. |
| 126 | if (mTransientSeek.getVisibility() == View.VISIBLE |
| 127 | && playbackPositionShouldMove(mCurrentPlayState)) { |
| 128 | postDelayed(mUpdateSeekBars, QUIESCENT_PLAYBACK_FACTOR); |
| 129 | } |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 130 | } |
| 131 | |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 132 | @Override |
| 133 | public void onClientTransportControlUpdate(int transportControlFlags) { |
| 134 | updateTransportControls(transportControlFlags); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 135 | } |
| 136 | |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 137 | @Override |
| 138 | public void onClientMetadataUpdate(RemoteController.MetadataEditor metadataEditor) { |
| 139 | updateMetadata(metadataEditor); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 140 | } |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 141 | }; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 142 | |
Jim Miller | cc747ad | 2013-10-24 19:53:09 -0700 | [diff] [blame] | 143 | private class UpdateSeekBarRunnable implements Runnable { |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 144 | public void run() { |
Jim Miller | cc747ad | 2013-10-24 19:53:09 -0700 | [diff] [blame] | 145 | boolean seekAble = updateOnce(); |
| 146 | if (seekAble) { |
Jim Miller | 1693f6a | 2013-10-20 17:21:57 -0700 | [diff] [blame] | 147 | removeCallbacks(this); |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 148 | postDelayed(this, 1000); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 149 | } |
| 150 | } |
Jim Miller | cc747ad | 2013-10-24 19:53:09 -0700 | [diff] [blame] | 151 | public boolean updateOnce() { |
| 152 | return updateSeekBars(); |
| 153 | } |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 154 | }; |
| 155 | |
Jim Miller | cc747ad | 2013-10-24 19:53:09 -0700 | [diff] [blame] | 156 | private final UpdateSeekBarRunnable mUpdateSeekBars = new UpdateSeekBarRunnable(); |
| 157 | |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 158 | private final Runnable mResetToMetadata = new Runnable() { |
| 159 | public void run() { |
| 160 | resetToMetadata(); |
| 161 | } |
| 162 | }; |
| 163 | |
| 164 | private final OnClickListener mTransportCommandListener = new OnClickListener() { |
| 165 | public void onClick(View v) { |
| 166 | int keyCode = -1; |
| 167 | if (v == mBtnPrev) { |
| 168 | keyCode = KeyEvent.KEYCODE_MEDIA_PREVIOUS; |
| 169 | } else if (v == mBtnNext) { |
| 170 | keyCode = KeyEvent.KEYCODE_MEDIA_NEXT; |
| 171 | } else if (v == mBtnPlay) { |
| 172 | keyCode = KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE; |
| 173 | } |
| 174 | if (keyCode != -1) { |
| 175 | sendMediaButtonClick(keyCode); |
Jim Miller | cc747ad | 2013-10-24 19:53:09 -0700 | [diff] [blame] | 176 | delayResetToMetadata(); // if the scrub bar is showing, keep showing it. |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 177 | } |
| 178 | } |
| 179 | }; |
| 180 | |
| 181 | private final OnLongClickListener mTransportShowSeekBarListener = new OnLongClickListener() { |
| 182 | @Override |
| 183 | public boolean onLongClick(View v) { |
| 184 | if (mSeekEnabled) { |
| 185 | return tryToggleSeekBar(); |
| 186 | } |
| 187 | return false; |
| 188 | } |
| 189 | }; |
| 190 | |
Jim Miller | cc747ad | 2013-10-24 19:53:09 -0700 | [diff] [blame] | 191 | // This class is here to throttle scrub position updates to the music client |
| 192 | class FutureSeekRunnable implements Runnable { |
| 193 | private int mProgress; |
| 194 | private boolean mPending; |
| 195 | |
| 196 | public void run() { |
| 197 | scrubTo(mProgress); |
| 198 | mPending = false; |
| 199 | } |
| 200 | |
| 201 | void setProgress(int progress) { |
| 202 | mProgress = progress; |
| 203 | if (!mPending) { |
| 204 | mPending = true; |
| 205 | postDelayed(this, 30); |
| 206 | } |
| 207 | } |
| 208 | }; |
| 209 | |
| 210 | // This is here because RemoteControlClient's method isn't visible :/ |
| 211 | private final static boolean playbackPositionShouldMove(int playstate) { |
| 212 | switch(playstate) { |
| 213 | case RemoteControlClient.PLAYSTATE_STOPPED: |
| 214 | case RemoteControlClient.PLAYSTATE_PAUSED: |
| 215 | case RemoteControlClient.PLAYSTATE_BUFFERING: |
| 216 | case RemoteControlClient.PLAYSTATE_ERROR: |
| 217 | case RemoteControlClient.PLAYSTATE_SKIPPING_FORWARDS: |
| 218 | case RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS: |
| 219 | return false; |
| 220 | case RemoteControlClient.PLAYSTATE_PLAYING: |
| 221 | case RemoteControlClient.PLAYSTATE_FAST_FORWARDING: |
| 222 | case RemoteControlClient.PLAYSTATE_REWINDING: |
| 223 | default: |
| 224 | return true; |
| 225 | } |
| 226 | } |
| 227 | |
| 228 | private final FutureSeekRunnable mFutureSeekRunnable = new FutureSeekRunnable(); |
| 229 | |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 230 | private final SeekBar.OnSeekBarChangeListener mOnSeekBarChangeListener = |
| 231 | new SeekBar.OnSeekBarChangeListener() { |
| 232 | @Override |
| 233 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { |
| 234 | if (fromUser) { |
Jim Miller | cc747ad | 2013-10-24 19:53:09 -0700 | [diff] [blame] | 235 | mFutureSeekRunnable.setProgress(progress); |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 236 | delayResetToMetadata(); |
Jim Miller | cc747ad | 2013-10-24 19:53:09 -0700 | [diff] [blame] | 237 | mTempDate.setTime(progress); |
| 238 | mTransientSeekTimeElapsed.setText(mFormat.format(mTempDate)); |
| 239 | } else { |
| 240 | updateSeekDisplay(); |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 241 | } |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 242 | } |
| 243 | |
| 244 | @Override |
| 245 | public void onStartTrackingTouch(SeekBar seekBar) { |
Jim Miller | cc747ad | 2013-10-24 19:53:09 -0700 | [diff] [blame] | 246 | delayResetToMetadata(); |
| 247 | removeCallbacks(mUpdateSeekBars); // don't update during user interaction |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 248 | } |
| 249 | |
| 250 | @Override |
| 251 | public void onStopTrackingTouch(SeekBar seekBar) { |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 252 | } |
| 253 | }; |
| 254 | |
| 255 | private static final int TRANSITION_DURATION = 200; |
| 256 | private final TransitionSet mMetadataChangeTransition; |
| 257 | |
| 258 | KeyguardHostView.TransportControlCallback mTransportControlCallback; |
| 259 | |
Jim Miller | 20daffd | 2013-10-07 14:59:53 -0700 | [diff] [blame] | 260 | private final KeyguardUpdateMonitorCallback mUpdateMonitor |
| 261 | = new KeyguardUpdateMonitorCallback() { |
| 262 | public void onScreenTurnedOff(int why) { |
| 263 | setEnableMarquee(false); |
Craig Mautner | 8334192 | 2013-10-30 10:29:38 -0700 | [diff] [blame] | 264 | } |
Jim Miller | 20daffd | 2013-10-07 14:59:53 -0700 | [diff] [blame] | 265 | public void onScreenTurnedOn() { |
| 266 | setEnableMarquee(true); |
Craig Mautner | 8334192 | 2013-10-30 10:29:38 -0700 | [diff] [blame] | 267 | } |
Jim Miller | 20daffd | 2013-10-07 14:59:53 -0700 | [diff] [blame] | 268 | }; |
| 269 | |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 270 | public KeyguardTransportControlView(Context context, AttributeSet attrs) { |
| 271 | super(context, attrs); |
Dianne Hackborn | 40e9f29 | 2012-11-27 19:12:23 -0800 | [diff] [blame] | 272 | if (DEBUG) Log.v(TAG, "Create TCV " + this); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 273 | mAudioManager = new AudioManager(mContext); |
| 274 | mCurrentPlayState = RemoteControlClient.PLAYSTATE_NONE; // until we get a callback |
Jean-Michel Trivi | f108cdd9 | 2013-09-27 18:37:36 -0700 | [diff] [blame] | 275 | mRemoteController = new RemoteController(context, mRCClientUpdateListener); |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 276 | |
| 277 | final DisplayMetrics dm = context.getResources().getDisplayMetrics(); |
| 278 | final int dim = Math.max(dm.widthPixels, dm.heightPixels); |
| 279 | mRemoteController.setArtworkConfiguration(true, dim, dim); |
| 280 | |
| 281 | final ChangeText tc = new ChangeText(); |
| 282 | tc.setChangeBehavior(ChangeText.CHANGE_BEHAVIOR_OUT_IN); |
| 283 | final TransitionSet inner = new TransitionSet(); |
| 284 | inner.addTransition(tc).addTransition(new ChangeBounds()); |
| 285 | final TransitionSet tg = new TransitionSet(); |
| 286 | tg.addTransition(new Fade(Fade.OUT)).addTransition(inner). |
| 287 | addTransition(new Fade(Fade.IN)); |
| 288 | tg.setOrdering(TransitionSet.ORDERING_SEQUENTIAL); |
| 289 | tg.setDuration(TRANSITION_DURATION); |
| 290 | mMetadataChangeTransition = tg; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 291 | } |
| 292 | |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 293 | private void updateTransportControls(int transportControlFlags) { |
| 294 | mTransportControlFlags = transportControlFlags; |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 295 | setSeekBarsEnabled( |
| 296 | (transportControlFlags & RemoteControlClient.FLAG_KEY_MEDIA_POSITION_UPDATE) != 0); |
| 297 | } |
| 298 | |
| 299 | void setSeekBarsEnabled(boolean enabled) { |
| 300 | if (enabled == mSeekEnabled) return; |
| 301 | |
| 302 | mSeekEnabled = enabled; |
Jim Miller | cc747ad | 2013-10-24 19:53:09 -0700 | [diff] [blame] | 303 | if (mTransientSeek.getVisibility() == VISIBLE && !enabled) { |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 304 | mTransientSeek.setVisibility(INVISIBLE); |
| 305 | mMetadataContainer.setVisibility(VISIBLE); |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 306 | cancelResetToMetadata(); |
| 307 | } |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 308 | } |
| 309 | |
| 310 | public void setTransportControlCallback(KeyguardHostView.TransportControlCallback |
| 311 | transportControlCallback) { |
| 312 | mTransportControlCallback = transportControlCallback; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 313 | } |
| 314 | |
Jim Miller | 20daffd | 2013-10-07 14:59:53 -0700 | [diff] [blame] | 315 | private void setEnableMarquee(boolean enabled) { |
| 316 | if (DEBUG) Log.v(TAG, (enabled ? "Enable" : "Disable") + " transport text marquee"); |
Adam Powell | 31049d7 | 2013-10-07 12:58:42 -0700 | [diff] [blame] | 317 | if (mTrackTitle != null) mTrackTitle.setSelected(enabled); |
| 318 | if (mTrackArtistAlbum != null) mTrackTitle.setSelected(enabled); |
Jim Miller | 20daffd | 2013-10-07 14:59:53 -0700 | [diff] [blame] | 319 | } |
| 320 | |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 321 | @Override |
| 322 | public void onFinishInflate() { |
| 323 | super.onFinishInflate(); |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 324 | mInfoContainer = (ViewGroup) findViewById(R.id.info_container); |
| 325 | mMetadataContainer = (ViewGroup) findViewById(R.id.metadata_container); |
| 326 | mBadge = (ImageView) findViewById(R.id.badge); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 327 | mTrackTitle = (TextView) findViewById(R.id.title); |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 328 | mTrackArtistAlbum = (TextView) findViewById(R.id.artist_album); |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 329 | mTransientSeek = findViewById(R.id.transient_seek); |
| 330 | mTransientSeekBar = (SeekBar) findViewById(R.id.transient_seek_bar); |
| 331 | mTransientSeekBar.setOnSeekBarChangeListener(mOnSeekBarChangeListener); |
| 332 | mTransientSeekTimeElapsed = (TextView) findViewById(R.id.transient_seek_time_elapsed); |
Chris Wren | 6af85cc | 2013-10-29 13:19:54 -0400 | [diff] [blame] | 333 | mTransientSeekTimeTotal = (TextView) findViewById(R.id.transient_seek_time_remaining); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 334 | mBtnPrev = (ImageView) findViewById(R.id.btn_prev); |
| 335 | mBtnPlay = (ImageView) findViewById(R.id.btn_play); |
| 336 | mBtnNext = (ImageView) findViewById(R.id.btn_next); |
| 337 | final View buttons[] = { mBtnPrev, mBtnPlay, mBtnNext }; |
| 338 | for (View view : buttons) { |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 339 | view.setOnClickListener(mTransportCommandListener); |
| 340 | view.setOnLongClickListener(mTransportShowSeekBarListener); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 341 | } |
Jim Miller | 20daffd | 2013-10-07 14:59:53 -0700 | [diff] [blame] | 342 | final boolean screenOn = KeyguardUpdateMonitor.getInstance(mContext).isScreenOn(); |
| 343 | setEnableMarquee(screenOn); |
Jim Miller | cc747ad | 2013-10-24 19:53:09 -0700 | [diff] [blame] | 344 | // Allow long-press anywhere else in this view to show the seek bar |
| 345 | setOnLongClickListener(mTransportShowSeekBarListener); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 346 | } |
| 347 | |
| 348 | @Override |
| 349 | public void onAttachedToWindow() { |
| 350 | super.onAttachedToWindow(); |
| 351 | if (DEBUG) Log.v(TAG, "onAttachToWindow()"); |
| 352 | if (mPopulateMetadataWhenAttached != null) { |
| 353 | updateMetadata(mPopulateMetadataWhenAttached); |
| 354 | mPopulateMetadataWhenAttached = null; |
| 355 | } |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 356 | if (DEBUG) Log.v(TAG, "Registering TCV " + this); |
Adam Powell | 3b435fb | 2013-10-15 19:15:39 -0700 | [diff] [blame] | 357 | mMetadata.clear(); |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 358 | mAudioManager.registerRemoteController(mRemoteController); |
Jim Miller | 20daffd | 2013-10-07 14:59:53 -0700 | [diff] [blame] | 359 | KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitor); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 360 | } |
| 361 | |
| 362 | @Override |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 363 | protected void onConfigurationChanged(Configuration newConfig) { |
| 364 | super.onConfigurationChanged(newConfig); |
| 365 | final DisplayMetrics dm = getContext().getResources().getDisplayMetrics(); |
| 366 | final int dim = Math.max(dm.widthPixels, dm.heightPixels); |
| 367 | mRemoteController.setArtworkConfiguration(true, dim, dim); |
Jean-Michel Trivi | 9e589b9 | 2013-03-08 14:30:10 -0800 | [diff] [blame] | 368 | } |
| 369 | |
| 370 | @Override |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 371 | public void onDetachedFromWindow() { |
| 372 | if (DEBUG) Log.v(TAG, "onDetachFromWindow()"); |
| 373 | super.onDetachedFromWindow(); |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 374 | if (DEBUG) Log.v(TAG, "Unregistering TCV " + this); |
| 375 | mAudioManager.unregisterRemoteController(mRemoteController); |
Jim Miller | 20daffd | 2013-10-07 14:59:53 -0700 | [diff] [blame] | 376 | KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitor); |
Adam Powell | 3b435fb | 2013-10-15 19:15:39 -0700 | [diff] [blame] | 377 | mMetadata.clear(); |
Jim Miller | b2c6469 | 2013-10-15 20:09:07 -0700 | [diff] [blame] | 378 | removeCallbacks(mUpdateSeekBars); |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 379 | } |
| 380 | |
Craig Mautner | 8334192 | 2013-10-30 10:29:38 -0700 | [diff] [blame] | 381 | @Override |
| 382 | protected Parcelable onSaveInstanceState() { |
| 383 | SavedState ss = new SavedState(super.onSaveInstanceState()); |
| 384 | ss.artist = mMetadata.artist; |
| 385 | ss.trackTitle = mMetadata.trackTitle; |
| 386 | ss.albumTitle = mMetadata.albumTitle; |
| 387 | ss.duration = mMetadata.duration; |
| 388 | ss.bitmap = mMetadata.bitmap; |
| 389 | return ss; |
| 390 | } |
| 391 | |
| 392 | @Override |
| 393 | protected void onRestoreInstanceState(Parcelable state) { |
| 394 | if (!(state instanceof SavedState)) { |
| 395 | super.onRestoreInstanceState(state); |
| 396 | return; |
| 397 | } |
| 398 | SavedState ss = (SavedState) state; |
| 399 | super.onRestoreInstanceState(ss.getSuperState()); |
| 400 | mMetadata.artist = ss.artist; |
| 401 | mMetadata.trackTitle = ss.trackTitle; |
| 402 | mMetadata.albumTitle = ss.albumTitle; |
| 403 | mMetadata.duration = ss.duration; |
| 404 | mMetadata.bitmap = ss.bitmap; |
| 405 | populateMetadata(); |
| 406 | } |
| 407 | |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 408 | void setBadgeIcon(Drawable bmp) { |
| 409 | mBadge.setImageDrawable(bmp); |
| 410 | |
| 411 | final ColorMatrix cm = new ColorMatrix(); |
| 412 | cm.setSaturation(0); |
| 413 | mBadge.setColorFilter(new ColorMatrixColorFilter(cm)); |
Adam Powell | 31049d7 | 2013-10-07 12:58:42 -0700 | [diff] [blame] | 414 | mBadge.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN)); |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 415 | mBadge.setImageAlpha(0xef); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 416 | } |
| 417 | |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 418 | class Metadata { |
| 419 | private String artist; |
| 420 | private String trackTitle; |
| 421 | private String albumTitle; |
| 422 | private Bitmap bitmap; |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 423 | private long duration; |
| 424 | |
| 425 | public void clear() { |
| 426 | artist = null; |
| 427 | trackTitle = null; |
| 428 | albumTitle = null; |
| 429 | bitmap = null; |
| 430 | duration = -1; |
| 431 | } |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 432 | |
| 433 | public String toString() { |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 434 | return "Metadata[artist=" + artist + " trackTitle=" + trackTitle + |
| 435 | " albumTitle=" + albumTitle + " duration=" + duration + "]"; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 436 | } |
| 437 | } |
| 438 | |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 439 | void clearMetadata() { |
| 440 | mPopulateMetadataWhenAttached = null; |
| 441 | mMetadata.clear(); |
| 442 | populateMetadata(); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 443 | } |
| 444 | |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 445 | void updateMetadata(RemoteController.MetadataEditor data) { |
| 446 | if (isAttachedToWindow()) { |
| 447 | mMetadata.artist = data.getString(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST, |
| 448 | mMetadata.artist); |
| 449 | mMetadata.trackTitle = data.getString(MediaMetadataRetriever.METADATA_KEY_TITLE, |
| 450 | mMetadata.trackTitle); |
| 451 | mMetadata.albumTitle = data.getString(MediaMetadataRetriever.METADATA_KEY_ALBUM, |
| 452 | mMetadata.albumTitle); |
| 453 | mMetadata.duration = data.getLong(MediaMetadataRetriever.METADATA_KEY_DURATION, -1); |
| 454 | mMetadata.bitmap = data.getBitmap(MediaMetadataEditor.BITMAP_KEY_ARTWORK, |
| 455 | mMetadata.bitmap); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 456 | populateMetadata(); |
| 457 | } else { |
| 458 | mPopulateMetadataWhenAttached = data; |
| 459 | } |
| 460 | } |
| 461 | |
| 462 | /** |
| 463 | * Populates the given metadata into the view |
| 464 | */ |
| 465 | private void populateMetadata() { |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 466 | if (ANIMATE_TRANSITIONS && isLaidOut() && mMetadataContainer.getVisibility() == VISIBLE) { |
| 467 | TransitionManager.beginDelayedTransition(mMetadataContainer, mMetadataChangeTransition); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 468 | } |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 469 | |
| 470 | final String remoteClientPackage = mRemoteController.getRemoteControlClientPackageName(); |
| 471 | Drawable badgeIcon = null; |
| 472 | try { |
| 473 | badgeIcon = getContext().getPackageManager().getApplicationIcon(remoteClientPackage); |
| 474 | } catch (PackageManager.NameNotFoundException e) { |
| 475 | Log.e(TAG, "Couldn't get remote control client package icon", e); |
| 476 | } |
| 477 | setBadgeIcon(badgeIcon); |
Adam Powell | 3b435fb | 2013-10-15 19:15:39 -0700 | [diff] [blame] | 478 | mTrackTitle.setText(!TextUtils.isEmpty(mMetadata.trackTitle) |
| 479 | ? mMetadata.trackTitle : null); |
| 480 | |
| 481 | final StringBuilder sb = new StringBuilder(); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 482 | if (!TextUtils.isEmpty(mMetadata.artist)) { |
| 483 | if (sb.length() != 0) { |
| 484 | sb.append(" - "); |
| 485 | } |
| 486 | sb.append(mMetadata.artist); |
| 487 | } |
| 488 | if (!TextUtils.isEmpty(mMetadata.albumTitle)) { |
| 489 | if (sb.length() != 0) { |
| 490 | sb.append(" - "); |
| 491 | } |
| 492 | sb.append(mMetadata.albumTitle); |
| 493 | } |
Adam Powell | 3b435fb | 2013-10-15 19:15:39 -0700 | [diff] [blame] | 494 | |
| 495 | final String trackArtistAlbum = sb.toString(); |
| 496 | mTrackArtistAlbum.setText(!TextUtils.isEmpty(trackArtistAlbum) ? |
| 497 | trackArtistAlbum : null); |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 498 | |
| 499 | if (mMetadata.duration >= 0) { |
| 500 | setSeekBarsEnabled(true); |
| 501 | setSeekBarDuration(mMetadata.duration); |
| 502 | |
| 503 | final String skeleton; |
| 504 | |
| 505 | if (mMetadata.duration >= 86400000) { |
| 506 | skeleton = "DDD kk mm ss"; |
| 507 | } else if (mMetadata.duration >= 3600000) { |
| 508 | skeleton = "kk mm ss"; |
| 509 | } else { |
| 510 | skeleton = "mm ss"; |
| 511 | } |
| 512 | mFormat = new SimpleDateFormat(DateFormat.getBestDateTimePattern( |
| 513 | getContext().getResources().getConfiguration().locale, |
| 514 | skeleton)); |
| 515 | mFormat.setTimeZone(TimeZone.getTimeZone("GMT+0")); |
| 516 | } else { |
| 517 | setSeekBarsEnabled(false); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 518 | } |
| 519 | |
Jim Miller | 1693f6a | 2013-10-20 17:21:57 -0700 | [diff] [blame] | 520 | KeyguardUpdateMonitor.getInstance(getContext()).dispatchSetBackground(mMetadata.bitmap); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 521 | final int flags = mTransportControlFlags; |
| 522 | setVisibilityBasedOnFlag(mBtnPrev, flags, RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS); |
| 523 | setVisibilityBasedOnFlag(mBtnNext, flags, RemoteControlClient.FLAG_KEY_MEDIA_NEXT); |
| 524 | setVisibilityBasedOnFlag(mBtnPlay, flags, |
| 525 | RemoteControlClient.FLAG_KEY_MEDIA_PLAY |
| 526 | | RemoteControlClient.FLAG_KEY_MEDIA_PAUSE |
| 527 | | RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE |
| 528 | | RemoteControlClient.FLAG_KEY_MEDIA_STOP); |
| 529 | |
| 530 | updatePlayPauseState(mCurrentPlayState); |
| 531 | } |
| 532 | |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 533 | void updateSeekDisplay() { |
| 534 | if (mMetadata != null && mRemoteController != null && mFormat != null) { |
Jim Miller | cc747ad | 2013-10-24 19:53:09 -0700 | [diff] [blame] | 535 | mTempDate.setTime(mRemoteController.getEstimatedMediaPosition()); |
| 536 | mTransientSeekTimeElapsed.setText(mFormat.format(mTempDate)); |
| 537 | mTempDate.setTime(mMetadata.duration); |
| 538 | mTransientSeekTimeTotal.setText(mFormat.format(mTempDate)); |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 539 | |
Jim Miller | cc747ad | 2013-10-24 19:53:09 -0700 | [diff] [blame] | 540 | if (DEBUG) Log.d(TAG, "updateSeekDisplay timeElapsed=" + mTempDate + |
Chris Wren | 6af85cc | 2013-10-29 13:19:54 -0400 | [diff] [blame] | 541 | " duration=" + mMetadata.duration); |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 542 | } |
| 543 | } |
| 544 | |
| 545 | boolean tryToggleSeekBar() { |
| 546 | if (ANIMATE_TRANSITIONS) { |
| 547 | TransitionManager.beginDelayedTransition(mInfoContainer); |
| 548 | } |
| 549 | if (mTransientSeek.getVisibility() == VISIBLE) { |
| 550 | mTransientSeek.setVisibility(INVISIBLE); |
| 551 | mMetadataContainer.setVisibility(VISIBLE); |
| 552 | cancelResetToMetadata(); |
Jim Miller | cc747ad | 2013-10-24 19:53:09 -0700 | [diff] [blame] | 553 | removeCallbacks(mUpdateSeekBars); // don't update if scrubber isn't visible |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 554 | } else { |
| 555 | mTransientSeek.setVisibility(VISIBLE); |
| 556 | mMetadataContainer.setVisibility(INVISIBLE); |
| 557 | delayResetToMetadata(); |
Jim Miller | cc747ad | 2013-10-24 19:53:09 -0700 | [diff] [blame] | 558 | if (playbackPositionShouldMove(mCurrentPlayState)) { |
| 559 | mUpdateSeekBars.run(); |
| 560 | } else { |
| 561 | mUpdateSeekBars.updateOnce(); |
| 562 | } |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 563 | } |
| 564 | mTransportControlCallback.userActivity(); |
| 565 | return true; |
| 566 | } |
| 567 | |
| 568 | void resetToMetadata() { |
| 569 | if (ANIMATE_TRANSITIONS) { |
| 570 | TransitionManager.beginDelayedTransition(mInfoContainer); |
| 571 | } |
| 572 | if (mTransientSeek.getVisibility() == VISIBLE) { |
| 573 | mTransientSeek.setVisibility(INVISIBLE); |
| 574 | mMetadataContainer.setVisibility(VISIBLE); |
| 575 | } |
| 576 | // TODO Also hide ratings, if applicable |
| 577 | } |
| 578 | |
| 579 | void delayResetToMetadata() { |
| 580 | removeCallbacks(mResetToMetadata); |
| 581 | postDelayed(mResetToMetadata, RESET_TO_METADATA_DELAY); |
| 582 | } |
| 583 | |
| 584 | void cancelResetToMetadata() { |
| 585 | removeCallbacks(mResetToMetadata); |
| 586 | } |
| 587 | |
| 588 | void setSeekBarDuration(long duration) { |
| 589 | mTransientSeekBar.setMax((int) duration); |
| 590 | } |
| 591 | |
| 592 | void scrubTo(int progress) { |
| 593 | mRemoteController.seekTo(progress); |
| 594 | mTransportControlCallback.userActivity(); |
| 595 | } |
| 596 | |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 597 | private static void setVisibilityBasedOnFlag(View view, int flags, int flag) { |
| 598 | if ((flags & flag) != 0) { |
| 599 | view.setVisibility(View.VISIBLE); |
| 600 | } else { |
Adam Powell | f517692 | 2013-10-13 10:39:04 -0700 | [diff] [blame] | 601 | view.setVisibility(View.INVISIBLE); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 602 | } |
| 603 | } |
| 604 | |
| 605 | private void updatePlayPauseState(int state) { |
| 606 | if (DEBUG) Log.v(TAG, |
| 607 | "updatePlayPauseState(), old=" + mCurrentPlayState + ", state=" + state); |
| 608 | if (state == mCurrentPlayState) { |
| 609 | return; |
| 610 | } |
| 611 | final int imageResId; |
| 612 | final int imageDescId; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 613 | switch (state) { |
| 614 | case RemoteControlClient.PLAYSTATE_ERROR: |
Jim Miller | 5ecd811 | 2013-01-09 18:50:26 -0800 | [diff] [blame] | 615 | imageResId = R.drawable.stat_sys_warning; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 616 | // TODO use more specific image description string for warning, but here the "play" |
| 617 | // message is still valid because this button triggers a play command. |
Jim Miller | 5ecd811 | 2013-01-09 18:50:26 -0800 | [diff] [blame] | 618 | imageDescId = R.string.keyguard_transport_play_description; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 619 | break; |
| 620 | |
| 621 | case RemoteControlClient.PLAYSTATE_PLAYING: |
Jim Miller | 5ecd811 | 2013-01-09 18:50:26 -0800 | [diff] [blame] | 622 | imageResId = R.drawable.ic_media_pause; |
| 623 | imageDescId = R.string.keyguard_transport_pause_description; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 624 | break; |
| 625 | |
| 626 | case RemoteControlClient.PLAYSTATE_BUFFERING: |
Jim Miller | 5ecd811 | 2013-01-09 18:50:26 -0800 | [diff] [blame] | 627 | imageResId = R.drawable.ic_media_stop; |
| 628 | imageDescId = R.string.keyguard_transport_stop_description; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 629 | break; |
| 630 | |
| 631 | case RemoteControlClient.PLAYSTATE_PAUSED: |
| 632 | default: |
Jim Miller | 5ecd811 | 2013-01-09 18:50:26 -0800 | [diff] [blame] | 633 | imageResId = R.drawable.ic_media_play; |
| 634 | imageDescId = R.string.keyguard_transport_play_description; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 635 | break; |
| 636 | } |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 637 | |
Jim Miller | cc747ad | 2013-10-24 19:53:09 -0700 | [diff] [blame] | 638 | boolean clientSupportsSeek = mMetadata != null && mMetadata.duration > 0; |
| 639 | setSeekBarsEnabled(clientSupportsSeek); |
| 640 | |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 641 | mBtnPlay.setImageResource(imageResId); |
| 642 | mBtnPlay.setContentDescription(getResources().getString(imageDescId)); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 643 | mCurrentPlayState = state; |
| 644 | } |
| 645 | |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 646 | boolean updateSeekBars() { |
| 647 | final int position = (int) mRemoteController.getEstimatedMediaPosition(); |
Jim Miller | cc747ad | 2013-10-24 19:53:09 -0700 | [diff] [blame] | 648 | if (DEBUG) Log.v(TAG, "Estimated time:" + position); |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 649 | if (position >= 0) { |
Jim Miller | cc747ad | 2013-10-24 19:53:09 -0700 | [diff] [blame] | 650 | mTransientSeekBar.setProgress(position); |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 651 | return true; |
| 652 | } |
| 653 | Log.w(TAG, "Updating seek bars; received invalid estimated media position (" + |
| 654 | position + "). Disabling seek."); |
| 655 | setSeekBarsEnabled(false); |
| 656 | return false; |
| 657 | } |
| 658 | |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 659 | static class SavedState extends BaseSavedState { |
Jim Miller | 223ce5c | 2012-10-05 19:13:23 -0700 | [diff] [blame] | 660 | boolean clientPresent; |
Craig Mautner | 8334192 | 2013-10-30 10:29:38 -0700 | [diff] [blame] | 661 | String artist; |
| 662 | String trackTitle; |
| 663 | String albumTitle; |
| 664 | long duration; |
| 665 | Bitmap bitmap; |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 666 | |
| 667 | SavedState(Parcelable superState) { |
| 668 | super(superState); |
| 669 | } |
| 670 | |
| 671 | private SavedState(Parcel in) { |
| 672 | super(in); |
Craig Mautner | 8334192 | 2013-10-30 10:29:38 -0700 | [diff] [blame] | 673 | clientPresent = in.readInt() != 0; |
| 674 | artist = in.readString(); |
| 675 | trackTitle = in.readString(); |
| 676 | albumTitle = in.readString(); |
| 677 | duration = in.readLong(); |
| 678 | bitmap = Bitmap.CREATOR.createFromParcel(in); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 679 | } |
| 680 | |
| 681 | @Override |
| 682 | public void writeToParcel(Parcel out, int flags) { |
| 683 | super.writeToParcel(out, flags); |
Craig Mautner | 8334192 | 2013-10-30 10:29:38 -0700 | [diff] [blame] | 684 | out.writeInt(clientPresent ? 1 : 0); |
| 685 | out.writeString(artist); |
| 686 | out.writeString(trackTitle); |
| 687 | out.writeString(albumTitle); |
| 688 | out.writeLong(duration); |
| 689 | bitmap.writeToParcel(out, flags); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 690 | } |
| 691 | |
| 692 | public static final Parcelable.Creator<SavedState> CREATOR |
| 693 | = new Parcelable.Creator<SavedState>() { |
| 694 | public SavedState createFromParcel(Parcel in) { |
| 695 | return new SavedState(in); |
| 696 | } |
| 697 | |
| 698 | public SavedState[] newArray(int size) { |
| 699 | return new SavedState[size]; |
| 700 | } |
| 701 | }; |
| 702 | } |
| 703 | |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 704 | private void sendMediaButtonClick(int keyCode) { |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 705 | // TODO We should think about sending these up/down events accurately with touch up/down |
| 706 | // on the buttons, but in the near term this will interfere with the long press behavior. |
| 707 | mRemoteController.sendMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode)); |
| 708 | mRemoteController.sendMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keyCode)); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 709 | |
Adam Powell | f889524 | 2013-09-30 16:16:24 -0700 | [diff] [blame] | 710 | mTransportControlCallback.userActivity(); |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 711 | } |
| 712 | |
| 713 | public boolean providesClock() { |
| 714 | return false; |
| 715 | } |
Jim Miller | ff2aa0b | 2012-09-06 19:03:52 -0700 | [diff] [blame] | 716 | } |