SampleMediaRouterActivity.java revision 7b95dd38981772983f00c5ed91aca4b30b782fac
1ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown/*
2ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * Copyright (C) 2013 The Android Open Source Project
3ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown *
4ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
5ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * you may not use this file except in compliance with the License.
6ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * You may obtain a copy of the License at
7ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown *
8ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
9ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown *
10ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * Unless required by applicable law or agreed to in writing, software
11ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
12ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * See the License for the specific language governing permissions and
14ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * limitations under the License.
15ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown */
16ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
17ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownpackage com.example.android.supportv7.media;
18ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
19ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport com.example.android.supportv7.R;
20ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
217578fad97dcd3b4b390652f37a30d805538980f5Chong Zhangimport android.content.ComponentName;
2257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.content.Context;
23ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.content.Intent;
2457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.content.IntentFilter;
2557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.content.BroadcastReceiver;
2657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.content.res.Resources;
2757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.content.DialogInterface;
2857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.app.PendingIntent;
2957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.app.Presentation;
307578fad97dcd3b4b390652f37a30d805538980f5Chong Zhangimport android.media.AudioManager;
317578fad97dcd3b4b390652f37a30d805538980f5Chong Zhangimport android.media.AudioManager.OnAudioFocusChangeListener;
327578fad97dcd3b4b390652f37a30d805538980f5Chong Zhangimport android.media.MediaMetadataRetriever;
337578fad97dcd3b4b390652f37a30d805538980f5Chong Zhangimport android.media.RemoteControlClient;
34ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.net.Uri;
357578fad97dcd3b4b390652f37a30d805538980f5Chong Zhangimport android.os.Build;
3657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.os.Handler;
37ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.os.Bundle;
3857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.os.SystemClock;
39f0dd451048100915f072423730a93d17c53fd899Jeff Brownimport android.support.v4.app.FragmentManager;
4055e47d370890d3cbdab82857090c42df734ba276Jeff Brownimport android.support.v4.view.MenuItemCompat;
4155e47d370890d3cbdab82857090c42df734ba276Jeff Brownimport android.support.v7.app.ActionBarActivity;
4255e47d370890d3cbdab82857090c42df734ba276Jeff Brownimport android.support.v7.app.MediaRouteActionProvider;
43f0dd451048100915f072423730a93d17c53fd899Jeff Brownimport android.support.v7.app.MediaRouteDiscoveryFragment;
44ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.support.v7.media.MediaControlIntent;
45ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.support.v7.media.MediaRouter;
46f0dd451048100915f072423730a93d17c53fd899Jeff Brownimport android.support.v7.media.MediaRouter.Callback;
47ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.support.v7.media.MediaRouter.RouteInfo;
48ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.support.v7.media.MediaRouter.ProviderInfo;
4955e47d370890d3cbdab82857090c42df734ba276Jeff Brownimport android.support.v7.media.MediaRouteSelector;
5057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.support.v7.media.MediaItemStatus;
51ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.util.Log;
5257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.view.Gravity;
537578fad97dcd3b4b390652f37a30d805538980f5Chong Zhangimport android.view.KeyEvent;
54ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.view.Menu;
55ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.view.MenuItem;
56ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.view.View;
57ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.view.View.OnClickListener;
5857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.view.ViewGroup;
5957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.view.Display;
6057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.view.SurfaceView;
6157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.view.SurfaceHolder;
6257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.view.WindowManager;
63ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.widget.AdapterView;
6457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.widget.AdapterView.OnItemClickListener;
65ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.widget.ArrayAdapter;
6657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.widget.ImageButton;
67ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.widget.ListView;
68ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.widget.TextView;
69ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brownimport android.widget.Toast;
7057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.widget.FrameLayout;
7157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.widget.TabHost;
7257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.widget.TabHost.TabSpec;
7357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.widget.TabHost.OnTabChangeListener;
7457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.widget.SeekBar;
7557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport android.widget.SeekBar.OnSeekBarChangeListener;
7657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
7757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
7857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhangimport java.io.File;
79ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
80ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown/**
81ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * <h3>Media Router Support Activity</h3>
82ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown *
83ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * <p>
84ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * This demonstrates how to use the {@link MediaRouter} API to build an
85ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * application that allows the user to send content to various rendering
86ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * targets.
87ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown * </p>
88ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown */
8955e47d370890d3cbdab82857090c42df734ba276Jeff Brownpublic class SampleMediaRouterActivity extends ActionBarActivity {
90f0dd451048100915f072423730a93d17c53fd899Jeff Brown    private static final String TAG = "MediaRouterSupport";
91f0dd451048100915f072423730a93d17c53fd899Jeff Brown    private static final String DISCOVERY_FRAGMENT_TAG = "DiscoveryFragment";
9257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private static final String ACTION_STATUS_CHANGE =
9357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            "com.example.android.supportv7.media.ACTION_STATUS_CHANGE";
94ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
95ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    private MediaRouter mMediaRouter;
9655e47d370890d3cbdab82857090c42df734ba276Jeff Brown    private MediaRouteSelector mSelector;
9757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private LibraryAdapter mLibraryItems;
9857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private PlaylistAdapter mPlayListItems;
99ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    private TextView mInfoTextView;
10057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private ListView mLibraryView;
10157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private ListView mPlayListView;
10257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private ImageButton mPauseResumeButton;
10357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private ImageButton mStopButton;
10457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private SeekBar mSeekBar;
10557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private String mStatsInfo;
10657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private boolean mPaused;
10757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private boolean mNeedResume;
10857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private boolean mSeeking;
10957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private long mLastStatusTime;
11057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private PlaylistAdapter mSavedPlaylist;
11157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
11257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private final Handler mHandler = new Handler();
11357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private final Runnable mUpdateSeekRunnable = new Runnable() {
11457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
11557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void run() {
11657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            updateProgress(getCheckedMediaQueueItem());
11757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            // update Ui every 1 second
11857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mHandler.postDelayed(this, 1000);
11957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
12057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    };
12157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
12257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private final MediaPlayerWrapper mMediaPlayer = new MediaPlayerWrapper(this);
12357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private final MediaPlayerWrapper.Callback mMediaPlayerCB =
12457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            new MediaPlayerWrapper.Callback()  {
12557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
12657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onError() {
12757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mPlayer.onFinish(true);
12857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
12957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
13057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
13157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onCompletion() {
13257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mPlayer.onFinish(false);
13357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
13457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
13557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
13657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onSizeChanged(int width, int height) {
1377b95dd38981772983f00c5ed91aca4b30b782facJeff Brown            mPlayer.updateSize(width, height);
13857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
13957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
14057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
14157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onStatusChanged() {
14257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (!mSeeking) {
14357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                updateUi();
14457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
14557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
14657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    };
14757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
14857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private final RemotePlayer mRemotePlayer = new RemotePlayer();
14957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private final LocalPlayer mLocalPlayer = new LocalPlayer();
15057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private Player mPlayer;
15157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private MediaSessionManager.Callback mPlayerCB;
15257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
15357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private final MediaRouter.Callback mMediaRouterCB = new MediaRouter.Callback() {
15457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // Return a custom callback that will simply log all of the route events
15557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // for demonstration purposes.
15657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
15757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onRouteAdded(MediaRouter router, RouteInfo route) {
15857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "onRouteAdded: route=" + route);
15957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
16057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
16157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
16257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onRouteChanged(MediaRouter router, RouteInfo route) {
16357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "onRouteChanged: route=" + route);
16457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mPlayer.showStatistics();
16557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
16657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
16757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
16857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onRouteRemoved(MediaRouter router, RouteInfo route) {
16957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "onRouteRemoved: route=" + route);
17057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
17157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
17257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
17357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onRouteSelected(MediaRouter router, RouteInfo route) {
17457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "onRouteSelected: route=" + route);
17557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
17657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Player player = mPlayer;
17757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            MediaSessionManager.Callback playerCB = mPlayerCB;
17857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
17957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (route.supportsControlCategory(
18057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {
18157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                Intent enqueueIntent = new Intent(MediaControlIntent.ACTION_ENQUEUE);
18257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                enqueueIntent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
18357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                enqueueIntent.setDataAndType(Uri.parse("http://"), "video/mp4");
18457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
18557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                Intent removeIntent = new Intent(MediaControlIntent.ACTION_REMOVE);
18657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                removeIntent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
18757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
18857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                // Remote Playback:
18957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                //   If route supports remote queuing, let it manage the queue;
19057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                //   otherwise, manage the queue locally and feed it one item at a time
19157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                if (route.supportsControlRequest(enqueueIntent)
19257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                 && route.supportsControlRequest(removeIntent)) {
19357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    player = mRemotePlayer;
19457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                } else {
19557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    player = mLocalPlayer;
19657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                }
19757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                playerCB = mRemotePlayer;
19857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mRemotePlayer.reset();
1997578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang
20057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            } else {
20157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                // Local Playback:
20257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                //   Use local player and feed media player one item at a time
20357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                player = mLocalPlayer;
20457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                playerCB = mMediaPlayer;
20557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
20657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
20757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (player != mPlayer || playerCB != mPlayerCB) {
20857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                // save current playlist
20957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                PlaylistAdapter playlist = new PlaylistAdapter();
21057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                for (int i = 0; i < mPlayListItems.getCount(); i++) {
21157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    MediaQueueItem item = mPlayListItems.getItem(i);
21257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    if (item.getState() == MediaItemStatus.PLAYBACK_STATE_PLAYING
21357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            || item.getState() == MediaItemStatus.PLAYBACK_STATE_PAUSED) {
21457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        long position = item.getContentPosition();
21557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        long timeDelta = mPaused ? 0 :
21657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                (SystemClock.elapsedRealtime() - mLastStatusTime);
21757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        item.setContentPosition(position + timeDelta);
21857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    }
21957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    playlist.add(item);
22057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                }
22157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
22257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                // switch players
22357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mPlayer.stop();
22457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mPaused = false;
22557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mLocalPlayer.setCallback(playerCB);
22657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mPlayerCB = playerCB;
22757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mPlayer = player;
22857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mPlayer.showStatistics();
22957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mLocalPlayer.updatePresentation();
23057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
23157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                // migrate playlist to new route
23257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                int count = playlist.getCount();
23357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                if (isRemoteQueue()) {
23457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    // if queuing is managed remotely, only enqueue the first
23557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    // item, as we need to have the returned session id to
23657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    // enqueue the rest of the playlist items
23757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    mSavedPlaylist = playlist;
23857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    count = 1;
23957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                }
24057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                for (int i = 0; i < count; i++) {
24157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    final MediaQueueItem item = playlist.getItem(i);
24257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    mPlayer.enqueue(item.getUri(), item.getContentPosition());
24357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                }
24457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
24557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            updateUi();
24657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
24757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
24857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
24957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onRouteUnselected(MediaRouter router, RouteInfo route) {
25057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "onRouteUnselected: route=" + route);
25157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mPlayer.showStatistics();
25257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
25357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
25457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
25557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onRouteVolumeChanged(MediaRouter router, RouteInfo route) {
25657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "onRouteVolumeChanged: route=" + route);
25757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
25857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
25957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
26057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onRoutePresentationDisplayChanged(
26157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                MediaRouter router, RouteInfo route) {
26257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "onRoutePresentationDisplayChanged: route=" + route);
26357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
26457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
26557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
26657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onProviderAdded(MediaRouter router, ProviderInfo provider) {
26757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "onRouteProviderAdded: provider=" + provider);
26857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
26957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
27057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
27157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onProviderRemoved(MediaRouter router, ProviderInfo provider) {
27257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "onRouteProviderRemoved: provider=" + provider);
27357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
27457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
27557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
27657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onProviderChanged(MediaRouter router, ProviderInfo provider) {
27757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "onRouteProviderChanged: provider=" + provider);
27857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
27957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    };
28057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
28157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
28257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
28357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onReceive(Context context, Intent intent) {
28457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "Received status update: " + intent);
28557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (intent.getAction().equals(ACTION_STATUS_CHANGE)) {
28657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID);
28757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                String iid = intent.getStringExtra(MediaControlIntent.EXTRA_ITEM_ID);
28857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                MediaItemStatus status = MediaItemStatus.fromBundle(
28957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    intent.getBundleExtra(MediaControlIntent.EXTRA_ITEM_STATUS));
29057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
29157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                if (status.getPlaybackState() ==
29257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        MediaItemStatus.PLAYBACK_STATE_FINISHED) {
29357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    mPlayer.onFinish(false);
29457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                } else if (status.getPlaybackState() ==
29557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        MediaItemStatus.PLAYBACK_STATE_ERROR) {
29657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    mPlayer.onFinish(true);
29757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    showToast("Error while playing item" +
29857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            ", sid " + sid + ", iid " + iid);
29957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                } else {
30057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    if (!mSeeking) {
30157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        updateUi();
30257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    }
30357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                }
30457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
30557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
30657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    };
307ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
3087578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    private RemoteControlClient mRemoteControlClient;
3097578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    private ComponentName mEventReceiver;
3107578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    private AudioManager mAudioManager;
3117578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    private PendingIntent mMediaPendingIntent;
3127578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    private final OnAudioFocusChangeListener mAfChangeListener =
3137578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            new OnAudioFocusChangeListener() {
3147578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        @Override
3157578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        public void onAudioFocusChange(int focusChange) {
3167578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
3177578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                Log.d(TAG, "onAudioFocusChange: LOSS_TRANSIENT");
3187578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
3197578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                Log.d(TAG, "onAudioFocusChange: AUDIOFOCUS_GAIN");
3207578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
3217578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                Log.d(TAG, "onAudioFocusChange: AUDIOFOCUS_LOSS");
3227578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            }
3237578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        }
3247578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    };
3257578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang
326ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    @Override
327ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    protected void onCreate(Bundle savedInstanceState) {
328ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        // Be sure to call the super class.
329ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        super.onCreate(savedInstanceState);
330ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
331ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        // Get the media router service.
332ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        mMediaRouter = MediaRouter.getInstance(this);
333ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
33455e47d370890d3cbdab82857090c42df734ba276Jeff Brown        // Create a route selector for the type of routes that we care about.
33555e47d370890d3cbdab82857090c42df734ba276Jeff Brown        mSelector = new MediaRouteSelector.Builder()
33655e47d370890d3cbdab82857090c42df734ba276Jeff Brown                .addControlCategory(MediaControlIntent.CATEGORY_LIVE_AUDIO)
33755e47d370890d3cbdab82857090c42df734ba276Jeff Brown                .addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO)
33855e47d370890d3cbdab82857090c42df734ba276Jeff Brown                .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
33955e47d370890d3cbdab82857090c42df734ba276Jeff Brown                .addControlCategory(SampleMediaRouteProvider.CATEGORY_SAMPLE_ROUTE)
34055e47d370890d3cbdab82857090c42df734ba276Jeff Brown                .build();
34155e47d370890d3cbdab82857090c42df734ba276Jeff Brown
342f0dd451048100915f072423730a93d17c53fd899Jeff Brown        // Add a fragment to take care of media route discovery.
343f0dd451048100915f072423730a93d17c53fd899Jeff Brown        // This fragment automatically adds or removes a callback whenever the activity
344f0dd451048100915f072423730a93d17c53fd899Jeff Brown        // is started or stopped.
345f0dd451048100915f072423730a93d17c53fd899Jeff Brown        FragmentManager fm = getSupportFragmentManager();
34657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        DiscoveryFragment fragment = (DiscoveryFragment)fm.findFragmentByTag(
34757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                DISCOVERY_FRAGMENT_TAG);
34857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        if (fragment == null) {
34957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            fragment = new DiscoveryFragment(mMediaRouterCB);
350f0dd451048100915f072423730a93d17c53fd899Jeff Brown            fragment.setRouteSelector(mSelector);
351f0dd451048100915f072423730a93d17c53fd899Jeff Brown            fm.beginTransaction()
352f0dd451048100915f072423730a93d17c53fd899Jeff Brown                    .add(fragment, DISCOVERY_FRAGMENT_TAG)
353f0dd451048100915f072423730a93d17c53fd899Jeff Brown                    .commit();
35457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        } else {
35557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            fragment.setCallback(mMediaRouterCB);
35657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            fragment.setRouteSelector(mSelector);
357f0dd451048100915f072423730a93d17c53fd899Jeff Brown        }
358f0dd451048100915f072423730a93d17c53fd899Jeff Brown
35957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // Populate an array adapter with streaming media items.
360ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        String[] mediaNames = getResources().getStringArray(R.array.media_names);
361ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        String[] mediaUris = getResources().getStringArray(R.array.media_uris);
36257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mLibraryItems = new LibraryAdapter();
363ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        for (int i = 0; i < mediaNames.length; i++) {
36457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mLibraryItems.add(new MediaItem(
36557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    "[streaming] "+mediaNames[i], Uri.parse(mediaUris[i])));
366ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        }
367ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
36857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // Scan local /sdcard/ directory for media files.
36957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        String sdcard = "/sdcard/";
37057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        File file = new File(sdcard);
37157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        File list[] = file.listFiles();
37257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        for (int i = 0; i < list.length; i++) {
37357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            String filename = list[i].getName();
37457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (filename.matches(".*\\.(m4v|mp4)")) {
37557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mLibraryItems.add(new MediaItem(
37657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        "[local] "+filename, Uri.parse("file:///sdcard/" + filename)));
37757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
37857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
37957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
38057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mPlayListItems = new PlaylistAdapter();
38157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
382ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        // Initialize the layout.
383ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        setContentView(R.layout.sample_media_router);
384ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
38557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        TabHost tabHost=(TabHost)findViewById(R.id.tabHost);
38657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        tabHost.setup();
38757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        String tabName = getResources().getString(R.string.library_tab_text);
38857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        TabSpec spec1=tabHost.newTabSpec(tabName);
38957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        spec1.setContent(R.id.tab1);
39057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        spec1.setIndicator(tabName);
39157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
39257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        tabName = getResources().getString(R.string.playlist_tab_text);
39357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        TabSpec spec2=tabHost.newTabSpec(tabName);
39457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        spec2.setIndicator(tabName);
39557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        spec2.setContent(R.id.tab2);
39657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
39757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        tabName = getResources().getString(R.string.statistics_tab_text);
39857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        TabSpec spec3=tabHost.newTabSpec(tabName);
39957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        spec3.setIndicator(tabName);
40057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        spec3.setContent(R.id.tab3);
40157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
40257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        tabHost.addTab(spec1);
40357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        tabHost.addTab(spec2);
40457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        tabHost.addTab(spec3);
40557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        tabHost.setOnTabChangedListener(new OnTabChangeListener() {
40657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            @Override
40757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            public void onTabChanged(String arg0) {
40857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                if (arg0.equals(getResources().getString(
40957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        R.string.statistics_tab_text))) {
41057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    mPlayer.showStatistics();
41157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                }
41257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                updateUi();
41357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
41457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        });
41557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
41657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mLibraryView = (ListView) findViewById(R.id.media);
41757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mLibraryView.setAdapter(mLibraryItems);
41857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mLibraryView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
41957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mLibraryView.setOnItemClickListener(new OnItemClickListener() {
42057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            @Override
42157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
42257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                updateButtons();
42357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
42457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        });
425ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
42657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mPlayListView = (ListView) findViewById(R.id.playlist);
42757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mPlayListView.setAdapter(mPlayListItems);
42857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mPlayListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
42957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mPlayListView.setOnItemClickListener(new OnItemClickListener() {
430ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            @Override
431ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
432ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown                updateButtons();
433ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            }
434ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        });
435ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
43657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mInfoTextView = (TextView) findViewById(R.id.info);
43757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
43857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mPauseResumeButton = (ImageButton)findViewById(R.id.pause_resume_button);
43957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mPauseResumeButton.setOnClickListener(new OnClickListener() {
440ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            @Override
441ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            public void onClick(View v) {
44257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                if (!mPaused) {
44357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    mPlayer.pause();
44457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                } else {
44557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    mPlayer.resume();
44657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                }
447ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            }
448ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        });
449ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
45057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mStopButton = (ImageButton)findViewById(R.id.stop_button);
45157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mStopButton.setOnClickListener(new OnClickListener() {
452ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            @Override
453ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            public void onClick(View v) {
45457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mPlayer.stop();
45557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                clearContent();
456ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            }
457ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        });
45857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
45957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mSeekBar = (SeekBar) findViewById(R.id.seekbar);
46057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
46157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            @Override
46257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
46357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                MediaQueueItem item = getCheckedMediaQueueItem();
46457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                if (fromUser && item != null && item.getContentDuration() > 0) {
46557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    long pos = progress * item.getContentDuration() / 100;
46657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    mPlayer.seek(item.getSessionId(), item.getItemId(), pos);
46757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    item.setContentPosition(pos);
46857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    mLastStatusTime = SystemClock.elapsedRealtime();
46957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                }
47057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
47157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            @Override
47257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            public void onStartTrackingTouch(SeekBar seekBar) {
47357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mSeeking = true;
47457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
47557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            @Override
47657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            public void onStopTrackingTouch(SeekBar seekBar) {
47757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mSeeking = false;
47857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                updateUi();
47957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
48057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        });
48157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
48257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // Schedule Ui update
48357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mHandler.postDelayed(mUpdateSeekRunnable, 1000);
48457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
48557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // Use local playback with media player by default
48657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mLocalPlayer.onCreate();
48757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mMediaPlayer.setCallback(mMediaPlayerCB);
48857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mLocalPlayer.setCallback(mMediaPlayer);
48957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mPlayerCB = mMediaPlayer;
49057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mPlayer = mLocalPlayer;
49157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
49257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // Register broadcast receiver to receive status update from MRP
49357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        IntentFilter filter = new IntentFilter();
49457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        filter.addAction(SampleMediaRouterActivity.ACTION_STATUS_CHANGE);
49557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        registerReceiver(mReceiver, filter);
4967578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang
4977578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        // Build the PendingIntent for the remote control client
4987578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
4997578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        mEventReceiver = new ComponentName(getPackageName(),
5007578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                SampleMediaButtonReceiver.class.getName());
5017578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
5027578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        mediaButtonIntent.setComponent(mEventReceiver);
5037578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        mMediaPendingIntent = PendingIntent.getBroadcast(this, 0, mediaButtonIntent, 0);
5047b95dd38981772983f00c5ed91aca4b30b782facJeff Brown
5057b95dd38981772983f00c5ed91aca4b30b782facJeff Brown        // Create and register the remote control client
5067b95dd38981772983f00c5ed91aca4b30b782facJeff Brown        registerRCC();
5077578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    }
5087578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang
5097578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    private void registerRCC() {
5107578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
5117578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            // Create the RCC and register with AudioManager and MediaRouter
5127578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            mAudioManager.requestAudioFocus(mAfChangeListener,
5137578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
5147578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            mAudioManager.registerMediaButtonEventReceiver(mEventReceiver);
5157578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            mRemoteControlClient = new RemoteControlClient(mMediaPendingIntent);
5167578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            mAudioManager.registerRemoteControlClient(mRemoteControlClient);
5177578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            mMediaRouter.addRemoteControlClient(mRemoteControlClient);
5187578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            SampleMediaButtonReceiver.setActivity(SampleMediaRouterActivity.this);
5197578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            mRemoteControlClient.setTransportControlFlags(
5207578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE);
5217578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            mRemoteControlClient.setPlaybackState(
5227578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    RemoteControlClient.PLAYSTATE_PLAYING);
5237578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        }
5247578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    }
5257578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang
5267578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    private void unregisterRCC() {
5277578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        // Unregister the RCC with AudioManager and MediaRouter
5287578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        if (mRemoteControlClient != null) {
5297578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            mRemoteControlClient.setTransportControlFlags(0);
5307578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            mAudioManager.abandonAudioFocus(mAfChangeListener);
5317578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            mAudioManager.unregisterMediaButtonEventReceiver(mEventReceiver);
5327578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            mAudioManager.unregisterRemoteControlClient(mRemoteControlClient);
5337578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            mMediaRouter.removeRemoteControlClient(mRemoteControlClient);
5347578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            SampleMediaButtonReceiver.setActivity(null);
5357578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            mRemoteControlClient = null;
5367578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        }
5377578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    }
5387578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang
5397578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    public boolean handleMediaKey(KeyEvent event) {
5407578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
5417578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            switch (event.getKeyCode()) {
5427578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
5437578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                {
5447578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    Log.d(TAG, "Received Play/Pause event from RemoteControlClient");
5457578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    if (!mPaused) {
5467578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                        mPlayer.pause();
5477578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    } else {
5487578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                        mPlayer.resume();
5497578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    }
5507578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    return true;
5517578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                }
5527578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                case KeyEvent.KEYCODE_MEDIA_PLAY:
5537578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                {
5547578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    Log.d(TAG, "Received Play event from RemoteControlClient");
5557578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    if (mPaused) {
5567578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                        mPlayer.resume();
5577578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    }
5587578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    return true;
5597578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                }
5607578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                case KeyEvent.KEYCODE_MEDIA_PAUSE:
5617578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                {
5627578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    Log.d(TAG, "Received Pause event from RemoteControlClient");
5637578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    if (!mPaused) {
5647578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                        mPlayer.pause();
5657578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    }
5667578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    return true;
5677578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                }
5687578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                case KeyEvent.KEYCODE_MEDIA_STOP:
5697578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                {
5707578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    Log.d(TAG, "Received Stop event from RemoteControlClient");
5717578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    mPlayer.stop();
5727578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    clearContent();
5737578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    return true;
5747578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                }
5757578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                default:
5767578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    break;
5777578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            }
5787578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        }
5797578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        return false;
5807578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    }
5817578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang
5827578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    @Override
5837578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    public boolean onKeyDown(int keyCode, KeyEvent event) {
5847578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        return handleMediaKey(event) || super.onKeyDown(keyCode, event);
5857578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    }
5867578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang
5877578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    @Override
5887578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang    public boolean onKeyUp(int keyCode, KeyEvent event) {
5897578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        return handleMediaKey(event) || super.onKeyUp(keyCode, event);
590ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    }
591ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
592ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    @Override
593f0dd451048100915f072423730a93d17c53fd899Jeff Brown    public void onStart() {
594ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        // Be sure to call the super class.
595f0dd451048100915f072423730a93d17c53fd899Jeff Brown        super.onStart();
59657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mPlayer.showStatistics();
59757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    }
598ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
59957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    @Override
60057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    public void onPause() {
60157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // pause media player for local playback case only
60257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        if (!isRemotePlayback() && !mPaused) {
60357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mNeedResume = true;
60457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mPlayer.pause();
60557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
60657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        super.onPause();
60757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    }
60857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
60957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    @Override
61057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    public void onResume() {
61157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // resume media player for local playback case only
61257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        if (!isRemotePlayback() && mNeedResume) {
61357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mPlayer.resume();
61457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mNeedResume = false;
61557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
61657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        super.onResume();
61757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    }
61857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
61957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    @Override
62057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    public void onDestroy() {
6217b95dd38981772983f00c5ed91aca4b30b782facJeff Brown        // Unregister the remote control client
6227b95dd38981772983f00c5ed91aca4b30b782facJeff Brown        unregisterRCC();
6237b95dd38981772983f00c5ed91aca4b30b782facJeff Brown
62457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // Unregister broadcast receiver
62557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        unregisterReceiver(mReceiver);
62657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mPlayer.stop();
62757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mMediaPlayer.release();
6287b95dd38981772983f00c5ed91aca4b30b782facJeff Brown
62957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        super.onDestroy();
630ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    }
631ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
632ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    @Override
633ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    public boolean onCreateOptionsMenu(Menu menu) {
634ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        // Be sure to call the super class.
635ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        super.onCreateOptionsMenu(menu);
636ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
637ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        // Inflate the menu and configure the media router action provider.
638ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        getMenuInflater().inflate(R.menu.sample_media_router_menu, menu);
639ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
64055e47d370890d3cbdab82857090c42df734ba276Jeff Brown        MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item);
641ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        MediaRouteActionProvider mediaRouteActionProvider =
64255e47d370890d3cbdab82857090c42df734ba276Jeff Brown                (MediaRouteActionProvider)MenuItemCompat.getActionProvider(mediaRouteMenuItem);
64355e47d370890d3cbdab82857090c42df734ba276Jeff Brown        mediaRouteActionProvider.setRouteSelector(mSelector);
644ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
645ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        // Return true to show the menu.
646ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        return true;
647ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    }
648ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
649b28eb61b29c0d956a5e504716cdea9f31184a998Jeff Brown    private void updateRouteDescription() {
650ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        RouteInfo route = mMediaRouter.getSelectedRoute();
65157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mInfoTextView.setText("Currently selected route:"
65257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                + "\nName: " + route.getName()
65357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                + "\nProvider: " + route.getProvider().getPackageName()
65457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                + "\nDescription: " + route.getDescription()
65557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                + "\nStatistics: " + mStatsInfo);
656ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        updateButtons();
65757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mLocalPlayer.updatePresentation();
65857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    }
65957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
66057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private void clearContent() {
66157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        //TO-DO: clear surface view
662ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    }
663ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
664ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    private void updateButtons() {
665ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
66657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // show pause or resume icon depending on current state
66757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mPauseResumeButton.setImageResource(mPaused ?
66857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                R.drawable.ic_media_play : R.drawable.ic_media_pause);
66957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // only enable seek bar when duration is known
67057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        MediaQueueItem item = getCheckedMediaQueueItem();
67157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mSeekBar.setEnabled(item != null && item.getContentDuration() > 0);
6727578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        if (mRemoteControlClient != null) {
6737578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            mRemoteControlClient.setPlaybackState(mPaused ?
6747578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                    RemoteControlClient.PLAYSTATE_PAUSED : RemoteControlClient.PLAYSTATE_PLAYING);
6757578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang        }
67657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    }
677ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
67857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private void updateProgress(MediaQueueItem queueItem) {
67957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // Estimate content position from last status time and elapsed time.
68057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // (Note this might be slightly out of sync with remote side, however
68157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // it avoids frequent polling the MRP.)
68257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        int progress = 0;
68357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        if (queueItem != null) {
68457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            int state = queueItem.getState();
68557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            long duration = queueItem.getContentDuration();
68657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (duration <= 0) {
68757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                if (state == MediaItemStatus.PLAYBACK_STATE_PLAYING
68857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        || state == MediaItemStatus.PLAYBACK_STATE_PAUSED) {
68957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    updateUi();
69057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                }
69157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            } else {
69257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                long position = queueItem.getContentPosition();
69357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                long timeDelta = mPaused ? 0 :
69457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        (SystemClock.elapsedRealtime() - mLastStatusTime);
69557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                progress = (int)(100.0 * (position + timeDelta) / duration);
69657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
697ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        }
69857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mSeekBar.setProgress(progress);
69957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    }
700ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
70157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private void updateUi() {
70257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        updatePlaylist();
70357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        updateButtons();
704ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    }
705ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
70657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private void updatePlaylist() {
70757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        Log.d(TAG, "updatePlaylist");
70857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        final PlaylistAdapter playlist = new PlaylistAdapter();
70957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // make a copy of current playlist
71057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        for (int i = 0; i < mPlayListItems.getCount(); i++) {
71157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            playlist.add(mPlayListItems.getItem(i));
712ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        }
71357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // clear mPlayListItems first, items will be added back when we get
71457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // status back from provider.
71557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mPlayListItems.clear();
71657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        mPlayListView.invalidate();
717ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
71857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        for (int i = 0; i < playlist.getCount(); i++) {
71957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            final MediaQueueItem item = playlist.getItem(i);
72057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            final boolean update = (i == playlist.getCount() - 1);
72157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mPlayer.getStatus(item, update);
72257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
72357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    }
724fcb6a9d1caaf43ae41f859ebb58a4483b12475a1Jeff Brown
72557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private MediaItem getCheckedMediaItem() {
72657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        int index = mLibraryView.getCheckedItemPosition();
72757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        if (index >= 0 && index < mLibraryItems.getCount()) {
72857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            return mLibraryItems.getItem(index);
72957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
73057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        return null;
73157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    }
732ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
73357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private MediaQueueItem getCheckedMediaQueueItem() {
73457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        int count = mPlayListView.getCount();
73557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        int index = mPlayListView.getCheckedItemPosition();
73657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        if (count > 0) {
73757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (index < 0 || index >= count) {
73857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                index = 0;
73957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mPlayListView.setItemChecked(0, true);
74057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
74157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            return mPlayListItems.getItem(index);
742ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        }
74357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        return null;
744ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    }
745ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
74657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private void enqueuePlaylist() {
74757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        if (mSavedPlaylist != null) {
74857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            final PlaylistAdapter playlist = mSavedPlaylist;
74957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mSavedPlaylist = null;
75057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            // migrate playlist (except for the 1st item) to new route
75157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            for (int i = 1; i < playlist.getCount(); i++) {
75257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                final MediaQueueItem item = playlist.getItem(i);
75357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mPlayer.enqueue(item.getUri(), item.getContentPosition());
75457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
75557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
75657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    }
757fcb6a9d1caaf43ae41f859ebb58a4483b12475a1Jeff Brown
75857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private boolean isRemoteQueue() {
75957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        return mPlayer == mRemotePlayer;
76057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    }
761ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
76257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private boolean isRemotePlayback() {
76357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        return mPlayerCB == mRemotePlayer;
764ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    }
765ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
76657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private void showToast(String msg) {
76757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        Toast toast = Toast.makeText(SampleMediaRouterActivity.this,
76857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                "[app] " + msg, Toast.LENGTH_LONG);
76957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        toast.setGravity(Gravity.TOP, 0, 100);
77057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        toast.show();
771ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    }
772ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
7737b95dd38981772983f00c5ed91aca4b30b782facJeff Brown    private interface Player {
7747b95dd38981772983f00c5ed91aca4b30b782facJeff Brown        void enqueue(final Uri uri, long pos);
7757b95dd38981772983f00c5ed91aca4b30b782facJeff Brown        void remove(final MediaQueueItem item);
7767b95dd38981772983f00c5ed91aca4b30b782facJeff Brown        void seek(String sid, String iid, long pos);
7777b95dd38981772983f00c5ed91aca4b30b782facJeff Brown        void getStatus(final MediaQueueItem item, final boolean update);
7787b95dd38981772983f00c5ed91aca4b30b782facJeff Brown        void pause();
7797b95dd38981772983f00c5ed91aca4b30b782facJeff Brown        void resume();
7807b95dd38981772983f00c5ed91aca4b30b782facJeff Brown        void stop();
7817b95dd38981772983f00c5ed91aca4b30b782facJeff Brown        void showStatistics();
7827b95dd38981772983f00c5ed91aca4b30b782facJeff Brown        void onFinish(boolean error);
7837b95dd38981772983f00c5ed91aca4b30b782facJeff Brown        void updateSize(int width, int height);
784ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    }
785ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
7867b95dd38981772983f00c5ed91aca4b30b782facJeff Brown    private class LocalPlayer implements Player, SurfaceHolder.Callback {
78757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private final MediaSessionManager mSessionManager = new MediaSessionManager();
78857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private String mSessionId;
78957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // The presentation to show on the secondary display.
79057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private DemoPresentation mPresentation;
79157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private SurfaceView mSurfaceView;
79257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private FrameLayout mLayout;
79357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private int mVideoWidth;
79457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private int mVideoHeight;
79557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
79657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onCreate() {
79757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mLayout = (FrameLayout)findViewById(R.id.player);
79857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mSurfaceView = (SurfaceView)findViewById(R.id.surface_view);
79957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            SurfaceHolder holder = mSurfaceView.getHolder();
8004523ef115a83bf0f655dc58262bd156d7555c91bChong Zhang            holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
8017b95dd38981772983f00c5ed91aca4b30b782facJeff Brown            holder.addCallback(this);
80257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
80357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
80457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void setCallback(MediaSessionManager.Callback cb) {
80557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mSessionManager.setCallback(cb);
806ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        }
807ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
808ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        @Override
80957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void enqueue(final Uri uri, long pos) {
81057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "LocalPlayer: enqueue, uri=" + uri + ", pos=" + pos);
81157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            MediaQueueItem playlistItem = mSessionManager.enqueue(mSessionId, uri, null);
81257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mSessionId = playlistItem.getSessionId();
8137578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            // Set remote control client title
8147578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            if (mPlayListItems.getCount() == 0 && mRemoteControlClient != null) {
8157578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                RemoteControlClient.MetadataEditor ed = mRemoteControlClient.editMetadata(true);
8167578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                ed.putString(MediaMetadataRetriever.METADATA_KEY_TITLE,
8177578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                        playlistItem.toString());
8187578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang                ed.apply();
8197578fad97dcd3b4b390652f37a30d805538980f5Chong Zhang            }
82057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mPlayListItems.add(playlistItem);
82157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (pos > 0) {
82257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                // Seek to initial position if needed
82357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mPlayer.seek(mSessionId, playlistItem.getItemId(), pos);
82457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
82557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            updateUi();
82657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
827ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
82857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
82957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void remove(final MediaQueueItem item) {
83057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "LocalPlayer: remove, item=" + item);
83157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mSessionManager.remove(item.getSessionId(), item.getItemId());
83257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            updateUi();
83357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
834ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
83557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
83657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void seek(String sid, String iid, long pos) {
83757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "LocalPlayer: seek, sid=" + sid + ", iid=" + iid);
83857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mSessionManager.seek(sid, iid, pos);
83957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
840ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
84157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
84257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void getStatus(final MediaQueueItem item, final boolean update) {
84357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "LocalPlayer: getStatus, item=" + item + ", update=" + update);
84457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            MediaQueueItem playlistItem =
84557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    mSessionManager.getStatus(item.getSessionId(), item.getItemId());
84657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (playlistItem != null) {
84757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mLastStatusTime = playlistItem.getStatus().getTimestamp();
84857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mPlayListItems.add(item);
84957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mPlayListView.invalidate();
85057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
85157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (update) {
85257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                clearContent();
85357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                updateButtons();
85457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
85557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
856ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
85757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
85857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void pause() {
85957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "LocalPlayer: pause");
86057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mSessionManager.pause(mSessionId);
86157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mPaused = true;
86257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            updateUi();
86357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
864ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
86557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
86657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void resume() {
86757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "LocalPlayer: resume");
86857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mSessionManager.resume(mSessionId);
86957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mPaused = false;
87057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            updateUi();
87157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
872ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
87357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
87457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void stop() {
87557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "LocalPlayer: stop");
87657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mSessionManager.stop(mSessionId);
87757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mSessionId = null;
87857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mPaused = false;
87957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            // For demo purpose, invalidate remote session when local session
88057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            // is stopped (note this is not necessary, remote player could reuse
88157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            // the same session)
88257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mRemotePlayer.reset();
88357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            updateUi();
88457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
88557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
88657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
88757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void showStatistics() {
88857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "LocalPlayer: showStatistics");
88957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mStatsInfo = null;
89057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (isRemotePlayback()) {
89157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mRemotePlayer.showStatistics();
89257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
89357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            updateRouteDescription();
89457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
89557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
89657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
89757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onFinish(boolean error) {
89857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            MediaQueueItem item = mSessionManager.finish(error);
89957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            updateUi();
9008e006e629800b4a2643416f97bca2711af728837Jeff Brown            if (error && item != null) {
90157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                showToast("Failed to play item " + item.getUri());
90257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
90357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
90457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
90557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // SurfaceHolder.Callback
90657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
90757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void surfaceChanged(SurfaceHolder holder, int format,
90857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                int width, int height) {
90957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "surfaceChanged "+width+"x"+height);
9108e006e629800b4a2643416f97bca2711af728837Jeff Brown            mMediaPlayer.setSurface(holder);
91157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
91257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
91357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
91457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void surfaceCreated(SurfaceHolder holder) {
91557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "surfaceCreated");
9168e006e629800b4a2643416f97bca2711af728837Jeff Brown            mMediaPlayer.setSurface(holder);
9177b95dd38981772983f00c5ed91aca4b30b782facJeff Brown            updateSize(mVideoWidth, mVideoHeight);
91857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
91957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
92057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
92157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void surfaceDestroyed(SurfaceHolder holder) {
92257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Log.d(TAG, "surfaceDestroyed");
92357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
92457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
9257b95dd38981772983f00c5ed91aca4b30b782facJeff Brown        @Override
9267b95dd38981772983f00c5ed91aca4b30b782facJeff Brown        public void updateSize(int width, int height) {
92757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (width > 0 && height > 0) {
92857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                if (mPresentation == null) {
92957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    int surfaceWidth = mLayout.getWidth();
93057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    int surfaceHeight = mLayout.getHeight();
93157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
93257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    // Calculate the new size of mSurfaceView, so that video is centered
93357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    // inside the framelayout with proper letterboxing/pillarboxing
93457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    ViewGroup.LayoutParams lp = mSurfaceView.getLayoutParams();
93557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    if (surfaceWidth * height < surfaceHeight * width) {
93657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        // Black bars on top&bottom, mSurfaceView has full layout width,
93757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        // while height is derived from video's aspect ratio
93857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        lp.width = surfaceWidth;
93957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        lp.height = surfaceWidth * height / width;
94057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    } else {
94157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        // Black bars on left&right, mSurfaceView has full layout height,
94257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        // while width is derived from video's aspect ratio
94357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        lp.width = surfaceHeight * width / height;
94457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        lp.height = surfaceHeight;
94557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    }
94657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    Log.d(TAG, "video rect is "+lp.width+"x"+lp.height);
94757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    mSurfaceView.setLayoutParams(lp);
94857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                } else {
94957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    mPresentation.updateSize(width, height);
950f0dd451048100915f072423730a93d17c53fd899Jeff Brown                }
95157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mVideoWidth = width;
95257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mVideoHeight = height;
95357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            } else {
95457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mVideoWidth = mVideoHeight = 0;
95557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
95657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
957ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
95857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private void updatePresentation() {
95957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            // Get the current route and its presentation display.
96057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
96157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Display presentationDisplay = route != null ? route.getPresentationDisplay() : null;
96257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
96357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            // Dismiss the current presentation if the display has changed.
96457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (mPresentation != null && mPresentation.getDisplay() != presentationDisplay) {
96557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                Log.i(TAG, "Dismissing presentation because the current route no longer "
96657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        + "has a presentation display.");
96757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mPresentation.dismiss();
96857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mPresentation = null;
96957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
97057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
97157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            // Show a new presentation if needed.
97257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (mPresentation == null && presentationDisplay != null) {
97357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                Log.i(TAG, "Showing presentation on display: " + presentationDisplay);
97457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mPresentation = new DemoPresentation(
97557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        SampleMediaRouterActivity.this, presentationDisplay);
97657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mPresentation.setOnDismissListener(mOnDismissListener);
97757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                try {
97857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    mPresentation.show();
97957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                } catch (WindowManager.InvalidDisplayException ex) {
98057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    Log.w(TAG, "Couldn't show presentation!  Display was removed in "
98157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            + "the meantime.", ex);
98257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    mPresentation = null;
983f0dd451048100915f072423730a93d17c53fd899Jeff Brown                }
98457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
985ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
98657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (mPresentation != null || route.supportsControlCategory(
98757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {
9884523ef115a83bf0f655dc58262bd156d7555c91bChong Zhang                mMediaPlayer.setSurface((SurfaceHolder)null);
9894523ef115a83bf0f655dc58262bd156d7555c91bChong Zhang                mMediaPlayer.reset();
99057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mSurfaceView.setVisibility(View.GONE);
99157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mLayout.setVisibility(View.GONE);
99257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            } else {
99357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mLayout.setVisibility(View.VISIBLE);
99457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mSurfaceView.setVisibility(View.VISIBLE);
99557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
99657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
99757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
99857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // Listens for when presentations are dismissed.
99957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private final DialogInterface.OnDismissListener mOnDismissListener =
100057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                new DialogInterface.OnDismissListener() {
100157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            @Override
100257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            public void onDismiss(DialogInterface dialog) {
100357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                if (dialog == mPresentation) {
100457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    Log.i(TAG, "Presentation was dismissed.");
100557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    mPresentation = null;
100657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    updatePresentation();
1007f0dd451048100915f072423730a93d17c53fd899Jeff Brown                }
100857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
100957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        };
1010f0dd451048100915f072423730a93d17c53fd899Jeff Brown
101157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private final class DemoPresentation extends Presentation {
10128e006e629800b4a2643416f97bca2711af728837Jeff Brown            private SurfaceView mPresentationSurfaceView;
101357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
101457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            public DemoPresentation(Context context, Display display) {
101557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                super(context, display);
101657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
101757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
101857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            @Override
101957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            protected void onCreate(Bundle savedInstanceState) {
102057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                // Be sure to call the super class.
102157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                super.onCreate(savedInstanceState);
102257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
102357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                // Get the resources for the context of the presentation.
102457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                // Notice that we are getting the resources from the context
102557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                // of the presentation.
102657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                Resources r = getContext().getResources();
102757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
102857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                // Inflate the layout.
102957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                setContentView(R.layout.sample_media_router_presentation);
103057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
10318e006e629800b4a2643416f97bca2711af728837Jeff Brown                // Set up the surface view.
10328e006e629800b4a2643416f97bca2711af728837Jeff Brown                mPresentationSurfaceView = (SurfaceView)findViewById(R.id.surface_view);
10338e006e629800b4a2643416f97bca2711af728837Jeff Brown                SurfaceHolder holder = mPresentationSurfaceView.getHolder();
10344523ef115a83bf0f655dc58262bd156d7555c91bChong Zhang                holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
10357b95dd38981772983f00c5ed91aca4b30b782facJeff Brown                holder.addCallback(LocalPlayer.this);
103657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
103757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
103857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            public void updateSize(int width, int height) {
10398e006e629800b4a2643416f97bca2711af728837Jeff Brown                int surfaceHeight = getWindow().getDecorView().getHeight();
10408e006e629800b4a2643416f97bca2711af728837Jeff Brown                int surfaceWidth = getWindow().getDecorView().getWidth();
10418e006e629800b4a2643416f97bca2711af728837Jeff Brown                ViewGroup.LayoutParams lp = mPresentationSurfaceView.getLayoutParams();
104257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                if (surfaceWidth * height < surfaceHeight * width) {
104357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    lp.width = surfaceWidth;
104457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    lp.height = surfaceWidth * height / width;
104557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                } else {
104657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    lp.width = surfaceHeight * width / height;
104757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    lp.height = surfaceHeight;
1048f0dd451048100915f072423730a93d17c53fd899Jeff Brown                }
10498e006e629800b4a2643416f97bca2711af728837Jeff Brown                Log.d(TAG, "video rect is " + lp.width + "x" + lp.height);
10508e006e629800b4a2643416f97bca2711af728837Jeff Brown                mPresentationSurfaceView.setLayoutParams(lp);
105157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
105257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
105357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    }
105457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
10557b95dd38981772983f00c5ed91aca4b30b782facJeff Brown    private class RemotePlayer implements Player, MediaSessionManager.Callback {
105657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private MediaQueueItem mQueueItem;
105757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private MediaQueueItem mPlaylistItem;
105857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private String mSessionId;
105957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private String mItemId;
106057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private long mPosition;
106157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
106257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void reset() {
106357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mQueueItem = null;
106457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mPlaylistItem = null;
106557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mSessionId = null;
106657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mItemId = null;
106757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mPosition = 0;
106857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
106957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
107057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // MediaSessionManager.Callback
107157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
107257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onStart() {
107357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            resume();
107457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
107557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
107657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
107757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onPause() {
107857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            pause();
107957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
108057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
108157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
108257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onStop() {
108357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            stop();
108457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
108557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
108657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
108757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onSeek(long pos) {
108857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            // If we're currently performing a Play/Enqueue, do not seek
108957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            // until we get the result back (or we may not have valid session
109057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            // and item ids); otherwise do the seek now
109157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (mSessionId != null) {
109257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                seek(mSessionId, mItemId, pos);
109357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
109457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            // Set current position to seek-to position, actual position will
109557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            // be updated when next getStatus is completed.
109657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mPosition = pos;
109757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
109857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
109957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
110057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onGetStatus(MediaQueueItem item) {
110157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (mQueueItem != null) {
110257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                mPlaylistItem = item;
110357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                getStatus(mQueueItem, false);
110457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
110557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
110657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
110757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
110857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onNewItem(Uri uri) {
110957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mPosition = 0;
111057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            play(uri, false, 0);
111157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
111257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
111357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        // Player API
111457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
111557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void enqueue(final Uri uri, long pos) {
111657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            play(uri, true, pos);
111757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
111857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
111957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
112057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void remove(final MediaQueueItem item) {
112157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
112257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Intent intent = makeRemoveIntent(item);
112357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (route.supportsControlRequest(intent)) {
112457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                MediaRouter.ControlRequestCallback callback =
112557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        new MediaRouter.ControlRequestCallback() {
112657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    @Override
112757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    public void onResult(Bundle data) {
112857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        MediaItemStatus status = MediaItemStatus.fromBundle(
112957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                data.getBundle(MediaControlIntent.EXTRA_ITEM_STATUS));
113057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        Log.d(TAG, "Remove request succeeded: status=" + status.toString());
113157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        updateUi();
113257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    }
113357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
113457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    @Override
113557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    public void onError(String error, Bundle data) {
113657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        Log.d(TAG, "Remove request failed: error=" + error + ", data=" + data);
113757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    }
113857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                };
113957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
114057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                Log.d(TAG, "Sending remove request: intent=" + intent);
114157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                route.sendControlRequest(intent, callback);
114257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            } else {
114357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                Log.d(TAG, "Remove request not supported!");
114457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
114557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
114657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
114757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
114857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void seek(String sid, String iid, long pos) {
114957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
115057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Intent intent = makeSeekIntent(sid, iid, pos);
115157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (route.supportsControlRequest(intent)) {
115257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                MediaRouter.ControlRequestCallback callback =
115357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        new MediaRouter.ControlRequestCallback() {
115457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    @Override
115557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    public void onResult(Bundle data) {
115657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        MediaItemStatus status = MediaItemStatus.fromBundle(
115757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                data.getBundle(MediaControlIntent.EXTRA_ITEM_STATUS));
115857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        Log.d(TAG, "Seek request succeeded: status=" + status.toString());
115957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    }
116057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
116157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    @Override
116257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    public void onError(String error, Bundle data) {
116357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        Log.d(TAG, "Seek request failed: error=" + error + ", data=" + data);
116457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    }
116557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                };
116657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
116757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                Log.d(TAG, "Sending seek request: intent=" + intent);
116857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                route.sendControlRequest(intent, callback);
116957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            } else {
117057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                Log.d(TAG, "Seek request not supported!");
117157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
117257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
117357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
117457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
117557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void getStatus(final MediaQueueItem item, final boolean update) {
117657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
117757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Intent intent = makeGetStatusIntent(item);
117857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (route.supportsControlRequest(intent)) {
117957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                MediaRouter.ControlRequestCallback callback =
118057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        new MediaRouter.ControlRequestCallback() {
118157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    @Override
118257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    public void onResult(Bundle data) {
118357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        if (data != null) {
118457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            String sid = data.getString(MediaControlIntent.EXTRA_SESSION_ID);
118557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            String iid = data.getString(MediaControlIntent.EXTRA_ITEM_ID);
118657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            MediaItemStatus status = MediaItemStatus.fromBundle(
118757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                    data.getBundle(MediaControlIntent.EXTRA_ITEM_STATUS));
118857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            Log.d(TAG, "GetStatus request succeeded: status=" + status.toString());
118957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            //showToast("GetStatus request succeeded " + item.mName);
119057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            if (isRemoteQueue()) {
119157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                int state = status.getPlaybackState();
119257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                if (state == MediaItemStatus.PLAYBACK_STATE_PLAYING
119357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                        || state == MediaItemStatus.PLAYBACK_STATE_PAUSED
119457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                        || state == MediaItemStatus.PLAYBACK_STATE_PENDING) {
119557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                    item.setState(state);
119657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                    item.setContentPosition(status.getContentPosition());
119757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                    item.setContentDuration(status.getContentDuration());
119857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                    mLastStatusTime = status.getTimestamp();
119957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                    mPlayListItems.add(item);
120057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                    mPlayListView.invalidate();
120157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                    // update buttons as the queue count might have changed
120257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                    if (update) {
120357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                        clearContent();
120457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                        updateButtons();
120557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                    }
120657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                }
120757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            } else {
120857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                if (mPlaylistItem != null) {
120957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                    mPlaylistItem.setContentPosition(status.getContentPosition());
121057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                    mPlaylistItem.setContentDuration(status.getContentDuration());
121157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                    mPlaylistItem = null;
121257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                    updateButtons();
121357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                }
121457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            }
121557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        }
121657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    }
121757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
121857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    @Override
121957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    public void onError(String error, Bundle data) {
122057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        Log.d(TAG, "GetStatus request failed: error=" + error + ", data=" + data);
122157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        //showToast("Unable to get status ");
122257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        if (isRemoteQueue()) {
122357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            if (update) {
122457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                clearContent();
122557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                updateButtons();
122657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            }
122757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        }
122857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    }
122957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                };
123057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
123157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                Log.d(TAG, "Sending GetStatus request: intent=" + intent);
123257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                route.sendControlRequest(intent, callback);
123357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            } else {
123457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                Log.d(TAG, "GetStatus request not supported!");
123557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
123657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
123757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
123857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
123957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void pause() {
124057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Intent intent = makePauseIntent();
124157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
124257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (route.supportsControlRequest(intent)) {
124357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                MediaRouter.ControlRequestCallback callback =
124457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        new MediaRouter.ControlRequestCallback() {
124557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    @Override
124657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    public void onResult(Bundle data) {
124757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        Log.d(TAG, "Pause request succeeded");
124857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        if (isRemoteQueue()) {
124957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            mPaused = true;
125057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            updateUi();
125157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        }
125257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    }
125357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
125457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    @Override
125557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    public void onError(String error, Bundle data) {
125657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        Log.d(TAG, "Pause request failed: error=" + error);
125757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    }
125857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                };
125957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
126057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                Log.d(TAG, "Sending pause request");
126157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                route.sendControlRequest(intent, callback);
126257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            } else {
126357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                Log.d(TAG, "Pause request not supported!");
126457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
126557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
126657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
126757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
126857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void resume() {
126957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Intent intent = makeResumeIntent();
127057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
127157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (route.supportsControlRequest(intent)) {
127257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                MediaRouter.ControlRequestCallback callback =
127357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        new MediaRouter.ControlRequestCallback() {
127457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    @Override
127557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    public void onResult(Bundle data) {
127657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        Log.d(TAG, "Resume request succeeded");
127757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        if (isRemoteQueue()) {
127857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            mPaused = false;
127957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            updateUi();
128057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        }
128157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    }
128257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
128357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    @Override
128457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    public void onError(String error, Bundle data) {
128557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        Log.d(TAG, "Resume request failed: error=" + error);
128657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    }
128757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                };
128857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
128957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                Log.d(TAG, "Sending resume request");
129057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                route.sendControlRequest(intent, callback);
129157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            } else {
129257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                Log.d(TAG, "Resume request not supported!");
129357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
129457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
129557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
129657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
129757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void stop() {
129857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Intent intent = makeStopIntent();
129957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
130057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (route.supportsControlRequest(intent)) {
130157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                MediaRouter.ControlRequestCallback callback =
130257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        new MediaRouter.ControlRequestCallback() {
130357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    @Override
130457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    public void onResult(Bundle data) {
130557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        Log.d(TAG, "Stop request succeeded");
130657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        if (isRemoteQueue()) {
130757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            // Reset mSessionId, so that next Play/Enqueue
130857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            // starts a new session
130957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            mQueueItem = null;
131057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            mSessionId = null;
131157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            mPaused = false;
131257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            updateUi();
131357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        }
131457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    }
131557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
131657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    @Override
131757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    public void onError(String error, Bundle data) {
131857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        Log.d(TAG, "Stop request failed: error=" + error);
131957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    }
132057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                };
132157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
132257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                Log.d(TAG, "Sending stop request");
132357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                route.sendControlRequest(intent, callback);
132457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            } else {
132557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                Log.d(TAG, "Stop request not supported!");
132657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
132757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
132857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
132957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
133057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void showStatistics() {
133157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
133257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Intent intent = makeStatisticsIntent();
133357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (route.supportsControlRequest(intent)) {
133457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                MediaRouter.ControlRequestCallback callback =
133557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        new MediaRouter.ControlRequestCallback() {
133657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    @Override
133757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    public void onResult(Bundle data) {
133857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        Log.d(TAG, "Statistics request succeeded: data=" + data);
133957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        if (data != null) {
134057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            int playbackCount = data.getInt(
134157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                    SampleMediaRouteProvider.DATA_PLAYBACK_COUNT, -1);
134257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            mStatsInfo = "Total playback count: " + playbackCount;
134357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        } else {
134457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            showToast("Statistics query did not return any data");
134557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        }
134657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        updateRouteDescription();
134757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    }
134857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
134957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    @Override
135057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    public void onError(String error, Bundle data) {
135157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        Log.d(TAG, "Statistics request failed: error=" + error + ", data=" + data);
135257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        showToast("Unable to query statistics, error: " + error);
135357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        updateRouteDescription();
135457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    }
135557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                };
135657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
135757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                Log.d(TAG, "Sent statistics request: intent=" + intent);
135857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                route.sendControlRequest(intent, callback);
135957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            } else {
136057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                Log.d(TAG, "Statistics request not supported!");
136157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
136257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
136357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
136457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
136557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
136657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void onFinish(boolean error) {
136757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            updateUi();
136857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
136957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
13707b95dd38981772983f00c5ed91aca4b30b782facJeff Brown        @Override
13717b95dd38981772983f00c5ed91aca4b30b782facJeff Brown        public void updateSize(int width, int height) {
13727b95dd38981772983f00c5ed91aca4b30b782facJeff Brown            // nothing to do
13737b95dd38981772983f00c5ed91aca4b30b782facJeff Brown        }
13747b95dd38981772983f00c5ed91aca4b30b782facJeff Brown
137557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private void play(final Uri uri, boolean enqueue, final long pos) {
137657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            // save the initial seek position
137757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mPosition = pos;
137857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
137957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Intent intent = makePlayIntent(uri, enqueue);
138057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            final String request = enqueue ? "Enqueue" : "Play";
138157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (route.supportsControlRequest(intent)) {
138257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                MediaRouter.ControlRequestCallback callback =
138357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        new MediaRouter.ControlRequestCallback() {
138457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    @Override
138557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    public void onResult(Bundle data) {
138657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        if (data != null) {
138757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            String sid = data.getString(MediaControlIntent.EXTRA_SESSION_ID);
138857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            String iid = data.getString(MediaControlIntent.EXTRA_ITEM_ID);
138957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            MediaItemStatus status = MediaItemStatus.fromBundle(
139057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                    data.getBundle(MediaControlIntent.EXTRA_ITEM_STATUS));
139157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            Log.d(TAG, request + " request succeeded: data=" + data +
139257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                    ", sid=" + sid + ", iid=" + iid);
139357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
139457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            // perform delayed initial seek
139557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            if (mSessionId == null && mPosition > 0) {
139657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                seek(sid, iid, mPosition);
139757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            }
139857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
139957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            mSessionId = sid;
140057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            mItemId = iid;
140157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            mQueueItem = new MediaQueueItem(sid, iid, null, null);
140257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
140357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            if (isRemoteQueue()) {
140457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                MediaQueueItem playlistItem =
140557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                        new MediaQueueItem(sid, iid, uri, null);
140657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                playlistItem.setState(status.getPlaybackState());
140757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                mPlayListItems.add(playlistItem);
140857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                updateUi();
140957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                                enqueuePlaylist();
141057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            }
141157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        }
141257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    }
141357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
141457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    @Override
141557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    public void onError(String error, Bundle data) {
141657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        Log.d(TAG, request + " request failed: error=" + error + ", data=" + data);
141757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        showToast("Unable to " + request + uri + ", error: " + error);
141857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    }
141957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                };
142057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
142157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                Log.d(TAG, "Sending " + request + " request: intent=" + intent);
142257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                route.sendControlRequest(intent, callback);
142357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            } else {
142457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                Log.d(TAG, request + " request not supported!");
142557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
142657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
142757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
142857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private Intent makePlayIntent(Uri uri, boolean enqueue) {
142957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Intent intent = new Intent(
143057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    enqueue ? MediaControlIntent.ACTION_ENQUEUE
143157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            : MediaControlIntent.ACTION_PLAY);
143257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            intent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
143357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            intent.setDataAndType(uri, "video/mp4");
143457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
143557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            // Provide a valid session id, or none (which starts a new session)
143657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (mSessionId != null) {
143757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, mSessionId);
143857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
143957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
144057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            // PendingIntent for receiving status update from MRP
144157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Intent statusIntent = new Intent(SampleMediaRouterActivity.ACTION_STATUS_CHANGE);
144257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            intent.putExtra(MediaControlIntent.EXTRA_ITEM_STATUS_UPDATE_RECEIVER,
144357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    PendingIntent.getBroadcast(SampleMediaRouterActivity.this,
144457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                            0, statusIntent, 0));
144557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
144657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            return intent;
144757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
144857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
144957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private Intent makeRemoveIntent(MediaQueueItem item) {
145057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Intent intent = new Intent(MediaControlIntent.ACTION_REMOVE);
145157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            intent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
145257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, item.getSessionId());
145357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            intent.putExtra(MediaControlIntent.EXTRA_ITEM_ID, item.getItemId());
145457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            return intent;
145557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
145657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
145757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private Intent makeSeekIntent(String sid, String iid, long pos) {
145857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Intent intent = new Intent(MediaControlIntent.ACTION_SEEK);
145957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            intent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
146057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, sid);
146157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            intent.putExtra(MediaControlIntent.EXTRA_ITEM_ID, iid);
146257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            intent.putExtra(MediaControlIntent.EXTRA_ITEM_CONTENT_POSITION, pos);
146357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            return intent;
146457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
146557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
146657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private Intent makePauseIntent() {
146757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Intent intent = new Intent(MediaControlIntent.ACTION_PAUSE);
146857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            intent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
146957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (mSessionId != null) {
147057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, mSessionId);
147157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
147257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            return intent;
147357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
147457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
147557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private Intent makeResumeIntent() {
147657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Intent intent = new Intent(MediaControlIntent.ACTION_RESUME);
147757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            intent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
147857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (mSessionId != null) {
147957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, mSessionId);
148057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
148157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            return intent;
148257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
148357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
148457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private Intent makeStopIntent() {
148557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Intent intent = new Intent(MediaControlIntent.ACTION_STOP);
148657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            intent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
148757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (mSessionId != null) {
148857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, mSessionId);
148957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
149057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            return intent;
149157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
149257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
149357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private Intent makeGetStatusIntent(MediaQueueItem item) {
149457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Intent intent = new Intent(MediaControlIntent.ACTION_GET_STATUS);
149557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            intent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
149657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, item.getSessionId());
149757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            intent.putExtra(MediaControlIntent.EXTRA_ITEM_ID, item.getItemId());
149857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            return intent;
149957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang         }
150057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
150157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private Intent makeStatisticsIntent() {
150257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            Intent intent = new Intent(SampleMediaRouteProvider.ACTION_GET_STATISTICS);
150357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            intent.addCategory(SampleMediaRouteProvider.CATEGORY_SAMPLE_ROUTE);
150457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            return intent;
150557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
150657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    }
150757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
150857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    public static final class DiscoveryFragment extends MediaRouteDiscoveryFragment {
150957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private static final String TAG = "DiscoveryFragment";
151057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        private Callback mCallback;
151157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
151257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public DiscoveryFragment() {
151357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mCallback = null;
151457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
151557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
151657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public DiscoveryFragment(Callback cb) {
151757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mCallback = cb;
151857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
151957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
152057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public void setCallback(Callback cb) {
152157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            mCallback = cb;
152257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
152357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
152457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
152557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public Callback onCreateCallback() {
152657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            return mCallback;
1527ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        }
152855e47d370890d3cbdab82857090c42df734ba276Jeff Brown
152955e47d370890d3cbdab82857090c42df734ba276Jeff Brown        @Override
1530f0dd451048100915f072423730a93d17c53fd899Jeff Brown        public int onPrepareCallbackFlags() {
1531f0dd451048100915f072423730a93d17c53fd899Jeff Brown            // Add the CALLBACK_FLAG_UNFILTERED_EVENTS flag to ensure that we will
1532f0dd451048100915f072423730a93d17c53fd899Jeff Brown            // observe and log all route events including those that are for routes
1533f0dd451048100915f072423730a93d17c53fd899Jeff Brown            // that do not match our selector.  This is only for demonstration purposes
1534f0dd451048100915f072423730a93d17c53fd899Jeff Brown            // and should not be needed by most applications.
1535f0dd451048100915f072423730a93d17c53fd899Jeff Brown            return super.onPrepareCallbackFlags()
1536f0dd451048100915f072423730a93d17c53fd899Jeff Brown                    | MediaRouter.CALLBACK_FLAG_UNFILTERED_EVENTS;
153755e47d370890d3cbdab82857090c42df734ba276Jeff Brown        }
1538f0dd451048100915f072423730a93d17c53fd899Jeff Brown    }
1539ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
1540ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    private static final class MediaItem {
1541ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        public final String mName;
1542ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        public final Uri mUri;
1543ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
1544ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        public MediaItem(String name, Uri uri) {
1545ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            mName = name;
1546ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            mUri = uri;
1547ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        }
1548ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown
1549ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        @Override
1550ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        public String toString() {
1551ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown            return mName;
1552ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown        }
1553ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown    }
155455e47d370890d3cbdab82857090c42df734ba276Jeff Brown
155557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private final class LibraryAdapter extends ArrayAdapter<MediaItem> {
155657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public LibraryAdapter() {
155757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            super(SampleMediaRouterActivity.this, R.layout.media_item);
155857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
155957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
156057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
156157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public View getView(int position, View convertView, ViewGroup parent) {
156257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            final View v;
156357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (convertView == null) {
156457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                v = getLayoutInflater().inflate(R.layout.media_item, null);
156557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            } else {
156657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                v = convertView;
156757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
156857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
156957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            final MediaItem item = getItem(position);
157057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
157157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            TextView tv = (TextView)v.findViewById(R.id.item_text);
157257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            tv.setText(item.mName);
157357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
157457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            ImageButton b = (ImageButton)v.findViewById(R.id.item_action);
157557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            b.setImageResource(R.drawable.ic_menu_add);
157657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            b.setTag(item);
157757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            b.setOnClickListener(new OnClickListener() {
157857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                @Override
157957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                public void onClick(View v) {
158057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    if (item != null) {
158157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        mPlayer.enqueue(item.mUri, 0);
158257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    }
158357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                }
158457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            });
158557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
158657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            return v;
158757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
158857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    }
158957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
159057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    private final class PlaylistAdapter extends ArrayAdapter<MediaQueueItem> {
159157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public PlaylistAdapter() {
159257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            super(SampleMediaRouterActivity.this, R.layout.media_item);
159357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
159457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
159557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        @Override
159657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        public View getView(int position, View convertView, ViewGroup parent) {
159757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            final View v;
159857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            if (convertView == null) {
159957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                v = getLayoutInflater().inflate(R.layout.media_item, null);
160057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            } else {
160157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                v = convertView;
160257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            }
160357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
160457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            final MediaQueueItem item = getItem(position);
160557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
160657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            TextView tv = (TextView)v.findViewById(R.id.item_text);
160757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            tv.setText(item.toString());
160857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
160957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            ImageButton b = (ImageButton)v.findViewById(R.id.item_action);
161057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            b.setImageResource(R.drawable.ic_menu_delete);
161157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            b.setTag(item);
161257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            b.setOnClickListener(new OnClickListener() {
161357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                @Override
161457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                public void onClick(View v) {
161557456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    if (item != null) {
161657456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                        mPlayer.remove(item);
161757456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                    }
161857456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang                }
161957456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            });
162057456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
162157456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang            return v;
162257456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang        }
162357456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang    }
162457456222f52fbfc1dcfb1b99030aad6acc02ad23Chong Zhang
162555e47d370890d3cbdab82857090c42df734ba276Jeff Brown    /**
162655e47d370890d3cbdab82857090c42df734ba276Jeff Brown     * Trivial subclass of this activity used to provide another copy of the
162755e47d370890d3cbdab82857090c42df734ba276Jeff Brown     * same activity using a light theme instead of the dark theme.
162855e47d370890d3cbdab82857090c42df734ba276Jeff Brown     */
162955e47d370890d3cbdab82857090c42df734ba276Jeff Brown    public static class Light extends SampleMediaRouterActivity {
163055e47d370890d3cbdab82857090c42df734ba276Jeff Brown    }
163155e47d370890d3cbdab82857090c42df734ba276Jeff Brown
163255e47d370890d3cbdab82857090c42df734ba276Jeff Brown    /**
163355e47d370890d3cbdab82857090c42df734ba276Jeff Brown     * Trivial subclass of this activity used to provide another copy of the
163455e47d370890d3cbdab82857090c42df734ba276Jeff Brown     * same activity using a light theme with dark action bar instead of the dark theme.
163555e47d370890d3cbdab82857090c42df734ba276Jeff Brown     */
163655e47d370890d3cbdab82857090c42df734ba276Jeff Brown    public static class LightWithDarkActionBar extends SampleMediaRouterActivity {
163755e47d370890d3cbdab82857090c42df734ba276Jeff Brown    }
1638ecdd1b114d4fb36682cdabe205e08e6f68f79f63Jeff Brown}
1639