diff options
| author | 2019-12-30 11:12:53 -0800 | |
|---|---|---|
| committer | 2020-02-14 10:27:15 -0800 | |
| commit | 75c8aa9197b2015afdb027073fd9f3b0f690d0bb (patch) | |
| tree | 22fa9aa026c593546cae973e4624622332f03df4 | |
| parent | bb1f866cb31b1a4457b1b9d3eb3ff40db9d7e814 (diff) | |
Add multi-display support
This change modifies and implements below methods to support
multi-display device implementations.
- getIGraphicBufferProducer() takes a target display identifier.
If a given identifier is not valid, this will return a null pointer.
- AutomotiveDisplayProxyService stores display tokens of each display.
- showWindow() is modified to set a layer stack properly for a target
display.
- getDisplayIdList() is newly implemented and returns stable IDs
of all available displays.
- getDisplayInfo() returns the description of a target display
that is identified by a given stable ID.
Bug: 141886260
Bug: 146567078
Test: VtsHalEvsV1_1TargetTest
Change-Id: Ia195a6c19416eb75bfe77da61d7a32030ec85967
Signed-off-by: Changyeon Jo <changyeon@google.com>
4 files changed, 146 insertions, 77 deletions
diff --git a/services/automotive/display/Android.bp b/services/automotive/display/Android.bp index d94fb273b0..8ff0711f55 100644 --- a/services/automotive/display/Android.bp +++ b/services/automotive/display/Android.bp @@ -36,4 +36,8 @@ cc_binary { local_include_dirs: [ "include", ], + + cflags: [ + "-DLOG_TAG=\"AutomotiveDisplayService\"" + ], } diff --git a/services/automotive/display/AutomotiveDisplayProxyService.cpp b/services/automotive/display/AutomotiveDisplayProxyService.cpp index 3cd8e390b2..8f57dcdb18 100644 --- a/services/automotive/display/AutomotiveDisplayProxyService.cpp +++ b/services/automotive/display/AutomotiveDisplayProxyService.cpp @@ -27,97 +27,163 @@ namespace display { namespace V1_0 { namespace implementation { -Return<sp<IGraphicBufferProducer>> -AutomotiveDisplayProxyService::getIGraphicBufferProducer() { - if (mSurface == nullptr) { - status_t err; - mSurfaceComposerClient = new SurfaceComposerClient(); - - err = mSurfaceComposerClient->initCheck(); - if (err != NO_ERROR) { - ALOGE("SurfaceComposerClient::initCheck error: %#x", err); - mSurfaceComposerClient = nullptr; - return nullptr; - } - const auto displayToken = SurfaceComposerClient::getInternalDisplayToken(); +Return<sp<IGraphicBufferProducer>> +AutomotiveDisplayProxyService::getIGraphicBufferProducer(uint64_t id) { + auto it = mDisplays.find(id); + sp<IBinder> displayToken = nullptr; + sp<SurfaceControl> surfaceControl = nullptr; + if (it == mDisplays.end()) { + displayToken = SurfaceComposerClient::getPhysicalDisplayToken(id); if (displayToken == nullptr) { - ALOGE("Failed to get internal display "); + ALOGE("Given display id, 0x%lX, is invalid.", id); return nullptr; } - err = SurfaceComposerClient::getActiveDisplayConfig(displayToken, &mDpyConfig); + // Get the resolution from stored display state. + DisplayConfig displayConfig = {}; + auto err = SurfaceComposerClient::getActiveDisplayConfig(displayToken, &displayConfig); if (err != NO_ERROR) { - ALOGE("Failed to get active display config"); + ALOGE("Failed to get display configuration of %lX. " + "This display will be ignored.", id); return nullptr; } - err = SurfaceComposerClient::getDisplayState(displayToken, &mDpyState); + ui::DisplayState displayState = {}; + err = SurfaceComposerClient::getDisplayState(displayToken, &displayState); if (err != NO_ERROR) { - ALOGE("Failed to get display state"); + ALOGE("Failed to get current display status of %lX. " + "This display will be ignored.", id); return nullptr; } - const ui::Size& resolution = mDpyConfig.resolution; - auto width = resolution.getWidth(); - auto height = resolution.getHeight(); + auto displayWidth = displayConfig.resolution.getWidth(); + auto displayHeight = displayConfig.resolution.getHeight(); + if ((displayState.orientation != ui::ROTATION_0) && + (displayState.orientation != ui::ROTATION_180)) { + std::swap(displayWidth, displayHeight); + } - if (mDpyState.orientation == ui::ROTATION_90 || - mDpyState.orientation == ui::ROTATION_270) { - std::swap(width, height); + sp<android::SurfaceComposerClient> surfaceClient = new SurfaceComposerClient(); + err = surfaceClient->initCheck(); + if (err != NO_ERROR) { + ALOGE("SurfaceComposerClient::initCheck error: %#x", err); + return nullptr; } - mSurfaceControl = mSurfaceComposerClient->createSurface( - String8("Automotive Display"), width, height, + // Create a SurfaceControl instance + surfaceControl = surfaceClient->createSurface( + String8::format("AutomotiveDisplay::%lX", id), + displayWidth, displayHeight, PIXEL_FORMAT_RGBX_8888, ISurfaceComposerClient::eOpaque); - if (mSurfaceControl == nullptr || !mSurfaceControl->isValid()) { - ALOGE("Failed to create SurfaceControl"); - mSurfaceComposerClient = nullptr; - mSurfaceControl = nullptr; + if (surfaceControl == nullptr || !surfaceControl->isValid()) { + ALOGE("Failed to create SurfaceControl."); return nullptr; } - // SurfaceControl::getSurface is guaranteed to be not null. - mSurface = mSurfaceControl->getSurface(); + // 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( - mSurface->getIGraphicBufferProducer()); + B2HGraphicBufferProducer(targetSurface->getIGraphicBufferProducer()); } -Return<bool> AutomotiveDisplayProxyService::showWindow() { - status_t status = NO_ERROR; - if (mSurfaceControl != nullptr) { - status = SurfaceComposerClient::Transaction{} - .setLayer( - mSurfaceControl, 0x7FFFFFFF) // always on top - .show(mSurfaceControl) - .apply(); - } else { - ALOGE("showWindow: Failed to get a valid SurfaceControl!"); +Return<bool> 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", 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<bool> AutomotiveDisplayProxyService::hideWindow() { - status_t status = NO_ERROR; - if (mSurfaceControl != nullptr) { - status = SurfaceComposerClient::Transaction{} - .hide(mSurfaceControl) - .apply(); - } else { - ALOGE("hideWindow: Failed to get a valid SurfaceControl!"); +Return<bool> 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<void> AutomotiveDisplayProxyService::getDisplayIdList(getDisplayIdList_cb _cb) { + hardware::hidl_vec<uint64_t> 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]; + } + + _cb(ids); + return hardware::Void(); +} + + +Return<void> AutomotiveDisplayProxyService::getDisplayInfo(uint64_t id, getDisplayInfo_cb _cb) { + HwDisplayConfig activeConfig; + HwDisplayState activeState; + + auto displayToken = SurfaceComposerClient::getPhysicalDisplayToken(id); + if (displayToken == nullptr) { + ALOGE("Given display id, 0x%lX, is invalid.", id); + } else { + DisplayConfig displayConfig = {}; + auto err = SurfaceComposerClient::getActiveDisplayConfig(displayToken, &displayConfig); + if (err != NO_ERROR) { + ALOGW("Failed to get display configuration of %lX. " + "This display will be ignored.", 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.", id); + } + + activeConfig.setToExternal((uint8_t*)&displayConfig, sizeof(DisplayConfig)); + activeState.setToExternal((uint8_t*)&displayState, sizeof(DisplayState)); + } + + _cb(activeConfig, activeState); + return hardware::Void(); +} + + } // namespace implementation } // namespace V1_0 } // namespace display diff --git a/services/automotive/display/include/AutomotiveDisplayProxyService.h b/services/automotive/display/include/AutomotiveDisplayProxyService.h index 3956602477..e2fc0d2eec 100644 --- a/services/automotive/display/include/AutomotiveDisplayProxyService.h +++ b/services/automotive/display/include/AutomotiveDisplayProxyService.h @@ -16,12 +16,14 @@ #pragma once #include <android/frameworks/automotive/display/1.0/IAutomotiveDisplayProxyService.h> -#include <gui/ISurfaceComposer.h> #include <gui/IGraphicBufferProducer.h> +#include <gui/ISurfaceComposer.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> #include <ui/DisplayConfig.h> #include <ui/DisplayState.h> +#include <tuple> +#include <vector> namespace android { namespace frameworks { @@ -31,32 +33,30 @@ namespace V1_0 { namespace implementation { using ::android::hardware::Return; -using ::android::sp; using ::android::hardware::graphics::bufferqueue::V2_0::IGraphicBufferProducer; +using ::android::sp; -class AutomotiveDisplayProxyService : public IAutomotiveDisplayProxyService { -public: - Return<sp<IGraphicBufferProducer>> getIGraphicBufferProducer() override; - Return<bool> showWindow() override; - Return<bool> hideWindow() override; - Return<void> getDisplayInfo(getDisplayInfo_cb _info_cb) override { - HwDisplayConfig cfg; - cfg.setToExternal((uint8_t*)&mDpyConfig, sizeof(DisplayConfig)); - HwDisplayState state; - state.setToExternal((uint8_t*)&mDpyState, sizeof(DisplayState)); +typedef struct DisplayDesc { + sp<IBinder> token; + sp<SurfaceControl> surfaceControl; +} DisplayDesc; - _info_cb(cfg, state); - return hardware::Void(); - } + +class AutomotiveDisplayProxyService : public IAutomotiveDisplayProxyService { +public: + Return<sp<IGraphicBufferProducer>> getIGraphicBufferProducer(uint64_t id) override; + Return<bool> showWindow(uint64_t id) override; + Return<bool> hideWindow(uint64_t id) override; + Return<void> getDisplayIdList(getDisplayIdList_cb _cb) override; + Return<void> getDisplayInfo(uint64_t, getDisplayInfo_cb _cb) override; private: - sp<android::Surface> mSurface; - sp<android::SurfaceComposerClient> mSurfaceComposerClient; - sp<android::SurfaceControl> mSurfaceControl; - DisplayConfig mDpyConfig; - ui::DisplayState mDpyState; + uint8_t getDisplayPort(const uint64_t id) { return (id & 0xF); } + + std::unordered_map<uint64_t, DisplayDesc> mDisplays; }; + } // namespace implementation } // namespace V1_0 } // namespace display diff --git a/services/automotive/display/main_automotivedisplayproxy.cpp b/services/automotive/display/main_automotivedisplayproxy.cpp index 626c1852c9..59b584cd46 100644 --- a/services/automotive/display/main_automotivedisplayproxy.cpp +++ b/services/automotive/display/main_automotivedisplayproxy.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "AutomotiveDisplayService" - #include <unistd.h> #include <hidl/HidlTransportSupport.h> @@ -39,9 +37,10 @@ using namespace android; const static char kServiceName[] = "default"; int main() { - ALOGI("Car Window Service is starting"); + ALOGI("Automotive Display Proxy Service is starting"); - android::sp<IAutomotiveDisplayProxyService> service = new AutomotiveDisplayProxyService(); + android::sp<IAutomotiveDisplayProxyService> service = + new AutomotiveDisplayProxyService(); configureRpcThreadpool(1, true /* callerWillJoin */); @@ -56,7 +55,7 @@ int main() { } // In normal operation, we don't expect the thread pool to exit - ALOGE("Car Window Service is shutting down"); + ALOGE("Automotive Window Service is shutting down"); return 1; } |