Activty启动到显示的过程[二]

news2024/9/19 10:55:34

Activity的显示从handleResumeActivity()方法开始。

//ActivityThread.java

@Override
    public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
            String reason) {
        final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
        ...
        if (r.window == null && !a.mFinished && willBeVisible) {
            r.window = r.activity.getWindow();
            View decor = r.window.getDecorView();
            decor.setVisibility(View.INVISIBLE);
            ViewManager wm = a.getWindowManager();
            ...
                if (a.mVisibleFromClient) {
                	if (!a.mWindowAdded) {
                    	a.mWindowAdded = true;
                    	android.util.Log.d(TAG, "linzh handleResumeActivity: l.token = " + l.token);
		            	wm.addView(decor, l);
                	} 
                }
        }
		...
    }

拿到对应Activity的的DecorView对象后,通过ViewManager接口的addView()方法开始显示界面的过程。

WindowManagerImpl是ViewManager的实现类,WindowManagerImpl调用WindowManagerGlobal类addView()方法。

addView

// WindowManagerGlobal.java    

	public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow, int userId) {
参考:https://blog.csdn.net/luoshengyang/article/details/46281499,https://androidperformance.com/2015/08/12/AndroidL-hwui-RenderThread-workflow/#/2-4-swapBuffers        
        	ViewRootImpl root;
        	...
            root = new ViewRootImpl(view.getContext(), display);
        
            view.setLayoutParams(wparams);

            mViews.add(view);
            mRoots.add(root);
            mParams.add(wparams);

            // do this last because it fires off messages to start doing things
            try {
                root.setView(view, wparams, panelParentView, userId);
            } catch (RuntimeException e) {
                // BadTokenException or InvalidDisplayException, clean up.
                if (index >= 0) {
                    removeViewLocked(index, true);
                }
                throw e;
            }
    }

ViewRootImpl构造方法中通过WindowManagerGlobal.getWindowSession()方法获取IWindowSession对象,IWindowSession是app进程和WMS(system_server进程)沟通的桥梁。

IWindowSession

// ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
    
    // These can be accessed by any thread, must be protected with a lock.
    // Surface can never be reassigned or cleared (use Surface.clear()).
    @UnsupportedAppUsage
    public final Surface mSurface = new Surface();
            
	public ViewRootImpl(Context context, Display display) {
        this(context, display, WindowManagerGlobal.getWindowSession(),
                false /* useSfChoreographer */);
    }

    public ViewRootImpl(Context context, Display display, IWindowSession session) {
        this(context, display, session, false /* useSfChoreographer */);
    }

    public ViewRootImpl(Context context, Display display, IWindowSession session,
            boolean useSfChoreographer) {
        mContext = context;
        mWindowSession = session;
        mDisplay = display;
        mBasePackageName = context.getBasePackageName();
        mThread = Thread.currentThread();
        mChoreographer = useSfChoreographer
                ? Choreographer.getSfInstance() : Choreographer.getInstance();
        ...
    }
}

类变量mSurface在声明时就被实例化了,但是此时的mSurface 还没有与底层的surface 关联起来,后面会通过copyFrom 进行关联。

ViewRootImpl构造方法中,初始化mWindowSession(app和WMS建立连接),mThread(确认在主线程更新UI),mChoreographer(与Vsync机制配合,实现统一调度界面绘图)。

sWindowSession是WindowManagerGlobal类的静态变量,使用单例模式初始化,确保一个进程中只存在一个IWindowSession实例。

// WindowManagerGlobal.java
public final class WindowManagerGlobal {
    
    @UnsupportedAppUsage
    private static IWindowSession sWindowSession;
    
    @UnsupportedAppUsage
    public static IWindowSession getWindowSession() {
        synchronized (WindowManagerGlobal.class) {
            if (sWindowSession == null) {
                try {
                    InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();
                    IWindowManager windowManager = getWindowManagerService();
                    sWindowSession = windowManager.openSession(
                            new IWindowSessionCallback.Stub() {
                                @Override
                                public void onAnimatorScaleChanged(float scale) {
                                    ValueAnimator.setDurationScale(scale);
                                }
                            });
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
            return sWindowSession;
        }
    }
}
// WindowManagerService.java    
	@Override
    public IWindowSession openSession(IWindowSessionCallback callback) {
        return new Session(this, callback);
    }

// Session.java
class Session extends IWindowSession.Stub implements IBinder.DeathRecipient{
    final WindowManagerService mService;
    SurfaceSession mSurfaceSession;
    ...
    public Session(WindowManagerService service, IWindowSessionCallback callback) {
        mService = service;
        ...
    }
}

WMS构建新的IWindowSession实例,Session类实现了IWindowSession.aidl接口,定义了app和WMS交互的接口方法,在构造方法中初始化WindowManagerService对象。还持有SurfaceSession 对象变量mSurfaceSession,mSurfaceSession并不在Session的构造方法中初始化,而是在调用IWindowSession定义的addToDisplayAsUser()方法时,由WMS(system_server进程)初始化。

setView

IWindowSession实例在ViewRootImpl构造方法中初始化好了, 终于开始要构建View了。

在方法开始会调用requestLayout(),然后通过mWindowSession.addToDisplayAsUser()方法初始化IWindowSession实例中的SurfaceSession对象。

后续setFrame()会继续调用requestLayout()方法。

requestLayout()在检查是主线程后(判断当前线程与实例化时是否同一线程),scheduleTraversals()方法中先在当前线程looper中postSyncBarrier()发送同步消息屏障,同步消息将被拖延执行,队列里的异步消息优先执行,通过 postCallback 提交一个任务,mTraversalRunnable是要执行的回调,有了同步消息屏障mTraversalRunnable就会被优先执行。

在安卓4.1之后,为了优化UI效果,安卓引入了Choreographer机制,配置底层上报的VSYNC信号,在收到信号后立即开始下一帧的渲染,保证mTraversalRunnable不被looper中的普通消息阻塞,立即执行渲染动作。

// ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView, int userId) {
        synchronized (this) {
            ...
                // Schedule the first layout -before- adding to the window
                // manager, to make sure we do the relayout before receiving
                // any other events from the system.
                requestLayout();
            ...
                try {
                    mOrigWindowType = mWindowAttributes.type;
                    mAttachInfo.mRecomputeGlobalAttributes = true;
                    collectViewAttributes();
                    adjustLayoutParamsForCompatibility(mWindowAttributes);
                    res = mWindowSession.addToDisplayAsUser(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrame,
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mDisplayCutout, inputChannel,
                            mTempInsets, mTempControls);
                    setFrame(mTmpFrame);
                } catch (RemoteException e) {
                    mAdded = false;
                    mView = null;
                    mAttachInfo.mRootView = null;
                    inputChannel = null;
                    mFallbackEventHandler.setView(null);
                    unscheduleTraversals();
                    setAccessibilityFocus(null, null);
                    throw new RuntimeException("Adding window failed", e);
                } finally {
                    if (restore) {
                        attrs.restore();
                    }
                }
        }
    }
    @Override
    public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            checkThread();
            mLayoutRequested = true;
            scheduleTraversals();
        }
    }
    @UnsupportedAppUsage
    void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            notifyRendererOfFramePending();
            pokeDrawLockIfNeeded();
        }
    }

SurfaceSession

mWindowSession.addToDisplayAsUser()通过WMS的addWindow()方法,实例化WindowState对象,记录到mWindowMap变量中,WindowState是WMS用来管理window而设计的一个类。

// WindowManagerService.java
public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
    
    /** Mapping from an IWindow IBinder to the server's Window object. */
    final HashMap<IBinder, WindowState> mWindowMap = new HashMap<>();

    
	public int addWindow(Session session, IWindow client, int seq,
            LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame,
            Rect outContentInsets, Rect outStableInsets,
            DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
            InsetsState outInsetsState, InsetsSourceControl[] outActiveControls,
            int requestUserId) {
            // 校验token等操作
            ...
                final WindowState win = new WindowState(this, session, client, token, parentWindow,
                        appOp[0], seq, attrs, viewVisibility, session.mUid, userId,
                    session.mCanAddInternalSystemWindow);
        		...
                win.attach();
                mWindowMap.put(client.asBinder(), win);
                win.initAppOpsState();
        	...
    }
}

Session类中的mSurfaceSession对象在这里被实例化。

win.attach();调用windowAddedLocked()方法,传入mAttrs.packageName作为参数。

// Session.java
class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
    
    SurfaceSession mSurfaceSession;
    
    void windowAddedLocked(String packageName) {
        mPackageName = packageName;
        mRelayoutTag = "relayoutWindow: " + mPackageName;
        if (mSurfaceSession == null) {
            mSurfaceSession = new SurfaceSession();
            mService.mSessions.add(this);
            if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
                mService.dispatchNewAnimatorScaleLocked(this);
            }
        }
        mNumWindow++;
    }
}

SurfaceSession构造方法中通过jni调用nativeCreate(),返回SurfaceComposerClient对象的地址,赋值给mNativeClient变量。

// SurfaceSession.java
public final class SurfaceSession {
    @UnsupportedAppUsage
    private long mNativeClient; // SurfaceComposerClient*
    
	@UnsupportedAppUsage
    public SurfaceSession() {
        mNativeClient = nativeCreate();
    }
}

// android_view_SufaceSession.cpp
static jlong nativeCreate(JNIEnv* env, jclass clazz) {
    SurfaceComposerClient* client = new SurfaceComposerClient();
    client->incStrong((void*)nativeCreate);
    jlong t = reinterpret_cast<jlong>(client);
    return reinterpret_cast<jlong>(client);
}

实例化一个SurfaceSession对象,nativeCreate()实例化SurfaceComposerClient对象,代表和surfaceflinger服务建立连接了。

到这里准备工作都做好了,就等Choreographer接受VSYNC信号执行mTraversalRunnable。

mTraversalRunnable

mTraversalRunnable被执行后,removeSyncBarrier()先移除looper中的同步屏障,普通的同步消息不再被拖延,performTraversals()先通过relayoutWindow()通知surfaceflinger创建一个surface,ViewRootImpl类的mSurface变量也在relayoutWindow()方法中通过copyFrom()方法和底层的surface对象关联起来。

performMeasure(), performLayout(), performDraw()分别会调用View的onMeasure(), onSizeChanaged(), onLayout(), onDraw()方法,开始画面绘制渲染。

    void doTraversal() {
        if (mTraversalScheduled) {
            mTraversalScheduled = false;
            mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);

            performTraversals();
        }
    }

    private void performTraversals() {
        ...
        relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
        
        performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
        
        performLayout(lp, mWidth, mHeight);
        
        performDraw();
        ...
    }

SurfaceControl / Surface

SurfaceControl是surface和如何处理surface的元数据(name, width, height, format)的组合。

SurfaceControl类在Java(frameworks/base/core/java/android/view/SurfaceControl.java)和cpp(frameworks/native/libs/gui/SurfaceControl.cpp)中都有实现。

Java层的SurfaceControl主要是对cpp层的SurfaceControl对象的封装,其类变量mNativeObject指向cpp层SurfaceControl对象的引用,mNativeHandle指向cpp层Layer类的内部类Handle,Handle继承了BBinder和LayerCleaner,LayerCleaner在handle被销毁时确保mFlinger->onLayerDestroyed()方法被调用。

// SurfaceControl.java
public final class SurfaceControl implements Parcelable {
    
    public long mNativeObject;
    private long mNativeHandle;
    
    private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
            SurfaceControl parent, SparseIntArray metadata, WeakReference<View> localOwnerView,
            String callsite){
        	...
            mNativeObject = nativeCreate(session, name, w, h, format, flags,
                    parent != null ? parent.mNativeObject : 0, metaParcel);
        	mNativeHandle = nativeGetHandle(mNativeObject);
    }
}

cpp层的SurfaceControl保存了SurfaceComposerClient,Surface,Handle,IGraphicBufferProducer等和surface控制相关的数据。

// SurfaceControl.cpp
class SurfaceControl : public RefBase
{
    
private:
    sp<SurfaceComposerClient>   mClient;
    sp<IBinder>                 mHandle;
    sp<IGraphicBufferProducer>  mGraphicBufferProducer;
    mutable Mutex               mLock;
    mutable sp<Surface>         mSurfaceData;
    
	SurfaceControl::SurfaceControl(const sp<SurfaceComposerClient>& client, const sp<IBinder>& handle,
                               const sp<IGraphicBufferProducer>& gbp,
                               uint32_t transform)
      : mClient(client),
        mHandle(handle),
        mGraphicBufferProducer(gbp),
        mTransformHint(transform) {}
    
    sp<Surface> SurfaceControl::generateSurfaceLocked() const
    {
        // This surface is always consumed by SurfaceFlinger, so the
        // producerControlledByApp value doesn't matter; using false.
        mSurfaceData = new Surface(mGraphicBufferProducer, false);

        return mSurfaceData;
    }

    sp<Surface> SurfaceControl::getSurface() const
    {
        Mutex::Autolock _l(mLock);
        if (mSurfaceData == nullptr) {
            ALOGD("mSurfaceData == nullptr");
            return generateSurfaceLocked();
        }
        return mSurfaceData;
    }
}

SurfaceControl在ViewRootImpl类的relayoutWindow()方法被初始化后,之前提到的ViewRootImpl类的mSurface变量也通过copyFrom()方法关联到cpp层的Surface对象。

通过SurfaceControl.mNativeObject获取到cpp层的SurfaceControl对象,SurfaceControl.getSurface()返回cpp层的Surface对象。至此Surface对象也准备好了。

// Surface.java
public class Surface implements Parcelable {
    long mNativeObject; // package scope only for SurfaceControl access
    
    public void copyFrom(SurfaceControl other) {
        long surfaceControlPtr = other.mNativeObject;
        long newNativeObject = nativeGetFromSurfaceControl(mNativeObject, surfaceControlPtr);
                synchronized (mLock) {
            if (newNativeObject == mNativeObject) {
                return;
            }
            if (mNativeObject != 0) {
                nativeRelease(mNativeObject);
            }
            setNativeObjectLocked(newNativeObject);
        }
    }
    
    private void setNativeObjectLocked(long ptr) {
        if (mNativeObject != ptr) {
            mNativeObject = ptr;
            mGenerationId += 1;
            if (mHwuiContext != null) {
                mHwuiContext.updateSurface();
            }
        }
    }
}

Layer/Producer/Consumer

SurfaceControl构造方法中nativeCreate()不仅仅创建了native层的SurfaceControl对象,还调用了surfaceflinger的createLayer()方法创建Layer对象。

A Layer is the most important unit of composition. A layer is a combination of a surface and an instance of SurfaceControl. Each layer has a set of properties that define how it interacts with other layers. Layer properties are described in the table below.

BufferQueueLayer在onFirstRef()方法中初始化生产者和消费者,消费者设置内容监听ContentsChangedListener。

// frameworks/native/services/surfaceflinger/BufferQueueLayer.cpp
/*
 * A new BufferQueue and a new BufferLayerConsumer are created when the
 * BufferLayer is first referenced.
 *
 * This also implements onFrameAvailable(), which notifies SurfaceFlinger
 * that new data has arrived.
 */
void BufferQueueLayer::onFirstRef() {
    BufferLayer::onFirstRef();

    // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
    sp<IGraphicBufferProducer> producer;
    sp<IGraphicBufferConsumer> consumer;
    mFlinger->getFactory().createBufferQueue(&producer, &consumer, true);
    mProducer = mFlinger->getFactory().createMonitoredProducer(producer, mFlinger, this);
    mConsumer =
            mFlinger->getFactory().createBufferLayerConsumer(consumer, mFlinger->getRenderEngine(),
                                                             mTextureName, this);
    mConsumer->setConsumerUsageBits(getEffectiveUsage(0));

    mContentsChangedListener = new ContentsChangedListener(this);
    mConsumer->setContentsChangedListener(mContentsChangedListener);
    mConsumer->setName(String8(mName.data(), mName.size()));

    // BufferQueueCore::mMaxDequeuedBufferCount is default to 1
    if (!mFlinger->isLayerTripleBufferingDisabled()) {
        mProducer->setMaxDequeuedBufferCount(2);
    }
}

void BufferQueueLayer::ContentsChangedListener::onFrameAvailable(const BufferItem& item) {
    Mutex::Autolock lock(mMutex);
    if (mBufferQueueLayer != nullptr) {
        mBufferQueueLayer->onFrameAvailable(item);
    }
}

RenderThread

mTraversalRunnable在调用relayoutWindow()方法完成surface对象的初始化后,开始performMeasure(),performLayout()计算View的位置信息,performDraw()开始渲染过程,在硬件加速渲染环境中,Android应用程序窗口的UI渲染是分两步进行的。第一步是构建Display List,发生在应用程序进程的Main Thread中;第二步是渲染Display List,发生在应用程序进程的Render Thread中。

// HardwareRenderer.java
public class HardwareRenderer {
    
    private final long mNativeProxy;
    /** @hide */
    protected RenderNode mRootNode;
    
	public HardwareRenderer() {
        mRootNode = RenderNode.adopt(nCreateRootRenderNode());
        mRootNode.setClipToBounds(false);
        mNativeProxy = nCreateProxy(!mOpaque, mIsWideGamut, mRootNode.mNativeRenderNode);
        if (mNativeProxy == 0) {
            throw new OutOfMemoryError("Unable to create hardware renderer");
        }
        Cleaner.create(this, new DestroyContextRunnable(mNativeProxy));
        ProcessInitializer.sInstance.init(mNativeProxy);
    }
}

ThreadedRenderer继承HardwareRenderer,构造方法中先分配唯一的RenderNode,nCreateProxy()初始化RenderProxy对象,RenderProxy负责native层的渲染RenderNode工作。

先看下RenderProxy的构造函数,一开始创建的RenderNode对象作为参数传递给了mContext(CanvasContext)和mDrawFrameTask。

//frameworks/base/libs/hwui/renderthread/RenderProxy.cpp
RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode,
                         IContextFactory* contextFactory)
        : mRenderThread(RenderThread::getInstance()), mContext(nullptr) {
    mContext = mRenderThread.queue().runSync([&]() -> CanvasContext* {
        return CanvasContext::create(mRenderThread, translucent, rootRenderNode, contextFactory);
    });
    mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode);
}

CanvasContext判断渲染类型选择SkiaOpenGLPipeline或是SkiaVulkanPipeline

//frameworks/base/libs/hwui/renderthread/CanvasContext.cpp
CanvasContext* CanvasContext::create(RenderThread& thread, bool translucent,
                                     RenderNode* rootRenderNode, IContextFactory* contextFactory) {
    auto renderType = Properties::getRenderPipelineType();

    switch (renderType) {
        case RenderPipelineType::SkiaGL:
            return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
                                     std::make_unique<skiapipeline::SkiaOpenGLPipeline>(thread));
        case RenderPipelineType::SkiaVulkan:
            return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
                                     std::make_unique<skiapipeline::SkiaVulkanPipeline>(thread));
        default:
            LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
            break;
    }
    return nullptr;
}

CanvasContext::CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
                             IContextFactory* contextFactory,
                             std::unique_ptr<IRenderPipeline> renderPipeline)
        : mRenderThread(thread)
        , mGenerationID(0)
        , mOpaque(!translucent)
        , mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord()))
        , mJankTracker(&thread.globalProfileData())
        , mProfiler(mJankTracker.frames(), thread.timeLord().frameIntervalNanos())
        , mContentDrawBounds(0, 0, 0, 0)
        , mRenderPipeline(std::move(renderPipeline)) {
    rootRenderNode->makeRoot();
    mRenderNodes.emplace_back(rootRenderNode);
    mProfiler.setDensity(DeviceInfo::getDensity());
    setRenderAheadDepth(Properties::defaultRenderAhead);
}

到这里native层的RenderNode,RenderProxy,CanvasContext,IRenderPipeline等对象都初始化完成。

ThreadedRenderer开始调用draw()方法开始RenderNode的渲染工作。

// ThreadedRenderer.java    
public final class ThreadedRenderer extends HardwareRenderer {
    
	void draw(View view, AttachInfo attachInfo, DrawCallbacks callbacks) {
        final Choreographer choreographer = attachInfo.mViewRootImpl.mChoreographer;
        choreographer.mFrameInfo.markDrawStart();

        updateRootDisplayList(view, callbacks);

        int syncResult = syncAndDrawFrame(choreographer.mFrameInfo);
        ...
    }
}

updateRootDisplayList()构建参数view描述的视图的Display List,即DecorView的DisplayList。构建好的这个DisplayList可以通过调用参数view描述的视图的成员函数getDisplayList()获得的一个RenderNode来描述。

syncAndDrawFrame()调用的是native方法nSyncAndDrawFrame(),主要逻辑操作在DrawFrameTask::run()方法,DrawFrameTask运行在RenderThread(下图1927)上,而不是UIThread(下图1905)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZaPy8juV-1678103236257)(/home/lin/Nutstore Files/我的坚果云/notes/activity/2022-07-27 16-42-23屏幕截图.png)]

//frameworks/base/libs/hwui/renderthread/DrawFrameTask.cpp
void DrawFrameTask::run() {
    ATRACE_NAME("DrawFrame");

    bool canUnblockUiThread;
    bool canDrawThisFrame;
    {
        TreeInfo info(TreeInfo::MODE_FULL, *mContext);
        canUnblockUiThread = syncFrameState(info);
        canDrawThisFrame = info.out.canDrawThisFrame;

        if (mFrameCompleteCallback) {
            mContext->addFrameCompleteListener(std::move(mFrameCompleteCallback));
            mFrameCompleteCallback = nullptr;
        }
    }

    // Grab a copy of everything we need
    CanvasContext* context = mContext;
    std::function<void(int64_t)> callback = std::move(mFrameCallback);
    mFrameCallback = nullptr;

    // From this point on anything in "this" is *UNSAFE TO ACCESS*
    if (canUnblockUiThread) {
        unblockUiThread();
    }

    // Even if we aren't drawing this vsync pulse the next frame number will still be accurate
    if (CC_UNLIKELY(callback)) {
        context->enqueueFrameWork(
                [callback, frameNr = context->getFrameNumber()]() { callback(frameNr); });
    }

    if (CC_LIKELY(canDrawThisFrame)) {
        context->draw();
    } else {
        // wait on fences so tasks don't overlap next frame
        context->waitOnFences();
    }

    if (!canUnblockUiThread) {
        unblockUiThread();
    }
}

syncFrameState()通过DecorView的RenderNode对象(HardwareRenderer.mRootNode)将应用程序窗口的DisplayList、RenderProperty以及DisplayList引用的Bitmap等信息从MainThread同步到RenderThread中。注意,在这个同步过程中,MainThread是处于等待状态的。

如果成员函数syncFrameState能顺利地完成信息同步,那么它的返回值canUnblockUiThread就会等于true,表示在Render Thread渲染应用程序窗口的下一帧之前,就可以唤醒Main Thread了。否则的话,就要等到Render Thread渲染应用程序窗口的下一帧之后,才能唤醒Main Thread。唤醒Render Thread是通过调用成员函数unblockUiThread来完成的。

context->draw(),调用成员变量mContext描述的一个CanvasContext对象的成员函数draw()渲染应用程序窗口的DisplayList。

//frameworks/base/libs/hwui/renderthread/CanvasContext.cpp

void CanvasContext::draw() {
    SkRect dirty;
    mDamageAccumulator.finish(&dirty);


    SkRect windowDirty = computeDirtyRect(frame, &dirty);

    bool drew = mRenderPipeline->draw(frame, windowDirty, dirty, mLightGeometry, &mLayerUpdateQueue,
                                      mContentDrawBounds, mOpaque, mLightInfo, mRenderNodes,
                                      &(profiler()));

    waitOnFences();

    bool didSwap =
            mRenderPipeline->swapBuffers(frame, drew, windowDirty, mCurrentFrameInfo, &requireSwap);

    mIsDirty = false;

    if (requireSwap) {
        ...
    }
	...
    mRenderThread.cacheManager().onFrameCompleted();
}

computeDirtyRect()计算脏区,mRenderPipeline->draw()开始渲染工作,mRenderPipeline->swapBuffers()后面会通过EglManager等处理,queueBuffer() 入队列这个buffer,将前面已经绘制好的图形缓冲区提交给SurfaceFlinger合成和显示,SurfaceFlinger在消费者onFrameAvailable()后开始接手工作。

参考:

https://blog.csdn.net/luoshengyang/article/details/46281499,

https://androidperformance.com/2015/08/12/AndroidL-hwui-RenderThread-workflow/#/2-4-swapBuffers

SurfaceView/TextureView

  • SurfaceView

    1. 具有独立的surface对象,对应WMS和SurfaceFlinger而言它就如同是一个DecorView,在WMS中有一个对应的WindowState,在SurfaceFlinger中有一个对应的Layer。

    2. 用来描述SurfaceView的Layer或者LayerBuffer的Z轴位置是小于用来其宿主Activity窗口的Layer的Z轴位置的,SurfaceView的onAttachedToWindow()方法中会请求宿主DecorView一块透明区域以显示SurfaceView画面。

      public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCallback {
          
          final Surface mSurface = new Surface();       // Current surface in use
          
          
      	@Override
          protected void onAttachedToWindow() {
              super.onAttachedToWindow();
      
              getViewRootImpl().addSurfaceChangedCallback(this);
              mWindowStopped = false;
      
              mViewVisibility = getVisibility() == VISIBLE;
              updateRequestedVisibility();
      
              mAttachedToWindow = true;
              mParent.requestTransparentRegion(SurfaceView.this);  		//请求透明区域
              if (!mGlobalListenersAdded) {
                  ViewTreeObserver observer = getViewTreeObserver();
                  observer.addOnScrollChangedListener(mScrollChangedListener);
                  observer.addOnPreDrawListener(mDrawListener);
                  mGlobalListenersAdded = true;
              }
          }
      }
      
    3. SurfaceView的UI绘制可以在独立的线程中进行,这样就可以进行复杂的UI绘制,并且不会影响应用程序的主线程响应用户输入。

  • TextureView

TextureView是对SurfaceTexture的包装,SurfaceTexture构造方法中通过nativeInit()实例化native层的SurfaceTexture对象和生产者Producer,消费者Consumer。

//SurfaceTexture.cpp
static void SurfaceTexture_init(JNIEnv* env, jobject thiz, jboolean isDetached,
        jint texName, jboolean singleBufferMode, jobject weakThiz)
{
    sp<IGraphicBufferProducer> producer;
    sp<IGraphicBufferConsumer> consumer;
    BufferQueue::createBufferQueue(&producer, &consumer);

    if (singleBufferMode) {
        consumer->setMaxBufferCount(1);
    }

    sp<SurfaceTexture> surfaceTexture;
    if (isDetached) {
        surfaceTexture = new SurfaceTexture(consumer, GL_TEXTURE_EXTERNAL_OES,
                true, !singleBufferMode);
    } else {
        surfaceTexture = new SurfaceTexture(consumer, texName,
                GL_TEXTURE_EXTERNAL_OES, true, !singleBufferMode);
    }

    SurfaceTexture_setSurfaceTexture(env, thiz, surfaceTexture);
    SurfaceTexture_setProducer(env, thiz, producer);

    surfaceTexture->setFrameAvailableListener(ctx);
    SurfaceTexture_setFrameAvailableListener(env, thiz, ctx);
}

SurfaceTexture对图像流的处理并不直接显示,而是转为GL外部纹理,用于图像流数据的二次处理。

TextureView就是对SurfaceTexture的二次处理,将纹理数据输出为View显示出来,TextureView覆盖了View的 draw() 方法。

//TextureView.java   
	@Override
    public final void draw(Canvas canvas) {
        // NOTE: Maintain this carefully (see View#draw)
        mPrivateFlags = (mPrivateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;

        /* Simplify drawing to guarantee the layer is the only thing drawn - so e.g. no background,
        scrolling, or fading edges. This guarantees all drawing is in the layer, so drawing
        properties (alpha, layer paint) affect all of the content of a TextureView. */

        if (canvas.isHardwareAccelerated()) {
            RecordingCanvas recordingCanvas = (RecordingCanvas) canvas;

            TextureLayer layer = getTextureLayer();
            if (layer != null) {
                applyUpdate();
                applyTransformMatrix();

                mLayer.setLayerPaint(mLayerPaint); // ensure layer paint is up to date
                recordingCanvas.drawTextureLayer(layer);
            }
        }
    }

可以看到TextureView必须工作在硬件加速的环境,通过 hwui 中的RenderThread渲染绘制图像,或者什么也不会做。

流程图:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/391986.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LCD液晶段码驱动IC/LCD液晶驱动芯片VK2C22高抗干扰/抗噪,适用于汽车仪表/单相智能电表

产品型号&#xff1a;VK2C22A/B产品品牌&#xff1a;永嘉微电/VINKA封装形式&#xff1a;LQFP52/48、DICE(COB邦定片)、COG(邦定玻璃用)产品年份&#xff1a;新年份原厂&#xff0c;工程服务&#xff0c;技术支持&#xff01;VK2C22A/B概述&#xff1a;VK2C22是一个点阵式存储映…

自然语言处理-基于预训练模型的方法-chapter3基础工具集与常用数据集

文章目录3.1NLTK工具集3.1.1常用语料库和词典资源3.1.2常见自然语言处理工具集3.2LTP工具集3.3pytorch基础3.3.1张量基本概念3.3.2张量基本运算3.3.3自动微分3.3.4调整张量形状3.3.5广播机制3.3.6索引与切片3.3.7降维与升维3.4大规模预训练模型3.1NLTK工具集 3.1.1常用语料库和…

2023年3月软考高项(信息系统项目管理师)报名走起!!!

信息系统项目管理师是全国计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff08;简称软考&#xff09;项目之一&#xff0c;是由国家人力资源和社会保障部、工业和信息化部共同组织的国家级考试&#xff0c;既属于国家职业资格考试&#xff0c;又是职称资…

图表控件LightningChart.NET 系列教程(十一):LightningChart 组件——添加至 Blend WPF 项目

LightningChart.NET 是一款高性能 WPF 和 Winforms 图表,可以实时可视化多达1万亿个数据点。可有效利用CPU和内存资源&#xff0c;实时监控数据流。同时&#xff0c;LightningChart使用突破性创新技术&#xff0c;以实时优化为前提&#xff0c;大大提升了实时渲染的效率和效果&…

网络编程 socket 编程(一)

1. C/S 架构 C/S 架构即客户端/服务端架构&#xff0c;B/S 架构&#xff08;浏览器与服务端&#xff09;也是 C/S 架构的一种。 C/S 架构与 socket 的关系&#xff1a;学习 socket 可以完成 C/S 架构的开发。 2. osi 七层 一个完整的计算机系统由硬件、操作系统以及应用软件…

Redis:主从同步

Redis&#xff1a;主从同步一. 概述二. 原理(1) 全量同步(2) 增量同步(3) 优化Redis主从集群三. 总结一. 概述 引入&#xff1a; Redis主从集群采用一个Master负责写&#xff0c;多个Slave负责读的方式&#xff08;读多写少&#xff09;&#xff0c;那么如何让读取数据时多个从…

访问学者进入美国哪些东西不能带?

随着疫情的稳定&#xff0c;各国签证的逐步放开&#xff0c;成功申请到国外访问学者、博士后如何顺利的进入国外&#xff0c;哪些东西不能带&#xff0c;下面就随知识人网小编一起看一看。一、畜禽肉类(Meats, Livestock and Poultry)不论是新鲜的、干燥的、罐头的、真空包装的…

pycharm激活虚拟环境时报错:无法加载文件activate.ps1,因为在此系统上禁止运行脚本,Windows10系统

问题&#xff1a; ii_env\Scripts\activate : 无法加载文件 F:\gitlab\AutoFrame\ii_env\Scripts\Activate.ps1&#xff0c;因为在此系统上禁止运行脚本。 有关详细信息&#xff0c;请参阅 https:/go.microsoft.com/fwlink/?LinkID135170 中的 about_Execution_Policies。 所在…

34 openEuler使用LVM管理硬盘-创建并挂载文件系统

文章目录34 openEuler使用LVM管理硬盘-创建并挂载文件系统34.1 创建文件系统34.2 手动挂载文件系统34.3 自动挂载文件系统34 openEuler使用LVM管理硬盘-创建并挂载文件系统 在创建完逻辑卷之后&#xff0c;需要在逻辑卷之上创建文件系统并挂载文件系统到相应目录下。 34.1 创…

大型医院云HIS系统:采用前后端分离架构,前端由Angular语言、JavaScript开发;后端使用Java语言开发 融合B/S版电子病历系统

一套医院云his系统源码 采用前后端分离架构&#xff0c;前端由Angular语言、JavaScript开发&#xff1b;后端使用Java语言开发。融合B/S版电子病历系统&#xff0c;支持电子病历四级&#xff0c;HIS与电子病历系统均拥有自主知识产权。 文末卡片获取联系&#xff01; 基于云计…

谷歌留痕霸屏平台有哪些?

谷歌留痕霸屏平台有哪些&#xff1f; 答案是&#xff1a;光算可以做谷歌留痕霸屏 我们要先了解什么是谷歌留痕霸屏平台这个概念。 很简单&#xff0c;就是你有哪些可以做排名的网站资源&#xff0c;一般情况下你不够专业&#xff0c;是没办法把这件事做好的。 通常你要做谷…

学python的第四天---基础(2)

一、三角形类型读入数组并排序的方法nlist(map(float,input().split())) c,b,asorted(n)list_1 list(map(float, input().split())) list_1.sort() list_1.reverse()lengthssorted(map(float,input().split(" ")),reverseTrue)二、动物写法一&#xff1a;d{" &…

css系统化学习

元素的语义化 SEO:搜索引擎优化 根据搜索引擎展示的规律,语义化的元素更容易被展示获得更多浏览量 字符编码 css历史 内联样式(inline) style"内容全写在等号后面,双引号里面,多个之间用;隔开" 内部样式(internal) style写在head里面,在title下面,不是在body内, …

Hadoop集群搭建,基于3.3.4hadoop和centos8【图文教程-从零开始搭建Hadoop集群】,常见问题解决

Hadoop集群搭建&#xff0c;基于3.3.4hadoop和centos8【小白图文教程-从零开始搭建Hadoop集群】&#xff0c;常见问题解决Hadoop集群搭建&#xff0c;基于3.3.4hadoop1.虚拟机的创建1.1 第一台虚拟机的创建1.2 第一台虚拟机的安装1.3 第一台虚拟机的网络配置1.3.1 主机名和IP映…

10.单点登录原理及JWT实现

单点登录原理及JWT实现 一、单点登录效果 首先我们看通过一个具体的案例来加深对单点登录的理解。案例地址&#xff1a;https://gitee.com/xuxueli0323/xxl-sso?_fromgitee_search 把案例代码直接导入到IDEA中 然后分别修改下server和samples中的配置信息 在host文件中配置 …

Python实现多键字典

实现背景 在许多场景中&#xff0c;有时需要通过多种信息来获取某个特定的值&#xff0c;而各种编程语言&#xff08;包括Python&#xff09;使用的字典&#xff08;Dict&#xff09;数据结构通常只支持单个键值寻值key-val对&#xff0c;即“一对一”&#xff08;一个键对应一…

哈工大服务科学与工程第一章作业

服务的概念服务是个非常广义的概念——涉及到经济、管理、业务、IT领域以下是一些各方对服务的定义&#xff1a;服务是一方向另一方提供的任意活动和好处。它是不可触知的&#xff0c;不形成任何所有权问题&#xff0c;其生产可能与物质产品有关&#xff0c;也可能无关。服务是…

数据挖掘(2.1)--数据预处理

一、基础知识 1.数据的基本概念 1.1基础知识 数据是数据对象(Data Objects)及其属性(Attributes)的集合。 数据对象(一条记录、一个实体、一个案例、一个样本等)是对一个事物或者物理对象的描述。 数据对象的属性则是这个对象的性质或特征&#xff0c;例如一个人的肤色、眼球…

28个案例问题分析---027---单表的11个Update接口--MyBatis

一&#xff1a;背景介绍 项目开发中。我们使用的是MyBatis&#xff0c;在MyBatis的xml文件里&#xff0c;两个表的更新功能&#xff0c;写了足足11个更新接口&#xff0c;毫无复用的思想 这种方式可以正常的实现功能&#xff0c;但是没有复用&#xff0c;无论是从时间上还是维…

推荐系统与推荐算法

文章目录第一章1.1推荐系统意义与价值1.2推荐系统历史与框架1.3推荐算法分类第二章2.1协同过滤的基本思想与分类2.2基于用户的协同过滤2.3基于项目的协同过滤2.4基于邻域的评分预测2.5基于二部图的协同过滤第三章3.1基于关联规则的推荐3.2基于矩阵分解的评分预测3.3概率矩阵分解…