Home | History | Annotate | Download | only in gfx
      1 // Copyright 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 package org.chromium.ui.gfx;
      6 
      7 import android.content.Context;
      8 import android.graphics.PixelFormat;
      9 import android.graphics.Point;
     10 import android.os.Build;
     11 import android.util.DisplayMetrics;
     12 import android.view.Display;
     13 import android.view.Surface;
     14 import android.view.WindowManager;
     15 
     16 import org.chromium.base.CalledByNative;
     17 import org.chromium.base.JNINamespace;
     18 
     19 /**
     20  * This class facilitates access to android information typically only
     21  * available using the Java SDK, including {@link Display} properties.
     22  *
     23  * Currently the information consists of very raw display information (height, width, DPI scale)
     24  * regarding the main display.
     25  */
     26 @JNINamespace("gfx")
     27 public class DeviceDisplayInfo {
     28 
     29     private final Context mAppContext;
     30     private final WindowManager mWinManager;
     31     private Point mTempPoint = new Point();
     32     private DisplayMetrics mTempMetrics = new DisplayMetrics();
     33 
     34     private DeviceDisplayInfo(Context context) {
     35         mAppContext = context.getApplicationContext();
     36         mWinManager = (WindowManager) mAppContext.getSystemService(Context.WINDOW_SERVICE);
     37     }
     38 
     39     /**
     40      * @return Display height in physical pixels.
     41      */
     42     @CalledByNative
     43     public int getDisplayHeight() {
     44         getDisplay().getSize(mTempPoint);
     45         return mTempPoint.y;
     46     }
     47 
     48     /**
     49      * @return Display width in physical pixels.
     50      */
     51     @CalledByNative
     52     public int getDisplayWidth() {
     53         getDisplay().getSize(mTempPoint);
     54         return mTempPoint.x;
     55     }
     56 
     57     /**
     58      * @return Real physical display height in physical pixels.
     59      */
     60     @CalledByNative
     61     public int getPhysicalDisplayHeight() {
     62         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
     63             return 0;
     64         }
     65         getDisplay().getRealSize(mTempPoint);
     66         return mTempPoint.y;
     67     }
     68 
     69     /**
     70      * @return Real physical display width in physical pixels.
     71      */
     72     @CalledByNative
     73     public int getPhysicalDisplayWidth() {
     74         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
     75             return 0;
     76         }
     77         getDisplay().getRealSize(mTempPoint);
     78         return mTempPoint.x;
     79     }
     80 
     81     @SuppressWarnings("deprecation")
     82     private int getPixelFormat() {
     83         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
     84             return getDisplay().getPixelFormat();
     85         }
     86         // JellyBean MR1 and later always uses RGBA_8888.
     87         return PixelFormat.RGBA_8888;
     88     }
     89 
     90     /**
     91      * @return Bits per pixel.
     92      */
     93     @CalledByNative
     94     public int getBitsPerPixel() {
     95         int format = getPixelFormat();
     96         PixelFormat info = new PixelFormat();
     97         PixelFormat.getPixelFormatInfo(format, info);
     98         return info.bitsPerPixel;
     99     }
    100 
    101     /**
    102      * @return Bits per component.
    103      */
    104     @SuppressWarnings("deprecation")
    105     @CalledByNative
    106     public int getBitsPerComponent() {
    107         int format = getPixelFormat();
    108         switch (format) {
    109             case PixelFormat.RGBA_4444:
    110                 return 4;
    111 
    112             case PixelFormat.RGBA_5551:
    113                 return 5;
    114 
    115             case PixelFormat.RGBA_8888:
    116             case PixelFormat.RGBX_8888:
    117             case PixelFormat.RGB_888:
    118                 return 8;
    119 
    120             case PixelFormat.RGB_332:
    121                 return 2;
    122 
    123             case PixelFormat.RGB_565:
    124                 return 5;
    125 
    126             // Non-RGB formats.
    127             case PixelFormat.A_8:
    128             case PixelFormat.LA_88:
    129             case PixelFormat.L_8:
    130                 return 0;
    131 
    132             // Unknown format. Use 8 as a sensible default.
    133             default:
    134                 return 8;
    135         }
    136     }
    137 
    138     /**
    139      * @return A scaling factor for the Density Independent Pixel unit. 1.0 is
    140      *         160dpi, 0.75 is 120dpi, 2.0 is 320dpi.
    141      */
    142     @CalledByNative
    143     public double getDIPScale() {
    144         getDisplay().getMetrics(mTempMetrics);
    145         return mTempMetrics.density;
    146     }
    147 
    148     /**
    149      * @return Smallest screen size in density-independent pixels that the
    150      *         application will see, regardless of orientation.
    151      */
    152     @CalledByNative
    153     private int getSmallestDIPWidth() {
    154         return mAppContext.getResources().getConfiguration().smallestScreenWidthDp;
    155     }
    156 
    157     /**
    158      * @return the screen's rotation angle from its 'natural' orientation.
    159      * Expected values are one of { 0, 90, 180, 270 }.
    160      * See http://developer.android.com/reference/android/view/Display.html#getRotation()
    161      * for more information about Display.getRotation() behavior.
    162      */
    163     @CalledByNative
    164     public int getRotationDegrees() {
    165         switch (getDisplay().getRotation()) {
    166             case Surface.ROTATION_0:
    167                 return 0;
    168             case Surface.ROTATION_90:
    169                 return 90;
    170             case Surface.ROTATION_180:
    171                 return 180;
    172             case Surface.ROTATION_270:
    173                 return 270;
    174         }
    175 
    176         // This should not happen.
    177         assert false;
    178         return 0;
    179     }
    180 
    181     /**
    182      * Inform the native implementation to update its cached representation of
    183      * the DeviceDisplayInfo values.
    184      */
    185     public void updateNativeSharedDisplayInfo() {
    186         nativeUpdateSharedDeviceDisplayInfo(
    187                 getDisplayHeight(), getDisplayWidth(),
    188                 getPhysicalDisplayHeight(), getPhysicalDisplayWidth(),
    189                 getBitsPerPixel(), getBitsPerComponent(),
    190                 getDIPScale(), getSmallestDIPWidth(), getRotationDegrees());
    191     }
    192 
    193     private Display getDisplay() {
    194         return mWinManager.getDefaultDisplay();
    195     }
    196 
    197     /**
    198      * Creates DeviceDisplayInfo for a given Context.
    199      *
    200      * @param context A context to use.
    201      * @return DeviceDisplayInfo associated with a given Context.
    202      */
    203     @CalledByNative
    204     public static DeviceDisplayInfo create(Context context) {
    205         return new DeviceDisplayInfo(context);
    206     }
    207 
    208     private native void nativeUpdateSharedDeviceDisplayInfo(
    209             int displayHeight, int displayWidth,
    210             int physicalDisplayHeight, int physicalDisplayWidth,
    211             int bitsPerPixel, int bitsPerComponent, double dipScale,
    212             int smallestDIPWidth, int rotationDegrees);
    213 
    214 }
    215