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 |