DisplayManagerGlobal.java revision c39d47a8e7c74bd539104b0efab898ef6fc43ddf
1088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar/* 2088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * Copyright (C) 2012 The Android Open Source Project 3088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * 4088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * Licensed under the Apache License, Version 2.0 (the "License"); 5088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * you may not use this file except in compliance with the License. 6088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * You may obtain a copy of the License at 7088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * 8088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * http://www.apache.org/licenses/LICENSE-2.0 9088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * 10088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * Unless required by applicable law or agreed to in writing, software 11088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * distributed under the License is distributed on an "AS IS" BASIS, 12088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * See the License for the specific language governing permissions and 14088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * limitations under the License. 15088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar */ 16088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar 17088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarpackage android.hardware.display; 18088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar 19dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millarimport android.content.Context; 200f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintanaimport android.hardware.display.DisplayManager.DisplayListener; 210f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintanaimport android.media.projection.MediaProjection; 228a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkeyimport android.media.projection.IMediaProjection; 23088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarimport android.os.Binder; 24088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarimport android.os.Handler; 25b2909eb9509092f1479ba7883dfaa1f1e7f4cc23Jeff Sharkeyimport android.os.IBinder; 260f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintanaimport android.os.Looper; 270f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintanaimport android.os.Message; 28088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarimport android.os.RemoteException; 29088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarimport android.os.ServiceManager; 30088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarimport android.text.TextUtils; 31088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarimport android.util.Log; 32088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarimport android.util.SparseArray; 335f123bdcde61b9fdcd58952882c621c34a727e10Dmitri Plotnikovimport android.view.DisplayAdjustments; 34088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarimport android.view.Display; 35088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarimport android.view.DisplayInfo; 36088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarimport android.view.Surface; 37088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar 38088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millarimport java.util.ArrayList; 39088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar 40088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar/** 410f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana * Manager communication with the display manager service on behalf of 420f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana * an application process. You're probably looking for {@link DisplayManager}. 430f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana * 440f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana * @hide 450f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana */ 460f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintanapublic final class DisplayManagerGlobal { 470f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana private static final String TAG = "DisplayManager"; 480f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana private static final boolean DEBUG = false; 490f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana 500f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana // True if display info and display ids should be cached. 510f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana // 520f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana // FIXME: The cache is currently disabled because it's unclear whether we have the 530f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana // necessary guarantees that the caches will always be flushed before clients 540f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana // attempt to observe their new state. For example, depending on the order 550f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana // in which the binder transactions take place, we might have a problem where 560f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana // an application could start processing a configuration change due to a display 570f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana // orientation change before the display info cache has actually been invalidated. 580f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana private static final boolean USE_CACHE = false; 590f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana 600f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana public static final int EVENT_DISPLAY_ADDED = 1; 610f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana public static final int EVENT_DISPLAY_CHANGED = 2; 620f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana public static final int EVENT_DISPLAY_REMOVED = 3; 630f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana 640f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana private static DisplayManagerGlobal sInstance; 650f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana 660f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana private final Object mLock = new Object(); 670f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana 680f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana private final IDisplayManager mDm; 690f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana 700f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana private DisplayManagerCallback mCallback; 710f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana private final ArrayList<DisplayListenerDelegate> mDisplayListeners = 720f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana new ArrayList<DisplayListenerDelegate>(); 730f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana 740f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana private final SparseArray<DisplayInfo> mDisplayInfoCache = new SparseArray<DisplayInfo>(); 750f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana private int[] mDisplayIdCache; 760f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana 770f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana private int mWifiDisplayScanNestCount; 780f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana 790f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana private DisplayManagerGlobal(IDisplayManager dm) { 800f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana mDm = dm; 810f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana } 820f4e1ab773d4d52bfb85a9ad2f050ead3b8b4e49Fred Quintana 8391e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov /** 8491e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov * Gets an instance of the display manager global singleton. 8591e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov * 8691e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov * @return The display manager instance, may be null early in system startup 8791e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov * before the display manager has been fully initialized. 8891e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov */ 8991e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov public static DisplayManagerGlobal getInstance() { 9091e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov synchronized (DisplayManagerGlobal.class) { 9191e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov if (sInstance == null) { 9291e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov IBinder b = ServiceManager.getService(Context.DISPLAY_SERVICE); 9391e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov if (b != null) { 9491e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov sInstance = new DisplayManagerGlobal(IDisplayManager.Stub.asInterface(b)); 9591e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov } 9691e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov } 9791e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov return sInstance; 9891e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov } 9991e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov } 10091e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov 10191e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov /** 10291e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov * Get information about a particular logical display. 10391e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov * 10491e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov * @param displayId The logical display id. 10591e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov * @return Information about the specified display, or null if it does not exist. 10691e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov * This object belongs to an internal cache and should be treated as if it were immutable. 10791e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov */ 10891e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov public DisplayInfo getDisplayInfo(int displayId) { 10991e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov try { 11091e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov synchronized (mLock) { 11191e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov DisplayInfo info; 11291e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov if (USE_CACHE) { 11391e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov info = mDisplayInfoCache.get(displayId); 11491e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov if (info != null) { 11591e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov return info; 11691e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov } 11791e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov } 11891e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov 11991e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov info = mDm.getDisplayInfo(displayId); 12091e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov if (info == null) { 12191e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov return null; 12291e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov } 12391e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov 12491e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov if (USE_CACHE) { 12591e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov mDisplayInfoCache.put(displayId, info); 12691e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov } 12791e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov registerCallbackIfNeededLocked(); 12891e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov 12991e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov if (DEBUG) { 13091e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov Log.d(TAG, "getDisplayInfo: displayId=" + displayId + ", info=" + info); 13191e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov } 13291e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov return info; 13391e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov } 13491e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov } catch (RemoteException ex) { 13591e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov Log.e(TAG, "Could not get display information from display manager.", ex); 13691e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov return null; 13791e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov } 13891e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov } 139c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov 140088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar /** 141088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * Gets all currently valid logical display ids. 142088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * 143088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * @return An array containing all display ids. 144088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar */ 145088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar public int[] getDisplayIds() { 146088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar try { 147088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar synchronized (mLock) { 148088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar if (USE_CACHE) { 149088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar if (mDisplayIdCache != null) { 150088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar return mDisplayIdCache; 151088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 152088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 153088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar 154088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar int[] displayIds = mDm.getDisplayIds(); 155088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar if (USE_CACHE) { 156088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar mDisplayIdCache = displayIds; 157088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 158088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar registerCallbackIfNeededLocked(); 159693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov return displayIds; 160693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov } 161693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov } catch (RemoteException ex) { 162693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov Log.e(TAG, "Could not get display ids from display manager.", ex); 163693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov return new int[] { Display.DEFAULT_DISPLAY }; 164693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov } 165693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov } 166693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov 167693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov /** 168693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov * Gets information about a logical display. 169693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov * 170c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov * The display metrics may be adjusted to provide compatibility 171c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov * for legacy applications or limited screen areas. 1727cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov * 173c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov * @param displayId The logical display id. 174c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov * @param daj The compatibility info and activityToken. 175c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov * @return The display object, or null if there is no display with the given id. 176c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov */ 177c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov public Display getCompatibleDisplay(int displayId, DisplayAdjustments daj) { 178693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov DisplayInfo displayInfo = getDisplayInfo(displayId); 179693d50e7aef79f16519bf9786af68124ffaf5cd8Dmitri Plotnikov if (displayInfo == null) { 180088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar return null; 181088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 182088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar return new Display(this, displayId, displayInfo, daj); 183088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 184569277732b4180c07c9f917ff8c3fc3111b10338Dmitri Plotnikov 185088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar /** 186088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * Gets information about a logical display without applying any compatibility metrics. 187088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * 188088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * @param displayId The logical display id. 189088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar * @return The display object, or null if there is no display with the given id. 190569277732b4180c07c9f917ff8c3fc3111b10338Dmitri Plotnikov */ 191088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar public Display getRealDisplay(int displayId) { 192088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar return getCompatibleDisplay(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS); 193088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 194088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar 195088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar /** 196b2909eb9509092f1479ba7883dfaa1f1e7f4cc23Jeff Sharkey * Gets information about a logical display without applying any compatibility metrics. 197b2909eb9509092f1479ba7883dfaa1f1e7f4cc23Jeff Sharkey * 1988a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey * @param displayId The logical display id. 1997cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov * @param IBinder the activity token for this display. 200b2909eb9509092f1479ba7883dfaa1f1e7f4cc23Jeff Sharkey * @return The display object, or null if there is no display with the given id. 201b2909eb9509092f1479ba7883dfaa1f1e7f4cc23Jeff Sharkey */ 20255048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov public Display getRealDisplay(int displayId, IBinder token) { 20355048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov return getCompatibleDisplay(displayId, new DisplayAdjustments(token)); 20455048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov } 20555048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov 20655048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov public void registerDisplayListener(DisplayListener listener, Handler handler) { 20755048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov if (listener == null) { 20855048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov throw new IllegalArgumentException("listener must not be null"); 20955048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov } 21055048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov 21155048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov synchronized (mLock) { 21255048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov int index = findDisplayListenerLocked(listener); 21355048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov if (index < 0) { 21455048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov mDisplayListeners.add(new DisplayListenerDelegate(listener, handler)); 21555048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov registerCallbackIfNeededLocked(); 21655048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov } 21755048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov } 21855048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov } 21955048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov 22055048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov public void unregisterDisplayListener(DisplayListener listener) { 22155048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov if (listener == null) { 22255048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov throw new IllegalArgumentException("listener must not be null"); 22355048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov } 22455048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov 22555048a980e80cddf8d3556f3feaf235759ef24ddDmitri Plotnikov synchronized (mLock) { 226088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar int index = findDisplayListenerLocked(listener); 227088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar if (index >= 0) { 228088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar DisplayListenerDelegate d = mDisplayListeners.get(index); 2297cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov d.clearEvents(); 2307cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov mDisplayListeners.remove(index); 231088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 23291e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov } 233c9ec66b68b4ec98c9b2acb10ea25cfd7f0f648a2Dmitri Plotnikov } 234088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar 235088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar private int findDisplayListenerLocked(DisplayListener listener) { 236088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar final int numListeners = mDisplayListeners.size(); 2377cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov for (int i = 0; i < numListeners; i++) { 238088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar if (mDisplayListeners.get(i).mListener == listener) { 239088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar return i; 240088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 241088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 2427cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov return -1; 243088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 244088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar 245d530b3ce850cfa3d61b79eba1aee6f67b04dba15Jeff Sharkey private void registerCallbackIfNeededLocked() { 24602c5b45565fd3a933b5dd5a868b7db33455d697cDmitri Plotnikov if (mCallback == null) { 247d530b3ce850cfa3d61b79eba1aee6f67b04dba15Jeff Sharkey mCallback = new DisplayManagerCallback(); 248d530b3ce850cfa3d61b79eba1aee6f67b04dba15Jeff Sharkey try { 2497cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov mDm.registerCallback(mCallback); 2508a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey } catch (RemoteException ex) { 251161dd86394a9733fd7ff303c31481cae7e31e7b4Evan Millar Log.e(TAG, "Failed to register callback with display manager service.", ex); 252161dd86394a9733fd7ff303c31481cae7e31e7b4Evan Millar mCallback = null; 2538a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey } 2547cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov } 255161dd86394a9733fd7ff303c31481cae7e31e7b4Evan Millar } 256161dd86394a9733fd7ff303c31481cae7e31e7b4Evan Millar 257161dd86394a9733fd7ff303c31481cae7e31e7b4Evan Millar private void handleDisplayEvent(int displayId, int event) { 258161dd86394a9733fd7ff303c31481cae7e31e7b4Evan Millar synchronized (mLock) { 2598a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey if (USE_CACHE) { 260dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar mDisplayInfoCache.remove(displayId); 261dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar 2627cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov if (event == EVENT_DISPLAY_ADDED || event == EVENT_DISPLAY_REMOVED) { 2637cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov mDisplayIdCache = null; 264dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar } 265dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar } 266dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar 2678a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey final int numListeners = mDisplayListeners.size(); 268dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar for (int i = 0; i < numListeners; i++) { 269dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar mDisplayListeners.get(i).sendDisplayEvent(displayId, event); 2708a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey } 2717cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov } 272dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar } 273dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar 274dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar public void startWifiDisplayScan() { 275dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar synchronized (mLock) { 276d530b3ce850cfa3d61b79eba1aee6f67b04dba15Jeff Sharkey if (mWifiDisplayScanNestCount++ == 0) { 277b926375cdabef2e56a8212a9fa1774566f659eaeEvan Millar registerCallbackIfNeededLocked(); 278b926375cdabef2e56a8212a9fa1774566f659eaeEvan Millar try { 279d530b3ce850cfa3d61b79eba1aee6f67b04dba15Jeff Sharkey mDm.startWifiDisplayScan(); 280088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } catch (RemoteException ex) { 281088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar Log.e(TAG, "Failed to scan for Wifi displays.", ex); 282088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 2837cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov } 284088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 285088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 286088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar 287088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar public void stopWifiDisplayScan() { 288088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar synchronized (mLock) { 2897cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov if (--mWifiDisplayScanNestCount == 0) { 290088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar try { 291088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar mDm.stopWifiDisplayScan(); 2927cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov } catch (RemoteException ex) { 293088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar Log.e(TAG, "Failed to scan for Wifi displays.", ex); 294088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 2958851e163fc5bc17d139bf29cd2ec2f3926d342bcFred Quintana } else if (mWifiDisplayScanNestCount < 0) { 296088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar Log.wtf(TAG, "Wifi display scan nest count became negative: " 297088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar + mWifiDisplayScanNestCount); 298088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar mWifiDisplayScanNestCount = 0; 299088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 300088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 301088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 302088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar 303088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar public void connectWifiDisplay(String deviceAddress) { 304088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar if (deviceAddress == null) { 305088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar throw new IllegalArgumentException("deviceAddress must not be null"); 3060918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov } 3070918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov 3080918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov try { 3097cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov mDm.connectWifiDisplay(deviceAddress); 3107cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov } catch (RemoteException ex) { 3110918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov Log.e(TAG, "Failed to connect to Wifi display " + deviceAddress + ".", ex); 3127cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov } 3130918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov } 3140918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov 3150918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov public void pauseWifiDisplay() { 3160918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov try { 3170918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov mDm.pauseWifiDisplay(); 3180918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov } catch (RemoteException ex) { 3190918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov Log.e(TAG, "Failed to pause Wifi display.", ex); 3200918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov } 3210918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov } 3220918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov 3230918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov public void resumeWifiDisplay() { 3240918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov try { 3250918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov mDm.resumeWifiDisplay(); 3260918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov } catch (RemoteException ex) { 3270918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov Log.e(TAG, "Failed to resume Wifi display.", ex); 32891e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov } 32991e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov } 3300918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov 33191e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov public void disconnectWifiDisplay() { 3320918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov try { 3330918bf06881f32e6e3cf750f713b16c7d65e4012Dmitri Plotnikov mDm.disconnectWifiDisplay(); 334088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } catch (RemoteException ex) { 335088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar Log.e(TAG, "Failed to disconnect from Wifi display.", ex); 3362365ded4465332cc1de7fa661e2198854153d6ddDmitri Plotnikov } 33703d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana } 3387cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov 3397cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov public void renameWifiDisplay(String deviceAddress, String alias) { 3408a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey if (deviceAddress == null) { 341088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar throw new IllegalArgumentException("deviceAddress must not be null"); 3427cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov } 343088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar 344088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar try { 3452365ded4465332cc1de7fa661e2198854153d6ddDmitri Plotnikov mDm.renameWifiDisplay(deviceAddress, alias); 3468a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey } catch (RemoteException ex) { 3478a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey Log.e(TAG, "Failed to rename Wifi display " + deviceAddress 3488a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey + " with alias " + alias + ".", ex); 3498a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey } 3508a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey } 3518a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey 3528a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey public void forgetWifiDisplay(String deviceAddress) { 3538a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey if (deviceAddress == null) { 3548a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey throw new IllegalArgumentException("deviceAddress must not be null"); 3558a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey } 3568a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey 3578a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey try { 358d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov mDm.forgetWifiDisplay(deviceAddress); 359d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov } catch (RemoteException ex) { 360d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov Log.e(TAG, "Failed to forget Wifi display.", ex); 361d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov } 362facbbb37835020b767f259f0f625386b52b2ad89Dmitri Plotnikov } 3637cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov 364d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov public WifiDisplayStatus getWifiDisplayStatus() { 3657cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov try { 366d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov return mDm.getWifiDisplayStatus(); 367d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov } catch (RemoteException ex) { 368d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov Log.e(TAG, "Failed to get Wifi display status.", ex); 3698a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey return new WifiDisplayStatus(); 3708a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey } 3718a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey } 3722365ded4465332cc1de7fa661e2198854153d6ddDmitri Plotnikov 3732365ded4465332cc1de7fa661e2198854153d6ddDmitri Plotnikov public VirtualDisplay createVirtualDisplay(Context context, MediaProjection projection, 3742365ded4465332cc1de7fa661e2198854153d6ddDmitri Plotnikov String name, int width, int height, int densityDpi, Surface surface, int flags, 3758a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey VirtualDisplay.Callbacks callbacks, Handler handler) { 3767cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov if (TextUtils.isEmpty(name)) { 37791e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov throw new IllegalArgumentException("name must be non-null and non-empty"); 3788a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey } 3798a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey if (width <= 0 || height <= 0 || densityDpi <= 0) { 3808a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey throw new IllegalArgumentException("width, height, and densityDpi must be " 3812365ded4465332cc1de7fa661e2198854153d6ddDmitri Plotnikov + "greater than 0"); 3828a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey } 3838a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey 3848a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey VirtualDisplayCallbacks callbackWrapper = new VirtualDisplayCallbacks(callbacks, handler); 385088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar IMediaProjection projectionToken = projection != null ? projection.getProjection() : null; 386088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar int displayId; 387facbbb37835020b767f259f0f625386b52b2ad89Dmitri Plotnikov try { 388088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar displayId = mDm.createVirtualDisplay(callbackWrapper, projectionToken, 389088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar context.getPackageName(), name, width, height, densityDpi, surface, flags); 390088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } catch (RemoteException ex) { 391088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar Log.e(TAG, "Could not create virtual display: " + name, ex); 392088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar return null; 393569277732b4180c07c9f917ff8c3fc3111b10338Dmitri Plotnikov } 394088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar if (displayId < 0) { 395088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar Log.e(TAG, "Could not create virtual display: " + name); 396dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar return null; 397dc2da5fd922fc8de0ffcb22df3622b57ed777732Evan Millar } 398088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar Display display = getRealDisplay(displayId); 399088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar if (display == null) { 400088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar Log.wtf(TAG, "Could not obtain display info for newly created " 401088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar + "virtual display: " + name); 402088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar try { 4037cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov mDm.releaseVirtualDisplay(callbackWrapper); 404088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } catch (RemoteException ex) { 405088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 406088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar return null; 407088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 408088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar return new VirtualDisplay(this, display, callbackWrapper, surface); 4097cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov } 410088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar 411088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar public void setVirtualDisplaySurface(IVirtualDisplayCallbacks token, Surface surface) { 412d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov try { 413d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov mDm.setVirtualDisplaySurface(token, surface); 414d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov } catch (RemoteException ex) { 415d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov Log.w(TAG, "Failed to set virtual display surface.", ex); 416d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov } 417d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov } 418d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov 419d5f56d1467cb877aa216effd605745f5f22b1917Dmitri Plotnikov public void releaseVirtualDisplay(IVirtualDisplayCallbacks token) { 420c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov try { 421c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov mDm.releaseVirtualDisplay(token); 422c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov } catch (RemoteException ex) { 423c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov Log.w(TAG, "Failed to release virtual display.", ex); 424c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov } 425facbbb37835020b767f259f0f625386b52b2ad89Dmitri Plotnikov } 426c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov 427c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub { 428c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov @Override 429c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov public void onDisplayEvent(int displayId, int event) { 430facbbb37835020b767f259f0f625386b52b2ad89Dmitri Plotnikov if (DEBUG) { 431c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov Log.d(TAG, "onDisplayEvent: displayId=" + displayId + ", event=" + event); 432c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov } 433c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov handleDisplayEvent(displayId, event); 434c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov } 435c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov } 436c991bfc53ff287c512a8ba567135499cc4157900Dmitri Plotnikov 437facbbb37835020b767f259f0f625386b52b2ad89Dmitri Plotnikov private static final class DisplayListenerDelegate extends Handler { 438088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar public final DisplayListener mListener; 439088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar 440088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar public DisplayListenerDelegate(DisplayListener listener, Handler handler) { 441088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar super(handler != null ? handler.getLooper() : Looper.myLooper(), null, true /*async*/); 442088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar mListener = listener; 443088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 4448a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey 4458a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey public void sendDisplayEvent(int displayId, int event) { 446088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar Message msg = obtainMessage(event, displayId, 0); 447088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar sendMessage(msg); 448088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 449088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar 450088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar public void clearEvents() { 451088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar removeCallbacksAndMessages(null); 452088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 453088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar 454088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar @Override 455088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar public void handleMessage(Message msg) { 4568a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey switch (msg.what) { 4578a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey case EVENT_DISPLAY_ADDED: 4588a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey mListener.onDisplayAdded(msg.arg1); 4598a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey break; 4608a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey case EVENT_DISPLAY_CHANGED: 4618a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey mListener.onDisplayChanged(msg.arg1); 4628a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey break; 4638a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey case EVENT_DISPLAY_REMOVED: 464088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar mListener.onDisplayRemoved(msg.arg1); 465088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar break; 466088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 467088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 4687cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov } 469569277732b4180c07c9f917ff8c3fc3111b10338Dmitri Plotnikov 470088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar private final static class VirtualDisplayCallbacks extends IVirtualDisplayCallbacks.Stub { 471facbbb37835020b767f259f0f625386b52b2ad89Dmitri Plotnikov private VirtualDisplayCallbacksDelegate mDelegate; 472facbbb37835020b767f259f0f625386b52b2ad89Dmitri Plotnikov 473ab5742dd63f4e62ee0f55f786854c024ef8c5bb4Evan Millar public VirtualDisplayCallbacks(VirtualDisplay.Callbacks callbacks, Handler handler) { 4747cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov mDelegate = new VirtualDisplayCallbacksDelegate(callbacks, handler); 475ab5742dd63f4e62ee0f55f786854c024ef8c5bb4Evan Millar } 476ab5742dd63f4e62ee0f55f786854c024ef8c5bb4Evan Millar 477ab5742dd63f4e62ee0f55f786854c024ef8c5bb4Evan Millar @Override // Binder call 478ab5742dd63f4e62ee0f55f786854c024ef8c5bb4Evan Millar public void onDisplayPaused() { 479ab5742dd63f4e62ee0f55f786854c024ef8c5bb4Evan Millar mDelegate.sendEmptyMessage(VirtualDisplayCallbacksDelegate.MSG_DISPLAY_PAUSED); 4807cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov } 4817cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov 4827cca5f83638b019cc68acfaedd533602a97486b0Dmitri Plotnikov @Override // Binder call 483ab5742dd63f4e62ee0f55f786854c024ef8c5bb4Evan Millar public void onDisplayResumed() { 484ab5742dd63f4e62ee0f55f786854c024ef8c5bb4Evan Millar mDelegate.sendEmptyMessage(VirtualDisplayCallbacksDelegate.MSG_DISPLAY_RESUMED); 485ab5742dd63f4e62ee0f55f786854c024ef8c5bb4Evan Millar } 486ab5742dd63f4e62ee0f55f786854c024ef8c5bb4Evan Millar 48728b68e5a59289f6947dc799b66a3b503571f876eJeff Sharkey @Override // Binder call 488c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana public void onDisplayStopped() { 489c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana mDelegate.sendEmptyMessage(VirtualDisplayCallbacksDelegate.MSG_DISPLAY_STOPPED); 490c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana } 491c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana } 492c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana 493c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana private final static class VirtualDisplayCallbacksDelegate extends Handler { 494c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana public static final int MSG_DISPLAY_PAUSED = 0; 495088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar public static final int MSG_DISPLAY_RESUMED = 1; 496088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar public static final int MSG_DISPLAY_STOPPED = 2; 497088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar 498088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar private final VirtualDisplay.Callbacks mCallbacks; 499088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar 500088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar public VirtualDisplayCallbacksDelegate(VirtualDisplay.Callbacks callbacks, 501088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar Handler handler) { 502088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar super(handler != null ? handler.getLooper() : Looper.myLooper(), null, true /*async*/); 503088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar mCallbacks = callbacks; 504088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 505088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar 506088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar @Override 507088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar public void handleMessage(Message msg) { 508088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar if (mCallbacks == null) { 509088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar return; 510088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar } 511088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar switch (msg.what) { 512088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar case MSG_DISPLAY_PAUSED: 513088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar mCallbacks.onDisplayPaused(); 514088b2918423ef79b92c0b0433f2f59a1fd0f7c1bEvan Millar break; 5158a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey case MSG_DISPLAY_RESUMED: 5168a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey mCallbacks.onDisplayResumed(); 5178a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey break; 5188a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey case MSG_DISPLAY_STOPPED: 5198a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey mCallbacks.onDisplayStopped(); 5208a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey break; 5218a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey } 5228a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey } 5238a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey } 5248a0193e4ca1522b9a817ebd399812b6e2f1b0cdcJeff Sharkey} 52591e4e85752ee60ef4965e5974cc3f62e3d0651fdDmitri Plotnikov