1bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown/* 2bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * Copyright (C) 2012 The Android Open Source Project 3bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * 4bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 5bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * you may not use this file except in compliance with the License. 6bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * You may obtain a copy of the License at 7bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * 8bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * http://www.apache.org/licenses/LICENSE-2.0 9bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * 10bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * Unless required by applicable law or agreed to in writing, software 11bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 12bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * See the License for the specific language governing permissions and 14bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * limitations under the License. 15bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown */ 16bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 17bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownpackage android.hardware.display; 18bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 19bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.content.Context; 20bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.hardware.display.DisplayManager.DisplayListener; 21c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.media.projection.MediaProjection; 22c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.media.projection.IMediaProjection; 23a506a6ec94863a35acca9feb165db76ddac3892cJeff Brownimport android.os.Binder; 24bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.os.Handler; 25bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.os.IBinder; 26bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.os.Looper; 27bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.os.Message; 28bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.os.RemoteException; 29bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.os.ServiceManager; 30a506a6ec94863a35acca9feb165db76ddac3892cJeff Brownimport android.text.TextUtils; 31bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.util.Log; 32bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.util.SparseArray; 3348d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautnerimport android.view.DisplayAdjustments; 34bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.view.Display; 35bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.view.DisplayInfo; 36a506a6ec94863a35acca9feb165db76ddac3892cJeff Brownimport android.view.Surface; 37bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 38bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport java.util.ArrayList; 39bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 40bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown/** 41bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * Manager communication with the display manager service on behalf of 42bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * an application process. You're probably looking for {@link DisplayManager}. 43bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * 44bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * @hide 45bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown */ 46bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownpublic final class DisplayManagerGlobal { 47bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private static final String TAG = "DisplayManager"; 48bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private static final boolean DEBUG = false; 49bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 504ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown // True if display info and display ids should be cached. 514ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown // 524ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown // FIXME: The cache is currently disabled because it's unclear whether we have the 534ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown // necessary guarantees that the caches will always be flushed before clients 544ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown // attempt to observe their new state. For example, depending on the order 554ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown // in which the binder transactions take place, we might have a problem where 564ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown // an application could start processing a configuration change due to a display 574ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown // orientation change before the display info cache has actually been invalidated. 584ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown private static final boolean USE_CACHE = false; 594ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 60bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public static final int EVENT_DISPLAY_ADDED = 1; 61bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public static final int EVENT_DISPLAY_CHANGED = 2; 62bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public static final int EVENT_DISPLAY_REMOVED = 3; 63bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 64bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private static DisplayManagerGlobal sInstance; 65bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 66bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private final Object mLock = new Object(); 67bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 68bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private final IDisplayManager mDm; 69bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 70bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private DisplayManagerCallback mCallback; 71bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private final ArrayList<DisplayListenerDelegate> mDisplayListeners = 72bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown new ArrayList<DisplayListenerDelegate>(); 73bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 74bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private final SparseArray<DisplayInfo> mDisplayInfoCache = new SparseArray<DisplayInfo>(); 75bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private int[] mDisplayIdCache; 76bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 77ce468a35b388ca46578934706b38dbae94941643Jeff Brown private int mWifiDisplayScanNestCount; 78ce468a35b388ca46578934706b38dbae94941643Jeff Brown 79bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private DisplayManagerGlobal(IDisplayManager dm) { 80bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown mDm = dm; 81bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 82bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 83bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown /** 84bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * Gets an instance of the display manager global singleton. 85bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * 86bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * @return The display manager instance, may be null early in system startup 87bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * before the display manager has been fully initialized. 88bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown */ 89bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public static DisplayManagerGlobal getInstance() { 90bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown synchronized (DisplayManagerGlobal.class) { 91bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (sInstance == null) { 92bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown IBinder b = ServiceManager.getService(Context.DISPLAY_SERVICE); 93bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (b != null) { 94bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown sInstance = new DisplayManagerGlobal(IDisplayManager.Stub.asInterface(b)); 95bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 96bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 97bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown return sInstance; 98bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 99bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 100bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 101bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown /** 102bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * Get information about a particular logical display. 103bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * 104bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * @param displayId The logical display id. 105bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * @return Information about the specified display, or null if it does not exist. 106bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * This object belongs to an internal cache and should be treated as if it were immutable. 107bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown */ 108bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public DisplayInfo getDisplayInfo(int displayId) { 109bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown try { 110bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown synchronized (mLock) { 1114ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown DisplayInfo info; 1124ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (USE_CACHE) { 1134ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown info = mDisplayInfoCache.get(displayId); 1144ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (info != null) { 1154ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown return info; 1164ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 117bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 118bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 119bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown info = mDm.getDisplayInfo(displayId); 120bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (info == null) { 121bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown return null; 122bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 1234ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 1244ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (USE_CACHE) { 1254ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mDisplayInfoCache.put(displayId, info); 1264ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 1274ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown registerCallbackIfNeededLocked(); 1284ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 129bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (DEBUG) { 130bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown Log.d(TAG, "getDisplayInfo: displayId=" + displayId + ", info=" + info); 131bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 132bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown return info; 133bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 134bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } catch (RemoteException ex) { 135bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown Log.e(TAG, "Could not get display information from display manager.", ex); 136bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown return null; 137bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 138bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 139bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 140bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown /** 141bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * Gets all currently valid logical display ids. 142bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * 143bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * @return An array containing all display ids. 144bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown */ 145bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public int[] getDisplayIds() { 146bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown try { 147bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown synchronized (mLock) { 1484ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (USE_CACHE) { 1494ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (mDisplayIdCache != null) { 1504ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown return mDisplayIdCache; 1514ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 1524ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 1534ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 1544ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown int[] displayIds = mDm.getDisplayIds(); 1554ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (USE_CACHE) { 1564ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mDisplayIdCache = displayIds; 157bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 1584ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown registerCallbackIfNeededLocked(); 1594ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown return displayIds; 160bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 161bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } catch (RemoteException ex) { 162bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown Log.e(TAG, "Could not get display ids from display manager.", ex); 163bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown return new int[] { Display.DEFAULT_DISPLAY }; 164bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 165bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 166bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 167bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown /** 168bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * Gets information about a logical display. 169bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * 170bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * The display metrics may be adjusted to provide compatibility 17148d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner * for legacy applications or limited screen areas. 172bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * 173bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * @param displayId The logical display id. 17448d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner * @param daj The compatibility info and activityToken. 175bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * @return The display object, or null if there is no display with the given id. 176bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown */ 17748d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner public Display getCompatibleDisplay(int displayId, DisplayAdjustments daj) { 178bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown DisplayInfo displayInfo = getDisplayInfo(displayId); 179bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (displayInfo == null) { 180bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown return null; 181bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 18248d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner return new Display(this, displayId, displayInfo, daj); 183bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 184bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 185bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown /** 186bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * Gets information about a logical display without applying any compatibility metrics. 187bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * 188bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * @param displayId The logical display id. 189bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * @return The display object, or null if there is no display with the given id. 190bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown */ 191bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public Display getRealDisplay(int displayId) { 19248d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner return getCompatibleDisplay(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS); 19348d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner } 19448d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner 19548d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner /** 19648d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner * Gets information about a logical display without applying any compatibility metrics. 19748d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner * 19848d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner * @param displayId The logical display id. 19948d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner * @param IBinder the activity token for this display. 20048d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner * @return The display object, or null if there is no display with the given id. 20148d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner */ 20248d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner public Display getRealDisplay(int displayId, IBinder token) { 20348d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner return getCompatibleDisplay(displayId, new DisplayAdjustments(token)); 204bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 205bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 206bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public void registerDisplayListener(DisplayListener listener, Handler handler) { 207bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (listener == null) { 208bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown throw new IllegalArgumentException("listener must not be null"); 209bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 210bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 211bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown synchronized (mLock) { 212bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown int index = findDisplayListenerLocked(listener); 213bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (index < 0) { 214bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown mDisplayListeners.add(new DisplayListenerDelegate(listener, handler)); 215bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown registerCallbackIfNeededLocked(); 216bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 217bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 218bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 219bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 220bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public void unregisterDisplayListener(DisplayListener listener) { 221bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (listener == null) { 222bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown throw new IllegalArgumentException("listener must not be null"); 223bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 224bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 225bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown synchronized (mLock) { 226bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown int index = findDisplayListenerLocked(listener); 227bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (index >= 0) { 228bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown DisplayListenerDelegate d = mDisplayListeners.get(index); 229bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown d.clearEvents(); 230bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown mDisplayListeners.remove(index); 231bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 232bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 233bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 234bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 235bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private int findDisplayListenerLocked(DisplayListener listener) { 236bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown final int numListeners = mDisplayListeners.size(); 237bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown for (int i = 0; i < numListeners; i++) { 238bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (mDisplayListeners.get(i).mListener == listener) { 239bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown return i; 240bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 241bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 242bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown return -1; 243bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 244bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 245bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private void registerCallbackIfNeededLocked() { 246bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (mCallback == null) { 247bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown mCallback = new DisplayManagerCallback(); 248bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown try { 249bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown mDm.registerCallback(mCallback); 250bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } catch (RemoteException ex) { 251bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown Log.e(TAG, "Failed to register callback with display manager service.", ex); 252bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown mCallback = null; 253bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 254bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 255bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 256bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 257bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private void handleDisplayEvent(int displayId, int event) { 258bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown synchronized (mLock) { 2594ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (USE_CACHE) { 2604ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mDisplayInfoCache.remove(displayId); 261bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 2624ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (event == EVENT_DISPLAY_ADDED || event == EVENT_DISPLAY_REMOVED) { 2634ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mDisplayIdCache = null; 2644ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 265bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 266bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 267bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown final int numListeners = mDisplayListeners.size(); 268bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown for (int i = 0; i < numListeners; i++) { 269bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown mDisplayListeners.get(i).sendDisplayEvent(displayId, event); 270bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 271bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 272bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 273bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 274ce468a35b388ca46578934706b38dbae94941643Jeff Brown public void startWifiDisplayScan() { 275ce468a35b388ca46578934706b38dbae94941643Jeff Brown synchronized (mLock) { 276ce468a35b388ca46578934706b38dbae94941643Jeff Brown if (mWifiDisplayScanNestCount++ == 0) { 277ce468a35b388ca46578934706b38dbae94941643Jeff Brown registerCallbackIfNeededLocked(); 278ce468a35b388ca46578934706b38dbae94941643Jeff Brown try { 279ce468a35b388ca46578934706b38dbae94941643Jeff Brown mDm.startWifiDisplayScan(); 280ce468a35b388ca46578934706b38dbae94941643Jeff Brown } catch (RemoteException ex) { 281ce468a35b388ca46578934706b38dbae94941643Jeff Brown Log.e(TAG, "Failed to scan for Wifi displays.", ex); 282ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 283ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 284ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 285ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 286ce468a35b388ca46578934706b38dbae94941643Jeff Brown 287ce468a35b388ca46578934706b38dbae94941643Jeff Brown public void stopWifiDisplayScan() { 288ce468a35b388ca46578934706b38dbae94941643Jeff Brown synchronized (mLock) { 289ce468a35b388ca46578934706b38dbae94941643Jeff Brown if (--mWifiDisplayScanNestCount == 0) { 290ce468a35b388ca46578934706b38dbae94941643Jeff Brown try { 291ce468a35b388ca46578934706b38dbae94941643Jeff Brown mDm.stopWifiDisplayScan(); 292ce468a35b388ca46578934706b38dbae94941643Jeff Brown } catch (RemoteException ex) { 293ce468a35b388ca46578934706b38dbae94941643Jeff Brown Log.e(TAG, "Failed to scan for Wifi displays.", ex); 294ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 295ce468a35b388ca46578934706b38dbae94941643Jeff Brown } else if (mWifiDisplayScanNestCount < 0) { 296ce468a35b388ca46578934706b38dbae94941643Jeff Brown Log.wtf(TAG, "Wifi display scan nest count became negative: " 297ce468a35b388ca46578934706b38dbae94941643Jeff Brown + mWifiDisplayScanNestCount); 298ce468a35b388ca46578934706b38dbae94941643Jeff Brown mWifiDisplayScanNestCount = 0; 299ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 300e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 301e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 302e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 303e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void connectWifiDisplay(String deviceAddress) { 304e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (deviceAddress == null) { 305e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown throw new IllegalArgumentException("deviceAddress must not be null"); 306e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 307e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 308e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown try { 309e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mDm.connectWifiDisplay(deviceAddress); 310e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } catch (RemoteException ex) { 311e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown Log.e(TAG, "Failed to connect to Wifi display " + deviceAddress + ".", ex); 312e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 313e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 314e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 3151f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang public void pauseWifiDisplay() { 3161f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang try { 3171f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang mDm.pauseWifiDisplay(); 3181f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } catch (RemoteException ex) { 3191f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang Log.e(TAG, "Failed to pause Wifi display.", ex); 3201f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 3211f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 3221f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang 3231f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang public void resumeWifiDisplay() { 3241f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang try { 3251f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang mDm.resumeWifiDisplay(); 3261f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } catch (RemoteException ex) { 3271f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang Log.e(TAG, "Failed to resume Wifi display.", ex); 3281f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 3291f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 3301f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang 331e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void disconnectWifiDisplay() { 332e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown try { 333e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mDm.disconnectWifiDisplay(); 334e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } catch (RemoteException ex) { 335e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown Log.e(TAG, "Failed to disconnect from Wifi display.", ex); 336e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 337e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 338e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 33989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void renameWifiDisplay(String deviceAddress, String alias) { 34089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (deviceAddress == null) { 34189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown throw new IllegalArgumentException("deviceAddress must not be null"); 34289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 34389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 34489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown try { 34589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mDm.renameWifiDisplay(deviceAddress, alias); 34689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } catch (RemoteException ex) { 34789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown Log.e(TAG, "Failed to rename Wifi display " + deviceAddress 34889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown + " with alias " + alias + ".", ex); 34989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 35089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 35189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 35289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void forgetWifiDisplay(String deviceAddress) { 35389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (deviceAddress == null) { 35489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown throw new IllegalArgumentException("deviceAddress must not be null"); 35589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 35689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 35789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown try { 35889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mDm.forgetWifiDisplay(deviceAddress); 35989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } catch (RemoteException ex) { 36089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown Log.e(TAG, "Failed to forget Wifi display.", ex); 36189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 36289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 36389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 364e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public WifiDisplayStatus getWifiDisplayStatus() { 365e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown try { 366e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown return mDm.getWifiDisplayStatus(); 367e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } catch (RemoteException ex) { 368e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown Log.e(TAG, "Failed to get Wifi display status.", ex); 369e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown return new WifiDisplayStatus(); 370e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 371e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 372e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 373c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public VirtualDisplay createVirtualDisplay(Context context, MediaProjection projection, 374c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright String name, int width, int height, int densityDpi, Surface surface, int flags, 37575ee9fcde4d9e1be3883eba6c8d193db4375b052Michael Wright VirtualDisplay.Callback callback, Handler handler) { 376a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown if (TextUtils.isEmpty(name)) { 377a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown throw new IllegalArgumentException("name must be non-null and non-empty"); 378a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } 379a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown if (width <= 0 || height <= 0 || densityDpi <= 0) { 380a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown throw new IllegalArgumentException("width, height, and densityDpi must be " 381a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown + "greater than 0"); 382a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } 383a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown 38475ee9fcde4d9e1be3883eba6c8d193db4375b052Michael Wright VirtualDisplayCallback callbackWrapper = new VirtualDisplayCallback(callback, handler); 385c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright IMediaProjection projectionToken = projection != null ? projection.getProjection() : null; 386a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown int displayId; 387a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown try { 388c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright displayId = mDm.createVirtualDisplay(callbackWrapper, projectionToken, 389c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright context.getPackageName(), name, width, height, densityDpi, surface, flags); 390a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } catch (RemoteException ex) { 3917d00affce6e25b22fd8fc135933b3bf6b547a0dcJeff Brown Log.e(TAG, "Could not create virtual display: " + name, ex); 392a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown return null; 393a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } 394a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown if (displayId < 0) { 3957d00affce6e25b22fd8fc135933b3bf6b547a0dcJeff Brown Log.e(TAG, "Could not create virtual display: " + name); 396a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown return null; 397a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } 398a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown Display display = getRealDisplay(displayId); 399a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown if (display == null) { 400a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown Log.wtf(TAG, "Could not obtain display info for newly created " 4017d00affce6e25b22fd8fc135933b3bf6b547a0dcJeff Brown + "virtual display: " + name); 402a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown try { 403c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright mDm.releaseVirtualDisplay(callbackWrapper); 404a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } catch (RemoteException ex) { 405a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } 406a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown return null; 407a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } 408c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright return new VirtualDisplay(this, display, callbackWrapper, surface); 40992207df753c27b094e9e0ca80d41bc0d54dc6bd5Jeff Brown } 41092207df753c27b094e9e0ca80d41bc0d54dc6bd5Jeff Brown 41175ee9fcde4d9e1be3883eba6c8d193db4375b052Michael Wright public void setVirtualDisplaySurface(IVirtualDisplayCallback token, Surface surface) { 41292207df753c27b094e9e0ca80d41bc0d54dc6bd5Jeff Brown try { 41392207df753c27b094e9e0ca80d41bc0d54dc6bd5Jeff Brown mDm.setVirtualDisplaySurface(token, surface); 41492207df753c27b094e9e0ca80d41bc0d54dc6bd5Jeff Brown } catch (RemoteException ex) { 41592207df753c27b094e9e0ca80d41bc0d54dc6bd5Jeff Brown Log.w(TAG, "Failed to set virtual display surface.", ex); 41692207df753c27b094e9e0ca80d41bc0d54dc6bd5Jeff Brown } 417a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } 418a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown 41975ee9fcde4d9e1be3883eba6c8d193db4375b052Michael Wright public void resizeVirtualDisplay(IVirtualDisplayCallback token, 42001e840ff9441e005153d799e71d65b38bcb21902Michael Wright int width, int height, int densityDpi) { 42101e840ff9441e005153d799e71d65b38bcb21902Michael Wright try { 42201e840ff9441e005153d799e71d65b38bcb21902Michael Wright mDm.resizeVirtualDisplay(token, width, height, densityDpi); 42301e840ff9441e005153d799e71d65b38bcb21902Michael Wright } catch (RemoteException ex) { 42401e840ff9441e005153d799e71d65b38bcb21902Michael Wright Log.w(TAG, "Failed to resize virtual display.", ex); 42501e840ff9441e005153d799e71d65b38bcb21902Michael Wright } 42601e840ff9441e005153d799e71d65b38bcb21902Michael Wright } 42701e840ff9441e005153d799e71d65b38bcb21902Michael Wright 42875ee9fcde4d9e1be3883eba6c8d193db4375b052Michael Wright public void releaseVirtualDisplay(IVirtualDisplayCallback token) { 429a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown try { 430a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown mDm.releaseVirtualDisplay(token); 431a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } catch (RemoteException ex) { 432a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown Log.w(TAG, "Failed to release virtual display.", ex); 433a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } 434a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } 435a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown 436bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub { 437bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown @Override 438bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public void onDisplayEvent(int displayId, int event) { 439bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (DEBUG) { 440bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown Log.d(TAG, "onDisplayEvent: displayId=" + displayId + ", event=" + event); 441bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 442bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown handleDisplayEvent(displayId, event); 443bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 444bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 445bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 446bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private static final class DisplayListenerDelegate extends Handler { 447bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public final DisplayListener mListener; 448bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 449bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public DisplayListenerDelegate(DisplayListener listener, Handler handler) { 450bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown super(handler != null ? handler.getLooper() : Looper.myLooper(), null, true /*async*/); 451bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown mListener = listener; 452bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 453bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 454bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public void sendDisplayEvent(int displayId, int event) { 455bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown Message msg = obtainMessage(event, displayId, 0); 456bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown sendMessage(msg); 457bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 458bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 459bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public void clearEvents() { 460bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown removeCallbacksAndMessages(null); 461bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 462bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 463bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown @Override 464bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public void handleMessage(Message msg) { 465bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown switch (msg.what) { 466bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown case EVENT_DISPLAY_ADDED: 467bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown mListener.onDisplayAdded(msg.arg1); 468bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown break; 469bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown case EVENT_DISPLAY_CHANGED: 470bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown mListener.onDisplayChanged(msg.arg1); 471bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown break; 472bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown case EVENT_DISPLAY_REMOVED: 473bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown mListener.onDisplayRemoved(msg.arg1); 474bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown break; 475bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 476bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 477bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 478c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 47975ee9fcde4d9e1be3883eba6c8d193db4375b052Michael Wright private final static class VirtualDisplayCallback extends IVirtualDisplayCallback.Stub { 48075ee9fcde4d9e1be3883eba6c8d193db4375b052Michael Wright private VirtualDisplayCallbackDelegate mDelegate; 481c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 48275ee9fcde4d9e1be3883eba6c8d193db4375b052Michael Wright public VirtualDisplayCallback(VirtualDisplay.Callback callback, Handler handler) { 48375ee9fcde4d9e1be3883eba6c8d193db4375b052Michael Wright if (callback != null) { 48475ee9fcde4d9e1be3883eba6c8d193db4375b052Michael Wright mDelegate = new VirtualDisplayCallbackDelegate(callback, handler); 4853d0c57a1d3b8eb6bb54045c02c2e93a9313d3cf7Craig Mautner } 486c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 487c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 488c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright @Override // Binder call 48975ee9fcde4d9e1be3883eba6c8d193db4375b052Michael Wright public void onPaused() { 4903d0c57a1d3b8eb6bb54045c02c2e93a9313d3cf7Craig Mautner if (mDelegate != null) { 49175ee9fcde4d9e1be3883eba6c8d193db4375b052Michael Wright mDelegate.sendEmptyMessage(VirtualDisplayCallbackDelegate.MSG_DISPLAY_PAUSED); 4923d0c57a1d3b8eb6bb54045c02c2e93a9313d3cf7Craig Mautner } 493c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 494c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 495c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright @Override // Binder call 49675ee9fcde4d9e1be3883eba6c8d193db4375b052Michael Wright public void onResumed() { 4973d0c57a1d3b8eb6bb54045c02c2e93a9313d3cf7Craig Mautner if (mDelegate != null) { 49875ee9fcde4d9e1be3883eba6c8d193db4375b052Michael Wright mDelegate.sendEmptyMessage(VirtualDisplayCallbackDelegate.MSG_DISPLAY_RESUMED); 4993d0c57a1d3b8eb6bb54045c02c2e93a9313d3cf7Craig Mautner } 500c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 501c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 502c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright @Override // Binder call 50375ee9fcde4d9e1be3883eba6c8d193db4375b052Michael Wright public void onStopped() { 5043d0c57a1d3b8eb6bb54045c02c2e93a9313d3cf7Craig Mautner if (mDelegate != null) { 50575ee9fcde4d9e1be3883eba6c8d193db4375b052Michael Wright mDelegate.sendEmptyMessage(VirtualDisplayCallbackDelegate.MSG_DISPLAY_STOPPED); 5063d0c57a1d3b8eb6bb54045c02c2e93a9313d3cf7Craig Mautner } 507c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 508c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 509c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 51075ee9fcde4d9e1be3883eba6c8d193db4375b052Michael Wright private final static class VirtualDisplayCallbackDelegate extends Handler { 511c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public static final int MSG_DISPLAY_PAUSED = 0; 512c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public static final int MSG_DISPLAY_RESUMED = 1; 513c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public static final int MSG_DISPLAY_STOPPED = 2; 514c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 51575ee9fcde4d9e1be3883eba6c8d193db4375b052Michael Wright private final VirtualDisplay.Callback mCallback; 516c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 51775ee9fcde4d9e1be3883eba6c8d193db4375b052Michael Wright public VirtualDisplayCallbackDelegate(VirtualDisplay.Callback callback, 518c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright Handler handler) { 519c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright super(handler != null ? handler.getLooper() : Looper.myLooper(), null, true /*async*/); 52075ee9fcde4d9e1be3883eba6c8d193db4375b052Michael Wright mCallback = callback; 521c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 522c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 523c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright @Override 524c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public void handleMessage(Message msg) { 525c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright switch (msg.what) { 526c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright case MSG_DISPLAY_PAUSED: 52775ee9fcde4d9e1be3883eba6c8d193db4375b052Michael Wright mCallback.onPaused(); 528c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright break; 529c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright case MSG_DISPLAY_RESUMED: 53075ee9fcde4d9e1be3883eba6c8d193db4375b052Michael Wright mCallback.onResumed(); 531c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright break; 532c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright case MSG_DISPLAY_STOPPED: 53375ee9fcde4d9e1be3883eba6c8d193db4375b052Michael Wright mCallback.onStopped(); 534c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright break; 535c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 536c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 537c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 538bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown} 539