diff options
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/app/ActivityManager.java | 4 | ||||
| -rw-r--r-- | core/java/android/app/ActivityThread.java | 3 | ||||
| -rw-r--r-- | core/java/android/app/ContextImpl.java | 9 | ||||
| -rw-r--r-- | core/java/android/hardware/display/DisplayManager.java | 206 | ||||
| -rw-r--r-- | core/java/android/hardware/display/DisplayManagerGlobal.java | 273 | ||||
| -rw-r--r-- | core/java/android/hardware/display/IDisplayManager.aidl | 6 | ||||
| -rw-r--r-- | core/java/android/hardware/display/IDisplayManagerCallback.aidl | 22 | ||||
| -rw-r--r-- | core/java/android/provider/Settings.java | 19 | ||||
| -rw-r--r-- | core/java/android/view/Choreographer.java | 10 | ||||
| -rw-r--r-- | core/java/android/view/Display.java | 63 | ||||
| -rw-r--r-- | core/java/android/view/DisplayInfo.java | 4 | ||||
| -rw-r--r-- | core/java/android/view/View.java | 5 | ||||
| -rw-r--r-- | core/java/android/view/WindowManager.java | 9 | ||||
| -rw-r--r-- | core/java/android/view/WindowManagerImpl.java | 3 |
14 files changed, 467 insertions, 169 deletions
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index e644db46e295..f8a9d75f2e30 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -31,6 +31,7 @@ import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Point; import android.hardware.display.DisplayManager; +import android.hardware.display.DisplayManagerGlobal; import android.os.Binder; import android.os.Bundle; import android.os.Debug; @@ -376,7 +377,8 @@ public class ActivityManager { return true; } - Display display = DisplayManager.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY); + Display display = DisplayManagerGlobal.getInstance().getRealDisplay( + Display.DEFAULT_DISPLAY); Point p = new Point(); display.getRealSize(p); int pixels = p.x * p.y; diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index b8e16c5a7cc9..4a1bf7523dd7 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -43,6 +43,7 @@ import android.database.sqlite.SQLiteDebug.DbStats; import android.graphics.Bitmap; import android.graphics.Canvas; import android.hardware.display.DisplayManager; +import android.hardware.display.DisplayManagerGlobal; import android.net.IConnectivityManager; import android.net.Proxy; import android.net.ProxyProperties; @@ -1557,7 +1558,7 @@ public final class ActivityThread { return dm; } - DisplayManager displayManager = DisplayManager.getInstance(); + DisplayManagerGlobal displayManager = DisplayManagerGlobal.getInstance(); if (displayManager == null) { // may be null early in system startup dm = new DisplayMetrics(); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 32086d736357..efe4b7b4e017 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -349,10 +349,11 @@ class ContextImpl extends Context { return InputManager.getInstance(); }}); - registerService(DISPLAY_SERVICE, new StaticServiceFetcher() { - public Object createStaticService() { - return DisplayManager.getInstance(); - }}); + registerService(DISPLAY_SERVICE, new ServiceFetcher() { + @Override + public Object createService(ContextImpl ctx) { + return new DisplayManager(ctx.getOuterContext()); + }}); registerService(INPUT_METHOD_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index 98d2f69ee226..74996da1ed1b 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -18,20 +18,12 @@ package android.hardware.display; import android.content.Context; import android.os.Handler; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.util.Log; +import android.util.SparseArray; import android.view.CompatibilityInfoHolder; import android.view.Display; -import android.view.DisplayInfo; - -import java.util.ArrayList; /** - * Manages the properties, media routing and power state of attached displays. + * Manages the properties of attached displays. * <p> * Get an instance of this class by calling * {@link android.content.Context#getSystemService(java.lang.String) @@ -43,110 +35,79 @@ public final class DisplayManager { private static final String TAG = "DisplayManager"; private static final boolean DEBUG = false; - private static final int MSG_DISPLAY_ADDED = 1; - private static final int MSG_DISPLAY_REMOVED = 2; - private static final int MSG_DISPLAY_CHANGED = 3; - - private static DisplayManager sInstance; - - private final IDisplayManager mDm; - - // Guarded by mDisplayLock - private final Object mDisplayLock = new Object(); - private final ArrayList<DisplayListenerDelegate> mDisplayListeners = - new ArrayList<DisplayListenerDelegate>(); + private final Context mContext; + private final DisplayManagerGlobal mGlobal; + private final Object mLock = new Object(); + private final SparseArray<Display> mDisplays = new SparseArray<Display>(); - private DisplayManager(IDisplayManager dm) { - mDm = dm; + /** @hide */ + public DisplayManager(Context context) { + mContext = context; + mGlobal = DisplayManagerGlobal.getInstance(); } /** - * Gets an instance of the display manager. + * Gets information about a logical display. * - * @return The display manager instance, may be null early in system startup - * before the display manager has been fully initialized. + * The display metrics may be adjusted to provide compatibility + * for legacy applications. * - * @hide + * @param displayId The logical display id. + * @return The display object, or null if there is no valid display with the given id. */ - public static DisplayManager getInstance() { - synchronized (DisplayManager.class) { - if (sInstance == null) { - IBinder b = ServiceManager.getService(Context.DISPLAY_SERVICE); - if (b != null) { - sInstance = new DisplayManager(IDisplayManager.Stub.asInterface(b)); - } - } - return sInstance; + public Display getDisplay(int displayId) { + synchronized (mLock) { + return getOrCreateDisplayLocked(displayId, false /*assumeValid*/); } } /** - * Get information about a particular logical display. + * Gets all currently valid logical displays. * - * @param displayId The logical display id. - * @param outInfo A structure to populate with the display info. - * @return True if the logical display exists, false otherwise. - * @hide + * @return An array containing all displays. */ - public boolean getDisplayInfo(int displayId, DisplayInfo outInfo) { - try { - return mDm.getDisplayInfo(displayId, outInfo); - } catch (RemoteException ex) { - Log.e(TAG, "Could not get display information from display manager.", ex); - return false; + public Display[] getDisplays() { + int[] displayIds = mGlobal.getDisplayIds(); + int expectedCount = displayIds.length; + Display[] displays = new Display[expectedCount]; + synchronized (mLock) { + int actualCount = 0; + for (int i = 0; i < expectedCount; i++) { + Display display = getOrCreateDisplayLocked(displayIds[i], true /*assumeValid*/); + if (display != null) { + displays[actualCount++] = display; + } + } + if (actualCount != expectedCount) { + Display[] oldDisplays = displays; + displays = new Display[actualCount]; + System.arraycopy(oldDisplays, 0, displays, 0, actualCount); + } } + return displays; } - /** - * Gets information about a logical display. - * - * The display metrics may be adjusted to provide compatibility - * for legacy applications. - * - * @param displayId The logical display id. - * @param applicationContext The application context from which to obtain - * compatible metrics. - * @return The display object. - */ - public Display getDisplay(int displayId, Context applicationContext) { - if (applicationContext == null) { - throw new IllegalArgumentException("applicationContext must not be null"); + private Display getOrCreateDisplayLocked(int displayId, boolean assumeValid) { + Display display = mDisplays.get(displayId); + if (display == null) { + display = mGlobal.getCompatibleDisplay(displayId, + getCompatibilityInfoForDisplayLocked(displayId)); + if (display != null) { + mDisplays.put(displayId, display); + } + } else if (!assumeValid && !display.isValid()) { + display = null; } + return display; + } + private CompatibilityInfoHolder getCompatibilityInfoForDisplayLocked(int displayId) { CompatibilityInfoHolder cih = null; if (displayId == Display.DEFAULT_DISPLAY) { - cih = applicationContext.getCompatibilityInfo(); + cih = mContext.getCompatibilityInfo(); } - return getCompatibleDisplay(displayId, cih); - } - - /** - * Gets information about a logical display. - * - * The display metrics may be adjusted to provide compatibility - * for legacy applications. - * - * @param displayId The logical display id. - * @param cih The compatibility info, or null if none is required. - * @return The display object. - * - * @hide - */ - public Display getCompatibleDisplay(int displayId, CompatibilityInfoHolder cih) { - return new Display(displayId, cih); - } - - /** - * Gets information about a logical display without applying any compatibility metrics. - * - * @param displayId The logical display id. - * @return The display object. - * - * @hide - */ - public Display getRealDisplay(int displayId) { - return getCompatibleDisplay(displayId, null); + return cih; } /** @@ -160,16 +121,7 @@ public final class DisplayManager { * @see #unregisterDisplayListener */ public void registerDisplayListener(DisplayListener listener, Handler handler) { - if (listener == null) { - throw new IllegalArgumentException("listener must not be null"); - } - - synchronized (mDisplayLock) { - int index = findDisplayListenerLocked(listener); - if (index < 0) { - mDisplayListeners.add(new DisplayListenerDelegate(listener, handler)); - } - } + mGlobal.registerDisplayListener(listener, handler); } /** @@ -180,28 +132,7 @@ public final class DisplayManager { * @see #registerDisplayListener */ public void unregisterDisplayListener(DisplayListener listener) { - if (listener == null) { - throw new IllegalArgumentException("listener must not be null"); - } - - synchronized (mDisplayLock) { - int index = findDisplayListenerLocked(listener); - if (index >= 0) { - DisplayListenerDelegate d = mDisplayListeners.get(index); - d.removeCallbacksAndMessages(null); - mDisplayListeners.remove(index); - } - } - } - - private int findDisplayListenerLocked(DisplayListener listener) { - final int numListeners = mDisplayListeners.size(); - for (int i = 0; i < numListeners; i++) { - if (mDisplayListeners.get(i).mListener == listener) { - return i; - } - } - return -1; + mGlobal.unregisterDisplayListener(listener); } /** @@ -210,7 +141,8 @@ public final class DisplayManager { public interface DisplayListener { /** * Called whenever a logical display has been added to the system. - * Use {@link DisplayManager#getDisplay} to get more information about the display. + * Use {@link DisplayManager#getDisplay} to get more information about + * the display. * * @param displayId The id of the logical display that was added. */ @@ -230,28 +162,4 @@ public final class DisplayManager { */ void onDisplayChanged(int displayId); } - - private static final class DisplayListenerDelegate extends Handler { - public final DisplayListener mListener; - - public DisplayListenerDelegate(DisplayListener listener, Handler handler) { - super(handler != null ? handler.getLooper() : Looper.myLooper()); - mListener = listener; - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_DISPLAY_ADDED: - mListener.onDisplayAdded(msg.arg1); - break; - case MSG_DISPLAY_REMOVED: - mListener.onDisplayRemoved(msg.arg1); - break; - case MSG_DISPLAY_CHANGED: - mListener.onDisplayChanged(msg.arg1); - break; - } - } - } } diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java new file mode 100644 index 000000000000..69c0319dc7bf --- /dev/null +++ b/core/java/android/hardware/display/DisplayManagerGlobal.java @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.display; + +import android.content.Context; +import android.hardware.display.DisplayManager.DisplayListener; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Log; +import android.util.SparseArray; +import android.view.CompatibilityInfoHolder; +import android.view.Display; +import android.view.DisplayInfo; + +import java.util.ArrayList; + +/** + * Manager communication with the display manager service on behalf of + * an application process. You're probably looking for {@link DisplayManager}. + * + * @hide + */ +public final class DisplayManagerGlobal { + private static final String TAG = "DisplayManager"; + private static final boolean DEBUG = false; + + public static final int EVENT_DISPLAY_ADDED = 1; + public static final int EVENT_DISPLAY_CHANGED = 2; + public static final int EVENT_DISPLAY_REMOVED = 3; + + private static DisplayManagerGlobal sInstance; + + private final Object mLock = new Object(); + + private final IDisplayManager mDm; + + private DisplayManagerCallback mCallback; + private final ArrayList<DisplayListenerDelegate> mDisplayListeners = + new ArrayList<DisplayListenerDelegate>(); + + private final SparseArray<DisplayInfo> mDisplayInfoCache = new SparseArray<DisplayInfo>(); + private int[] mDisplayIdCache; + + private DisplayManagerGlobal(IDisplayManager dm) { + mDm = dm; + } + + /** + * Gets an instance of the display manager global singleton. + * + * @return The display manager instance, may be null early in system startup + * before the display manager has been fully initialized. + */ + public static DisplayManagerGlobal getInstance() { + synchronized (DisplayManagerGlobal.class) { + if (sInstance == null) { + IBinder b = ServiceManager.getService(Context.DISPLAY_SERVICE); + if (b != null) { + sInstance = new DisplayManagerGlobal(IDisplayManager.Stub.asInterface(b)); + } + } + return sInstance; + } + } + + /** + * Get information about a particular logical display. + * + * @param displayId The logical display id. + * @return Information about the specified display, or null if it does not exist. + * This object belongs to an internal cache and should be treated as if it were immutable. + */ + public DisplayInfo getDisplayInfo(int displayId) { + try { + synchronized (mLock) { + DisplayInfo info = mDisplayInfoCache.get(displayId); + if (info != null) { + return info; + } + + info = mDm.getDisplayInfo(displayId); + if (info == null) { + return null; + } + if (DEBUG) { + Log.d(TAG, "getDisplayInfo: displayId=" + displayId + ", info=" + info); + } + + mDisplayInfoCache.put(displayId, info); + registerCallbackIfNeededLocked(); + return info; + } + } catch (RemoteException ex) { + Log.e(TAG, "Could not get display information from display manager.", ex); + return null; + } + } + + /** + * Gets all currently valid logical display ids. + * + * @return An array containing all display ids. + */ + public int[] getDisplayIds() { + try { + synchronized (mLock) { + if (mDisplayIdCache == null) { + mDisplayIdCache = mDm.getDisplayIds(); + registerCallbackIfNeededLocked(); + } + return mDisplayIdCache; + } + } catch (RemoteException ex) { + Log.e(TAG, "Could not get display ids from display manager.", ex); + return new int[] { Display.DEFAULT_DISPLAY }; + } + } + + /** + * Gets information about a logical display. + * + * The display metrics may be adjusted to provide compatibility + * for legacy applications. + * + * @param displayId The logical display id. + * @param cih The compatibility info, or null if none is required. + * @return The display object, or null if there is no display with the given id. + */ + public Display getCompatibleDisplay(int displayId, CompatibilityInfoHolder cih) { + DisplayInfo displayInfo = getDisplayInfo(displayId); + if (displayInfo == null) { + return null; + } + return new Display(this, displayId, displayInfo, cih); + } + + /** + * Gets information about a logical display without applying any compatibility metrics. + * + * @param displayId The logical display id. + * @return The display object, or null if there is no display with the given id. + */ + public Display getRealDisplay(int displayId) { + return getCompatibleDisplay(displayId, null); + } + + public void registerDisplayListener(DisplayListener listener, Handler handler) { + if (listener == null) { + throw new IllegalArgumentException("listener must not be null"); + } + + synchronized (mLock) { + int index = findDisplayListenerLocked(listener); + if (index < 0) { + mDisplayListeners.add(new DisplayListenerDelegate(listener, handler)); + registerCallbackIfNeededLocked(); + } + } + } + + public void unregisterDisplayListener(DisplayListener listener) { + if (listener == null) { + throw new IllegalArgumentException("listener must not be null"); + } + + synchronized (mLock) { + int index = findDisplayListenerLocked(listener); + if (index >= 0) { + DisplayListenerDelegate d = mDisplayListeners.get(index); + d.clearEvents(); + mDisplayListeners.remove(index); + } + } + } + + private int findDisplayListenerLocked(DisplayListener listener) { + final int numListeners = mDisplayListeners.size(); + for (int i = 0; i < numListeners; i++) { + if (mDisplayListeners.get(i).mListener == listener) { + return i; + } + } + return -1; + } + + private void registerCallbackIfNeededLocked() { + if (mCallback == null) { + mCallback = new DisplayManagerCallback(); + try { + mDm.registerCallback(mCallback); + } catch (RemoteException ex) { + Log.e(TAG, "Failed to register callback with display manager service.", ex); + mCallback = null; + } + } + } + + private void handleDisplayEvent(int displayId, int event) { + synchronized (mLock) { + mDisplayInfoCache.remove(displayId); + + if (event == EVENT_DISPLAY_ADDED || event == EVENT_DISPLAY_REMOVED) { + mDisplayIdCache = null; + } + + final int numListeners = mDisplayListeners.size(); + for (int i = 0; i < numListeners; i++) { + mDisplayListeners.get(i).sendDisplayEvent(displayId, event); + } + } + } + + private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub { + @Override + public void onDisplayEvent(int displayId, int event) { + if (DEBUG) { + Log.d(TAG, "onDisplayEvent: displayId=" + displayId + ", event=" + event); + } + handleDisplayEvent(displayId, event); + } + } + + private static final class DisplayListenerDelegate extends Handler { + public final DisplayListener mListener; + + public DisplayListenerDelegate(DisplayListener listener, Handler handler) { + super(handler != null ? handler.getLooper() : Looper.myLooper(), null, true /*async*/); + mListener = listener; + } + + public void sendDisplayEvent(int displayId, int event) { + Message msg = obtainMessage(event, displayId, 0); + sendMessage(msg); + } + + public void clearEvents() { + removeCallbacksAndMessages(null); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case EVENT_DISPLAY_ADDED: + mListener.onDisplayAdded(msg.arg1); + break; + case EVENT_DISPLAY_CHANGED: + mListener.onDisplayChanged(msg.arg1); + break; + case EVENT_DISPLAY_REMOVED: + mListener.onDisplayRemoved(msg.arg1); + break; + } + } + } +} diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl index fd8c35f8d614..d802aa16d6a5 100644 --- a/core/java/android/hardware/display/IDisplayManager.aidl +++ b/core/java/android/hardware/display/IDisplayManager.aidl @@ -16,9 +16,13 @@ package android.hardware.display; +import android.hardware.display.IDisplayManagerCallback; import android.view.DisplayInfo; /** @hide */ interface IDisplayManager { - boolean getDisplayInfo(int displayId, out DisplayInfo outInfo); + DisplayInfo getDisplayInfo(int displayId); + int[] getDisplayIds(); + + void registerCallback(in IDisplayManagerCallback callback); } diff --git a/core/java/android/hardware/display/IDisplayManagerCallback.aidl b/core/java/android/hardware/display/IDisplayManagerCallback.aidl new file mode 100644 index 000000000000..c50e3fb26156 --- /dev/null +++ b/core/java/android/hardware/display/IDisplayManagerCallback.aidl @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.display; + +/** @hide */ +interface IDisplayManagerCallback { + oneway void onDisplayEvent(int displayId, int event); +} diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 6f43891a88b6..b4841b18bb77 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -4351,6 +4351,25 @@ public final class Settings { public static final String SMS_SHORT_CODES_PREFIX = "sms_short_codes_"; /** + * Overlay display devices setting. + * The associated value is a specially formatted string that describes the + * size and density of simulated secondary display devices. + * <p> + * Format: {width}x{height}/{dpi};... + * </p><p> + * Example: + * <ul> + * <li><code>1280x720/213</code>: make one overlay that is 1280x720 at 213dpi.</li> + * <li><code>1920x1080/320;1280x720/213</code>: make two overlays, the first + * at 1080p and the second at 720p.</li> + * <li>If the value is empty, then no overlay display devices are created.</li> + * </ul></p> + * + * @hide + */ + public static final String OVERLAY_DISPLAY_DEVICES = "overlay_display_devices"; + + /** * This are the settings to be backed up. * * NOTE: Settings are backed up and restored in the order they appear diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java index 392d1f2dd19e..6848606c758a 100644 --- a/core/java/android/view/Choreographer.java +++ b/core/java/android/view/Choreographer.java @@ -17,6 +17,7 @@ package android.view; import android.hardware.display.DisplayManager; +import android.hardware.display.DisplayManagerGlobal; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -166,8 +167,7 @@ public final class Choreographer { mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper) : null; mLastFrameTimeNanos = Long.MIN_VALUE; - Display d = DisplayManager.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY); - mFrameIntervalNanos = (long)(1000000000 / d.getRefreshRate()); + mFrameIntervalNanos = (long)(1000000000 / getRefreshRate()); mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1]; for (int i = 0; i <= CALLBACK_LAST; i++) { @@ -175,6 +175,12 @@ public final class Choreographer { } } + private static float getRefreshRate() { + DisplayInfo di = DisplayManagerGlobal.getInstance().getDisplayInfo( + Display.DEFAULT_DISPLAY); + return di.refreshRate; + } + /** * Gets the choreographer for the calling thread. Must be called from * a thread that already has a {@link android.os.Looper} associated with it. diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index 6f8ca13f1c76..ec635a2156fe 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -19,7 +19,7 @@ package android.view; import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.Rect; -import android.hardware.display.DisplayManager; +import android.hardware.display.DisplayManagerGlobal; import android.os.SystemClock; import android.util.DisplayMetrics; import android.util.Log; @@ -49,10 +49,14 @@ import android.util.Log; */ public final class Display { private static final String TAG = "Display"; + private static final boolean DEBUG = false; + private final DisplayManagerGlobal mGlobal; private final int mDisplayId; private final CompatibilityInfoHolder mCompatibilityInfo; - private final DisplayInfo mDisplayInfo = new DisplayInfo(); + + private DisplayInfo mDisplayInfo; // never null + private boolean mIsValid; // Temporary display metrics structure used for compatibility mode. private final DisplayMetrics mTempMetrics = new DisplayMetrics(); @@ -80,9 +84,14 @@ public final class Display { * * @hide */ - public Display(int displayId, CompatibilityInfoHolder compatibilityInfo) { + public Display(DisplayManagerGlobal global, + int displayId, DisplayInfo displayInfo /*not null*/, + CompatibilityInfoHolder compatibilityInfo) { + mGlobal = global; mDisplayId = displayId; + mDisplayInfo = displayInfo; mCompatibilityInfo = compatibilityInfo; + mIsValid = true; } /** @@ -97,15 +106,37 @@ public final class Display { } /** + * Returns true if this display is still valid, false if the display has been removed. + * + * If the display is invalid, then the methods of this class will + * continue to report the most recently observed display information. + * However, it is unwise (and rather fruitless) to continue using a + * {@link Display} object after the display's demise. + * + * It's possible for a display that was previously invalid to become + * valid again if a display with the same id is reconnected. + * + * @return True if the display is still valid. + */ + public boolean isValid() { + synchronized (this) { + updateDisplayInfoLocked(); + return mIsValid; + } + } + + /** * Gets a full copy of the display information. * * @param outDisplayInfo The object to receive the copy of the display information. + * @return True if the display is still valid. * @hide */ - public void getDisplayInfo(DisplayInfo outDisplayInfo) { + public boolean getDisplayInfo(DisplayInfo outDisplayInfo) { synchronized (this) { updateDisplayInfoLocked(); outDisplayInfo.copyFrom(mDisplayInfo); + return mIsValid; } } @@ -366,9 +397,25 @@ public final class Display { } private void updateDisplayInfoLocked() { - // TODO: only refresh the display information when needed - if (!DisplayManager.getInstance().getDisplayInfo(mDisplayId, mDisplayInfo)) { - Log.e(TAG, "Could not get information about logical display " + mDisplayId); + // Note: The display manager caches display info objects on our behalf. + DisplayInfo newInfo = mGlobal.getDisplayInfo(mDisplayId); + if (newInfo == null) { + // Preserve the old mDisplayInfo after the display is removed. + if (mIsValid) { + mIsValid = false; + if (DEBUG) { + Log.d(TAG, "Logical display " + mDisplayId + " was removed."); + } + } + } else { + // Use the new display info. (It might be the same object if nothing changed.) + mDisplayInfo = newInfo; + if (!mIsValid) { + mIsValid = true; + if (DEBUG) { + Log.d(TAG, "Logical display " + mDisplayId + " was recreated."); + } + } } } @@ -390,7 +437,7 @@ public final class Display { updateDisplayInfoLocked(); mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo); return "Display id " + mDisplayId + ": " + mDisplayInfo - + ", " + mTempMetrics; + + ", " + mTempMetrics + ", isValid=" + mIsValid; } } } diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java index e38f245be92b..593e8c4700f0 100644 --- a/core/java/android/view/DisplayInfo.java +++ b/core/java/android/view/DisplayInfo.java @@ -138,6 +138,10 @@ public final class DisplayInfo implements Parcelable { public DisplayInfo() { } + public DisplayInfo(DisplayInfo other) { + copyFrom(other); + } + private DisplayInfo(Parcel source) { readFromParcel(source); } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 44f39de31497..6ce73e168f25 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -40,6 +40,7 @@ import android.graphics.Shader; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.hardware.display.DisplayManager; +import android.hardware.display.DisplayManagerGlobal; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -7359,7 +7360,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, outRect.bottom -= insets.bottom; return; } - Display d = DisplayManager.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY); + // The view is not attached to a display so we don't have a context. + // Make a best guess about the display size. + Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY); d.getRectSize(outRect); } diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 123d9e76071b..51503fd71861 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -179,7 +179,8 @@ public interface WindowManager extends ViewManager { @ViewDebug.IntToString(from = TYPE_BOOT_PROGRESS, to = "TYPE_BOOT_PROGRESS"), @ViewDebug.IntToString(from = TYPE_HIDDEN_NAV_CONSUMER, to = "TYPE_HIDDEN_NAV_CONSUMER"), @ViewDebug.IntToString(from = TYPE_DREAM, to = "TYPE_DREAM"), - @ViewDebug.IntToString(from = TYPE_NAVIGATION_BAR_PANEL, to = "TYPE_NAVIGATION_BAR_PANEL") + @ViewDebug.IntToString(from = TYPE_NAVIGATION_BAR_PANEL, to = "TYPE_NAVIGATION_BAR_PANEL"), + @ViewDebug.IntToString(from = TYPE_DISPLAY_OVERLAY, to = "TYPE_DISPLAY_OVERLAY"), }) public int type; @@ -435,6 +436,12 @@ public interface WindowManager extends ViewManager { public static final int TYPE_UNIVERSE_BACKGROUND = FIRST_SYSTEM_WINDOW+25; /** + * Window type: Display overlay window. Used to simulate secondary display devices. + * @hide + */ + public static final int TYPE_DISPLAY_OVERLAY = FIRST_SYSTEM_WINDOW+26; + + /** * End of types of system windows. */ public static final int LAST_SYSTEM_WINDOW = 2999; diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java index bf061df19791..aa9179f6309b 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -52,8 +52,9 @@ public final class WindowManagerImpl implements WindowManager { private final Window mParentWindow; public WindowManagerImpl(Context context, int displayId) { + DisplayManager dm = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); mContext = context; - mDisplay = DisplayManager.getInstance().getDisplay(displayId, mContext); + mDisplay = dm.getDisplay(displayId); mParentWindow = null; } |
