Vsync之app层面深入分析

背景

前面文章和视频课程都是直接从SurfaceFlinger层面开始讲解Vsync部分的,当然vsync的主要核心逻辑也确实在SurfaceFlinger,但是一般vsync都是由app层面发起请求的,这一部分也还是有必要带大家了解清楚

java层面的分析和堆栈:

在Activity进行Resume时候,会addView,这个时候会对ViewRootImpl进行够着,构建出一个Choreographer,在构造时候会构造方法里面又会对应的FrameDisplayEventReceiver,FrameDisplayEventReceiver本身继承DisplayEventReceiver
这里的DisplayEventReceiver就是核心部分,它负责和sf进行双向通讯,不过这里双向不是一种ipc通讯方式,涉及到两个方式
在这里插入图片描述

app主动发起请求一般都是直接使用binder调用,比如常见的如下几个接口:

interface IDisplayEventConnection {
    /*
     * stealReceiveChannel() returns a BitTube to receive events from. Only the receive file
     * descriptor of outChannel will be initialized, and this effectively "steals" the receive
     * channel from the remote end (such that the remote end can only use its send channel).
     */
    void stealReceiveChannel(out BitTube outChannel);

    /*
     * setVsyncRate() sets the vsync event delivery rate. A value of 1 returns every vsync event.
     * A value of 2 returns every other event, etc. A value of 0 returns no event unless
     * requestNextVsync() has been called.
     */
    void setVsyncRate(in int count);

    /*
     * requestNextVsync() schedules the next vsync event. It has no effect if the vsync rate is > 0.
     */
    oneway void requestNextVsync(); // Asynchronous

    /*
     * getLatestVsyncEventData() gets the latest vsync event data.
     */
    ParcelableVsyncEventData getLatestVsyncEventData();
}

SurfaceFlinger进程也需要与app进行通讯,比如把vsync来临这种通知调用:
在这里插入图片描述

这里为啥sf要是有socket呢?这里主要还是为了性能考虑,socket相比延时阻塞情况比binder好,vsync通知这种属于实时性较强的操作。

下面接着看看app层面FrameDisplayEventReceiver构造接下来干了啥

  public FrameDisplayEventReceiver(Looper looper, int vsyncSource) {
            super(looper, vsyncSource, 0);//直接调用了父类的构造
        }

   /**
     * Creates a display event receiver.
     *
     * @param looper The looper to use when invoking callbacks.
     * @param vsyncSource The source of the vsync tick. Must be on of the VSYNC_SOURCE_* values.
     * @param eventRegistration Which events to dispatch. Must be a bitfield consist of the
     * EVENT_REGISTRATION_*_FLAG values.
     */
    public DisplayEventReceiver(Looper looper, int vsyncSource, int eventRegistration) {
        mMessageQueue = looper.getQueue();
        mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue,
                vsyncSource, eventRegistration);
    }

这里调用了nativeInit,接下来代码就到了native层面了
具体堆栈如下:
在这里插入图片描述

native层面的分析和堆栈:

接上面的nativeInit
frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp


static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak, jobject messageQueueObj,
                        jint vsyncSource, jint eventRegistration) {
    //省略部分
    sp<NativeDisplayEventReceiver> receiver =
            new NativeDisplayEventReceiver(env, receiverWeak, messageQueue, vsyncSource,
                                           eventRegistration);
    status_t status = receiver->initialize();
  //省略部分
    return reinterpret_cast<jlong>(receiver.get());
}

构造 NativeDisplayEventReceiver类:

NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env, jobject receiverWeak,
                                                       const sp<MessageQueue>& messageQueue,
                                                       jint vsyncSource, jint eventRegistration)
      : DisplayEventDispatcher(messageQueue->getLooper(),
                               static_cast<ISurfaceComposer::VsyncSource>(vsyncSource),
                               static_cast<ISurfaceComposer::EventRegistration>(eventRegistration)),
        mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
        mMessageQueue(messageQueue) {
}

注意这里的NativeDisplayEventReceiver继承DisplayEventDispatcher

DisplayEventDispatcher::DisplayEventDispatcher(
        const sp<Looper>& looper, ISurfaceComposer::VsyncSource vsyncSource,
        ISurfaceComposer::EventRegistrationFlags eventRegistration)
      : mLooper(looper), mReceiver(vsyncSource, eventRegistration), mWaitingForVsync(false),
        mLastVsyncCount(0), mLastScheduleVsyncTime(0) {
    ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
}

注意这里的DisplayEventDispatcher构造也会mReceiver也构造, mReceiver是DisplayEventReceiver 类型,构造方法如下:

DisplayEventReceiver::DisplayEventReceiver(
        ISurfaceComposer::VsyncSource vsyncSource,
        ISurfaceComposer::EventRegistrationFlags eventRegistration) {
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != nullptr) {
       //会与sf进行跨进程通讯,让创建对应connection
        mEventConnection = sf->createDisplayEventConnection(vsyncSource, eventRegistration);
        if (mEventConnection != nullptr) {
            mDataChannel = std::make_unique<gui::BitTube>();
            //connection创建成功,这里就会调用mEventConnection的stealReceiveChannel获取通讯的socket的fd
            const auto status = mEventConnection->stealReceiveChannel(mDataChannel.get());
        }
    }
}

这里可以看出来和sf通讯开始用mEventConnection啦

initialize主要干的事如下:

status_t DisplayEventDispatcher::initialize() {
    if (mLooper != nullptr) {
        int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL);
        if (rc < 0) {
            return UNKNOWN_ERROR;
        }
    }

    return OK;
}

把对应的服务端sf传递socket的fd进行输入事件监听,这样sf有往socket写入数据,app既可以接受到了

SurfaceFlinger端的相关方法分析

createDisplayEventConnection方法,这个方法app发起跨进程调用后会到服务端BnSurfaceComposer,这个SurfaceFlinger是继承这个BnSurfaceComposer的

class BnSurfaceComposer: public BnInterface<ISurfaceComposer> 

class SurfaceFlinger : public BnSurfaceComposer,
                       public PriorityDumper,
                       private IBinder::DeathRecipient,
                       private HWC2::ComposerCallback,
                       private ICompositor,
                       private scheduler::ISchedulerCallback {

所以这里直接看SurfaceFlinger的createDisplayEventConnection

sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
        ISurfaceComposer::VsyncSource vsyncSource,
        ISurfaceComposer::EventRegistrationFlags eventRegistration) {
        //这里参数有一个vsyncSource就是app还是appSf两个,以前没有appSf,这个参数来选着哪个EventThread
    const auto& handle =
            vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle;

    return mScheduler->createDisplayEventConnection(handle, eventRegistration);
}

再看看Scheduler::createDisplayEventConnection

sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
        ConnectionHandle handle, ISurfaceComposer::EventRegistrationFlags eventRegistration) {
    return createConnectionInternal(mConnections[handle].thread.get(), eventRegistration);
}

sp<EventThreadConnection> Scheduler::createConnectionInternal(
        EventThread* eventThread, ISurfaceComposer::EventRegistrationFlags eventRegistration) {
    return eventThread->createEventConnection([&] { resync(); }, eventRegistration);
}

sp<EventThreadConnection> EventThread::createEventConnection(
        ResyncCallback resyncCallback,
        ISurfaceComposer::EventRegistrationFlags eventRegistration) const {
        //创建对应的EventThreadConnection对象
    return new EventThreadConnection(const_cast<EventThread*>(this),
                                     IPCThreadState::self()->getCallingUid(),
                                     std::move(resyncCallback), eventRegistration);
}

可以看到最后其实是构造了一个EventThreadConnection对象

class EventThreadConnection : public gui::BnDisplayEventConnection {
public:
    EventThreadConnection(EventThread*, uid_t callingUid, ResyncCallback,
                          ISurfaceComposer::EventRegistrationFlags eventRegistration = {});

    virtual status_t postEvent(const DisplayEventReceiver::Event& event);

    binder::Status stealReceiveChannel(gui::BitTube* outChannel) override;
    binder::Status setVsyncRate(int rate) override;
    binder::Status requestNextVsync() override; // asynchronous
    binder::Status getLatestVsyncEventData(ParcelableVsyncEventData* outVsyncEventData) override;

};

上面就是它几个主要方法,就是app和sf通过这个EventThreadConnection进行通讯的接口方法

同时注意一下EventThreadConnection的onFirstRef方法

void EventThreadConnection::onFirstRef() {
    mEventThread->registerDisplayEventConnection(this);
}

这里调用了EventThread的registerDisplayEventConnection方法

status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) {
    std::lock_guard<std::mutex> lock(mMutex);
    mDisplayEventConnections.push_back(connection);
    mCondition.notify_all();
    return NO_ERROR;
}

这里主要就是把每个app的connection都放到了mDisplayEventConnections这个变量中

接下来看看对应的stealReceiveChannel的接口方法

binder::Status EventThreadConnection::stealReceiveChannel(gui::BitTube* outChannel) {
      outChannel->setReceiveFd(mChannel.moveReceiveFd());
    outChannel->setSendFd(base::unique_fd(dup(mChannel.getSendFd())));
    return binder::Status::ok();
}

可以看出这里主要是把EventThreadConnection的mChannel的fd搞到outChannel的fd具体mChannel其实是个BitTube类型

BitTube::BitTube(size_t bufsize)
    : mSendFd(-1), mReceiveFd(-1)
{
    init(bufsize, bufsize);//调用是init方法
}
void BitTube::init(size_t rcvbuf, size_t sndbuf) {
    int sockets[2];
    //其实本质是有一对socketpair
    if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
        size_t size = DEFAULT_SOCKET_BUFFER_SIZE;
        setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
        setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
        // sine we don't use the "return channel", we keep it small...
        setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
        setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
        fcntl(sockets[0], F_SETFL, O_NONBLOCK);
        fcntl(sockets[1], F_SETFL, O_NONBLOCK);
        mReceiveFd = sockets[0];
        mSendFd = sockets[1];
    } else {
        mReceiveFd = -errno;
        ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd));
    }
}

sf总结图如下:
在这里插入图片描述

本文章更多详细代码和资料需要购买课程获取
hal+perfetto+surfaceflinger
https://mp.weixin.qq.com/s/LbVLnu1udqExHVKxd74ILg
在这里插入图片描述

私聊作者+v(androidframework007)

其他课程七件套专题:在这里插入图片描述
点击这里
https://mp.weixin.qq.com/s/Qv8zjgQ0CkalKmvi8tMGaw

视频试看:
https://www.bilibili.com/video/BV1wc41117L4/

  • 30
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值