// // Copyright (C) 2019 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include #include #include "AutomotiveDisplayProxyService.h" namespace android { namespace frameworks { namespace automotive { namespace display { namespace V1_0 { namespace implementation { Return> AutomotiveDisplayProxyService::getIGraphicBufferProducer(uint64_t id) { auto it = mDisplays.find(id); sp displayToken = nullptr; sp surfaceControl = nullptr; if (it == mDisplays.end()) { displayToken = SurfaceComposerClient::getPhysicalDisplayToken(PhysicalDisplayId(id)); if (displayToken == nullptr) { ALOGE("Given display id, 0x%lX, is invalid.", (unsigned long)id); return nullptr; } // Get the resolution from stored display state. ui::DisplayMode displayMode = {}; auto err = SurfaceComposerClient::getActiveDisplayMode(displayToken, &displayMode); if (err != NO_ERROR) { ALOGE("Failed to get display mode of %lX. " "This display will be ignored.", (unsigned long)id); return nullptr; } ui::DisplayState displayState = {}; err = SurfaceComposerClient::getDisplayState(displayToken, &displayState); if (err != NO_ERROR) { ALOGE("Failed to get current display status of %lX. " "This display will be ignored.", (unsigned long)id); return nullptr; } auto displayWidth = displayMode.resolution.getWidth(); auto displayHeight = displayMode.resolution.getHeight(); if ((displayState.orientation != ui::ROTATION_0) && (displayState.orientation != ui::ROTATION_180)) { std::swap(displayWidth, displayHeight); } sp surfaceClient = new SurfaceComposerClient(); err = surfaceClient->initCheck(); if (err != NO_ERROR) { ALOGE("SurfaceComposerClient::initCheck error: %#x", err); return nullptr; } // Create a SurfaceControl instance surfaceControl = surfaceClient->createSurface( String8::format("AutomotiveDisplay::%lX", (unsigned long)id), displayWidth, displayHeight, PIXEL_FORMAT_RGBX_8888, ISurfaceComposerClient::eOpaque); if (surfaceControl == nullptr || !surfaceControl->isValid()) { ALOGE("Failed to create SurfaceControl."); return nullptr; } // Store DisplayDesc descriptor = {displayToken, surfaceControl}; mDisplays.insert_or_assign(id, std::move(descriptor)); } else { displayToken = it->second.token; surfaceControl = it->second.surfaceControl; } // SurfaceControl::getSurface is guaranteed to be not null. auto targetSurface = surfaceControl->getSurface(); return new ::android::hardware::graphics::bufferqueue::V2_0::utils:: B2HGraphicBufferProducer(targetSurface->getIGraphicBufferProducer()); } Return AutomotiveDisplayProxyService::showWindow(uint64_t id) { auto it = mDisplays.find(id); if (it == mDisplays.end()) { ALOGE("Given display token is invalid or unknown."); return false; } ui::DisplayState displayState; auto err = SurfaceComposerClient::getDisplayState(it->second.token, &displayState); if (err != NO_ERROR) { ALOGE("Failed to get current state of the display 0x%lX", (unsigned long)id); return false; } SurfaceComposerClient::Transaction t; t.setDisplayLayerStack(it->second.token, displayState.layerStack); t.setLayerStack(it->second.surfaceControl, displayState.layerStack); status_t status = t.setLayer(it->second.surfaceControl, 0x7FFFFFFF) .show(it->second.surfaceControl) .apply(); return status == NO_ERROR; } Return AutomotiveDisplayProxyService::hideWindow(uint64_t id) { auto it = mDisplays.find(id); if (it == mDisplays.end()) { ALOGE("Given display token is invalid or unknown."); return false; } status_t status = SurfaceComposerClient::Transaction{} .hide(it->second.surfaceControl) .apply(); return status == NO_ERROR; } Return AutomotiveDisplayProxyService::getDisplayIdList(getDisplayIdList_cb _cb) { hardware::hidl_vec ids; // Get stable IDs of all available displays and get their tokens and // descriptors. auto displayIds = SurfaceComposerClient::getPhysicalDisplayIds(); ids.resize(displayIds.size()); for (auto i = 0; i < displayIds.size(); ++i) { ids[i] = displayIds[i].value; } _cb(ids); return hardware::Void(); } Return AutomotiveDisplayProxyService::getDisplayInfo(uint64_t id, getDisplayInfo_cb _cb) { HwDisplayConfig activeConfig; HwDisplayState activeState; auto displayToken = SurfaceComposerClient::getPhysicalDisplayToken(PhysicalDisplayId(id)); if (displayToken == nullptr) { ALOGE("Given display id, 0x%lX, is invalid.", (unsigned long)id); } else { ui::DisplayMode displayMode = {}; auto err = SurfaceComposerClient::getActiveDisplayMode(displayToken, &displayMode); if (err != NO_ERROR) { ALOGW("Failed to get display mode of %lX. " "This display will be ignored.", (unsigned long)id); } ui::DisplayState displayState = {}; err = SurfaceComposerClient::getDisplayState(displayToken, &displayState); if (err != NO_ERROR) { ALOGW("Failed to get current display status of %lX. " "This display will be ignored.", (unsigned long)id); } activeConfig.setToExternal((uint8_t*)&displayMode, sizeof(ui::DisplayMode)); activeState.setToExternal((uint8_t*)&displayState, sizeof(DisplayState)); } _cb(activeConfig, activeState); return hardware::Void(); } } // namespace implementation } // namespace V1_0 } // namespace display } // namespace automotive } // namespace frameworks } // namespace android