summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/ActivityManager.java4
-rw-r--r--core/java/android/app/ActivityThread.java3
-rw-r--r--core/java/android/app/ContextImpl.java9
-rw-r--r--core/java/android/hardware/display/DisplayManager.java206
-rw-r--r--core/java/android/hardware/display/DisplayManagerGlobal.java273
-rw-r--r--core/java/android/hardware/display/IDisplayManager.aidl6
-rw-r--r--core/java/android/hardware/display/IDisplayManagerCallback.aidl22
-rw-r--r--core/java/android/provider/Settings.java19
-rw-r--r--core/java/android/view/Choreographer.java10
-rw-r--r--core/java/android/view/Display.java63
-rw-r--r--core/java/android/view/DisplayInfo.java4
-rw-r--r--core/java/android/view/View.java5
-rw-r--r--core/java/android/view/WindowManager.java9
-rw-r--r--core/java/android/view/WindowManagerImpl.java3
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;
}