Home | History | Annotate | Download | only in view
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.view;
     18 
     19 import android.content.res.CompatibilityInfo;
     20 import android.graphics.Point;
     21 import android.graphics.Rect;
     22 import android.os.RemoteException;
     23 import android.os.ServiceManager;
     24 import android.os.SystemClock;
     25 import android.util.DisplayMetrics;
     26 import android.util.Slog;
     27 
     28 /**
     29  * Provides information about the display size and density.
     30  */
     31 public class Display {
     32     static final String TAG = "Display";
     33     static final boolean DEBUG_DISPLAY_SIZE = false;
     34 
     35     /**
     36      * The default Display id.
     37      */
     38     public static final int DEFAULT_DISPLAY = 0;
     39 
     40     /**
     41      * Use {@link android.view.WindowManager#getDefaultDisplay()
     42      * WindowManager.getDefaultDisplay()} to create a Display object.
     43      * Display gives you access to some information about a particular display
     44      * connected to the device.
     45      */
     46     Display(int display, CompatibilityInfoHolder compatInfo) {
     47         // initalize the statics when this class is first instansiated. This is
     48         // done here instead of in the static block because Zygote
     49         synchronized (sStaticInit) {
     50             if (!sInitialized) {
     51                 nativeClassInit();
     52                 sInitialized = true;
     53             }
     54         }
     55         mCompatibilityInfo = compatInfo != null ? compatInfo : new CompatibilityInfoHolder();
     56         mDisplay = display;
     57         init(display);
     58     }
     59 
     60     /**
     61      * Returns the index of this display.  This is currently undefined; do
     62      * not use.
     63      */
     64     public int getDisplayId() {
     65         return mDisplay;
     66     }
     67 
     68     /**
     69      * Returns the number of displays connected to the device.  This is
     70      * currently undefined; do not use.
     71      */
     72     native static int getDisplayCount();
     73 
     74     /**
     75      * Gets the size of the display, in pixels.
     76      * <p>
     77      * Note that this value should <em>not</em> be used for computing layouts,
     78      * since a device will typically have screen decoration (such as a status bar)
     79      * along the edges of the display that reduce the amount of application
     80      * space available from the size returned here.  Layouts should instead use
     81      * the window size.
     82      * </p><p>
     83      * The size is adjusted based on the current rotation of the display.
     84      * </p><p>
     85      * The size returned by this method does not necessarily represent the
     86      * actual raw size (native resolution) of the display.  The returned size may
     87      * be adjusted to exclude certain system decor elements that are always visible.
     88      * It may also be scaled to provide compatibility with older applications that
     89      * were originally designed for smaller displays.
     90      * </p>
     91      *
     92      * @param outSize A {@link Point} object to receive the size information.
     93      */
     94     public void getSize(Point outSize) {
     95         getSizeInternal(outSize, true);
     96     }
     97 
     98     private void getSizeInternal(Point outSize, boolean doCompat) {
     99         try {
    100             IWindowManager wm = getWindowManager();
    101             if (wm != null) {
    102                 wm.getDisplaySize(outSize);
    103                 CompatibilityInfo ci;
    104                 if (doCompat && (ci=mCompatibilityInfo.getIfNeeded()) != null) {
    105                     synchronized (mTmpMetrics) {
    106                         mTmpMetrics.noncompatWidthPixels = outSize.x;
    107                         mTmpMetrics.noncompatHeightPixels = outSize.y;
    108                         mTmpMetrics.density = mDensity;
    109                         ci.applyToDisplayMetrics(mTmpMetrics);
    110                         outSize.x = mTmpMetrics.widthPixels;
    111                         outSize.y = mTmpMetrics.heightPixels;
    112                     }
    113                 }
    114             } else {
    115                 // This is just for boot-strapping, initializing the
    116                 // system process before the window manager is up.
    117                 outSize.x = getRawWidth();
    118                 outSize.y = getRawHeight();
    119             }
    120             if (false) {
    121                 RuntimeException here = new RuntimeException("here");
    122                 here.fillInStackTrace();
    123                 Slog.v(TAG, "Returning display size: " + outSize, here);
    124             }
    125             if (DEBUG_DISPLAY_SIZE && doCompat) Slog.v(
    126                     TAG, "Returning display size: " + outSize);
    127         } catch (RemoteException e) {
    128             Slog.w("Display", "Unable to get display size", e);
    129         }
    130     }
    131 
    132     /**
    133      * Gets the size of the display as a rectangle, in pixels.
    134      *
    135      * @param outSize A {@link Rect} object to receive the size information.
    136      * @see #getSize(Point)
    137      */
    138     public void getRectSize(Rect outSize) {
    139         synchronized (mTmpPoint) {
    140             getSizeInternal(mTmpPoint, true);
    141             outSize.set(0, 0, mTmpPoint.x, mTmpPoint.y);
    142         }
    143     }
    144 
    145     /**
    146      * Return the maximum screen size dimension that will happen.  This is
    147      * mostly for wallpapers.
    148      * @hide
    149      */
    150     public int getMaximumSizeDimension() {
    151         try {
    152             IWindowManager wm = getWindowManager();
    153             return wm.getMaximumSizeDimension();
    154         } catch (RemoteException e) {
    155             Slog.w("Display", "Unable to get display maximum size dimension", e);
    156             return 0;
    157         }
    158     }
    159 
    160     /**
    161      * @deprecated Use {@link #getSize(Point)} instead.
    162      */
    163     @Deprecated
    164     public int getWidth() {
    165         synchronized (mTmpPoint) {
    166             long now = SystemClock.uptimeMillis();
    167             if (now > (mLastGetTime+20)) {
    168                 getSizeInternal(mTmpPoint, true);
    169                 mLastGetTime = now;
    170             }
    171             return mTmpPoint.x;
    172         }
    173     }
    174 
    175     /**
    176      * @deprecated Use {@link #getSize(Point)} instead.
    177      */
    178     @Deprecated
    179     public int getHeight() {
    180         synchronized (mTmpPoint) {
    181             long now = SystemClock.uptimeMillis();
    182             if (now > (mLastGetTime+20)) {
    183                 getSizeInternal(mTmpPoint, true);
    184                 mLastGetTime = now;
    185             }
    186             return mTmpPoint.y;
    187         }
    188     }
    189 
    190     /**
    191      * Gets the real size of the display without subtracting any window decor or
    192      * applying any compatibility scale factors.
    193      * <p>
    194      * The real size may be smaller than the raw size when the window manager
    195      * is emulating a smaller display (using adb shell am display-size).
    196      * </p><p>
    197      * The size is adjusted based on the current rotation of the display.
    198      * </p>
    199      * @hide
    200      */
    201     public void getRealSize(Point outSize) {
    202         try {
    203             IWindowManager wm = getWindowManager();
    204             if (wm != null) {
    205                 wm.getRealDisplaySize(outSize);
    206             } else {
    207                 // This is just for boot-strapping, initializing the
    208                 // system process before the window manager is up.
    209                 outSize.x = getRawWidth();
    210                 outSize.y = getRawHeight();
    211             }
    212             if (DEBUG_DISPLAY_SIZE) Slog.v(
    213                     TAG, "Returning real display size: " + outSize);
    214         } catch (RemoteException e) {
    215             Slog.w("Display", "Unable to get real display size", e);
    216         }
    217     }
    218 
    219     /**
    220      * Gets the raw width of the display, in pixels.
    221      * <p>
    222      * The size is adjusted based on the current rotation of the display.
    223      * </p>
    224      * @hide
    225      */
    226     public int getRawWidth() {
    227         int w = getRawWidthNative();
    228         if (DEBUG_DISPLAY_SIZE) Slog.v(
    229                 TAG, "Returning raw display width: " + w);
    230         return w;
    231     }
    232     private native int getRawWidthNative();
    233 
    234     /**
    235      * Gets the raw height of the display, in pixels.
    236      * <p>
    237      * The size is adjusted based on the current rotation of the display.
    238      * </p>
    239      * @hide
    240      */
    241     public int getRawHeight() {
    242         int h = getRawHeightNative();
    243         if (DEBUG_DISPLAY_SIZE) Slog.v(
    244                 TAG, "Returning raw display height: " + h);
    245         return h;
    246     }
    247     private native int getRawHeightNative();
    248 
    249     /**
    250      * Returns the rotation of the screen from its "natural" orientation.
    251      * The returned value may be {@link Surface#ROTATION_0 Surface.ROTATION_0}
    252      * (no rotation), {@link Surface#ROTATION_90 Surface.ROTATION_90},
    253      * {@link Surface#ROTATION_180 Surface.ROTATION_180}, or
    254      * {@link Surface#ROTATION_270 Surface.ROTATION_270}.  For
    255      * example, if a device has a naturally tall screen, and the user has
    256      * turned it on its side to go into a landscape orientation, the value
    257      * returned here may be either {@link Surface#ROTATION_90 Surface.ROTATION_90}
    258      * or {@link Surface#ROTATION_270 Surface.ROTATION_270} depending on
    259      * the direction it was turned.  The angle is the rotation of the drawn
    260      * graphics on the screen, which is the opposite direction of the physical
    261      * rotation of the device.  For example, if the device is rotated 90
    262      * degrees counter-clockwise, to compensate rendering will be rotated by
    263      * 90 degrees clockwise and thus the returned value here will be
    264      * {@link Surface#ROTATION_90 Surface.ROTATION_90}.
    265      */
    266     public int getRotation() {
    267         return getOrientation();
    268     }
    269 
    270     /**
    271      * @deprecated use {@link #getRotation}
    272      * @return orientation of this display.
    273      */
    274     @Deprecated native public int getOrientation();
    275 
    276     /**
    277      * Return the native pixel format of the display.  The returned value
    278      * may be one of the constants int {@link android.graphics.PixelFormat}.
    279      */
    280     public int getPixelFormat() {
    281         return mPixelFormat;
    282     }
    283 
    284     /**
    285      * Return the refresh rate of this display in frames per second.
    286      */
    287     public float getRefreshRate() {
    288         return mRefreshRate;
    289     }
    290 
    291     /**
    292      * Gets display metrics that describe the size and density of this display.
    293      * <p>
    294      * The size is adjusted based on the current rotation of the display.
    295      * </p><p>
    296      * The size returned by this method does not necessarily represent the
    297      * actual raw size (native resolution) of the display.  The returned size may
    298      * be adjusted to exclude certain system decor elements that are always visible.
    299      * It may also be scaled to provide compatibility with older applications that
    300      * were originally designed for smaller displays.
    301      * </p>
    302      *
    303      * @param outMetrics A {@link DisplayMetrics} object to receive the metrics.
    304      */
    305     public void getMetrics(DisplayMetrics outMetrics) {
    306         synchronized (mTmpPoint) {
    307             getSizeInternal(mTmpPoint, false);
    308             getMetricsWithSize(outMetrics, mTmpPoint.x, mTmpPoint.y);
    309         }
    310 
    311         CompatibilityInfo ci = mCompatibilityInfo.getIfNeeded();
    312         if (ci != null) {
    313             ci.applyToDisplayMetrics(outMetrics);
    314         }
    315 
    316         if (DEBUG_DISPLAY_SIZE) Slog.v(TAG, "Returning DisplayMetrics: "
    317                 + outMetrics.widthPixels + "x" + outMetrics.heightPixels
    318                 + " " + outMetrics.density);
    319     }
    320 
    321     /**
    322      * Gets display metrics based on the real size of this display.
    323      * @hide
    324      */
    325     public void getRealMetrics(DisplayMetrics outMetrics) {
    326         synchronized (mTmpPoint) {
    327             getRealSize(mTmpPoint);
    328             getMetricsWithSize(outMetrics, mTmpPoint.x, mTmpPoint.y);
    329         }
    330     }
    331 
    332     /**
    333      * If the display is mirrored to an external HDMI display, returns the
    334      * width of that display.
    335      * @hide
    336      */
    337     public int getRawExternalWidth() {
    338         return 1280;
    339     }
    340 
    341     /**
    342      * If the display is mirrored to an external HDMI display, returns the
    343      * height of that display.
    344      * @hide
    345      */
    346     public int getRawExternalHeight() {
    347         return 720;
    348     }
    349 
    350     /**
    351      * Gets display metrics based on an explicit assumed display size.
    352      * @hide
    353      */
    354     public void getMetricsWithSize(DisplayMetrics outMetrics,
    355             int width, int height) {
    356         outMetrics.densityDpi   = (int)((mDensity*DisplayMetrics.DENSITY_DEFAULT)+.5f);
    357 
    358         outMetrics.noncompatWidthPixels  = outMetrics.widthPixels = width;
    359         outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height;
    360 
    361         outMetrics.density = outMetrics.noncompatDensity = mDensity;
    362         outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density;
    363         outMetrics.xdpi = outMetrics.noncompatXdpi = mDpiX;
    364         outMetrics.ydpi = outMetrics.noncompatYdpi = mDpiY;
    365     }
    366 
    367     static IWindowManager getWindowManager() {
    368         synchronized (sStaticInit) {
    369             if (sWindowManager == null) {
    370                 sWindowManager = IWindowManager.Stub.asInterface(
    371                         ServiceManager.getService("window"));
    372             }
    373             return sWindowManager;
    374         }
    375     }
    376 
    377     /*
    378      * We use a class initializer to allow the native code to cache some
    379      * field offsets.
    380      */
    381     native private static void nativeClassInit();
    382 
    383     private native void init(int display);
    384 
    385     private final CompatibilityInfoHolder mCompatibilityInfo;
    386     private final int   mDisplay;
    387     // Following fields are initialized from native code
    388     private int         mPixelFormat;
    389     private float       mRefreshRate;
    390     /*package*/ float   mDensity;
    391     /*package*/ float   mDpiX;
    392     /*package*/ float   mDpiY;
    393 
    394     private final Point mTmpPoint = new Point();
    395     private final DisplayMetrics mTmpMetrics = new DisplayMetrics();
    396     private float mLastGetTime;
    397 
    398     private static final Object sStaticInit = new Object();
    399     private static boolean sInitialized = false;
    400     private static IWindowManager sWindowManager;
    401 
    402     /**
    403      * Returns a display object which uses the metric's width/height instead.
    404      * @hide
    405      */
    406     public static Display createCompatibleDisplay(int displayId, CompatibilityInfoHolder compat) {
    407         return new Display(displayId, compat);
    408     }
    409 }
    410 
    411