Add type to DisplayViewport

Add type to DisplayViewport. Store a single array of viewports, but
only allow 1 internal and 1 external viewport for now.
DisplayManagerService now totally in charge of the viewports.

Bug: 111108021
Test: atest -a libinput_tests inputflinger_tests
Change-Id: Iac3dbc2e4a61b9609344db475d29bcdc7c167b1c
diff --git a/include/input/DisplayViewport.h b/include/input/DisplayViewport.h
index 0f336dd..0de3bb7 100644
--- a/include/input/DisplayViewport.h
+++ b/include/input/DisplayViewport.h
@@ -17,11 +17,37 @@
 #ifndef _LIBINPUT_DISPLAY_VIEWPORT_H
 #define _LIBINPUT_DISPLAY_VIEWPORT_H
 
+#include <android-base/stringprintf.h>
 #include <ui/DisplayInfo.h>
 #include <input/Input.h>
 
+using android::base::StringPrintf;
+
 namespace android {
 
+/**
+ * Describes the different type of viewports supported by input flinger.
+ * Keep in sync with values in InputManagerService.java.
+ */
+enum class ViewportType : int32_t {
+    VIEWPORT_INTERNAL = 1,
+    VIEWPORT_EXTERNAL = 2,
+    VIEWPORT_VIRTUAL = 3,
+};
+
+static const char* viewportTypeToString(ViewportType type) {
+    switch(type) {
+        case ViewportType::VIEWPORT_INTERNAL:
+            return "INTERNAL";
+        case ViewportType::VIEWPORT_EXTERNAL:
+            return "EXTERNAL";
+        case ViewportType::VIEWPORT_VIRTUAL:
+            return "VIRTUAL";
+        default:
+            return "UNKNOWN";
+    }
+}
+
 /*
  * Describes how coordinates are mapped on a physical display.
  * See com.android.server.display.DisplayViewport.
@@ -40,12 +66,13 @@
     int32_t deviceWidth;
     int32_t deviceHeight;
     std::string uniqueId;
+    ViewportType type;
 
     DisplayViewport() :
             displayId(ADISPLAY_ID_NONE), orientation(DISPLAY_ORIENTATION_0),
             logicalLeft(0), logicalTop(0), logicalRight(0), logicalBottom(0),
             physicalLeft(0), physicalTop(0), physicalRight(0), physicalBottom(0),
-            deviceWidth(0), deviceHeight(0), uniqueId() {
+            deviceWidth(0), deviceHeight(0), uniqueId(), type(ViewportType::VIEWPORT_INTERNAL) {
     }
 
     bool operator==(const DisplayViewport& other) const {
@@ -61,7 +88,8 @@
                 && physicalBottom == other.physicalBottom
                 && deviceWidth == other.deviceWidth
                 && deviceHeight == other.deviceHeight
-                && uniqueId == other.uniqueId;
+                && uniqueId == other.uniqueId
+                && type == other.type;
     }
 
     bool operator!=(const DisplayViewport& other) const {
@@ -86,17 +114,22 @@
         deviceWidth = width;
         deviceHeight = height;
         uniqueId.clear();
+        type = ViewportType::VIEWPORT_INTERNAL;
     }
-};
 
-/**
- * Describes the different type of viewports supported by input flinger.
- * Keep in sync with values in InputManagerService.java.
- */
-enum class ViewportType : int32_t {
-    VIEWPORT_INTERNAL = 1,
-    VIEWPORT_EXTERNAL = 2,
-    VIEWPORT_VIRTUAL = 3,
+    std::string toString() const {
+        return StringPrintf("Viewport %s: displayId=%d, orientation=%d, "
+            "logicalFrame=[%d, %d, %d, %d], "
+            "physicalFrame=[%d, %d, %d, %d], "
+            "deviceSize=[%d, %d]",
+            viewportTypeToString(type),
+            displayId, orientation,
+            logicalLeft, logicalTop,
+            logicalRight, logicalBottom,
+            physicalLeft, physicalTop,
+            physicalRight, physicalBottom,
+            deviceWidth, deviceHeight);
+    }
 };
 
 } // namespace android
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 8f12129..528e937 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -258,64 +258,36 @@
 
 bool InputReaderConfiguration::getDisplayViewport(ViewportType viewportType,
         const std::string& uniqueDisplayId, DisplayViewport* outViewport) const {
-    const DisplayViewport* viewport = nullptr;
-    if (viewportType == ViewportType::VIEWPORT_VIRTUAL && !uniqueDisplayId.empty()) {
-
-        for (const DisplayViewport& currentViewport : mVirtualDisplays) {
-            if (currentViewport.uniqueId == uniqueDisplayId) {
-                viewport = &currentViewport;
-                break;
+    for (const DisplayViewport& currentViewport : mDisplays) {
+        // for virtual displays, uniqueId must match
+        if (viewportType == ViewportType::VIEWPORT_VIRTUAL) {
+            if (currentViewport.type == ViewportType::VIEWPORT_VIRTUAL
+                    && currentViewport.uniqueId == uniqueDisplayId) {
+                *outViewport = currentViewport;
+                return true;
             }
+        } else if (viewportType == currentViewport.type) {
+            // there can only be 1 internal or external viewport, for now
+            *outViewport = currentViewport;
+            return true;
         }
-    } else if (viewportType == ViewportType::VIEWPORT_EXTERNAL) {
-        viewport = &mExternalDisplay;
-    } else if (viewportType == ViewportType::VIEWPORT_INTERNAL) {
-        viewport = &mInternalDisplay;
-    }
-
-    if (viewport != nullptr && viewport->displayId >= 0) {
-        *outViewport = *viewport;
-        return true;
     }
     return false;
 }
 
-void InputReaderConfiguration::setPhysicalDisplayViewport(ViewportType viewportType,
-        const DisplayViewport& viewport) {
-    if (viewportType == ViewportType::VIEWPORT_EXTERNAL) {
-        mExternalDisplay = viewport;
-    } else if (viewportType == ViewportType::VIEWPORT_INTERNAL) {
-        mInternalDisplay = viewport;
-    }
-}
-
-void InputReaderConfiguration::setVirtualDisplayViewports(
-        const Vector<DisplayViewport>& viewports) {
-    mVirtualDisplays = viewports;
+void InputReaderConfiguration::setDisplayViewports(const std::vector<DisplayViewport>& viewports) {
+    mDisplays = viewports;
 }
 
 void InputReaderConfiguration::dump(std::string& dump) const {
-    dump += INDENT4 "ViewportInternal:\n";
-    dumpViewport(dump, mInternalDisplay);
-    dump += INDENT4 "ViewportExternal:\n";
-    dumpViewport(dump, mExternalDisplay);
-    dump += INDENT4 "ViewportVirtual:\n";
-    for (const DisplayViewport& viewport : mVirtualDisplays) {
+    for (const DisplayViewport& viewport : mDisplays) {
         dumpViewport(dump, viewport);
     }
 }
 
-void InputReaderConfiguration::dumpViewport(std::string& dump, const DisplayViewport& viewport) const {
-    dump += StringPrintf(INDENT5 "Viewport: displayId=%d, orientation=%d, uniqueId='%s', "
-            "logicalFrame=[%d, %d, %d, %d], "
-            "physicalFrame=[%d, %d, %d, %d], "
-            "deviceSize=[%d, %d]\n",
-            viewport.displayId, viewport.orientation, viewport.uniqueId.c_str(),
-            viewport.logicalLeft, viewport.logicalTop,
-            viewport.logicalRight, viewport.logicalBottom,
-            viewport.physicalLeft, viewport.physicalTop,
-            viewport.physicalRight, viewport.physicalBottom,
-            viewport.deviceWidth, viewport.deviceHeight);
+void InputReaderConfiguration::dumpViewport(std::string& dump, const DisplayViewport& viewport)
+        const {
+    dump += StringPrintf(INDENT4 "%s\n", viewport.toString().c_str());
 }
 
 
@@ -3600,6 +3572,12 @@
                 break;
             }
 
+            if (naturalPhysicalHeight == 0 || naturalPhysicalWidth == 0) {
+                ALOGE("Viewport is not set properly: %s", mViewport.toString().c_str());
+                naturalPhysicalHeight = naturalPhysicalHeight == 0 ? 1 : naturalPhysicalHeight;
+                naturalPhysicalWidth = naturalPhysicalWidth == 0 ? 1 : naturalPhysicalWidth;
+            }
+
             mPhysicalWidth = naturalPhysicalWidth;
             mPhysicalHeight = naturalPhysicalHeight;
             mPhysicalLeft = naturalPhysicalLeft;
@@ -3913,17 +3891,7 @@
 }
 
 void TouchInputMapper::dumpSurface(std::string& dump) {
-    dump += StringPrintf(INDENT3 "Viewport: displayId=%d, orientation=%d, "
-            "logicalFrame=[%d, %d, %d, %d], "
-            "physicalFrame=[%d, %d, %d, %d], "
-            "deviceSize=[%d, %d]\n",
-            mViewport.displayId, mViewport.orientation,
-            mViewport.logicalLeft, mViewport.logicalTop,
-            mViewport.logicalRight, mViewport.logicalBottom,
-            mViewport.physicalLeft, mViewport.physicalTop,
-            mViewport.physicalRight, mViewport.physicalBottom,
-            mViewport.deviceWidth, mViewport.deviceHeight);
-
+    dump += StringPrintf(INDENT3 "%s\n", mViewport.toString().c_str());
     dump += StringPrintf(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth);
     dump += StringPrintf(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight);
     dump += StringPrintf(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft);
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index c06168d..74668b7 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -38,6 +38,7 @@
 #include <optional>
 #include <stddef.h>
 #include <unistd.h>
+#include <vector>
 
 // Maximum supported size of a vibration pattern.
 // Must be at least 2.
@@ -203,17 +204,14 @@
 
     bool getDisplayViewport(ViewportType viewportType, const std::string& uniqueDisplayId,
             DisplayViewport* outViewport) const;
-    void setPhysicalDisplayViewport(ViewportType viewportType, const DisplayViewport& viewport);
-    void setVirtualDisplayViewports(const Vector<DisplayViewport>& viewports);
+    void setDisplayViewports(const std::vector<DisplayViewport>& viewports);
 
 
     void dump(std::string& dump) const;
     void dumpViewport(std::string& dump, const DisplayViewport& viewport) const;
 
 private:
-    DisplayViewport mInternalDisplay;
-    DisplayViewport mExternalDisplay;
-    Vector<DisplayViewport> mVirtualDisplays;
+    std::vector<DisplayViewport> mDisplays;
 };
 
 
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 9b985dc..b70ee09 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -132,6 +132,7 @@
     InputReaderConfiguration mConfig;
     KeyedVector<int32_t, sp<FakePointerController> > mPointerControllers;
     Vector<InputDeviceInfo> mInputDevices;
+    std::vector<DisplayViewport> mViewports;
     TouchAffineTransformation transform;
 
 protected:
@@ -143,17 +144,20 @@
 
     void setDisplayViewport(int32_t displayId, int32_t width, int32_t height, int32_t orientation,
             const std::string& uniqueId) {
-        DisplayViewport v = createDisplayViewport(displayId, width, height, orientation, uniqueId);
+        mViewports.clear();
         // Set the size of both the internal and external display at the same time.
-        mConfig.setPhysicalDisplayViewport(ViewportType::VIEWPORT_INTERNAL, v);
-        mConfig.setPhysicalDisplayViewport(ViewportType::VIEWPORT_EXTERNAL, v);
+        mViewports.push_back(createDisplayViewport(displayId, width, height, orientation, uniqueId,
+                ViewportType::VIEWPORT_INTERNAL));
+        mViewports.push_back(createDisplayViewport(displayId, width, height, orientation, uniqueId,
+                ViewportType::VIEWPORT_EXTERNAL));
+        mConfig.setDisplayViewports(mViewports);
     }
 
     void setVirtualDisplayViewport(int32_t displayId, int32_t width, int32_t height, int32_t orientation,
             const std::string& uniqueId) {
-        Vector<DisplayViewport> viewports;
-        viewports.push_back(createDisplayViewport(displayId, width, height, orientation, uniqueId));
-        mConfig.setVirtualDisplayViewports(viewports);
+        mViewports.push_back(createDisplayViewport(displayId, width, height, orientation, uniqueId,
+                ViewportType::VIEWPORT_VIRTUAL));
+        mConfig.setDisplayViewports(mViewports);
     }
 
     void addExcludedDeviceName(const std::string& deviceName) {
@@ -203,7 +207,7 @@
 
 private:
     DisplayViewport createDisplayViewport(int32_t displayId, int32_t width, int32_t height,
-            int32_t orientation, const std::string& uniqueId) {
+            int32_t orientation, const std::string& uniqueId, ViewportType type) {
         bool isRotated = (orientation == DISPLAY_ORIENTATION_90
                 || orientation == DISPLAY_ORIENTATION_270);
         DisplayViewport v;
@@ -220,6 +224,7 @@
         v.deviceWidth = isRotated ? height : width;
         v.deviceHeight = isRotated ? width : height;
         v.uniqueId = uniqueId;
+        v.type = type;
         return v;
     }