Android(安卓)P图形架构之三屏异显实现
相关源码:
\frameworks\base\core\java\android\view\SurfaceControl.java
\frameworks\base\services\core\java\com\android\server\display\LocalDisplayAdapter.java
\frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp
frameworks\native\services\surfaceflinger\DisplayHardware\HWComposer.h
\hardware\libhardware\include\hardware\hwcomposer_defs.h
\vendor\nxp-opensource\imx\display\hwcomposer_v20\hwcomposer.cpp
\vendor\nxp-opensource\imx\display\display\DisplayManager.cpp
我们都知道安卓支持多屏异显。但是android 9.0系统中,默认只加载了两个物理屏和一个虚拟屏。
具体资料可以参考谷歌官方资料:
https://developer.android.com/guide/topics/ui/multi-window
https://developer.android.com/about/versions/oreo/android-8.0
参考文章:
《Android P实现双屏异显》
《Android P图形架构之SurfaceFlinger加载显示屏流程》
android 9.0显示屏的定义:
- display 0 主屏
- display 1 副屏(辅助屏)
- display 2 虚拟屏(显示display 1上)
增加第三块屏后的定义:
- display 0 主屏
- display 1 副屏(辅助屏)
- display 2 扩展屏(第三块屏)
- display 3 虚拟屏(显示display 1或者display 2上)
Framework层
1、SurfaceControl中,增加第三块屏的定义:
\frameworks\base\core\java\android\view\SurfaceControl.java
/** * Built-in physical display id: Main display. * Use only with {@link SurfaceControl#getBuiltInDisplay(int)}. */public static final int BUILT_IN_DISPLAY_ID_MAIN = 0;/*** Built-in physical display id: Attached HDMI display.* Use only with {@link SurfaceControl#getBuiltInDisplay(int)}.*/public static final int BUILT_IN_DISPLAY_ID_HDMI = 1;//add by sunxiaolin 20190906public static final int BUILT_IN_DISPLAY_ID_THIRD = 2;2、LocalDisplayAdapter中,增加第三块屏的逻辑处理:\frameworks\base\services\core\java\com\android\server\display\LocalDisplayAdapter.javaprivate static final int[] BUILT_IN_DISPLAY_IDS_TO_SCAN = new int[] { SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN, SurfaceControl.BUILT_IN_DISPLAY_ID_HDMI, SurfaceControl.BUILT_IN_DISPLAY_ID_THIRD,//add by sunxiaolin 20190906};@Overridepublic void registerLocked() { super.registerLocked(); mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper()); for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) { tryConnectDisplayLocked(builtInDisplayId); }}
3、SurfaceFlinger中,增加第三块屏的逻辑处理:
\frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp
DisplayDevice::DisplayType SurfaceFlinger::determineDisplayType(hwc2_display_t display, HWC2::Connection connection) const { // Figure out whether the event is for the primary display or an // external display by matching the Hwc display id against one for a // connected display. If we did not find a match, we then check what // displays are not already connected to determine the type. If we don't // have a connected primary display, we assume the new display is meant to // be the primary display, and then if we don't have an external display, // we assume it is that. ALOGI("sunxiaolin determineDisplayType"); const auto primaryDisplayId = getBE().mHwc->getHwcDisplayId(DisplayDevice::DISPLAY_PRIMARY); const auto externalDisplayId = getBE().mHwc->getHwcDisplayId(DisplayDevice::DISPLAY_EXTERNAL); const auto thirdDisplayId = getBE().mHwc->getHwcDisplayId(DisplayDevice::DISPLAY_THIRD); if (primaryDisplayId && primaryDisplayId == display) {ALOGI("sunxiaolin determineDisplayType primaryDisplayId"); return DisplayDevice::DISPLAY_PRIMARY; } else if (externalDisplayId && externalDisplayId == display) {ALOGI("sunxiaolin determineDisplayType externalDisplayId"); return DisplayDevice::DISPLAY_EXTERNAL; } else if (thirdDisplayId && thirdDisplayId == display) {ALOGI("sunxiaolin determineDisplayType thirdDisplayId"); return DisplayDevice::DISPLAY_THIRD; } else if (connection == HWC2::Connection::Connected && !primaryDisplayId) {ALOGI("sunxiaolin determineDisplayType primaryDisplayId2"); return DisplayDevice::DISPLAY_PRIMARY; } else if (connection == HWC2::Connection::Connected && !externalDisplayId) {ALOGI("sunxiaolin determineDisplayType externalDisplayId2"); return DisplayDevice::DISPLAY_EXTERNAL; } else if (connection == HWC2::Connection::Connected && !thirdDisplayId) {ALOGI("sunxiaolin determineDisplayType thirdDisplayId2"); return DisplayDevice::DISPLAY_THIRD; } return DisplayDevice::DISPLAY_ID_INVALID;}void SurfaceFlinger::processDisplayHotplugEventsLocked() { for (const auto& event : mPendingHotplugEvents) { auto displayType = determineDisplayType(event.display, event.connection); if (displayType == DisplayDevice::DISPLAY_ID_INVALID) { ALOGW("Unable to determine the display type for display %" PRIu64, event.display); continue; } if (getBE().mHwc->isUsingVrComposer() && displayType == DisplayDevice::DISPLAY_EXTERNAL) { ALOGE("External displays are not supported by the vr hardware composer."); continue; } getBE().mHwc->onHotplug(event.display, displayType, event.connection);ALOGI("sunxiaolin processDisplayHotplugEventsLocked displayType=%d",displayType); if (event.connection == HWC2::Connection::Connected) { if (!mBuiltinDisplays[displayType].get()) { ALOGV("sunxiaolin,Creating built in display %d", displayType); mBuiltinDisplays[displayType] = new BBinder(); // All non-virtual displays are currently considered secure. DisplayDeviceState info(displayType, true); //处理第三块屏 if( displayType == DisplayDevice::DISPLAY_THIRD ){info.displayName = "THIRD Screen";}else{ info.displayName = displayType == DisplayDevice::DISPLAY_PRIMARY ? "Built-in Screen" : "External Screen";} mCurrentState.displays.add(mBuiltinDisplays[displayType], info); mInterceptor->saveDisplayCreation(info); } } else { ALOGV("Removing built in display %d", displayType); ssize_t idx = mCurrentState.displays.indexOfKey(mBuiltinDisplays[displayType]); if (idx >= 0) { const DisplayDeviceState& info(mCurrentState.displays.valueAt(idx)); mInterceptor->saveDisplayDeletion(info.displayId); mCurrentState.displays.removeItemsAt(idx); } mBuiltinDisplays[displayType].clear(); } processDisplayChangesLocked(); } mPendingHotplugEvents.clear();}
4、修改虚拟屏的判断,增加一块屏将2改成3,即display 3是虚拟屏
static const int32_t VIRTUAL_DISPLAY_ID_BASE = 3;
HAL层
HAL层中,也需要修改显示屏的定义,即display 0,1,2修改成display 0,1,2,3:
源码:hardware\libhardware\include\hardware\hwcomposer_defs.h
/* Display types and associated mask bits. */enum { HWC_DISPLAY_PRIMARY = 0, HWC_DISPLAY_EXTERNAL = 1, // HDMI, DP, etc. //add by sunxiaolin 20190906 HWC_DISPLAY_THIRD = 2,// the third display HWC_DISPLAY_VIRTUAL = 3,//modiy start by sunxiaolin 20190906 HWC_NUM_PHYSICAL_DISPLAY_TYPES = 3, // value 2 --> 3 HWC_NUM_DISPLAY_TYPES = 4,// value 3 --> 4 //modiy end by sunxiaolin 20190906};
驱动层
最终是驱动层将屏的相关信息,通过HAL层,发送给SurfaceFlinger中。
display中获取显示屏的处理:
\vendor\nxp-opensource\imx\display\hwcomposer_v20\hwcomposer.cpp
//主屏的初始化,回调给SurfaceFlingerstatic int hwc2_register_callback(hwc2_device_t* device, int32_t descriptor, hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer){ if (!device) { ALOGE("%s invalid device", __func__); return HWC2_ERROR_BAD_PARAMETER; } struct hwc2_context_t *ctx = (struct hwc2_context_t*)device; switch (descriptor) { case HWC2_CALLBACK_HOTPLUG: ctx->mHotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(pointer); ctx->mHotplugData = callbackData; break; case HWC2_CALLBACK_REFRESH: ctx->mRefresh = reinterpret_cast<HWC2_PFN_REFRESH>(pointer); ctx->mRefreshData = callbackData; break; case HWC2_CALLBACK_VSYNC: ctx->mVsync = reinterpret_cast<HWC2_PFN_VSYNC>(pointer); ctx->mVsyncData = callbackData; break; } DisplayManager::getInstance()->setCallback(ctx->mListener); if (descriptor == HWC2_CALLBACK_HOTPLUG && pointer != NULL) {ALOGI("sunxiaolin,hwc2_register_callback HWC_DISPLAY_PRIMARY"); ctx->mListener->onHotplug(HWC_DISPLAY_PRIMARY, true); } return HWC2_ERROR_NONE;}//副屏的初始化,回调给SurfaceFlingerstatic int hwc2_present_display(hwc2_device_t* device, hwc2_display_t display, int32_t* outPresentFence){ if (!device) { ALOGE("%s invalid device", __func__); return HWC2_ERROR_BAD_PARAMETER; } Display* pDisplay = NULL; DisplayManager* displayManager = DisplayManager::getInstance(); pDisplay = displayManager->getDisplay(display); if (pDisplay == NULL) { ALOGE("%s invalid display id:%" PRId64, __func__, display); return HWC2_ERROR_BAD_DISPLAY; } pDisplay->composeLayers(); pDisplay->updateScreen(); if (outPresentFence != NULL) { pDisplay->getPresentFence(outPresentFence); } struct hwc2_context_t *ctx = (struct hwc2_context_t*)device; if (ctx->checkHDMI && ctx->mHotplug != NULL && ctx->mVsync != NULL) { ctx->checkHDMI = false; Display* fb = displayManager->getPhysicalDisplay(HWC_DISPLAY_EXTERNAL); ALOGI("sunxiaolin,hwc2_present_display HWC_DISPLAY_EXTERNAL"); ctx->mListener->onHotplug(HWC_DISPLAY_EXTERNAL, fb->connected()); //增加第三块屏(扩展平),回调给SurfaceFlinger ctx->checkHDMI = false; Display* fb2 = displayManager->getPhysicalDisplay(HWC_DISPLAY_THIRD); ALOGI("sunxiaolin,hwc2_present_display HWC_DISPLAY_THIRD"); ctx->mListener->onHotplug(HWC_DISPLAY_THIRD, fb2->connected()); } return HWC2_ERROR_NONE;}//回调给HAL层,在给到SurfaceFlinger.sovoid DisplayListener::onHotplug(int disp, bool connected){ALOGI("sunxiaolin,onHotplug disp=%d,connected=%d",disp,connected); if (mCtx == NULL || mCtx->mHotplug == NULL) { return; } hwc2_connection_t connection = connected ? HWC2_CONNECTION_CONNECTED : HWC2_CONNECTION_DISCONNECTED; mCtx->mHotplug(mCtx->mHotplugData, disp, connection);}
重点:
Display* fb = displayManager->getPhysicalDisplay(HWC_DISPLAY_EXTERNAL);
Display* fb2 = displayManager->getPhysicalDisplay(HWC_DISPLAY_THIRD);
DisplayManager中管理者显示屏,前提是kernel里已经加载了第三块显示屏驱动:
\vendor\nxp-opensource\imx\display\display\DisplayManager.cpp
#define MAX_PHYSICAL_DISPLAY 10#define MAX_VIRTUAL_DISPLAY 16Display* DisplayManager::getPhysicalDisplay(int id){ Mutex::Autolock _l(mLock); if (id < 0 || id >= MAX_PHYSICAL_DISPLAY) { ALOGE("%s invalid id %d", __func__, __LINE__); return NULL; }ALOGI("%s %d sunxiaolin id=%d", __func__, __LINE__,id); if (mDrmMode) { return mKmsDisplays[id]; } return mFbDisplays[id];}
更多相关文章
- Android(安卓)Studio 创建虚拟机失败 Failed to load 解决办法
- Android(安卓)tp的虚拟按键(virtual key)处理
- Android(安卓)平台简介
- Android的系统构架
- 《Android(安卓)Dev Guide》系列教程1:什么是Android?
- 隐藏Android底部的虚拟按键
- android:inputType标签
- jdk及android studio环境变量配置
- android:inputType标签