相关源码:
\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显示屏的定义:
增加第三块屏后的定义:
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 20190906
public static final int BUILT_IN_DISPLAY_ID_THIRD = 2;
2、LocalDisplayAdapter中,增加第三块屏的逻辑处理:
\frameworks\base\services\core\java\com\android\server\display\LocalDisplayAdapter.java
private 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
};
@Override
public 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层中,也需要修改显示屏的定义,即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
//主屏的初始化,回调给SurfaceFlinger
static 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;
}
//副屏的初始化,回调给SurfaceFlinger
static 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.so
void 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 16
Display* 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];
}