Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(797)

Side by Side Diff: ui/android/java/src/org/chromium/ui/display/DisplayAndroid.java

Issue 2416403002: Reland of Android: support multiple displays on C++ side (Closed)
Patch Set: Update a map of Displays from Java Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698