setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mInputChannel);
}
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outContentInsets,
InputChannel outInputChannel) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
outContentInsets, outInputChannel);
}
public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
Rect outContentInsets, InputChannel outInputChannel) {
win = new WindowState(this, session, client, token,
...
win.attach();
}
frameworks/base/services/java/com/android/server/wm/WindowState.java
void attach() {
mSession.windowAddedLocked();
}
void windowAddedLocked() {
if (mSurfaceSession == null) {
mSurfaceSession = new SurfaceSession();
mService.mSessions.add(this);
}
mNumWindow++;
}
/** Create a new connection with the surface flinger. */
public SurfaceSession() {
mNativeClient = nativeCreate();
}
frameworks/base/core/jni/android_view_SurfaceSession.cpp
static jint nativeCreate(JNIEnv* env, jclass clazz) {
SurfaceComposerClient* client = new SurfaceComposerClient();
client->incStrong(clazz);
return reinterpret_cast<jint>(client);
}
frameworks/native/libs/gui/SurfaceComposerClient.cpp
SurfaceComposerClient::SurfaceComposerClient() : mStatus(NO_INIT), mComposer(Composer::getInstance()) { } void SurfaceComposerClient::onFirstRef() { sp<ISurfaceComposer> sm(ComposerService::getComposerService()); if (sm != 0) { sp<ISurfaceComposerClient> conn = sm->createConnection(); if (conn != 0) { mClient = conn; mStatus = NO_ERROR; } } }
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
返回的是Client的ISurfaceComposerClient
sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() { sp<ISurfaceComposerClient> bclient; sp<Client> client(new Client(this)); // mFlinger(flinger), mNameGenerator(1) status_t err = client->initCheck(); // return NO_ERROR; if (err == NO_ERROR) { bclient = client; } return bclient; }
frameworks/base/core/java/android/view/ViewRootImpl.java
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility, boolean insetsPending) { int relayoutResult = mWindowSession.relayout( mWindow, mSeq, params, (int) (mView.getMeasuredWidth() * appScale + 0.5f), (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, mWinFrame, mPendingContentInsets, mPendingVisibleInsets, mPendingConfiguration, mSurface); }
frameworks/base/services/java/com/android/server/wm/Session.java
public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewFlags, int flags, Rect outFrame, Rect outContentInsets, Rect outVisibleInsets, Configuration outConfig, Surface outSurface) { int res = mService.relayoutWindow(this, window, seq, attrs, requestedWidth, requestedHeight, viewFlags, flags, outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface); return res; }
frameworks/base/services/java/com/android/server/wm/WindowManagerService.java
public int relayoutWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, int flags, Rect outFrame, Rect outContentInsets, Rect outVisibleInsets, Configuration outConfig, Surface outSurface) { }
............ 分析中。。
frameworks/base/core/java/android/view/Surface.java
frameworks/base/core/jni/android_view_Surface.cpp
在这里,Surface根据前面创建的SurfaceSession找到在SF端对应的Client对象。通过Client对象创建一个SurfaceControl并它保存在 gSurfaceClassInfo.mNativeSurfaceControl中。
static void nativeCreate(JNIEnv* env, jobject surfaceObj, jobject sessionObj, jstring nameStr, jint w, jint h, jint format, jint flags) { ... sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj)); sp<SurfaceControl> surface = client->createSurface String8(name.c_str()), w, h, format, flags); setSurfaceControl(env, surfaceObj, surface); }
frameworks/base/core/jni/android_view_SurfaceSession.cpp
Client对象保存在gSurfaceSessionClassInfo.mNativeClient中。
sp<SurfaceComposerClient> android_view_SurfaceSession_getClient(
JNIEnv* env, jobject surfaceSessionObj) {
return reinterpret_cast<SurfaceComposerClient*>(
env->GetIntField(surfaceSessionObj, gSurfaceSessionClassInfo.mNativeClient));
}
frameworks/native/libs/gui/SurfaceComposerClient.cpp
将mClient创建的ISurface包裹成一个SurfaceControl. 一个包含ISurface, ISurfaceComposerClient的对象。
sp<SurfaceControl> SurfaceComposerClient::createSurface( const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { sp<SurfaceControl> result; if (mStatus == NO_ERROR) { ISurfaceComposerClient::surface_data_t data; sp<ISurface> surface = mClient->createSurface(&data, name, w, h, format, flags); if (surface != 0) { result = new SurfaceControl(this, surface, data); } } return result; }
SurfaceControl::SurfaceControl( const sp<SurfaceComposerClient>& client, const sp<ISurface>& surface, const ISurfaceComposerClient::surface_data_t& data) : mClient(client), mSurface(surface), mToken(data.token), mIdentity(data.identity) { }
创建layer
sp<ISurface> Client::createSurface( ISurfaceComposerClient::surface_data_t* params, const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { class MessageCreateLayer : public MessageBase { ... sp<ISurface> getResult() const { return result; } virtual bool handler() { result = flinger->createLayer(params, name, client, w, h, format, flags); return true; } }; sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(), params, name, this, w, h, format, flags); mFlinger->postMessageSync(msg); return static_cast<MessageCreateLayer*>( msg.get() )->getResult(); }
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
创建Layer, 并将这个创建的Layer添加到Client的mLayers中。返回给客户端的是一个ISurface类型的BSurface. BSurface继承BnSurface.
sp<ISurface> SurfaceFlinger::createLayer( ISurfaceComposerClient::surface_data_t* params, const String8& name, const sp<Client>& client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { sp<LayerBaseClient> layer; sp<ISurface> surfaceHandle; switch (flags & ISurfaceComposerClient::eFXSurfaceMask) { case ISurfaceComposerClient::eFXSurfaceNormal: layer = createNormalLayer(client, w, h, flags, format); break; } if (layer != 0) { layer->initStates(w, h, flags); //set mCurrentState of layer in LayerBase, e.g. w, h, flags, sequence... layer->setName(name); ssize_t token = addClientLayer(client, layer);
surfaceHandle = layer->getSurface(); if (surfaceHandle != 0) { params->token = token; params->identity = layer->getIdentity(); } setTransactionFlags(eTransactionNeeded); } return surfaceHandle; }
sp<Layer> SurfaceFlinger::createNormalLayer( const sp<Client>& client, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format) { switch (format) { //PIXEL_FORMAT_RGBA_8888 or PIXEL_FORMAT_RGBX_8888 etc } sp<Layer> layer = new Layer(this, client); //上图显示Layer的继承关系 status_t err = layer->setBuffers(w, h, format, flags); return layer; }
frameworks/native/services/surfaceflinger/Layer.cpp
Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client)
: LayerBaseClient(flinger, client),
mTextureName(-1U),
mQueuedFrames(0),
mCurrentTransform(0),
mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
mCurrentOpacity(true),
mRefreshPending(false),
mFrameLatencyNeeded(false),
mFrameLatencyOffset(0),
mFormat(PIXEL_FORMAT_NONE),
mGLExtensions(GLExtensions::getInstance()),
mOpaqueLayer(true),
mSecure(false),
mProtectedByApp(false)
{
mCurrentCrop.makeInvalid();
glGenTextures(1, &mTextureName);
}
这里的SurfaceTexutreLayer继承BufferQueue,所以STL就相当于Layer的BufferQueue. 而且SurfaceTexture管理BufferQueue.
BufferQueue有个GrafficBufferAlloc.
void Layer::onFirstRef() { LayerBaseClient::onFirstRef(); struct FrameQueuedListener : public SurfaceTexture::FrameAvailableListener { FrameQueuedListener(Layer* layer) : mLayer(layer) { } private: wp<Layer> mLayer; virtual void onFrameAvailable() { sp<Layer> that(mLayer.promote()); if (that != 0) { that->onFrameQueued(); } } }; // Creates a custom BufferQueue for SurfaceTexture to use sp<BufferQueue> bq = new SurfaceTextureLayer(); //相当于BufferQueue mSurfaceTexture = new SurfaceTexture(mTextureName, true, GL_TEXTURE_EXTERNAL_OES, false, bq); mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0)); mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this)); mSurfaceTexture->setSynchronousMode(true); const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice()); //get PRIMARY DISPLAY stored in mDisplays[] updateTransformHint(hw); }
SurfaceTextureLayer::SurfaceTextureLayer() : BufferQueue(true) {//SurfaceTextureLayer is a BufferQueue
}frameworks/native/libs/gui/SurfaceTexture.cpp
SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode, GLenum texTarget, bool useFenceSync, const sp<BufferQueue> &bufferQueue) : ConsumerBase(bufferQueue == 0 ? new BufferQueue(allowSynchronousMode) : bufferQueue), mCurrentTransform(0), mCurrentTimestamp(0), mFilteringEnabled(true), mTexName(tex), #ifdef USE_FENCE_SYNC mUseFenceSync(useFenceSync), #else mUseFenceSync(false), #endif mTexTarget(texTarget), mEglDisplay(EGL_NO_DISPLAY), mEglContext(EGL_NO_CONTEXT), mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT), mAttached(true) { memcpy(mCurrentTransformMatrix, mtxIdentity, sizeof(mCurrentTransformMatrix)); mBufferQueue->setConsumerUsageBits(DEFAULT_USAGE_FLAGS); }
frameworks/native/libs/gui/BufferQueue.cpp
BufferQueue::BufferQueue(bool allowSynchronousMode, const sp<IGraphicBufferAlloc>& allocator) : mDefaultWidth(1), mDefaultHeight(1), mMaxAcquiredBufferCount(1), mDefaultMaxBufferCount(2), mOverrideMaxBufferCount(0), mSynchronousMode(false), mAllowSynchronousMode(allowSynchronousMode), mConnectedApi(NO_CONNECTED_API), mAbandoned(false), mFrameCounter(0), mBufferHasBeenQueued(false), mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888), mConsumerUsageBits(0), mTransformHint(0) { if (allocator == NULL) { sp<ISurfaceComposer> composer(ComposerService::getComposerService()); mGraphicBufferAlloc = composer->createGraphicBufferAlloc(); } else { mGraphicBufferAlloc = allocator; } }frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc() { sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc()); return gba; }
frameworks/native/services/surfaceflinger/GraphicBufferAlloc.cpp
GraphicBufferAlloc::GraphicBufferAlloc() { }
status_t Layer::setBuffers( uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { // this surfaces pixel format PixelFormatInfo info; status_t err = getPixelFormatInfo(format, &info); mFormat = format; mSecure = (flags & ISurfaceComposerClient::eSecure) ? true : false; mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false; mOpaqueLayer = (flags & ISurfaceComposerClient::eOpaque); mCurrentOpacity = getOpacityForFormat(format); mSurfaceTexture->setDefaultBufferSize(w, h); mSurfaceTexture->setDefaultBufferFormat(format); mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0)); return NO_ERROR; }
status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h) { Mutex::Autolock lock(mMutex); mDefaultWidth = w; mDefaultHeight = h; return mBufferQueue->setDefaultBufferSize(w, h); }
status_t BufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h)
{
Mutex::Autolock lock(mMutex);
mDefaultWidth = w;
mDefaultHeight = h;
return OK;
}
ssize_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<LayerBaseClient>& lbc) { // attach this layer to the client size_t name = client->attachLayer(lbc); // add this layer to the current state list Mutex::Autolock _l(mStateLock); mCurrentState.layersSortedByZ.add(lbc); return ssize_t(name); }
// protected by mLock DefaultKeyedVector< size_t, wp<LayerBaseClient> > mLayers;
size_t Client::attachLayer(const sp<LayerBaseClient>& layer) { Mutex::Autolock _l(mLock); size_t name = mNameGenerator++; mLayers.add(name, layer); return name; }
sp<ISurface> LayerBaseClient::getSurface() { sp<ISurface> s; Mutex::Autolock _l(mLock); mHasSurface = true; s = createSurface(); mClientSurfaceBinder = s->asBinder(); return s; }
sp<ISurface> LayerBaseClient::createSurface() { class BSurface : public BnSurface, public LayerCleaner { virtual sp<ISurfaceTexture> getSurfaceTexture() const { return 0; } public: BSurface(const sp<SurfaceFlinger>& flinger, const sp<LayerBaseClient>& layer) : LayerCleaner(flinger, layer) { } }; sp<ISurface> sur(new BSurface(mFlinger, this)); return sur; }
Surface.openTransaction(); ... surface.setSize(surface.getWidth(), surface.getHeight()); ... Surface.closeTransaction();
/** start a transaction @hide */
public static void openTransaction() {
nativeOpenTransaction();
}
/** @hide */
public void setSize(int w, int h) {
mWidth = w;
mHeight = h;
nativeSetSize(w, h);
}
public static void closeTransaction() {
nativeCloseTransaction();
}
static void nativeOpenTransaction(JNIEnv* env, jclass clazz) { SurfaceComposerClient::openGlobalTransaction(); } static void nativeSetSize(JNIEnv* env, jobject surfaceObj, jint w, jint h) { sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); if (surface == NULL) return; status_t err = surface->setSize(w, h); if (err < 0 && err != NO_INIT) { doThrowIAE(env); } } static void nativeCloseTransaction(JNIEnv* env, jclass clazz) { SurfaceComposerClient::closeGlobalTransaction(); }
static void nativeOpenTransaction(JNIEnv* env, jclass clazz) {
SurfaceComposerClient::openGlobalTransaction();
}
status_t SurfaceControl::setSize(uint32_t w, uint32_t h) { status_t err = validate(); if (err < 0) return err; const sp<SurfaceComposerClient>& client(mClient); return client->setSize(mToken, w, h); }
void SurfaceComposerClient::openGlobalTransaction() { // Currently a no-op }
status_t SurfaceComposerClient::setSize(SurfaceID id, uint32_t w, uint32_t h) {
return getComposer().setSize(this, id, w, h);
}
status_t Composer::setSize(const sp<SurfaceComposerClient>& client, SurfaceID id, uint32_t w, uint32_t h) { Mutex::Autolock _l(mLock); layer_state_t* s = getLayerStateLocked(client, id); if (!s) return BAD_INDEX; s->what |= layer_state_t::eSizeChanged; s->w = w; s->h = h; // Resizing a surface makes the transaction synchronous. mForceSynchronous = true; return NO_ERROR; }
layer_state_t* Composer::getLayerStateLocked( const sp<SurfaceComposerClient>& client, SurfaceID id) { ComposerState s; s.client = client->mClient; s.state.surface = id; ssize_t index = mComposerStates.indexOf(s); if (index < 0) { // we don't have it, add an initialized layer_state to our list index = mComposerStates.add(s); } ComposerState* const out = mComposerStates.editArray(); return &(out[index].state); }
void Composer::closeGlobalTransactionImpl(bool synchronous) { sp<ISurfaceComposer> sm(ComposerService::getComposerService()); Vector<ComposerState> transaction; Vector<DisplayState> displayTransaction; uint32_t flags = 0; { // scope for the lock Mutex::Autolock _l(mLock); transaction = mComposerStates; mComposerStates.clear(); displayTransaction = mDisplayStates; mDisplayStates.clear(); ... } sm->setTransactionState(transaction, displayTransaction, flags); }
void SurfaceFlinger::setTransactionState( const Vector<ComposerState>& state, const Vector<DisplayState>& displays, uint32_t flags) { Mutex::Autolock _l(mStateLock); size_t count = displays.size(); for (size_t i=0 ; i<count ; i++) { const DisplayState& s(displays[i]); transactionFlags |= setDisplayStateLocked(s); }
count = state.size();
for (size_t i=0 ; i<count ; i++) {
const ComposerState& s(state[i]);
if (s.client != NULL) {
sp<IBinder> binder = s.client->asBinder();
if (binder != NULL) {
String16 desc(binder->getInterfaceDescriptor());
if (desc == ISurfaceComposerClient::descriptor) {
sp<Client> client( static_cast<Client *>(s.client.get()) );
//返回flags |= eTraversalNeeded; transactionFlags |= setClientStateLocked(client, s.state); } } } } if (transactionFlags) { // this triggers the transaction setTransactionFlags(transactionFlags); ... while (mTransactionPending) { status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5)); if (CC_UNLIKELY(err != NO_ERROR)) { // just in case something goes wrong in SF, return to the // called after a few seconds. ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!"); mTransactionPending = false; break; } }
} }
uint32_t SurfaceFlinger::setClientStateLocked( const sp<Client>& client, const layer_state_t& s) { uint32_t flags = 0; sp<LayerBaseClient> layer(client->getLayerUser(s.surface)); if (layer != 0) { const uint32_t what = s.what; ... if (what & layer_state_t::eSizeChanged) { if (layer->setSize(s.w, s.h)) { flags |= eTraversalNeeded; } } ... } return flags; }
setTransactionFlags() 给SurfaceFlinger的mTransactionFlags添加eTraversalNeeded标志位。如果mTransactionFlags之前没有被设过这个标志位的话,wake ther server up by signalTransaction()
uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) { uint32_t old = android_atomic_or(flags, &mTransactionFlags); //更新mTransactionFlags变量, 返回mTransactionFlags在执行android_atomic_or(flags, &mTransactionFlags)之前的值。 if ((old & flags)==0) { // wake the server up signalTransaction(); } return old; }
bool LayerBase::setSize(uint32_t w, uint32_t h) { if (mCurrentState.requested.w == w && mCurrentState.requested.h == h) return false; mCurrentState.requested.w = w; mCurrentState.requested.h = h; requestTransaction(); return true; }
bool LayerBase::requestTransaction() { int32_t old = setTransactionFlags(eTransactionNeeded); return ((old & eTransactionNeeded) == 0); } uint32_t LayerBase::setTransactionFlags(uint32_t flags) { return android_atomic_or(flags, &mTransactionFlags); //mTransactionFlags变量添加eTransactionNeeded标志位 }frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::signalTransaction() {
mEventQueue.invalidate();
}
// start the EventThread mEventThread = new EventThread(this); mEventQueue.setEventThread(mEventThread);
void MessageQueue::init(const sp<SurfaceFlinger>& flinger) { mFlinger = flinger; mLooper = new Looper(true); mHandler = new Handler(*this); } void MessageQueue::setEventThread(const sp<EventThread>& eventThread) { mEventThread = eventThread; mEvents = eventThread->createEventConnection(); // mEventTube = mEvents->getDataChannel(); mLooper->addFd(mEventTube->getFd(), 0, ALOOPER_EVENT_INPUT, MessageQueue::cb_eventReceiver, this); }
/* when INVALIDATE_ON_VSYNC is set, SF only processes * buffer updates on VSYNC and performs a refresh immediately * after. * * when INVALIDATE_ON_VSYNC is set to false, SF will instead * perform the buffer updates immediately, but the refresh only * at the next VSYNC. * THIS MODE IS BUGGY ON GALAXY NEXUS AND WILL CAUSE HANGS */ #define INVALIDATE_ON_VSYNC 1 void MessageQueue::invalidate() { #if INVALIDATE_ON_VSYNC mEvents->requestNextVsync(); #else mHandler->dispatchInvalidate(); #endif }
EventThread::EventThread(const sp<SurfaceFlinger>& flinger) : mFlinger(flinger), mLastVSyncTimestamp(0), mUseSoftwareVSync(false), mLastVSyncDisplayType(-1), mDebugVsyncEnabled(false), mVsyncDisabled(false){ for (int32_t i=0 ; i<HWC_DISPLAY_TYPES_SUPPORTED ; i++) { mVSyncEvent[i].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; mVSyncEvent[i].header.id = 0; mVSyncEvent[i].header.timestamp = 0; mVSyncEvent[i].vsync.count = 0; } } void EventThread::onFirstRef() { ... run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); }
sp<EventThread::Connection> EventThread::createEventConnection() const { return new Connection(const_cast<EventThread*>(this)); }
EventThread::Connection::Connection( const sp<EventThread>& eventThread) : count(-1), mEventThread(eventThread), mChannel(new BitTube()), mLastRequestTimestamp(0) { } void EventThread::Connection::onFirstRef() { // NOTE: mEventThread doesn't hold a strong reference on us mEventThread->registerDisplayEventConnection(this); }
status_t EventThread::registerDisplayEventConnection( const sp<EventThread::Connection>& connection) { Mutex::Autolock _l(mLock);mDisplayEventConnections.add(connection);
mCondition.broadcast();
return NO_ERROR;
}
BitTube::BitTube() : mSendFd(-1), mReceiveFd(-1) { int sockets[2]; if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) { int size = SOCKET_BUFFER_SIZE; setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)); setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)); setsockopt(sockets[1], 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)); } }
void EventThread::Connection::requestNextVsync() { mEventThread->requestNextVsync(this); }
void EventThread::requestNextVsync( const sp<EventThread::Connection>& connection) { Mutex::Autolock _l(mLock); if (connection->count < 0) { connection->count = 0; connection->mLastRequestTimestamp = systemTime(CLOCK_MONOTONIC); if(Connection::s_oldestUnreponsedRequestTimestamp == 0) {
//这个时间戳会在waitForEvent()时判断VSYNC是否超时 Connection::s_oldestUnreponsedRequestTimestamp = connection->mLastRequestTimestamp; } if (mVsyncDisabled) { // FIXME: how do we decide which display id the fake // vsync came from ? mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; mVSyncEvent[0].header.id = HWC_DISPLAY_PRIMARY; mVSyncEvent[0].header.timestamp = systemTime(SYSTEM_TIME_MONOTONIC); mVSyncEvent[0].vsync.count++; } mCondition.broadcast(); //触发等待中的mCondition.wait; } }
bool EventThread::threadLoop() { DisplayEventReceiver::Event event; Vector< sp<EventThread::Connection> > signalConnections; signalConnections = waitForEvent(&event); // dispatch events to listeners... const size_t count = signalConnections.size(); for (size_t i=0 ; i<count ; i++) { const sp<Connection>& conn(signalConnections[i]); // now see if we still need to report this event status_t err = conn->postEvent(event); if (err == -EAGAIN || err == -EWOULDBLOCK) { // The destination doesn't accept events anymore, it's probably // full. For now, we just drop the events on the floor. // FIXME: Note that some events cannot be dropped and would have // to be re-sent later. // Right-now we don't have the ability to do this. ALOGW("EventThread: dropping event (%08x) for connection %p", event.header.type, conn.get()); } else if (err < 0) { // handle any other error on the pipe as fatal. the only // reasonable thing to do is to clean-up this connection. // The most common error we'll get here is -EPIPE. removeDisplayEventConnection(signalConnections[i]); } } return true; }
// This will return when (1) a vsync event has been received, and (2) there was // at least one connection interested in receiving it when we started waiting. Vector< sp<EventThread::Connection> > EventThread::waitForEvent( DisplayEventReceiver::Event* event) { Mutex::Autolock _l(mLock); Vector< sp<EventThread::Connection> > signalConnections; nsecs_t currentVSyncTimestamp = 0; int currentVSyncDisplayType = -1; do { bool eventPending = false; bool waitForVSync = false; size_t vsyncCount = 0; nsecs_t timestamp = 0; for (int32_t i=0 ; i<HWC_DISPLAY_TYPES_SUPPORTED ; i++) { timestamp = mVSyncEvent[i].header.timestamp; if (timestamp) {
//把当前Vsync event的时间戳赋给currentVSyncTimestamp, 并把mVSyncEvent[i]的时间戳清零。 // we have a vsync event to dispatch currentVSyncTimestamp = timestamp; currentVSyncDisplayType = i; *event = mVSyncEvent[i]; mVSyncEvent[i].header.timestamp = 0; vsyncCount = mVSyncEvent[i].vsync.count; break; } } ... // find out connections waiting for events size_t count = mDisplayEventConnections.size(); for (size_t i=0 ; i<count ; i++) { sp<Connection> connection(mDisplayEventConnections[i].promote()); if (connection != NULL) { bool added = false;
//connection->count的值在EventThread::requestNextVsync中从初始时的-1变成0 if (connection->count >= 0) { // we need vsync events because at least // one connection is waiting for it waitForVSync = true; if (timestamp) { // we consume the event only if it's time // (ie: we received a vsync event)
// if (connection->count == 0) { // fired this time around connection->count = -1; signalConnections.add(connection); added = true; } else if (connection->count == 1 || (vsyncCount % connection->count) == 0) { // continuous event, and time to report it signalConnections.add(connection); added = true; } } } if (eventPending && !timestamp && !added) { // we don't have a vsync event to process // (timestamp==0), but we have some pending // messages. signalConnections.add(connection); } } else { // we couldn't promote this reference, the connection has // died, so clean-up! mDisplayEventConnections.removeAt(i); --i; --count; } } // Here we figure out if we need to enable or disable vsyncs if (timestamp && !waitForVSync) { // we received a VSYNC but we have no clients // don't report it, and disable VSYNC events disableVSyncLocked(); } else if (!timestamp && waitForVSync) { // we have at least one client, so we want vsync enabled // (TODO: this function is called right after we finish // notifying clients of a vsync, so this call will be made // at the vsync rate, e.g. 60fps. If we can accurately // track the current state we could avoid making this call // so often.) enableVSyncLocked(); } // note: !timestamp implies signalConnections.isEmpty(), because we // don't populate signalConnections if there's no vsync pending if (!timestamp && !eventPending) { // wait for something to happen if (waitForVSync) { // This is where we spend most of our time, waiting // for vsync events and new client registrations. // // If the screen is off, we can't use h/w vsync, so we // use a 16ms timeout instead. It doesn't need to be // precise, we just need to keep feeding our clients. // // We don't want to stall if there's a driver bug, so we // use a (long) timeout when waiting for h/w vsync, and // generate fake events when necessary. bool softwareSync = mUseSoftwareVSync; nsecs_t timeout = softwareSync ? ms2ns(16) : ms2ns(1000); if (mCondition.waitRelative(mLock, timeout) == TIMED_OUT) { if (!softwareSync) { ALOGW("Timed out waiting for hw vsync; faking it"); } // FIXME: how do we decide which display id the fake // vsync came from ? mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; mVSyncEvent[0].header.id = HWC_DISPLAY_PRIMARY; mVSyncEvent[0].header.timestamp = systemTime(SYSTEM_TIME_MONOTONIC); mVSyncEvent[0].vsync.count++; } } else { // Nobody is interested in vsync, so we just want to sleep. // h/w vsync should be disabled, so this will wait until we // get a new connection, or an existing connection becomes // interested in receiving vsync again. mCondition.wait(mLock); } } } while (signalConnections.isEmpty()); mLastVSyncTimestamp = currentVSyncTimestamp; mLastVSyncDisplayType = currentVSyncDisplayType;
//如果Vsync时间超出100ms, 就报warning. //take care are only single shot request mode if(Connection::s_oldestUnreponsedRequestTimestamp != 0){ const nsecs_t VSYNC_WARNING_THRESHOLD = 100000000; //100ms nsecs_t syncResponseinterval = systemTime(CLOCK_MONOTONIC) - Connection::s_oldestUnreponsedRequestTimestamp; if( syncResponseinterval > VSYNC_WARNING_THRESHOLD ){ ALOGW(" warning! VSYNC take %lld ms to deliver!" ,syncResponseinterval/1000000); } Connection::s_oldestUnreponsedRequestTimestamp = 0; } // here we're guaranteed to have a timestamp and some connections to signal // (The connections might have dropped out of mDisplayEventConnections // while we were asleep, but we'll still have strong references to them.) return signalConnections; }
status_t EventThread::Connection::postEvent( const DisplayEventReceiver::Event& event) { ssize_t size = DisplayEventReceiver::sendEvents(mChannel, &event, 1); return size < 0 ? status_t(size) : status_t(NO_ERROR); }
ssize_t DisplayEventReceiver::sendEvents(const sp<BitTube>& dataChannel, Event const* events, size_t count) { return BitTube::sendObjects(dataChannel, events, count); }
ssize_t BitTube::sendObjects(const sp<BitTube>& tube,
void const* events, size_t count, size_t objSize)
{
ssize_t numObjects = 0;
for (size_t i=0 ; i<count ; i++) {
const char* vaddr = reinterpret_cast<const char*>(events) + objSize * i;
ssize_t size = tube->write(vaddr, objSize);
if (size < 0) {
// error occurred
return size;
} else if (size == 0) {
// no more space
break;
}
numObjects++;
}
return numObjects;
}
ssize_t BitTube::write(void const* vaddr, size_t size) { ssize_t err, len; do { len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL); err = len < 0 ? errno : 0; } while (err == EINTR); return err == 0 ? len : -err; }