Merge "Add a demo for using Presentations with the MediaRouter." into jb-mr1-dev
diff --git a/samples/ApiDemos/AndroidManifest.xml b/samples/ApiDemos/AndroidManifest.xml
index b7f6819..8db231c 100644
--- a/samples/ApiDemos/AndroidManifest.xml
+++ b/samples/ApiDemos/AndroidManifest.xml
@@ -262,6 +262,14 @@
             </intent-filter>
         </activity>
 
+        <activity android:name=".app.PresentationWithMediaRouterActivity"
+                android:label="@string/activity_presentation_with_media_router">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.SAMPLE_CODE" />
+            </intent-filter>
+        </activity>
+
         <activity android:name=".app.SecureWindowActivity"
                 android:label="@string/activity_secure_window">
             <intent-filter>
diff --git a/samples/ApiDemos/res/layout/presentation_activity.xml b/samples/ApiDemos/res/layout/presentation_activity.xml
index 62670e4..52c5022 100644
--- a/samples/ApiDemos/res/layout/presentation_activity.xml
+++ b/samples/ApiDemos/res/layout/presentation_activity.xml
@@ -32,6 +32,13 @@
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:text="@string/presentation_activity_text"/>
 
+    <!-- A checkbox to toggle between showing all displays or only presentation displays. -->
+    <CheckBox android:id="@+id/show_all_displays"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="0"
+        android:text="@string/presentation_show_all_displays" />
+
     <!-- List that will show information about all connected displays. -->
     <ListView android:id="@+id/display_list"
         android:layout_width="match_parent"
diff --git a/samples/ApiDemos/res/layout/presentation_with_media_router_activity.xml b/samples/ApiDemos/res/layout/presentation_with_media_router_activity.xml
new file mode 100644
index 0000000..005002c
--- /dev/null
+++ b/samples/ApiDemos/res/layout/presentation_with_media_router_activity.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- See corresponding Java code PresentationWithMediaRouterActivity.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical">
+
+    <!-- Message to show to use. -->
+    <TextView android:id="@+id/text"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="0"
+        android:gravity="center_vertical|center_horizontal"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:text="@string/presentation_with_media_router_activity_text"/>
+
+    <!-- Some information about what's going on. -->
+    <TextView android:id="@+id/info"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="0"
+        android:gravity="center_vertical|center_horizontal"
+        android:textAppearance="?android:attr/textAppearanceMedium"/>
+
+    <!-- Some content for visual interest in the case where no presentation is showing. -->
+    <android.opengl.GLSurfaceView android:id="@+id/surface_view"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" />
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/presentation_with_media_router_content.xml b/samples/ApiDemos/res/layout/presentation_with_media_router_content.xml
new file mode 100644
index 0000000..8eb981b
--- /dev/null
+++ b/samples/ApiDemos/res/layout/presentation_with_media_router_content.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- The content that we show on secondary displays.
+     See corresponding Java code PresentationWithMediaRouterActivity.java. -->
+
+<android.opengl.GLSurfaceView  xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/surface_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" />
diff --git a/samples/ApiDemos/res/menu/presentation_with_media_router_menu.xml b/samples/ApiDemos/res/menu/presentation_with_media_router_menu.xml
new file mode 100644
index 0000000..08ef0dc
--- /dev/null
+++ b/samples/ApiDemos/res/menu/presentation_with_media_router_menu.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 Google Inc.
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/menu_media_route"
+        android:title="@string/presentation_with_media_router_play_on"
+        android:showAsAction="always"
+        android:orderInCategory="1"
+        android:actionProviderClass="android.app.MediaRouteActionProvider"/>
+</menu>
diff --git a/samples/ApiDemos/res/values/strings.xml b/samples/ApiDemos/res/values/strings.xml
index 9d8616d..6211a0d 100644
--- a/samples/ApiDemos/res/values/strings.xml
+++ b/samples/ApiDemos/res/values/strings.xml
@@ -113,15 +113,27 @@
     <string name="apply">Apply</string>
 
     <string name="activity_presentation">App/Activity/Presentation</string>
-    <string name="presentation_activity_text">This activity demonstrates how to use the Presentation activity to show content on other Displays.\n
+    <string name="presentation_activity_text">This activity demonstrates how to use a
+                  Presentation and the DisplayManager to show content on other Displays.\n
                   Try connecting a secondary display and watch what happens.\n
                   Selecting a Display will open a Presentation on it.</string>
-    <string name="presentation_channel_text">You\'re watching channel %1$d on display %2$d.</string>
+    <string name="presentation_show_all_displays">Show all displays</string>
+    <string name="presentation_photo_text">Showing photo #%1$d on display #%2$d: %3$s.</string>
     <string name="presentation_info_text">Info</string>
-    <string name="presentation_display_id_text">Display #%1$d</string>
-    <string name="presentation_alert_info_text">Display %1$d Info</string>
+    <string name="presentation_display_id_text">Display #%1$d: %2$s</string>
+    <string name="presentation_alert_info_text">Display #%1$d Info</string>
     <string name="presentation_alert_dismiss_text">OK</string>
 
+    <string name="activity_presentation_with_media_router">App/Activity/Presentation with Media Router</string>
+    <string name="presentation_with_media_router_activity_text">This activity demonstrates how to
+                  use a Presentation and the MediaRouter to automatically
+                  show content on a secondary display when available based on the currently
+                  selected media route.\n
+                  Try connecting a secondary display and watch what happens.</string>
+    <string name="presentation_with_media_router_play_on">Play on...</string>
+    <string name="presentation_with_media_router_now_playing_locally">Now playing on main display \'%s\'.</string>
+    <string name="presentation_with_media_router_now_playing_remotely">Now playing on secondary display \'%s\'.</string>
+
     <string name="activity_secure_window">App/Activity/Secure Surfaces/Secure Window</string>
     <string name="secure_window_activity_text">This activity demonstrates how to make an activity
             use a secure surface so that its contents will only be visible on secure displays.
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/PresentationActivity.java b/samples/ApiDemos/src/com/example/android/apis/app/PresentationActivity.java
index 3e561aa..c626022 100644
--- a/samples/ApiDemos/src/com/example/android/apis/app/PresentationActivity.java
+++ b/samples/ApiDemos/src/com/example/android/apis/app/PresentationActivity.java
@@ -30,6 +30,9 @@
 import android.graphics.drawable.GradientDrawable;
 import android.hardware.display.DisplayManager;
 import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.Parcelable.Creator;
 import android.util.Log;
 import android.util.SparseArray;
 import android.view.Display;
@@ -45,6 +48,7 @@
 import android.widget.ListView;
 import android.widget.TextView;
 
+//BEGIN_INCLUDE(activity)
 /**
  * <h3>Presentation Activity</h3>
  *
@@ -52,18 +56,32 @@
  * This demonstrates how to create an activity that shows some content
  * on a secondary display using a {@link Presentation}.
  * </p><p>
- * The activity automatically creates and displays a {@link Presentation} whenever
- * a new non-default display is detected.  You can try this out by using
- * the "Simulate secondary displays" feature in Development Settings to create
- * a few simulated secondary displays.
+ * The activity uses the {@link DisplayManager} API to enumerate displays.
+ * When the user selects a display, the activity opens a {@link Presentation}
+ * on that display.  We show a different photograph in each presentation
+ * on a unique background along with a label describing the display.
+ * We also write information about displays and display-related events to
+ * the Android log which you can read using <code>adb logcat</code>.
+ * </p><p>
+ * You can try this out using an HDMI or Wifi display or by using the
+ * "Simulate secondary displays" feature in Development Settings to create a few
+ * simulated secondary displays.  Each display will appear in the list along with a
+ * checkbox to show a presentation on that display.
+ * </p><p>
+ * See also the {@link PresentationWithMediaRouterActivity} sample which
+ * uses the media router to automatically select a secondary display
+ * on which to show content based on the currently selected route.
  * </p>
  */
 public class PresentationActivity extends Activity
         implements OnCheckedChangeListener, OnClickListener {
     private final String TAG = "PresentationActivity";
 
+    // Key for storing saved instance state.
+    private static final String PRESENTATION_KEY = "presentation";
+
     // The content that we want to show on the presentation.
-    private static final int[] CHANNELS = new int[] {
+    private static final int[] PHOTOS = new int[] {
         R.drawable.frantic,
         R.drawable.photo1, R.drawable.photo2, R.drawable.photo3,
         R.drawable.photo4, R.drawable.photo5, R.drawable.photo6,
@@ -72,14 +90,16 @@
 
     private DisplayManager mDisplayManager;
     private DisplayListAdapter mDisplayListAdapter;
+    private CheckBox mShowAllDisplaysCheckbox;
     private ListView mListView;
-    private int mNextChannelNumber;
+    private int mNextImageNumber;
 
-    // Indexed by displayId. Persists across pause/resume.
-    private final SparseArray<PresentationContents> mSavedPresentationContents =
-            new SparseArray<PresentationContents>();
+    // List of presentation contents indexed by displayId.
+    // This state persists so that we can restore the old presentation
+    // contents when the activity is paused or resumed.
+    private SparseArray<PresentationContents> mSavedPresentationContents;
 
-    // Indexed by displayId. Contains all currently displayed Presentations.
+    // List of all currently visible presentations indexed by display id.
     private final SparseArray<DemoPresentation> mActivePresentations =
             new SparseArray<DemoPresentation>();
 
@@ -93,6 +113,14 @@
         // Be sure to call the super class.
         super.onCreate(savedInstanceState);
 
+        // Restore saved instance state.
+        if (savedInstanceState != null) {
+            mSavedPresentationContents =
+                    savedInstanceState.getSparseParcelableArray(PRESENTATION_KEY);
+        } else {
+            mSavedPresentationContents = new SparseArray<PresentationContents>();
+        }
+
         // Get the display manager service.
         mDisplayManager = (DisplayManager)getSystemService(Context.DISPLAY_SERVICE);
 
@@ -101,6 +129,11 @@
         // the content of our screen.
         setContentView(R.layout.presentation_activity);
 
+        // Set up checkbox to toggle between showing all displays or only presentation displays.
+        mShowAllDisplaysCheckbox = (CheckBox)findViewById(R.id.show_all_displays);
+        mShowAllDisplaysCheckbox.setOnCheckedChangeListener(this);
+
+        // Set up the list of displays.
         mDisplayListAdapter = new DisplayListAdapter(this);
         mListView = (ListView)findViewById(R.id.display_list);
         mListView.setAdapter(mDisplayListAdapter);
@@ -114,6 +147,7 @@
         // Update our list of displays on resume.
         mDisplayListAdapter.updateContents();
 
+        // Restore presentations from before the activity was paused.
         final int numDisplays = mDisplayListAdapter.getCount();
         for (int i = 0; i < numDisplays; i++) {
             final Display display = mDisplayListAdapter.getItem(i);
@@ -137,7 +171,7 @@
         // Unregister from the display manager.
         mDisplayManager.unregisterDisplayListener(mDisplayListener);
 
-        // Dismiss all of our presentations.
+        // Dismiss all of our presentations but remember their contents.
         Log.d(TAG, "Activity is being paused.  Dismissing all active presentation.");
         for (int i = 0; i < mActivePresentations.size(); i++) {
             DemoPresentation presentation = mActivePresentations.valueAt(i);
@@ -148,6 +182,13 @@
         mActivePresentations.clear();
     }
 
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        // Be sure to call the super class.
+        super.onSaveInstanceState(outState);
+        outState.putSparseParcelableArray(PRESENTATION_KEY, mSavedPresentationContents);
+    }
+
     /**
      * Shows a {@link Presentation} on the specified display.
      */
@@ -157,8 +198,8 @@
             return;
         }
 
-        Log.d(TAG, "Showing presentation channel " + contents.channel
-                + " on display " + displayId + ".");
+        Log.d(TAG, "Showing presentation photo #" + contents.photo
+                + " on display #" + displayId + ".");
 
         DemoPresentation presentation = new DemoPresentation(this, display, contents);
         presentation.show();
@@ -176,32 +217,44 @@
             return;
         }
 
-        Log.d(TAG, "Dismissing presentation on display " + displayId + ".");
+        Log.d(TAG, "Dismissing presentation on display #" + displayId + ".");
 
         presentation.dismiss();
         mActivePresentations.delete(displayId);
     }
 
-    private int getNextChannel() {
-        final int channel = mNextChannelNumber;
-        mNextChannelNumber = (mNextChannelNumber + 1) % CHANNELS.length;
-        return channel;
+    private int getNextPhoto() {
+        final int photo = mNextImageNumber;
+        mNextImageNumber = (mNextImageNumber + 1) % PHOTOS.length;
+        return photo;
     }
 
+    /**
+     * Called when the show all displays checkbox is toggled or when
+     * an item in the list of displays is checked or unchecked.
+     */
     @Override
-    /** Presentation CheckBox */
     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
-        final Display display = (Display)buttonView.getTag();
-        if (isChecked) {
-            PresentationContents contents = new PresentationContents(getNextChannel());
-            showPresentation(display, contents);
+        if (buttonView == mShowAllDisplaysCheckbox) {
+            // Show all displays checkbox was toggled.
+            mDisplayListAdapter.updateContents();
         } else {
-            hidePresentation(display);
+            // Display item checkbox was toggled.
+            final Display display = (Display)buttonView.getTag();
+            if (isChecked) {
+                PresentationContents contents = new PresentationContents(getNextPhoto());
+                showPresentation(display, contents);
+            } else {
+                hidePresentation(display);
+            }
         }
     }
 
+    /**
+     * Called when the Info button next to a display is clicked to show information
+     * about the display.
+     */
     @Override
-    /** Info Button */
     public void onClick(View v) {
         Context context = v.getContext();
         AlertDialog.Builder builder = new AlertDialog.Builder(context);
@@ -235,19 +288,19 @@
             new DisplayManager.DisplayListener() {
         @Override
         public void onDisplayAdded(int displayId) {
-            Log.d(TAG, "Display " + displayId + " added.");
+            Log.d(TAG, "Display #" + displayId + " added.");
             mDisplayListAdapter.updateContents();
         }
 
         @Override
         public void onDisplayChanged(int displayId) {
-            Log.d(TAG, "Display " + displayId + " changed.");
+            Log.d(TAG, "Display #" + displayId + " changed.");
             mDisplayListAdapter.updateContents();
         }
 
         @Override
         public void onDisplayRemoved(int displayId) {
-            Log.d(TAG, "Display " + displayId + " removed.");
+            Log.d(TAG, "Display #" + displayId + " removed.");
             mDisplayListAdapter.updateContents();
         }
     };
@@ -261,7 +314,7 @@
         public void onDismiss(DialogInterface dialog) {
             DemoPresentation presentation = (DemoPresentation)dialog;
             int displayId = presentation.getDisplay().getDisplayId();
-            Log.d(TAG, "Presentation on display " + displayId + " was dismissed.");
+            Log.d(TAG, "Presentation on display #" + displayId + " was dismissed.");
             mActivePresentations.delete(displayId);
             mDisplayListAdapter.notifyDataSetChanged();
         }
@@ -300,7 +353,7 @@
 
             TextView tv = (TextView)v.findViewById(R.id.display_id);
             tv.setText(v.getContext().getResources().getString(
-                    R.string.presentation_display_id_text, displayId));
+                    R.string.presentation_display_id_text, displayId, display.getName()));
 
             Button b = (Button)v.findViewById(R.id.info);
             b.setTag(display);
@@ -316,7 +369,8 @@
         public void updateContents() {
             clear();
 
-            Display[] displays = mDisplayManager.getDisplays();
+            String displayCategory = getDisplayCategory();
+            Display[] displays = mDisplayManager.getDisplays(displayCategory);
             addAll(displays);
 
             Log.d(TAG, "There are currently " + displays.length + " displays connected.");
@@ -324,12 +378,17 @@
                 Log.d(TAG, "  " + display);
             }
         }
+
+        private String getDisplayCategory() {
+            return mShowAllDisplaysCheckbox.isChecked() ? null :
+                DisplayManager.DISPLAY_CATEGORY_PRESENTATION;
+        }
     }
 
     /**
      * The presentation to show on the secondary display.
      *
-     * Note that this display may have different metrics from the display on which
+     * Note that the presentation display may have different metrics from the display on which
      * the main activity is showing so we must be careful to use the presentation's
      * own {@link Context} whenever we load resources.
      */
@@ -356,15 +415,16 @@
 
             final Display display = getDisplay();
             final int displayId = display.getDisplayId();
-            final int channel = mContents.channel;
+            final int photo = mContents.photo;
 
-            // Show a text message to describe what's going on.
+            // Show a caption to describe what's going on.
             TextView text = (TextView)findViewById(R.id.text);
-            text.setText(r.getString(R.string.presentation_channel_text, channel, displayId));
+            text.setText(r.getString(R.string.presentation_photo_text,
+                    photo, displayId, display.getName()));
 
             // Show a n image for visual interest.
             ImageView image = (ImageView)findViewById(R.id.image);
-            image.setImageDrawable(r.getDrawable(CHANNELS[channel]));
+            image.setImageDrawable(r.getDrawable(PHOTOS[photo]));
 
             GradientDrawable drawable = new GradientDrawable();
             drawable.setShape(GradientDrawable.RECTANGLE);
@@ -379,15 +439,49 @@
         }
     }
 
-    private final static class PresentationContents {
-        final int channel;
+    /**
+     * Information about the content we want to show in a presentation.
+     */
+    private final static class PresentationContents implements Parcelable {
+        final int photo;
         final int[] colors;
 
-        public PresentationContents(int channel) {
-            this.channel = channel;
+        public static final Creator<PresentationContents> CREATOR =
+                new Creator<PresentationContents>() {
+            @Override
+            public PresentationContents createFromParcel(Parcel in) {
+                return new PresentationContents(in);
+            }
+
+            @Override
+            public PresentationContents[] newArray(int size) {
+                return new PresentationContents[size];
+            }
+        };
+
+        public PresentationContents(int photo) {
+            this.photo = photo;
             colors = new int[] {
                     ((int) (Math.random() * Integer.MAX_VALUE)) | 0xFF000000,
                     ((int) (Math.random() * Integer.MAX_VALUE)) | 0xFF000000 };
         }
+
+        private PresentationContents(Parcel in) {
+            photo = in.readInt();
+            colors = new int[] { in.readInt(), in.readInt() };
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeInt(photo);
+            dest.writeInt(colors[0]);
+            dest.writeInt(colors[1]);
+        }
     }
 }
+//END_INCLUDE(activity)
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/PresentationWithMediaRouterActivity.java b/samples/ApiDemos/src/com/example/android/apis/app/PresentationWithMediaRouterActivity.java
new file mode 100644
index 0000000..5ba476e
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/PresentationWithMediaRouterActivity.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.apis.app;
+
+import com.example.android.apis.R;
+import com.example.android.apis.graphics.CubeRenderer;
+
+import android.app.Activity;
+import android.app.MediaRouteActionProvider;
+import android.app.Presentation;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.media.MediaRouter;
+import android.media.MediaRouter.RouteInfo;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Display;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.TextView;
+
+//BEGIN_INCLUDE(activity)
+/**
+ * <h3>Presentation Activity</h3>
+ *
+ * <p>
+ * This demonstrates how to create an activity that shows some content
+ * on a secondary display using a {@link Presentation}.
+ * </p><p>
+ * The activity uses the {@link MediaRouter} API to automatically detect when
+ * a presentation display is available and to allow the user to control the
+ * media routes using a menu item.  When a presentation display is available,
+ * we stop showing content in the main activity and instead open up a
+ * {@link Presentation} on the preferred presentation display.  When a presentation
+ * display is removed, we revert to showing content in the main activity.
+ * We also write information about displays and display-related events to
+ * the Android log which you can read using <code>adb logcat</code>.
+ * </p><p>
+ * You can try this out using an HDMI or Wifi display or by using the
+ * "Simulate secondary displays" feature in Development Settings to create a few
+ * simulated secondary displays.  Each display will appear in the list along with a
+ * checkbox to show a presentation on that display.
+ * </p><p>
+ * See also the {@link PresentationActivity} sample which
+ * uses the low-level display manager to enumerate displays and to show multiple
+ * simultaneous presentations on different displays.
+ * </p>
+ */
+public class PresentationWithMediaRouterActivity extends Activity {
+    private final String TAG = "PresentationWithMediaRouterActivity";
+
+    private MediaRouter mMediaRouter;
+    private DemoPresentation mPresentation;
+    private GLSurfaceView mSurfaceView;
+    private TextView mInfoTextView;
+    private boolean mPaused;
+
+    /**
+     * Initialization of the Activity after it is first created.  Must at least
+     * call {@link android.app.Activity#setContentView setContentView()} to
+     * describe what is to be displayed in the screen.
+     */
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        // Be sure to call the super class.
+        super.onCreate(savedInstanceState);
+
+        // Get the media router service.
+        mMediaRouter = (MediaRouter)getSystemService(Context.MEDIA_ROUTER_SERVICE);
+
+        // See assets/res/any/layout/presentation_with_media_router_activity.xml for this
+        // view layout definition, which is being set here as
+        // the content of our screen.
+        setContentView(R.layout.presentation_with_media_router_activity);
+
+        // Set up the surface view for visual interest.
+        mSurfaceView = (GLSurfaceView)findViewById(R.id.surface_view);
+        mSurfaceView.setRenderer(new CubeRenderer(false));
+
+        // Get a text view where we will show information about what's happening.
+        mInfoTextView = (TextView)findViewById(R.id.info);
+    }
+
+    @Override
+    protected void onResume() {
+        // Be sure to call the super class.
+        super.onResume();
+
+        // Listen for changes to media routes.
+        mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_LIVE_VIDEO, mMediaRouterCallback);
+
+        // Update the presentation based on the currently selected route.
+        mPaused = false;
+        updatePresentation();
+    }
+
+    @Override
+    protected void onPause() {
+        // Be sure to call the super class.
+        super.onPause();
+
+        // Stop listening for changes to media routes.
+        mMediaRouter.removeCallback(mMediaRouterCallback);
+
+        // Pause rendering.
+        mPaused = true;
+        updateContents();
+    }
+
+    @Override
+    protected void onStop() {
+        // Be sure to call the super class.
+        super.onStop();
+
+        // Dismiss the presentation when the activity is not visible.
+        if (mPresentation != null) {
+            Log.i(TAG, "Dismissing presentation because the activity is no longer visible.");
+            mPresentation.dismiss();
+            mPresentation = null;
+        }
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        // Be sure to call the super class.
+        super.onCreateOptionsMenu(menu);
+
+        // Inflate the menu and configure the media router action provider.
+        getMenuInflater().inflate(R.menu.presentation_with_media_router_menu, menu);
+
+        MenuItem mediaRouteMenuItem = menu.findItem(R.id.menu_media_route);
+        MediaRouteActionProvider mediaRouteActionProvider =
+                (MediaRouteActionProvider)mediaRouteMenuItem.getActionProvider();
+        mediaRouteActionProvider.setRouteTypes(MediaRouter.ROUTE_TYPE_LIVE_VIDEO);
+
+        // Return true to show the menu.
+        return true;
+    }
+
+    private void updatePresentation() {
+        // Get the current route and its presentation display.
+        MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute(
+                MediaRouter.ROUTE_TYPE_LIVE_VIDEO);
+        Display presentationDisplay = route != null ? route.getPresentationDisplay() : null;
+
+        // Dismiss the current presentation if the display has changed.
+        if (mPresentation != null && mPresentation.getDisplay() != presentationDisplay) {
+            Log.i(TAG, "Dismissing presentation because the current route no longer "
+                    + "has a presentation display.");
+            mPresentation.dismiss();
+            mPresentation = null;
+        }
+
+        // Show a new presentation if needed.
+        if (mPresentation == null && presentationDisplay != null) {
+            Log.i(TAG, "Showing presentation on display: " + presentationDisplay);
+            mPresentation = new DemoPresentation(this, presentationDisplay);
+            mPresentation.setOnDismissListener(mOnDismissListener);
+            try {
+                mPresentation.show();
+            } catch (WindowManager.InvalidDisplayException ex) {
+                Log.w(TAG, "Couldn't show presentation!  Display was removed in "
+                        + "the meantime.", ex);
+                mPresentation = null;
+            }
+        }
+
+        // Update the contents playing in this activity.
+        updateContents();
+    }
+
+    private void updateContents() {
+        // Show either the content in the main activity or the content in the presentation
+        // along with some descriptive text about what is happening.
+        if (mPresentation != null) {
+            mInfoTextView.setText(getResources().getString(
+                    R.string.presentation_with_media_router_now_playing_remotely,
+                    mPresentation.getDisplay().getName()));
+            mSurfaceView.setVisibility(View.INVISIBLE);
+            mSurfaceView.onPause();
+            if (mPaused) {
+                mPresentation.getSurfaceView().onPause();
+            } else {
+                mPresentation.getSurfaceView().onResume();
+            }
+        } else {
+            mInfoTextView.setText(getResources().getString(
+                    R.string.presentation_with_media_router_now_playing_locally,
+                    getWindowManager().getDefaultDisplay().getName()));
+            mSurfaceView.setVisibility(View.VISIBLE);
+            if (mPaused) {
+                mSurfaceView.onPause();
+            } else {
+                mSurfaceView.onResume();
+            }
+        }
+    }
+
+    private final MediaRouter.SimpleCallback mMediaRouterCallback =
+            new MediaRouter.SimpleCallback() {
+        @Override
+        public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
+            Log.d(TAG, "onRouteSelected: type=" + type + ", info=" + info);
+            updatePresentation();
+        }
+
+        @Override
+        public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
+            Log.d(TAG, "onRouteUnselected: type=" + type + ", info=" + info);
+            updatePresentation();
+        }
+
+        @Override
+        public void onRoutePresentationDisplayChanged(MediaRouter router, RouteInfo info) {
+            Log.d(TAG, "onRoutePresentationDisplayChanged: info=" + info);
+            updatePresentation();
+        }
+    };
+
+    /**
+     * Listens for when presentations are dismissed.
+     */
+    private final DialogInterface.OnDismissListener mOnDismissListener =
+            new DialogInterface.OnDismissListener() {
+        @Override
+        public void onDismiss(DialogInterface dialog) {
+            if (dialog == mPresentation) {
+                Log.i(TAG, "Presentation was dismissed.");
+                mPresentation = null;
+                updateContents();
+            }
+        }
+    };
+
+    /**
+     * The presentation to show on the secondary display.
+     * <p>
+     * Note that this display may have different metrics from the display on which
+     * the main activity is showing so we must be careful to use the presentation's
+     * own {@link Context} whenever we load resources.
+     * </p>
+     */
+    private final static class DemoPresentation extends Presentation {
+        private GLSurfaceView mSurfaceView;
+
+        public DemoPresentation(Context context, Display display) {
+            super(context, display);
+        }
+
+        @Override
+        protected void onCreate(Bundle savedInstanceState) {
+            // Be sure to call the super class.
+            super.onCreate(savedInstanceState);
+
+            // Get the resources for the context of the presentation.
+            // Notice that we are getting the resources from the context of the presentation.
+            Resources r = getContext().getResources();
+
+            // Inflate the layout.
+            setContentView(R.layout.presentation_with_media_router_content);
+
+            // Set up the surface view for visual interest.
+            mSurfaceView = (GLSurfaceView)findViewById(R.id.surface_view);
+            mSurfaceView.setRenderer(new CubeRenderer(false));
+        }
+
+        public GLSurfaceView getSurfaceView() {
+            return mSurfaceView;
+        }
+    }
+}
+//END_INCLUDE(activity)
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/SecureSurfaceViewActivity.java b/samples/ApiDemos/src/com/example/android/apis/app/SecureSurfaceViewActivity.java
index 2c3abed..978c70c 100644
--- a/samples/ApiDemos/src/com/example/android/apis/app/SecureSurfaceViewActivity.java
+++ b/samples/ApiDemos/src/com/example/android/apis/app/SecureSurfaceViewActivity.java
@@ -51,6 +51,8 @@
  * </p>
  */
 public class SecureSurfaceViewActivity extends Activity {
+    private GLSurfaceView mSurfaceView;
+
     /**
      * Initialization of the Activity after it is first created.  Must at least
      * call {@link android.app.Activity#setContentView setContentView()} to
@@ -69,13 +71,31 @@
         // Set up the surface view.
         // We use a GLSurfaceView in this demonstration but ordinary
         // SurfaceViews also support the same secure surface functionality.
-        GLSurfaceView surfaceView = (GLSurfaceView)findViewById(R.id.surface_view);
-        surfaceView.setRenderer(new CubeRenderer(false));
+        mSurfaceView = (GLSurfaceView)findViewById(R.id.surface_view);
+        mSurfaceView.setRenderer(new CubeRenderer(false));
 
         // Make the surface view secure.  This must be done at the time the surface view
         // is created before the surface view's containing window is attached to
         // the window manager which happens after onCreate returns.
         // It cannot be changed later.
-        surfaceView.setSecure(true);
+        mSurfaceView.setSecure(true);
+    }
+
+    @Override
+    protected void onResume() {
+        // Be sure to call the super class.
+        super.onResume();
+
+        // Resume rendering.
+        mSurfaceView.onResume();
+    }
+
+    @Override
+    protected void onPause() {
+        // Be sure to call the super class.
+        super.onPause();
+
+        // Pause rendering.
+        mSurfaceView.onPause();
     }
 }