日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

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

發布時間:2025/3/15 Android 65 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于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 }@Overrideprotectedvoid 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管理對象為上面創建的這個@Overridepublic 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.javapublic void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow) { ...root = new ViewRootImpl(view.getContext(), display); ... }ViewRootImpl.javapublic void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { ...res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,getHostVisibility(), mDisplay.getDisplayId(),mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mInputChannel); ... }WindowManagerService.javapublic 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;elsemCBContext->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 //此宏為1mEvents->requestNextVsync(); #elsemHandler->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 identicalconst 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為trueMutex::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 eventeventPending = !mPendingEvents.isEmpty();if (eventPending) {// we have some other event to dispatch*event = mPendingEvents[0]; //取出上面插入的eventmPendingEvents.removeAt(0);}}// find out connections waiting for eventssize_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_VSYNCmHandler->dispatchInvalidate(); #elsemHandler->dispatchRefresh(); #endifbreak;}}}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(); //mChannelmLooper->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,此處值為1IBinder 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 itSlog.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中的mHandleMutex::Autolock _l(mLock);layer_state_t* s = getLayerStateLocked(client, id); //將第二個屏對應的ComposerState對象添加到mComposerStates中。ComposerState對象s.client為SF的Bp端,s.state.surface為IBinder對象mHandleif (!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 transactionsetTransactionFlags(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為truestatus_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

總結

以上是生活随笔為你收集整理的基于Android5.1的双屏异显分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。