Use Diplay.getMetrics in DisplayController

- This is a workaround of b/163815566, where DisplayMetrics is stale
  when onDisplayChanged is called.
- Instead of relying on stale DisplayConext, get the DisplayMetrics
  from the Display directly.
- Also optimized how DisplayController.Info is created by passing in
  Display only
- Use mDisplayContext.getDisplay directly if availalbe

Bug: 163815566, 160544577
Test: DPI looks correct on device boot
Change-Id: I2a7454bb8cf2073ce592e8662781b87fc998444f
(cherry picked from commit 177c38243dc3bf245d1f7db3c265dfb56522f441)
This commit is contained in:
Alex Chau 2020-10-19 18:00:39 +01:00
parent b03d2b4161
commit acfac6187d
2 changed files with 23 additions and 16 deletions

View File

@ -201,7 +201,7 @@ public class InvariantDeviceProfile {
DisplayController.getDefaultDisplay(context).getInfo(),
getPredefinedDeviceProfiles(context, gridName));
Info myInfo = new Info(context, display);
Info myInfo = new Info(display);
DisplayOption myDisplayOption = invDistWeightedInterpolate(
myInfo, getPredefinedDeviceProfiles(context, gridName));

View File

@ -31,6 +31,8 @@ import android.view.Display;
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.Utilities;
import java.util.ArrayList;
/**
@ -157,13 +159,13 @@ public class DisplayController implements DisplayListener {
private final ArrayList<DisplayInfoChangeListener> mListeners = new ArrayList<>();
private DisplayController.Info mInfo;
private DisplayHolder(Context displayContext) {
private DisplayHolder(Context displayContext, Display display) {
mDisplayContext = displayContext;
// Note that the Display object must be obtained from DisplayManager which is
// associated to the display context, so the Display is isolated from Activity and
// Application to provide the actual state of device that excludes the additional
// adjustment and override.
mInfo = new DisplayController.Info(mDisplayContext);
mInfo = new DisplayController.Info(display);
mId = mInfo.id;
}
@ -180,22 +182,31 @@ public class DisplayController implements DisplayListener {
}
protected void handleOnChange() {
Display display = Utilities.ATLEAST_R
? mDisplayContext.getDisplay()
: mDisplayContext
.getSystemService(DisplayManager.class)
.getDisplay(mId);
if (display == null) {
return;
}
Info oldInfo = mInfo;
Info info = new Info(mDisplayContext);
Info newInfo = new Info(display);
int change = 0;
if (info.hasDifferentSize(oldInfo)) {
if (newInfo.hasDifferentSize(oldInfo)) {
change |= CHANGE_SIZE;
}
if (oldInfo.rotation != info.rotation) {
if (newInfo.rotation != oldInfo.rotation) {
change |= CHANGE_ROTATION;
}
if (info.singleFrameMs != oldInfo.singleFrameMs) {
if (newInfo.singleFrameMs != oldInfo.singleFrameMs) {
change |= CHANGE_FRAME_DELAY;
}
if (change != 0) {
mInfo = info;
mInfo = newInfo;
final int flags = change;
MAIN_EXECUTOR.execute(() -> notifyChange(flags));
}
@ -216,7 +227,7 @@ public class DisplayController implements DisplayListener {
// Use application context to create display context so that it can have its own
// Resources.
Context displayContext = context.getApplicationContext().createDisplayContext(display);
return new DisplayHolder(displayContext);
return new DisplayHolder(displayContext, display);
}
}
@ -244,12 +255,7 @@ public class DisplayController implements DisplayListener {
this.metrics = metrics;
}
private Info(Context context) {
this(context, context.getSystemService(DisplayManager.class)
.getDisplay(DEFAULT_DISPLAY));
}
public Info(Context context, Display display) {
public Info(Display display) {
id = display.getDisplayId();
rotation = display.getRotation();
@ -262,7 +268,8 @@ public class DisplayController implements DisplayListener {
display.getRealSize(realSize);
display.getCurrentSizeRange(smallestSize, largestSize);
metrics = context.getResources().getDisplayMetrics();
metrics = new DisplayMetrics();
display.getMetrics(metrics);
}
private boolean hasDifferentSize(Info info) {