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