Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.ui.display; | 5 package org.chromium.ui.display; |
| 6 | 6 |
| 7 import android.annotation.TargetApi; | 7 import android.annotation.TargetApi; |
| 8 import android.content.Context; | 8 import android.content.Context; |
| 9 import android.graphics.PixelFormat; | |
| 9 import android.graphics.Point; | 10 import android.graphics.Point; |
| 10 import android.os.Build; | 11 import android.os.Build; |
| 11 import android.util.DisplayMetrics; | 12 import android.util.DisplayMetrics; |
| 12 import android.view.Display; | 13 import android.view.Display; |
| 14 import android.view.Surface; | |
| 13 | 15 |
| 14 import org.chromium.base.CommandLine; | 16 import org.chromium.base.CommandLine; |
| 15 import org.chromium.base.Log; | 17 import org.chromium.base.Log; |
| 18 import org.chromium.base.annotations.JNINamespace; | |
| 16 | 19 |
| 17 import java.util.WeakHashMap; | 20 import java.util.WeakHashMap; |
| 18 | 21 |
| 19 /** | 22 /** |
| 20 * Chromium's object for android.view.Display. Instances of this object should b e obtained | 23 * Chromium's object for android.view.Display. Instances of this object should b e obtained |
| 21 * from WindowAndroid. | 24 * from WindowAndroid. |
| 22 * This class is designed to avoid leaks. It is ok to hold a strong ref of this class from | 25 * This class is designed to avoid leaks. It is ok to hold a strong ref of this class from |
| 23 * anywhere, as long as the corresponding WindowAndroids are destroyed. The obse rvers are | 26 * anywhere, as long as the corresponding WindowAndroids are destroyed. The obse rvers are |
| 24 * held weakly so to not lead to leaks. | 27 * held weakly so to not lead to leaks. |
| 25 */ | 28 */ |
| 29 @JNINamespace("ui") | |
|
mthiesse
2016/10/26 14:49:49
I think the native code for Displays on android sh
boliu
2016/10/26 17:24:20
Pass by value is not really a thing in java, but y
| |
| 26 public class DisplayAndroid { | 30 public class DisplayAndroid { |
| 27 /** | 31 /** |
| 28 * DisplayAndroidObserver interface for changes to this Display. | 32 * DisplayAndroidObserver interface for changes to this Display. |
| 29 */ | 33 */ |
| 30 public interface DisplayAndroidObserver { | 34 public interface DisplayAndroidObserver { |
| 31 /** | 35 /** |
| 32 * Called whenever the screen orientation changes. | 36 * Called whenever the screen orientation changes. |
| 33 * | 37 * |
| 34 * @param orientation One of Surface.ROTATION_* values. | 38 * @param orientation One of Surface.ROTATION_* values. |
| 35 */ | 39 */ |
| 36 void onRotationChanged(int rotation); | 40 void onRotationChanged(int rotation); |
| 37 } | 41 } |
| 38 | 42 |
| 39 private static final String TAG = "DisplayAndroid"; | 43 private static final String TAG = "DisplayAndroid"; |
| 40 | 44 |
| 41 private static final DisplayAndroidObserver[] EMPTY_OBSERVER_ARRAY = | 45 private static final DisplayAndroidObserver[] EMPTY_OBSERVER_ARRAY = |
| 42 new DisplayAndroidObserver[0]; | 46 new DisplayAndroidObserver[0]; |
| 43 | 47 |
| 44 private final int mSdkDisplayId; | 48 private final int mSdkDisplayId; |
| 45 private final WeakHashMap<DisplayAndroidObserver, Object /* null */> mObserv ers; | 49 private final WeakHashMap<DisplayAndroidObserver, Object /* null */> mObserv ers; |
| 46 // Do NOT add strong references to objects with potentially complex lifetime , like Context. | 50 // Do NOT add strong references to objects with potentially complex lifetime , like Context. |
| 47 | 51 |
| 48 // Updated by updateFromDisplay. | 52 // Updated by updateFromDisplay. |
| 49 private final Point mSize; | 53 private final Point mSize; |
| 50 private final Point mPhysicalSize; | 54 private final Point mPhysicalSize; |
| 51 private final DisplayMetrics mDisplayMetrics; | 55 private final DisplayMetrics mDisplayMetrics; |
| 56 private int mPixelFormatId; | |
| 52 private int mRotation; | 57 private int mRotation; |
| 53 | 58 |
| 54 // When this object exists, a positive value means that the forced DIP scale is set and | 59 // When this object exists, a positive value means that the forced DIP scale is set and |
| 55 // the zero means it is not. The non existing object (i.e. null reference) m eans that | 60 // the zero means it is not. The non existing object (i.e. null reference) m eans that |
| 56 // the existence and value of the forced DIP scale has not yet been determin ed. | 61 // the existence and value of the forced DIP scale has not yet been determin ed. |
| 57 private static Float sForcedDIPScale; | 62 private static Float sForcedDIPScale; |
| 58 | 63 |
| 59 private static boolean hasForcedDIPScale() { | 64 private static boolean hasForcedDIPScale() { |
| 60 if (sForcedDIPScale == null) { | 65 if (sForcedDIPScale == null) { |
| 61 String forcedScaleAsString = CommandLine.getInstance().getSwitchValu e( | 66 String forcedScaleAsString = CommandLine.getInstance().getSwitchValu e( |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 90 * Get the DisplayAndroid for this context. It's safe to call this with any type of context | 95 * Get the DisplayAndroid for this context. It's safe to call this with any type of context |
| 91 * including the Application. However to support multi-display, prefer to us e the Activity | 96 * including the Application. However to support multi-display, prefer to us e the Activity |
| 92 * context if available, or obtain DisplayAndroid from WindowAndroid instead . | 97 * context if available, or obtain DisplayAndroid from WindowAndroid instead . |
| 93 */ | 98 */ |
| 94 public static DisplayAndroid get(Context context) { | 99 public static DisplayAndroid get(Context context) { |
| 95 Display display = DisplayAndroidManager.getDisplayFromContext(context); | 100 Display display = DisplayAndroidManager.getDisplayFromContext(context); |
| 96 return getManager().getDisplayAndroid(display); | 101 return getManager().getDisplayAndroid(display); |
| 97 } | 102 } |
| 98 | 103 |
| 99 /** | 104 /** |
| 105 * @return Display id as defined in Android's Display. | |
| 106 */ | |
| 107 public int getSdkDisplayId() { | |
|
mthiesse
2016/10/26 14:49:49
If we store a mapping from window to display in bo
boliu
2016/10/26 17:24:20
yeah, this is one of those weird things where we r
mthiesse
2016/10/26 17:52:49
The main benefit is consistency between native and
boliu
2016/10/26 18:24:43
Ok I objected to that because the current thing se
mthiesse
2016/10/26 18:48:24
sgtm
Tima Vaisburd
2016/10/27 07:55:58
Done, except for Java side.
| |
| 108 return mSdkDisplayId; | |
| 109 } | |
| 110 | |
| 111 /** | |
| 100 * @return Display height in physical pixels. | 112 * @return Display height in physical pixels. |
| 101 */ | 113 */ |
| 102 public int getDisplayHeight() { | 114 public int getDisplayHeight() { |
| 103 return mSize.y; | 115 return mSize.y; |
| 104 } | 116 } |
| 105 | 117 |
| 106 /** | 118 /** |
| 107 * @return Display width in physical pixels. | 119 * @return Display width in physical pixels. |
| 108 */ | 120 */ |
| 109 public int getDisplayWidth() { | 121 public int getDisplayWidth() { |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 125 } | 137 } |
| 126 | 138 |
| 127 /** | 139 /** |
| 128 * @return current orientation. One of Surface.ORIENTATION_* values. | 140 * @return current orientation. One of Surface.ORIENTATION_* values. |
| 129 */ | 141 */ |
| 130 public int getRotation() { | 142 public int getRotation() { |
| 131 return mRotation; | 143 return mRotation; |
| 132 } | 144 } |
| 133 | 145 |
| 134 /** | 146 /** |
| 147 * @return current orientation in degrees. One of the values 0, 90, 180, 270 . | |
| 148 */ | |
| 149 public int getRotationDegrees() { | |
| 150 switch (mRotation) { | |
| 151 case Surface.ROTATION_0: | |
| 152 return 0; | |
| 153 case Surface.ROTATION_90: | |
| 154 return 90; | |
| 155 case Surface.ROTATION_180: | |
| 156 return 180; | |
| 157 case Surface.ROTATION_270: | |
| 158 return 270; | |
| 159 } | |
| 160 | |
| 161 // This should not happen. | |
| 162 assert false; | |
| 163 return 0; | |
| 164 } | |
| 165 | |
| 166 /** | |
| 135 * @return A scaling factor for the Density Independent Pixel unit. | 167 * @return A scaling factor for the Density Independent Pixel unit. |
| 136 */ | 168 */ |
| 137 public float getDIPScale() { | 169 public float getDIPScale() { |
| 138 return mDisplayMetrics.density; | 170 return mDisplayMetrics.density; |
| 139 } | 171 } |
| 140 | 172 |
| 141 /** | 173 /** |
| 174 * @return Number of bits per pixel. | |
| 175 */ | |
| 176 public int getBitsPerPixel() { | |
| 177 PixelFormat info = new PixelFormat(); | |
| 178 PixelFormat.getPixelFormatInfo(mPixelFormatId, info); | |
| 179 return info.bitsPerPixel; | |
| 180 } | |
| 181 | |
| 182 /** | |
| 183 * @return Number of bits per each color component. | |
| 184 */ | |
| 185 @SuppressWarnings("deprecation") | |
| 186 public int getBitsPerComponent() { | |
| 187 switch (mPixelFormatId) { | |
| 188 case PixelFormat.RGBA_4444: | |
| 189 return 4; | |
| 190 | |
| 191 case PixelFormat.RGBA_5551: | |
| 192 return 5; | |
| 193 | |
| 194 case PixelFormat.RGBA_8888: | |
| 195 case PixelFormat.RGBX_8888: | |
| 196 case PixelFormat.RGB_888: | |
| 197 return 8; | |
| 198 | |
| 199 case PixelFormat.RGB_332: | |
| 200 return 2; | |
| 201 | |
| 202 case PixelFormat.RGB_565: | |
| 203 return 5; | |
| 204 | |
| 205 // Non-RGB formats. | |
| 206 case PixelFormat.A_8: | |
| 207 case PixelFormat.LA_88: | |
| 208 case PixelFormat.L_8: | |
| 209 return 0; | |
| 210 | |
| 211 // Unknown format. Use 8 as a sensible default. | |
| 212 default: | |
| 213 return 8; | |
| 214 } | |
| 215 } | |
| 216 | |
| 217 /** | |
| 142 * Add observer. Note repeat observers will be called only one. | 218 * Add observer. Note repeat observers will be called only one. |
| 143 * Observers are held only weakly by Display. | 219 * Observers are held only weakly by Display. |
| 144 */ | 220 */ |
| 145 public void addObserver(DisplayAndroidObserver observer) { | 221 public void addObserver(DisplayAndroidObserver observer) { |
| 146 mObservers.put(observer, null); | 222 mObservers.put(observer, null); |
| 147 } | 223 } |
| 148 | 224 |
| 149 /** | 225 /** |
| 150 * Remove observer. | 226 * Remove observer. |
| 151 */ | 227 */ |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 168 public static void stopAccurateListening() { | 244 public static void stopAccurateListening() { |
| 169 getManager().startAccurateListening(); | 245 getManager().startAccurateListening(); |
| 170 } | 246 } |
| 171 | 247 |
| 172 /* package */ DisplayAndroid(Display display) { | 248 /* package */ DisplayAndroid(Display display) { |
| 173 mSdkDisplayId = display.getDisplayId(); | 249 mSdkDisplayId = display.getDisplayId(); |
| 174 mObservers = new WeakHashMap<>(); | 250 mObservers = new WeakHashMap<>(); |
| 175 mSize = new Point(); | 251 mSize = new Point(); |
| 176 mPhysicalSize = new Point(); | 252 mPhysicalSize = new Point(); |
| 177 mDisplayMetrics = new DisplayMetrics(); | 253 mDisplayMetrics = new DisplayMetrics(); |
| 254 mPixelFormatId = PixelFormat.RGBA_8888; | |
| 178 updateFromDisplay(display); | 255 updateFromDisplay(display); |
| 179 } | 256 } |
| 180 | 257 |
| 258 @SuppressWarnings("deprecation") | |
| 181 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) | 259 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) |
| 182 /* package */ void updateFromDisplay(Display display) { | 260 /* package */ void updateFromDisplay(Display display) { |
| 261 final Point oldSize = new Point(mSize); | |
| 262 final Point oldPhysicalSize = new Point(mPhysicalSize); | |
| 263 final float oldDensity = mDisplayMetrics.density; | |
| 264 final int oldPixelFormatId = mPixelFormatId; | |
| 265 final int oldRotation = mRotation; | |
| 266 | |
| 183 display.getSize(mSize); | 267 display.getSize(mSize); |
| 184 display.getMetrics(mDisplayMetrics); | 268 display.getMetrics(mDisplayMetrics); |
| 185 | 269 |
| 186 if (hasForcedDIPScale()) mDisplayMetrics.density = sForcedDIPScale.float Value(); | 270 if (hasForcedDIPScale()) mDisplayMetrics.density = sForcedDIPScale.float Value(); |
| 187 | 271 |
| 188 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { | 272 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { |
| 189 display.getRealSize(mPhysicalSize); | 273 display.getRealSize(mPhysicalSize); |
| 190 } | 274 } |
| 191 | 275 |
| 192 int newRotation = display.getRotation(); | 276 // JellyBean MR1 and later always uses RGBA_8888. |
| 193 boolean rotationChanged = newRotation != mRotation; | 277 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { |
| 194 mRotation = newRotation; | 278 mPixelFormatId = display.getPixelFormat(); |
| 279 } | |
| 195 | 280 |
| 196 if (rotationChanged) { | 281 mRotation = display.getRotation(); |
| 282 | |
| 283 final boolean noChanges = oldSize.equals(mSize) && oldPhysicalSize.equal s(mPhysicalSize) | |
| 284 && oldDensity == mDisplayMetrics.density && oldPixelFormatId == mPixelFormatId | |
| 285 && oldRotation == mRotation; | |
| 286 if (noChanges) return; | |
| 287 | |
| 288 updateNativeSide(); | |
| 289 | |
| 290 if (oldRotation != mRotation) { | |
| 197 DisplayAndroidObserver[] observers = getObservers(); | 291 DisplayAndroidObserver[] observers = getObservers(); |
| 198 for (DisplayAndroidObserver o : observers) { | 292 for (DisplayAndroidObserver o : observers) { |
| 199 o.onRotationChanged(mRotation); | 293 o.onRotationChanged(mRotation); |
| 200 } | 294 } |
| 201 } | 295 } |
| 202 } | 296 } |
| 203 | 297 |
| 298 /* package */ void onAddedToMap() { | |
| 299 updateNativeSide(); | |
| 300 } | |
| 301 | |
| 302 /* package */ void onRemovedFromMap() { | |
| 303 nativeRemoveDisplayAndroid(mSdkDisplayId); | |
| 304 } | |
| 305 | |
| 306 private void updateNativeSide() { | |
| 307 nativeUpdateDisplayAndroid(mSdkDisplayId, mPhysicalSize.x, mPhysicalSize .y, mSize.x, | |
| 308 mSize.y, mDisplayMetrics.density, getRotationDegrees(), getBitsP erPixel(), | |
| 309 getBitsPerComponent()); | |
| 310 } | |
| 311 | |
| 204 private DisplayAndroidObserver[] getObservers() { | 312 private DisplayAndroidObserver[] getObservers() { |
| 205 // Makes a copy to allow concurrent edit. | 313 // Makes a copy to allow concurrent edit. |
| 206 return mObservers.keySet().toArray(EMPTY_OBSERVER_ARRAY); | 314 return mObservers.keySet().toArray(EMPTY_OBSERVER_ARRAY); |
| 207 } | 315 } |
| 316 | |
| 317 private static native void nativeUpdateDisplayAndroid(int sdkDisplayId, int physicalWidth, | |
| 318 int physicalHeight, int width, int height, float dipScale, int rotat ionDegrees, | |
| 319 int bitsPerPixel, int bitsPerComponent); | |
| 320 private static native void nativeRemoveDisplayAndroid(int sdkDisplayId); | |
| 208 } | 321 } |
| OLD | NEW |