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/Android.bp b/services/automotive/display/Android.bp
index d94fb27..8ff0711 100644
--- a/services/automotive/display/Android.bp
+++ b/services/automotive/display/Android.bp
@@ -36,4 +36,8 @@
     local_include_dirs: [
         "include",
     ],
+
+    cflags: [
+        "-DLOG_TAG=\"AutomotiveDisplayService\""
+    ],
 }
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
diff --git a/services/automotive/display/include/AutomotiveDisplayProxyService.h b/services/automotive/display/include/AutomotiveDisplayProxyService.h
index 3956602..e2fc0d2 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 implementation {
 
 using ::android::hardware::Return;
-using ::android::sp;
 using ::android::hardware::graphics::bufferqueue::V2_0::IGraphicBufferProducer;
+using ::android::sp;
+
+
+typedef struct DisplayDesc {
+    sp<IBinder>        token;
+    sp<SurfaceControl> surfaceControl;
+} DisplayDesc;
+
 
 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));
-
-       _info_cb(cfg, state);
-        return hardware::Void();
-    }
+    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 626c185..59b584c 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 @@
 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 @@
     }
 
     // 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;
 }