14c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri/* 24c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri * Copyright (C) 2016 The Android Open Source Project 34c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri * 44c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri * Licensed under the Apache License, Version 2.0 (the "License"); 54c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri * you may not use this file except in compliance with the License. 64c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri * You may obtain a copy of the License at 74c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri * 84c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri * http://www.apache.org/licenses/LICENSE-2.0 94c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri * 104c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri * Unless required by applicable law or agreed to in writing, software 114c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri * distributed under the License is distributed on an "AS IS" BASIS, 124c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri * See the License for the specific language governing permissions and 144c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri * limitations under the License. 154c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri */ 164c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiripackage android.support.v17.leanback.app; 174c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 184c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiriimport android.content.Context; 194c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiriimport android.graphics.drawable.Drawable; 204c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiriimport android.os.Bundle; 214c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiriimport android.os.Handler; 224c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiriimport android.support.v17.leanback.media.PlaybackControlGlue; 234c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiriimport android.support.v17.leanback.test.R; 244c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiriimport android.support.v17.leanback.widget.Action; 254c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiriimport android.support.v17.leanback.widget.ArrayObjectAdapter; 265a4d3a98d681cc9042b28a923aa5a23a6b961998Dake Guimport android.support.v17.leanback.widget.ClassPresenterSelector; 274c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiriimport android.support.v17.leanback.widget.HeaderItem; 284c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiriimport android.support.v17.leanback.widget.ListRow; 294c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiriimport android.support.v17.leanback.widget.ListRowPresenter; 304c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiriimport android.support.v17.leanback.widget.OnItemViewClickedListener; 314c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiriimport android.support.v17.leanback.widget.PlaybackControlsRow; 324c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiriimport android.support.v17.leanback.widget.Presenter; 334c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiriimport android.support.v17.leanback.widget.PresenterSelector; 344c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiriimport android.support.v17.leanback.widget.Row; 354c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiriimport android.support.v17.leanback.widget.RowPresenter; 364c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiriimport android.support.v17.leanback.widget.SparseArrayObjectAdapter; 374c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiriimport android.util.Log; 384c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiriimport android.view.KeyEvent; 394c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiriimport android.view.View; 404c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiriimport android.widget.Toast; 414c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 424c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiripublic class PlaybackTestFragment extends PlaybackFragment { 434c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private static final String TAG = "PlaybackTestFragment"; 444c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 454c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri /** 464c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri * Change this to choose a different overlay background. 474c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri */ 484c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private static final int BACKGROUND_TYPE = PlaybackFragment.BG_LIGHT; 494c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 504c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri /** 514c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri * Change this to select hidden 524c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri */ 534c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private static final boolean SECONDARY_HIDDEN = false; 544c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 554c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri /** 564c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri * Change the number of related content rows. 574c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri */ 584c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private static final int RELATED_CONTENT_ROWS = 3; 594c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 604c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private android.support.v17.leanback.media.PlaybackControlGlue mGlue; 616f8b365afb35cda46d1c4042ce633c1177197808Dake Gu boolean mDestroyCalled; 624c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 63e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas @Override 644c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public SparseArrayObjectAdapter getAdapter() { 654c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri return (SparseArrayObjectAdapter) super.getAdapter(); 664c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 674c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 684c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private OnItemViewClickedListener mOnItemViewClickedListener = new OnItemViewClickedListener() { 694c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 704c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, 714c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri RowPresenter.ViewHolder rowViewHolder, Row row) { 724c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri Log.d(TAG, "onItemClicked: " + item + " row " + row); 734c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 744c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri }; 754c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 764c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 776f8b365afb35cda46d1c4042ce633c1177197808Dake Gu public void onDestroy() { 786f8b365afb35cda46d1c4042ce633c1177197808Dake Gu super.onDestroy(); 796f8b365afb35cda46d1c4042ce633c1177197808Dake Gu mDestroyCalled = true; 806f8b365afb35cda46d1c4042ce633c1177197808Dake Gu } 816f8b365afb35cda46d1c4042ce633c1177197808Dake Gu 826f8b365afb35cda46d1c4042ce633c1177197808Dake Gu @Override 834c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public void onCreate(Bundle savedInstanceState) { 844c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri Log.i(TAG, "onCreate"); 854c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri super.onCreate(savedInstanceState); 864c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 874c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri setBackgroundType(BACKGROUND_TYPE); 884c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 894c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri createComponents(getActivity()); 904c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri setOnItemViewClickedListener(mOnItemViewClickedListener); 914c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 924c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 934c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private void createComponents(Context context) { 944c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri mGlue = new PlaybackControlHelper(context) { 954c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 964c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public int getUpdatePeriod() { 973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu long totalTime = getControlsRow().getDuration(); 984c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri if (getView() == null || getView().getWidth() == 0 || totalTime <= 0) { 994c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri return 1000; 1004c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 1013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return 16; 1024c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 1034c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 1044c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 1054c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public void onActionClicked(Action action) { 1064c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri if (action.getId() == R.id.lb_control_picture_in_picture) { 1074c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri getActivity().enterPictureInPictureMode(); 1084c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri return; 1094c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 1104c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri super.onActionClicked(action); 1114c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 1124c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 1134c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 1144c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri protected void onCreateControlsRowAndPresenter() { 1154c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri super.onCreateControlsRowAndPresenter(); 1164c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri getControlsRowPresenter().setSecondaryActionsHidden(SECONDARY_HIDDEN); 1174c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 1184c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri }; 1194c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 1204c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri mGlue.setHost(new PlaybackFragmentGlueHost(this)); 1215a4d3a98d681cc9042b28a923aa5a23a6b961998Dake Gu ClassPresenterSelector selector = new ClassPresenterSelector(); 1225a4d3a98d681cc9042b28a923aa5a23a6b961998Dake Gu selector.addClassPresenter(ListRow.class, new ListRowPresenter()); 1234c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 1245a4d3a98d681cc9042b28a923aa5a23a6b961998Dake Gu setAdapter(new SparseArrayObjectAdapter(selector)); 1254c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 1264c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri // Add related content rows 1274c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri for (int i = 0; i < RELATED_CONTENT_ROWS; ++i) { 1284c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(new StringPresenter()); 1294c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri listRowAdapter.add("Some related content"); 1304c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri listRowAdapter.add("Other related content"); 1314c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri HeaderItem header = new HeaderItem(i, "Row " + i); 1325a4d3a98d681cc9042b28a923aa5a23a6b961998Dake Gu getAdapter().set(1 + i, new ListRow(header, listRowAdapter)); 1334c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 1344c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 1354c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 1364c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public PlaybackControlGlue getGlue() { 1374c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri return mGlue; 1384c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 1394c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 1404c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri abstract static class PlaybackControlHelper extends PlaybackControlGlue { 1414c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri /** 1424c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri * Change the location of the thumbs up/down controls 1434c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri */ 1444c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private static final boolean THUMBS_PRIMARY = true; 1454c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 1464c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private static final String FAUX_TITLE = "A short song of silence"; 1474c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private static final String FAUX_SUBTITLE = "2014"; 1484c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private static final int FAUX_DURATION = 33 * 1000; 1494c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 1504c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri // These should match the playback service FF behavior 1514c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private static int[] sFastForwardSpeeds = { 2, 3, 4, 5 }; 1524c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 1534c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private boolean mIsPlaying; 1544c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private int mSpeed = PLAYBACK_SPEED_PAUSED; 1554c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private long mStartTime; 1564c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private long mStartPosition = 0; 1574c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 1584c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private PlaybackControlsRow.RepeatAction mRepeatAction; 1594c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private PlaybackControlsRow.ThumbsUpAction mThumbsUpAction; 1604c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private PlaybackControlsRow.ThumbsDownAction mThumbsDownAction; 1614c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private PlaybackControlsRow.PictureInPictureAction mPipAction; 1624c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private static Handler sProgressHandler = new Handler(); 1634c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 1644c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private final Runnable mUpdateProgressRunnable = new Runnable() { 1654c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 1664c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public void run() { 1674c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri updateProgress(); 1684c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri sProgressHandler.postDelayed(this, getUpdatePeriod()); 1694c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 1704c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri }; 1714c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 1724c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri PlaybackControlHelper(Context context) { 1734c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri super(context, sFastForwardSpeeds); 1744c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri mThumbsUpAction = new PlaybackControlsRow.ThumbsUpAction(context); 175946a01cfedb6838e98d7a37e30f64c39b603893dDake Gu mThumbsUpAction.setIndex(PlaybackControlsRow.ThumbsUpAction.INDEX_OUTLINE); 1764c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri mThumbsDownAction = new PlaybackControlsRow.ThumbsDownAction(context); 177946a01cfedb6838e98d7a37e30f64c39b603893dDake Gu mThumbsDownAction.setIndex(PlaybackControlsRow.ThumbsDownAction.INDEX_OUTLINE); 1784c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri mRepeatAction = new PlaybackControlsRow.RepeatAction(context); 1794c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri mPipAction = new PlaybackControlsRow.PictureInPictureAction(context); 1804c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 1814c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 1824c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 1834c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri protected SparseArrayObjectAdapter createPrimaryActionsAdapter( 1844c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri PresenterSelector presenterSelector) { 1854c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri SparseArrayObjectAdapter adapter = new SparseArrayObjectAdapter(presenterSelector); 1864c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri if (THUMBS_PRIMARY) { 1874c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri adapter.set(PlaybackControlGlue.ACTION_CUSTOM_LEFT_FIRST, mThumbsUpAction); 1884c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri adapter.set(PlaybackControlGlue.ACTION_CUSTOM_RIGHT_FIRST, mThumbsDownAction); 1894c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 1904c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri return adapter; 1914c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 1924c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 1934c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 1944c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public void onActionClicked(Action action) { 1954c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri if (shouldDispatchAction(action)) { 1964c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri dispatchAction(action); 1974c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri return; 1984c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 1994c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri super.onActionClicked(action); 2004c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 2014c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 2024c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 2034c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public boolean onKey(View view, int keyCode, KeyEvent keyEvent) { 2044c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) { 2054c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri Action action = getControlsRow().getActionForKeyCode(keyEvent.getKeyCode()); 2064c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri if (shouldDispatchAction(action)) { 2074c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri dispatchAction(action); 2084c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri return true; 2094c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 2104c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 2114c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri return super.onKey(view, keyCode, keyEvent); 2124c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 2134c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 2144c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private boolean shouldDispatchAction(Action action) { 2154c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri return action == mRepeatAction || action == mThumbsUpAction 2164c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri || action == mThumbsDownAction; 2174c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 2184c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 2194c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private void dispatchAction(Action action) { 2204c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri Toast.makeText(getContext(), action.toString(), Toast.LENGTH_SHORT).show(); 2214c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri PlaybackControlsRow.MultiAction multiAction = (PlaybackControlsRow.MultiAction) action; 2224c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri multiAction.nextIndex(); 2234c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri notifyActionChanged(multiAction); 2244c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 2254c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 2264c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private void notifyActionChanged(PlaybackControlsRow.MultiAction action) { 2274c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri int index; 2284c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri index = getPrimaryActionsAdapter().indexOf(action); 2294c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri if (index >= 0) { 2304c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri getPrimaryActionsAdapter().notifyArrayItemRangeChanged(index, 1); 2314c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } else { 2324c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri index = getSecondaryActionsAdapter().indexOf(action); 2334c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri if (index >= 0) { 2344c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri getSecondaryActionsAdapter().notifyArrayItemRangeChanged(index, 1); 2354c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 2364c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 2374c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 2384c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 2394c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private SparseArrayObjectAdapter getPrimaryActionsAdapter() { 2404c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri return (SparseArrayObjectAdapter) getControlsRow().getPrimaryActionsAdapter(); 2414c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 2424c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 2434c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri private ArrayObjectAdapter getSecondaryActionsAdapter() { 2444c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri return (ArrayObjectAdapter) getControlsRow().getSecondaryActionsAdapter(); 2454c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 2464c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 2474c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 2484c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public boolean hasValidMedia() { 2494c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri return true; 2504c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 2514c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 2524c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 2534c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public boolean isMediaPlaying() { 2544c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri return mIsPlaying; 2554c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 2564c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 2574c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 2584c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public CharSequence getMediaTitle() { 2594c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri return FAUX_TITLE; 2604c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 2614c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 2624c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 2634c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public CharSequence getMediaSubtitle() { 2644c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri return FAUX_SUBTITLE; 2654c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 2664c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 2674c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 2684c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public int getMediaDuration() { 2694c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri return FAUX_DURATION; 2704c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 2714c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 2724c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 2734c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public Drawable getMediaArt() { 2744c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri return null; 2754c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 2764c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 2774c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 2784c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public long getSupportedActions() { 2794c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri return ACTION_PLAY_PAUSE | ACTION_FAST_FORWARD | ACTION_REWIND; 2804c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 2814c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 2824c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 2834c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public int getCurrentSpeedId() { 2844c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri return mSpeed; 2854c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 2864c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 2874c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 2884c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public int getCurrentPosition() { 2894c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri int speed; 2904c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri if (mSpeed == PlaybackControlGlue.PLAYBACK_SPEED_PAUSED) { 2914c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri speed = 0; 2924c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } else if (mSpeed == PlaybackControlGlue.PLAYBACK_SPEED_NORMAL) { 2934c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri speed = 1; 2944c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } else if (mSpeed >= PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0) { 2954c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri int index = mSpeed - PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0; 2964c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri speed = getFastForwardSpeeds()[index]; 2974c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } else if (mSpeed <= -PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0) { 2984c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri int index = -mSpeed - PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0; 2994c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri speed = -getRewindSpeeds()[index]; 3004c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } else { 3014c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri return -1; 3024c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 3034c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri long position = mStartPosition + (System.currentTimeMillis() - mStartTime) * speed; 3044c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri if (position > getMediaDuration()) { 3054c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri position = getMediaDuration(); 3064c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri onPlaybackComplete(true); 3074c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } else if (position < 0) { 3084c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri position = 0; 3094c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri onPlaybackComplete(false); 3104c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 3114c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri return (int) position; 3124c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 3134c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 3144c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri void onPlaybackComplete(final boolean ended) { 3154c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri sProgressHandler.post(new Runnable() { 3164c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 3174c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public void run() { 318946a01cfedb6838e98d7a37e30f64c39b603893dDake Gu if (mRepeatAction.getIndex() == PlaybackControlsRow.RepeatAction.INDEX_NONE) { 3194c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri pause(); 3204c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } else { 3214c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri play(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL); 3224c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 3234c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri mStartPosition = 0; 3244c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri onStateChanged(); 3254c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 3264c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri }); 3274c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 3284c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 3294c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 3304c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public void play(int speed) { 3314c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri if (speed == mSpeed) { 3324c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri return; 3334c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 3344c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri mStartPosition = getCurrentPosition(); 3354c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri mSpeed = speed; 3364c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri mIsPlaying = true; 3374c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri mStartTime = System.currentTimeMillis(); 3384c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 3394c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 3404c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 3414c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public void pause() { 3424c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri if (mSpeed == PLAYBACK_SPEED_PAUSED) { 3434c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri return; 3444c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 3454c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri mStartPosition = getCurrentPosition(); 3464c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri mSpeed = PLAYBACK_SPEED_PAUSED; 3474c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri mIsPlaying = false; 3484c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 3494c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 3504c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 3514c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public void next() { 3524c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri // Not supported 3534c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 3544c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 3554c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 3564c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public void previous() { 3574c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri // Not supported 3584c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 3594c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri 3604c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri @Override 3614c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri public void enableProgressUpdating(boolean enable) { 3624c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri sProgressHandler.removeCallbacks(mUpdateProgressRunnable); 3634c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri if (enable) { 3644c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri mUpdateProgressRunnable.run(); 3654c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 3664c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 3674c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri } 3684c9758b25091b36c0fd55bf422188e5ac9314da4Keyvan Amiri} 369