上一篇文章我們分析了UI刷新機制,知道了Android UI刷新是在接收到Vsync信號之後才進行的,接着我準備繼續分析Vsync如何向native層註冊以及native層如何將Vsync發到上層,這部分比較複雜,我準備分兩篇文章來分析,主要就是兩個native函數:nativeInit和nativeScheduleVsync
根據上一篇文章,我們知道每當UI請求重繪時會調用Choreographer中的DisplayEventReceiver類的nativeScheduleVsync向native層註冊監聽Vsync,並且當下一個Vsync到來時會回調DisplayEventReceiver的onVsync方法,可以看出來DisplayEventReceiver這個類就是處理Vsync相關的核心
我們就從DisplayEventReceiver的創建開始分析,DisplayEventReceiver是個抽象類,它的實現類FrameDisplayEventReceiver在Choreographer的構造方法中初始化的
Choreographer
private Choreographer(Looper looper, int vsyncSource) {
//UI線程的looper
mLooper = looper;
mHandler = new FrameHandler(looper);
//USE_VSYNC爲true,使用VSYNC
mDisplayEventReceiver = USE_VSYNC
? new FrameDisplayEventReceiver(looper, vsyncSource)
: null;
mLastFrameTimeNanos = Long.MIN_VALUE;
//Android默認60FPS,mFrameIntervalNanos爲16.6
mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());
mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
for (int i = 0; i <= CALLBACK_LAST; i++) {
mCallbackQueues[i] = new CallbackQueue();
}
// b/68769804: For low FPS experiments.
setFPSDivisor(SystemProperties.getInt(ThreadedRenderer.DEBUG_FPS_DIVISOR, 1));
}
Choreographer構造中做一些重要的初始化工作,我們這裏注意一下vsyncSource這個值
DisplayEventReceiver中定義瞭如下兩個常量,代表VSYNC的兩種使用,APP和SurfaceFlinger,這裏傳遞到native層的是VSYNC_SOURCE_APP這種,即APP層請求的VSYNC
/**
* When retrieving vsync events, this specifies that the vsync event should happen at the normal
* vsync-app tick.
* <p>
* Needs to be kept in sync with frameworks/native/include/gui/ISurfaceComposer.h
*/
public static final int VSYNC_SOURCE_APP = 0;
/**
* When retrieving vsync events, this specifies that the vsync event should happen whenever
* Surface Flinger is processing a frame.
* <p>
* Needs to be kept in sync with frameworks/native/include/gui/ISurfaceComposer.h
*/
public static final int VSYNC_SOURCE_SURFACE_FLINGER = 1;
FrameDisplayEventReceiver的構造方法中顯式調用了父類DisplayEventReceiver的構造方法:
public DisplayEventReceiver(Looper looper, int vsyncSource) {
if (looper == null) {
throw new IllegalArgumentException("looper must not be null");
}
mMessageQueue = looper.getQueue();
mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue,
vsyncSource);
mCloseGuard.open("dispose");
}
調用nativeInit,將主線程的MessageQueue傳遞了過去
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
jobject messageQueueObj, jint vsyncSource) {
//根據java層messageQueue的到native層messageQueue
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
if (messageQueue == NULL) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
}
//步驟1
sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
receiverWeak, messageQueue, vsyncSource);
//步驟2
status_t status = receiver->initialize();
if (status) {
String8 message;
message.appendFormat("Failed to initialize display event receiver. status=%d", status);
jniThrowRuntimeException(env, message.string());
return 0;
}
receiver->incStrong(gDisplayEventReceiverClassInfo.clazz); // retain a reference for the object
return reinterpret_cast<jlong>(receiver.get());
}
這個方法重點就兩部分,步驟1:創建NativeDisplayEventReceiver,步驟2:調用其initialize方法
我們首先看步驟1:
NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env,
jobject receiverWeak, const sp<MessageQueue>& messageQueue, jint vsyncSource) :
DisplayEventDispatcher(messageQueue->getLooper(),
static_cast<ISurfaceComposer::VsyncSource>(vsyncSource)),
mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
mMessageQueue(messageQueue) {
ALOGV("receiver %p ~ Initializing display event receiver.", this);
}
NativeDisplayEventReceiver構造方法中調用了父類DisplayEventDispatcher的構造方法,並且將java層傳遞下來的VSYNC_SOURCE_APP強轉爲了ISurfaceComposer::VsyncSource傳遞給了DisplayEventDispatcher,
VsyncSource是枚舉類型,VSYNC_SOURCE_APP爲0,所以就相當於強轉爲了eVsyncSourceApp,代表由APP層請求的Vsync
class ISurfaceComposer: public IInterface {
...
enum VsyncSource {
eVsyncSourceApp = 0,
eVsyncSourceSurfaceFlinger = 1
};
...
}
我們看DisplayEventDispatcher構造方法中將vsyncSource賦值給了mReceiver
DisplayEventDispatcher::DisplayEventDispatcher(const sp<Looper>& looper,
ISurfaceComposer::VsyncSource vsyncSource) :
mLooper(looper), mReceiver(vsyncSource), mWaitingForVsync(false) {
ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
}
mReceiver是DisplayEventReceiver類型,這裏相當與調用DisplayEventReceiver的構造函數進行初始化
DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource) {
//步驟1
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
if (sf != nullptr) {
//步驟2
mEventConnection = sf->createDisplayEventConnection(vsyncSource);
if (mEventConnection != nullptr) {
//步驟3
mDataChannel = std::make_unique<gui::BitTube>();
//步驟4
mEventConnection->stealReceiveChannel(mDataChannel.get());
}
}
}
DisplayEventReceiver的構造函數做的事情非常重要,且比較複雜,主要是建立應用層與SurfaceFlinger的連接,這裏分爲四個步驟來分析
步驟1:獲取SurfaceFlinger服務
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
ComposerService::getComposerService()
/*static*/ sp<ISurfaceComposer> ComposerService::getComposerService() {
ComposerService& instance = ComposerService::getInstance();
Mutex::Autolock _l(instance.mLock);
if (instance.mComposerService == nullptr) {
ComposerService::getInstance().connectLocked();
assert(instance.mComposerService != nullptr);
ALOGD("ComposerService reconnected");
}
return instance.mComposerService;
}
這個函數定義在SurfaceComposerClient.cpp中,這個函數中調用了ComposerService的connectLocked函數
connectLocked
void ComposerService::connectLocked() {
const String16 name("SurfaceFlinger");
while (getService(name, &mComposerService) != NO_ERROR) {
usleep(250000);
}
assert(mComposerService != nullptr);
// 創建死亡回調
......
}
connectLocked函數的作用很簡單,獲取SurfaceFlinger服務,保存在ComposerService的mComposerService中,其實獲取的是SurfaceFlinger的Bp端BpSurfaceComposer,SurfaceFlinger的是它的Bn端BnSurfaceComposer的子類
接着看步驟2:通過Binder實現跨進程調用,最終到SurfaceFlinger中,
mEventConnection = sf->createDisplayEventConnection(vsyncSource);
createDisplayEventConnection
virtual sp<IDisplayEventConnection> createDisplayEventConnection(VsyncSource vsyncSource)
{
.....
err = remote()->transact(
BnSurfaceComposer::CREATE_DISPLAY_EVENT_CONNECTION,
data, &reply);
......
lt = interface_cast<IDisplayEventConnection>(reply.readStrongBinder());
return result;
}
需要注意最終從SurfaceFlinger返回的也是EventThreadConnection的Bp端BpDisplayEventConnection,EventThreadConnection繼承自BnDisplayEventConnection
好了,來看SurfaceFlinger的createDisplayEventConnection函數,傳遞的參數是eVsyncSourceApp = 0,應用層請求的Vsync
mEventConnection = sf->createDisplayEventConnection(vsyncSource);
createDisplayEventConnection
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
ISurfaceComposer::VsyncSource vsyncSource) {
auto resyncCallback = mScheduler->makeResyncCallback([this] {
Mutex::Autolock lock(mStateLock);
return getVsyncPeriod();
});
const auto& handle =
vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle;
return mScheduler->createDisplayEventConnection(handle, std::move(resyncCallback));
}
這個函數我們首先來看mScheduler->makeResyncCallback,mScheduler是Scheduler類型,在SurfaceFlinger的init中創建的,這裏會創建一個resyncCallback,類型爲ResyncCallback,定義在EventThread.cpp中,std::function這是個新API
using ResyncCallback = std::function<void()>;
大致功能是將一段可執行代碼封裝到ResyncCallback中,僅從功能上看,和函數指針作用類似
ResyncCallback Scheduler::makeResyncCallback(GetVsyncPeriod&& getVsyncPeriod) {
std::weak_ptr<VsyncState> ptr = mPrimaryVsyncState;
return [ptr, getVsyncPeriod = std::move(getVsyncPeriod)]() {
if (const auto vsync = ptr.lock()) {
vsync->resync(getVsyncPeriod);
}
};
}
接着得到handle的類型,因爲一開始傳遞的就是App請求的Vsync,所以handle爲mAppConnectionHandle,它的類型爲sp<Scheduler::ConnectionHandle> mAppConnectionHandle;看名字這是用來處理Vsync到APP的連接的,它也是在SurfaceFlinger的init中創建的,我們來大概看看它的創建:
void SurfaceFlinger::init() {
......
mScheduler =
getFactory().createScheduler([this](bool enabled) { setPrimaryVsyncEnabled(enabled); },
mRefreshRateConfigs);
auto resyncCallback =
mScheduler->makeResyncCallback(std::bind(&SurfaceFlinger::getVsyncPeriod, this));
mAppConnectionHandle =
mScheduler->createConnection("app", mPhaseOffsets->getCurrentAppOffset(),
resyncCallback,
impl::EventThread::InterceptVSyncsCallback());
......
}
調用mScheduler的createConnection函數創建的,它的名字是"app",
createConnection
sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
const char* connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback,
impl::EventThread::InterceptVSyncsCallback interceptCallback) {
//id從0累加
const int64_t id = sNextId++;
ALOGV("Creating a connection handle with ID: %" PRId64 "\n", id);
//創建對應connectionName名字的EventThread
std::unique_ptr<EventThread> eventThread =
makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs,
std::move(interceptCallback));
//創建EventThreadConnection
auto eventThreadConnection =
createConnectionInternal(eventThread.get(), std::move(resyncCallback));
//創建ConnectionHandle,與id對應
mConnections.emplace(id,
std::make_unique<Connection>(new ConnectionHandle(id),
eventThreadConnection,
std::move(eventThread)));
//返回”app“的ConnectionHandle
return mConnections[id]->handle;
}
createConnection這個函數在SurfaceFlinger中調用了兩次,一次是創建"app"的Connection,一次是創建"sf"的Connection,我們可以理解爲創建兩套連接,一套給app使用,一套個surfaceFlinger使用,兩套連接的用connectionName以及id進行標識,(id爲0,connectionName等於”app“的)與(id爲1,connectionName等於”sf“的)
createConnection函數根據connectionName創建EventThread,根據EventThread創建EventThreadConnection,然後創建ConnectionHandle,根據ConnectionHandle,EventThreadConnection,EventThread最終創建Connection,並以id爲key,Connection爲value加入到mConnections的map中,最終返回”app“的ConnectionHandle,這些類的創建肯定初始化了很多重要過程,我們這裏不去一一分析,只要知道後面用的時候有創建過這些類
mAppConnectionHandle的創建過程我們大致看了下,知道了這是一個”app“的ConnectionHandle,
接着我們繼續看:mScheduler->createDisplayEventConnection(handle, std::move(resyncCallback));
sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
const sp<Scheduler::ConnectionHandle>& handle, ResyncCallback resyncCallback) {
RETURN_VALUE_IF_INVALID(nullptr);
return createConnectionInternal(mConnections[handle->id]->thread.get(),
std::move(resyncCallback));
}
調用createConnectionInternal,handle->id用於標識這套連接是app還是surfaceFlinger
createConnectionInternal
sp<EventThreadConnection> Scheduler::createConnectionInternal(EventThread* eventThread,
ResyncCallback&& resyncCallback) {
return eventThread->createEventConnection(std::move(resyncCallback));
}
調用EventThread的createEventConnection函數
createEventConnection
sp<EventThreadConnection> EventThread::createEventConnection(ResyncCallback resyncCallback) const {
return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback));
}
創建了一個EventThreadConnection對象,看下它的構造函數
EventThreadConnection::EventThreadConnection(EventThread* eventThread,
ResyncCallback resyncCallback)
: resyncCallback(std::move(resyncCallback)),
mEventThread(eventThread),
mChannel(gui::BitTube::DefaultSize) {}
構造函數中最重要的就是創建了mChannel,mChannel是gui::BitTube類型
接着看gui::BitTube的構造函數:這裏傳遞的DefaultSize爲4kb,
定義在BitTube.h中:
// creates a BitTube with a default (4KB) send buffer
struct DefaultSizeType {};
static constexpr DefaultSizeType DefaultSize{};
BitTube::BitTube(size_t bufsize) {
init(bufsize, bufsize);
}
init
void BitTube::init(size_t rcvbuf, size_t sndbuf) {
int sockets[2];
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));
// since 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.reset(sockets[0]);
mSendFd.reset(sockets[1]);
} else {
mReceiveFd.reset();
ALOGE("BitTube: pipe creation failed (%s)", strerror(errno));
}
}
init函數主要是通過socketpair函數創建一對socket
socketpair()函數用於創建一對無名的、相互連接的socket
如果成功,則返回0,創建好的socket分別是sv[0]和sv[1];否則返回-1
- 這對socket可以用於全雙工通信,每一個socket既可以讀也可以寫。例如,可以往sv[0]中寫,從sv[1]中讀,或者從sv[1]中寫,從sv[0]中讀。
- 如果往一個socket(如sv[0])中寫入後,再從該socket讀時會阻塞,只能在另一個socket中(sv[1])上讀成功;
- 讀、寫操作可以位於同一個進程,也可以分別位於不同的進程。
通過socketpair創建好了一對socket之後,再通過setsockopt對socket進行設置,再調用fcntl函數針對socket描述符提供控制,不用管具體幹嘛的,
最後我們看mReceiveFd.reset(sockets[0]),mSendFd.reset(sockets[1]);建立Fd與socket的關聯,很明顯這一對sockets一個用來接受消息,一個用來發送消息,到這裏我們可以猜測,Vsync到來的時候通過mSendFd寫入消息,然後app監聽mReceiveFd接受消息,就完成了app對Vsync的接收,需要注意一點,此時的mReceiveFd依然還在SurfaceFlinger進程,app端要使用肯定是需要回傳回去的,但是步驟2的調用已經結束,沒看到那裏返回mReceiveFd的,那麼我們接着往後分析看看
我們總結一下步驟2:
mEventConnection = sf->createDisplayEventConnection(vsyncSource);
步驟2其實就是根據vsyncSource,得到此Vsync請求來自app,然後創建一套app的連接,其實最終就是創建一對socket用來進行進程間通信,類似的還有Input系統,也是通過一對socket來連接app和InputDispatcher
我們接着之前分了四個步驟的代碼進行分析:
DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource) {
//步驟1 獲取SurfaceFlinger服務
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
if (sf != nullptr) {
//步驟2 創建一對socket連接
mEventConnection = sf->createDisplayEventConnection(vsyncSource);
if (mEventConnection != nullptr) {
//步驟3 獲得gui::BitTube對象
mDataChannel = std::make_unique<gui::BitTube>();
//步驟4
mEventConnection->stealReceiveChannel(mDataChannel.get());
}
}
}
我們已經分析完了步驟1,步驟2,步驟3比較簡單,就是獲得gui::BitTube對象,來看步驟4:
mEventConnection->stealReceiveChannel(mDataChannel.get());
我們步驟2分析過mEventConnection是從SurfaceFlinger返回的Binder Bp端,BpDisplayEventConnection,那麼先看看Bp端的調用
stealReceiveChannel
class BpDisplayEventConnection : public SafeBpInterface<IDisplayEventConnection> {
public:
......
status_t stealReceiveChannel(gui::BitTube* outChannel) override {
return callRemote<decltype(
&IDisplayEventConnection::stealReceiveChannel)>(Tag::STEAL_RECEIVE_CHANNEL,
outChannel);
}
}
這個方法裏面的語法我不太清楚,但既然是Binder通信,最終一定是調到BnDisplayEventConnection中去了,Tag爲STEAL_RECEIVE_CHANNEL,類似Binder的code,用來找對應方法的,我們來看看Bn端的具體實現:
status_t EventThreadConnection::stealReceiveChannel(gui::BitTube* outChannel) {
outChannel->setReceiveFd(mChannel.moveReceiveFd());
return NO_ERROR;
}
mChannel保存的是gui::BitTube
base::unique_fd BitTube::moveReceiveFd() {
return std::move(mReceiveFd);
}
void BitTube::setReceiveFd(base::unique_fd&& receiveFd) {
mReceiveFd = std::move(receiveFd);
}
所以stealReceiveChannel就等價於
outChannel.mReceiveFd = mChannel.mReceiveFd
這什麼意思呢?其實就相當於將步驟2在surfaceFlinger進程中創建的mReceiveFd傳遞到app進程中去,app進程有了mReceiveFd,surfaceFlinger進程有了mSendFd就能夠實現通信了
到此我們已經分析完了DisplayEventReceiver構造函數中的四個步驟,把代碼再貼出來看下
DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource) {
//步驟1
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
if (sf != nullptr) {
//步驟2
mEventConnection = sf->createDisplayEventConnection(vsyncSource);
if (mEventConnection != nullptr) {
//步驟3
mDataChannel = std::make_unique<gui::BitTube>();
//步驟4
mEventConnection->stealReceiveChannel(mDataChannel.get());
}
}
}
我們對這四個步驟進行總結:
- 獲取surfaceFlinger的Bp端,以便與surfaceFlinger進行Binder通信
- 獲取EventThread::EventThreadConnection的Bp端,在創建EventThread::EventThreadConnection又創建了gui::BitTube對象,在gui::BitTube的init函數中創建了一對socket,並建立mReceiveFd,mSendFd和socket的關聯,以便在監聽mReceiveFd時能夠收到mSendFd寫入的消息
- 在app端創建一個gui::BitTube
- 通過stealReceiveChannel函數將app端的gui::BitTube傳遞到surfaceFlinger進程,目的是將surfaceFlinger進程的mReceiveFd傳遞到app端
到現在爲止我們僅僅分析了最開始的nativeInit函數的步驟1
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
......
//步驟1
sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
receiverWeak, messageQueue, vsyncSource);
//步驟2
status_t status = receiver->initialize();
......
return reinterpret_cast<jlong>(receiver.get());
}
我們接這來看看步驟2:receiver->initialize,它的實現在DisplayEventDispatcher中:
initialize
status_t DisplayEventDispatcher::initialize() {
//檢查mReceiver是否異常
status_t result = mReceiver.initCheck();
...
int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT,
this, NULL);
if (rc < 0) {
return UNKNOWN_ERROR;
}
return OK;
}
這個函數就比較簡單了,調用Looper的addFd將我們前面得到的mReceiveFd添加到Handler進行監聽,關於Handler的native層的消息機制可以參考我以前分析過的AndroidQ Handler消息機制(native層),我們這裏就大概說一下,Handler消息機制可以處理三種消息,java層msg,native層msg,以及通過addFd創建的request,request中包含監聽的fd以及收到消息時的回調handleEvent
所以這裏監聽了mReceiveFd之後,當mSendFd寫入數據時就能收到消息,並回調DisplayEventDispatcher的handleEvent函數
限於篇幅,這篇文章就分析到這裏,主要就是分析了nativeInit這一個native的函數