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>
diff --git a/services/automotive/display/AutomotiveDisplayProxyService.cpp b/services/automotive/display/AutomotiveDisplayProxyService.cpp
index 3cd8e39..8f57dcd 100644
--- a/services/automotive/display/AutomotiveDisplayProxyService.cpp
+++ b/services/automotive/display/AutomotiveDisplayProxyService.cpp
@@ -27,97 +27,163 @@
 namespace V1_0 {
 namespace implementation {
 
-Return<sp<IGraphicBufferProducer>>
-AutomotiveDisplayProxyService::getIGraphicBufferProducer() {
-    if (mSurface == nullptr) {
-        status_t err;
-        mSurfaceComposerClient = new SurfaceComposerClient();
 
-        err = mSurfaceComposerClient->initCheck();
+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("Given display id, 0x%lX, is invalid.", id);
+            return nullptr;
+        }
+
+        // Get the resolution from stored display state.
+        DisplayConfig displayConfig = {};
+        auto err = SurfaceComposerClient::getActiveDisplayConfig(displayToken, &displayConfig);
+        if (err != NO_ERROR) {
+            ALOGE("Failed to get display configuration of %lX.  "
+                  "This display will be ignored.", 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.", id);
+            return nullptr;
+        }
+
+        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);
+        }
+
+        sp<android::SurfaceComposerClient> surfaceClient = new SurfaceComposerClient();
+        err = surfaceClient->initCheck();
         if (err != NO_ERROR) {
             ALOGE("SurfaceComposerClient::initCheck error: %#x", err);
-            mSurfaceComposerClient = nullptr;
             return nullptr;
         }
 
-        const auto displayToken = SurfaceComposerClient::getInternalDisplayToken();
-        if (displayToken == nullptr) {
-            ALOGE("Failed to get internal display ");
-            return nullptr;
-        }
-
-        err = SurfaceComposerClient::getActiveDisplayConfig(displayToken, &mDpyConfig);
-        if (err != NO_ERROR) {
-            ALOGE("Failed to get active display config");
-            return nullptr;
-        }
-
-        err = SurfaceComposerClient::getDisplayState(displayToken, &mDpyState);
-        if (err != NO_ERROR) {
-            ALOGE("Failed to get display state");
-            return nullptr;
-        }
-
-        const ui::Size& resolution = mDpyConfig.resolution;
-        auto width = resolution.getWidth();
-        auto height = resolution.getHeight();
-
-        if (mDpyState.orientation == ui::ROTATION_90 ||
-            mDpyState.orientation == ui::ROTATION_270) {
-            std::swap(width, height);
-        }
-
-        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