1 // CHECKSTYLE:OFF Generated code 2 /* This file is auto-generated from PlaybackControlHelper.java. DO NOT MODIFY. */ 3 4 /* 5 * Copyright (C) 2015 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License 18 */ 19 20 package com.example.android.leanback; 21 22 import android.content.Context; 23 import android.graphics.drawable.Drawable; 24 import android.os.Handler; 25 import android.support.v17.leanback.app.PlaybackControlSupportGlue; 26 import android.support.v17.leanback.widget.Action; 27 import android.support.v17.leanback.widget.ArrayObjectAdapter; 28 import android.support.v17.leanback.widget.ControlButtonPresenterSelector; 29 import android.support.v17.leanback.widget.PlaybackControlsRow; 30 import android.support.v17.leanback.widget.PlaybackControlsRowPresenter; 31 import android.support.v17.leanback.widget.PresenterSelector; 32 import android.support.v17.leanback.widget.SparseArrayObjectAdapter; 33 import android.view.KeyEvent; 34 import android.view.View; 35 import android.widget.Toast; 36 37 abstract class PlaybackControlSupportHelper extends PlaybackControlSupportGlue { 38 /** 39 * Change the location of the thumbs up/down controls 40 */ 41 private static final boolean THUMBS_PRIMARY = true; 42 43 private static final String FAUX_TITLE = "A short song of silence"; 44 private static final String FAUX_SUBTITLE = "2014"; 45 private static final int FAUX_DURATION = 33 * 1000; 46 47 // These should match the playback service FF behavior 48 private static int[] sFastForwardSpeeds = { 2, 3, 4, 5 }; 49 50 private boolean mIsPlaying; 51 private int mSpeed = PlaybackControlSupportGlue.PLAYBACK_SPEED_PAUSED; 52 private long mStartTime; 53 private long mStartPosition = 0; 54 55 private PlaybackControlsRow.RepeatAction mRepeatAction; 56 private PlaybackControlsRow.ThumbsUpAction mThumbsUpAction; 57 private PlaybackControlsRow.ThumbsDownAction mThumbsDownAction; 58 private PlaybackControlsRow.PictureInPictureAction mPipAction; 59 60 private Handler mHandler = new Handler(); 61 // simulating whether the media is yet prepared and ready to play 62 private boolean mInitialized = true; 63 64 private final Runnable mUpdateProgressRunnable = new Runnable() { 65 @Override 66 public void run() { 67 updateProgress(); 68 mHandler.postDelayed(this, getUpdatePeriod()); 69 } 70 }; 71 PlaybackControlSupportHelper(Context context, PlaybackOverlaySupportFragment fragment)72 PlaybackControlSupportHelper(Context context, PlaybackOverlaySupportFragment fragment) { 73 super(context, fragment, sFastForwardSpeeds); 74 mThumbsUpAction = new PlaybackControlsRow.ThumbsUpAction(context); 75 mThumbsUpAction.setIndex(PlaybackControlsRow.ThumbsUpAction.INDEX_OUTLINE); 76 mThumbsDownAction = new PlaybackControlsRow.ThumbsDownAction(context); 77 mThumbsDownAction.setIndex(PlaybackControlsRow.ThumbsDownAction.INDEX_OUTLINE); 78 mRepeatAction = new PlaybackControlsRow.RepeatAction(context); 79 mPipAction = new PlaybackControlsRow.PictureInPictureAction(context); 80 } 81 82 @Override createControlsRowAndPresenter()83 public PlaybackControlsRowPresenter createControlsRowAndPresenter() { 84 PlaybackControlsRowPresenter presenter = super.createControlsRowAndPresenter(); 85 86 ArrayObjectAdapter adapter = new ArrayObjectAdapter(new ControlButtonPresenterSelector()); 87 getControlsRow().setSecondaryActionsAdapter(adapter); 88 if (!THUMBS_PRIMARY) { 89 adapter.add(mThumbsDownAction); 90 } 91 if (android.os.Build.VERSION.SDK_INT > 23) { 92 adapter.add(mPipAction); 93 } 94 adapter.add(mRepeatAction); 95 if (!THUMBS_PRIMARY) { 96 adapter.add(mThumbsUpAction); 97 } 98 99 return presenter; 100 } 101 102 @Override createPrimaryActionsAdapter( PresenterSelector presenterSelector)103 protected SparseArrayObjectAdapter createPrimaryActionsAdapter( 104 PresenterSelector presenterSelector) { 105 SparseArrayObjectAdapter adapter = new SparseArrayObjectAdapter(presenterSelector); 106 if (THUMBS_PRIMARY) { 107 adapter.set(PlaybackControlSupportGlue.ACTION_CUSTOM_LEFT_FIRST, mThumbsUpAction); 108 adapter.set(PlaybackControlSupportGlue.ACTION_CUSTOM_RIGHT_FIRST, mThumbsDownAction); 109 } 110 return adapter; 111 } 112 113 @Override onActionClicked(Action action)114 public void onActionClicked(Action action) { 115 if (shouldDispatchAction(action)) { 116 dispatchAction(action); 117 return; 118 } 119 super.onActionClicked(action); 120 } 121 122 @Override onKey(View view, int keyCode, KeyEvent keyEvent)123 public boolean onKey(View view, int keyCode, KeyEvent keyEvent) { 124 if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) { 125 Action action = getControlsRow().getActionForKeyCode(keyEvent.getKeyCode()); 126 if (shouldDispatchAction(action)) { 127 dispatchAction(action); 128 return true; 129 } 130 } 131 return super.onKey(view, keyCode, keyEvent); 132 } 133 shouldDispatchAction(Action action)134 private boolean shouldDispatchAction(Action action) { 135 return action == mRepeatAction || action == mThumbsUpAction || action == mThumbsDownAction; 136 } 137 dispatchAction(Action action)138 private void dispatchAction(Action action) { 139 Toast.makeText(getContext(), action.toString(), Toast.LENGTH_SHORT).show(); 140 PlaybackControlsRow.MultiAction multiAction = (PlaybackControlsRow.MultiAction) action; 141 multiAction.nextIndex(); 142 notifyActionChanged(multiAction); 143 } 144 notifyActionChanged(PlaybackControlsRow.MultiAction action)145 private void notifyActionChanged(PlaybackControlsRow.MultiAction action) { 146 int index; 147 index = getPrimaryActionsAdapter().indexOf(action); 148 if (index >= 0) { 149 getPrimaryActionsAdapter().notifyArrayItemRangeChanged(index, 1); 150 } else { 151 index = getSecondaryActionsAdapter().indexOf(action); 152 if (index >= 0) { 153 getSecondaryActionsAdapter().notifyArrayItemRangeChanged(index, 1); 154 } 155 } 156 } 157 getPrimaryActionsAdapter()158 private SparseArrayObjectAdapter getPrimaryActionsAdapter() { 159 return (SparseArrayObjectAdapter) getControlsRow().getPrimaryActionsAdapter(); 160 } 161 getSecondaryActionsAdapter()162 private ArrayObjectAdapter getSecondaryActionsAdapter() { 163 return (ArrayObjectAdapter) getControlsRow().getSecondaryActionsAdapter(); 164 } 165 166 @Override hasValidMedia()167 public boolean hasValidMedia() { 168 return mInitialized; 169 } 170 171 @Override isMediaPlaying()172 public boolean isMediaPlaying() { 173 return mIsPlaying; 174 } 175 176 @Override getMediaTitle()177 public CharSequence getMediaTitle() { 178 return FAUX_TITLE; 179 } 180 181 @Override getMediaSubtitle()182 public CharSequence getMediaSubtitle() { 183 return FAUX_SUBTITLE; 184 } 185 186 @Override getMediaDuration()187 public int getMediaDuration() { 188 return mInitialized ? FAUX_DURATION : 0; 189 } 190 191 @Override getMediaArt()192 public Drawable getMediaArt() { 193 return null; 194 } 195 196 @Override getSupportedActions()197 public long getSupportedActions() { 198 return PlaybackControlSupportGlue.ACTION_PLAY_PAUSE | 199 PlaybackControlSupportGlue.ACTION_FAST_FORWARD | 200 PlaybackControlSupportGlue.ACTION_REWIND; 201 } 202 203 @Override getCurrentSpeedId()204 public int getCurrentSpeedId() { 205 return mSpeed; 206 } 207 208 @Override getCurrentPosition()209 public int getCurrentPosition() { 210 int speed; 211 if (mSpeed == PlaybackControlSupportGlue.PLAYBACK_SPEED_PAUSED) { 212 speed = 0; 213 } else if (mSpeed == PlaybackControlSupportGlue.PLAYBACK_SPEED_NORMAL) { 214 speed = 1; 215 } else if (mSpeed >= PlaybackControlSupportGlue.PLAYBACK_SPEED_FAST_L0) { 216 int index = mSpeed - PlaybackControlSupportGlue.PLAYBACK_SPEED_FAST_L0; 217 speed = getFastForwardSpeeds()[index]; 218 } else if (mSpeed <= -PlaybackControlSupportGlue.PLAYBACK_SPEED_FAST_L0) { 219 int index = -mSpeed - PlaybackControlSupportGlue.PLAYBACK_SPEED_FAST_L0; 220 speed = -getRewindSpeeds()[index]; 221 } else { 222 return -1; 223 } 224 long position = mStartPosition + 225 (System.currentTimeMillis() - mStartTime) * speed; 226 if (position > getMediaDuration()) { 227 position = getMediaDuration(); 228 onPlaybackComplete(true); 229 } else if (position < 0) { 230 position = 0; 231 onPlaybackComplete(false); 232 } 233 return (int) position; 234 } 235 onPlaybackComplete(final boolean ended)236 void onPlaybackComplete(final boolean ended) { 237 mHandler.post(new Runnable() { 238 @Override 239 public void run() { 240 if (mRepeatAction.getIndex() == PlaybackControlsRow.RepeatAction.INDEX_NONE) { 241 pausePlayback(); 242 } else { 243 startPlayback(PlaybackControlSupportGlue.PLAYBACK_SPEED_NORMAL); 244 } 245 mStartPosition = 0; 246 onStateChanged(); 247 } 248 }); 249 } 250 251 @Override startPlayback(int speed)252 protected void startPlayback(int speed) { 253 if (speed == mSpeed) { 254 return; 255 } 256 mStartPosition = getCurrentPosition(); 257 mSpeed = speed; 258 mIsPlaying = true; 259 mStartTime = System.currentTimeMillis(); 260 } 261 262 @Override pausePlayback()263 protected void pausePlayback() { 264 if (mSpeed == PlaybackControlSupportGlue.PLAYBACK_SPEED_PAUSED) { 265 return; 266 } 267 mStartPosition = getCurrentPosition(); 268 mSpeed = PlaybackControlSupportGlue.PLAYBACK_SPEED_PAUSED; 269 mIsPlaying = false; 270 } 271 272 @Override skipToNext()273 protected void skipToNext() { 274 // Not supported 275 } 276 277 @Override skipToPrevious()278 protected void skipToPrevious() { 279 // Not supported 280 } 281 282 @Override enableProgressUpdating(boolean enable)283 public void enableProgressUpdating(boolean enable) { 284 mHandler.removeCallbacks(mUpdateProgressRunnable); 285 if (enable) { 286 mUpdateProgressRunnable.run(); 287 } 288 } 289 isInitialized()290 public boolean isInitialized() { 291 return mInitialized; 292 } 293 setInitialized(boolean initialized)294 public void setInitialized(boolean initialized) { 295 if (mInitialized != initialized) { 296 mInitialized = initialized; 297 onMetadataChanged(); 298 onStateChanged(); 299 } 300 } 301 }; 302