diff options
33 files changed, 1129 insertions, 655 deletions
@@ -114,6 +114,7 @@ LOCAL_SRC_FILES += \ core/java/android/content/pm/IPackageStatsObserver.aidl \ core/java/android/database/IContentObserver.aidl \ core/java/android/hardware/ISerialManager.aidl \ + core/java/android/hardware/display/IDisplayManager.aidl \ core/java/android/hardware/input/IInputManager.aidl \ core/java/android/hardware/input/IInputDevicesChangedListener.aidl \ core/java/android/hardware/usb/IUsbManager.aidl \ @@ -22892,7 +22892,7 @@ package android.view { method protected void onApplyThemeResource(android.content.res.Resources.Theme, int, boolean); } - public class Display { + public final class Display { method public void getCurrentSizeRange(android.graphics.Point, android.graphics.Point); method public int getDisplayId(); method public deprecated int getHeight(); diff --git a/api/current.txt b/api/current.txt index 2716d5b..c910bd0 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5355,6 +5355,7 @@ package android.content { field public static final int CONTEXT_INCLUDE_CODE = 1; // 0x1 field public static final int CONTEXT_RESTRICTED = 4; // 0x4 field public static final java.lang.String DEVICE_POLICY_SERVICE = "device_policy"; + field public static final java.lang.String DISPLAY_SERVICE = "display"; field public static final java.lang.String DOWNLOAD_SERVICE = "download"; field public static final java.lang.String DROPBOX_SERVICE = "dropbox"; field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method"; @@ -9952,6 +9953,13 @@ package android.hardware { } +package android.hardware.display { + + public final class DisplayManager { + } + +} + package android.hardware.input { public final class InputManager { @@ -23120,13 +23128,15 @@ package android.view { method protected void onApplyThemeResource(android.content.res.Resources.Theme, int, boolean); } - public class Display { + public final class Display { method public void getCurrentSizeRange(android.graphics.Point, android.graphics.Point); method public int getDisplayId(); method public deprecated int getHeight(); method public void getMetrics(android.util.DisplayMetrics); method public deprecated int getOrientation(); - method public int getPixelFormat(); + method public deprecated int getPixelFormat(); + method public void getRealMetrics(android.util.DisplayMetrics); + method public void getRealSize(android.graphics.Point); method public void getRectSize(android.graphics.Rect); method public float getRefreshRate(); method public int getRotation(); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index f3f9b64..74fce62 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -47,6 +47,7 @@ import android.hardware.ISerialManager; import android.hardware.SensorManager; import android.hardware.SerialManager; import android.hardware.SystemSensorManager; +import android.hardware.display.DisplayManager; import android.hardware.input.IInputManager; import android.hardware.input.InputManager; import android.hardware.usb.IUsbManager; @@ -343,6 +344,11 @@ class ContextImpl extends Context { return InputManager.getInstance(); }}); + registerService(DISPLAY_SERVICE, new StaticServiceFetcher() { + public Object createStaticService() { + return DisplayManager.getInstance(); + }}); + registerService(INPUT_METHOD_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { return InputMethodManager.getInstance(ctx); diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 490165d..8597993 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -1955,6 +1955,15 @@ public abstract class Context { /** * Use with {@link #getSystemService} to retrieve a + * {@link android.hardware.display.DisplayManager} for interacting with display devices. + * + * @see #getSystemService + * @see android.hardware.display.DisplayManager + */ + public static final String DISPLAY_SERVICE = "display"; + + /** + * Use with {@link #getSystemService} to retrieve a * {@link android.os.SchedulingPolicyService} for managing scheduling policy. * * @see #getSystemService diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java new file mode 100644 index 0000000..13a2db4 --- /dev/null +++ b/core/java/android/hardware/display/DisplayManager.java @@ -0,0 +1,76 @@ +/* + * 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.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Log; +import android.view.DisplayInfo; + +/** + * Manages the properties, media routing and power state of attached displays. + * <p> + * Get an instance of this class by calling + * {@link android.content.Context#getSystemService(java.lang.String) + * Context.getSystemService()} with the argument + * {@link android.content.Context#DISPLAY_SERVICE}. + * </p> + */ +public final class DisplayManager { + private static final String TAG = "DisplayManager"; + + private static DisplayManager sInstance; + + private final IDisplayManager mDm; + + private DisplayManager(IDisplayManager dm) { + mDm = dm; + } + + /** + * Gets an instance of the display manager. + * @return The display manager instance. + * @hide + */ + public static DisplayManager getInstance() { + synchronized (DisplayManager.class) { + if (sInstance == null) { + IBinder b = ServiceManager.getService(Context.DISPLAY_SERVICE); + sInstance = new DisplayManager(IDisplayManager.Stub.asInterface(b)); + } + return sInstance; + } + } + + /** + * Get information about a particular logical display. + * + * @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. + */ + 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; + } + } +} diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl new file mode 100644 index 0000000..fd8c35f --- /dev/null +++ b/core/java/android/hardware/display/IDisplayManager.aidl @@ -0,0 +1,24 @@ +/* + * 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.view.DisplayInfo; + +/** @hide */ +interface IDisplayManager { + boolean getDisplayInfo(int displayId, out DisplayInfo outInfo); +} diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index 6136d8f..46e4d6e 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -17,20 +17,56 @@ package android.view; import android.content.res.CompatibilityInfo; +import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.Rect; +import android.hardware.display.DisplayManager; import android.os.RemoteException; -import android.os.ServiceManager; import android.os.SystemClock; import android.util.DisplayMetrics; -import android.util.Slog; +import android.util.Log; /** - * Provides information about the display size and density. + * Provides information about the size and density of a logical display. + * <p> + * The display area is described in two different ways. + * <ul> + * <li>The application display area specifies the part of the display that may contain + * an application window, excluding the system decorations. The application display area may + * be smaller than the real display area because the system subtracts the space needed + * for decor elements such as the status bar. Use the following methods to query the + * application display area: {@link #getSize}, {@link #getRectSize} and {@link #getMetrics}.</li> + * <li>The real display area specifies the part of the display that contains content + * including the system decorations. Even so, the real display area may be smaller than the + * physical size of the display if the window manager is emulating a smaller display + * using (adb shell am display-size). Use the following methods to query the + * real display area: {@link #getRealSize}, {@link #getRealMetrics}.</li> + * </ul> + * </p><p> + * A logical display does not necessarily represent a particular physical display device + * such as the built-in screen or an external monitor. The contents of a logical + * display may be presented on one or more physical displays according to the devices + * that are currently attached and whether mirroring has been enabled. + * </p> */ -public class Display { - static final String TAG = "Display"; - static final boolean DEBUG_DISPLAY_SIZE = false; +public final class Display { + private static final String TAG = "Display"; + + private final int mDisplayId; + private final CompatibilityInfoHolder mCompatibilityInfo; + private final DisplayInfo mDisplayInfo = new DisplayInfo(); + + // Temporary display metrics structure used for compatibility mode. + private final DisplayMetrics mTempMetrics = new DisplayMetrics(); + + // We cache the app width and height properties briefly between calls + // to getHeight() and getWidth() to ensure that applications perceive + // consistent results when the size changes (most of the time). + // Applications should now be using getSize() instead. + private static final int CACHED_APP_SIZE_DURATION_MILLIS = 20; + private long mLastCachedAppSizeUpdate; + private int mCachedAppWidthCompat; + private int mCachedAppHeightCompat; /** * The default Display id. @@ -38,40 +74,29 @@ public class Display { public static final int DEFAULT_DISPLAY = 0; /** - * Use {@link android.view.WindowManager#getDefaultDisplay() - * WindowManager.getDefaultDisplay()} to create a Display object. - * Display gives you access to some information about a particular display - * connected to the device. + * Internal method to create a display. + * Applications should use {@link android.view.WindowManager#getDefaultDisplay()} + * to get a display object for the default display. + * + * @hide */ - Display(int display, CompatibilityInfoHolder compatInfo) { - // initalize the statics when this class is first instansiated. This is - // done here instead of in the static block because Zygote - synchronized (sStaticInit) { - if (!sInitialized) { - nativeClassInit(); - sInitialized = true; - } - } - mCompatibilityInfo = compatInfo != null ? compatInfo : new CompatibilityInfoHolder(); - mDisplay = display; - init(display); + public Display(int displayId, CompatibilityInfoHolder compatibilityInfo) { + mDisplayId = displayId; + mCompatibilityInfo = compatibilityInfo; } /** - * Returns the index of this display. This is currently undefined; do - * not use. + * Gets the display id. + * <p> + * Each logical display has a unique id. + * The default display has id {@link #DEFAULT_DISPLAY}. + * </p> */ public int getDisplayId() { - return mDisplay; + return mDisplayId; } /** - * Returns the number of displays connected to the device. This is - * currently undefined; do not use. - */ - native static int getDisplayCount(); - - /** * Gets the size of the display, in pixels. * <p> * Note that this value should <em>not</em> be used for computing layouts, @@ -84,7 +109,7 @@ public class Display { * </p><p> * The size returned by this method does not necessarily represent the * actual raw size (native resolution) of the display. The returned size may - * be adjusted to exclude certain system decor elements that are always visible. + * be adjusted to exclude certain system decoration elements that are always visible. * It may also be scaled to provide compatibility with older applications that * were originally designed for smaller displays. * </p> @@ -92,43 +117,14 @@ public class Display { * @param outSize A {@link Point} object to receive the size information. */ public void getSize(Point outSize) { - getSizeInternal(outSize, true); - } - - private void getSizeInternal(Point outSize, boolean doCompat) { - try { - IWindowManager wm = getWindowManager(); - if (wm != null) { - wm.getDisplaySize(outSize); - CompatibilityInfo ci; - if (doCompat && (ci=mCompatibilityInfo.getIfNeeded()) != null) { - synchronized (mTmpMetrics) { - mTmpMetrics.noncompatWidthPixels = outSize.x; - mTmpMetrics.noncompatHeightPixels = outSize.y; - mTmpMetrics.density = mDensity; - ci.applyToDisplayMetrics(mTmpMetrics); - outSize.x = mTmpMetrics.widthPixels; - outSize.y = mTmpMetrics.heightPixels; - } - } - } else { - // This is just for boot-strapping, initializing the - // system process before the window manager is up. - outSize.x = getRawWidth(); - outSize.y = getRawHeight(); - } - if (false) { - RuntimeException here = new RuntimeException("here"); - here.fillInStackTrace(); - Slog.v(TAG, "Returning display size: " + outSize, here); - } - if (DEBUG_DISPLAY_SIZE && doCompat) Slog.v( - TAG, "Returning display size: " + outSize); - } catch (RemoteException e) { - Slog.w("Display", "Unable to get display size", e); + synchronized (this) { + updateDisplayInfoLocked(); + mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo); + outSize.x = mTempMetrics.widthPixels; + outSize.y = mTempMetrics.heightPixels; } } - + /** * Gets the size of the display as a rectangle, in pixels. * @@ -136,9 +132,10 @@ public class Display { * @see #getSize(Point) */ public void getRectSize(Rect outSize) { - synchronized (mTmpPoint) { - getSizeInternal(mTmpPoint, true); - outSize.set(0, 0, mTmpPoint.x, mTmpPoint.y); + synchronized (this) { + updateDisplayInfoLocked(); + mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo); + outSize.set(0, 0, mTempMetrics.widthPixels, mTempMetrics.heightPixels); } } @@ -173,15 +170,12 @@ public class Display { * for example, screen decorations like the status bar are being hidden. */ public void getCurrentSizeRange(Point outSmallestSize, Point outLargestSize) { - try { - IWindowManager wm = getWindowManager(); - wm.getCurrentSizeRange(outSmallestSize, outLargestSize); - } catch (RemoteException e) { - Slog.w("Display", "Unable to get display size range", e); - outSmallestSize.x = 0; - outSmallestSize.y = 0; - outLargestSize.x = 0; - outLargestSize.y = 0; + synchronized (this) { + updateDisplayInfoLocked(); + outSmallestSize.x = mDisplayInfo.smallestNominalAppWidth; + outSmallestSize.y = mDisplayInfo.smallestNominalAppHeight; + outLargestSize.x = mDisplayInfo.largestNominalAppWidth; + outLargestSize.y = mDisplayInfo.largestNominalAppHeight; } } @@ -191,12 +185,9 @@ public class Display { * @hide */ public int getMaximumSizeDimension() { - try { - IWindowManager wm = getWindowManager(); - return wm.getMaximumSizeDimension(); - } catch (RemoteException e) { - Slog.w("Display", "Unable to get display maximum size dimension", e); - return 0; + synchronized (this) { + updateDisplayInfoLocked(); + return Math.max(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); } } @@ -205,13 +196,9 @@ public class Display { */ @Deprecated public int getWidth() { - synchronized (mTmpPoint) { - long now = SystemClock.uptimeMillis(); - if (now > (mLastGetTime+20)) { - getSizeInternal(mTmpPoint, true); - mLastGetTime = now; - } - return mTmpPoint.x; + synchronized (this) { + updateCachedAppSizeIfNeededLocked(); + return mCachedAppWidthCompat; } } @@ -220,76 +207,13 @@ public class Display { */ @Deprecated public int getHeight() { - synchronized (mTmpPoint) { - long now = SystemClock.uptimeMillis(); - if (now > (mLastGetTime+20)) { - getSizeInternal(mTmpPoint, true); - mLastGetTime = now; - } - return mTmpPoint.y; - } - } - - /** - * Gets the real size of the display without subtracting any window decor or - * applying any compatibility scale factors. - * <p> - * The real size may be smaller than the raw size when the window manager - * is emulating a smaller display (using adb shell am display-size). - * </p><p> - * The size is adjusted based on the current rotation of the display. - * </p> - * @hide - */ - public void getRealSize(Point outSize) { - try { - IWindowManager wm = getWindowManager(); - if (wm != null) { - wm.getRealDisplaySize(outSize); - } else { - // This is just for boot-strapping, initializing the - // system process before the window manager is up. - outSize.x = getRawWidth(); - outSize.y = getRawHeight(); - } - if (DEBUG_DISPLAY_SIZE) Slog.v( - TAG, "Returning real display size: " + outSize); - } catch (RemoteException e) { - Slog.w("Display", "Unable to get real display size", e); + synchronized (this) { + updateCachedAppSizeIfNeededLocked(); + return mCachedAppHeightCompat; } } /** - * Gets the raw width of the display, in pixels. - * <p> - * The size is adjusted based on the current rotation of the display. - * </p> - * @hide - */ - public int getRawWidth() { - int w = getRawWidthNative(); - if (DEBUG_DISPLAY_SIZE) Slog.v( - TAG, "Returning raw display width: " + w); - return w; - } - private native int getRawWidthNative(); - - /** - * Gets the raw height of the display, in pixels. - * <p> - * The size is adjusted based on the current rotation of the display. - * </p> - * @hide - */ - public int getRawHeight() { - int h = getRawHeightNative(); - if (DEBUG_DISPLAY_SIZE) Slog.v( - TAG, "Returning raw display height: " + h); - return h; - } - private native int getRawHeightNative(); - - /** * Returns the rotation of the screen from its "natural" orientation. * The returned value may be {@link Surface#ROTATION_0 Surface.ROTATION_0} * (no rotation), {@link Surface#ROTATION_90 Surface.ROTATION_90}, @@ -307,30 +231,43 @@ public class Display { * {@link Surface#ROTATION_90 Surface.ROTATION_90}. */ public int getRotation() { - return getOrientation(); + synchronized (this) { + updateDisplayInfoLocked(); + return mDisplayInfo.rotation; + } } - + /** * @deprecated use {@link #getRotation} * @return orientation of this display. */ - @Deprecated native public int getOrientation(); + @Deprecated + public int getOrientation() { + return getRotation(); + } /** - * Return the native pixel format of the display. The returned value - * may be one of the constants int {@link android.graphics.PixelFormat}. + * Gets the pixel format of the display. + * @return One of the constants defined in {@link android.graphics.PixelFormat}. + * + * @deprecated This method is no longer supported. + * The result is always {@link PixelFormat#RGBA_8888}. */ + @Deprecated public int getPixelFormat() { - return mPixelFormat; + return PixelFormat.RGBA_8888; } - + /** - * Return the refresh rate of this display in frames per second. + * Gets the refresh rate of this display in frames per second. */ public float getRefreshRate() { - return mRefreshRate; + synchronized (this) { + updateDisplayInfoLocked(); + return mDisplayInfo.refreshRate; + } } - + /** * Gets display metrics that describe the size and density of this display. * <p> @@ -346,102 +283,71 @@ public class Display { * @param outMetrics A {@link DisplayMetrics} object to receive the metrics. */ public void getMetrics(DisplayMetrics outMetrics) { - synchronized (mTmpPoint) { - getSizeInternal(mTmpPoint, false); - getMetricsWithSize(outMetrics, mTmpPoint.x, mTmpPoint.y); + synchronized (this) { + updateDisplayInfoLocked(); + mDisplayInfo.getAppMetrics(outMetrics, mCompatibilityInfo); } - CompatibilityInfo ci = mCompatibilityInfo.getIfNeeded(); + final CompatibilityInfo ci = mCompatibilityInfo.getIfNeeded(); if (ci != null) { ci.applyToDisplayMetrics(outMetrics); } - - if (DEBUG_DISPLAY_SIZE) Slog.v(TAG, "Returning DisplayMetrics: " - + outMetrics.widthPixels + "x" + outMetrics.heightPixels - + " " + outMetrics.density); } /** - * Gets display metrics based on the real size of this display. - * @hide + * Gets the real size of the display without subtracting any window decor or + * applying any compatibility scale factors. + * <p> + * The size is adjusted based on the current rotation of the display. + * </p><p> + * The real size may be smaller than the physical size of the screen when the + * window manager is emulating a smaller display (using adb shell am display-size). + * </p> + * + * @param outSize Set to the real size of the display. */ - public void getRealMetrics(DisplayMetrics outMetrics) { - synchronized (mTmpPoint) { - getRealSize(mTmpPoint); - getMetricsWithSize(outMetrics, mTmpPoint.x, mTmpPoint.y); + public void getRealSize(Point outSize) { + synchronized (this) { + updateDisplayInfoLocked(); + outSize.x = mDisplayInfo.logicalWidth; + outSize.y = mDisplayInfo.logicalHeight; } } /** - * If the display is mirrored to an external HDMI display, returns the - * width of that display. - * @hide - */ - public int getRawExternalWidth() { - return 1280; - } - - /** - * If the display is mirrored to an external HDMI display, returns the - * height of that display. - * @hide - */ - public int getRawExternalHeight() { - return 720; - } - - /** - * If the display is mirrored to an external HDMI display, returns the - * rotation of that display relative to its natural orientation. - * @hide + * Gets display metrics based on the real size of this display. + * <p> + * The size is adjusted based on the current rotation of the display. + * </p><p> + * The real size may be smaller than the physical size of the screen when the + * window manager is emulating a smaller display (using adb shell am display-size). + * </p> + * + * @param outMetrics A {@link DisplayMetrics} object to receive the metrics. */ - public int getExternalRotation() { - return Surface.ROTATION_0; + public void getRealMetrics(DisplayMetrics outMetrics) { + synchronized (this) { + updateDisplayInfoLocked(); + mDisplayInfo.getLogicalMetrics(outMetrics, null); + } } - /** - * Gets display metrics based on an explicit assumed display size. - * @hide - */ - public void getMetricsWithSize(DisplayMetrics outMetrics, - int width, int height) { - outMetrics.densityDpi = (int)((mDensity*DisplayMetrics.DENSITY_DEFAULT)+.5f); - - outMetrics.noncompatWidthPixels = outMetrics.widthPixels = width; - outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height; - - outMetrics.density = outMetrics.noncompatDensity = mDensity; - outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density; - outMetrics.xdpi = outMetrics.noncompatXdpi = mDpiX; - outMetrics.ydpi = outMetrics.noncompatYdpi = mDpiY; + 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); + } } - private static IWindowManager getWindowManager() { - return WindowManagerImpl.getWindowManagerService(); + private void updateCachedAppSizeIfNeededLocked() { + long now = SystemClock.uptimeMillis(); + if (now > mLastCachedAppSizeUpdate + CACHED_APP_SIZE_DURATION_MILLIS) { + updateDisplayInfoLocked(); + mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo); + mCachedAppWidthCompat = mTempMetrics.widthPixels; + mCachedAppHeightCompat = mTempMetrics.heightPixels; + mLastCachedAppSizeUpdate = now; + } } - - /* - * We use a class initializer to allow the native code to cache some - * field offsets. - */ - native private static void nativeClassInit(); - - private native void init(int display); - - private final CompatibilityInfoHolder mCompatibilityInfo; - private final int mDisplay; - // Following fields are initialized from native code - private int mPixelFormat; - private float mRefreshRate; - /*package*/ float mDensity; - /*package*/ float mDpiX; - /*package*/ float mDpiY; - - private final Point mTmpPoint = new Point(); - private final DisplayMetrics mTmpMetrics = new DisplayMetrics(); - private float mLastGetTime; - - private static final Object sStaticInit = new Object(); - private static boolean sInitialized = false; } diff --git a/core/java/android/view/DisplayInfo.aidl b/core/java/android/view/DisplayInfo.aidl new file mode 100644 index 0000000..e679208 --- /dev/null +++ b/core/java/android/view/DisplayInfo.aidl @@ -0,0 +1,19 @@ +/* + * 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.view; + +parcelable DisplayInfo; diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java new file mode 100644 index 0000000..69b6d67 --- /dev/null +++ b/core/java/android/view/DisplayInfo.java @@ -0,0 +1,226 @@ +/* + * 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.view; + +import android.content.res.CompatibilityInfo; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.DisplayMetrics; + +/** + * Describes the characteristics of a particular logical display. + * @hide + */ +public final class DisplayInfo implements Parcelable { + /** + * The width of the portion of the display that is available to applications, in pixels. + * Represents the size of the display minus any system decorations. + */ + public int appWidth; + + /** + * The height of the portion of the display that is available to applications, in pixels. + * Represents the size of the display minus any system decorations. + */ + public int appHeight; + + /** + * The smallest value of {@link #appWidth} that an application is likely to encounter, + * in pixels, excepting cases where the width may be even smaller due to the presence + * of a soft keyboard, for example. + */ + public int smallestNominalAppWidth; + + /** + * The smallest value of {@link #appHeight} that an application is likely to encounter, + * in pixels, excepting cases where the height may be even smaller due to the presence + * of a soft keyboard, for example. + */ + public int smallestNominalAppHeight; + + /** + * The largest value of {@link #appWidth} that an application is likely to encounter, + * in pixels, excepting cases where the width may be even larger due to system decorations + * such as the status bar being hidden, for example. + */ + public int largestNominalAppWidth; + + /** + * The largest value of {@link #appHeight} that an application is likely to encounter, + * in pixels, excepting cases where the height may be even larger due to system decorations + * such as the status bar being hidden, for example. + */ + public int largestNominalAppHeight; + + /** + * The logical width of the display, in pixels. + * Represents the usable size of the display which may be smaller than the + * physical size when the system is emulating a smaller display. + */ + public int logicalWidth; + + /** + * The logical height of the display, in pixels. + * Represents the usable size of the display which may be smaller than the + * physical size when the system is emulating a smaller display. + */ + public int logicalHeight; + + /** + * The rotation of the display relative to its natural orientation. + * May be one of {@link android.view.Surface#ROTATION_0}, + * {@link android.view.Surface#ROTATION_90}, {@link android.view.Surface#ROTATION_180}, + * {@link android.view.Surface#ROTATION_270}. + * <p> + * The value of this field is indeterminate if the logical display is presented on + * more than one physical display. + * </p> + */ + public int rotation; + + /** + * The refresh rate of this display in frames per second. + * <p> + * The value of this field is indeterminate if the logical display is presented on + * more than one physical display. + * </p> + */ + public float refreshRate; + + /** + * The logical display density which represents the scaling factor for + * the Density Independent Pixel unit. + */ + public float logicalDensity; + + /** + * The exact physical pixels per inch of the screen in the X dimension. + * <p> + * The value of this field is indeterminate if the logical display is presented on + * more than one physical display. + * </p> + */ + public float physicalXDpi; + + /** + * The exact physical pixels per inch of the screen in the Y dimension. + * <p> + * The value of this field is indeterminate if the logical display is presented on + * more than one physical display. + * </p> + */ + public float physicalYDpi; + + public static final Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() { + public DisplayInfo createFromParcel(Parcel source) { + return new DisplayInfo(source); + } + + public DisplayInfo[] newArray(int size) { + return new DisplayInfo[size]; + } + }; + + public DisplayInfo() { + } + + private DisplayInfo(Parcel source) { + readFromParcel(source); + } + + @Override + public int describeContents() { + return 0; + } + + public void copyFrom(DisplayInfo other) { + appWidth = other.appWidth; + appHeight = other.appHeight; + smallestNominalAppWidth = other.smallestNominalAppWidth; + smallestNominalAppHeight = other.smallestNominalAppHeight; + largestNominalAppWidth = other.largestNominalAppWidth; + largestNominalAppHeight = other.largestNominalAppHeight; + logicalWidth = other.logicalWidth; + logicalHeight = other.logicalHeight; + rotation = other.rotation; + refreshRate = other.refreshRate; + logicalDensity = other.logicalDensity; + physicalXDpi = other.physicalXDpi; + physicalYDpi = other.physicalYDpi; + } + + public void readFromParcel(Parcel source) { + appWidth = source.readInt(); + appHeight = source.readInt(); + smallestNominalAppWidth = source.readInt(); + smallestNominalAppHeight = source.readInt(); + largestNominalAppWidth = source.readInt(); + largestNominalAppHeight = source.readInt(); + logicalWidth = source.readInt(); + logicalHeight = source.readInt(); + rotation = source.readInt(); + refreshRate = source.readFloat(); + logicalDensity = source.readFloat(); + physicalXDpi = source.readFloat(); + physicalYDpi = source.readFloat(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(appWidth); + dest.writeInt(appHeight); + dest.writeInt(smallestNominalAppWidth); + dest.writeInt(smallestNominalAppHeight); + dest.writeInt(largestNominalAppWidth); + dest.writeInt(largestNominalAppHeight); + dest.writeInt(logicalWidth); + dest.writeInt(logicalHeight); + dest.writeInt(rotation); + dest.writeFloat(refreshRate); + dest.writeFloat(logicalDensity); + dest.writeFloat(physicalXDpi); + dest.writeFloat(physicalYDpi); + } + + public void getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfoHolder cih) { + getMetricsWithSize(outMetrics, cih, appWidth, appHeight); + } + + public void getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfoHolder cih) { + getMetricsWithSize(outMetrics, cih, logicalWidth, logicalHeight); + } + + private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfoHolder cih, + int width, int height) { + outMetrics.densityDpi = + (int)((logicalDensity * DisplayMetrics.DENSITY_DEFAULT) + .5f); + outMetrics.noncompatWidthPixels = outMetrics.widthPixels = width; + outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height; + + outMetrics.density = outMetrics.noncompatDensity = logicalDensity; + outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density; + outMetrics.xdpi = outMetrics.noncompatXdpi = physicalXDpi; + outMetrics.ydpi = outMetrics.noncompatYdpi = physicalYDpi; + + if (cih != null) { + CompatibilityInfo ci = cih.getIfNeeded(); + if (ci != null) { + ci.applyToDisplayMetrics(outMetrics); + } + } + } +} diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 5941e44..a65d6f5 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -25,6 +25,7 @@ import android.graphics.Bitmap; import android.graphics.Point; import android.graphics.Rect; import android.os.IRemoteCallback; +import android.view.DisplayInfo; import android.view.IApplicationToken; import android.view.IOnKeyguardExitResult; import android.view.IRotationWatcher; @@ -56,11 +57,6 @@ interface IWindowManager IWindowSession openSession(in IInputMethodClient client, in IInputContext inputContext); boolean inputMethodClientHasFocus(IInputMethodClient client); - - void getDisplaySize(out Point size); - void getRealDisplaySize(out Point size); - int getMaximumSizeDimension(); - void getCurrentSizeRange(out Point smallestSize, out Point largestSize); void setForcedDisplaySize(int longDimen, int shortDimen); void clearForcedDisplaySize(); diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 1105038..02ecb65 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -403,31 +403,16 @@ public class Surface implements Parcelable { public native void destroy(); private native Canvas lockCanvasNative(Rect dirty); - - /* - * set display parameters & screenshots - */ /** * set the orientation of the given display. * @param display * @param orientation - * @param flags Currently unused, set to 0. * @hide */ - public static native void setOrientation(int display, int orientation, int flags); + public static native void setOrientation(int display, int orientation); /** - * set the orientation of the given display. - * @param display - * @param orientation - * @hide - */ - public static void setOrientation(int display, int orientation) { - setOrientation(display, orientation, 0); - } - - /** * Like {@link #screenshot(int, int, int, int)} but includes all * Surfaces in the screenshot. * diff --git a/core/jni/Android.mk b/core/jni/Android.mk index e429ffc..b1423ca 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -44,7 +44,6 @@ LOCAL_SRC_FILES:= \ android_database_SQLiteGlobal.cpp \ android_database_SQLiteDebug.cpp \ android_emoji_EmojiFactory.cpp \ - android_view_Display.cpp \ android_view_DisplayEventReceiver.cpp \ android_view_Surface.cpp \ android_view_TextureView.cpp \ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index f0dd321..c936b0b 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -116,7 +116,6 @@ extern int register_android_graphics_Region(JNIEnv* env); extern int register_android_graphics_SurfaceTexture(JNIEnv* env); extern int register_android_graphics_Xfermode(JNIEnv* env); extern int register_android_graphics_PixelFormat(JNIEnv* env); -extern int register_android_view_Display(JNIEnv* env); extern int register_android_view_DisplayEventReceiver(JNIEnv* env); extern int register_android_view_GLES20DisplayList(JNIEnv* env); extern int register_android_view_GLES20Canvas(JNIEnv* env); @@ -1088,7 +1087,6 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_os_SystemProperties), REG_JNI(register_android_os_Binder), REG_JNI(register_android_os_Parcel), - REG_JNI(register_android_view_Display), REG_JNI(register_android_view_DisplayEventReceiver), REG_JNI(register_android_nio_utils), REG_JNI(register_android_graphics_PixelFormat), diff --git a/core/jni/android_view_Display.cpp b/core/jni/android_view_Display.cpp deleted file mode 100644 index aedf1e4..0000000 --- a/core/jni/android_view_Display.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#include <stdio.h> -#include <assert.h> - -#include <cutils/properties.h> - -#include <gui/SurfaceComposerClient.h> -#include <ui/PixelFormat.h> -#include <ui/DisplayInfo.h> - -#include "jni.h" -#include "JNIHelp.h" -#include <android_runtime/AndroidRuntime.h> -#include <utils/misc.h> -#include <utils/Log.h> -#include <cutils/properties.h> - -// ---------------------------------------------------------------------------- - -namespace android { - -// ---------------------------------------------------------------------------- - -struct offsets_t { - jfieldID display; - jfieldID pixelFormat; - jfieldID fps; - jfieldID density; - jfieldID xdpi; - jfieldID ydpi; -}; -static offsets_t offsets; -static bool headless = false; - -// ---------------------------------------------------------------------------- - -static void android_view_Display_init( - JNIEnv* env, jobject clazz, jint dpy) -{ - DisplayInfo info; - if (headless) { - // initialize dummy display with reasonable values - info.pixelFormatInfo.format = 1; // RGB_8888 - info.fps = 60; - info.density = 160; - info.xdpi = 160; - info.ydpi = 160; - } else { - status_t err = SurfaceComposerClient::getDisplayInfo(DisplayID(dpy), &info); - if (err < 0) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); - return; - } - } - env->SetIntField(clazz, offsets.pixelFormat,info.pixelFormatInfo.format); - env->SetFloatField(clazz, offsets.fps, info.fps); - env->SetFloatField(clazz, offsets.density, info.density); - env->SetFloatField(clazz, offsets.xdpi, info.xdpi); - env->SetFloatField(clazz, offsets.ydpi, info.ydpi); -} - -static jint android_view_Display_getRawWidthNative( - JNIEnv* env, jobject clazz) -{ - if (headless) return 640; - DisplayID dpy = env->GetIntField(clazz, offsets.display); - return SurfaceComposerClient::getDisplayWidth(dpy); -} - -static jint android_view_Display_getRawHeightNative( - JNIEnv* env, jobject clazz) -{ - if (headless) return 480; - DisplayID dpy = env->GetIntField(clazz, offsets.display); - return SurfaceComposerClient::getDisplayHeight(dpy); -} - -static jint android_view_Display_getOrientation( - JNIEnv* env, jobject clazz) -{ - if (headless) return 0; // Surface.ROTATION_0 - DisplayID dpy = env->GetIntField(clazz, offsets.display); - return SurfaceComposerClient::getDisplayOrientation(dpy); -} - -static jint android_view_Display_getDisplayCount( - JNIEnv* env, jclass clazz) -{ - if (headless) return 1; - return SurfaceComposerClient::getNumberOfDisplays(); -} - -// ---------------------------------------------------------------------------- - -const char* const kClassPathName = "android/view/Display"; - -static void nativeClassInit(JNIEnv* env, jclass clazz); - -static JNINativeMethod gMethods[] = { - { "nativeClassInit", "()V", - (void*)nativeClassInit }, - { "getDisplayCount", "()I", - (void*)android_view_Display_getDisplayCount }, - { "init", "(I)V", - (void*)android_view_Display_init }, - { "getRawWidthNative", "()I", - (void*)android_view_Display_getRawWidthNative }, - { "getRawHeightNative", "()I", - (void*)android_view_Display_getRawHeightNative }, - { "getOrientation", "()I", - (void*)android_view_Display_getOrientation } -}; - -void nativeClassInit(JNIEnv* env, jclass clazz) -{ - char value[PROPERTY_VALUE_MAX]; - - property_get("ro.config.headless", value, "0"); - if (strcmp(value, "1") == 0) - headless = true; - - offsets.display = env->GetFieldID(clazz, "mDisplay", "I"); - offsets.pixelFormat = env->GetFieldID(clazz, "mPixelFormat", "I"); - offsets.fps = env->GetFieldID(clazz, "mRefreshRate", "F"); - offsets.density = env->GetFieldID(clazz, "mDensity", "F"); - offsets.xdpi = env->GetFieldID(clazz, "mDpiX", "F"); - offsets.ydpi = env->GetFieldID(clazz, "mDpiY", "F"); -} - -int register_android_view_Display(JNIEnv* env) -{ - return AndroidRuntime::registerNativeMethods(env, - kClassPathName, gMethods, NELEM(gMethods)); -} - -}; diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index 60f8c48..3cd28b1 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -473,9 +473,9 @@ static void Surface_closeTransaction( } static void Surface_setOrientation( - JNIEnv* env, jobject clazz, jint display, jint orientation, jint flags) + JNIEnv* env, jobject clazz, jint display, jint orientation) { - int err = SurfaceComposerClient::setOrientation(display, orientation, flags); + int err = SurfaceComposerClient::setOrientation(display, orientation, 0); if (err < 0) { doThrowIAE(env); } @@ -839,7 +839,7 @@ static JNINativeMethod gSurfaceMethods[] = { {"unlockCanvas", "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvas }, {"openTransaction", "()V", (void*)Surface_openTransaction }, {"closeTransaction", "()V", (void*)Surface_closeTransaction }, - {"setOrientation", "(III)V", (void*)Surface_setOrientation }, + {"setOrientation", "(II)V", (void*)Surface_setOrientation }, {"screenshot", "(II)Landroid/graphics/Bitmap;", (void*)Surface_screenshotAll }, {"screenshot", "(IIII)Landroid/graphics/Bitmap;", (void*)Surface_screenshot }, {"setLayer", "(I)V", (void*)Surface_setLayer }, diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 2185456..d766afd 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -49,6 +49,7 @@ import com.android.internal.os.SamplingProfilerIntegration; import com.android.internal.widget.LockSettingsService; import com.android.server.accessibility.AccessibilityManagerService; import com.android.server.am.ActivityManagerService; +import com.android.server.display.DisplayManagerService; import com.android.server.input.InputManagerService; import com.android.server.net.NetworkPolicyManagerService; import com.android.server.net.NetworkStatsService; @@ -115,6 +116,7 @@ class ServerThread extends Thread { LightsService lights = null; PowerManagerService power = null; + DisplayManagerService display = null; BatteryService battery = null; VibratorService vibrator = null; AlarmManagerService alarm = null; @@ -148,8 +150,13 @@ class ServerThread extends Thread { power = new PowerManagerService(); ServiceManager.addService(Context.POWER_SERVICE, power); + Slog.i(TAG, "Display Manager"); + display = new DisplayManagerService(); + ServiceManager.addService(Context.DISPLAY_SERVICE, display); + Slog.i(TAG, "Activity Manager"); context = ActivityManagerService.main(factoryTest); + display.setContext(context); Slog.i(TAG, "Telephony Registry"); ServiceManager.addService("telephony.registry", new TelephonyRegistry(context)); @@ -214,7 +221,7 @@ class ServerThread extends Thread { // only initialize the power service after we have started the // lights service, content providers and the battery service. - power.init(context, lights, ActivityManagerService.self(), battery); + power.init(context, lights, ActivityManagerService.self(), battery, display); Slog.i(TAG, "Alarm Manager"); alarm = new AlarmManagerService(context); @@ -225,7 +232,7 @@ class ServerThread extends Thread { ActivityManagerService.self()); Slog.i(TAG, "Window Manager"); - wm = WindowManagerService.main(context, power, + wm = WindowManagerService.main(context, power, display, factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL, !firstBoot, onlyCore); ServiceManager.addService(Context.WINDOW_SERVICE, wm); diff --git a/services/java/com/android/server/display/DisplayAdapter.java b/services/java/com/android/server/display/DisplayAdapter.java new file mode 100644 index 0000000..e150bf8 --- /dev/null +++ b/services/java/com/android/server/display/DisplayAdapter.java @@ -0,0 +1,35 @@ +/* + * 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 com.android.server.display; + +/** + * A display adapter makes one or more display devices available to the system. + * <p> + * For now, all display adapters are registered in the system server but + * in principle it could be done from other processes. + * </p> + */ +public abstract class DisplayAdapter { + /** + * Gets the display adapter name. + * @return The display adapter name. + */ + public abstract String getName(); + + // TODO: dynamically register display devices + public abstract DisplayDevice[] getDisplayDevices(); +} diff --git a/services/java/com/android/server/display/DisplayDevice.java b/services/java/com/android/server/display/DisplayDevice.java new file mode 100644 index 0000000..6d723f2 --- /dev/null +++ b/services/java/com/android/server/display/DisplayDevice.java @@ -0,0 +1,25 @@ +/* + * 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 com.android.server.display; + +/** + * Represents a physical display device such as the built-in display + * or an external monitor. + */ +public abstract class DisplayDevice { + public abstract void getInfo(DisplayDeviceInfo outInfo); +} diff --git a/services/java/com/android/server/display/DisplayDeviceInfo.java b/services/java/com/android/server/display/DisplayDeviceInfo.java new file mode 100644 index 0000000..c28b9bb --- /dev/null +++ b/services/java/com/android/server/display/DisplayDeviceInfo.java @@ -0,0 +1,54 @@ +/* + * 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 com.android.server.display; + +/** + * Describes the characteristics of a physical display device. + */ +public final class DisplayDeviceInfo { + /** + * The width of the display in its natural orientation, in pixels. + * This value is not affected by display rotation. + */ + public int width; + + /** + * The height of the display in its natural orientation, in pixels. + * This value is not affected by display rotation. + */ + public int height; + + public float refreshRate; + public float density; + public float xDpi; + public float yDpi; + + public void copyFrom(DisplayDeviceInfo other) { + width = other.width; + height = other.height; + refreshRate = other.refreshRate; + density = other.density; + xDpi = other.xDpi; + yDpi = other.yDpi; + } + + @Override + public String toString() { + return width + " x " + height + ", " + refreshRate + " fps, " + + "density " + density + ", " + xDpi + " x " + yDpi + " dpi"; + } +} diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java new file mode 100644 index 0000000..082d28f --- /dev/null +++ b/services/java/com/android/server/display/DisplayManagerService.java @@ -0,0 +1,155 @@ +/* + * 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 com.android.server.display; + +import android.Manifest; +import android.content.Context; +import android.content.pm.PackageManager; +import android.hardware.display.IDisplayManager; +import android.os.Binder; +import android.os.SystemProperties; +import android.view.Display; +import android.view.DisplayInfo; +import android.view.Surface; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.ArrayList; + +/** + * Manages the properties, media routing and power state of attached displays. + * <p> + * The display manager service does not own or directly control the displays. + * Instead, other components in the system register their display adapters with the + * display manager service which acts as a central controller. + * </p> + */ +public final class DisplayManagerService extends IDisplayManager.Stub { + private static final String TAG = "DisplayManagerService"; + + private static final String SYSTEM_HEADLESS = "ro.config.headless"; + + private final Object mLock = new Object(); + + private Context mContext; + private final boolean mHeadless; + private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>(); + + // TODO: represent this as a map between logical and physical devices + private DisplayInfo mDefaultDisplayInfo; + private DisplayDevice mDefaultDisplayDevice; + private DisplayDeviceInfo mDefaultDisplayDeviceInfo; + + public DisplayManagerService() { + mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1"); + registerDisplayAdapters(); + initializeDefaultDisplay(); + } + + public void setContext(Context context) { + mContext = context; + } + + // FIXME: this isn't the right API for the long term + public void setDefaultDisplayInfo(DisplayInfo info) { + synchronized (mLock) { + mDefaultDisplayInfo.copyFrom(info); + } + } + + // FIXME: this isn't the right API for the long term + public void getDefaultExternalDisplayDeviceInfo(DisplayDeviceInfo info) { + // hardcoded assuming 720p touch screen plugged into HDMI and USB + // need to redesign this + info.width = 1280; + info.height = 720; + } + + public boolean isHeadless() { + return mHeadless; + } + + @Override // Binder call + public boolean getDisplayInfo(int displayId, DisplayInfo outInfo) { + synchronized (mLock) { + if (displayId == Display.DEFAULT_DISPLAY) { + outInfo.copyFrom(mDefaultDisplayInfo); + return true; + } + return false; + } + } + + @Override // Binder call + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (mContext == null + || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump DisplayManager from from pid=" + + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); + return; + } + + pw.println("DISPLAY MANAGER (dumpsys display)\n"); + + pw.println("Headless: " + mHeadless); + + DisplayDeviceInfo info = new DisplayDeviceInfo(); + for (DisplayAdapter adapter : mDisplayAdapters) { + pw.println("Displays for adapter " + adapter.getName()); + for (DisplayDevice device : adapter.getDisplayDevices()) { + device.getInfo(info); + pw.print(" "); + pw.println(info); + } + } + } + + private void registerDisplayAdapters() { + if (mHeadless) { + registerDisplayAdapter(new HeadlessDisplayAdapter()); + } else { + registerDisplayAdapter(new SurfaceFlingerDisplayAdapter()); + } + } + + private void registerDisplayAdapter(DisplayAdapter adapter) { + // TODO: do this dynamically + mDisplayAdapters.add(adapter); + mDefaultDisplayDevice = adapter.getDisplayDevices()[0]; + mDefaultDisplayDeviceInfo = new DisplayDeviceInfo(); + mDefaultDisplayDevice.getInfo(mDefaultDisplayDeviceInfo); + } + + private void initializeDefaultDisplay() { + // Bootstrap the default logical display using the default physical display. + mDefaultDisplayInfo = new DisplayInfo(); + mDefaultDisplayInfo.appWidth = mDefaultDisplayDeviceInfo.width; + mDefaultDisplayInfo.appHeight = mDefaultDisplayDeviceInfo.height; + mDefaultDisplayInfo.logicalWidth = mDefaultDisplayDeviceInfo.width; + mDefaultDisplayInfo.logicalHeight = mDefaultDisplayDeviceInfo.height; + mDefaultDisplayInfo.rotation = Surface.ROTATION_0; + mDefaultDisplayInfo.refreshRate = mDefaultDisplayDeviceInfo.refreshRate; + mDefaultDisplayInfo.logicalDensity = mDefaultDisplayDeviceInfo.density; + mDefaultDisplayInfo.physicalXDpi = mDefaultDisplayDeviceInfo.xDpi; + mDefaultDisplayInfo.physicalYDpi = mDefaultDisplayDeviceInfo.yDpi; + mDefaultDisplayInfo.smallestNominalAppWidth = mDefaultDisplayDeviceInfo.width; + mDefaultDisplayInfo.smallestNominalAppHeight = mDefaultDisplayDeviceInfo.height; + mDefaultDisplayInfo.largestNominalAppWidth = mDefaultDisplayDeviceInfo.width; + mDefaultDisplayInfo.largestNominalAppHeight = mDefaultDisplayDeviceInfo.height; + } +} diff --git a/services/java/com/android/server/display/HeadlessDisplayAdapter.java b/services/java/com/android/server/display/HeadlessDisplayAdapter.java new file mode 100644 index 0000000..d2a70d2 --- /dev/null +++ b/services/java/com/android/server/display/HeadlessDisplayAdapter.java @@ -0,0 +1,44 @@ +/* + * 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 com.android.server.display; + +/** + * Provides a fake default display for headless systems. + */ +public final class HeadlessDisplayAdapter extends DisplayAdapter { + private final DisplayDevice mDefaultDisplay = new DisplayDevice() { + @Override + public void getInfo(DisplayDeviceInfo outInfo) { + outInfo.width = 640; + outInfo.height = 480; + outInfo.refreshRate = 60; + outInfo.density = 1.0f; + outInfo.xDpi = 160; + outInfo.yDpi = 160; + } + }; + + @Override + public String getName() { + return "HeadlessDisplayAdapter"; + } + + @Override + public DisplayDevice[] getDisplayDevices() { + return new DisplayDevice[] { mDefaultDisplay }; + } +} diff --git a/services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java b/services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java new file mode 100644 index 0000000..89934d3 --- /dev/null +++ b/services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java @@ -0,0 +1,41 @@ +/* + * 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 com.android.server.display; + +/** + * A display adapter for the displays managed by Surface Flinger. + */ +public final class SurfaceFlingerDisplayAdapter extends DisplayAdapter { + private static native void nativeGetDefaultDisplayDeviceInfo(DisplayDeviceInfo outInfo); + + private final DisplayDevice mDefaultDisplay = new DisplayDevice() { + @Override + public void getInfo(DisplayDeviceInfo outInfo) { + nativeGetDefaultDisplayDeviceInfo(outInfo); + } + }; + + @Override + public String getName() { + return "SurfaceFlingerDisplayAdapter"; + } + + @Override + public DisplayDevice[] getDisplayDevices() { + return new DisplayDevice[] { mDefaultDisplay }; + } +} diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java index 2940b70..b3cd0f2 100644 --- a/services/java/com/android/server/power/PowerManagerService.java +++ b/services/java/com/android/server/power/PowerManagerService.java @@ -22,6 +22,7 @@ import com.android.server.EventLogTags; import com.android.server.LightsService; import com.android.server.Watchdog; import com.android.server.am.BatteryStatsService; +import com.android.server.display.DisplayManagerService; import android.app.ActivityManagerNative; import android.app.IActivityManager; @@ -254,6 +255,7 @@ public class PowerManagerService extends IPowerManager.Stub private IActivityManager mActivityService; private IBatteryStats mBatteryStats; private BatteryService mBatteryService; + private DisplayManagerService mDisplayManagerService; private SensorManager mSensorManager; private Sensor mProximitySensor; private Sensor mLightSensor; @@ -543,12 +545,13 @@ public class PowerManagerService extends IPowerManager.Stub private ContentQueryMap mSettings; public void init(Context context, LightsService lights, IActivityManager activity, - BatteryService battery) { + BatteryService battery, DisplayManagerService displayManagerService) { mLightsService = lights; mContext = context; mActivityService = activity; mBatteryStats = BatteryStatsService.getService(); mBatteryService = battery; + mDisplayManagerService = displayManagerService; mLcdLight = lights.getLight(LightsService.LIGHT_ID_BACKLIGHT); mButtonLight = lights.getLight(LightsService.LIGHT_ID_BUTTONS); diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java index b2cf3e0..f0b0e1f 100644 --- a/services/java/com/android/server/wm/DragState.java +++ b/services/java/com/android/server/wm/DragState.java @@ -125,8 +125,8 @@ class DragState { // The drag window covers the entire display mDragWindowHandle.frameLeft = 0; mDragWindowHandle.frameTop = 0; - mDragWindowHandle.frameRight = mService.mCurDisplayWidth; - mDragWindowHandle.frameBottom = mService.mCurDisplayHeight; + mDragWindowHandle.frameRight = mService.mDisplayInfo.logicalWidth; + mDragWindowHandle.frameBottom = mService.mDisplayInfo.logicalHeight; // Pause rotations before a drag. if (WindowManagerService.DEBUG_ORIENTATION) { diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index d0456ee..ac0fa87 100755 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -45,6 +45,8 @@ import com.android.server.AttributeCache; import com.android.server.EventLogTags; import com.android.server.Watchdog; import com.android.server.am.BatteryStatsService; +import com.android.server.display.DisplayDeviceInfo; +import com.android.server.display.DisplayManagerService; import com.android.server.input.InputManagerService; import com.android.server.power.PowerManagerService; import com.android.server.power.ShutdownThread; @@ -104,6 +106,7 @@ import android.util.SparseIntArray; import android.util.TypedValue; import android.view.Choreographer; import android.view.Display; +import android.view.DisplayInfo; import android.view.Gravity; import android.view.IApplicationToken; import android.view.IInputFilter; @@ -271,7 +274,6 @@ public class WindowManagerService extends IWindowManager.Stub private static final String SYSTEM_SECURE = "ro.secure"; private static final String SYSTEM_DEBUGGABLE = "ro.debuggable"; - private static final String SYSTEM_HEADLESS = "ro.config.headless"; /** * Condition waited on by {@link #reenableKeyguard} to know the call to @@ -482,14 +484,7 @@ public class WindowManagerService extends IWindowManager.Stub int mInitialDisplayHeight = 0; int mBaseDisplayWidth = 0; int mBaseDisplayHeight = 0; - int mCurDisplayWidth = 0; - int mCurDisplayHeight = 0; - int mAppDisplayWidth = 0; - int mAppDisplayHeight = 0; - int mSmallestDisplayWidth = 0; - int mSmallestDisplayHeight = 0; - int mLargestDisplayWidth = 0; - int mLargestDisplayHeight = 0; + final DisplayInfo mDisplayInfo = new DisplayInfo(); int mRotation = 0; int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; @@ -616,6 +611,7 @@ public class WindowManagerService extends IWindowManager.Stub float mAnimatorDurationScale = 1.0f; final InputManagerService mInputManager; + final DisplayManagerService mDisplayManager; // Who is holding the screen on. Session mHoldingScreenOn; @@ -785,9 +781,10 @@ public class WindowManagerService extends IWindowManager.Stub final boolean mOnlyCore; public static WindowManagerService main(Context context, - PowerManagerService pm, boolean haveInputMethods, boolean allowBootMsgs, + PowerManagerService pm, DisplayManagerService dm, + boolean haveInputMethods, boolean allowBootMsgs, boolean onlyCore) { - WMThread thr = new WMThread(context, pm, haveInputMethods, allowBootMsgs, onlyCore); + WMThread thr = new WMThread(context, pm, dm, haveInputMethods, allowBootMsgs, onlyCore); thr.start(); synchronized (thr) { @@ -806,15 +803,18 @@ public class WindowManagerService extends IWindowManager.Stub private final Context mContext; private final PowerManagerService mPM; + private final DisplayManagerService mDisplayManager; private final boolean mHaveInputMethods; private final boolean mAllowBootMessages; private final boolean mOnlyCore; public WMThread(Context context, PowerManagerService pm, + DisplayManagerService dm, boolean haveInputMethods, boolean allowBootMsgs, boolean onlyCore) { super("WindowManager"); mContext = context; mPM = pm; + mDisplayManager = dm; mHaveInputMethods = haveInputMethods; mAllowBootMessages = allowBootMsgs; mOnlyCore = onlyCore; @@ -825,7 +825,7 @@ public class WindowManagerService extends IWindowManager.Stub Looper.prepare(); //Looper.myLooper().setMessageLogging(new LogPrinter( // android.util.Log.DEBUG, TAG, android.util.Log.LOG_ID_SYSTEM)); - WindowManagerService s = new WindowManagerService(mContext, mPM, + WindowManagerService s = new WindowManagerService(mContext, mPM, mDisplayManager, mHaveInputMethods, mAllowBootMessages, mOnlyCore); android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_DISPLAY); @@ -892,6 +892,7 @@ public class WindowManagerService extends IWindowManager.Stub } private WindowManagerService(Context context, PowerManagerService pm, + DisplayManagerService displayManager, boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) { mContext = context; mHaveInputMethods = haveInputMethods; @@ -899,7 +900,8 @@ public class WindowManagerService extends IWindowManager.Stub mOnlyCore = onlyCore; mLimitedAlphaCompositing = context.getResources().getBoolean( com.android.internal.R.bool.config_sf_limitedAlpha); - mHeadless = "1".equals(SystemProperties.get(SYSTEM_HEADLESS, "0")); + mDisplayManager = displayManager; + mHeadless = displayManager.isHeadless(); mPowerManager = pm; mPowerManager.setPolicy(mPolicy); @@ -1650,8 +1652,8 @@ public class WindowManagerService extends IWindowManager.Stub mInnerFields.mWallpaperMayChange = false; int changed = 0; - final int dw = mAppDisplayWidth; - final int dh = mAppDisplayHeight; + final int dw = mDisplayInfo.appWidth; + final int dh = mDisplayInfo.appHeight; // First find top-most window that has asked to be on top of the // wallpaper; all wallpapers go behind it. @@ -2060,8 +2062,8 @@ public class WindowManagerService extends IWindowManager.Stub } void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) { - final int dw = mAppDisplayWidth; - final int dh = mAppDisplayHeight; + final int dw = mDisplayInfo.appWidth; + final int dh = mDisplayInfo.appHeight; WindowState target = mWallpaperTarget; if (target != null) { @@ -2123,8 +2125,8 @@ public class WindowManagerService extends IWindowManager.Stub void updateWallpaperVisibilityLocked() { final boolean visible = isWallpaperVisible(mWallpaperTarget); - final int dw = mAppDisplayWidth; - final int dh = mAppDisplayHeight; + final int dw = mDisplayInfo.appWidth; + final int dh = mDisplayInfo.appHeight; int curTokenIndex = mWallpaperTokens.size(); while (curTokenIndex > 0) { @@ -2699,9 +2701,11 @@ public class WindowManagerService extends IWindowManager.Stub mTmpFloats[Matrix.MSKEW_X] = dsdy; mTmpFloats[Matrix.MSCALE_Y] = dtdy; matrix.setValues(mTmpFloats); - final RectF dispRect = new RectF(0, 0, mCurDisplayWidth, mCurDisplayHeight); + final RectF dispRect = new RectF(0, 0, + mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); matrix.mapRect(dispRect); - window.mGivenTouchableRegion.set(0, 0, mCurDisplayWidth, mCurDisplayHeight); + window.mGivenTouchableRegion.set(0, 0, + mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top, (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE); window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; @@ -2981,7 +2985,8 @@ public class WindowManagerService extends IWindowManager.Stub configChanged = updateOrientationFromAppTokensLocked(false); performLayoutAndPlaceSurfacesLocked(); if (toBeDisplayed && win.mIsWallpaper) { - updateWallpaperOffsetLocked(win, mAppDisplayWidth, mAppDisplayHeight, false); + updateWallpaperOffsetLocked(win, + mDisplayInfo.appWidth, mDisplayInfo.appHeight, false); } if (win.mAppToken != null) { win.mAppToken.updateReportedVisibilityLocked(); @@ -3201,8 +3206,8 @@ public class WindowManagerService extends IWindowManager.Stub } if (enter) { // Entering app zooms out from the center of the initial rect. - float scaleW = mNextAppTransitionStartWidth / (float) mAppDisplayWidth; - float scaleH = mNextAppTransitionStartHeight / (float) mAppDisplayHeight; + float scaleW = mNextAppTransitionStartWidth / (float) mDisplayInfo.appWidth; + float scaleH = mNextAppTransitionStartHeight / (float) mDisplayInfo.appHeight; Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1, computePivot(mNextAppTransitionStartX, scaleW), computePivot(mNextAppTransitionStartY, scaleH)); @@ -3222,8 +3227,8 @@ public class WindowManagerService extends IWindowManager.Stub final Interpolator interpolator = AnimationUtils.loadInterpolator(mContext, com.android.internal.R.interpolator.decelerate_cubic); a.setInterpolator(interpolator); - a.initialize(mAppDisplayWidth, mAppDisplayHeight, - mAppDisplayWidth, mAppDisplayHeight); + a.initialize(mDisplayInfo.appWidth, mDisplayInfo.appHeight, + mDisplayInfo.appWidth, mDisplayInfo.appHeight); return a; } @@ -3252,8 +3257,8 @@ public class WindowManagerService extends IWindowManager.Stub if (thumb) { // Animation for zooming thumbnail from its initial size to // filling the screen. - float scaleW = mAppDisplayWidth/thumbWidth; - float scaleH = mAppDisplayHeight/thumbHeight; + float scaleW = mDisplayInfo.appWidth/thumbWidth; + float scaleH = mDisplayInfo.appHeight/thumbHeight; Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH, computePivot(mNextAppTransitionStartX, 1/scaleW), @@ -3273,8 +3278,8 @@ public class WindowManagerService extends IWindowManager.Stub a = set; } else if (enter) { // Entering app zooms out from the center of the thumbnail. - float scaleW = thumbWidth / mAppDisplayWidth; - float scaleH = thumbHeight / mAppDisplayHeight; + float scaleW = thumbWidth / mDisplayInfo.appWidth; + float scaleH = thumbHeight / mDisplayInfo.appHeight; Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1, computePivot(mNextAppTransitionStartX, scaleW), computePivot(mNextAppTransitionStartY, scaleH)); @@ -3300,8 +3305,8 @@ public class WindowManagerService extends IWindowManager.Stub final Interpolator interpolator = AnimationUtils.loadInterpolator(mContext, com.android.internal.R.interpolator.decelerate_quad); a.setInterpolator(interpolator); - a.initialize(mAppDisplayWidth, mAppDisplayHeight, - mAppDisplayWidth, mAppDisplayHeight); + a.initialize(mDisplayInfo.appWidth, mDisplayInfo.appHeight, + mDisplayInfo.appWidth, mDisplayInfo.appHeight); return a; } @@ -5498,8 +5503,8 @@ public class WindowManagerService extends IWindowManager.Stub synchronized(mWindowMap) { long ident = Binder.clearCallingIdentity(); - dw = mCurDisplayWidth; - dh = mCurDisplayHeight; + dw = mDisplayInfo.logicalWidth; + dh = mDisplayInfo.logicalHeight; int aboveAppLayer = mPolicy.windowTypeToLayerLw( WindowManager.LayoutParams.TYPE_APPLICATION) * TYPE_LAYER_MULTIPLIER @@ -5793,8 +5798,7 @@ public class WindowManagerService extends IWindowManager.Stub mWaitingForConfig = true; mLayoutNeeded = true; startFreezingDisplayLocked(inTransaction); - mInputManager.setDisplayOrientation(0, rotation, - mDisplay != null ? mDisplay.getExternalRotation() : Surface.ROTATION_0); + mInputManager.setDisplayOrientation(0, rotation, Surface.ROTATION_0); // We need to update our screen size information to match the new // rotation. Note that this is redundant with the later call to @@ -5816,7 +5820,7 @@ public class WindowManagerService extends IWindowManager.Stub && mAnimator.mScreenRotationAnimation.hasScreenshot()) { if (mAnimator.mScreenRotationAnimation.setRotation(rotation, mFxSession, MAX_ANIMATION_DURATION, mTransitionAnimationScale, - mCurDisplayWidth, mCurDisplayHeight)) { + mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight)) { updateLayoutToAnimationLocked(); } } @@ -6315,18 +6319,18 @@ public class WindowManagerService extends IWindowManager.Stub private void adjustDisplaySizeRanges(int rotation, int dw, int dh) { final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation); - if (width < mSmallestDisplayWidth) { - mSmallestDisplayWidth = width; + if (width < mDisplayInfo.smallestNominalAppWidth) { + mDisplayInfo.smallestNominalAppWidth = width; } - if (width > mLargestDisplayWidth) { - mLargestDisplayWidth = width; + if (width > mDisplayInfo.largestNominalAppWidth) { + mDisplayInfo.largestNominalAppWidth = width; } final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation); - if (height < mSmallestDisplayHeight) { - mSmallestDisplayHeight = height; + if (height < mDisplayInfo.smallestNominalAppHeight) { + mDisplayInfo.smallestNominalAppHeight = height; } - if (height > mLargestDisplayHeight) { - mLargestDisplayHeight = height; + if (height > mDisplayInfo.largestNominalAppHeight) { + mDisplayInfo.largestNominalAppHeight = height; } } @@ -6423,10 +6427,10 @@ public class WindowManagerService extends IWindowManager.Stub unrotDw = dw; unrotDh = dh; } - mSmallestDisplayWidth = 1<<30; - mSmallestDisplayHeight = 1<<30; - mLargestDisplayWidth = 0; - mLargestDisplayHeight = 0; + mDisplayInfo.smallestNominalAppWidth = 1<<30; + mDisplayInfo.smallestNominalAppHeight = 1<<30; + mDisplayInfo.largestNominalAppWidth = 0; + mDisplayInfo.largestNominalAppHeight = 0; adjustDisplaySizeRanges(Surface.ROTATION_0, unrotDw, unrotDh); adjustDisplaySizeRanges(Surface.ROTATION_90, unrotDh, unrotDw); adjustDisplaySizeRanges(Surface.ROTATION_180, unrotDw, unrotDh); @@ -6437,7 +6441,7 @@ public class WindowManagerService extends IWindowManager.Stub sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw); sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh); sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw); - outConfig.smallestScreenWidthDp = (int)(mSmallestDisplayWidth / density); + outConfig.smallestScreenWidthDp = (int)(mDisplayInfo.smallestNominalAppWidth / density); outConfig.screenLayout = sl; } @@ -6481,33 +6485,25 @@ public class WindowManagerService extends IWindowManager.Stub || mRotation == Surface.ROTATION_270); final int realdw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; final int realdh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; + int dw = realdw; + int dh = realdh; - synchronized(mDisplaySizeLock) { - if (mAltOrientation) { - mCurDisplayWidth = realdw; - mCurDisplayHeight = realdh; - if (realdw > realdh) { - // Turn landscape into portrait. - int maxw = (int)(realdh/1.3f); - if (maxw < realdw) { - mCurDisplayWidth = maxw; - } - } else { - // Turn portrait into landscape. - int maxh = (int)(realdw/1.3f); - if (maxh < realdh) { - mCurDisplayHeight = maxh; - } + if (mAltOrientation) { + if (realdw > realdh) { + // Turn landscape into portrait. + int maxw = (int)(realdh/1.3f); + if (maxw < realdw) { + dw = maxw; } } else { - mCurDisplayWidth = realdw; - mCurDisplayHeight = realdh; + // Turn portrait into landscape. + int maxh = (int)(realdw/1.3f); + if (maxh < realdh) { + dh = maxh; + } } } - final int dw = mCurDisplayWidth; - final int dh = mCurDisplayHeight; - if (config != null) { int orientation = Configuration.ORIENTATION_SQUARE; if (dw < dh) { @@ -6518,25 +6514,26 @@ public class WindowManagerService extends IWindowManager.Stub config.orientation = orientation; } - // Update real display metrics. - mDisplay.getMetricsWithSize(mRealDisplayMetrics, mCurDisplayWidth, mCurDisplayHeight); - // Update application display metrics. - final DisplayMetrics dm = mDisplayMetrics; final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation); final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation); synchronized(mDisplaySizeLock) { - mAppDisplayWidth = appWidth; - mAppDisplayHeight = appHeight; - mAnimator.setDisplayDimensions(mCurDisplayWidth, mCurDisplayHeight, - mAppDisplayWidth, mAppDisplayHeight); + mDisplayInfo.rotation = mRotation; + mDisplayInfo.logicalWidth = dw; + mDisplayInfo.logicalHeight = dh; + mDisplayInfo.appWidth = appWidth; + mDisplayInfo.appHeight = appHeight; + mDisplayInfo.getLogicalMetrics(mRealDisplayMetrics, null); + mDisplayInfo.getAppMetrics(mDisplayMetrics, null); + mDisplayManager.setDefaultDisplayInfo(mDisplayInfo); + + mAnimator.setDisplayDimensions(dw, dh, appWidth, appHeight); } if (false) { - Slog.i(TAG, "Set app display size: " + mAppDisplayWidth - + " x " + mAppDisplayHeight); + Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight); } - mDisplay.getMetricsWithSize(dm, mAppDisplayWidth, mAppDisplayHeight); + final DisplayMetrics dm = mDisplayMetrics; mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm, mCompatDisplayMetrics); @@ -6843,27 +6840,26 @@ public class WindowManagerService extends IWindowManager.Stub mDisplay = wm.getDefaultDisplay(); mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( PackageManager.FEATURE_TOUCHSCREEN); + synchronized(mDisplaySizeLock) { - mInitialDisplayWidth = mDisplay.getRawWidth(); - mInitialDisplayHeight = mDisplay.getRawHeight(); - int rot = mDisplay.getRotation(); - if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { - // If the screen is currently rotated, we need to swap the - // initial width and height to get the true natural values. - int tmp = mInitialDisplayWidth; - mInitialDisplayWidth = mInitialDisplayHeight; - mInitialDisplayHeight = tmp; - } - mBaseDisplayWidth = mCurDisplayWidth = mAppDisplayWidth = mInitialDisplayWidth; - mBaseDisplayHeight = mCurDisplayHeight = mAppDisplayHeight = mInitialDisplayHeight; - mAnimator.setDisplayDimensions(mCurDisplayWidth, mCurDisplayHeight, - mAppDisplayWidth, mAppDisplayHeight); + // Bootstrap the default logical display from the display manager. + mDisplayManager.getDisplayInfo(Display.DEFAULT_DISPLAY, mDisplayInfo); + mInitialDisplayWidth = mDisplayInfo.logicalWidth; + mInitialDisplayHeight = mDisplayInfo.logicalHeight; + mBaseDisplayWidth = mInitialDisplayWidth; + mBaseDisplayHeight = mInitialDisplayHeight; + + mAnimator.setDisplayDimensions(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight, + mDisplayInfo.appWidth, mDisplayInfo.appHeight); } + + DisplayDeviceInfo info = new DisplayDeviceInfo(); + mDisplayManager.getDefaultExternalDisplayDeviceInfo(info); mInputManager.setDisplaySize(Display.DEFAULT_DISPLAY, - mDisplay.getRawWidth(), mDisplay.getRawHeight(), - mDisplay.getRawExternalWidth(), mDisplay.getRawExternalHeight()); + mInitialDisplayWidth, mInitialDisplayHeight, + info.width, info.height); mInputManager.setDisplayOrientation(Display.DEFAULT_DISPLAY, - mDisplay.getRotation(), mDisplay.getExternalRotation()); + mDisplay.getRotation(), Surface.ROTATION_0); mPolicy.setInitialDisplaySize(mDisplay, mInitialDisplayWidth, mInitialDisplayHeight); } @@ -7471,20 +7467,6 @@ public class WindowManagerService extends IWindowManager.Stub return false; } - public void getDisplaySize(Point size) { - synchronized(mDisplaySizeLock) { - size.x = mAppDisplayWidth; - size.y = mAppDisplayHeight; - } - } - - public void getRealDisplaySize(Point size) { - synchronized(mDisplaySizeLock) { - size.x = mCurDisplayWidth; - size.y = mCurDisplayHeight; - } - } - public void getInitialDisplaySize(Point size) { synchronized(mDisplaySizeLock) { size.x = mInitialDisplayWidth; @@ -7492,23 +7474,6 @@ public class WindowManagerService extends IWindowManager.Stub } } - public int getMaximumSizeDimension() { - synchronized(mDisplaySizeLock) { - // Do this based on the raw screen size, until we are smarter. - return mBaseDisplayWidth > mBaseDisplayHeight - ? mBaseDisplayWidth : mBaseDisplayHeight; - } - } - - public void getCurrentSizeRange(Point smallestSize, Point largestSize) { - synchronized(mDisplaySizeLock) { - smallestSize.x = mSmallestDisplayWidth; - smallestSize.y = mSmallestDisplayHeight; - largestSize.x = mLargestDisplayWidth; - largestSize.y = mLargestDisplayHeight; - } - } - public void setForcedDisplaySize(int longDimen, int shortDimen) { synchronized(mWindowMap) { int width, height; @@ -7899,8 +7864,8 @@ public class WindowManagerService extends IWindowManager.Stub mLayoutNeeded = false; - final int dw = mCurDisplayWidth; - final int dh = mCurDisplayHeight; + final int dw = mDisplayInfo.logicalWidth; + final int dh = mDisplayInfo.logicalHeight; final int NFW = mFakeWindows.size(); for (int i=0; i<NFW; i++) { @@ -8492,8 +8457,8 @@ public class WindowManagerService extends IWindowManager.Stub if (!mAnimator.isDimming(winAnimator)) { final int width, height; if (attrs.type == WindowManager.LayoutParams.TYPE_BOOT_PROGRESS) { - width = mCurDisplayWidth; - height = mCurDisplayHeight; + width = mDisplayInfo.logicalWidth; + height = mDisplayInfo.logicalHeight; } else { width = innerDw; height = innerDh; @@ -8537,10 +8502,10 @@ public class WindowManagerService extends IWindowManager.Stub } final long currentTime = SystemClock.uptimeMillis(); - final int dw = mCurDisplayWidth; - final int dh = mCurDisplayHeight; - final int innerDw = mAppDisplayWidth; - final int innerDh = mAppDisplayHeight; + final int dw = mDisplayInfo.logicalWidth; + final int dh = mDisplayInfo.logicalHeight; + final int innerDw = mDisplayInfo.appWidth; + final int innerDh = mDisplayInfo.appHeight; int i; @@ -9456,7 +9421,7 @@ public class WindowManagerService extends IWindowManager.Stub } mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext, - mFxSession, inTransaction, mCurDisplayWidth, mCurDisplayHeight, + mFxSession, inTransaction, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight, mDisplay.getRotation()); } } @@ -9486,7 +9451,7 @@ public class WindowManagerService extends IWindowManager.Stub && mAnimator.mScreenRotationAnimation.hasScreenshot()) { if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); if (mAnimator.mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, - mTransitionAnimationScale, mCurDisplayWidth, mCurDisplayHeight)) { + mTransitionAnimationScale, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight)) { updateLayoutToAnimationLocked(); } else { mAnimator.mScreenRotationAnimation.kill(); @@ -9935,19 +9900,21 @@ public class WindowManagerService extends IWindowManager.Stub pw.print(" base="); pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight); } - final int rawWidth = mDisplay.getRawWidth(); - final int rawHeight = mDisplay.getRawHeight(); - if (rawWidth != mCurDisplayWidth || rawHeight != mCurDisplayHeight) { - pw.print(" raw="); pw.print(rawWidth); pw.print("x"); pw.print(rawHeight); + if (mInitialDisplayWidth != mDisplayInfo.logicalWidth + || mInitialDisplayHeight != mDisplayInfo.logicalHeight) { + pw.print(" init="); pw.print(mInitialDisplayWidth); + pw.print("x"); pw.print(mInitialDisplayHeight); } pw.print(" cur="); - pw.print(mCurDisplayWidth); pw.print("x"); pw.print(mCurDisplayHeight); + pw.print(mDisplayInfo.logicalWidth); + pw.print("x"); pw.print(mDisplayInfo.logicalHeight); pw.print(" app="); - pw.print(mAppDisplayWidth); pw.print("x"); pw.print(mAppDisplayHeight); - pw.print(" rng="); pw.print(mSmallestDisplayWidth); - pw.print("x"); pw.print(mSmallestDisplayHeight); - pw.print("-"); pw.print(mLargestDisplayWidth); - pw.print("x"); pw.println(mLargestDisplayHeight); + pw.print(mDisplayInfo.appWidth); + pw.print("x"); pw.print(mDisplayInfo.appHeight); + pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth); + pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight); + pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth); + pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight); } else { pw.println(" NO DISPLAY"); } diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java index 94fd199..d371828 100644 --- a/services/java/com/android/server/wm/WindowState.java +++ b/services/java/com/android/server/wm/WindowState.java @@ -480,7 +480,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) { mService.updateWallpaperOffsetLocked(this, - mService.mAppDisplayWidth, mService.mAppDisplayHeight, false); + mService.mDisplayInfo.appWidth, mService.mDisplayInfo.appHeight, false); } if (WindowManagerService.localLOGV) { diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java index f08204f..ce87f4c 100644 --- a/services/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/java/com/android/server/wm/WindowStateAnimator.java @@ -151,8 +151,8 @@ class WindowStateAnimator { mAnimator = service.mAnimator; mPolicy = service.mPolicy; mContext = service.mContext; - mAnimDw = service.mAppDisplayWidth; - mAnimDh = service.mAppDisplayHeight; + mAnimDw = service.mDisplayInfo.appWidth; + mAnimDh = service.mDisplayInfo.appHeight; mWin = win; mAttachedWinAnimator = win.mAttachedWindow == null @@ -248,8 +248,8 @@ class WindowStateAnimator { " scale=" + mService.mWindowAnimationScale); mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(), mAnimDw, mAnimDh); - mAnimDw = mService.mAppDisplayWidth; - mAnimDh = mService.mAppDisplayHeight; + mAnimDw = mService.mDisplayInfo.appWidth; + mAnimDh = mService.mDisplayInfo.appHeight; mAnimation.setStartTime(currentTime); mLocalAnimating = true; mAnimating = true; @@ -1102,7 +1102,7 @@ class WindowStateAnimator { WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; if ((w.mAttrs.flags & LayoutParams.FLAG_DIM_BEHIND) != 0) { mService.startDimming(this, w.mExiting ? 0 : w.mAttrs.dimAmount, - mService.mAppDisplayWidth, mService.mAppDisplayHeight); + mService.mDisplayInfo.appWidth, mService.mDisplayInfo.appHeight); } } catch (RuntimeException e) { // If something goes wrong with the surface (such diff --git a/services/jni/Android.mk b/services/jni/Android.mk index d097a93..43e59b2 100644 --- a/services/jni/Android.mk +++ b/services/jni/Android.mk @@ -4,6 +4,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ com_android_server_AlarmManagerService.cpp \ com_android_server_BatteryService.cpp \ + com_android_server_display_SurfaceFlingerDisplayAdapter.cpp \ com_android_server_input_InputApplicationHandle.cpp \ com_android_server_input_InputManagerService.cpp \ com_android_server_input_InputWindowHandle.cpp \ diff --git a/services/jni/com_android_server_display_SurfaceFlingerDisplayAdapter.cpp b/services/jni/com_android_server_display_SurfaceFlingerDisplayAdapter.cpp new file mode 100644 index 0000000..162cbaf --- /dev/null +++ b/services/jni/com_android_server_display_SurfaceFlingerDisplayAdapter.cpp @@ -0,0 +1,94 @@ +/* + * 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. + */ + +#define LOG_TAG "SurfaceFlingerDisplayAdapter" + +#include "JNIHelp.h" +#include "jni.h" +#include <android_runtime/AndroidRuntime.h> + +#include <gui/SurfaceComposerClient.h> +#include <ui/DisplayInfo.h> + +#include <utils/Log.h> + +namespace android { + +static struct { + jfieldID width; + jfieldID height; + jfieldID refreshRate; + jfieldID density; + jfieldID xDpi; + jfieldID yDpi; +} gDisplayDeviceInfoClassInfo; + + +static void nativeGetDefaultDisplayDeviceInfo(JNIEnv* env, jclass clazz, jobject infoObj) { + DisplayInfo info; + status_t err = SurfaceComposerClient::getDisplayInfo(0, &info); + if (err < 0) { + jniThrowExceptionFmt(env, "java/lang/RuntimeException", + "Could not get display info. err=%d", err); + return; + } + + bool rotated = (info.orientation == DISPLAY_ORIENTATION_90 + || info.orientation == DISPLAY_ORIENTATION_270); + env->SetIntField(infoObj, gDisplayDeviceInfoClassInfo.width, + rotated ? info.h : info.w); + env->SetIntField(infoObj, gDisplayDeviceInfoClassInfo.height, + rotated ? info.w : info.h); + env->SetFloatField(infoObj, gDisplayDeviceInfoClassInfo.refreshRate, info.fps); + env->SetFloatField(infoObj, gDisplayDeviceInfoClassInfo.density, info.density); + env->SetFloatField(infoObj, gDisplayDeviceInfoClassInfo.xDpi, info.xdpi); + env->SetFloatField(infoObj, gDisplayDeviceInfoClassInfo.yDpi, info.ydpi); +} + + +static JNINativeMethod gSurfaceFlingerDisplayAdapterMethods[] = { + /* name, signature, funcPtr */ + { "nativeGetDefaultDisplayDeviceInfo", + "(Lcom/android/server/display/DisplayDeviceInfo;)V", + (void*) nativeGetDefaultDisplayDeviceInfo }, +}; + +#define FIND_CLASS(var, className) \ + var = env->FindClass(className); \ + LOG_FATAL_IF(! var, "Unable to find class " className); + +#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ + var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ + LOG_FATAL_IF(! var, "Unable to find field " fieldName); + +int register_android_server_display_SurfaceFlingerDisplayAdapter(JNIEnv* env) { + int res = jniRegisterNativeMethods(env, + "com/android/server/display/SurfaceFlingerDisplayAdapter", + gSurfaceFlingerDisplayAdapterMethods, NELEM(gSurfaceFlingerDisplayAdapterMethods)); + LOG_FATAL_IF(res < 0, "Unable to register native methods."); + + jclass clazz; + FIND_CLASS(clazz, "com/android/server/display/DisplayDeviceInfo"); + GET_FIELD_ID(gDisplayDeviceInfoClassInfo.width, clazz, "width", "I"); + GET_FIELD_ID(gDisplayDeviceInfoClassInfo.height, clazz, "height", "I"); + GET_FIELD_ID(gDisplayDeviceInfoClassInfo.refreshRate, clazz, "refreshRate", "F"); + GET_FIELD_ID(gDisplayDeviceInfoClassInfo.density, clazz, "density", "F"); + GET_FIELD_ID(gDisplayDeviceInfoClassInfo.xDpi, clazz, "xDpi", "F"); + GET_FIELD_ID(gDisplayDeviceInfoClassInfo.yDpi, clazz, "yDpi", "F"); + return 0; +} + +} /* namespace android */ diff --git a/services/jni/onload.cpp b/services/jni/onload.cpp index 423ebd1..50873fc 100644 --- a/services/jni/onload.cpp +++ b/services/jni/onload.cpp @@ -22,6 +22,7 @@ namespace android { int register_android_server_AlarmManagerService(JNIEnv* env); int register_android_server_BatteryService(JNIEnv* env); +int register_android_server_display_SurfaceFlingerDisplayAdapter(JNIEnv* env); int register_android_server_InputApplicationHandle(JNIEnv* env); int register_android_server_InputWindowHandle(JNIEnv* env); int register_android_server_InputManager(JNIEnv* env); @@ -51,6 +52,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) register_android_server_PowerManagerService(env); register_android_server_SerialService(env); + register_android_server_display_SurfaceFlingerDisplayAdapter(env); register_android_server_InputApplicationHandle(env); register_android_server_InputWindowHandle(env); register_android_server_InputManager(env); diff --git a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java index 8868c65..6ccdcb6 100644 --- a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java +++ b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java @@ -31,57 +31,4 @@ import android.os.RemoteException; */ public class Display_Delegate { - // ---- Overridden methods ---- - - @LayoutlibDelegate - public static IWindowManager getWindowManager() { - return RenderAction.getCurrentContext().getIWindowManager(); - } - - // ---- Native methods ---- - - @LayoutlibDelegate - /*package*/ static int getDisplayCount() { - return 1; - } - - @LayoutlibDelegate - /** @hide special for when we are faking the screen size. */ - /*package*/ static int getRawWidthNative(Display theDisplay) { - // same as real since we're not faking compatibility mode. - return RenderAction.getCurrentContext().getIWindowManager().getMetrics().widthPixels; - } - - @LayoutlibDelegate - /** @hide special for when we are faking the screen size. */ - /*package*/ static int getRawHeightNative(Display theDisplay) { - // same as real since we're not faking compatibility mode. - return RenderAction.getCurrentContext().getIWindowManager().getMetrics().heightPixels; - } - - @LayoutlibDelegate - /*package*/ static int getOrientation(Display theDisplay) { - try { - // always dynamically query for the current window manager - return getWindowManager().getRotation(); - } catch (RemoteException e) { - // this will never been thrown since this is not a true RPC. - } - - return Surface.ROTATION_0; - } - - @LayoutlibDelegate - /*package*/ static void nativeClassInit() { - // not needed for now. - } - - @LayoutlibDelegate - /*package*/ static void init(Display theDisplay, int display) { - // always dynamically query for the current window manager - BridgeWindowManager wm = RenderAction.getCurrentContext().getIWindowManager(); - theDisplay.mDensity = wm.getMetrics().density; - theDisplay.mDpiX = wm.getMetrics().xdpi; - theDisplay.mDpiY = wm.getMetrics().ydpi; - } } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java index 3e56b60..2acccd3 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java @@ -29,6 +29,7 @@ import android.os.IRemoteCallback; import android.os.RemoteException; import android.util.DisplayMetrics; import android.view.Display; +import android.view.DisplayInfo; import android.view.Display_Delegate; import android.view.Gravity; import android.view.IApplicationToken; @@ -70,20 +71,14 @@ public class BridgeWindowManager implements IWindowManager { } @Override - public int getMaximumSizeDimension() throws RemoteException { - return 0; - } - - @Override - public void getCurrentSizeRange(Point smallestSize, Point largestSize) { - } - - @Override - public void getDisplaySize(Point arg0) throws RemoteException { - } - - @Override - public void getRealDisplaySize(Point arg0) throws RemoteException { + public void getDisplayInfo(int arg0, DisplayInfo arg1) throws RemoteException { + arg1.appWidth = mMetrics.widthPixels; + arg1.appHeight = mMetrics.heightPixels; + arg1.logicalWidth = mMetrics.widthPixels; + arg1.logicalHeight = mMetrics.heightPixels; + arg1.logicalDensity = mMetrics.density; + arg1.physicalXDpi = mMetrics.xdpi; + arg1.physicalYDpi = mMetrics.ydpi; } // ---- unused implementation of IWindowManager ---- |