基于Android5.1的双屏异显分析

平台:android5.1 
场景:客户的设备需要使用到双屏异显。分析双屏异显时,framework所做的准备。 
时间:2016.9.28

Android从4.2开始支持双屏异显,其Java使用示例代码如下:

1.如何获取设备上的屏幕?

DisplayManager  mDisplayManager;//屏幕管理类
    Display[]  displays;//屏幕数组
    mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
    displays =mDisplayManager.getDisplays();

2.主屏和副屏的区分? 
主屏:displays[0] 
副屏:displays[1]

3.如何在副屏上展示内容? 
通过Presentation来实现,Presentation继承了Dialog。 
假设我们写了一个DifferentDislay的类,这个类是要继承Presentation类:

privateclass DifferentDislay extends Presentation{
        public DifferentDislay(ContextouterContext, Display display) {
            super(outerContext,display);
            //TODOAuto-generated constructor stub 
        }
        @Override
        protectedvoid onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.diffrentdisplay_basket);
        }
    }

4.开启副屏

DifferentDislay  mPresentation =new DifferentDislay (context,displays[1]);//displays[1]是副屏
                     mPresentation.getWindow().setType(WindowManager.LayoutParams.TYPE_TOAST);
    mPresentation.show();

以上代码的核心在于Presentation类,其继承与Dialog。 
从new DifferentDislay (context,displays[1]) 函数分析其初始化:

public Presentation(Context outerContext, Display display, int theme) {
        super(createPresentationContext(outerContext, display, theme), theme, false);      //核心函数

        mDisplay = display;
        mDisplayManager = (DisplayManager)getContext().getSystemService(Context.DISPLAY_SERVICE);

        getWindow().setGravity(Gravity.FILL);
        setCanceledOnTouchOutside(false);
    }
private static Context createPresentationContext(
            Context outerContext, Display display, int theme) {
...
          Context displayContext = outerContext.createDisplayContext(display);
...
        // Derive the display's window manager from the outer window manager.
        // We do this because the outer window manager have some extra information
        // such as the parent window, which is important if the presentation uses
        // an application window type.
        final WindowManagerImpl outerWindowManager =
                (WindowManagerImpl)outerContext.getSystemService(Context.WINDOW_SERVICE);
        final WindowManagerImpl displayWindowManager =
                outerWindowManager.createPresentationWindowManager(display);     //针对特定的display创建对应的WindowManagerImpl管理对象
        return new ContextThemeWrapper(displayContext, theme) {               //返回的Context的getSystemService()被重载,通过此Context获取的Window管理对象为上面创建的这个
            @Override
            public Object getSystemService(String name) {
                if (Context.WINDOW_SERVICE.equals(name)) {
                    return displayWindowManager;
                }
                return super.getSystemService(name);
            }
        };
}

上面代码的设计原则: 
每一个display拥有自己的管理对象以及context对象,这样双屏的操作互相独立—Display是核心对象。对于上层而言,其即意味着一个屏幕。 
mPresentation.show()拉开了双屏异显的序幕。结合上面的分析,WindowManagerImpl.java中的addView()方法将传入上面初始化的display[1],继而:

WindowManagerGlobal.java
    public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
...
     root = new ViewRootImpl(view.getContext(), display);
...
}

ViewRootImpl.java
     public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
...
                    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(),
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mInputChannel);
...
}

WindowManagerService.java
    public int addWindow(Session session, IWindow client, int seq,
            WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
            Rect outContentInsets, Rect outStableInsets, InputChannel outInputChannel) {
...
     final DisplayContent displayContent = getDisplayContentLocked(displayId);     //先从mDisplayContents查询。若没有,则先判定displayId对应的设备是否存在。若存在,则调用newDisplayContentLocked创建新的DisplayContent对象,并保存到mDisplayContents
...
            win = new WindowState(this, session, client, token,
                    attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);          //DisplayContent内部保存了mDisplayId,以都与相对的WindowState进行了绑定
...
} 
    private DisplayContent newDisplayContentLocked(final Display display) {
...
        DisplayInfo displayInfo = displayContent.getDisplayInfo();
        final Rect rect = new Rect();
        mDisplaySettings.getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect);
        synchronized (displayContent.mDisplaySizeLock) {
            displayInfo.overscanLeft = rect.left;
            displayInfo.overscanTop = rect.top;
            displayInfo.overscanRight = rect.right;
            displayInfo.overscanBottom = rect.bottom;
            mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
                    displayId, displayInfo);     //此函数可以深究,当前存在双屏,其在找到displayId对应屏的情况下,会发送DisplayManagerGlobal.EVENT_DISPLAY_CHANGED消息
        }
        configureDisplayPolicyLocked(displayContent);               //以上初始化displayContent中的displayInfo对象
...
}

关于displayId与displayInfo.layerstack,当检测到双屏后:
    // Adds a new logical display based on the given display device.
    // Sends notifications if needed.
    private void addLogicalDisplayLocked(DisplayDevice device) {
...
        final int displayId = assignDisplayIdLocked(isDefault);
        final int layerStack = assignLayerStackLocked(displayId);     //直接将displayId赋值给layerStack。即他们始终为同一个值
        LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);          //此处创建的LogicalDisplay对象为上面提供的display[1]的某一真实对象
...
}

接下来开始进入到主题,framework为支持双屏异显做了哪些工作? 
两个重点: 
1.检测到双屏(第二个屏)后,系统做了哪些准备?(主屏幕和HDMI是两个默认开机就进行检测的屏幕设备,其他监听后使用hotplug处理) 
2.如何进行/区分双屏异显?

上面提到Android4.2开始支持双屏异显,除了引入Presentation 类,其还定制了HWComposer,其构造函数中:

if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
                mCBContext->procs.hotplug = &hook_hotplug;
            else
                mCBContext->procs.hotplug = NULL;

即HWC的版本大于等于1.1即可支持双屏异显。我们从hook_hotplug开始查看检测到插入新屏时的系统

HWComposer.cpp   
void HWComposer::hotplug(int disp, int connected)

SurfaceFlinger.cpp
void SurfaceFlinger::onHotplugReceived(int type, bool connected) //NUM_BUILTIN_DISPLAY_TYPES = HWC_NUM_PHYSICAL_DISPLAY_TYPES//默认为2。当type小于2时,才会继续执行。即默认最多支持两个屏。此处的type标示着屏幕类型,如下所示:
    enum DisplayType {
        DISPLAY_ID_INVALID = -1,
        DISPLAY_PRIMARY     = HWC_DISPLAY_PRIMARY,     //0,默认屏幕
        DISPLAY_EXTERNAL    = HWC_DISPLAY_EXTERNAL,          //1,第二屏
        DISPLAY_VIRTUAL     = HWC_DISPLAY_VIRTUAL,          //虚拟屏幕
        NUM_BUILTIN_DISPLAY_TYPES = HWC_NUM_PHYSICAL_DISPLAY_TYPES,
    };

void SurfaceFlinger::createBuiltinDisplayLocked(DisplayDevice::DisplayType type){
    ALOGW_IF(mBuiltinDisplays[type],
            "Overwriting display token for display type %d", type);
    mBuiltinDisplays[type] = new BBinder();
    DisplayDeviceState info(type);
    // All non-virtual displays are currently considered secure.
    info.isSecure = true;
    mCurrentState.displays.add(mBuiltinDisplays[type], info); //保存到mCurrentState.displays,此处的info为DisplayDeviceState对象,mBuiltinDisplays[type]为IBinder对象。
}
uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags)
void SurfaceFlinger::signalTransaction()
MessageQueue.cpp
void MessageQueue::invalidate() {
#if INVALIDATE_ON_VSYNC               //此宏为1
    mEvents->requestNextVsync();
#else
    mHandler->dispatchInvalidate();
#endif
}

EventThread.cpp
void EventThread::requestNextVsync( const sp<EventThread::Connection>& connection)          //mCondition.broadcast()将挂起的线程唤起
Vector< sp<EventThread::Connection> > EventThread::waitForEvent( DisplayEventReceiver::Event* event)     //此函数中的mDisplayEventConnections值得深究。其通过registerDisplayEventConnection()<<<EventThread::Connection::onFirstRef()<<<EventThread::createEventConnection()<<<(SurfaceFlinger::createDisplayEventConnection() <<<DisplayEventReceiver::DisplayEventReceiver())---这个是mEventThread对象的 | (MessageQueue::setEventThread()<<<SurfaceFlinger::init())---这个是mSFEventThread对象的在此构造函数中创建了DisplayEventConnection
SurfaceFlinger.cpp
void SurfaceFlinger::onMessageReceived(int32_t what)     
void SurfaceFlinger::handleTransaction(uint32_t transactionFlags){
...
    // Here we're guaranteed that some transaction flags are set
    // so we can call handleTransactionLocked() unconditionally.
    // We call getTransactionFlags(), which will also clear the flags,
    // with mStateLock held to guarantee that mCurrentState won't change
    // until the transaction is committed.

    transactionFlags = getTransactionFlags(eTransactionMask);          //此函数作用?
    handleTransactionLocked(transactionFlags);                    //上面函数看上去是将transactionFlags清零
...
     invalidateHwcGeometry();
}
void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags){
...
         if (transactionFlags & eDisplayTransactionNeeded) {
        // here we take advantage of Vector's copy-on-write semantics to
        // improve performance by skipping the transaction entirely when
        // know that the lists are identical
        const KeyedVector<  wp<IBinder>, DisplayDeviceState>& curr(mCurrentState.displays);
        const KeyedVector<  wp<IBinder>, DisplayDeviceState>& draw(mDrawingState.displays);
     ...
          const size_t cc = curr.size();
     ...
                      // find displays that were added
            // (ie: in current state but not in drawing state)
            for (size_t i=0 ; i<cc ; i++) {
                    ...
                    BufferQueue::createBufferQueue(&bqProducer, &bqConsumer, new GraphicBufferAlloc());             //为对应的display创建新的BufferQueue
                    ...
                    else {
                            mEventThread->onHotplugReceived(state.type, true);          //通知有新屏设备接入,mEventThread对象中的Connection需要先创建,即createEventConnection()函数需要先被执行,以便后面利用Connection内部对象mChannel来通信!---注意区分与mSFEventThread差别
                        }
               }
     }
...
}
EventThread.cpp
void EventThread::onHotplugReceived(int type, bool connected){     //此时type为1,即DISPLAY_EXTERNAL。connected为true
    Mutex::Autolock _l(mLock);
    if (type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
        DisplayEventReceiver::Event event;
        event.header.type = DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG;      
        event.header.id = type;
        event.header.timestamp = systemTime();
        event.hotplug.connected = connected;
        mPendingEvents.add(event);                    //插入event,将在waitForEvent()读取
        mCondition.broadcast();
    }
}
Vector< sp<EventThread::Connection> > EventThread::waitForEvent(DisplayEventReceiver::Event* event){
...
        if (!timestamp) {
            // no vsync event, see if there are some other event
            eventPending = !mPendingEvents.isEmpty();
            if (eventPending) {
                // we have some other event to dispatch
                *event = mPendingEvents[0];               //取出上面插入的event
                mPendingEvents.removeAt(0);
            }
        }

        // find out connections waiting for events
        size_t count = mDisplayEventConnections.size();          //此处对应新display的connectcion已经建立,如何建立???
     ...
                if (eventPending && !timestamp && !added) {
                    // we don't have a vsync event to process
                    // (timestamp==0), but we have some pending
                    // messages.
                    signalConnections.add(connection);
                }
...
          if (!timestamp && !eventPending) {                         //此时eventPending为true,不会进入此if进行wait,同时signalConnections.add(),所以会退出while循环
          ...
          }
          while (signalConnections.isEmpty());
...
}
bool EventThread::threadLoop()
status_t EventThread::Connection::postEvent( const DisplayEventReceiver::Event& event)          //sendEvents()中的mChannel为new new BitTube(),此对象用于pipe通信。关注此时signalConnections[i]来源,其决定pipe通信的两端。
BitTube.cpp
ssize_t BitTube::sendObjects(const sp<BitTube>& tube, void const* events, size_t count, size_t objSize)      //objSize为模板size
ssize_t BitTube::write(void const* vaddr, size_t size){    //vaddr为event的地址,size为objSize*count
...
     len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL);     //socket函数进行pipe通信。BitTube的构造函数中,调用init函数,其调用socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)初始化了mReceiveFd和mSendFd
...
}

至此,将新屏插入的event消息通过socket发出。 
那何处何时接收并处理此消息呢?从mReceiveFd逆向推出:

BitTube.cpp
ssize_t BitTube::read(void* vaddr, size_t size)
ssize_t BitTube::recvObjects(const sp<BitTube>& tube, void* events, size_t count, size_t objSize)
DisplayEventReceiver.cpp
DisplayEventReceiver::getEvents(mDataChannel, events, count)     //此处mDataChannel为mEventConnection建立时,初始化的针对此connection的数据通道,其为DisplayEventReceiver内部对象mEventConnection中的mChannel。event为读取的插入事件指针
MessageQueue.cpp
int MessageQueue::eventReceiver(int /*fd*/, int /*events*/){          
    ssize_t n;
    DisplayEventReceiver::Event buffer[8];
    while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {
        for (int i=0 ; i<n ; i++) {
            if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
#if INVALIDATE_ON_VSYNC
                mHandler->dispatchInvalidate();
#else
                mHandler->dispatchRefresh();
#endif
                break;
            }
        }
    }
    return 1;
}

SF在创建事件线程时,同时创建了监听回调:

mSFEventThread = new EventThread(sfVsyncSrc);
    mEventQueue.setEventThread(mSFEventThread);

void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
{
    mEventThread = eventThread;
    mEvents = eventThread->createEventConnection();     //其中new Connection(),即初始化了mChannel(new BitTube()),此通道用于监听注册
    mEventTube = mEvents->getDataChannel();               //mChannel
    mLooper->addFd(mEventTube->getFd(), 0, Looper::EVENT_INPUT,
            MessageQueue::cb_eventReceiver, this);               //Android自4.1后在SF嵌入了消息机制。mLooper->addFd()为注册监听,MessageQueue::cb_eventReceiver为回调函数,其调用了eventReceiver()
}

分析到此处,插入消息接收处理仿佛已经找到,但 eventReceiver()只处理DISPLAY_EVENT_VSYNC,而我们event包含的是DISPLAY_EVENT_HOTPLUG消息,莫非不用处理? 
addFd()先注册了监听,当向pipe写入event插入消息时,从消息队列中唤起并执行处理。

先关注mEventTube->getFd()监听的对象: 
setEventThread()只适用于mSFEventThread变量,而我们跟踪的是另外EventThread对象mEventThread。 
所以上面并非正确的调用处。

回头看DisplayEventReceiver::getEvents(),同时结合其构造函数创建mEventConnection,等同创建mChannel,必然有地方提前初始化此对象。 
搜索”DisplayEventReceiver “:

android_view_DisplayEventReceiver.cpp
class NativeDisplayEventReceiver : public LooperCallback {
...    
     virtual int handleEvent(int receiveFd, int events, void* data);          //回调函数
     DisplayEventReceiver mReceiver;
...
}

此类继承LooperCallback,说明其可以实现消息机制的回调。再查看注册监听以及消息获取:

int rc = mMessageQueue->getLooper()->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL);          
while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0)

该有的都有了,断定此处即为处理插入事件的地方。

在分析EventThread::waitForEvent()时,此函数中的mDisplayEventConnections通过

registerDisplayEventConnection()<<<EventThread::Connection::onFirstRef()<<<EventThread::createEventConnection()<<<(SurfaceFlinger::createDisplayEventConnection() <<<DisplayEventReceiver::DisplayEventReceiver())"

所以addFd(mReceiver.getFd(),xxx)和conn->postEvent(event)中的mChannel为同一个。 
关于native的消息机制,与java的原理类似,熟悉的Handler,Looper,MessageQueue。

Looper.cpp
int Looper::pollInner(int timeoutMillis) {
...
     int callbackResult = response.request.callback->handleEvent(fd, events, data);          //setEventThread() 对应的mSFEventThread也使用了callback方式,其传入了函数指针,被SimpleLooperCallback封装
...
}

总结一下mChannel这个变量: 
DisplayEventReceiver::mDataChannel<>EventThread::Connection::mChannel 
1).其为BitTube对象 
2).BitTube对象中的mReceiveFd和mSendFd为socket的两端 
3).addFd注册监听,传入BitTube::mReceiveFd被epoll挂起监听。同时获取消息时,::recv(mReceiveFd, vaddr, size, MSG_DONTWAIT),从mReceiveFd读取 
4).::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL),mSendFd用于发送消息

现在搞清楚了监听注册,接受消息,我们继续看两个问题: 
(1).对于插入新屏的处理 
(2).android_view_DisplayEventReceiver.cpp的初始化

android_view_DisplayEventReceiver.cpp

int NativeDisplayEventReceiver::handleEvent(int receiveFd, int events, void* data)     //虽然传入了receiveFd,但此函数内部并没有使用。为什么可以自己思考。
bool NativeDisplayEventReceiver::processPendingEvents( nsecs_t* outTimestamp, int32_t* outId, uint32_t* outCount){
...
     while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
          ...
        case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
                dispatchHotplug(ev.header.timestamp, ev.header.id, ev.hotplug.connected);
                break;
     }
...
}

DisplayEventReceiver.java //DisplayEventReceiver.java为抽象类,LocalDisplayAdapter.java的内部类HotplugDisplayEventReceiver继承了DisplayEventReceiver 
// Called from native code. 
@SuppressWarnings(“unused”) 
private void dispatchHotplug(long timestampNanos, int builtInDisplayId, boolean connected) { 
onHotplug(timestampNanos, builtInDisplayId, connected); 
}

LocalDisplayAdapter.java

private void tryConnectDisplayLocked(int builtInDisplayId){          //为ev.header.id,此处值为1
        IBinder displayToken = SurfaceControl.getBuiltInDisplay(builtInDisplayId);
        if (displayToken != null) {
            SurfaceControl.PhysicalDisplayInfo[] configs =
                    SurfaceControl.getDisplayConfigs(displayToken);                    //查询mBuiltinDisplays.此处configs何时被设定?
            if (configs == null) {
                // There are no valid configs for this device, so we can't use it
                Slog.w(TAG, "No valid configs found for display device " +
                        builtInDisplayId);
                return;
            }
...
            LocalDisplayDevice device = mDevices.get(builtInDisplayId);               //此处创建的是LocalDisplayDevice对象
            if (device == null) {
                // Display was added.
                device = new LocalDisplayDevice(displayToken, builtInDisplayId,
                        configs, activeConfig);
                mDevices.put(builtInDisplayId, device);
                sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);               //此处场景为第一次插入第二个屏
            }
... 
}

DisplayManagerService.java

private void handleDisplayDeviceAddedLocked(DisplayDevice device){
...
     addLogicalDisplayLocked(device);
       Runnable work = updateDisplayStateLocked(device);          //此device为FLAG_NEVER_BLANK并且mGlobalDisplayState状态不一致时,会调用SurfaceControl.setDisplayPowerMode(token, mode)
        if (work != null) {
            work.run();
       }
        scheduleTraversalLocked(false);          //将调用WindowManagerService::performLayoutAndPlaceSurfacesLockedLoop()>>>performLayoutAndPlaceSurfacesLockedInner()>>>mDisplayManagerInternal.performTraversalInTransactionFromWindowManager()>>>DMS::performTraversalInTransactionLocked()>>>configureDisplayInTransactionLocked()>>>LogicalDisplay::configureDisplayInTransactionLocked()>>>DisplayDevice::setLayerStackInTransactionLocked()>>>SurfaceControl.setDisplayLayerStack(mDisplayToken, layerStack)
如此重要的调用,隐藏的好深!其最终对应Composer::setDisplayLayerStack(),将新创建DisplayState对象并保存到mDisplayStates中,同时DisplayState对象设定状态eLayerStackChanged和对应layerstack,提供后面显示使用
...     
}
private void addLogicalDisplayLocked(DisplayDevice device){     //Adds a new logical display based on the given display device. Sends notifications if needed.
...
        final int displayId = assignDisplayIdLocked(isDefault);
        final int layerStack = assignLayerStackLocked(displayId);          //最开始提到的将displayid与layerstack一致便是此时完成

        LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
        display.updateLocked(mDisplayDevices);
...
     sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
}

DisplayManagerGlobal.java

public void registerDisplayListener(DisplayListener listener, Handler handler)     //收到EVENT_DISPLAY_ADDED消息,将调用参数listener的回调函数onDisplayAdded()。Presentation.java和ViewRootImpl.java对ADD是空操作,它们更关心CHANGE,REMOVE的变化

到此,插入第二个屏基本结束。从SF开始,到WMS结束。 
其主要作用:在SF对新屏进行了参数初始化,在DMS创建并保存了新的Display,DisplayDevice对象,使得displayId与layerstack对应一致。 
注意:此处分析的是插入新屏,系统开机过程中,DMS默认会对主屏和HDMI进行扫描并创建设备对象: 
LocalDisplayAdapter.java

public void registerLocked() {
        super.registerLocked();

        mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper());

        for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) {
            tryConnectDisplayLocked(builtInDisplayId);
        }
    }

系统初始化了第二个的设备对象,那么是如何控制显示的呢? 
我们从ViewRootImpl说起: 
ViewRootImpl.java

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
...
                    requestLayout();     //下面的跨进程调用addToDisplay()先创建了win,并绑定了对应的displayId。此处将通过Handler执行performTraversals()
...
                    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(),
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mInputChannel);
...
}
     private void performTraversals() {
...
               relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);      //创建对应的Surface画布
...
               performDraw();   //在创建并返回的Surface上执行绘画
...
}

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 outOverscanInsets, Rect outContentInsets,
            Rect outVisibleInsets, Rect outStableInsets, Configuration outConfig,
            Surface outSurface){                              //此处outSurface为null,其在WMS被创建赋值,并返回给ViewRootImpl
...
                    SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
                    if (surfaceControl != null) {
                        outSurface.copyFrom(surfaceControl);
                        if (SHOW_TRANSACTIONS) Slog.i(TAG,
                                " OUT SURFACE " + outSurface + ": copied");
                    }
...
}

WindowStateAnimator.java

SurfaceControl createSurfaceLocked(){
...
// Start a new transaction and apply position & offset.
            SurfaceControl.openTransaction();
...
                    if (displayContent != null) {
                        mSurfaceControl.setLayerStack(displayContent.getDisplay().getLayerStack());          //此处只关注第二个屏,即layerstack的处理
                    }
...
               SurfaceControl.closeTransaction();     //将此处的设置一并提交
...
}

因为SF与framework对应的变量有着重重封装,此处直接跳过:

SurfaceComposerClient.cpp

status_t Composer::setLayerStack(const sp<SurfaceComposerClient>& client,
        const sp<IBinder>& id, uint32_t layerStack) {          //id为SurfaceControl.cpp中的mHandle
    Mutex::Autolock _l(mLock);
    layer_state_t* s = getLayerStateLocked(client, id);     //将第二个屏对应的ComposerState对象添加到mComposerStates中。ComposerState对象s.client为SF的Bp端,s.state.surface为IBinder对象mHandle
    if (!s)
        return BAD_INDEX;
    s->what |= layer_state_t::eLayerStackChanged;
    s->layerStack = layerStack;                                   //设置了flag和laystack,在closeTransaction()提交时处理
    return NO_ERROR;
}

//SurfaceControl.closeTransaction()的对应处理
void Composer::closeGlobalTransactionImpl(bool synchronous) {
...
        transaction = mComposerStates;
        mComposerStates.clear();

        displayTransaction = mDisplayStates;               //上面分析已经提供mComposerStates和mDisplayStates的创建添加
        mDisplayStates.clear();
...
     sm->setTransactionState(transaction, displayTransaction, flags);          //因为前面也有getLayerStateLockedmSurfaceControl.setSize(),其会将mForceSynchronous赋值为true,所以flag有eSynchronous。
}

SurfaceFlinger.cpp

void SurfaceFlinger::setTransactionState(
        const Vector<ComposerState>& state,
        const Vector<DisplayState>& displays,
        uint32_t flags)
{
...
    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()) );
                    transactionFlags |= setClientStateLocked(client, s.state);     //将调用Layer::setLayerStack(),将layerstack保存到mCurrentState.layerStack,为mTransactionFlags添加eTransactionNeeded,后面的onDraw()使用
                }
            }
        }
    }
...
    if (transactionFlags) {          //此时eTransactionNeeded|eTraversalNeeded
        // this triggers the transaction
        setTransactionFlags(transactionFlags);          //将调用到handleTransactionLocked()

        // if this is a synchronous transaction, wait for it to take effect
        // before returning.
        if (flags & eSynchronous) {               
            mTransactionPending = true;
        }
        if (flags & eAnimation) {
            mAnimTransactionPending = true;
        }
        while (mTransactionPending) {               //此时mTransactionPending为true
            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;
            }
        }
    }
}
     void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags){
...
              if (transactionFlags & eTraversalNeeded) {
        for (size_t i=0 ; i<count ; i++) {
            const sp<Layer>& layer(currentLayers[i]);
            uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);          //
            if (!trFlags) continue;

            const uint32_t flags = layer->doTransaction(0);          //每个layer进行遍历处理,将调用Layer::commitTransaction()>>>mDrawingState = mCurrentState。这样第二个屏的已经转变为mDrawingState状态。
            if (flags & Layer::eVisibleRegion)
                mVisibleRegionsDirty = true;
        }
    }
...
           commitTransaction();          //调用mTransactionCV.broadcast(),使得 SurfaceControl.closeTransaction()线程返回.同时mDrawingState = mCurrentState;
           updateCursorAsync();
}

至此,已经将SF和Layer中的mDrawingState与第二个屏绑定。performDraw()可以愉快在插入的新屏上绘制了。

http://www.voidcn.com/article/p-wxfimpep-bpd.html

展开阅读全文

没有更多推荐了,返回首页