summaryrefslogtreecommitdiff
path: root/core/java/android/view/ViewRootImpl.java
diff options
context:
space:
mode:
authorGeorge Zacharia <george.zcharia@gmail.com>2023-04-03 21:58:43 +0530
committerGeorge Zacharia <george.zcharia@gmail.com>2023-04-03 21:58:43 +0530
commitdcf61a20e815a87591f972a1f7346e853e7577d8 (patch)
treece9ff4f64103970d62d2913669e0796684d4e718 /core/java/android/view/ViewRootImpl.java
parent55ec62431ce028bd946c8fa1327e8a470c4e6d38 (diff)
parentaf0429f7c3314ac83bc537bf6281dc78f55bcccf (diff)
Merge tag 'android-13.0.0_r35' of https://android.googlesource.com/platform/frameworks/base into t13.0
Android 13.0.0 release 35 Change-Id: I709958b2f015d1774b2ece25894467c3a279f93c
Diffstat (limited to 'core/java/android/view/ViewRootImpl.java')
-rw-r--r--core/java/android/view/ViewRootImpl.java254
1 files changed, 184 insertions, 70 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 07a2504335a4..8ad1bcd533fc 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -77,6 +77,7 @@ import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
@@ -257,6 +258,7 @@ public final class ViewRootImpl implements ViewParent,
private static final boolean DEBUG_CONTENT_CAPTURE = false || LOCAL_LOGV;
private static final boolean DEBUG_SCROLL_CAPTURE = false || LOCAL_LOGV;
private static final boolean DEBUG_BLAST = false || LOCAL_LOGV;
+ private static final int LOGTAG_INPUT_FOCUS = 62001;
/**
* Set to false if we do not want to use the multi threaded renderer even though
@@ -284,7 +286,7 @@ public final class ViewRootImpl implements ViewParent,
* @hide
*/
public static final boolean LOCAL_LAYOUT =
- SystemProperties.getBoolean("persist.debug.local_layout", false);
+ SystemProperties.getBoolean("persist.debug.local_layout", true);
/**
* Set this system property to true to force the view hierarchy to render
@@ -502,6 +504,13 @@ public final class ViewRootImpl implements ViewParent,
Region mTouchableRegion;
Region mPreviousTouchableRegion;
+ private int mMeasuredWidth;
+ private int mMeasuredHeight;
+
+ // This indicates that we've already known the window size but without measuring the views.
+ // If this is true, we must measure the views before laying out them.
+ private boolean mViewMeasureDeferred;
+
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
int mWidth;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@@ -712,7 +721,7 @@ public final class ViewRootImpl implements ViewParent,
private final InsetsState mTempInsets = new InsetsState();
private final InsetsSourceControl[] mTempControls = new InsetsSourceControl[SIZE];
private final WindowConfiguration mTempWinConfig = new WindowConfiguration();
- private float mInvSizeCompatScale = 1f;
+ private float mInvCompatScale = 1f;
final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets
= new ViewTreeObserver.InternalInsetsInfo();
@@ -1099,6 +1108,10 @@ public final class ViewRootImpl implements ViewParent,
mInputQueueCallback.onInputQueueCreated(mInputQueue);
}
}
+
+ // Update the last resource config in case the resource configuration was changed while
+ // activity relaunched.
+ updateLastConfigurationFromResources(getConfiguration());
}
private Configuration getConfiguration() {
@@ -1107,11 +1120,11 @@ public final class ViewRootImpl implements ViewParent,
private WindowConfiguration getCompatWindowConfiguration() {
final WindowConfiguration winConfig = getConfiguration().windowConfiguration;
- if (mInvSizeCompatScale == 1f) {
+ if (mInvCompatScale == 1f) {
return winConfig;
}
mTempWinConfig.setTo(winConfig);
- mTempWinConfig.scale(mInvSizeCompatScale);
+ mTempWinConfig.scale(mInvCompatScale);
return mTempWinConfig;
}
@@ -1245,11 +1258,11 @@ public final class ViewRootImpl implements ViewParent,
controlInsetsForCompatibility(mWindowAttributes);
Rect attachedFrame = new Rect();
- final float[] sizeCompatScale = { 1f };
+ final float[] compatScale = { 1f };
res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), userId,
mInsetsController.getRequestedVisibilities(), inputChannel, mTempInsets,
- mTempControls, attachedFrame, sizeCompatScale);
+ mTempControls, attachedFrame, compatScale);
if (!attachedFrame.isValid()) {
attachedFrame = null;
}
@@ -1259,8 +1272,8 @@ public final class ViewRootImpl implements ViewParent,
mTranslator.translateRectInScreenToAppWindow(attachedFrame);
}
mTmpFrames.attachedFrame = attachedFrame;
- mTmpFrames.sizeCompatScale = sizeCompatScale[0];
- mInvSizeCompatScale = 1f / sizeCompatScale[0];
+ mTmpFrames.compatScale = compatScale[0];
+ mInvCompatScale = 1f / compatScale[0];
} catch (RemoteException e) {
mAdded = false;
mView = null;
@@ -1401,7 +1414,11 @@ public final class ViewRootImpl implements ViewParent,
mFirstPostImeInputStage = earlyPostImeStage;
mPendingInputEventQueueLengthCounterName = "aq:pending:" + counterSuffix;
- AnimationHandler.requestAnimatorsEnabled(mAppVisible, this);
+ if (!mRemoved || !mAppVisible) {
+ AnimationHandler.requestAnimatorsEnabled(mAppVisible, this);
+ } else if (LOCAL_LOGV) {
+ Log.v(mTag, "setView() enabling visibility when removed");
+ }
}
}
}
@@ -1739,7 +1756,12 @@ public final class ViewRootImpl implements ViewParent,
if (!mAppVisible) {
WindowManagerGlobal.trimForeground();
}
- AnimationHandler.requestAnimatorsEnabled(mAppVisible, this);
+ // Only enable if the window is not already removed (via earlier call to doDie())
+ if (!mRemoved || !mAppVisible) {
+ AnimationHandler.requestAnimatorsEnabled(mAppVisible, this);
+ } else if (LOCAL_LOGV) {
+ Log.v(mTag, "handleAppVisibility() enabling visibility when removed");
+ }
}
}
@@ -1769,24 +1791,24 @@ public final class ViewRootImpl implements ViewParent,
mTranslator.translateRectInScreenToAppWindow(displayFrame);
mTranslator.translateRectInScreenToAppWindow(attachedFrame);
}
- final float sizeCompatScale = frames.sizeCompatScale;
+ final float compatScale = frames.compatScale;
final boolean frameChanged = !mWinFrame.equals(frame);
final boolean configChanged = !mLastReportedMergedConfiguration.equals(mergedConfiguration);
final boolean attachedFrameChanged = LOCAL_LAYOUT
&& !Objects.equals(mTmpFrames.attachedFrame, attachedFrame);
final boolean displayChanged = mDisplay.getDisplayId() != displayId;
final boolean resizeModeChanged = mResizeMode != resizeMode;
- final boolean sizeCompatScaleChanged = mTmpFrames.sizeCompatScale != sizeCompatScale;
+ final boolean compatScaleChanged = mTmpFrames.compatScale != compatScale;
if (msg == MSG_RESIZED && !frameChanged && !configChanged && !attachedFrameChanged
&& !displayChanged && !resizeModeChanged && !forceNextWindowRelayout
- && !sizeCompatScaleChanged) {
+ && !compatScaleChanged) {
return;
}
mPendingDragResizing = resizeMode != RESIZE_MODE_INVALID;
mResizeMode = resizeMode;
- mTmpFrames.sizeCompatScale = sizeCompatScale;
- mInvSizeCompatScale = 1f / sizeCompatScale;
+ mTmpFrames.compatScale = compatScale;
+ mInvCompatScale = 1f / compatScale;
if (configChanged) {
// If configuration changed - notify about that and, maybe, about move to display.
@@ -2549,7 +2571,8 @@ public final class ViewRootImpl implements ViewParent,
}
private boolean measureHierarchy(final View host, final WindowManager.LayoutParams lp,
- final Resources res, final int desiredWindowWidth, final int desiredWindowHeight) {
+ final Resources res, final int desiredWindowWidth, final int desiredWindowHeight,
+ boolean forRootSizeOnly) {
int childWidthMeasureSpec;
int childHeightMeasureSpec;
boolean windowSizeMayChange = false;
@@ -2605,7 +2628,15 @@ public final class ViewRootImpl implements ViewParent,
lp.privateFlags);
childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height,
lp.privateFlags);
- performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
+ if (!forRootSizeOnly || !setMeasuredRootSizeFromSpec(
+ childWidthMeasureSpec, childHeightMeasureSpec)) {
+ performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
+ } else {
+ // We already know how big the window should be before measuring the views.
+ // We can measure the views before laying out them. This is to avoid unnecessary
+ // measure.
+ mViewMeasureDeferred = true;
+ }
if (mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight()) {
windowSizeMayChange = true;
}
@@ -2621,6 +2652,25 @@ public final class ViewRootImpl implements ViewParent,
}
/**
+ * Sets the measured root size for requesting the window frame.
+ *
+ * @param widthMeasureSpec contains the size and the mode of the width.
+ * @param heightMeasureSpec contains the size and the mode of the height.
+ * @return {@code true} if we actually set the measured size; {@code false} otherwise.
+ */
+ private boolean setMeasuredRootSizeFromSpec(int widthMeasureSpec, int heightMeasureSpec) {
+ final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+ final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+ if (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY) {
+ // We don't know the exact size. We need to measure the hierarchy to know that.
+ return false;
+ }
+ mMeasuredWidth = MeasureSpec.getSize(widthMeasureSpec);
+ mMeasuredHeight = MeasureSpec.getSize(heightMeasureSpec);
+ return true;
+ }
+
+ /**
* Modifies the input matrix such that it maps view-local coordinates to
* on-screen coordinates.
*
@@ -2707,6 +2757,14 @@ public final class ViewRootImpl implements ViewParent,
|| lp.type == TYPE_VOLUME_OVERLAY;
}
+ /**
+ * @return {@code true} if we should reduce unnecessary measure for the window.
+ * TODO(b/260382739): Apply this to all windows.
+ */
+ private static boolean shouldOptimizeMeasure(final WindowManager.LayoutParams lp) {
+ return lp.type == TYPE_NOTIFICATION_SHADE;
+ }
+
private Rect getWindowBoundsInsetSystemBars() {
final Rect bounds = new Rect(
mContext.getResources().getConfiguration().windowConfiguration.getBounds());
@@ -2757,6 +2815,7 @@ public final class ViewRootImpl implements ViewParent,
mAppVisibilityChanged = false;
final boolean viewUserVisibilityChanged = !mFirst &&
((mViewVisibility == View.VISIBLE) != (viewVisibility == View.VISIBLE));
+ final boolean shouldOptimizeMeasure = shouldOptimizeMeasure(lp);
WindowManager.LayoutParams params = null;
CompatibilityInfo compatibilityInfo =
@@ -2878,7 +2937,7 @@ public final class ViewRootImpl implements ViewParent,
// Ask host how big it wants to be
windowSizeMayChange |= measureHierarchy(host, lp, mView.getContext().getResources(),
- desiredWindowWidth, desiredWindowHeight);
+ desiredWindowWidth, desiredWindowHeight, shouldOptimizeMeasure);
}
if (collectViewAttributes()) {
@@ -2918,8 +2977,8 @@ public final class ViewRootImpl implements ViewParent,
// we don't need to go through two layout passes when things
// change due to fitting system windows, which can happen a lot.
windowSizeMayChange |= measureHierarchy(host, lp,
- mView.getContext().getResources(),
- desiredWindowWidth, desiredWindowHeight);
+ mView.getContext().getResources(), desiredWindowWidth, desiredWindowHeight,
+ shouldOptimizeMeasure);
}
}
@@ -3334,6 +3393,13 @@ public final class ViewRootImpl implements ViewParent,
maybeHandleWindowMove(frame);
}
+ if (mViewMeasureDeferred) {
+ // It's time to measure the views since we are going to layout them.
+ performMeasure(
+ MeasureSpec.makeMeasureSpec(frame.width(), MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(frame.height(), MeasureSpec.EXACTLY));
+ }
+
if (!mRelayoutRequested && mCheckIfCanDraw) {
// We had a sync previously, but we didn't call IWindowSession#relayout in this
// traversal. So we don't know if the sync is complete that we can continue to draw.
@@ -3739,45 +3805,7 @@ public final class ViewRootImpl implements ViewParent,
}
if (mAdded) {
- profileRendering(hasWindowFocus);
- if (hasWindowFocus) {
- if (mAttachInfo.mThreadedRenderer != null && mSurface.isValid()) {
- mFullRedrawNeeded = true;
- try {
- final Rect surfaceInsets = mWindowAttributes.surfaceInsets;
- mAttachInfo.mThreadedRenderer.initializeIfNeeded(
- mWidth, mHeight, mAttachInfo, mSurface, surfaceInsets);
- } catch (OutOfResourcesException e) {
- Log.e(mTag, "OutOfResourcesException locking surface", e);
- try {
- if (!mWindowSession.outOfMemory(mWindow)) {
- Slog.w(mTag, "No processes killed for memory;"
- + " killing self");
- Process.killProcess(Process.myPid());
- }
- } catch (RemoteException ex) {
- }
- // Retry in a bit.
- mHandler.sendMessageDelayed(mHandler.obtainMessage(
- MSG_WINDOW_FOCUS_CHANGED), 500);
- return;
- }
- }
- }
-
- mAttachInfo.mHasWindowFocus = hasWindowFocus;
- mImeFocusController.updateImeFocusable(mWindowAttributes, true /* force */);
- mImeFocusController.onPreWindowFocus(hasWindowFocus, mWindowAttributes);
-
- if (mView != null) {
- mAttachInfo.mKeyDispatchState.reset();
- mView.dispatchWindowFocusChanged(hasWindowFocus);
- mAttachInfo.mTreeObserver.dispatchOnWindowFocusChange(hasWindowFocus);
- if (mAttachInfo.mTooltipHost != null) {
- mAttachInfo.mTooltipHost.hideTooltip();
- }
- }
-
+ dispatchFocusEvent(hasWindowFocus, false /* fakeFocus */);
// Note: must be done after the focus change callbacks,
// so all of the view state is set up correctly.
mImeFocusController.onPostWindowFocus(
@@ -3812,6 +3840,73 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ /**
+ * Send a fake focus event for unfocused apps in split screen as some game engines wait to
+ * get focus before drawing the content of the app. This will be used so that apps do not get
+ * blacked out when they are resumed and do not have focus yet.
+ *
+ * {@hide}
+ */
+ // TODO(b/263094829): Investigate dispatching this for onPause as well
+ public void dispatchCompatFakeFocus() {
+ boolean aboutToHaveFocus = false;
+ synchronized (this) {
+ aboutToHaveFocus = mWindowFocusChanged && mUpcomingWindowFocus;
+ }
+ final boolean alreadyHaveFocus = mAttachInfo.mHasWindowFocus;
+ if (aboutToHaveFocus || alreadyHaveFocus) {
+ // Do not need to toggle focus if app doesn't need it, or has focus.
+ return;
+ }
+ EventLog.writeEvent(LOGTAG_INPUT_FOCUS,
+ "Giving fake focus to " + mBasePackageName, "reason=unity bug workaround");
+ dispatchFocusEvent(true /* hasWindowFocus */, true /* fakeFocus */);
+ EventLog.writeEvent(LOGTAG_INPUT_FOCUS,
+ "Removing fake focus from " + mBasePackageName, "reason=timeout callback");
+ dispatchFocusEvent(false /* hasWindowFocus */, true /* fakeFocus */);
+ }
+
+ private void dispatchFocusEvent(boolean hasWindowFocus, boolean fakeFocus) {
+ profileRendering(hasWindowFocus);
+ if (hasWindowFocus && mAttachInfo.mThreadedRenderer != null && mSurface.isValid()) {
+ mFullRedrawNeeded = true;
+ try {
+ final Rect surfaceInsets = mWindowAttributes.surfaceInsets;
+ mAttachInfo.mThreadedRenderer.initializeIfNeeded(
+ mWidth, mHeight, mAttachInfo, mSurface, surfaceInsets);
+ } catch (OutOfResourcesException e) {
+ Log.e(mTag, "OutOfResourcesException locking surface", e);
+ try {
+ if (!mWindowSession.outOfMemory(mWindow)) {
+ Slog.w(mTag, "No processes killed for memory;"
+ + " killing self");
+ Process.killProcess(Process.myPid());
+ }
+ } catch (RemoteException ex) {
+ }
+ // Retry in a bit.
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(
+ MSG_WINDOW_FOCUS_CHANGED), 500);
+ return;
+ }
+ }
+
+ mAttachInfo.mHasWindowFocus = hasWindowFocus;
+ if (!fakeFocus) {
+ mImeFocusController.updateImeFocusable(mWindowAttributes, true /* force */);
+ mImeFocusController.onPreWindowFocus(hasWindowFocus, mWindowAttributes);
+ }
+
+ if (mView != null) {
+ mAttachInfo.mKeyDispatchState.reset();
+ mView.dispatchWindowFocusChanged(hasWindowFocus);
+ mAttachInfo.mTreeObserver.dispatchOnWindowFocusChange(hasWindowFocus);
+ if (mAttachInfo.mTooltipHost != null) {
+ mAttachInfo.mTooltipHost.hideTooltip();
+ }
+ }
+ }
+
private void handleWindowTouchModeChanged() {
final boolean inTouchMode;
synchronized (this) {
@@ -3923,6 +4018,9 @@ public final class ViewRootImpl implements ViewParent,
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
+ mMeasuredWidth = mView.getMeasuredWidth();
+ mMeasuredHeight = mView.getMeasuredHeight();
+ mViewMeasureDeferred = false;
}
/**
@@ -4018,7 +4116,7 @@ public final class ViewRootImpl implements ViewParent,
view.requestLayout();
}
measureHierarchy(host, lp, mView.getContext().getResources(),
- desiredWindowWidth, desiredWindowHeight);
+ desiredWindowWidth, desiredWindowHeight, false /* forRootSizeOnly */);
mInLayout = true;
host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
@@ -5390,13 +5488,7 @@ public final class ViewRootImpl implements ViewParent,
// Update the display with new DisplayAdjustments.
updateInternalDisplay(mDisplay.getDisplayId(), localResources);
- final int lastLayoutDirection = mLastConfigurationFromResources.getLayoutDirection();
- final int currentLayoutDirection = config.getLayoutDirection();
- mLastConfigurationFromResources.setTo(config);
- if (lastLayoutDirection != currentLayoutDirection
- && mViewLayoutDirectionInitial == View.LAYOUT_DIRECTION_INHERIT) {
- mView.setLayoutDirection(currentLayoutDirection);
- }
+ updateLastConfigurationFromResources(config);
mView.dispatchConfigurationChanged(config);
// We could have gotten this {@link Configuration} update after we called
@@ -5410,6 +5502,17 @@ public final class ViewRootImpl implements ViewParent,
updateForceDarkMode();
}
+ private void updateLastConfigurationFromResources(Configuration resConfig) {
+ final int lastLayoutDirection = mLastConfigurationFromResources.getLayoutDirection();
+ final int currentLayoutDirection = resConfig.getLayoutDirection();
+ mLastConfigurationFromResources.setTo(resConfig);
+ // Update layout direction in case the language or screen layout is changed.
+ if (lastLayoutDirection != currentLayoutDirection && mView != null
+ && mViewLayoutDirectionInitial == View.LAYOUT_DIRECTION_INHERIT) {
+ mView.setLayoutDirection(currentLayoutDirection);
+ }
+ }
+
/**
* Return true if child is an ancestor of parent, (or equal to the parent).
*/
@@ -8086,8 +8189,8 @@ public final class ViewRootImpl implements ViewParent,
final WindowConfiguration winConfigFromWm =
mLastReportedMergedConfiguration.getGlobalConfiguration().windowConfiguration;
final WindowConfiguration winConfig = getCompatWindowConfiguration();
- final int measuredWidth = mView.getMeasuredWidth();
- final int measuredHeight = mView.getMeasuredHeight();
+ final int measuredWidth = mMeasuredWidth;
+ final int measuredHeight = mMeasuredHeight;
final boolean relayoutAsync;
if (LOCAL_LAYOUT
&& (mViewFrameInfo.flags & FrameInfo.FLAG_WINDOW_VISIBILITY_CHANGED) == 0
@@ -8157,6 +8260,7 @@ public final class ViewRootImpl implements ViewParent,
mLastSyncSeqId, mTmpFrames, mPendingMergedConfiguration, mSurfaceControl,
mTempInsets, mTempControls, mRelayoutBundle);
mRelayoutRequested = true;
+
final int maybeSyncSeqId = mRelayoutBundle.getInt("seqid");
if (maybeSyncSeqId > 0) {
mSyncSeqId = maybeSyncSeqId;
@@ -8169,7 +8273,7 @@ public final class ViewRootImpl implements ViewParent,
mTranslator.translateInsetsStateInScreenToAppWindow(mTempInsets);
mTranslator.translateSourceControlsInScreenToAppWindow(mTempControls);
}
- mInvSizeCompatScale = 1f / mTmpFrames.sizeCompatScale;
+ mInvCompatScale = 1f / mTmpFrames.compatScale;
mInsetsController.onStateChanged(mTempInsets);
mInsetsController.onControlsChanged(mTempControls);
@@ -8196,6 +8300,12 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ if (mSurfaceControl.isValid() && !HardwareRenderer.isDrawingEnabled()) {
+ // When drawing is disabled the window layer won't have a valid buffer.
+ // Set a window crop so input can get delivered to the window.
+ mTransaction.setWindowCrop(mSurfaceControl, mSurfaceSize.x, mSurfaceSize.y).apply();
+ }
+
mLastTransformHint = transformHint;
mSurfaceControl.setTransformHint(transformHint);
@@ -8485,6 +8595,10 @@ public final class ViewRootImpl implements ViewParent,
if (mLocalSyncState != LOCAL_SYNC_NONE) {
writer.println(innerPrefix + "mLocalSyncState=" + mLocalSyncState);
}
+ writer.println(innerPrefix + "mLastReportedMergedConfiguration="
+ + mLastReportedMergedConfiguration);
+ writer.println(innerPrefix + "mLastConfigurationFromResources="
+ + mLastConfigurationFromResources);
writer.println(innerPrefix + "mIsAmbientMode=" + mIsAmbientMode);
writer.println(innerPrefix + "mUnbufferedInputSource="
+ Integer.toHexString(mUnbufferedInputSource));