Snap for 8704887 from 40f049bcb4 to tm-qpr1-release

Change-Id: Ic38ed6e819efc13eafd9f9140820b6cf30232740
This commit is contained in:
Android Build Coastguard Worker
2022-06-10 01:25:04 +00:00
20 changed files with 364 additions and 195 deletions
@@ -35,6 +35,7 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_N
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING;
import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_REGION;
import android.animation.ArgbEvaluator;
@@ -105,6 +106,7 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
private static final int FLAG_DISABLE_BACK = 1 << 9;
private static final int FLAG_NOTIFICATION_SHADE_EXPANDED = 1 << 10;
private static final int FLAG_SCREEN_PINNING_ACTIVE = 1 << 11;
private static final int FLAG_VOICE_INTERACTION_WINDOW_SHOWING = 1 << 12;
private static final int MASK_IME_SWITCHER_VISIBLE = FLAG_SWITCHER_SUPPORTED | FLAG_IME_VISIBLE;
@@ -207,9 +209,12 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
boolean isInKidsMode = mContext.isNavBarKidsModeActive();
boolean alwaysShowButtons = isThreeButtonNav || isInSetup;
// Make sure to remove nav bar buttons translation when notification shade is expanded or
// IME is showing (add separate translation for IME).
int flagsToRemoveTranslation = FLAG_NOTIFICATION_SHADE_EXPANDED | FLAG_IME_VISIBLE;
// Make sure to remove nav bar buttons translation when any of the following occur:
// - Notification shade is expanded
// - IME is showing (add separate translation for IME)
// - VoiceInteractionWindow (assistant) is showing
int flagsToRemoveTranslation = FLAG_NOTIFICATION_SHADE_EXPANDED | FLAG_IME_VISIBLE
| FLAG_VOICE_INTERACTION_WINDOW_SHOWING;
mPropertyHolders.add(new StatePropertyHolder(mNavButtonInAppDisplayProgressForSysui,
flags -> (flags & flagsToRemoveTranslation) != 0, AnimatedFloat.VALUE,
1, 0));
@@ -443,6 +448,8 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
| SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
boolean isNotificationShadeExpanded = (sysUiStateFlags & shadeExpandedFlags) != 0;
boolean isScreenPinningActive = (sysUiStateFlags & SYSUI_STATE_SCREEN_PINNING) != 0;
boolean isVoiceInteractionWindowShowing =
(sysUiStateFlags & SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING) != 0;
// TODO(b/202218289) we're getting IME as not visible on lockscreen from system
updateStateForFlag(FLAG_IME_VISIBLE, isImeVisible);
@@ -453,6 +460,7 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
updateStateForFlag(FLAG_DISABLE_BACK, isBackDisabled);
updateStateForFlag(FLAG_NOTIFICATION_SHADE_EXPANDED, isNotificationShadeExpanded);
updateStateForFlag(FLAG_SCREEN_PINNING_ACTIVE, isScreenPinningActive);
updateStateForFlag(FLAG_VOICE_INTERACTION_WINDOW_SHOWING, isVoiceInteractionWindowShowing);
if (mA11yButton != null) {
// Only used in 3 button
@@ -750,6 +758,8 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
appendFlag(str, flags, FLAG_NOTIFICATION_SHADE_EXPANDED,
"FLAG_NOTIFICATION_SHADE_EXPANDED");
appendFlag(str, flags, FLAG_SCREEN_PINNING_ACTIVE, "FLAG_SCREEN_PINNING_ACTIVE");
appendFlag(str, flags, FLAG_VOICE_INTERACTION_WINDOW_SHOWING,
"FLAG_VOICE_INTERACTION_WINDOW_SHOWING");
return str.toString();
}
@@ -43,7 +43,8 @@ public class StashedHandleViewController implements TaskbarControllers.LoggableT
public static final int ALPHA_INDEX_STASHED = 0;
public static final int ALPHA_INDEX_HOME_DISABLED = 1;
private static final int NUM_ALPHA_CHANNELS = 2;
public static final int ALPHA_INDEX_ASSISTANT_INVOKED = 2;
private static final int NUM_ALPHA_CHANNELS = 3;
/**
* The SharedPreferences key for whether the stashed handle region is dark.
@@ -27,6 +27,7 @@ import static com.android.launcher3.ResourceUtils.getBoolByName;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
@@ -200,7 +201,8 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
new TaskbarPopupController(this),
new TaskbarForceVisibleImmersiveController(this),
new TaskbarAllAppsController(this, dp),
new TaskbarInsetsController(this));
new TaskbarInsetsController(this),
new VoiceInteractionWindowController(this));
}
public void init(@NonNull TaskbarSharedState sharedState) {
@@ -246,12 +248,20 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
return super.getStatsLogManager();
}
/** Creates LayoutParams for adding a view directly to WindowManager as a new window */
/** @see #createDefaultWindowLayoutParams(int) */
public WindowManager.LayoutParams createDefaultWindowLayoutParams() {
return createDefaultWindowLayoutParams(TYPE_NAVIGATION_BAR_PANEL);
}
/**
* Creates LayoutParams for adding a view directly to WindowManager as a new window.
* @param type The window type to pass to the created WindowManager.LayoutParams.
*/
public WindowManager.LayoutParams createDefaultWindowLayoutParams(int type) {
WindowManager.LayoutParams windowLayoutParams = new WindowManager.LayoutParams(
MATCH_PARENT,
mLastRequestedNonFullscreenHeight,
TYPE_NAVIGATION_BAR_PANEL,
type,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_SLIPPERY,
PixelFormat.TRANSLUCENT);
@@ -468,6 +478,8 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
fromInit);
mControllers.navButtonController.updateSysuiFlags(systemUiStateFlags);
mControllers.taskbarForceVisibleImmersiveController.updateSysuiFlags(systemUiStateFlags);
mControllers.voiceInteractionWindowController.setIsVoiceInteractionWindowVisible(
(systemUiStateFlags & SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING) != 0, fromInit);
}
/**
@@ -612,7 +624,9 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
/** Removes the given view from WindowManager. See {@link #addWindowView}. */
public void removeWindowView(View view) {
mWindowManager.removeViewImmediate(view);
if (view.isAttachedToWindow()) {
mWindowManager.removeViewImmediate(view);
}
}
protected void onTaskbarIconClicked(View view) {
@@ -52,6 +52,7 @@ public class TaskbarControllers {
public final TaskbarForceVisibleImmersiveController taskbarForceVisibleImmersiveController;
public final TaskbarAllAppsController taskbarAllAppsController;
public final TaskbarInsetsController taskbarInsetsController;
public final VoiceInteractionWindowController voiceInteractionWindowController;
@Nullable private LoggableTaskbarController[] mControllersToLog = null;
@@ -80,7 +81,8 @@ public class TaskbarControllers {
TaskbarPopupController taskbarPopupController,
TaskbarForceVisibleImmersiveController taskbarForceVisibleImmersiveController,
TaskbarAllAppsController taskbarAllAppsController,
TaskbarInsetsController taskbarInsetsController) {
TaskbarInsetsController taskbarInsetsController,
VoiceInteractionWindowController voiceInteractionWindowController) {
this.taskbarActivityContext = taskbarActivityContext;
this.taskbarDragController = taskbarDragController;
this.navButtonController = navButtonController;
@@ -99,6 +101,7 @@ public class TaskbarControllers {
this.taskbarForceVisibleImmersiveController = taskbarForceVisibleImmersiveController;
this.taskbarAllAppsController = taskbarAllAppsController;
this.taskbarInsetsController = taskbarInsetsController;
this.voiceInteractionWindowController = voiceInteractionWindowController;
}
/**
@@ -126,13 +129,15 @@ public class TaskbarControllers {
taskbarAllAppsController.init(this, sharedState.allAppsVisible);
navButtonController.init(this);
taskbarInsetsController.init(this);
voiceInteractionWindowController.init(this);
mControllersToLog = new LoggableTaskbarController[] {
taskbarDragController, navButtonController, navbarButtonsViewController,
taskbarDragLayerController, taskbarScrimViewController, taskbarViewController,
taskbarUnfoldAnimationController, taskbarKeyguardController,
stashedHandleViewController, taskbarStashController, taskbarEduController,
taskbarAutohideSuspendController, taskbarPopupController, taskbarInsetsController
taskbarAutohideSuspendController, taskbarPopupController, taskbarInsetsController,
voiceInteractionWindowController
};
mAreAllControllersInitialized = true;
@@ -172,6 +177,7 @@ public class TaskbarControllers {
taskbarAllAppsController.onDestroy();
navButtonController.onDestroy();
taskbarInsetsController.onDestroy();
voiceInteractionWindowController.onDestroy();
mControllersToLog = null;
}
@@ -63,7 +63,8 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
public static final int ALPHA_INDEX_STASH = 2;
public static final int ALPHA_INDEX_RECENTS_DISABLED = 3;
public static final int ALPHA_INDEX_NOTIFICATION_EXPANDED = 4;
private static final int NUM_ALPHA_CHANNELS = 5;
public static final int ALPHA_INDEX_ASSISTANT_INVOKED = 5;
private static final int NUM_ALPHA_CHANNELS = 6;
private final TaskbarActivityContext mActivity;
private final TaskbarView mTaskbarView;
@@ -0,0 +1,109 @@
package com.android.launcher3.taskbar
import android.graphics.Canvas
import android.view.WindowManager
import android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
import com.android.launcher3.views.BaseDragLayer
import com.android.systemui.animation.ViewRootSync
import java.io.PrintWriter
private const val TASKBAR_ICONS_FADE_DURATION = 300L
private const val STASHED_HANDLE_FADE_DURATION = 180L
/**
* Controls Taskbar behavior while Voice Interaction Window (assistant) is showing.
*/
class VoiceInteractionWindowController(val context: TaskbarActivityContext)
: TaskbarControllers.LoggableTaskbarController {
private val taskbarBackgroundRenderer = TaskbarBackgroundRenderer(context)
// Initialized in init.
private lateinit var controllers: TaskbarControllers
private lateinit var separateWindowForTaskbarBackground: BaseDragLayer<TaskbarActivityContext>
private lateinit var separateWindowLayoutParams: WindowManager.LayoutParams
private var isVoiceInteractionWindowVisible: Boolean = false
fun init(controllers: TaskbarControllers) {
this.controllers = controllers
separateWindowForTaskbarBackground =
object : BaseDragLayer<TaskbarActivityContext>(context, null, 0) {
override fun recreateControllers() {
mControllers = emptyArray()
}
override fun draw(canvas: Canvas) {
super.draw(canvas)
taskbarBackgroundRenderer.draw(canvas)
}
}
separateWindowForTaskbarBackground.recreateControllers()
separateWindowForTaskbarBackground.setWillNotDraw(false)
separateWindowLayoutParams = context.createDefaultWindowLayoutParams(
TYPE_APPLICATION_OVERLAY)
separateWindowLayoutParams.isSystemApplicationOverlay = true
}
fun onDestroy() {
setIsVoiceInteractionWindowVisible(visible = false, skipAnim = true)
}
fun setIsVoiceInteractionWindowVisible(visible: Boolean, skipAnim: Boolean) {
if (isVoiceInteractionWindowVisible == visible) {
return
}
isVoiceInteractionWindowVisible = visible
// Fade out taskbar icons and stashed handle.
val taskbarIconAlpha = if (isVoiceInteractionWindowVisible) 0f else 1f
val fadeTaskbarIcons = controllers.taskbarViewController.taskbarIconAlpha
.getProperty(TaskbarViewController.ALPHA_INDEX_ASSISTANT_INVOKED)
.animateToValue(taskbarIconAlpha)
.setDuration(TASKBAR_ICONS_FADE_DURATION)
val fadeStashedHandle = controllers.stashedHandleViewController.stashedHandleAlpha
.getProperty(StashedHandleViewController.ALPHA_INDEX_ASSISTANT_INVOKED)
.animateToValue(taskbarIconAlpha)
.setDuration(STASHED_HANDLE_FADE_DURATION)
fadeTaskbarIcons.start()
fadeStashedHandle.start()
if (skipAnim) {
fadeTaskbarIcons.end()
fadeStashedHandle.end()
}
if (context.isGestureNav && controllers.taskbarStashController.isInAppAndNotStashed) {
moveTaskbarBackgroundToLowerLayer()
}
}
/**
* Hides the TaskbarDragLayer background and creates a new window to draw just that background.
*/
private fun moveTaskbarBackgroundToLowerLayer() {
val taskbarBackgroundOverride = controllers.taskbarDragLayerController
.overrideBackgroundAlpha
if (isVoiceInteractionWindowVisible) {
// First add the temporary window, then hide the overlapping taskbar background.
context.addWindowView(separateWindowForTaskbarBackground, separateWindowLayoutParams)
ViewRootSync.synchronizeNextDraw(separateWindowForTaskbarBackground, context.dragLayer
) {
taskbarBackgroundOverride.updateValue(0f)
}
} else {
// First reapply the original taskbar background, then remove the temporary window.
taskbarBackgroundOverride.updateValue(1f)
ViewRootSync.synchronizeNextDraw(separateWindowForTaskbarBackground, context.dragLayer
) {
context.removeWindowView(separateWindowForTaskbarBackground)
}
}
}
override fun dumpLogs(prefix: String, pw: PrintWriter) {
pw.println(prefix + "VoiceInteractionWindowController:")
pw.println("$prefix\tisVoiceInteractionWindowVisible=$isVoiceInteractionWindowVisible")
}
}
@@ -1284,8 +1284,11 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
? runningTaskTarget.taskInfo.launchCookies
: new ArrayList<>();
boolean isTranslucent = runningTaskTarget != null && runningTaskTarget.isTranslucent;
boolean hasValidLeash = runningTaskTarget != null
&& runningTaskTarget.leash != null
&& runningTaskTarget.leash.isValid();
boolean appCanEnterPip = !mDeviceState.isPipActive()
&& runningTaskTarget != null
&& hasValidLeash
&& runningTaskTarget.allowEnterPip
&& runningTaskTarget.taskInfo.pictureInPictureParams != null
&& runningTaskTarget.taskInfo.pictureInPictureParams.isAutoEnterEnabled();
@@ -1394,9 +1397,6 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
}
}
/**
* TODO(b/195473090) handle multiple task simulators (if needed) for PIP
*/
private SwipePipToHomeAnimator createWindowAnimationToPip(HomeAnimationFactory homeAnimFactory,
RemoteAnimationTargetCompat runningTaskTarget, float startProgress) {
// Directly animate the app to PiP (picture-in-picture) mode
@@ -514,9 +514,6 @@ public final class TaskViewUtils {
for (SurfaceControl leash: openingTargets) {
t.setAlpha(leash, progress);
}
for (SurfaceControl leash: closingTargets) {
t.setAlpha(leash, 1 - progress);
}
t.apply();
});
animator.addListener(new AnimatorListenerAdapter() {
@@ -15,11 +15,20 @@
*/
package com.android.quickstep.util;
import android.content.Context;
import android.view.Display;
import static android.view.Display.DEFAULT_DISPLAY;
import android.content.Context;
import android.util.ArrayMap;
import android.view.Surface;
import android.view.WindowManager;
import android.view.WindowMetrics;
import com.android.launcher3.util.WindowBounds;
import com.android.launcher3.util.window.CachedDisplayInfo;
import com.android.launcher3.util.window.WindowManagerProxy;
import java.util.Set;
/**
* Extension of {@link WindowManagerProxy} with some assumption for the default system Launcher
*/
@@ -30,17 +39,23 @@ public class SystemWindowManagerProxy extends WindowManagerProxy {
}
@Override
protected String getDisplayId(Display display) {
return display.getUniqueId();
public int getRotation(Context displayInfoContext) {
return displayInfoContext.getResources().getConfiguration().windowConfiguration
.getRotation();
}
@Override
public boolean isInternalDisplay(Display display) {
return display.getType() == Display.TYPE_INTERNAL;
}
@Override
public int getRotation(Context context) {
return context.getResources().getConfiguration().windowConfiguration.getRotation();
public ArrayMap<CachedDisplayInfo, WindowBounds[]> estimateInternalDisplayBounds(
Context displayInfoContext) {
ArrayMap<CachedDisplayInfo, WindowBounds[]> result = new ArrayMap<>();
WindowManager windowManager = displayInfoContext.getSystemService(WindowManager.class);
Set<WindowMetrics> possibleMaximumWindowMetrics =
windowManager.getPossibleMaximumWindowMetrics(DEFAULT_DISPLAY);
for (WindowMetrics windowMetrics : possibleMaximumWindowMetrics) {
CachedDisplayInfo info = getDisplayInfo(windowMetrics, Surface.ROTATION_0);
WindowBounds[] bounds = estimateWindowBounds(displayInfoContext, info);
result.put(info, bounds);
}
return result;
}
}
@@ -35,7 +35,6 @@ import android.graphics.Rect;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
import android.util.Size;
import android.view.Display;
import android.view.MotionEvent;
import android.view.Surface;
@@ -290,15 +289,17 @@ public class OrientationTouchTransformerTest {
private DisplayController.Info createDisplayInfo(Size screenSize, int rotation) {
Point displaySize = new Point(screenSize.getWidth(), screenSize.getHeight());
RotationUtils.rotateSize(displaySize, rotation);
CachedDisplayInfo cdi = new CachedDisplayInfo(displaySize, rotation);
WindowBounds wm = new WindowBounds(
CachedDisplayInfo cachedDisplayInfo = new CachedDisplayInfo(displaySize, rotation);
WindowBounds windowBounds = new WindowBounds(
new Rect(0, 0, displaySize.x, displaySize.y),
new Rect());
WindowManagerProxy wmProxy = mock(WindowManagerProxy.class);
doReturn(cdi).when(wmProxy).getDisplayInfo(any(), any());
doReturn(wm).when(wmProxy).getRealBounds(any(), any(), any());
doReturn(cachedDisplayInfo).when(wmProxy).getDisplayInfo(any());
doReturn(windowBounds).when(wmProxy).getRealBounds(any(), any());
ArrayMap<CachedDisplayInfo, WindowBounds[]> internalDisplayBounds = new ArrayMap<>();
doReturn(internalDisplayBounds).when(wmProxy).estimateInternalDisplayBounds(any());
return new DisplayController.Info(
getApplicationContext(), mock(Display.class), wmProxy, new ArrayMap<>());
getApplicationContext(), wmProxy, new ArrayMap<>());
}
private float generateTouchRegionHeight(Size screenSize, int rotation) {
@@ -23,8 +23,6 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.ArrayMap;
import android.util.Pair;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -148,7 +146,7 @@ public class TaskViewSimulatorTest {
int rotation = mDisplaySize.x > mDisplaySize.y
? Surface.ROTATION_90 : Surface.ROTATION_0;
CachedDisplayInfo cdi =
new CachedDisplayInfo("test-display", mDisplaySize, rotation , new Rect());
new CachedDisplayInfo(mDisplaySize, rotation, new Rect());
WindowBounds wm = new WindowBounds(
new Rect(0, 0, mDisplaySize.x, mDisplaySize.y),
mDisplayInsets);
@@ -164,15 +162,15 @@ public class TaskViewSimulatorTest {
}
WindowManagerProxy wmProxy = mock(WindowManagerProxy.class);
doReturn(cdi).when(wmProxy).getDisplayInfo(any(), any());
doReturn(wm).when(wmProxy).getRealBounds(any(), any(), any());
doReturn(cdi).when(wmProxy).getDisplayInfo(any());
doReturn(wm).when(wmProxy).getRealBounds(any(), any());
ArrayMap<String, Pair<CachedDisplayInfo, WindowBounds[]>> perDisplayBoundsCache =
ArrayMap<CachedDisplayInfo, WindowBounds[]> perDisplayBoundsCache =
new ArrayMap<>();
perDisplayBoundsCache.put(cdi.id, Pair.create(cdi.normalize(), allBounds));
perDisplayBoundsCache.put(cdi.normalize(), allBounds);
DisplayController.Info mockInfo = new Info(
helper.sandboxContext, mock(Display.class), wmProxy, perDisplayBoundsCache);
helper.sandboxContext, wmProxy, perDisplayBoundsCache);
DisplayController controller =
DisplayController.INSTANCE.get(helper.sandboxContext);
@@ -234,7 +234,8 @@ public class InvariantDeviceProfile {
/*allowDisabledGrid=*/false),
defaultDeviceType);
Info myInfo = new Info(context, display);
Context displayContext = context.createDisplayContext(display);
Info myInfo = new Info(displayContext);
@DeviceType int deviceType = getDeviceType(myInfo);
DisplayOption myDisplayOption = invDistWeightedInterpolate(
myInfo,
@@ -642,7 +643,7 @@ public class InvariantDeviceProfile {
+ "\nconfig: " + config
+ "\ndisplayMetrics: " + res.getDisplayMetrics()
+ "\nrotation: " + rotation
+ "\n" + stringWriter.toString(),
+ "\n" + stringWriter,
new Exception());
}
return getBestMatch(screenWidth, screenHeight, rotation);
@@ -26,6 +26,7 @@ import android.util.FloatProperty;
import android.util.IntProperty;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.TextView;
import com.android.launcher3.util.MultiScalePropertyFactory;
@@ -115,6 +116,32 @@ public class LauncherAnimUtils {
}
};
public static final IntProperty<TextView> TEXT_COLOR =
new IntProperty<TextView>("textColor") {
@Override
public Integer get(TextView view) {
return view.getTextColors().getDefaultColor();
}
@Override
public void setValue(TextView view, int color) {
view.setTextColor(color);
}
};
public static final IntProperty<TextView> HINT_TEXT_COLOR =
new IntProperty<TextView>("hintTextColor") {
@Override
public Integer get(TextView view) {
return view.getHintTextColors().getDefaultColor();
}
@Override
public void setValue(TextView view, int color) {
view.setHintTextColor(color);
}
};
public static final FloatProperty<View> VIEW_TRANSLATE_X =
View.TRANSLATION_X instanceof FloatProperty ? (FloatProperty) View.TRANSLATION_X
: new FloatProperty<View>("translateX") {
@@ -97,6 +97,18 @@ public class AnimatedPropertySetter extends PropertySetter {
return anim;
}
@NonNull
@Override
public <T> Animator setColor(T target, IntProperty<T> property, int value,
TimeInterpolator interpolator) {
if (property.get(target) == value) {
return NO_OP;
}
Animator anim = ObjectAnimator.ofArgb(target, property, value);
anim.setInterpolator(interpolator);
add(anim);
return anim;
}
/**
* Adds a callback to be run on every frame of the animation
@@ -88,6 +88,16 @@ public abstract class PropertySetter {
return NO_OP;
}
/**
* Updates a color property of the target using the provided interpolator
*/
@NonNull
public <T> Animator setColor(T target, IntProperty<T> property, int value,
TimeInterpolator interpolator) {
property.setValue(target, value);
return NO_OP;
}
/**
* Runs the animation as part of setting the property
*/
@@ -41,7 +41,6 @@ import android.os.Build;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
import android.view.Display;
import androidx.annotation.AnyThread;
@@ -117,8 +116,9 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
getPackageFilter(TARGET_OVERLAY_PACKAGE, ACTION_OVERLAY_CHANGED));
WindowManagerProxy wmProxy = WindowManagerProxy.INSTANCE.get(context);
mInfo = new Info(getDisplayInfoContext(display), display,
wmProxy, wmProxy.estimateInternalDisplayBounds(context));
Context displayInfoContext = getDisplayInfoContext(display);
mInfo = new Info(displayInfoContext, wmProxy,
wmProxy.estimateInternalDisplayBounds(displayInfoContext));
}
/**
@@ -216,18 +216,18 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
WindowManagerProxy wmProxy = WindowManagerProxy.INSTANCE.get(mContext);
Info oldInfo = mInfo;
Context displayContext = getDisplayInfoContext(display);
Info newInfo = new Info(displayContext, display, wmProxy, oldInfo.mPerDisplayBounds);
Context displayInfoContext = getDisplayInfoContext(display);
Info newInfo = new Info(displayInfoContext, wmProxy, oldInfo.mPerDisplayBounds);
if (newInfo.densityDpi != oldInfo.densityDpi || newInfo.fontScale != oldInfo.fontScale
|| newInfo.navigationMode != oldInfo.navigationMode) {
// Cache may not be valid anymore, recreate without cache
newInfo = new Info(displayContext, display, wmProxy,
wmProxy.estimateInternalDisplayBounds(displayContext));
newInfo = new Info(displayInfoContext, wmProxy,
wmProxy.estimateInternalDisplayBounds(displayInfoContext));
}
int change = 0;
if (!newInfo.displayId.equals(oldInfo.displayId)) {
if (!newInfo.normalizedDisplayInfo.equals(oldInfo.normalizedDisplayInfo)) {
change |= CHANGE_ACTIVE_SCREEN;
}
if (newInfo.rotation != oldInfo.rotation) {
@@ -242,35 +242,16 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
if (!newInfo.supportedBounds.equals(oldInfo.supportedBounds)
|| !newInfo.mPerDisplayBounds.equals(oldInfo.mPerDisplayBounds)) {
change |= CHANGE_SUPPORTED_BOUNDS;
Point currentS = newInfo.currentSize;
Pair<CachedDisplayInfo, WindowBounds[]> cachedBounds =
oldInfo.mPerDisplayBounds.get(newInfo.displayId);
Point expectedS = cachedBounds == null ? null : cachedBounds.first.size;
if (newInfo.supportedBounds.size() != oldInfo.supportedBounds.size()) {
Log.e("b/198965093",
"Inconsistent number of displays"
+ "\ndisplay state: " + display.getState()
+ "\noldInfo.supportedBounds: " + oldInfo.supportedBounds
+ "\nnewInfo.supportedBounds: " + newInfo.supportedBounds);
}
if (expectedS != null
&& (Math.min(currentS.x, currentS.y) != Math.min(expectedS.x, expectedS.y)
|| Math.max(currentS.x, currentS.y) != Math.max(expectedS.x, expectedS.y))
&& display.getState() == Display.STATE_OFF) {
Log.e("b/198965093",
"Display size changed while display is off, ignoring change");
return;
}
}
Log.d("b/198965093", "handleInfoChange"
+ "\n\tchange: " + change
+ "\n\tConfiguration diff: " + newInfo.mConfiguration.diff(oldInfo.mConfiguration));
+ "\n\tchange: 0b" + Integer.toBinaryString(change)
+ "\n\tConfiguration diff: 0x" + Integer.toHexString(
newInfo.mConfiguration.diff(oldInfo.mConfiguration)));
if (change != 0) {
mInfo = newInfo;
final int flags = change;
MAIN_EXECUTOR.execute(() -> notifyChange(displayContext, flags));
MAIN_EXECUTOR.execute(() -> notifyChange(displayInfoContext, flags));
}
}
@@ -288,8 +269,8 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
public static class Info {
// Cached property
public final CachedDisplayInfo normalizedDisplayInfo;
public final int rotation;
public final String displayId;
public final Point currentSize;
public final Rect cutout;
@@ -302,60 +283,71 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
public final Set<WindowBounds> supportedBounds = new ArraySet<>();
private final ArrayMap<String, Pair<CachedDisplayInfo, WindowBounds[]>> mPerDisplayBounds =
private final ArrayMap<CachedDisplayInfo, WindowBounds[]> mPerDisplayBounds =
new ArrayMap<>();
// TODO(b/198965093): Remove after investigation
private Configuration mConfiguration;
public Info(Context context, Display display) {
public Info(Context displayInfoContext) {
/* don't need system overrides for external displays */
this(context, display, new WindowManagerProxy(), new ArrayMap<>());
this(displayInfoContext, new WindowManagerProxy(), new ArrayMap<>());
}
// Used for testing
public Info(Context context, Display display,
public Info(Context displayInfoContext,
WindowManagerProxy wmProxy,
ArrayMap<String, Pair<CachedDisplayInfo, WindowBounds[]>> perDisplayBoundsCache) {
CachedDisplayInfo displayInfo = wmProxy.getDisplayInfo(context, display);
ArrayMap<CachedDisplayInfo, WindowBounds[]> perDisplayBoundsCache) {
CachedDisplayInfo displayInfo = wmProxy.getDisplayInfo(displayInfoContext);
normalizedDisplayInfo = displayInfo.normalize();
rotation = displayInfo.rotation;
currentSize = displayInfo.size;
displayId = displayInfo.id;
cutout = displayInfo.cutout;
Configuration config = context.getResources().getConfiguration();
Configuration config = displayInfoContext.getResources().getConfiguration();
fontScale = config.fontScale;
densityDpi = config.densityDpi;
mScreenSizeDp = new PortraitSize(config.screenHeightDp, config.screenWidthDp);
navigationMode = parseNavigationMode(context);
navigationMode = parseNavigationMode(displayInfoContext);
// TODO(b/198965093): Remove after investigation
mConfiguration = config;
mPerDisplayBounds.putAll(perDisplayBoundsCache);
Pair<CachedDisplayInfo, WindowBounds[]> cachedValue = mPerDisplayBounds.get(displayId);
WindowBounds[] cachedValue = mPerDisplayBounds.get(normalizedDisplayInfo);
WindowBounds realBounds = wmProxy.getRealBounds(context, display, displayInfo);
WindowBounds realBounds = wmProxy.getRealBounds(displayInfoContext, displayInfo);
if (cachedValue == null) {
supportedBounds.add(realBounds);
} else {
// Unexpected normalizedDisplayInfo is found, recreate the cache
Log.e("b/198965093", "Unexpected normalizedDisplayInfo found, invalidating cache");
mPerDisplayBounds.clear();
mPerDisplayBounds.putAll(wmProxy.estimateInternalDisplayBounds(displayInfoContext));
cachedValue = mPerDisplayBounds.get(normalizedDisplayInfo);
if (cachedValue == null) {
Log.e("b/198965093", "normalizedDisplayInfo not found in estimation: "
+ normalizedDisplayInfo);
supportedBounds.add(realBounds);
}
}
if (cachedValue != null) {
// Verify that the real bounds are a match
WindowBounds expectedBounds = cachedValue.second[displayInfo.rotation];
WindowBounds expectedBounds = cachedValue[displayInfo.rotation];
if (!realBounds.equals(expectedBounds)) {
WindowBounds[] clone = new WindowBounds[4];
System.arraycopy(cachedValue.second, 0, clone, 0, 4);
System.arraycopy(cachedValue, 0, clone, 0, 4);
clone[displayInfo.rotation] = realBounds;
cachedValue = Pair.create(displayInfo.normalize(), clone);
mPerDisplayBounds.put(displayId, cachedValue);
mPerDisplayBounds.put(normalizedDisplayInfo, clone);
}
}
mPerDisplayBounds.values().forEach(
pair -> Collections.addAll(supportedBounds, pair.second));
windowBounds -> Collections.addAll(supportedBounds, windowBounds));
Log.e("b/198965093", "mConfiguration: " + mConfiguration);
Log.d("b/198965093", "displayInfo: " + displayInfo);
Log.d("b/198965093", "realBounds: " + realBounds);
mPerDisplayBounds.values().forEach(pair -> Log.d("b/198965093",
"perDisplayBounds - " + pair.first + ": " + Arrays.deepToString(pair.second)));
Log.d("b/198965093", "normalizedDisplayInfo: " + normalizedDisplayInfo);
mPerDisplayBounds.forEach((key, value) -> Log.d("b/198965093",
"perDisplayBounds - " + key + ": " + Arrays.deepToString(value)));
}
/**
@@ -383,14 +375,14 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
public void dump(PrintWriter pw) {
Info info = mInfo;
pw.println("DisplayController.Info:");
pw.println(" id=" + info.displayId);
pw.println(" normalizedDisplayInfo=" + info.normalizedDisplayInfo);
pw.println(" rotation=" + info.rotation);
pw.println(" fontScale=" + info.fontScale);
pw.println(" densityDpi=" + info.densityDpi);
pw.println(" navigationMode=" + info.navigationMode.name());
pw.println(" currentSize=" + info.currentSize);
info.mPerDisplayBounds.values().forEach(pair -> pw.println(
" perDisplayBounds - " + pair.first + ": " + Arrays.deepToString(pair.second)));
info.mPerDisplayBounds.forEach((key, value) -> pw.println(
" perDisplayBounds - " + key + ": " + Arrays.deepToString(value)));
}
/**
@@ -30,7 +30,6 @@ import java.util.Objects;
*/
public class CachedDisplayInfo {
public final String id;
public final Point size;
public final int rotation;
public final Rect cutout;
@@ -40,11 +39,10 @@ public class CachedDisplayInfo {
}
public CachedDisplayInfo(Point size, int rotation) {
this("", size, rotation, new Rect());
this(size, rotation, new Rect());
}
public CachedDisplayInfo(String id, Point size, int rotation, Rect cutout) {
this.id = id;
public CachedDisplayInfo(Point size, int rotation, Rect cutout) {
this.size = size;
this.rotation = rotation;
this.cutout = cutout;
@@ -62,16 +60,15 @@ public class CachedDisplayInfo {
Rect newCutout = new Rect(cutout);
rotateRect(newCutout, deltaRotation(rotation, Surface.ROTATION_0));
return new CachedDisplayInfo(id, newSize, Surface.ROTATION_0, newCutout);
return new CachedDisplayInfo(newSize, Surface.ROTATION_0, newCutout);
}
@Override
public String toString() {
return "CachedDisplayInfo{"
+ "id='" + id + '\''
+ ", size=" + size
+ ", rotation=" + rotation
+ "size=" + size
+ ", cutout=" + cutout
+ ", rotation=" + rotation
+ '}';
}
@@ -80,13 +77,13 @@ public class CachedDisplayInfo {
if (this == o) return true;
if (!(o instanceof CachedDisplayInfo)) return false;
CachedDisplayInfo that = (CachedDisplayInfo) o;
return rotation == that.rotation && Objects.equals(id, that.id)
&& Objects.equals(size, that.size) && Objects.equals(cutout,
that.cutout);
return rotation == that.rotation
&& Objects.equals(size, that.size)
&& Objects.equals(cutout, that.cutout);
}
@Override
public int hashCode() {
return Objects.hash(id, size, rotation, cutout);
return Objects.hash(size, rotation, cutout);
}
}
@@ -16,7 +16,6 @@
package com.android.launcher3.util.window;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static com.android.launcher3.ResourceUtils.INVALID_RESOURCE_HANDLE;
import static com.android.launcher3.ResourceUtils.NAVBAR_HEIGHT;
@@ -41,7 +40,6 @@ import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.os.Build;
import android.util.ArrayMap;
import android.util.Pair;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.Surface;
@@ -88,20 +86,12 @@ public class WindowManagerProxy implements ResourceBasedOverride {
* Returns a map of normalized info of internal displays to estimated window bounds
* for that display
*/
public ArrayMap<String, Pair<CachedDisplayInfo, WindowBounds[]>> estimateInternalDisplayBounds(
Context context) {
Display[] displays = context.getSystemService(DisplayManager.class).getDisplays();
ArrayMap<String, Pair<CachedDisplayInfo, WindowBounds[]>> result = new ArrayMap<>();
for (Display display : displays) {
if (isInternalDisplay(display)) {
Context displayContext = Utilities.ATLEAST_S
? context.createWindowContext(display, TYPE_APPLICATION, null)
: context.createDisplayContext(display);
CachedDisplayInfo info = getDisplayInfo(displayContext, display).normalize();
WindowBounds[] bounds = estimateWindowBounds(context, info);
result.put(info.id, Pair.create(info, bounds));
}
}
public ArrayMap<CachedDisplayInfo, WindowBounds[]> estimateInternalDisplayBounds(
Context displayInfoContext) {
CachedDisplayInfo info = getDisplayInfo(displayInfoContext).normalize();
WindowBounds[] bounds = estimateWindowBounds(displayInfoContext, info);
ArrayMap<CachedDisplayInfo, WindowBounds[]> result = new ArrayMap<>();
result.put(info, bounds);
return result;
}
@@ -109,12 +99,11 @@ public class WindowManagerProxy implements ResourceBasedOverride {
* Returns the real bounds for the provided display after applying any insets normalization
*/
@TargetApi(Build.VERSION_CODES.R)
public WindowBounds getRealBounds(Context windowContext,
Display display, CachedDisplayInfo info) {
public WindowBounds getRealBounds(Context displayInfoContext, CachedDisplayInfo info) {
if (!Utilities.ATLEAST_R) {
Point smallestSize = new Point();
Point largestSize = new Point();
display.getCurrentSizeRange(smallestSize, largestSize);
getDisplay(displayInfoContext).getCurrentSizeRange(smallestSize, largestSize);
if (info.size.y > info.size.x) {
// Portrait
@@ -122,17 +111,16 @@ public class WindowManagerProxy implements ResourceBasedOverride {
info.rotation);
} else {
// Landscape
new WindowBounds(info.size.x, info.size.y, largestSize.x, smallestSize.y,
return new WindowBounds(info.size.x, info.size.y, largestSize.x, smallestSize.y,
info.rotation);
}
}
WindowMetrics wm = windowContext.getSystemService(WindowManager.class)
WindowMetrics windowMetrics = displayInfoContext.getSystemService(WindowManager.class)
.getMaximumWindowMetrics();
Rect insets = new Rect();
normalizeWindowInsets(windowContext, wm.getWindowInsets(), insets);
return new WindowBounds(wm.getBounds(), insets, info.rotation);
normalizeWindowInsets(displayInfoContext, windowMetrics.getWindowInsets(), insets);
return new WindowBounds(windowMetrics.getBounds(), insets, info.rotation);
}
/**
@@ -169,12 +157,9 @@ public class WindowManagerProxy implements ResourceBasedOverride {
insetsBuilder.setInsetsIgnoringVisibility(WindowInsets.Type.navigationBars(), newNavInsets);
Insets statusBarInsets = oldInsets.getInsets(WindowInsets.Type.statusBars());
int statusBarHeight = getDimenByName(systemRes,
(isPortrait) ? STATUS_BAR_HEIGHT_PORTRAIT : STATUS_BAR_HEIGHT_LANDSCAPE,
STATUS_BAR_HEIGHT);
Insets newStatusBarInsets = Insets.of(
statusBarInsets.left,
Math.max(statusBarInsets.top, statusBarHeight),
@@ -201,22 +186,15 @@ public class WindowManagerProxy implements ResourceBasedOverride {
return result;
}
/**
* Returns true if the display is an internal displays
*/
protected boolean isInternalDisplay(Display display) {
return display.getDisplayId() == Display.DEFAULT_DISPLAY;
}
/**
* Returns a list of possible WindowBounds for the display keyed on the 4 surface rotations
*/
public WindowBounds[] estimateWindowBounds(Context context, CachedDisplayInfo display) {
protected WindowBounds[] estimateWindowBounds(Context context, CachedDisplayInfo displayInfo) {
int densityDpi = context.getResources().getConfiguration().densityDpi;
int rotation = display.rotation;
Rect safeCutout = display.cutout;
int rotation = displayInfo.rotation;
Rect safeCutout = displayInfo.cutout;
int minSize = Math.min(display.size.x, display.size.y);
int minSize = Math.min(displayInfo.size.x, displayInfo.size.y);
int swDp = (int) dpiFromPx(minSize, densityDpi);
Resources systemRes;
@@ -255,7 +233,7 @@ public class WindowManagerProxy implements ResourceBasedOverride {
Point tempSize = new Point();
for (int i = 0; i < 4; i++) {
int rotationChange = deltaRotation(rotation, i);
tempSize.set(display.size.x, display.size.y);
tempSize.set(displayInfo.size.x, displayInfo.size.y);
rotateSize(tempSize, rotationChange);
Rect bounds = new Rect(0, 0, tempSize.x, tempSize.y);
@@ -311,48 +289,58 @@ public class WindowManagerProxy implements ResourceBasedOverride {
* Returns a CachedDisplayInfo initialized for the current display
*/
@TargetApi(Build.VERSION_CODES.S)
public CachedDisplayInfo getDisplayInfo(Context displayContext, Display display) {
int rotation = getRotation(displayContext);
Rect cutoutRect = new Rect();
Point size = new Point();
public CachedDisplayInfo getDisplayInfo(Context displayInfoContext) {
int rotation = getRotation(displayInfoContext);
if (Utilities.ATLEAST_S) {
WindowMetrics wm = displayContext.getSystemService(WindowManager.class)
WindowMetrics windowMetrics = displayInfoContext.getSystemService(WindowManager.class)
.getMaximumWindowMetrics();
DisplayCutout cutout = wm.getWindowInsets().getDisplayCutout();
if (cutout != null) {
cutoutRect.set(cutout.getSafeInsetLeft(), cutout.getSafeInsetTop(),
cutout.getSafeInsetRight(), cutout.getSafeInsetBottom());
}
size.set(wm.getBounds().right, wm.getBounds().bottom);
return getDisplayInfo(windowMetrics, rotation);
} else {
Point size = new Point();
Display display = getDisplay(displayInfoContext);
display.getRealSize(size);
Rect cutoutRect = new Rect();
return new CachedDisplayInfo(size, rotation, cutoutRect);
}
return new CachedDisplayInfo(getDisplayId(display), size, rotation, cutoutRect);
}
/**
* Returns a unique ID representing the display
* Returns a CachedDisplayInfo initialized for the current display
*/
protected String getDisplayId(Display display) {
return Integer.toString(display.getDisplayId());
@TargetApi(Build.VERSION_CODES.S)
protected CachedDisplayInfo getDisplayInfo(WindowMetrics windowMetrics, int rotation) {
Point size = new Point(windowMetrics.getBounds().right, windowMetrics.getBounds().bottom);
Rect cutoutRect = new Rect();
DisplayCutout cutout = windowMetrics.getWindowInsets().getDisplayCutout();
if (cutout != null) {
cutoutRect.set(cutout.getSafeInsetLeft(), cutout.getSafeInsetTop(),
cutout.getSafeInsetRight(), cutout.getSafeInsetBottom());
}
return new CachedDisplayInfo(size, rotation, cutoutRect);
}
/**
* Returns rotation of the display associated with the context.
* Returns rotation of the display associated with the context, or rotation of DEFAULT_DISPLAY
* if the context isn't associated with a display.
*/
public int getRotation(Context context) {
Display d = null;
public int getRotation(Context displayInfoContext) {
return getDisplay(displayInfoContext).getRotation();
}
/**
*
* Returns the display associated with the context, or DEFAULT_DISPLAY if the context isn't
* associated with a display.
*/
protected Display getDisplay(Context displayInfoContext) {
if (Utilities.ATLEAST_R) {
try {
d = context.getDisplay();
return displayInfoContext.getDisplay();
} catch (UnsupportedOperationException e) {
// Ignore
}
}
if (d == null) {
d = context.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY);
}
return d.getRotation();
return displayInfoContext.getSystemService(DisplayManager.class).getDisplay(
DEFAULT_DISPLAY);
}
}
@@ -47,8 +47,7 @@ public class DisplayEmulator {
* By changing the WindowManagerProxy we can override the window insets information
**/
private IWindowManager changeWindowManagerInstance(DeviceEmulationData deviceData) {
WindowManagerProxy.INSTANCE.initializeForTesting(
new TestWindowManagerProxy(mContext, deviceData));
WindowManagerProxy.INSTANCE.initializeForTesting(new TestWindowManagerProxy(deviceData));
return WindowManagerGlobal.getWindowManagerService();
}
@@ -57,8 +56,7 @@ public class DisplayEmulator {
WindowManagerProxy original = WindowManagerProxy.INSTANCE.get(mContext);
// Set up emulation
final int userId = UserHandle.myUserId();
WindowManagerProxy.INSTANCE.initializeForTesting(
new TestWindowManagerProxy(mContext, device));
WindowManagerProxy.INSTANCE.initializeForTesting(new TestWindowManagerProxy(device));
IWindowManager wm = changeWindowManagerInstance(device);
// Change density twice to force display controller to reset its state
wm.setForcedDisplayDensityForUser(Display.DEFAULT_DISPLAY, device.density / 2, userId);
@@ -19,7 +19,6 @@ import android.content.Context;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
import android.view.Display;
import android.view.WindowInsets;
import com.android.launcher3.deviceemulator.models.DeviceEmulationData;
@@ -32,16 +31,11 @@ public class TestWindowManagerProxy extends WindowManagerProxy {
private final DeviceEmulationData mDevice;
public TestWindowManagerProxy(Context context, DeviceEmulationData device) {
public TestWindowManagerProxy(DeviceEmulationData device) {
super(true);
mDevice = device;
}
@Override
public boolean isInternalDisplay(Display display) {
return display.getDisplayId() == Display.DEFAULT_DISPLAY;
}
@Override
protected int getDimenByName(Resources res, String resName) {
Integer mock = mDevice.resourceOverrides.get(resName);
@@ -54,27 +48,25 @@ public class TestWindowManagerProxy extends WindowManagerProxy {
}
@Override
public CachedDisplayInfo getDisplayInfo(Context context, Display display) {
int rotation = display.getRotation();
public CachedDisplayInfo getDisplayInfo(Context displayInfoContext) {
int rotation = getRotation(displayInfoContext);
Point size = new Point(mDevice.width, mDevice.height);
RotationUtils.rotateSize(size, rotation);
Rect cutout = new Rect(mDevice.cutout);
RotationUtils.rotateRect(cutout, rotation);
return new CachedDisplayInfo(getDisplayId(display), size, rotation, cutout);
return new CachedDisplayInfo(size, rotation, cutout);
}
@Override
public WindowBounds getRealBounds(Context windowContext, Display display,
CachedDisplayInfo info) {
return estimateInternalDisplayBounds(windowContext)
.get(getDisplayId(display)).second[display.getRotation()];
public WindowBounds getRealBounds(Context displayInfoContext, CachedDisplayInfo info) {
return estimateInternalDisplayBounds(displayInfoContext).get(
getDisplayInfo(displayInfoContext))[getDisplay(displayInfoContext).getRotation()];
}
@Override
public WindowInsets normalizeWindowInsets(Context context, WindowInsets oldInsets,
Rect outInsets) {
outInsets.set(getRealBounds(context, context.getDisplay(),
getDisplayInfo(context, context.getDisplay())).insets);
outInsets.set(getRealBounds(context, getDisplayInfo(context)).insets);
return oldInsets;
}
}