diff options
| author | George Zacharia <george.zcharia@gmail.com> | 2023-04-03 21:58:43 +0530 |
|---|---|---|
| committer | George Zacharia <george.zcharia@gmail.com> | 2023-04-03 21:58:43 +0530 |
| commit | dcf61a20e815a87591f972a1f7346e853e7577d8 (patch) | |
| tree | ce9ff4f64103970d62d2913669e0796684d4e718 /core/java/android/view/ViewRootImpl.java | |
| parent | 55ec62431ce028bd946c8fa1327e8a470c4e6d38 (diff) | |
| parent | af0429f7c3314ac83bc537bf6281dc78f55bcccf (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.java | 254 |
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)); |
