10debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski/* 20debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * Copyright (C) 2012 The Android Open Source Project 30debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * 40debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 50debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * you may not use this file except in compliance with the License. 60debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * You may obtain a copy of the License at 70debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * 80debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 90debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * 100debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * Unless required by applicable law or agreed to in writing, software 110debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 120debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * See the License for the specific language governing permissions and 140debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * limitations under the License. 150debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski */ 160debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 170debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinskipackage android.app; 180debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 1953ab92d89069fb0178ba98eb641a6fc87145543aAdam Lesinskiimport android.content.Context; 20cf76872a62075abf9008e99ca08413fb70761dc2Amith Yamasaniimport android.content.res.Resources; 21cf76872a62075abf9008e99ca08413fb70761dc2Amith Yamasaniimport android.hardware.display.DisplayManager; 220debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinskiimport android.hardware.display.DisplayManager.DisplayListener; 23cf76872a62075abf9008e99ca08413fb70761dc2Amith Yamasaniimport android.view.ContextThemeWrapper; 247f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinskiimport android.view.Display; 250debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinskiimport android.view.Gravity; 263516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.view.WindowManagerImpl; 27b0ff32245cb6b51e43dd3ee40b86d683c62de2b9Amith Yamasaniimport android.os.Handler; 280debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinskiimport android.os.Message; 290debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinskiimport android.util.DisplayMetrics; 30b0ff32245cb6b51e43dd3ee40b86d683c62de2b9Amith Yamasaniimport android.util.Log; 31e4a8da8ea241858b52d8122480316db79582c44dAmith Yamasaniimport android.util.TypedValue; 323c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski 330debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski/** 3437a40c24deb02bca3868a8085069afae112f22e4Amith Yamasani * Base class for presentations. 350debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * <p> 363c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * A presentation is a special kind of dialog whose purpose is to present 373c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * content on a secondary display. A {@link Presentation} is associated with 384a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn * the target {@link Display} at creation time and configures its context and 39cf76872a62075abf9008e99ca08413fb70761dc2Amith Yamasani * resource configuration according to the display's metrics. 4053ab92d89069fb0178ba98eb641a6fc87145543aAdam Lesinski * </p><p> 413516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * Notably, the {@link Context} of a presentation is different from the context 423c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * of its containing {@link Activity}. It is important to inflate the layout 437f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski * of a presentation and load other resources using the presentation's own context 44b0ff32245cb6b51e43dd3ee40b86d683c62de2b9Amith Yamasani * to ensure that assets of the correct size and density for the target display 4506bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani * are loaded. 467cc902bea78dd16488d367e8ed0ccf25d4d825c2Wenchao Tong * </p><p> 4715e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani * A presentation is automatically canceled (see {@link Dialog#cancel()}) when 486776849dc5ff851a225745393f082b702754e278Amith Yamasani * the display to which it is attached is removed. An activity should take 490debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * care of pausing and resuming whatever content is playing within the presentation 500debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * whenever the activity itself is paused or resumed. 510debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * </p> 5206bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani * 530debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * <h3>Choosing a presentation display</h3> 540debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * <p> 55520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani * Before showing a {@link Presentation} it's important to choose the {@link Display} 567eb599b267d00cbde891c0a87924f2f5086f4497Jeff Hao * on which it will appear. Choosing a presentation display is sometimes difficult 577f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski * because there may be multiple displays attached. Rather than trying to guess 5806bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani * which display is best, an application should let the system choose a suitable 5937a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski * presentation display. 603c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * </p><p> 613c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * There are two main ways to choose a {@link Display}. 62b0ff32245cb6b51e43dd3ee40b86d683c62de2b9Amith Yamasani * </p> 63b4b9ca7580c75f07330e5222cbd9ccc93b12935eZach Johnson * 640debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * <h4>Using the media router to choose a presentation display</h4> 6506bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani * <p> 66a6232df053cdc2df9d8a1d97a5c81d55cce7a1e2Adam Lesinski * The easiest way to choose a presentation display is to use the 670debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * {@link android.media.MediaRouter MediaRouter} API. The media router service keeps 683c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * track of which audio and video routes are available on the system. 694a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn * The media router sends notifications whenever routes are selected or unselected 70a6232df053cdc2df9d8a1d97a5c81d55cce7a1e2Adam Lesinski * or when the preferred presentation display of a route changes. 7106bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani * So an application can simply watch for these notifications and show or dismiss 723c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * a presentation on the preferred presentation display automatically. 730a11e69428d4c00dfcb368c1eb4e60ad8e0dc918Amith Yamasani * </p><p> 746776849dc5ff851a225745393f082b702754e278Amith Yamasani * The preferred presentation display is the display that the media router recommends 750debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * that the application should use if it wants to show content on the secondary display. 7637a40c24deb02bca3868a8085069afae112f22e4Amith Yamasani * Sometimes there may not be a preferred presentation display in which 771bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski * case the application should show its content locally without using a presentation. 780debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * </p><p> 790debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * Here's how to use the media router to create and show a presentation on the preferred 8006bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani * presentation display using {@link android.media.MediaRouter.RouteInfo#getPresentationDisplay()}. 810debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * </p> 821bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski * <pre> 8306bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani * MediaRouter mediaRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE); 8406bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani * MediaRouter.RouteInfo route = mediaRouter.getSelectedRoute(); 8506bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani * if (route != null) { 861bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski * Display presentationDisplay = route.getPresentationDisplay(); 87b0ff32245cb6b51e43dd3ee40b86d683c62de2b9Amith Yamasani * if (presentationDisplay != null) { 883c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * Presentation presentation = new MyPresentation(context, presentationDisplay); 893c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * presentation.show(); 900debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * } 913516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * }</pre> 923516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * <p> 933516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * The following sample code from <code>ApiDemos</code> demonstrates how to use the media 943516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * router to automatically switch between showing content in the main activity and showing 953c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * the content in a presentation when a presentation display is available. 963c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * </p> 9706bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/PresentationWithMediaRouterActivity.java 980debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * activity} 990debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * 100af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani * <h4>Using the display manager to choose a presentation display</h4> 1016776849dc5ff851a225745393f082b702754e278Amith Yamasani * <p> 1020a11e69428d4c00dfcb368c1eb4e60ad8e0dc918Amith Yamasani * Another way to choose a presentation display is to use the {@link DisplayManager} API 1030debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * directly. The display manager service provides functions to enumerate and describe all 104520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani * displays that are attached to the system including displays that may be used 1050debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * for presentations. 106af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani * </p><p> 10766143fa5b34eea7413335111838fb692987b611aAdam Lesinski * The display manager keeps track of all displays in the system. However, not all 108520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani * displays are appropriate for showing presentations. For example, if an activity 109a6232df053cdc2df9d8a1d97a5c81d55cce7a1e2Adam Lesinski * attempted to show a presentation on the main display it might obscure its own content 110a6232df053cdc2df9d8a1d97a5c81d55cce7a1e2Adam Lesinski * (it's like opening a dialog on top of your activity). 111a6232df053cdc2df9d8a1d97a5c81d55cce7a1e2Adam Lesinski * </p><p> 112a6232df053cdc2df9d8a1d97a5c81d55cce7a1e2Adam Lesinski * Here's how to identify suitable displays for showing presentations using 113a6232df053cdc2df9d8a1d97a5c81d55cce7a1e2Adam Lesinski * {@link DisplayManager#getDisplays(String)} and the 1140debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * {@link DisplayManager#DISPLAY_CATEGORY_PRESENTATION} category. 1150debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * </p> 1160debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * <pre> 1170debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * DisplayManager displayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE); 1183c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * Display[] presentationDisplays = displayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION); 119b0ff32245cb6b51e43dd3ee40b86d683c62de2b9Amith Yamasani * if (presentationDisplays.length > 0) { 12006bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani * // If there is more than one suitable presentation display, then we could consider 12115e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani * // giving the user a choice. For this example, we simply choose the first display 122520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani * // which is the one the system recommends as the preferred presentation display. 123520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani * Display display = presentationDisplays[0]; 12437a40c24deb02bca3868a8085069afae112f22e4Amith Yamasani * Presentation presentation = new MyPresentation(context, presentationDisplay); 1258dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen * presentation.show(); 1260debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * }</pre> 1273c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * <p> 1280debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * The following sample code from <code>ApiDemos</code> demonstrates how to use the display 1290debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * manager to enumerate displays and show content on multiple presentation displays 1303c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * simultaneously. 131e4a8da8ea241858b52d8122480316db79582c44dAmith Yamasani * </p> 13206bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/PresentationActivity.java 13306bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani * activity} 134520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani * 1356776849dc5ff851a225745393f082b702754e278Amith Yamasani * @see android.media.MediaRouter#ROUTE_TYPE_LIVE_VIDEO for information on about live 1360debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * video routes and how to obtain the preferred presentation display for the 1373c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * current media route. 1383c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * @see DisplayManager for information on how to enumerate displays and receive 13937a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski * notifications when displays are added or removed. 14037a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski */ 141520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasanipublic class Presentation extends Dialog { 14292617036fcc9b25378c8448c923d6346a012346bDianne Hackborn private static final String TAG = "Presentation"; 14315e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani 14406bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani private static final int MSG_CANCEL = 1; 145520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani 146a6232df053cdc2df9d8a1d97a5c81d55cce7a1e2Adam Lesinski private final Display mDisplay; 14706bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani private final DisplayManager mDisplayManager; 14806bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani 149b0ff32245cb6b51e43dd3ee40b86d683c62de2b9Amith Yamasani /** 1500a11e69428d4c00dfcb368c1eb4e60ad8e0dc918Amith Yamasani * Creates a new presentation that is attached to the specified display 1510a11e69428d4c00dfcb368c1eb4e60ad8e0dc918Amith Yamasani * using the default theme. 1520a11e69428d4c00dfcb368c1eb4e60ad8e0dc918Amith Yamasani * 153b0ff32245cb6b51e43dd3ee40b86d683c62de2b9Amith Yamasani * @param outerContext The context of the application that is showing the presentation. 154b0ff32245cb6b51e43dd3ee40b86d683c62de2b9Amith Yamasani * The presentation will create its own context (see {@link #getContext()}) based 155b0ff32245cb6b51e43dd3ee40b86d683c62de2b9Amith Yamasani * on this context and information about the associated display. 1560debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * @param display The display to which the presentation should be attached. 1570debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski */ 1580debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski public Presentation(Context outerContext, Display display) { 1590debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski this(outerContext, display, 0); 1600debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 1610debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 1620debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski /** 1633c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * Creates a new presentation that is attached to the specified display 16415e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani * using the optionally specified theme. 1650debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * 1660debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * @param outerContext The context of the application that is showing the presentation. 1670debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * The presentation will create its own context (see {@link #getContext()}) based 1683c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * on this context and information about the associated display. 1693c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * @param display The display to which the presentation should be attached. 1703c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * @param theme A style resource describing the theme to use for the window. 1713c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * See <a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes"> 1723c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * Style and Theme Resources</a> for more information about defining and using 1733c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * styles. This theme is applied on top of the current theme in 1743c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * <var>outerContext</var>. If 0, the default presentation theme will be used. 17515e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani */ 17615e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani public Presentation(Context outerContext, Display display, int theme) { 17715e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani super(createPresentationContext(outerContext, display, theme), theme, false); 17815e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani 1790debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski mDisplay = display; 18092617036fcc9b25378c8448c923d6346a012346bDianne Hackborn mDisplayManager = (DisplayManager)getContext().getSystemService(Context.DISPLAY_SERVICE); 18192617036fcc9b25378c8448c923d6346a012346bDianne Hackborn 18292617036fcc9b25378c8448c923d6346a012346bDianne Hackborn getWindow().setGravity(Gravity.FILL); 18392617036fcc9b25378c8448c923d6346a012346bDianne Hackborn setCanceledOnTouchOutside(false); 18492617036fcc9b25378c8448c923d6346a012346bDianne Hackborn } 18592617036fcc9b25378c8448c923d6346a012346bDianne Hackborn 18692617036fcc9b25378c8448c923d6346a012346bDianne Hackborn /** 18792617036fcc9b25378c8448c923d6346a012346bDianne Hackborn * Gets the {@link Display} that this presentation appears on. 18892617036fcc9b25378c8448c923d6346a012346bDianne Hackborn * 1890debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * @return The display. 1903c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski */ 1910debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski public Display getDisplay() { 1920debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski return mDisplay; 19337a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski } 19437a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski 195a6232df053cdc2df9d8a1d97a5c81d55cce7a1e2Adam Lesinski /** 1960debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * Gets the {@link Resources} that should be used to inflate the layout of this presentation. 1970debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * This resources object has been configured according to the metrics of the 1980debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * display that the presentation appears on. 1990debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * 200b0ff32245cb6b51e43dd3ee40b86d683c62de2b9Amith Yamasani * @return The presentation resources object. 201b0ff32245cb6b51e43dd3ee40b86d683c62de2b9Amith Yamasani */ 202b0ff32245cb6b51e43dd3ee40b86d683c62de2b9Amith Yamasani public Resources getResources() { 203b0ff32245cb6b51e43dd3ee40b86d683c62de2b9Amith Yamasani return getContext().getResources(); 204a6232df053cdc2df9d8a1d97a5c81d55cce7a1e2Adam Lesinski } 205a6232df053cdc2df9d8a1d97a5c81d55cce7a1e2Adam Lesinski 206a6232df053cdc2df9d8a1d97a5c81d55cce7a1e2Adam Lesinski @Override 207a6232df053cdc2df9d8a1d97a5c81d55cce7a1e2Adam Lesinski protected void onStart() { 208e4a8da8ea241858b52d8122480316db79582c44dAmith Yamasani super.onStart(); 20906bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani mDisplayManager.registerDisplayListener(mDisplayListener, mHandler); 2101958e5e7870579337f1d1d3e6c6fae096ba3abb9Dianne Hackborn 2116776849dc5ff851a225745393f082b702754e278Amith Yamasani // Since we were not watching for display changes until just now, there is a 2126776849dc5ff851a225745393f082b702754e278Amith Yamasani // chance that the display metrics have changed. If so, we will need to 21306bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani // dismiss the presentation immediately. This case is expected 21406bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani // to be rare but surprising, so we'll write a log message about it. 215520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani if (!isConfigurationStillValid()) { 216520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani Log.i(TAG, "Presentation is being dismissed because the " 21706bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani + "display metrics have changed since it was created."); 21806bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani mHandler.sendEmptyMessage(MSG_CANCEL); 21906bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani } 22006bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani } 22106bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani 22206bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani @Override 22306bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani protected void onStop() { 22406bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani mDisplayManager.unregisterDisplayListener(mDisplayListener); 22515e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani super.onStop(); 22615e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani } 227b0ff32245cb6b51e43dd3ee40b86d683c62de2b9Amith Yamasani 228b0ff32245cb6b51e43dd3ee40b86d683c62de2b9Amith Yamasani /** 229b0ff32245cb6b51e43dd3ee40b86d683c62de2b9Amith Yamasani * Inherited from {@link Dialog#show}. Will throw 23015e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani * {@link android.view.WindowManager.InvalidDisplayException} if the specified secondary 2313c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * {@link Display} can't be found. 2323c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski */ 2333c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski @Override 23415e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani public void show() { 23515e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani super.show(); 2363c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski } 2373c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski 2383c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski /** 23915e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani * Called by the system when the {@link Display} to which the presentation 24015e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani * is attached has been removed. 2416776849dc5ff851a225745393f082b702754e278Amith Yamasani * 24215e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani * The system automatically calls {@link #cancel} to dismiss the presentation 24315e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani * after sending this event. 24415e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani * 24515e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani * @see #getDisplay 24615e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani */ 24715e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani public void onDisplayRemoved() { 24815e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani } 24915e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani 25015e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani /** 25115e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani * Called by the system when the properties of the {@link Display} to which 25215e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani * the presentation is attached have changed. 25315e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani * 254520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani * If the display metrics have changed (for example, if the display has been 255520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani * resized or rotated), then the system automatically calls 2560debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * {@link #cancel} to dismiss the presentation. 2570debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * 2583c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * @see #getDisplay 2590debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski */ 26006bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani public void onDisplayChanged() { 26106bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani } 26206bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani 26306bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani private void handleDisplayRemoved() { 26406bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani onDisplayRemoved(); 26506bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani cancel(); 26606bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani } 26706bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani 26806bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani private void handleDisplayChanged() { 26906bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani onDisplayChanged(); 27006bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani 27106bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani // We currently do not support configuration changes for presentations 27206bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani // (although we could add that feature with a bit more work). 27306bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani // If the display metrics have changed in any way then the current configuration 27406bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani // is invalid and the application must recreate the presentation to get 27506bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani // a new context. 27606bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani if (!isConfigurationStillValid()) { 27706bf824628c118fbd5ad6756913d7fd63a6f4ce5Amith Yamasani Log.i(TAG, "Presentation is being dismissed because the " 2783c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski + "display metrics have changed since it was created."); 2793c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski cancel(); 2803c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski } 2813c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski } 2820debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 2833c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski private boolean isConfigurationStillValid() { 2843c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski DisplayMetrics dm = new DisplayMetrics(); 2853c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski mDisplay.getMetrics(dm); 2863c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski return dm.equalsPhysical(getResources().getDisplayMetrics()); 2870debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 2880debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 2893c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski private static Context createPresentationContext( 2903c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski Context outerContext, Display display, int theme) { 2913c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski if (outerContext == null) { 2923c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski throw new IllegalArgumentException("outerContext must not be null"); 2933c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski } 2940debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski if (display == null) { 2950debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski throw new IllegalArgumentException("display must not be null"); 2963c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski } 2973c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski 2983c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski Context displayContext = outerContext.createDisplayContext(display); 2993c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski if (theme == 0) { 3003c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski TypedValue outValue = new TypedValue(); 3013c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski displayContext.getTheme().resolveAttribute( 3020debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski com.android.internal.R.attr.presentationTheme, outValue, true); 3030debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski theme = outValue.resourceId; 3043c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski } 3053c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski 3063c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski // Derive the display's window manager from the outer window manager. 3073c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski // We do this because the outer window manager have some extra information 3083c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski // such as the parent window, which is important if the presentation uses 3093c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski // an application window type. 310520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani final WindowManagerImpl outerWindowManager = 31115e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani (WindowManagerImpl)outerContext.getSystemService(Context.WINDOW_SERVICE); 31215e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani final WindowManagerImpl displayWindowManager = 31315e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani outerWindowManager.createPresentationWindowManager(display); 31415e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani return new ContextThemeWrapper(displayContext, theme) { 315520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani @Override 316520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani public Object getSystemService(String name) { 317520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani if (Context.WINDOW_SERVICE.equals(name)) { 318520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani return displayWindowManager; 319520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani } 3208dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen return super.getSystemService(name); 32115e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani } 32215e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani }; 32315e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani } 32415e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani 325520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani private final DisplayListener mDisplayListener = new DisplayListener() { 326520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani @Override 327520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani public void onDisplayAdded(int displayId) { 328520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani } 329520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani 330520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani @Override 331a6232df053cdc2df9d8a1d97a5c81d55cce7a1e2Adam Lesinski public void onDisplayRemoved(int displayId) { 332520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani if (displayId == mDisplay.getDisplayId()) { 333520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani handleDisplayRemoved(); 334520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani } 335520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani } 336520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani 337520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani @Override 338520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani public void onDisplayChanged(int displayId) { 339520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani if (displayId == mDisplay.getDisplayId()) { 340520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani handleDisplayChanged(); 341520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani } 342a6232df053cdc2df9d8a1d97a5c81d55cce7a1e2Adam Lesinski } 343520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani }; 344520d8f2ac6ad2c3cd244e1f710103b3a43a41725Amith Yamasani 3458dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen private final Handler mHandler = new Handler() { 3468dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen @Override 3478dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen public void handleMessage(Message msg) { 3488dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen switch (msg.what) { 3498dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen case MSG_CANCEL: 3508dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen cancel(); 3516776849dc5ff851a225745393f082b702754e278Amith Yamasani break; 3526776849dc5ff851a225745393f082b702754e278Amith Yamasani } 35315e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani } 35415e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani }; 3556776849dc5ff851a225745393f082b702754e278Amith Yamasani} 3566776849dc5ff851a225745393f082b702754e278Amith Yamasani