Add new sample for Presentation API.

Change-Id: Ia31deb9ca6ad9a4db1dd6f852c00fa9a94caa4c3
diff --git a/samples/ApiDemos/AndroidManifest.xml b/samples/ApiDemos/AndroidManifest.xml
index 817b23a..7326170 100644
--- a/samples/ApiDemos/AndroidManifest.xml
+++ b/samples/ApiDemos/AndroidManifest.xml
@@ -254,6 +254,14 @@
             </intent-filter>
         </activity>
 
+        <activity android:name=".app.PresentationActivity"
+                android:label="@string/activity_presentation">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.SAMPLE_CODE" />
+            </intent-filter>
+        </activity>
+
         <!-- Fragment Samples -->
 
         <activity android:name=".app.FragmentAlertDialog"
diff --git a/samples/ApiDemos/res/layout/presentation_activity.xml b/samples/ApiDemos/res/layout/presentation_activity.xml
new file mode 100644
index 0000000..62670e4
--- /dev/null
+++ b/samples/ApiDemos/res/layout/presentation_activity.xml
@@ -0,0 +1,40 @@
+<?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.
+-->
+
+<!-- Demonstrates an activity that shows content on secondary displays using
+     the android.app.Presentation class.
+     See corresponding Java code PresentationActivity.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_activity_text"/>
+
+    <!-- List that will show information about all connected displays. -->
+    <ListView android:id="@+id/display_list"
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1" />
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/presentation_content.xml b/samples/ApiDemos/res/layout/presentation_content.xml
new file mode 100644
index 0000000..7e9aaa0
--- /dev/null
+++ b/samples/ApiDemos/res/layout/presentation_content.xml
@@ -0,0 +1,37 @@
+<?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 PresentationActivity.java. -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical">
+
+    <!-- A picture for visual interest. -->
+    <ImageView android:id="@+id/image"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <!-- A caption. -->
+    <TextView android:id="@+id/text"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center_vertical|center_horizontal"
+        android:textAppearance="?android:attr/textAppearanceMedium"/>
+
+</FrameLayout>
diff --git a/samples/ApiDemos/res/values/strings.xml b/samples/ApiDemos/res/values/strings.xml
index a64de16..778beca 100644
--- a/samples/ApiDemos/res/values/strings.xml
+++ b/samples/ApiDemos/res/values/strings.xml
@@ -112,6 +112,10 @@
     <string name="redirect_getter">Enter the text that will be used by the main activity.  Press back to cancel.</string>
     <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.  Try connecting a secondary display and watch what happens.</string>
+    <string name="presentation_channel_text">You\'re watching channel %1$d on display %2$d.</string>
+
     <string name="fragment_alert_dialog">App/Fragment/Alert Dialog</string>
 
     <string name="fragment_arguments">App/Fragment/Arguments</string>
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/PresentationActivity.java b/samples/ApiDemos/src/com/example/android/apis/app/PresentationActivity.java
new file mode 100644
index 0000000..e7e043b
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/PresentationActivity.java
@@ -0,0 +1,289 @@
+/*
+ * 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;
+
+// Need the following import to get access to the app resources, since this
+// class is in a sub-package.
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.app.Presentation;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.hardware.display.DisplayManager;
+import android.os.Bundle;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.Display;
+import android.view.View;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+/**
+ * <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 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.
+ * </p>
+ */
+public class PresentationActivity extends Activity {
+    private final String TAG = "PresentationActivity";
+
+    // The content that we want to show on the presentation.
+    private static final int[] CHANNELS = new int[] {
+        R.drawable.photo1, R.drawable.photo2, R.drawable.photo3,
+        R.drawable.photo4, R.drawable.photo5, R.drawable.photo6,
+    };
+
+    private DisplayManager mDisplayManager;
+    private ListView mDisplayList;
+    private DisplayListAdapter mDisplayListAdapter;
+    private int mNextChannelNumber;
+
+    // All active presentations indexed by display id.
+    private final SparseArray<DemoPresentation> mActivePresentations =
+            new SparseArray<DemoPresentation>();
+
+    /**
+     * 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 display manager service.
+        mDisplayManager = (DisplayManager)getSystemService(Context.DISPLAY_SERVICE);
+
+        // See assets/res/any/layout/presentation_activity.xml for this
+        // view layout definition, which is being set here as
+        // the content of our screen.
+        setContentView(R.layout.presentation_activity);
+
+        mDisplayListAdapter = new DisplayListAdapter(this);
+
+        mDisplayList = (ListView)findViewById(R.id.display_list);
+        mDisplayList.setAdapter(mDisplayListAdapter);
+        mDisplayList.setOnItemClickListener(mOnItemClickListener);
+    }
+
+    @Override
+    protected void onResume() {
+        // Be sure to call the super class.
+        super.onResume();
+
+        // Update our list of displays on resume.
+        mDisplayListAdapter.updateContents();
+
+        // Register to receive events from the display manager.
+        mDisplayManager.registerDisplayListener(mDisplayListener, null);
+    }
+
+    @Override
+    protected void onPause() {
+        // Be sure to call the super class.
+        super.onPause();
+
+        // Unregister from the display manager.
+        mDisplayManager.unregisterDisplayListener(mDisplayListener);
+
+        // Dismiss all of our presentations.
+        Log.d(TAG, "Activity is being paused.  Dimissing all active presentation.");
+        for (int i = 0; i < mActivePresentations.size(); i++) {
+            Presentation presentation = mActivePresentations.valueAt(i);
+            presentation.dismiss();
+        }
+        mActivePresentations.clear();
+    }
+
+    /**
+     * Shows a {@link Presentation} on the specified display.
+     */
+    private void showPresentation(Display display) {
+        // Do nothing if there is already a presentation showing on the display.
+        if (mActivePresentations.get(display.getDisplayId()) != null) {
+            return;
+        }
+
+        Log.d(TAG, "Showing presentation on display " + display.getDisplayId() + ".");
+
+        int channelNumber = mNextChannelNumber;
+        mNextChannelNumber = (mNextChannelNumber + 1) % CHANNELS.length;
+
+        final DemoPresentation presentation = new DemoPresentation(this, display, channelNumber);
+        mActivePresentations.put(display.getDisplayId(), presentation);
+        presentation.show();
+        presentation.setOnDismissListener(mOnDismissListener);
+    }
+
+    /**
+     * Shows a {@link Presentation} on the specified display, or dismisses it if one
+     * already showing there.
+     */
+    private void showOrDismissPresentation(Display display) {
+        // Dismiss if already showing.
+        DemoPresentation presentation = mActivePresentations.get(display.getDisplayId());
+        if (presentation != null) {
+            Log.d(TAG, "Dimissing presentation on display " + display.getDisplayId() + ".");
+            presentation.dismiss();
+            return;
+        }
+
+        // Otherwise show the presentation.
+        showPresentation(display);
+    }
+
+    /**
+     * Listens for displays to be added, changed or removed.
+     * We use it to update the list and show a new {@link Presentation} when a
+     * display is connected.
+     *
+     * Note that we don't bother dismissing the {@link Presentation} when a
+     * display is removed, although we could.  The presentation API takes care
+     * of doing that automatically for us.
+     */
+    private final DisplayManager.DisplayListener mDisplayListener =
+            new DisplayManager.DisplayListener() {
+        @Override
+        public void onDisplayAdded(int displayId) {
+            Log.d(TAG, "Display " + displayId + " added.");
+            mDisplayListAdapter.updateContents();
+
+            Display display = mDisplayManager.getDisplay(displayId);
+            if (display != null) {
+                showPresentation(display);
+            }
+        }
+
+        @Override
+        public void onDisplayChanged(int displayId) {
+            Log.d(TAG, "Display " + displayId + " changed.");
+            mDisplayListAdapter.updateContents();
+        }
+
+        @Override
+        public void onDisplayRemoved(int displayId) {
+            Log.d(TAG, "Display " + displayId + " removed.");
+            mDisplayListAdapter.updateContents();
+        }
+    };
+
+    /**
+     * Listens for when presentations are dismissed.
+     */
+    private final DialogInterface.OnDismissListener mOnDismissListener =
+            new DialogInterface.OnDismissListener() {
+        @Override
+        public void onDismiss(DialogInterface dialog) {
+            DemoPresentation presentation = (DemoPresentation)dialog;
+            Display display = presentation.getDisplay();
+            Log.d(TAG, "Presentation on display " + display.getDisplayId() + " was dismissed.");
+            mActivePresentations.remove(display.getDisplayId());
+        }
+    };
+
+    /**
+     * List adapter.
+     * Shows information about all displays.
+     */
+    private final class DisplayListAdapter extends ArrayAdapter<Display> {
+        public DisplayListAdapter(Context context) {
+            super(context, android.R.layout.simple_list_item_1);
+        }
+
+        /**
+         * Update the contents of the display list adapter to show
+         * information about all current displays.
+         */
+        public void updateContents() {
+            clear();
+
+            Display[] displays = mDisplayManager.getDisplays();
+            addAll(displays);
+
+            Log.d(TAG, "There are currently " + displays.length + " displays connected.");
+            for (Display display : displays) {
+                Log.d(TAG, "  " + display);
+            }
+        }
+    }
+
+    /**
+     * Called when an item in the display list is clicked.
+     *
+     * Causes a presentation to be shown or dismissed on that display if already showing.
+     */
+    private final OnItemClickListener mOnItemClickListener = new OnItemClickListener() {
+        @Override
+        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+            Display display = (Display)parent.getItemAtPosition(position);
+            showOrDismissPresentation(display);
+        }
+    };
+
+    /**
+     * The presentation to show on the secondary display.
+     *
+     * 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.
+     */
+    private final class DemoPresentation extends Presentation {
+        // Specifies the content that we want to show in this presentation.
+        private final int mChannelNumber;
+
+        public DemoPresentation(Context context, Display display, int channelNumber) {
+            super(context, display);
+            mChannelNumber = channelNumber;
+        }
+
+        @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_content);
+
+            // Show a text message to describe what's going on.
+            TextView text = (TextView)findViewById(R.id.text);
+            text.setText(r.getString(R.string.presentation_channel_text, mChannelNumber + 1,
+                    getDisplay().getDisplayId()));
+
+            // Show a n image for visual interest.
+            ImageView image = (ImageView)findViewById(R.id.image);
+            image.setImageDrawable(r.getDrawable(CHANNELS[mChannelNumber]));
+        }
+    }
+}