Expand Presentation demo to test 4K mode switches.

Bug: 18241736
Change-Id: I5bedb656696bc3dfc756df35dd326ff3524152c1
diff --git a/samples/ApiDemos/res/layout/presentation_list_item.xml b/samples/ApiDemos/res/layout/presentation_list_item.xml
index d28b5d9..7c4de91 100644
--- a/samples/ApiDemos/res/layout/presentation_list_item.xml
+++ b/samples/ApiDemos/res/layout/presentation_list_item.xml
@@ -17,32 +17,40 @@
 <!-- The content that we show on secondary displays.
      See corresponding Java code PresentationActivity.java. -->
 
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:orientation="horizontal">
+        android:orientation="vertical">
+    <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="horizontal">
 
-    <CheckBox
-        android:id="@+id/checkbox_presentation"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_alignParentLeft="true"
-        android:layout_centerVertical="true"
-        android:layout_marginRight="16dip"/>
+        <CheckBox
+            android:id="@+id/checkbox_presentation"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentLeft="true"
+            android:layout_centerVertical="true"
+            android:layout_marginRight="16dip"/>
 
-    <TextView android:id="@+id/display_id"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_toRightOf="@id/checkbox_presentation"
-        android:layout_centerVertical="true"
-        android:textAppearance="?android:attr/textAppearanceLarge"/>
+        <TextView android:id="@+id/display_id"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_toRightOf="@id/checkbox_presentation"
+            android:layout_centerVertical="true"
+            android:textAppearance="?android:attr/textAppearanceLarge"/>
 
-    <Button android:id="@+id/info"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_alignParentRight="true"
-        android:layout_centerVertical="true"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:text="@string/presentation_info_text"/>
+        <Button android:id="@+id/info"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentRight="true"
+            android:layout_centerVertical="true"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:text="@string/presentation_info_text"/>
+    </RelativeLayout>
 
-</RelativeLayout>
+    <Spinner android:id="@+id/modes"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+</LinearLayout>
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 c626022..48ffc44 100644
--- a/samples/ApiDemos/src/com/example/android/apis/app/PresentationActivity.java
+++ b/samples/ApiDemos/src/com/example/android/apis/app/PresentationActivity.java
@@ -39,13 +39,17 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
+import android.view.WindowManager;
 import android.widget.CheckBox;
 import android.widget.CompoundButton;
 import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
 import android.widget.ArrayAdapter;
 import android.widget.Button;
 import android.widget.ImageView;
 import android.widget.ListView;
+import android.widget.Spinner;
 import android.widget.TextView;
 
 //BEGIN_INCLUDE(activity)
@@ -74,7 +78,7 @@
  * </p>
  */
 public class PresentationActivity extends Activity
-        implements OnCheckedChangeListener, OnClickListener {
+        implements OnCheckedChangeListener, OnClickListener, OnItemSelectedListener {
     private final String TAG = "PresentationActivity";
 
     // Key for storing saved instance state.
@@ -97,7 +101,7 @@
     // 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;
+    private SparseArray<DemoPresentationContents> mSavedPresentationContents;
 
     // List of all currently visible presentations indexed by display id.
     private final SparseArray<DemoPresentation> mActivePresentations =
@@ -118,7 +122,7 @@
             mSavedPresentationContents =
                     savedInstanceState.getSparseParcelableArray(PRESENTATION_KEY);
         } else {
-            mSavedPresentationContents = new SparseArray<PresentationContents>();
+            mSavedPresentationContents = new SparseArray<DemoPresentationContents>();
         }
 
         // Get the display manager service.
@@ -151,7 +155,7 @@
         final int numDisplays = mDisplayListAdapter.getCount();
         for (int i = 0; i < numDisplays; i++) {
             final Display display = mDisplayListAdapter.getItem(i);
-            final PresentationContents contents =
+            final DemoPresentationContents contents =
                     mSavedPresentationContents.get(display.getDisplayId());
             if (contents != null) {
                 showPresentation(display, contents);
@@ -192,7 +196,7 @@
     /**
      * Shows a {@link Presentation} on the specified display.
      */
-    private void showPresentation(Display display, PresentationContents contents) {
+    private void showPresentation(Display display, DemoPresentationContents contents) {
         final int displayId = display.getDisplayId();
         if (mActivePresentations.get(displayId) != null) {
             return;
@@ -223,6 +227,20 @@
         mActivePresentations.delete(displayId);
     }
 
+    /**
+     * Sets the display mode of the {@link Presentation} on the specified display
+     * if it is already shown.
+     */
+    private void setPresentationDisplayMode(Display display, int displayModeId) {
+        final int displayId = display.getDisplayId();
+        DemoPresentation presentation = mActivePresentations.get(displayId);
+        if (presentation == null) {
+            return;
+        }
+
+        presentation.setPreferredDisplayMode(displayModeId);
+    }
+
     private int getNextPhoto() {
         final int photo = mNextImageNumber;
         mNextImageNumber = (mNextImageNumber + 1) % PHOTOS.length;
@@ -242,11 +260,12 @@
             // Display item checkbox was toggled.
             final Display display = (Display)buttonView.getTag();
             if (isChecked) {
-                PresentationContents contents = new PresentationContents(getNextPhoto());
+                DemoPresentationContents contents = new DemoPresentationContents(getNextPhoto());
                 showPresentation(display, contents);
             } else {
                 hidePresentation(display);
             }
+            mDisplayListAdapter.updateContents();
         }
     }
 
@@ -276,6 +295,26 @@
     }
 
     /**
+     * Called when a display mode has been selected.
+     */
+    @Override
+    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+        final Display display = (Display)parent.getTag();
+        final Display.Mode[] modes = display.getSupportedModes();
+        setPresentationDisplayMode(display, position >= 1 && position <= modes.length ?
+                modes[position - 1].getModeId() : 0);
+    }
+
+    /**
+     * Called when a display mode has been unselected.
+     */
+    @Override
+    public void onNothingSelected(AdapterView<?> parent) {
+        final Display display = (Display)parent.getTag();
+        setPresentationDisplayMode(display, 0);
+    }
+
+    /**
      * 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.
@@ -345,11 +384,17 @@
             final Display display = getItem(position);
             final int displayId = display.getDisplayId();
 
+            DemoPresentation presentation = mActivePresentations.get(displayId);
+            DemoPresentationContents contents = presentation != null ?
+                    presentation.mContents : null;
+            if (contents == null) {
+                contents = mSavedPresentationContents.get(displayId);
+            }
+
             CheckBox cb = (CheckBox)v.findViewById(R.id.checkbox_presentation);
             cb.setTag(display);
             cb.setOnCheckedChangeListener(PresentationActivity.this);
-            cb.setChecked(mActivePresentations.indexOfKey(displayId) >= 0
-                    || mSavedPresentationContents.indexOfKey(displayId) >= 0);
+            cb.setChecked(contents != null);
 
             TextView tv = (TextView)v.findViewById(R.id.display_id);
             tv.setText(v.getContext().getResources().getString(
@@ -359,6 +404,32 @@
             b.setTag(display);
             b.setOnClickListener(PresentationActivity.this);
 
+            Spinner s = (Spinner)v.findViewById(R.id.modes);
+            Display.Mode[] modes = display.getSupportedModes();
+            if (contents == null || modes.length == 1) {
+                s.setVisibility(View.GONE);
+                s.setAdapter(null);
+            } else {
+                ArrayAdapter<String> modeAdapter = new ArrayAdapter<String>(mContext,
+                        android.R.layout.simple_list_item_1);
+                s.setVisibility(View.VISIBLE);
+                s.setAdapter(modeAdapter);
+                s.setTag(display);
+                s.setOnItemSelectedListener(PresentationActivity.this);
+
+                modeAdapter.add("<default mode>");
+
+                for (Display.Mode mode : modes) {
+                    modeAdapter.add(String.format("Mode %d: %dx%d/%.1ffps",
+                            mode.getModeId(),
+                            mode.getPhysicalWidth(), mode.getPhysicalHeight(),
+                            mode.getRefreshRate()));
+                    if (contents.displayModeId == mode.getModeId()) {
+                        s.setSelection(modeAdapter.getCount() - 1);
+                    }
+                }
+            }
+
             return v;
         }
 
@@ -394,13 +465,25 @@
      */
     private final class DemoPresentation extends Presentation {
 
-        final PresentationContents mContents;
+        final DemoPresentationContents mContents;
 
-        public DemoPresentation(Context context, Display display, PresentationContents contents) {
+        public DemoPresentation(Context context, Display display,
+                DemoPresentationContents contents) {
             super(context, display);
             mContents = contents;
         }
 
+        /**
+         * Sets the preferred display mode id for the presentation.
+         */
+        public void setPreferredDisplayMode(int modeId) {
+            mContents.displayModeId = modeId;
+
+            WindowManager.LayoutParams params = getWindow().getAttributes();
+            params.preferredDisplayModeId = modeId;
+            getWindow().setAttributes(params);
+        }
+
         @Override
         protected void onCreate(Bundle savedInstanceState) {
             // Be sure to call the super class.
@@ -440,35 +523,37 @@
     }
 
     /**
-     * Information about the content we want to show in a presentation.
+     * Information about the content we want to show in the presentation.
      */
-    private final static class PresentationContents implements Parcelable {
+    private final static class DemoPresentationContents implements Parcelable {
         final int photo;
         final int[] colors;
+        int displayModeId;
 
-        public static final Creator<PresentationContents> CREATOR =
-                new Creator<PresentationContents>() {
+        public static final Creator<DemoPresentationContents> CREATOR =
+                new Creator<DemoPresentationContents>() {
             @Override
-            public PresentationContents createFromParcel(Parcel in) {
-                return new PresentationContents(in);
+            public DemoPresentationContents createFromParcel(Parcel in) {
+                return new DemoPresentationContents(in);
             }
 
             @Override
-            public PresentationContents[] newArray(int size) {
-                return new PresentationContents[size];
+            public DemoPresentationContents[] newArray(int size) {
+                return new DemoPresentationContents[size];
             }
         };
 
-        public PresentationContents(int photo) {
+        public DemoPresentationContents(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) {
+        private DemoPresentationContents(Parcel in) {
             photo = in.readInt();
             colors = new int[] { in.readInt(), in.readInt() };
+            displayModeId = in.readInt();
         }
 
         @Override
@@ -481,6 +566,7 @@
             dest.writeInt(photo);
             dest.writeInt(colors[0]);
             dest.writeInt(colors[1]);
+            dest.writeInt(displayModeId);
         }
     }
 }