1a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown/* 2a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * Copyright (C) 2012 The Android Open Source Project 3a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * 4a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 5a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * you may not use this file except in compliance with the License. 6a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * You may obtain a copy of the License at 7a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * 8a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 9a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * 10a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * Unless required by applicable law or agreed to in writing, software 11a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 12a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * See the License for the specific language governing permissions and 14a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * limitations under the License. 15a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown */ 16a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 17a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brownpackage android.app; 18a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 19a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brownimport android.content.Context; 20a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brownimport android.content.res.Resources; 21a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brownimport android.hardware.display.DisplayManager; 22a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brownimport android.hardware.display.DisplayManager.DisplayListener; 23a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brownimport android.view.ContextThemeWrapper; 24a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brownimport android.view.Display; 25a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brownimport android.view.Gravity; 26a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brownimport android.view.WindowManagerImpl; 27a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brownimport android.os.Handler; 28a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brownimport android.os.Message; 29a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brownimport android.util.DisplayMetrics; 30a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brownimport android.util.Log; 31a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brownimport android.util.TypedValue; 32a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 33a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown/** 34a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * Base class for presentations. 35a95a3b494fd88f83c9f5d32e001452575ba235ecJeff Brown * <p> 36a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * A presentation is a special kind of dialog whose purpose is to present 37a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * content on a secondary display. A {@link Presentation} is associated with 38a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * the target {@link Display} at creation time and configures its context and 39a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * resource configuration according to the display's metrics. 40a95a3b494fd88f83c9f5d32e001452575ba235ecJeff Brown * </p><p> 41a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * Notably, the {@link Context} of a presentation is different from the context 42a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * of its containing {@link Activity}. It is important to inflate the layout 43a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * of a presentation and load other resources using the presentation's own context 44a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * to ensure that assets of the correct size and density for the target display 45a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * are loaded. 46a95a3b494fd88f83c9f5d32e001452575ba235ecJeff Brown * </p><p> 47a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * A presentation is automatically canceled (see {@link Dialog#cancel()}) when 48a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * the display to which it is attached is removed. An activity should take 49a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * care of pausing and resuming whatever content is playing within the presentation 50a95a3b494fd88f83c9f5d32e001452575ba235ecJeff Brown * whenever the activity itself is paused or resumed. 51a95a3b494fd88f83c9f5d32e001452575ba235ecJeff Brown * </p> 52a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * 5392130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * <h3>Choosing a presentation display</h3> 5492130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * <p> 5592130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * Before showing a {@link Presentation} it's important to choose the {@link Display} 5692130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * on which it will appear. Choosing a presentation display is sometimes difficult 5792130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * because there may be multiple displays attached. Rather than trying to guess 5892130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * which display is best, an application should let the system choose a suitable 5992130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * presentation display. 6092130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * </p><p> 6192130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * There are two main ways to choose a {@link Display}. 6292130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * </p> 6392130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * 6492130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * <h4>Using the media router to choose a presentation display</h4> 6592130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * <p> 6692130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * The easiest way to choose a presentation display is to use the 6792130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * {@link android.media.MediaRouter MediaRouter} API. The media router service keeps 6892130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * track of which audio and video routes are available on the system. 6992130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * The media router sends notifications whenever routes are selected or unselected 7092130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * or when the preferred presentation display of a route changes. 7192130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * So an application can simply watch for these notifications and show or dismiss 7292130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * a presentation on the preferred presentation display automatically. 7392130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * </p><p> 7492130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * The preferred presentation display is the display that the media router recommends 7592130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * that the application should use if it wants to show content on the secondary display. 7692130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * Sometimes there may not be a preferred presentation display in which 7792130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * case the application should show its content locally without using a presentation. 7892130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * </p><p> 7992130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * Here's how to use the media router to create and show a presentation on the preferred 8092130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * presentation display using {@link android.media.MediaRouter.RouteInfo#getPresentationDisplay()}. 8192130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * </p> 829cc531cc26d928c7b53105def0d80647fba1acd7Scott Main * <pre> 8392130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * MediaRouter mediaRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE); 8492130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * MediaRouter.RouteInfo route = mediaRouter.getSelectedRoute(); 859cc531cc26d928c7b53105def0d80647fba1acd7Scott Main * if (route != null) { 8692130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * Display presentationDisplay = route.getPresentationDisplay(); 879cc531cc26d928c7b53105def0d80647fba1acd7Scott Main * if (presentationDisplay != null) { 8892130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * Presentation presentation = new MyPresentation(context, presentationDisplay); 8992130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * presentation.show(); 909cc531cc26d928c7b53105def0d80647fba1acd7Scott Main * } 919cc531cc26d928c7b53105def0d80647fba1acd7Scott Main * }</pre> 9292130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * <p> 9392130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * The following sample code from <code>ApiDemos</code> demonstrates how to use the media 9492130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * router to automatically switch between showing content in the main activity and showing 9592130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * the content in a presentation when a presentation display is available. 9692130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * </p> 9792130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/PresentationWithMediaRouterActivity.java 9892130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * activity} 9992130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * 10092130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * <h4>Using the display manager to choose a presentation display</h4> 10192130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * <p> 10292130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * Another way to choose a presentation display is to use the {@link DisplayManager} API 10392130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * directly. The display manager service provides functions to enumerate and describe all 10492130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * displays that are attached to the system including displays that may be used 10592130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * for presentations. 10692130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * </p><p> 10792130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * The display manager keeps track of all displays in the system. However, not all 10892130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * displays are appropriate for showing presentations. For example, if an activity 10992130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * attempted to show a presentation on the main display it might obscure its own content 11092130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * (it's like opening a dialog on top of your activity). 11192130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * </p><p> 11292130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * Here's how to identify suitable displays for showing presentations using 11392130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * {@link DisplayManager#getDisplays(String)} and the 11492130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * {@link DisplayManager#DISPLAY_CATEGORY_PRESENTATION} category. 11592130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * </p> 1169cc531cc26d928c7b53105def0d80647fba1acd7Scott Main * <pre> 11792130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * DisplayManager displayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE); 11892130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * Display[] presentationDisplays = displayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION); 1199cc531cc26d928c7b53105def0d80647fba1acd7Scott Main * if (presentationDisplays.length > 0) { 12092130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * // If there is more than one suitable presentation display, then we could consider 12192130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * // giving the user a choice. For this example, we simply choose the first display 12292130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * // which is the one the system recommends as the preferred presentation display. 12392130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * Display display = presentationDisplays[0]; 12492130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * Presentation presentation = new MyPresentation(context, presentationDisplay); 12592130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * presentation.show(); 1269cc531cc26d928c7b53105def0d80647fba1acd7Scott Main * }</pre> 12792130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * <p> 12892130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * The following sample code from <code>ApiDemos</code> demonstrates how to use the display 12992130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * manager to enumerate displays and show content on multiple presentation displays 13092130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * simultaneously. 13192130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * </p> 13292130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/PresentationActivity.java 13392130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * activity} 13492130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * 13592130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * @see android.media.MediaRouter#ROUTE_TYPE_LIVE_VIDEO for information on about live 13692130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * video routes and how to obtain the preferred presentation display for the 13792130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown * current media route. 138a95a3b494fd88f83c9f5d32e001452575ba235ecJeff Brown * @see DisplayManager for information on how to enumerate displays and receive 139a95a3b494fd88f83c9f5d32e001452575ba235ecJeff Brown * notifications when displays are added or removed. 140a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown */ 141a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brownpublic class Presentation extends Dialog { 142a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown private static final String TAG = "Presentation"; 143a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 144a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown private static final int MSG_CANCEL = 1; 145a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 146a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown private final Display mDisplay; 147a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown private final DisplayManager mDisplayManager; 148a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 149a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown /** 150a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * Creates a new presentation that is attached to the specified display 151a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * using the default theme. 152a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * 153a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * @param outerContext The context of the application that is showing the presentation. 154a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * The presentation will create its own context (see {@link #getContext()}) based 155a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * on this context and information about the associated display. 156a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * @param display The display to which the presentation should be attached. 157a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown */ 158a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown public Presentation(Context outerContext, Display display) { 159a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown this(outerContext, display, 0); 160a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 161a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 162a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown /** 163a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * Creates a new presentation that is attached to the specified display 164a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * using the optionally specified theme. 165a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * 166a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * @param outerContext The context of the application that is showing the presentation. 167a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * The presentation will create its own context (see {@link #getContext()}) based 168a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * on this context and information about the associated display. 169a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * @param display The display to which the presentation should be attached. 170a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * @param theme A style resource describing the theme to use for the window. 171a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * See <a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes"> 172a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * Style and Theme Resources</a> for more information about defining and using 173a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * styles. This theme is applied on top of the current theme in 174a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * <var>outerContext</var>. If 0, the default presentation theme will be used. 175a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown */ 176a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown public Presentation(Context outerContext, Display display, int theme) { 177a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown super(createPresentationContext(outerContext, display, theme), theme, false); 178a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 179a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown mDisplay = display; 180a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown mDisplayManager = (DisplayManager)getContext().getSystemService(Context.DISPLAY_SERVICE); 181a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 182a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown getWindow().setGravity(Gravity.FILL); 183a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown setCanceledOnTouchOutside(false); 184a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 185a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 186a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown /** 187a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * Gets the {@link Display} that this presentation appears on. 188a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * 189a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * @return The display. 190a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown */ 191a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown public Display getDisplay() { 192a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown return mDisplay; 193a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 194a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 195a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown /** 196a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * Gets the {@link Resources} that should be used to inflate the layout of this presentation. 197a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * This resources object has been configured according to the metrics of the 198a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * display that the presentation appears on. 199a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * 200a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * @return The presentation resources object. 201a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown */ 202a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown public Resources getResources() { 203a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown return getContext().getResources(); 204a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 205a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 206a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown @Override 207a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown protected void onStart() { 208a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown super.onStart(); 20992130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown mDisplayManager.registerDisplayListener(mDisplayListener, mHandler); 210a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 211a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown // Since we were not watching for display changes until just now, there is a 212a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown // chance that the display metrics have changed. If so, we will need to 213a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown // dismiss the presentation immediately. This case is expected 214a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown // to be rare but surprising, so we'll write a log message about it. 215a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown if (!isConfigurationStillValid()) { 216a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown Log.i(TAG, "Presentation is being immediately dismissed because the " 217a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown + "display metrics have changed since it was created."); 218a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown mHandler.sendEmptyMessage(MSG_CANCEL); 219a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 220a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 221a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 222a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown @Override 223a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown protected void onStop() { 224a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown mDisplayManager.unregisterDisplayListener(mDisplayListener); 225a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown super.onStop(); 226a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 227a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 228a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown /** 2296018aeec27914f138f36b00d8f00136a87562fd3Craig Mautner * Inherited from {@link Dialog#show}. Will throw 2306018aeec27914f138f36b00d8f00136a87562fd3Craig Mautner * {@link android.view.WindowManager.InvalidDisplayException} if the specified secondary 2316018aeec27914f138f36b00d8f00136a87562fd3Craig Mautner * {@link Display} can't be found. 2326018aeec27914f138f36b00d8f00136a87562fd3Craig Mautner */ 2336018aeec27914f138f36b00d8f00136a87562fd3Craig Mautner @Override 2346018aeec27914f138f36b00d8f00136a87562fd3Craig Mautner public void show() { 2356018aeec27914f138f36b00d8f00136a87562fd3Craig Mautner super.show(); 2366018aeec27914f138f36b00d8f00136a87562fd3Craig Mautner } 2376018aeec27914f138f36b00d8f00136a87562fd3Craig Mautner 2386018aeec27914f138f36b00d8f00136a87562fd3Craig Mautner /** 239a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * Called by the system when the {@link Display} to which the presentation 240a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * is attached has been removed. 241a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * 242a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * The system automatically calls {@link #cancel} to dismiss the presentation 243a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * after sending this event. 244a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * 245a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * @see #getDisplay 246a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown */ 247a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown public void onDisplayRemoved() { 248a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 249a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 250a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown /** 251a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * Called by the system when the properties of the {@link Display} to which 252a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * the presentation is attached have changed. 253a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * 254a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * If the display metrics have changed (for example, if the display has been 255a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * resized or rotated), then the system automatically calls 256a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * {@link #cancel} to dismiss the presentation. 257a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * 258a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown * @see #getDisplay 259a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown */ 260a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown public void onDisplayChanged() { 261a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 262a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 263a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown private void handleDisplayRemoved() { 264a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown onDisplayRemoved(); 265a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown cancel(); 266a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 267a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 268a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown private void handleDisplayChanged() { 269a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown onDisplayChanged(); 270a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 271a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown // We currently do not support configuration changes for presentations 272a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown // (although we could add that feature with a bit more work). 273a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown // If the display metrics have changed in any way then the current configuration 274a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown // is invalid and the application must recreate the presentation to get 275a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown // a new context. 276a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown if (!isConfigurationStillValid()) { 277a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown cancel(); 278a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 279a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 280a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 281a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown private boolean isConfigurationStillValid() { 282a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown DisplayMetrics dm = new DisplayMetrics(); 283a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown mDisplay.getMetrics(dm); 2847ac8bbddfcaa2539f6311be54323d22f2dcc4a35Dianne Hackborn return dm.equalsPhysical(getResources().getDisplayMetrics()); 285a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 286a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 287a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown private static Context createPresentationContext( 288a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown Context outerContext, Display display, int theme) { 289a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown if (outerContext == null) { 290a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown throw new IllegalArgumentException("outerContext must not be null"); 291a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 292a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown if (display == null) { 293a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown throw new IllegalArgumentException("display must not be null"); 294a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 295a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 296a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown Context displayContext = outerContext.createDisplayContext(display); 297a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown if (theme == 0) { 298a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown TypedValue outValue = new TypedValue(); 299a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown displayContext.getTheme().resolveAttribute( 300a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown com.android.internal.R.attr.presentationTheme, outValue, true); 301a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown theme = outValue.resourceId; 302a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 303a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 304a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown // Derive the display's window manager from the outer window manager. 305a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown // We do this because the outer window manager have some extra information 306a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown // such as the parent window, which is important if the presentation uses 307a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown // an application window type. 308a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown final WindowManagerImpl outerWindowManager = 309a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown (WindowManagerImpl)outerContext.getSystemService(Context.WINDOW_SERVICE); 310a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown final WindowManagerImpl displayWindowManager = 311a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown outerWindowManager.createPresentationWindowManager(display); 312a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown return new ContextThemeWrapper(displayContext, theme) { 313a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown @Override 314a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown public Object getSystemService(String name) { 315a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown if (Context.WINDOW_SERVICE.equals(name)) { 316a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown return displayWindowManager; 317a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 318a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown return super.getSystemService(name); 319a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 320a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown }; 321a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 322a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 323a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown private final DisplayListener mDisplayListener = new DisplayListener() { 324a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown @Override 325a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown public void onDisplayAdded(int displayId) { 326a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 327a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 328a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown @Override 329a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown public void onDisplayRemoved(int displayId) { 330a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown if (displayId == mDisplay.getDisplayId()) { 331a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown handleDisplayRemoved(); 332a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 333a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 334a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 335a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown @Override 336a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown public void onDisplayChanged(int displayId) { 337a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown if (displayId == mDisplay.getDisplayId()) { 338a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown handleDisplayChanged(); 339a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 340a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 341a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown }; 342a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown 343a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown private final Handler mHandler = new Handler() { 344a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown @Override 345a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown public void handleMessage(Message msg) { 346a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown switch (msg.what) { 347a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown case MSG_CANCEL: 348a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown cancel(); 349a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown break; 350a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 351a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown } 352a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown }; 353a492c3a7b2c18426fd0cb4d017eacbc368195dc5Jeff Brown} 354