DisplayManagerGlobal.java revision 48d0d1886731ff19ed3fb47a5997be5df0d1bba8
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; 21a506a6ec94863a35acca9feb165db76ddac3892cJeff Brownimport android.os.Binder; 22bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.os.Handler; 23bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.os.IBinder; 24bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.os.Looper; 25bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.os.Message; 26bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.os.RemoteException; 27bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.os.ServiceManager; 28a506a6ec94863a35acca9feb165db76ddac3892cJeff Brownimport android.text.TextUtils; 29bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.util.Log; 30bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.util.SparseArray; 3148d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautnerimport android.view.DisplayAdjustments; 32bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.view.Display; 33bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.view.DisplayInfo; 34a506a6ec94863a35acca9feb165db76ddac3892cJeff Brownimport android.view.Surface; 35bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 36bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport java.util.ArrayList; 37bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 38bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown/** 39bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * Manager communication with the display manager service on behalf of 40bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * an application process. You're probably looking for {@link DisplayManager}. 41bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * 42bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * @hide 43bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown */ 44bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownpublic final class DisplayManagerGlobal { 45bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private static final String TAG = "DisplayManager"; 46bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private static final boolean DEBUG = false; 47bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 484ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown // True if display info and display ids should be cached. 494ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown // 504ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown // FIXME: The cache is currently disabled because it's unclear whether we have the 514ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown // necessary guarantees that the caches will always be flushed before clients 524ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown // attempt to observe their new state. For example, depending on the order 534ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown // in which the binder transactions take place, we might have a problem where 544ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown // an application could start processing a configuration change due to a display 554ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown // orientation change before the display info cache has actually been invalidated. 564ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown private static final boolean USE_CACHE = false; 574ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 58bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public static final int EVENT_DISPLAY_ADDED = 1; 59bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public static final int EVENT_DISPLAY_CHANGED = 2; 60bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public static final int EVENT_DISPLAY_REMOVED = 3; 61bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 62bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private static DisplayManagerGlobal sInstance; 63bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 64bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private final Object mLock = new Object(); 65bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 66bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private final IDisplayManager mDm; 67bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 68bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private DisplayManagerCallback mCallback; 69bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private final ArrayList<DisplayListenerDelegate> mDisplayListeners = 70bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown new ArrayList<DisplayListenerDelegate>(); 71bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 72bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private final SparseArray<DisplayInfo> mDisplayInfoCache = new SparseArray<DisplayInfo>(); 73bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private int[] mDisplayIdCache; 74bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 75bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private DisplayManagerGlobal(IDisplayManager dm) { 76bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown mDm = dm; 77bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 78bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 79bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown /** 80bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * Gets an instance of the display manager global singleton. 81bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * 82bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * @return The display manager instance, may be null early in system startup 83bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * before the display manager has been fully initialized. 84bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown */ 85bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public static DisplayManagerGlobal getInstance() { 86bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown synchronized (DisplayManagerGlobal.class) { 87bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (sInstance == null) { 88bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown IBinder b = ServiceManager.getService(Context.DISPLAY_SERVICE); 89bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (b != null) { 90bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown sInstance = new DisplayManagerGlobal(IDisplayManager.Stub.asInterface(b)); 91bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 92bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 93bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown return sInstance; 94bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 95bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 96bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 97bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown /** 98bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * Get information about a particular logical display. 99bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * 100bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * @param displayId The logical display id. 101bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * @return Information about the specified display, or null if it does not exist. 102bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * This object belongs to an internal cache and should be treated as if it were immutable. 103bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown */ 104bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public DisplayInfo getDisplayInfo(int displayId) { 105bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown try { 106bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown synchronized (mLock) { 1074ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown DisplayInfo info; 1084ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (USE_CACHE) { 1094ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown info = mDisplayInfoCache.get(displayId); 1104ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (info != null) { 1114ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown return info; 1124ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 113bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 114bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 115bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown info = mDm.getDisplayInfo(displayId); 116bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (info == null) { 117bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown return null; 118bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 1194ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 1204ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (USE_CACHE) { 1214ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mDisplayInfoCache.put(displayId, info); 1224ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 1234ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown registerCallbackIfNeededLocked(); 1244ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 125bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (DEBUG) { 126bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown Log.d(TAG, "getDisplayInfo: displayId=" + displayId + ", info=" + info); 127bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 128bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown return info; 129bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 130bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } catch (RemoteException ex) { 131bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown Log.e(TAG, "Could not get display information from display manager.", ex); 132bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown return null; 133bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 134bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 135bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 136bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown /** 137bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * Gets all currently valid logical display ids. 138bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * 139bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * @return An array containing all display ids. 140bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown */ 141bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public int[] getDisplayIds() { 142bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown try { 143bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown synchronized (mLock) { 1444ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (USE_CACHE) { 1454ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (mDisplayIdCache != null) { 1464ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown return mDisplayIdCache; 1474ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 1484ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 1494ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 1504ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown int[] displayIds = mDm.getDisplayIds(); 1514ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (USE_CACHE) { 1524ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mDisplayIdCache = displayIds; 153bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 1544ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown registerCallbackIfNeededLocked(); 1554ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown return displayIds; 156bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 157bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } catch (RemoteException ex) { 158bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown Log.e(TAG, "Could not get display ids from display manager.", ex); 159bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown return new int[] { Display.DEFAULT_DISPLAY }; 160bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 161bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 162bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 163bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown /** 164bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * Gets information about a logical display. 165bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * 166bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * The display metrics may be adjusted to provide compatibility 16748d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner * for legacy applications or limited screen areas. 168bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * 169bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * @param displayId The logical display id. 17048d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner * @param daj The compatibility info and activityToken. 171bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * @return The display object, or null if there is no display with the given id. 172bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown */ 17348d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner public Display getCompatibleDisplay(int displayId, DisplayAdjustments daj) { 174bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown DisplayInfo displayInfo = getDisplayInfo(displayId); 175bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (displayInfo == null) { 176bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown return null; 177bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 17848d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner return new Display(this, displayId, displayInfo, daj); 179bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 180bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 181bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown /** 182bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * Gets information about a logical display without applying any compatibility metrics. 183bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * 184bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * @param displayId The logical display id. 185bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * @return The display object, or null if there is no display with the given id. 186bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown */ 187bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public Display getRealDisplay(int displayId) { 18848d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner return getCompatibleDisplay(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS); 18948d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner } 19048d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner 19148d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner /** 19248d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner * Gets information about a logical display without applying any compatibility metrics. 19348d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner * 19448d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner * @param displayId The logical display id. 19548d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner * @param IBinder the activity token for this display. 19648d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner * @return The display object, or null if there is no display with the given id. 19748d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner */ 19848d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner public Display getRealDisplay(int displayId, IBinder token) { 19948d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner return getCompatibleDisplay(displayId, new DisplayAdjustments(token)); 200bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 201bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 202bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public void registerDisplayListener(DisplayListener listener, Handler handler) { 203bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (listener == null) { 204bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown throw new IllegalArgumentException("listener must not be null"); 205bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 206bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 207bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown synchronized (mLock) { 208bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown int index = findDisplayListenerLocked(listener); 209bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (index < 0) { 210bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown mDisplayListeners.add(new DisplayListenerDelegate(listener, handler)); 211bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown registerCallbackIfNeededLocked(); 212bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 213bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 214bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 215bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 216bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public void unregisterDisplayListener(DisplayListener listener) { 217bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (listener == null) { 218bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown throw new IllegalArgumentException("listener must not be null"); 219bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 220bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 221bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown synchronized (mLock) { 222bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown int index = findDisplayListenerLocked(listener); 223bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (index >= 0) { 224bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown DisplayListenerDelegate d = mDisplayListeners.get(index); 225bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown d.clearEvents(); 226bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown mDisplayListeners.remove(index); 227bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 228bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 229bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 230bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 231bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private int findDisplayListenerLocked(DisplayListener listener) { 232bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown final int numListeners = mDisplayListeners.size(); 233bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown for (int i = 0; i < numListeners; i++) { 234bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (mDisplayListeners.get(i).mListener == listener) { 235bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown return i; 236bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 237bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 238bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown return -1; 239bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 240bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 241bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private void registerCallbackIfNeededLocked() { 242bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (mCallback == null) { 243bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown mCallback = new DisplayManagerCallback(); 244bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown try { 245bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown mDm.registerCallback(mCallback); 246bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } catch (RemoteException ex) { 247bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown Log.e(TAG, "Failed to register callback with display manager service.", ex); 248bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown mCallback = null; 249bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 250bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 251bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 252bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 253bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private void handleDisplayEvent(int displayId, int event) { 254bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown synchronized (mLock) { 2554ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (USE_CACHE) { 2564ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mDisplayInfoCache.remove(displayId); 257bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 2584ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (event == EVENT_DISPLAY_ADDED || event == EVENT_DISPLAY_REMOVED) { 2594ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mDisplayIdCache = null; 2604ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 261bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 262bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 263bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown final int numListeners = mDisplayListeners.size(); 264bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown for (int i = 0; i < numListeners; i++) { 265bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown mDisplayListeners.get(i).sendDisplayEvent(displayId, event); 266bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 267bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 268bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 269bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 270e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void scanWifiDisplays() { 271e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown try { 272e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mDm.scanWifiDisplays(); 273e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } catch (RemoteException ex) { 274e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown Log.e(TAG, "Failed to scan for Wifi displays.", ex); 275e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 276e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 277e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 278e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void connectWifiDisplay(String deviceAddress) { 279e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (deviceAddress == null) { 280e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown throw new IllegalArgumentException("deviceAddress must not be null"); 281e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 282e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 283e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown try { 284e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mDm.connectWifiDisplay(deviceAddress); 285e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } catch (RemoteException ex) { 286e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown Log.e(TAG, "Failed to connect to Wifi display " + deviceAddress + ".", ex); 287e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 288e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 289e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 290e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void disconnectWifiDisplay() { 291e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown try { 292e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mDm.disconnectWifiDisplay(); 293e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } catch (RemoteException ex) { 294e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown Log.e(TAG, "Failed to disconnect from Wifi display.", ex); 295e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 296e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 297e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 29889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void renameWifiDisplay(String deviceAddress, String alias) { 29989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (deviceAddress == null) { 30089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown throw new IllegalArgumentException("deviceAddress must not be null"); 30189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 30289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 30389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown try { 30489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mDm.renameWifiDisplay(deviceAddress, alias); 30589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } catch (RemoteException ex) { 30689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown Log.e(TAG, "Failed to rename Wifi display " + deviceAddress 30789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown + " with alias " + alias + ".", ex); 30889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 30989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 31089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 31189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void forgetWifiDisplay(String deviceAddress) { 31289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (deviceAddress == null) { 31389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown throw new IllegalArgumentException("deviceAddress must not be null"); 31489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 31589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 31689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown try { 31789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mDm.forgetWifiDisplay(deviceAddress); 31889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } catch (RemoteException ex) { 31989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown Log.e(TAG, "Failed to forget Wifi display.", ex); 32089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 32189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 32289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 323e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public WifiDisplayStatus getWifiDisplayStatus() { 324e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown try { 325e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown return mDm.getWifiDisplayStatus(); 326e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } catch (RemoteException ex) { 327e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown Log.e(TAG, "Failed to get Wifi display status.", ex); 328e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown return new WifiDisplayStatus(); 329e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 330e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 331e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 332a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown public VirtualDisplay createPrivateVirtualDisplay(Context context, String name, 333a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown int width, int height, int densityDpi, Surface surface) { 334a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown if (TextUtils.isEmpty(name)) { 335a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown throw new IllegalArgumentException("name must be non-null and non-empty"); 336a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } 337a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown if (width <= 0 || height <= 0 || densityDpi <= 0) { 338a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown throw new IllegalArgumentException("width, height, and densityDpi must be " 339a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown + "greater than 0"); 340a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } 341a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown if (surface == null) { 342a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown throw new IllegalArgumentException("surface must not be null"); 343a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } 344a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown 345a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown Binder token = new Binder(); 346a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown int displayId; 347a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown try { 348a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown displayId = mDm.createPrivateVirtualDisplay(token, context.getPackageName(), 349a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown name, width, height, densityDpi, surface); 350a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } catch (RemoteException ex) { 351a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown Log.e(TAG, "Could not create private virtual display: " + name, ex); 352a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown return null; 353a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } 354a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown if (displayId < 0) { 355a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown Log.e(TAG, "Could not create private virtual display: " + name); 356a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown return null; 357a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } 358a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown Display display = getRealDisplay(displayId); 359a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown if (display == null) { 360a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown Log.wtf(TAG, "Could not obtain display info for newly created " 361a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown + "private virtual display: " + name); 362a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown try { 363a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown mDm.releaseVirtualDisplay(token); 364a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } catch (RemoteException ex) { 365a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } 366a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown return null; 367a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } 368a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown return new VirtualDisplay(this, display, token); 369a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } 370a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown 371a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown public void releaseVirtualDisplay(IBinder token) { 372a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown try { 373a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown mDm.releaseVirtualDisplay(token); 374a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } catch (RemoteException ex) { 375a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown Log.w(TAG, "Failed to release virtual display.", ex); 376a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } 377a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown } 378a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown 379bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub { 380bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown @Override 381bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public void onDisplayEvent(int displayId, int event) { 382bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown if (DEBUG) { 383bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown Log.d(TAG, "onDisplayEvent: displayId=" + displayId + ", event=" + event); 384bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 385bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown handleDisplayEvent(displayId, event); 386bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 387bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 388bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 389bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private static final class DisplayListenerDelegate extends Handler { 390bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public final DisplayListener mListener; 391bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 392bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public DisplayListenerDelegate(DisplayListener listener, Handler handler) { 393bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown super(handler != null ? handler.getLooper() : Looper.myLooper(), null, true /*async*/); 394bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown mListener = listener; 395bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 396bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 397bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public void sendDisplayEvent(int displayId, int event) { 398bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown Message msg = obtainMessage(event, displayId, 0); 399bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown sendMessage(msg); 400bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 401bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 402bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public void clearEvents() { 403bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown removeCallbacksAndMessages(null); 404bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 405bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown 406bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown @Override 407bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown public void handleMessage(Message msg) { 408bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown switch (msg.what) { 409bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown case EVENT_DISPLAY_ADDED: 410bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown mListener.onDisplayAdded(msg.arg1); 411bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown break; 412bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown case EVENT_DISPLAY_CHANGED: 413bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown mListener.onDisplayChanged(msg.arg1); 414bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown break; 415bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown case EVENT_DISPLAY_REMOVED: 416bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown mListener.onDisplayRemoved(msg.arg1); 417bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown break; 418bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 419bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 420bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 421bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown} 422