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(), DisplayController.getDefaultDisplay(context).getInfo(),
getPredefinedDeviceProfiles(context, gridName)); getPredefinedDeviceProfiles(context, gridName));
Info myInfo = new Info(context, display); Info myInfo = new Info(display);
DisplayOption myDisplayOption = invDistWeightedInterpolate( DisplayOption myDisplayOption = invDistWeightedInterpolate(
myInfo, getPredefinedDeviceProfiles(context, gridName)); myInfo, getPredefinedDeviceProfiles(context, gridName));

View File

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