performDraw

  1. 初始化app后DecorView调用performTraversals(),执行完measure和layout后知道了view的ltrb(左上右下)坐标信息,下一步就是执行performDraw进行绘制了
  2. performDraw中经过层层调用,最终构造了canvas,并调用mView.draw(canvas)
  3. view的draw分了六步
        1. Draw the background
        2. If necessary, save the canvas' layers to prepare for fading(可忽略)
        3. Draw view's content
        4. Draw children
        5. If necessary, draw the fading edges and restore layers(可忽略)
        6. Draw decorations (scrollbars for instance)
    1. 画背景
      1. setBackgroundBounds中根据layout获得的ltrb参数设置绘制区域
    2. 保存canvas的layer信息
    3. 画view内容
      1. 空函数,需要具体类去实现
    4. 遍历画子view dispatchDraw(canvas);
      1. 没有子view不需要处理
      2. 看一下viewGroup中的处理
        protected void dispatchDraw(Canvas canvas) {
            boolean usingRenderNodeProperties = canvas.isRecordingFor(mRenderNode);
            final int childrenCount = mChildrenCount;
            final View[] children = mChildren;
            int flags = mGroupFlags;
        
            if ((flags & FLAG_RUN_ANIMATION) != 0 && canAnimate()) {
                final boolean buildCache = !isHardwareAccelerated();
                for (int i = 0; i < childrenCount; i++) {
                    final View child = children[i];
                    if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
                        final LayoutParams params = child.getLayoutParams();
                        attachLayoutAnimationParameters(child, params, i, childrenCount);
                        bindLayoutAnimation(child);
                    }
                }
        
                final LayoutAnimationController controller = mLayoutAnimationController;
                if (controller.willOverlap()) {
                    mGroupFlags |= FLAG_OPTIMIZE_INVALIDATE;
                }
        
                controller.start();
        
                mGroupFlags &= ~FLAG_RUN_ANIMATION;
                mGroupFlags &= ~FLAG_ANIMATION_DONE;
        
                if (mAnimationListener != null) {
                    mAnimationListener.onAnimationStart(controller.getAnimation());
                }
            }
        
            int clipSaveCount = 0;
            final boolean clipToPadding = (flags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK;
            if (clipToPadding) {
                clipSaveCount = canvas.save();
                canvas.clipRect(mScrollX + mPaddingLeft, mScrollY + mPaddingTop,
                        mScrollX + mRight - mLeft - mPaddingRight,
                        mScrollY + mBottom - mTop - mPaddingBottom);
            }
        
            // We will draw our child's animation, let's reset the flag
            mPrivateFlags &= ~PFLAG_DRAW_ANIMATION;
            mGroupFlags &= ~FLAG_INVALIDATE_REQUIRED;
        
            boolean more = false;
            final long drawingTime = getDrawingTime();
        
            if (usingRenderNodeProperties) canvas.insertReorderBarrier();
            final int transientCount = mTransientIndices == null ? 0 : mTransientIndices.size();
            int transientIndex = transientCount != 0 ? 0 : -1;
            // Only use the preordered list if not HW accelerated, since the HW pipeline will do the
            // draw reordering internally
            final ArrayList<View> preorderedList = usingRenderNodeProperties
                    ? null : buildOrderedChildList();
            final boolean customOrder = preorderedList == null
                    && isChildrenDrawingOrderEnabled();
            for (int i = 0; i < childrenCount; i++) {
                while (transientIndex >= 0 && mTransientIndices.get(transientIndex) == i) {
                    final View transientChild = mTransientViews.get(transientIndex);
                    if ((transientChild.mViewFlags & VISIBILITY_MASK) == VISIBLE ||
                            transientChild.getAnimation() != null) {
                        more |= drawChild(canvas, transientChild, drawingTime);
                    }
                    transientIndex++;
                    if (transientIndex >= transientCount) {
                        transientIndex = -1;
                    }
                }
        
                final int childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder);
                final View child = getAndVerifyPreorderedView(preorderedList, children, childIndex);
                if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {
                    more |= drawChild(canvas, child, drawingTime);
                }
            }
            while (transientIndex >= 0) {
                // there may be additional transient views after the normal views
                final View transientChild = mTransientViews.get(transientIndex);
                if ((transientChild.mViewFlags & VISIBILITY_MASK) == VISIBLE ||
                        transientChild.getAnimation() != null) {
                    more |= drawChild(canvas, transientChild, drawingTime);
                }
                transientIndex++;
                if (transientIndex >= transientCount) {
                    break;
                }
            }
            if (preorderedList != null) preorderedList.clear();
        
            // Draw any disappearing views that have animations
            if (mDisappearingChildren != null) {
                final ArrayList<View> disappearingChildren = mDisappearingChildren;
                final int disappearingCount = disappearingChildren.size() - 1;
                // Go backwards -- we may delete as animations finish
                for (int i = disappearingCount; i >= 0; i--) {
                    final View child = disappearingChildren.get(i);
                    more |= drawChild(canvas, child, drawingTime);
                }
            }
            if (usingRenderNodeProperties) canvas.insertInorderBarrier();
        
            if (debugDraw()) {
                onDebugDraw(canvas);
            }
        
            if (clipToPadding) {
                canvas.restoreToCount(clipSaveCount);
            }
        
            // mGroupFlags might have been updated by drawChild()
            flags = mGroupFlags;
        
            if ((flags & FLAG_INVALIDATE_REQUIRED) == FLAG_INVALIDATE_REQUIRED) {
                invalidate(true);
            }
        
            if ((flags & FLAG_ANIMATION_DONE) == 0 && (flags & FLAG_NOTIFY_ANIMATION_LISTENER) == 0 &&
                    mLayoutAnimationController.isDone() && !more) {
                // We want to erase the drawing cache and notify the listener after the
                // next frame is drawn because one extra invalidate() is caused by
                // drawChild() after the animation is over
                mGroupFlags |= FLAG_NOTIFY_ANIMATION_LISTENER;
                final Runnable end = new Runnable() {
                   @Override
                   public void run() {
                       notifyAnimationListener();
                   }
                };
                post(end);
            }
        }


      3. 遍历子view执行 drawChild(canvas, transientChild, drawingTime),drawChild里面执行了child.draw
    5. 画渐变的效果,并保存layrers
    6. 画scrollbars和foreground
private void performTraversals() { 3295 mLastPerformTraversalsSkipDrawReason = null; 3296 3297 // cache mView since it is used so much below... 3298 final View host = mView; 3299 if (DBG) { 3300 System.out.println("======================================"); 3301 System.out.println("performTraversals"); 3302 host.debug(); 3303 } 3304 3305 if (host == null || !mAdded) { 3306 mLastPerformTraversalsSkipDrawReason = host == null ? "no_host" : "not_added"; 3307 return; 3308 } 3309 3310 if (mNumPausedForSync > 0) { 3311 if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) { 3312 Trace.instant(Trace.TRACE_TAG_VIEW, 3313 TextUtils.formatSimple("performTraversals#mNumPausedForSync=%d", 3314 mNumPausedForSync)); 3315 } 3316 3317 Log.d(mTag, "Skipping traversal due to sync " + mNumPausedForSync); 3318 mLastPerformTraversalsSkipDrawReason = "paused_for_sync"; 3319 return; 3320 } 3321 3322 // #ifdef OPLUS_FEATURE_VIEW_DEBUG 3323 // Bard.Zhang@Android.UIFramework 2023-01-28 Add for : view debug 3324 mViewRootImplExt.markOnPerformTraversalsStart(host, mFirst); 3325 // #endif /* OPLUS_FEATURE_VIEW_DEBUG */ 3326 3327 mIsInTraversal = true; 3328 mWillDrawSoon = true; 3329 boolean cancelDraw = false; 3330 String cancelReason = null; 3331 boolean isSyncRequest = false; 3332 3333 boolean windowSizeMayChange = false; 3334 WindowManager.LayoutParams lp = mWindowAttributes; 3335 3336 int desiredWindowWidth; 3337 int desiredWindowHeight; 3338 3339 final int viewVisibility = getHostVisibility(); 3340 final boolean viewVisibilityChanged = !mFirst 3341 && (mViewVisibility != viewVisibility || mNewSurfaceNeeded 3342 // Also check for possible double visibility update, which will make current 3343 // viewVisibility value equal to mViewVisibility and we may miss it. 3344 || mAppVisibilityChanged); 3345 mAppVisibilityChanged = false; 3346 final boolean viewUserVisibilityChanged = !mFirst && 3347 ((mViewVisibility == View.VISIBLE) != (viewVisibility == View.VISIBLE)); 3348 final boolean shouldOptimizeMeasure = shouldOptimizeMeasure(lp); 3349 3350 WindowManager.LayoutParams params = null; 3351 CompatibilityInfo compatibilityInfo = 3352 mDisplay.getDisplayAdjustments().getCompatibilityInfo(); 3353 if (compatibilityInfo.supportsScreen() == mLastInCompatMode) { 3354 params = lp; 3355 mFullRedrawNeeded = true; 3356 mLayoutRequested = true; 3357 if (mLastInCompatMode) { 3358 params.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; 3359 mLastInCompatMode = false; 3360 } else { 3361 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; 3362 mLastInCompatMode = true; 3363 } 3364 } 3365 3366 Rect frame = mWinFrame; 3367 if (mFirst) { 3368 mFullRedrawNeeded = true; 3369 mLayoutRequested = true; 3370 3371 final Configuration config = getConfiguration(); 3372 if (shouldUseDisplaySize(lp)) { 3373 // NOTE -- system code, won't try to do compat mode. 3374 Point size = new Point(); 3375 mDisplay.getRealSize(size); 3376 desiredWindowWidth = size.x; 3377 desiredWindowHeight = size.y; 3378 } else if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT 3379 || lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) { 3380 // For wrap content, we have to remeasure later on anyways. Use size consistent with 3381 // below so we get best use of the measure cache. 3382 final Rect bounds = getWindowBoundsInsetSystemBars(); 3383 desiredWindowWidth = bounds.width(); 3384 desiredWindowHeight = bounds.height(); 3385 } else { 3386 // After addToDisplay, the frame contains the frameHint from window manager, which 3387 // for most windows is going to be the same size as the result of relayoutWindow. 3388 // Using this here allows us to avoid remeasuring after relayoutWindow 3389 desiredWindowWidth = frame.width(); 3390 desiredWindowHeight = frame.height(); 3391 } 3392 3393 // We used to use the following condition to choose 32 bits drawing caches: 3394 // PixelFormat.hasAlpha(lp.format) || lp.format == PixelFormat.RGBX_8888 3395 // However, windows are now always 32 bits by default, so choose 32 bits 3396 mAttachInfo.mUse32BitDrawingCache = true; 3397 mAttachInfo.mWindowVisibility = viewVisibility; 3398 mAttachInfo.mRecomputeGlobalAttributes = false; 3399 mLastConfigurationFromResources.setTo(config); 3400 mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility; 3401 // Set the layout direction if it has not been set before (inherit is the default) 3402 if (mViewLayoutDirectionInitial == View.LAYOUT_DIRECTION_INHERIT) { 3403 host.setLayoutDirection(config.getLayoutDirection()); 3404 } 3405 //#ifdef OPLUS_FEATURE_BRACKETMODE_2_0 3406 //wenguangyu@ANDROID.WMS, 2022/10/02, add for bracket mode 3407 mViewRootImplExt.attachToWindow(); 3408 //#endif /*OPLUS_FEATURE_BRACKETMODE_2_0*/ 3409 host.dispatchAttachedToWindow(mAttachInfo, 0); 3410 mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(true); 3411 dispatchApplyInsets(host); 3412 if (!mOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled()) { 3413 // For apps requesting legacy back behavior, we add a compat callback that 3414 // dispatches {@link KeyEvent#KEYCODE_BACK} to their root views. 3415 // This way from system point of view, these apps are providing custom 3416 // {@link OnBackInvokedCallback}s, and will not play system back animations 3417 // for them. 3418 registerCompatOnBackInvokedCallback(); 3419 } 3420 } else { 3421 desiredWindowWidth = frame.width(); 3422 desiredWindowHeight = frame.height(); 3423 if (desiredWindowWidth != mWidth || desiredWindowHeight != mHeight) { 3424 if (DEBUG_ORIENTATION) Log.v(mTag, "View " + host + " resized to: " + frame); 3425 mFullRedrawNeeded = true; 3426 mLayoutRequested = true; 3427 windowSizeMayChange = true; 3428 } 3429 } 3430 3431 if (viewVisibilityChanged) { 3432 mAttachInfo.mWindowVisibility = viewVisibility; 3433 host.dispatchWindowVisibilityChanged(viewVisibility); 3434 mAttachInfo.mTreeObserver.dispatchOnWindowVisibilityChange(viewVisibility); 3435 if (viewUserVisibilityChanged) { 3436 host.dispatchVisibilityAggregated(viewVisibility == View.VISIBLE); 3437 } 3438 if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) { 3439 endDragResizing(); 3440 destroyHardwareResources(); 3441 } 3442 } 3443 3444 // Non-visible windows can't hold accessibility focus. 3445 if (mAttachInfo.mWindowVisibility != View.VISIBLE) { 3446 host.clearAccessibilityFocus(); 3447 } 3448 3449 // Execute enqueued actions on every traversal in case a detached view enqueued an action 3450 getRunQueue().executeActions(mAttachInfo.mHandler); 3451 3452 if (mFirst) { 3453 // make sure touch mode code executes by setting cached value 3454 // to opposite of the added touch mode. 3455 mAttachInfo.mInTouchMode = !mAddedTouchMode; 3456 ensureTouchModeLocally(mAddedTouchMode); 3457 } 3458 3459 boolean layoutRequested = mLayoutRequested && (!mStopped || mReportNextDraw); 3460 if (layoutRequested) { 3461 if (!mFirst) { 3462 if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT 3463 || lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) { 3464 windowSizeMayChange = true; 3465 3466 if (shouldUseDisplaySize(lp)) { 3467 // NOTE -- system code, won't try to do compat mode. 3468 Point size = new Point(); 3469 mDisplay.getRealSize(size); 3470 desiredWindowWidth = size.x; 3471 desiredWindowHeight = size.y; 3472 } else { 3473 final Rect bounds = getWindowBoundsInsetSystemBars(); 3474 desiredWindowWidth = bounds.width(); 3475 desiredWindowHeight = bounds.height(); 3476 } 3477 } 3478 } 3479 3480 // Ask host how big it wants to be 3481 windowSizeMayChange |= measureHierarchy(host, lp, mView.getContext().getResources(), 3482 desiredWindowWidth, desiredWindowHeight, shouldOptimizeMeasure); 3483 } 3484 3485 if (collectViewAttributes()) { 3486 params = lp; 3487 } 3488 if (mAttachInfo.mForceReportNewAttributes) { 3489 mAttachInfo.mForceReportNewAttributes = false; 3490 params = lp; 3491 } 3492 3493 if (mFirst || mAttachInfo.mViewVisibilityChanged) { 3494 mAttachInfo.mViewVisibilityChanged = false; 3495 int resizeMode = mSoftInputMode & SOFT_INPUT_MASK_ADJUST; 3496 // If we are in auto resize mode, then we need to determine 3497 // what mode to use now. 3498 if (resizeMode == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED) { 3499 final int N = mAttachInfo.mScrollContainers.size(); 3500 for (int i=0; i<N; i++) { 3501 if (mAttachInfo.mScrollContainers.get(i).isShown()) { 3502 resizeMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; 3503 } 3504 } 3505 if (resizeMode == 0) { 3506 resizeMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN; 3507 } 3508 if ((lp.softInputMode & SOFT_INPUT_MASK_ADJUST) != resizeMode) { 3509 lp.softInputMode = (lp.softInputMode & ~SOFT_INPUT_MASK_ADJUST) | resizeMode; 3510 params = lp; 3511 } 3512 } 3513 } 3514 3515 if (mApplyInsetsRequested) { 3516 dispatchApplyInsets(host); 3517 if (mLayoutRequested) { 3518 // Short-circuit catching a new layout request here, so 3519 // we don't need to go through two layout passes when things 3520 // change due to fitting system windows, which can happen a lot. 3521 windowSizeMayChange |= measureHierarchy(host, lp, 3522 mView.getContext().getResources(), desiredWindowWidth, desiredWindowHeight, 3523 shouldOptimizeMeasure); 3524 } 3525 } 3526 3527 if (layoutRequested) { 3528 // Clear this now, so that if anything requests a layout in the 3529 // rest of this function we will catch it and re-run a full 3530 // layout pass. 3531 mLayoutRequested = false; 3532 } 3533 3534 boolean windowShouldResize = layoutRequested && windowSizeMayChange 3535 && ((mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight()) 3536 || (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT && 3537 frame.width() < desiredWindowWidth && frame.width() != mWidth) 3538 || (lp.height == ViewGroup.LayoutParams.WRAP_CONTENT && 3539 frame.height() < desiredWindowHeight && frame.height() != mHeight)); 3540 windowShouldResize |= mDragResizing && mPendingDragResizing; 3541 3542 // Determine whether to compute insets. 3543 // If there are no inset listeners remaining then we may still need to compute 3544 // insets in case the old insets were non-empty and must be reset. 3545 final boolean computesInternalInsets = 3546 mAttachInfo.mTreeObserver.hasComputeInternalInsetsListeners() 3547 || mAttachInfo.mHasNonEmptyGivenInternalInsets; 3548 3549 boolean insetsPending = false; 3550 int relayoutResult = 0; 3551 boolean updatedConfiguration = false; 3552 3553 final int surfaceGenerationId = mSurface.getGenerationId(); 3554 3555 final boolean isViewVisible = viewVisibility == View.VISIBLE; 3556 boolean surfaceSizeChanged = false; 3557 boolean surfaceCreated = false; 3558 boolean surfaceDestroyed = false; 3559 // True if surface generation id changes or relayout result is RELAYOUT_RES_SURFACE_CHANGED. 3560 boolean surfaceReplaced = false; 3561 3562 final boolean windowAttributesChanged = mWindowAttributesChanged; 3563 if (windowAttributesChanged) { 3564 mWindowAttributesChanged = false; 3565 params = lp; 3566 } 3567 3568 if (params != null) { 3569 if ((host.mPrivateFlags & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0 3570 && !PixelFormat.formatHasAlpha(params.format)) { 3571 params.format = PixelFormat.TRANSLUCENT; 3572 } 3573 adjustLayoutParamsForCompatibility(params); 3574 controlInsetsForCompatibility(params); 3575 if (mDispatchedSystemBarAppearance != params.insetsFlags.appearance) { 3576 mDispatchedSystemBarAppearance = params.insetsFlags.appearance; 3577 mView.onSystemBarAppearanceChanged(mDispatchedSystemBarAppearance); 3578 } 3579 } 3580 3581 if (mFirst || windowShouldResize || viewVisibilityChanged || params != null 3582 || mForceNextWindowRelayout) { 3583 if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) { 3584 Trace.traceBegin(Trace.TRACE_TAG_VIEW, 3585 TextUtils.formatSimple("relayoutWindow#" 3586 + "first=%b/resize=%b/vis=%b/params=%b/force=%b", 3587 mFirst, windowShouldResize, viewVisibilityChanged, params != null, 3588 mForceNextWindowRelayout)); 3589 } 3590 3591 mForceNextWindowRelayout = false; 3592 3593 // If this window is giving internal insets to the window manager, then we want to first 3594 // make the provided insets unchanged during layout. This avoids it briefly causing 3595 // other windows to resize/move based on the raw frame of the window, waiting until we 3596 // can finish laying out this window and get back to the window manager with the 3597 // ultimately computed insets. 3598 insetsPending = computesInternalInsets; 3599 3600 if (mSurfaceHolder != null) { 3601 mSurfaceHolder.mSurfaceLock.lock(); 3602 mDrawingAllowed = true; 3603 } 3604 3605 boolean hwInitialized = false; 3606 boolean dispatchApplyInsets = false; 3607 boolean hadSurface = mSurface.isValid(); 3608 3609 try { 3610 if (DEBUG_LAYOUT) { 3611 Log.i(mTag, "host=w:" + host.getMeasuredWidth() + ", h:" + 3612 host.getMeasuredHeight() + ", params=" + params); 3613 } 3614 3615 if (mFirst || viewVisibilityChanged) { 3616 mViewFrameInfo.flags |= FrameInfo.FLAG_WINDOW_VISIBILITY_CHANGED; 3617 } 3618 //#ifdef OPLUS_FEATURE_JANK_TRACKER 3619 //wangwei11@oppo.com, 2021/11/28, Add for janktracker 3620 mChoreographer.mChoreographerExt.markRelayout(); 3621 //#endif /*OPLUS_FEATURE_JANK_TRACKER*/ 3622 relayoutResult = relayoutWindow(params, viewVisibility, insetsPending); 3623 cancelDraw = (relayoutResult & RELAYOUT_RES_CANCEL_AND_REDRAW) 3624 == RELAYOUT_RES_CANCEL_AND_REDRAW; 3625 cancelReason = "relayout"; 3626 final boolean dragResizing = mPendingDragResizing; 3627 if (mSyncSeqId > mLastSyncSeqId) { 3628 mLastSyncSeqId = mSyncSeqId; 3629 if (DEBUG_BLAST) { 3630 Log.d(mTag, "Relayout called with blastSync"); 3631 } 3632 reportNextDraw("relayout"); 3633 mSyncBuffer = true; 3634 isSyncRequest = true; 3635 if (!cancelDraw) { 3636 mDrewOnceForSync = false; 3637 } 3638 } 3639 3640 final boolean surfaceControlChanged = 3641 (relayoutResult & RELAYOUT_RES_SURFACE_CHANGED) 3642 == RELAYOUT_RES_SURFACE_CHANGED; 3643 3644 if (mSurfaceControl.isValid()) { 3645 updateOpacity(mWindowAttributes, dragResizing, 3646 surfaceControlChanged /*forceUpdate */); 3647 // No need to updateDisplayDecoration if it's a new SurfaceControl and 3648 // mDisplayDecorationCached is false, since that's the default for a new 3649 // SurfaceControl. 3650 if (surfaceControlChanged && mDisplayDecorationCached) { 3651 updateDisplayDecoration(); 3652 } 3653 if (surfaceControlChanged 3654 && mWindowAttributes.type 3655 == WindowManager.LayoutParams.TYPE_STATUS_BAR) { 3656 mTransaction.setDefaultFrameRateCompatibility(mSurfaceControl, 3657 Surface.FRAME_RATE_COMPATIBILITY_NO_VOTE).apply(); 3658 } 3659 } 3660 3661 if (DEBUG_LAYOUT) Log.v(mTag, "relayout: frame=" + frame.toShortString() 3662 + " surface=" + mSurface); 3663 3664 // If the pending {@link MergedConfiguration} handed back from 3665 // {@link #relayoutWindow} does not match the one last reported, 3666 // WindowManagerService has reported back a frame from a configuration not yet 3667 // handled by the client. In this case, we need to accept the configuration so we 3668 // do not lay out and draw with the wrong configuration. 3669 if (mRelayoutRequested 3670 && !mPendingMergedConfiguration.equals(mLastReportedMergedConfiguration)) { 3671 if (DEBUG_CONFIGURATION) Log.v(mTag, "Visible with new config: " 3672 + mPendingMergedConfiguration.getMergedConfiguration()); 3673 performConfigurationChange(new MergedConfiguration(mPendingMergedConfiguration), 3674 !mFirst, INVALID_DISPLAY /* same display */); 3675 updatedConfiguration = true; 3676 } 3677 final boolean updateSurfaceNeeded = mUpdateSurfaceNeeded; 3678 mUpdateSurfaceNeeded = false; 3679 3680 surfaceSizeChanged = false; 3681 if (!mLastSurfaceSize.equals(mSurfaceSize)) { 3682 surfaceSizeChanged = true; 3683 mLastSurfaceSize.set(mSurfaceSize.x, mSurfaceSize.y); 3684 } 3685 final boolean alwaysConsumeSystemBarsChanged = 3686 mPendingAlwaysConsumeSystemBars != mAttachInfo.mAlwaysConsumeSystemBars; 3687 updateColorModeIfNeeded(lp.getColorMode()); 3688 surfaceCreated = !hadSurface && mSurface.isValid(); 3689 surfaceDestroyed = hadSurface && !mSurface.isValid(); 3690 3691 // When using Blast, the surface generation id may not change when there's a new 3692 // SurfaceControl. In that case, we also check relayout flag 3693 // RELAYOUT_RES_SURFACE_CHANGED since it should indicate that WMS created a new 3694 // SurfaceControl. 3695 surfaceReplaced = (surfaceGenerationId != mSurface.getGenerationId() 3696 || surfaceControlChanged) && mSurface.isValid(); 3697 if (surfaceReplaced) { 3698 mSurfaceSequenceId++; 3699 } 3700 if (alwaysConsumeSystemBarsChanged) { 3701 mAttachInfo.mAlwaysConsumeSystemBars = mPendingAlwaysConsumeSystemBars; 3702 dispatchApplyInsets = true; 3703 } 3704 if (updateCaptionInsets()) { 3705 dispatchApplyInsets = true; 3706 } 3707 if (dispatchApplyInsets || mLastSystemUiVisibility != 3708 mAttachInfo.mSystemUiVisibility || mApplyInsetsRequested) { 3709 mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility; 3710 dispatchApplyInsets(host); 3711 // We applied insets so force contentInsetsChanged to ensure the 3712 // hierarchy is measured below. 3713 dispatchApplyInsets = true; 3714 } 3715 3716 if (surfaceCreated) { 3717 // If we are creating a new surface, then we need to 3718 // completely redraw it. 3719 mFullRedrawNeeded = true; 3720 mPreviousTransparentRegion.setEmpty(); 3721 3722 // Only initialize up-front if transparent regions are not 3723 // requested, otherwise defer to see if the entire window 3724 // will be transparent 3725 if (mAttachInfo.mThreadedRenderer != null) { 3726 try { 3727 hwInitialized = mAttachInfo.mThreadedRenderer.initialize(mSurface); 3728 // #ifdef OPLUS_EXTENSION_HOOK 3729 // yanliang@Android.Performance 2023-02-13 Add for Optimize sliding effect 3730 mViewRootImplExt.setPendingBufferCountSetting(true); 3731 // #endif /*OPLUS_EXTENSION_HOOK*/ 3732 if (hwInitialized && (host.mPrivateFlags 3733 //#ifndef OPLUS_BUG_STABILITY 3734 //Weitao.Chen@ANDROID.STABILITY.2742412, 2020/01/02, Add for null pointer exp 3735 //& View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0) { 3736 //#else 3737 & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0 && mAttachInfo.mThreadedRenderer != null) { 3738 //#endif /*OPLUS_BUG_STABILITY*/ 3739 // Don't pre-allocate if transparent regions 3740 // are requested as they may not be needed 3741 mAttachInfo.mThreadedRenderer.allocateBuffers(); 3742 } 3743 } catch (OutOfResourcesException e) { 3744 handleOutOfResourcesException(e); 3745 mLastPerformTraversalsSkipDrawReason = "oom_initialize_renderer"; 3746 return; 3747 } 3748 } 3749 } else if (surfaceDestroyed) { 3750 // If the surface has been removed, then reset the scroll 3751 // positions. 3752 if (mLastScrolledFocus != null) { 3753 mLastScrolledFocus.clear(); 3754 } 3755 mScrollY = mCurScrollY = 0; 3756 if (mView instanceof RootViewSurfaceTaker) { 3757 ((RootViewSurfaceTaker) mView).onRootViewScrollYChanged(mCurScrollY); 3758 } 3759 if (mScroller != null) { 3760 mScroller.abortAnimation(); 3761 } 3762 // Our surface is gone 3763 if (isHardwareEnabled()) { 3764 mAttachInfo.mThreadedRenderer.destroy(); 3765 } 3766 } else if ((surfaceReplaced || surfaceSizeChanged || updateSurfaceNeeded) 3767 && mSurfaceHolder == null 3768 && mAttachInfo.mThreadedRenderer != null 3769 && mSurface.isValid()) { 3770 mFullRedrawNeeded = true; 3771 try { 3772 // Need to do updateSurface (which leads to CanvasContext::setSurface and 3773 // re-create the EGLSurface) if either the Surface changed (as indicated by 3774 // generation id), or WindowManager changed the surface size. The latter is 3775 // because on some chips, changing the consumer side's BufferQueue size may 3776 // not take effect immediately unless we create a new EGLSurface. 3777 // Note that frame size change doesn't always imply surface size change (eg. 3778 // drag resizing uses fullscreen surface), need to check surfaceSizeChanged 3779 // flag from WindowManager. 3780 mAttachInfo.mThreadedRenderer.updateSurface(mSurface); 3781 } catch (OutOfResourcesException e) { 3782 handleOutOfResourcesException(e); 3783 mLastPerformTraversalsSkipDrawReason = "oom_update_surface"; 3784 return; 3785 } 3786 } 3787 3788 if (mDragResizing != dragResizing) { 3789 if (dragResizing) { 3790 final boolean backdropSizeMatchesFrame = 3791 mWinFrame.width() == mPendingBackDropFrame.width() 3792 && mWinFrame.height() == mPendingBackDropFrame.height(); 3793 // TODO: Need cutout? 3794 startDragResizing(mPendingBackDropFrame, !backdropSizeMatchesFrame, 3795 mAttachInfo.mContentInsets, mAttachInfo.mStableInsets); 3796 } else { 3797 // We shouldn't come here, but if we come we should end the resize. 3798 endDragResizing(); 3799 } 3800 } 3801 if (!mUseMTRenderer) { 3802 if (dragResizing) { 3803 mCanvasOffsetX = mWinFrame.left; 3804 mCanvasOffsetY = mWinFrame.top; 3805 } else { 3806 mCanvasOffsetX = mCanvasOffsetY = 0; 3807 } 3808 } 3809 } catch (RemoteException e) { 3810 } finally { 3811 if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) { 3812 Trace.traceEnd(Trace.TRACE_TAG_VIEW); 3813 } 3814 } 3815 3816 if (DEBUG_ORIENTATION) Log.v( 3817 TAG, "Relayout returned: frame=" + frame + ", surface=" + mSurface); 3818 3819 mAttachInfo.mWindowLeft = frame.left; 3820 mAttachInfo.mWindowTop = frame.top; 3821 3822 // !!FIXME!! This next section handles the case where we did not get the 3823 // window size we asked for. We should avoid this by getting a maximum size from 3824 // the window session beforehand. 3825 if (mWidth != frame.width() || mHeight != frame.height()) { 3826 mWidth = frame.width(); 3827 mHeight = frame.height(); 3828 } 3829 3830 if (mSurfaceHolder != null) { 3831 // The app owns the surface; tell it about what is going on. 3832 if (mSurface.isValid()) { 3833 // XXX .copyFrom() doesn't work! 3834 //mSurfaceHolder.mSurface.copyFrom(mSurface); 3835 mSurfaceHolder.mSurface = mSurface; 3836 } 3837 mSurfaceHolder.setSurfaceFrameSize(mWidth, mHeight); 3838 mSurfaceHolder.mSurfaceLock.unlock(); 3839 if (surfaceCreated) { 3840 mSurfaceHolder.ungetCallbacks(); 3841 3842 mIsCreating = true; 3843 SurfaceHolder.Callback[] callbacks = mSurfaceHolder.getCallbacks(); 3844 if (callbacks != null) { 3845 for (SurfaceHolder.Callback c : callbacks) { 3846 c.surfaceCreated(mSurfaceHolder); 3847 } 3848 } 3849 } 3850 3851 if ((surfaceCreated || surfaceReplaced || surfaceSizeChanged 3852 || windowAttributesChanged) && mSurface.isValid()) { 3853 SurfaceHolder.Callback[] callbacks = mSurfaceHolder.getCallbacks(); 3854 if (callbacks != null) { 3855 for (SurfaceHolder.Callback c : callbacks) { 3856 c.surfaceChanged(mSurfaceHolder, lp.format, 3857 mWidth, mHeight); 3858 } 3859 } 3860 mIsCreating = false; 3861 } 3862 3863 if (surfaceDestroyed) { 3864 notifyHolderSurfaceDestroyed(); 3865 mSurfaceHolder.mSurfaceLock.lock(); 3866 try { 3867 mSurfaceHolder.mSurface = new Surface(); 3868 } finally { 3869 mSurfaceHolder.mSurfaceLock.unlock(); 3870 } 3871 } 3872 } 3873 3874 final ThreadedRenderer threadedRenderer = mAttachInfo.mThreadedRenderer; 3875 if (threadedRenderer != null && threadedRenderer.isEnabled()) { 3876 if (hwInitialized 3877 || mWidth != threadedRenderer.getWidth() 3878 || mHeight != threadedRenderer.getHeight() 3879 || mNeedsRendererSetup) { 3880 threadedRenderer.setup(mWidth, mHeight, mAttachInfo, 3881 mWindowAttributes.surfaceInsets); 3882 mNeedsRendererSetup = false; 3883 } 3884 } 3885 3886 // TODO: In the CL "ViewRootImpl: Fix issue with early draw report in 3887 // seamless rotation". We moved processing of RELAYOUT_RES_BLAST_SYNC 3888 // earlier in the function, potentially triggering a call to 3889 // reportNextDraw(). That same CL changed this and the next reference 3890 // to wasReportNextDraw, such that this logic would remain undisturbed 3891 // (it continues to operate as if the code was never moved). This was 3892 // done to achieve a more hermetic fix for S, but it's entirely 3893 // possible that checking the most recent value is actually more 3894 // correct here. 3895 if (!mStopped || mReportNextDraw) { 3896 if (mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight() 3897 || dispatchApplyInsets || updatedConfiguration) { 3898 int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width, 3899 lp.privateFlags); 3900 int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height, 3901 lp.privateFlags); 3902 3903 if (DEBUG_LAYOUT) Log.v(mTag, "Ooops, something changed! mWidth=" 3904 + mWidth + " measuredWidth=" + host.getMeasuredWidth() 3905 + " mHeight=" + mHeight 3906 + " measuredHeight=" + host.getMeasuredHeight() 3907 + " dispatchApplyInsets=" + dispatchApplyInsets); 3908 3909 // #ifdef OPLUS_FEATURE_VIEW_DEBUG 3910 // Bard.Zhang@Android.UIFramework 2023-01-19 Add for : view debug 3911 String measureReason = "Measure reason mFirst " + mFirst 3912 + " windowShouldResize " + windowShouldResize 3913 + " viewVisibilityChanged " + viewVisibilityChanged 3914 + " params != null " + (params != null) 3915 + " mForceNextWindowRelayout " + mForceNextWindowRelayout 3916 + " mStopped " + mStopped + " mReportNextDraw " + mReportNextDraw 3917 + " mWidth " + mWidth + " host.getMeasuredWidth " + host.getMeasuredWidth() 3918 + " mHeight " + mHeight + " host.getMeasuredHeight " + host.getMeasuredHeight() 3919 + " dispatchApplyInsets " + dispatchApplyInsets 3920 + " updateConfiguration " + updatedConfiguration; 3921 mViewRootImplExt.markPerformMeasureReason(measureReason); 3922 // #endif /* OPLUS_FEATURE_VIEW_DEBUG */ 3923 // #ifdef OPLUS_BUG_COMPATIBILITY 3924 //Qian.Jiang@Android.Wms, 2023/05/19: fix bug-5573936 3925 int heightMesure = MeasureSpec.getSize(childHeightMeasureSpec); 3926 int widthMesure = MeasureSpec.getSize(childWidthMeasureSpec); 3927 if (PANIC_DEBUG && (heightMesure > LIMIT || widthMesure > LIMIT)) { 3928 Log.d(mTag, "performMeasure heightMesure = " + heightMesure + ",widthMesure = " + widthMesure); 3929 } 3930 //#endif /* OPLUS_BUG_COMPATIBILITY */ 3931 // Ask host how big it wants to be 3932 performMeasure(childWidthMeasureSpec, childHeightMeasureSpec); 3933 3934 // Implementation of weights from WindowManager.LayoutParams 3935 // We just grow the dimensions as needed and re-measure if 3936 // needs be 3937 int width = host.getMeasuredWidth(); 3938 int height = host.getMeasuredHeight(); 3939 boolean measureAgain = false; 3940 3941 if (lp.horizontalWeight > 0.0f) { 3942 width += (int) ((mWidth - width) * lp.horizontalWeight); 3943 childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width, 3944 MeasureSpec.EXACTLY); 3945 measureAgain = true; 3946 } 3947 if (lp.verticalWeight > 0.0f) { 3948 height += (int) ((mHeight - height) * lp.verticalWeight); 3949 childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, 3950 MeasureSpec.EXACTLY); 3951 measureAgain = true; 3952 } 3953 3954 if (measureAgain) { 3955 if (DEBUG_LAYOUT) Log.v(mTag, 3956 "And hey let's measure once more: width=" + width 3957 + " height=" + height); 3958 3959 // #ifdef OPLUS_FEATURE_VIEW_DEBUG 3960 // Bard.Zhang@Android.UIFramework 2023-01-19 Add for : view debug 3961 mMeasureReason = "3"; 3962 String measureAgainReason = "Measure again lp.horizontalWeight " + lp.horizontalWeight 3963 + " lp.verticalWeight " + lp.verticalWeight; 3964 mViewRootImplExt.markPerformMeasureReason(measureAgainReason); 3965 // #endif /* OPLUS_FEATURE_VIEW_DEBUG */ 3966 3967 // #ifdef OPLUS_BUG_COMPATIBILITY 3968 //Qian.Jiang@Android.Wms, 2023/05/19: fix bug-5573936 3969 int heightAgain = MeasureSpec.getSize(childHeightMeasureSpec); 3970 int widthAgain = MeasureSpec.getSize(childWidthMeasureSpec); 3971 if (PANIC_DEBUG && (heightAgain > LIMIT || widthAgain > LIMIT)) { 3972 Log.d(mTag, "measureAgain performMeasure heightAgain = " + heightAgain + ",widthAgain = " + widthAgain); 3973 } 3974 //#endif /* OPLUS_BUG_COMPATIBILITY */ 3975 performMeasure(childWidthMeasureSpec, childHeightMeasureSpec); 3976 } 3977 3978 layoutRequested = true; 3979 } 3980 } 3981 } else { 3982 // Not the first pass and no window/insets/visibility change but the window 3983 // may have moved and we need check that and if so to update the left and right 3984 // in the attach info. We translate only the window frame since on window move 3985 // the window manager tells us only for the new frame but the insets are the 3986 // same and we do not want to translate them more than once. 3987 maybeHandleWindowMove(frame); 3988 } 3989 3990 if (mViewMeasureDeferred) { 3991 // It's time to measure the views since we are going to layout them. 3992 performMeasure( 3993 MeasureSpec.makeMeasureSpec(frame.width(), MeasureSpec.EXACTLY), 3994 MeasureSpec.makeMeasureSpec(frame.height(), MeasureSpec.EXACTLY)); 3995 } 3996 3997 if (!mRelayoutRequested && mCheckIfCanDraw) { 3998 // We had a sync previously, but we didn't call IWindowSession#relayout in this 3999 // traversal. So we don't know if the sync is complete that we can continue to draw. 4000 // Here invokes cancelDraw to obtain the information. 4001 try { 4002 cancelDraw = mWindowSession.cancelDraw(mWindow); 4003 cancelReason = "wm_sync"; 4004 Log.d(mTag, "cancelDraw returned " + cancelDraw); 4005 } catch (RemoteException e) { 4006 } 4007 } 4008 4009 if (surfaceSizeChanged || surfaceReplaced || surfaceCreated || 4010 windowAttributesChanged || mChildBoundingInsetsChanged) { 4011 // If the surface has been replaced, there's a chance the bounds layer is not parented 4012 // to the new layer. When updating bounds layer, also reparent to the main VRI 4013 // SurfaceControl to ensure it's correctly placed in the hierarchy. 4014 // 4015 // This needs to be done on the client side since WMS won't reparent the children to the 4016 // new surface if it thinks the app is closing. WMS gets the signal that the app is 4017 // stopping, but on the client side it doesn't get stopped since it's restarted quick 4018 // enough. WMS doesn't want to keep around old children since they will leak when the 4019 // client creates new children. 4020 prepareSurfaces(); 4021 mChildBoundingInsetsChanged = false; 4022 } 4023 4024 final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw); 4025 boolean triggerGlobalLayoutListener = didLayout 4026 || mAttachInfo.mRecomputeGlobalAttributes; 4027 if (didLayout) { 4028 //#ifdef OPLUS_EXTENSION_HOOK 4029 //Jie.Zhang@ANDROID.PERFORMANCE, 2021/12/14, Add for quality information update 4030 final long startTime = SystemClock.uptimeMillis(); 4031 performLayout(lp, mWidth, mHeight); 4032 ExtLoader.type(IOplusJankMonitorExt.class).create().setLaunchStageTime(ActivityThread.currentProcessName(), "performLayout", startTime); 4033 //#endif /* OPLUS_EXTENSION_HOOK */ 4034 // #ifdef OPLUS_EXTENSION_HOOK 4035 // Guofu.Yang@ANDROID.WMS, 2018/02/23, [OSP-1634] add for Screen mode. 4036 mViewRootImplExt.setRefreshRateIfNeed((mView instanceof ViewGroup), mContext, 4037 mView, mWindow); 4038 // #endif /* OPLUS_EXTENSION_HOOK */ 4039 4040 // By this point all views have been sized and positioned 4041 // We can compute the transparent area 4042 4043 if ((host.mPrivateFlags & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) { 4044 // start out transparent 4045 // TODO: AVOID THAT CALL BY CACHING THE RESULT? 4046 host.getLocationInWindow(mTmpLocation); 4047 mTransparentRegion.set(mTmpLocation[0], mTmpLocation[1], 4048 mTmpLocation[0] + host.mRight - host.mLeft, 4049 mTmpLocation[1] + host.mBottom - host.mTop); 4050 4051 host.gatherTransparentRegion(mTransparentRegion); 4052 if (mTranslator != null) { 4053 mTranslator.translateRegionInWindowToScreen(mTransparentRegion); 4054 } 4055 4056 if (!mTransparentRegion.equals(mPreviousTransparentRegion)) { 4057 mPreviousTransparentRegion.set(mTransparentRegion); 4058 mFullRedrawNeeded = true; 4059 // TODO: Ideally we would do this in prepareSurfaces, 4060 // but prepareSurfaces is currently working under 4061 // the assumption that we paused the render thread 4062 // via the WM relayout code path. We probably eventually 4063 // want to synchronize transparent region hint changes 4064 // with draws. 4065 SurfaceControl sc = getSurfaceControl(); 4066 if (sc.isValid()) { 4067 mTransaction.setTransparentRegionHint(sc, mTransparentRegion).apply(); 4068 } 4069 } 4070 } 4071 4072 if (DBG) { 4073 System.out.println("======================================"); 4074 System.out.println("performTraversals -- after setFrame"); 4075 host.debug(); 4076 } 4077 } 4078 4079 boolean didUseTransaction = false; 4080 // These callbacks will trigger SurfaceView SurfaceHolder.Callbacks and must be invoked 4081 // after the measure pass. If its invoked before the measure pass and the app modifies 4082 // the view hierarchy in the callbacks, we could leave the views in a broken state. 4083 if (surfaceCreated) { 4084 notifySurfaceCreated(mTransaction); 4085 didUseTransaction = true; 4086 } else if (surfaceReplaced) { 4087 notifySurfaceReplaced(mTransaction); 4088 didUseTransaction = true; 4089 } else if (surfaceDestroyed) { 4090 notifySurfaceDestroyed(); 4091 } 4092 4093 if (didUseTransaction) { 4094 applyTransactionOnDraw(mTransaction); 4095 } 4096 4097 if (triggerGlobalLayoutListener) { 4098 mAttachInfo.mRecomputeGlobalAttributes = false; 4099 mAttachInfo.mTreeObserver.dispatchOnGlobalLayout(); 4100 } 4101 4102 Rect contentInsets = null; 4103 Rect visibleInsets = null; 4104 Region touchableRegion = null; 4105 int touchableInsetMode = TOUCHABLE_INSETS_REGION; 4106 boolean computedInternalInsets = false; 4107 if (computesInternalInsets) { 4108 final ViewTreeObserver.InternalInsetsInfo insets = mAttachInfo.mGivenInternalInsets; 4109 4110 // Clear the original insets. 4111 insets.reset(); 4112 4113 // Compute new insets in place. 4114 mAttachInfo.mTreeObserver.dispatchOnComputeInternalInsets(insets); 4115 mAttachInfo.mHasNonEmptyGivenInternalInsets = !insets.isEmpty(); 4116 4117 // Tell the window manager. 4118 if (insetsPending || !mLastGivenInsets.equals(insets)) { 4119 mLastGivenInsets.set(insets); 4120 4121 // Translate insets to screen coordinates if needed. 4122 if (mTranslator != null) { 4123 contentInsets = mTranslator.getTranslatedContentInsets(insets.contentInsets); 4124 visibleInsets = mTranslator.getTranslatedVisibleInsets(insets.visibleInsets); 4125 touchableRegion = mTranslator.getTranslatedTouchableArea(insets.touchableRegion); 4126 } else { 4127 contentInsets = insets.contentInsets; 4128 visibleInsets = insets.visibleInsets; 4129 touchableRegion = insets.touchableRegion; 4130 } 4131 computedInternalInsets = true; 4132 } 4133 touchableInsetMode = insets.mTouchableInsets; 4134 } 4135 boolean needsSetInsets = computedInternalInsets; 4136 needsSetInsets |= !Objects.equals(mPreviousTouchableRegion, mTouchableRegion) && 4137 (mTouchableRegion != null); 4138 if (needsSetInsets) { 4139 if (mTouchableRegion != null) { 4140 if (mPreviousTouchableRegion == null) { 4141 mPreviousTouchableRegion = new Region(); 4142 } 4143 mPreviousTouchableRegion.set(mTouchableRegion); 4144 if (touchableInsetMode != TOUCHABLE_INSETS_REGION) { 4145 Log.e(mTag, "Setting touchableInsetMode to non TOUCHABLE_INSETS_REGION" + 4146 " from OnComputeInternalInsets, while also using setTouchableRegion" + 4147 " causes setTouchableRegion to be ignored"); 4148 } 4149 } else { 4150 mPreviousTouchableRegion = null; 4151 } 4152 if (contentInsets == null) contentInsets = new Rect(0,0,0,0); 4153 if (visibleInsets == null) visibleInsets = new Rect(0,0,0,0); 4154 if (touchableRegion == null) { 4155 touchableRegion = mTouchableRegion; 4156 } else if (touchableRegion != null && mTouchableRegion != null) { 4157 touchableRegion.op(touchableRegion, mTouchableRegion, Region.Op.UNION); 4158 } 4159 try { 4160 mWindowSession.setInsets(mWindow, touchableInsetMode, 4161 contentInsets, visibleInsets, touchableRegion); 4162 } catch (RemoteException e) { 4163 throw e.rethrowFromSystemServer(); 4164 } 4165 } else if (mTouchableRegion == null && mPreviousTouchableRegion != null) { 4166 mPreviousTouchableRegion = null; 4167 try { 4168 mWindowSession.clearTouchableRegion(mWindow); 4169 } catch (RemoteException e) { 4170 throw e.rethrowFromSystemServer(); 4171 } 4172 } 4173 4174 if (mFirst) { 4175 if (sAlwaysAssignFocus || !isInTouchMode()) { 4176 // handle first focus request 4177 if (DEBUG_INPUT_RESIZE) { 4178 Log.v(mTag, "First: mView.hasFocus()=" + mView.hasFocus()); 4179 } 4180 if (mView != null) { 4181 if (!mView.hasFocus()) { 4182 mView.restoreDefaultFocus(); 4183 if (DEBUG_INPUT_RESIZE) { 4184 Log.v(mTag, "First: requested focused view=" + mView.findFocus()); 4185 } 4186 } else { 4187 if (DEBUG_INPUT_RESIZE) { 4188 Log.v(mTag, "First: existing focused view=" + mView.findFocus()); 4189 } 4190 } 4191 } 4192 } else { 4193 // Some views (like ScrollView) won't hand focus to descendants that aren't within 4194 // their viewport. Before layout, there's a good change these views are size 0 4195 // which means no children can get focus. After layout, this view now has size, but 4196 // is not guaranteed to hand-off focus to a focusable child (specifically, the edge- 4197 // case where the child has a size prior to layout and thus won't trigger 4198 // focusableViewAvailable). 4199 View focused = mView.findFocus(); 4200 if (focused instanceof ViewGroup 4201 && ((ViewGroup) focused).getDescendantFocusability() 4202 == ViewGroup.FOCUS_AFTER_DESCENDANTS) { 4203 focused.restoreDefaultFocus(); 4204 } 4205 } 4206 //#ifdef OPLUS_EXTENSION_HOOK 4207 //Honzhu@ANDROID.VIEW, 2020/07/20, add for Optimize app startup speed 4208 mViewRootImplExt.checkIsFragmentAnimUI(); 4209 //#endif /* OPLUS_EXTENSION_HOOK */ 4210 } 4211 4212 final boolean changedVisibility = (viewVisibilityChanged || mFirst) && isViewVisible; 4213 if (changedVisibility) { 4214 maybeFireAccessibilityWindowStateChangedEvent(); 4215 } 4216 4217 mFirst = false; 4218 mWillDrawSoon = false; 4219 mNewSurfaceNeeded = false; 4220 mViewVisibility = viewVisibility; 4221 4222 final boolean hasWindowFocus = mAttachInfo.mHasWindowFocus && isViewVisible; 4223 mImeFocusController.onTraversal(hasWindowFocus, mWindowAttributes); 4224 4225 if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { 4226 reportNextDraw("first_relayout"); 4227 } 4228 4229 mCheckIfCanDraw = isSyncRequest || cancelDraw; 4230 4231 boolean cancelDueToPreDrawListener = mAttachInfo.mTreeObserver.dispatchOnPreDraw(); 4232 boolean cancelAndRedraw = cancelDueToPreDrawListener 4233 || (cancelDraw && mDrewOnceForSync); 4234 //#ifdef OPLUS_EXTENSION_HOOK 4235 //Guofu.Yang@@ANDROID.WMS 2023/03/14,Add for fixed bug 5268134,5132324 4236 cancelAndRedraw = mViewRootImplExt.cancelAndRedraw(mTag,cancelAndRedraw,isViewVisible,mSyncBuffer); 4237 //#endif // OPLUS_EXTENSION_HOOK 4238 4239 if (!cancelAndRedraw) { 4240 // A sync was already requested before the WMS requested sync. This means we need to 4241 // sync the buffer, regardless if WMS wants to sync the buffer. 4242 if (mActiveSurfaceSyncGroup != null) { 4243 mSyncBuffer = true; 4244 } 4245 4246 createSyncIfNeeded(); 4247 notifyDrawStarted(isInWMSRequestedSync()); 4248 mDrewOnceForSync = true; 4249 4250 // If the active SSG is also requesting to sync a buffer, the following needs to happen 4251 // 1. Ensure we keep track of the number of active syncs to know when to disable RT 4252 // RT animations that conflict with syncing a buffer. 4253 // 2. Add a safeguard SSG to prevent multiple SSG that sync buffers from being submitted 4254 // out of order. 4255 if (mActiveSurfaceSyncGroup != null && mSyncBuffer) { 4256 updateSyncInProgressCount(mActiveSurfaceSyncGroup); 4257 safeguardOverlappingSyncs(mActiveSurfaceSyncGroup); 4258 } 4259 } 4260 // #ifdef OPLUS_FEATURE_EXTENSION_HOOKS 4261 // Bard.Zhang@Android.UIFramework 2023-10-30 Add for : debug 6429918 4262 else { 4263 Log.w(TAG, "cancelAndRedraw cancelDueToPreDrawListener " + cancelDueToPreDrawListener 4264 + " cancelDraw " + cancelDraw 4265 + " mDrewOnceForSync " + mDrewOnceForSync 4266 + " isSyncRequest " + isSyncRequest); 4267 } 4268 // #endif /* OPLUS_FEATURE_EXTENSION_HOOKS */ 4269 4270 if (!isViewVisible) { 4271 mLastPerformTraversalsSkipDrawReason = "view_not_visible"; 4272 if (mPendingTransitions != null && mPendingTransitions.size() > 0) { 4273 for (int i = 0; i < mPendingTransitions.size(); ++i) { 4274 mPendingTransitions.get(i).endChangingAnimations(); 4275 } 4276 mPendingTransitions.clear(); 4277 } 4278 4279 if (mActiveSurfaceSyncGroup != null) { 4280 mActiveSurfaceSyncGroup.markSyncReady(); 4281 } 4282 } else if (cancelAndRedraw) { 4283 mLastPerformTraversalsSkipDrawReason = cancelDueToPreDrawListener 4284 ? "predraw_" + mAttachInfo.mTreeObserver.getLastDispatchOnPreDrawCanceledReason() 4285 : "cancel_" + cancelReason; 4286 // Try again 4287 scheduleTraversals(); 4288 } else { 4289 if (mPendingTransitions != null && mPendingTransitions.size() > 0) { 4290 for (int i = 0; i < mPendingTransitions.size(); ++i) { 4291 mPendingTransitions.get(i).startChangingAnimations(); 4292 } 4293 mPendingTransitions.clear(); 4294 } 4295 if (!performDraw(mActiveSurfaceSyncGroup) && mActiveSurfaceSyncGroup != null) { 4296 mActiveSurfaceSyncGroup.markSyncReady(); 4297 } 4298 } 4299 4300 if (mAttachInfo.mContentCaptureEvents != null) { 4301 notifyContentCaptureEvents(); 4302 } 4303 mIsInTraversal = false; 4304 mRelayoutRequested = false; 4305 4306 if (!cancelAndRedraw) { 4307 mReportNextDraw = false; 4308 mLastReportNextDrawReason = null; 4309 mActiveSurfaceSyncGroup = null; 4310 mSyncBuffer = false; 4311 if (isInWMSRequestedSync()) { 4312 mWmsRequestSyncGroup.markSyncReady(); 4313 mWmsRequestSyncGroup = null; 4314 mWmsRequestSyncGroupState = WMS_SYNC_NONE; 4315 } 4316 } 4317 4318 // #ifdef OPLUS_FEATURE_VIEW_DEBUG 4319 // Bard.Zhang@Android.UIFramework 2023-01-28 Add for : view debug 4320 mViewRootImplExt.markOnPerformTraversalsEnd(host); 4321 // #endif /* OPLUS_FEATURE_VIEW_DEBUG */ 4322 4323 // #ifdef OPLUS_EXTENSION_HOOK 4324 // yanliang@Android.Performance 2023-02-13 Add for Optimize sliding effect 4325 mViewRootImplExt.checkPendingBufferCountSetting(mSurface); 4326 // #endif /*OPLUS_EXTENSION_HOOK*/ 4327 } 4328 解释里面的每行代码
最新发布
09-24
----- pid 28257 at 2025-08-12 12:17:54.599346475+0800 ----- Cmd line: com.ss.android.article.video Build fingerprint: 'realme/RMX3992/RE5C3F:16/BP2A.250605.015/U.2bb19e6-cb8404-cbba88:user/release-keys' ABI: 'arm64' Build type: optimized Debug Store: 3,16,37768860::ID:0,C:P,T:37763452,N:Finish,D:tname=main;tid=2;prid=4715950||ID:19,C:E,T:37763452||ID:19,C:S,T:37763452,N:BcRcvReg,D:tname=main;tid=2;act=android.intent.action.SIM_STATE_CHANGED;cmp=null;pkg=null;prid=4715950||ID:0,C:P,T:37763452,N:Finish,D:tname=main;tid=2;prid=272134d||ID:18,C:E,T:37763452||ID:18,C:S,T:37763451,N:BcRcvReg,D:tname=main;tid=2;act=android.net.conn.CONNECTIVITY_CHANGE;cmp=null;pkg=null;prid=272134d||ID:0,C:P,T:37763450,N:Finish,D:tname=main;tid=2;prid=33a5b38||ID:17,C:E,T:37763450||ID:17,C:S,T:37763450,N:BcRcvReg,D:tname=main;tid=2;act=android.net.conn.CONNECTIVITY_CHANGE;cmp=null;pkg=null;prid=33a5b38||ID:0,C:P,T:37763446,N:Finish,D:tname=main;tid=2;prid=a07ff43||ID:16,C:E,T:37763446||ID:16,C:S,T:37763446,N:BcRcvReg,D:tname=main;tid=2;act=android.intent.action.BATTERY_CHANGED;cmp=null;pkg=null;prid=a07ff43||ID:0,C:P,T:37763444,N:Finish,D:tname=main;tid=2;prid=2bef1bc||ID:15,C:E,T:37763444||ID:15,C:S,T:37763443,N:BcRcvReg,D:tname=main;tid=2;act=android.net.conn.CONNECTIVITY_CHANGE;cmp=null;pkg=null;prid=2bef1bc||ID:0,C:P,T:37763443,N:Finish,D:tname=main;tid=2;prid=4010ab7;; suspend all histogram: Sum: 133us 99% C.I. 4us-33us Avg: 13.300us Max: 33us DALVIK THREADS (170): "main" prio=5 tid=1 Native | group="main" sCount=1 ucsCount=0 flags=1 obj=0xabe78430 self=0xb400007e828c2000 | sysTid=28257 nice=-10 cgrp=top-app sched=0/0 handle=0x7f3bae6098 | state=S schedstat=( 803321781 98899153 962 ) utm=61 stm=18 core=6 HZ=100 | stack=0x7ff8f1e000-0x7ff8f20000 stackSize=8188KB | held mutexes= native: #00 pc 000aeb1c /apex/com.android.runtime/lib64/bionic/libc.so (syscall+28) (BuildId: c135d9ca249ce7b7bdf2415d0639f65d) native: #01 pc 000897f0 /apex/com.android.runtime/lib64/bionic/libc.so (__futex_wait_ex+144) (BuildId: c135d9ca249ce7b7bdf2415d0639f65d) native: #02 pc 00097688 /apex/com.android.runtime/lib64/bionic/libc.so (pthread_cond_wait+72) (BuildId: c135d9ca249ce7b7bdf2415d0639f65d) native: #03 pc 000a19ac /system/lib64/libc++.so (std::__1::__assoc_sub_state::copy+56) (BuildId: ada37e5198285720b02f7d77fd27626c7782fe29) native: #04 pc 000a1d14 /system/lib64/libc++.so (std::__1::future<void>::get+28) (BuildId: ada37e5198285720b02f7d77fd27626c7782fe29) native: #05 pc 0038ca1c /system/lib64/libhwui.so (android::uirenderer::renderthread::RenderProxy::setStopped+284) (BuildId: 42040d65e42b0c44e419563874d2eff0) at android.graphics.HardwareRenderer.nSetStopped(Native method) at android.graphics.HardwareRenderer.setStopped(HardwareRenderer.java:599) at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:6317) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:5082) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:3508) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:11929) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1809) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1818) at android.view.Choreographer.doCallbacks(Choreographer.java:1336) at android.view.Choreographer.doFrame(Choreographer.java:1222) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1792) at android.os.Handler.handleCallback(Handler.java:1027) at android.os.Handler.dispatchMessage(Handler.java:108) at android.os.Looper.loopOnce(Looper.java:298) at android.os.Looper.loop(Looper.java:408) at android.app.ActivityThread.main(ActivityThread.java:9952) at java.lang.reflect.Method.invoke(Native method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:613) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1074) DumpLatencyMs: 0.55377分析这个ANR看是系统的问题还是应用的问题
08-28
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值