Merge "Remove PointerProperties::copyFrom" into main
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index 035d96d..2aaddf5 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -66,38 +66,23 @@
     return enabled;
 }
 
-std::list<NotifyArgs> InputDevice::updateEnableState(nsecs_t when,
-                                                     const InputReaderConfiguration& readerConfig,
-                                                     bool forceEnable) {
-    bool enable = true;
-    if (!forceEnable) {
-        // If the device was explicitly disabled by the user, it would be present in the
-        // "disabledDevices" list. This device should be disabled.
-        enable = readerConfig.disabledDevices.find(mId) == readerConfig.disabledDevices.end();
-
-        // If a device is associated with a specific display but there is no
-        // associated DisplayViewport, don't enable the device.
-        if (enable && (mAssociatedDisplayPort || mAssociatedDisplayUniqueId) &&
-            !mAssociatedViewport) {
-            const std::string desc = mAssociatedDisplayPort
-                    ? "port " + std::to_string(*mAssociatedDisplayPort)
-                    : "uniqueId " + *mAssociatedDisplayUniqueId;
-            ALOGW("Cannot enable input device %s because it is associated "
-                  "with %s, but the corresponding viewport is not found",
-                  getName().c_str(), desc.c_str());
-            enable = false;
-        }
+std::list<NotifyArgs> InputDevice::setEnabled(bool enabled, nsecs_t when) {
+    std::list<NotifyArgs> out;
+    if (enabled && mAssociatedDisplayPort && !mAssociatedViewport) {
+        ALOGW("Cannot enable input device %s because it is associated with port %" PRIu8 ", "
+              "but the corresponding viewport is not found",
+              getName().c_str(), *mAssociatedDisplayPort);
+        enabled = false;
     }
 
-    std::list<NotifyArgs> out;
-    if (isEnabled() == enable) {
+    if (isEnabled() == enabled) {
         return out;
     }
 
     // When resetting some devices, the driver needs to be queried to ensure that a proper reset is
     // performed. The querying must happen when the device is enabled, so we reset after enabling
     // but before disabling the device. See MultiTouchMotionAccumulator::reset for more information.
-    if (enable) {
+    if (enabled) {
         for_each_subdevice([](auto& context) { context.enableDevice(); });
         out += reset(when);
     } else {
@@ -173,23 +158,18 @@
     mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
 }
 
-[[nodiscard]] std::list<NotifyArgs> InputDevice::addEventHubDevice(
-        nsecs_t when, int32_t eventHubId, const InputReaderConfiguration& readerConfig) {
+void InputDevice::addEventHubDevice(int32_t eventHubId,
+                                    const InputReaderConfiguration& readerConfig) {
     if (mDevices.find(eventHubId) != mDevices.end()) {
-        return {};
+        return;
     }
+    std::unique_ptr<InputDeviceContext> contextPtr(new InputDeviceContext(*this, eventHubId));
+    std::vector<std::unique_ptr<InputMapper>> mappers = createMappers(*contextPtr, readerConfig);
 
-    // Add an empty device configure and keep it enabled to allow mapper population
-    // with correct configuration/context
-    addEmptyEventHubDevice(eventHubId);
-    std::list<NotifyArgs> out = configure(when, readerConfig, {}, /*forceEnable=*/true);
-
-    DevicePair& devicePair = mDevices[eventHubId];
-    devicePair.second = createMappers(*devicePair.first, readerConfig);
-
+    // insert the context into the devices set
+    mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
     // Must change generation to flag this device as changed
     bumpGeneration();
-    return out;
 }
 
 void InputDevice::removeEventHubDevice(int32_t eventHubId) {
@@ -202,7 +182,7 @@
 
 std::list<NotifyArgs> InputDevice::configure(nsecs_t when,
                                              const InputReaderConfiguration& readerConfig,
-                                             ConfigurationChanges changes, bool forceEnable) {
+                                             ConfigurationChanges changes) {
     std::list<NotifyArgs> out;
     mSources = 0;
     mClasses = ftl::Flags<InputDeviceClass>(0);
@@ -272,6 +252,15 @@
             }
         }
 
+        if (changes.test(Change::ENABLED_STATE)) {
+            // Do not execute this code on the first configure, because 'setEnabled' would call
+            // InputMapper::reset, and you can't reset a mapper before it has been configured.
+            // The mappers are configured for the first time at the bottom of this function.
+            auto it = readerConfig.disabledDevices.find(mId);
+            bool enabled = it == readerConfig.disabledDevices.end();
+            out += setEnabled(enabled, when);
+        }
+
         if (!changes.any() || changes.test(Change::DISPLAY_INFO)) {
             // In most situations, no port or name will be specified.
             mAssociatedDisplayPort = std::nullopt;
@@ -295,8 +284,12 @@
                 }
             }
 
-            // If it is associated with a specific display, then find the corresponding viewport
-            // which will be used to enable/disable the device.
+            // If the device was explicitly disabled by the user, it would be present in the
+            // "disabledDevices" list. If it is associated with a specific display, and it was not
+            // explicitly disabled, then enable/disable the device based on whether we can find the
+            // corresponding viewport.
+            bool enabled =
+                    (readerConfig.disabledDevices.find(mId) == readerConfig.disabledDevices.end());
             if (mAssociatedDisplayPort) {
                 mAssociatedViewport =
                         readerConfig.getDisplayViewportByPort(*mAssociatedDisplayPort);
@@ -304,6 +297,7 @@
                     ALOGW("Input device %s should be associated with display on port %" PRIu8 ", "
                           "but the corresponding viewport is not found.",
                           getName().c_str(), *mAssociatedDisplayPort);
+                    enabled = false;
                 }
             } else if (mAssociatedDisplayUniqueId != std::nullopt) {
                 mAssociatedViewport =
@@ -312,21 +306,30 @@
                     ALOGW("Input device %s should be associated with display %s but the "
                           "corresponding viewport cannot be found",
                           getName().c_str(), mAssociatedDisplayUniqueId->c_str());
+                    enabled = false;
                 }
             }
-        }
 
-        if (!changes.any() || changes.test(Change::ENABLED_STATE) ||
-            changes.test(Change::DISPLAY_INFO)) {
-            // Whether a device is enabled can depend on the display association,
-            // so update the enabled state when there is a change in display info.
-            out += updateEnableState(when, readerConfig, forceEnable);
+            if (changes.any()) {
+                // For first-time configuration, only allow device to be disabled after mappers have
+                // finished configuring. This is because we need to read some of the properties from
+                // the device's open fd.
+                out += setEnabled(enabled, when);
+            }
         }
 
         for_each_mapper([this, when, &readerConfig, changes, &out](InputMapper& mapper) {
             out += mapper.reconfigure(when, readerConfig, changes);
             mSources |= mapper.getSources();
         });
+
+        // If a device is just plugged but it might be disabled, we need to update some info like
+        // axis range of touch from each InputMapper first, then disable it.
+        if (!changes.any()) {
+            out += setEnabled(readerConfig.disabledDevices.find(mId) ==
+                                      readerConfig.disabledDevices.end(),
+                              when);
+        }
     }
     return out;
 }
@@ -519,9 +522,9 @@
         classes.test(InputDeviceClass::TOUCH_MT) && !isSonyDualShock4Touchpad) {
         mappers.push_back(createInputMapper<TouchpadInputMapper>(contextPtr, readerConfig));
     } else if (classes.test(InputDeviceClass::TOUCH_MT)) {
-        mappers.push_back(createInputMapper<MultiTouchInputMapper>(contextPtr, readerConfig));
+        mappers.push_back(std::make_unique<MultiTouchInputMapper>(contextPtr, readerConfig));
     } else if (classes.test(InputDeviceClass::TOUCH)) {
-        mappers.push_back(createInputMapper<SingleTouchInputMapper>(contextPtr, readerConfig));
+        mappers.push_back(std::make_unique<SingleTouchInputMapper>(contextPtr, readerConfig));
     }
 
     // Joystick-like devices.
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 7d0f28b..ea95f78 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -234,7 +234,7 @@
     }
 
     InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(eventHubId);
-    std::shared_ptr<InputDevice> device = createDeviceLocked(when, eventHubId, identifier);
+    std::shared_ptr<InputDevice> device = createDeviceLocked(eventHubId, identifier);
 
     notifyAll(device->configure(when, mConfig, /*changes=*/{}));
     notifyAll(device->reset(when));
@@ -319,7 +319,7 @@
 }
 
 std::shared_ptr<InputDevice> InputReader::createDeviceLocked(
-        nsecs_t when, int32_t eventHubId, const InputDeviceIdentifier& identifier) {
+        int32_t eventHubId, const InputDeviceIdentifier& identifier) {
     auto deviceIt = std::find_if(mDevices.begin(), mDevices.end(), [identifier](auto& devicePair) {
         const InputDeviceIdentifier identifier2 =
                 devicePair.second->getDeviceInfo().getIdentifier();
@@ -334,7 +334,7 @@
         device = std::make_shared<InputDevice>(&mContext, deviceId, bumpGenerationLocked(),
                                                identifier);
     }
-    notifyAll(device->addEventHubDevice(when, eventHubId, mConfig));
+    device->addEventHubDevice(eventHubId, mConfig);
     return device;
 }
 
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index d92f4a2..aae3fe7 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -77,16 +77,15 @@
     inline bool isIgnored() { return !getMapperCount() && !mController; }
 
     bool isEnabled();
+    [[nodiscard]] std::list<NotifyArgs> setEnabled(bool enabled, nsecs_t when);
 
     void dump(std::string& dump, const std::string& eventHubDevStr);
     void addEmptyEventHubDevice(int32_t eventHubId);
-    [[nodiscard]] std::list<NotifyArgs> addEventHubDevice(
-            nsecs_t when, int32_t eventHubId, const InputReaderConfiguration& readerConfig);
+    void addEventHubDevice(int32_t eventHubId, const InputReaderConfiguration& readerConfig);
     void removeEventHubDevice(int32_t eventHubId);
     [[nodiscard]] std::list<NotifyArgs> configure(nsecs_t when,
                                                   const InputReaderConfiguration& readerConfig,
-                                                  ConfigurationChanges changes,
-                                                  bool forceEnable = false);
+                                                  ConfigurationChanges changes);
     [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when);
     [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvents, size_t count);
     [[nodiscard]] std::list<NotifyArgs> timeoutExpired(nsecs_t when);
@@ -207,9 +206,6 @@
     std::vector<std::unique_ptr<InputMapper>> createMappers(
             InputDeviceContext& contextPtr, const InputReaderConfiguration& readerConfig);
 
-    [[nodiscard]] std::list<NotifyArgs> updateEnableState(
-            nsecs_t when, const InputReaderConfiguration& readerConfig, bool forceEnable = false);
-
     PropertyMap mConfiguration;
 
     // Runs logic post a `process` call. This can be used to update the generated `NotifyArgs` as
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 391a889..9112913 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -121,7 +121,7 @@
 
 protected:
     // These members are protected so they can be instrumented by test cases.
-    virtual std::shared_ptr<InputDevice> createDeviceLocked(nsecs_t when, int32_t deviceId,
+    virtual std::shared_ptr<InputDevice> createDeviceLocked(int32_t deviceId,
                                                             const InputDeviceIdentifier& identifier)
             REQUIRES(mLock);
 
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
index 1d788df..f300ee1 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
@@ -27,6 +27,8 @@
     friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
                                                 const InputReaderConfiguration& readerConfig,
                                                 Args... args);
+    explicit MultiTouchInputMapper(InputDeviceContext& deviceContext,
+                                   const InputReaderConfiguration& readerConfig);
 
     ~MultiTouchInputMapper() override;
 
@@ -39,8 +41,6 @@
     bool hasStylus() const override;
 
 private:
-    explicit MultiTouchInputMapper(InputDeviceContext& deviceContext,
-                                   const InputReaderConfiguration& readerConfig);
     // simulate_stylus_with_touch is a debug mode that converts all finger pointers reported by this
     // mapper's touchscreen into stylus pointers, and adds SOURCE_STYLUS to the input device.
     // It is used to simulate stylus events for debugging and testing on a device that does not
diff --git a/services/inputflinger/reader/mapper/SingleTouchInputMapper.h b/services/inputflinger/reader/mapper/SingleTouchInputMapper.h
index 7726bfb..dac53cf 100644
--- a/services/inputflinger/reader/mapper/SingleTouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/SingleTouchInputMapper.h
@@ -27,6 +27,8 @@
     friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
                                                 const InputReaderConfiguration& readerConfig,
                                                 Args... args);
+    explicit SingleTouchInputMapper(InputDeviceContext& deviceContext,
+                                    const InputReaderConfiguration& readerConfig);
 
     ~SingleTouchInputMapper() override;
 
@@ -40,8 +42,6 @@
 
 private:
     SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;
-    explicit SingleTouchInputMapper(InputDeviceContext& deviceContext,
-                                    const InputReaderConfiguration& readerConfig);
 };
 
 } // namespace android
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index f4e471d..e751c89 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -2553,7 +2553,7 @@
 
 // A single input device is associated with a specific display. Check that:
 // 1. Device is disabled if the viewport corresponding to the associated display is not found
-// 2. Device is disabled when configure API is called
+// 2. Device is disabled when setEnabled API is called
 TEST_F(InputDeviceTest, Configure_AssignsDisplayPort) {
     mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
                                         AINPUT_SOURCE_TOUCHSCREEN);
@@ -2660,8 +2660,7 @@
     mFakeEventHub->addDevice(TEST_EVENTHUB_ID, "Test EventHub device", InputDeviceClass::BATTERY);
 
     InputDevice device(mReader->getContext(), /*id=*/1, /*generation=*/2, /*identifier=*/{});
-    auto _ = device.addEventHubDevice(ARBITRARY_TIME, TEST_EVENTHUB_ID,
-                                      mFakePolicy->getReaderConfiguration());
+    device.addEventHubDevice(TEST_EVENTHUB_ID, mFakePolicy->getReaderConfiguration());
     device.removeEventHubDevice(TEST_EVENTHUB_ID);
     std::string dumpStr, eventHubDevStr;
     device.dump(dumpStr, eventHubDevStr);
diff --git a/services/inputflinger/tests/InstrumentedInputReader.cpp b/services/inputflinger/tests/InstrumentedInputReader.cpp
index 110ca5f..1f8cd12 100644
--- a/services/inputflinger/tests/InstrumentedInputReader.cpp
+++ b/services/inputflinger/tests/InstrumentedInputReader.cpp
@@ -38,13 +38,13 @@
 }
 
 std::shared_ptr<InputDevice> InstrumentedInputReader::createDeviceLocked(
-        nsecs_t when, int32_t eventHubId, const InputDeviceIdentifier& identifier) REQUIRES(mLock) {
+        int32_t eventHubId, const InputDeviceIdentifier& identifier) REQUIRES(mLock) {
     if (!mNextDevices.empty()) {
         std::shared_ptr<InputDevice> device(std::move(mNextDevices.front()));
         mNextDevices.pop();
         return device;
     }
-    return InputReader::createDeviceLocked(when, eventHubId, identifier);
+    return InputReader::createDeviceLocked(eventHubId, identifier);
 }
 
 } // namespace android
diff --git a/services/inputflinger/tests/InstrumentedInputReader.h b/services/inputflinger/tests/InstrumentedInputReader.h
index e6bf3f9..7f8d556 100644
--- a/services/inputflinger/tests/InstrumentedInputReader.h
+++ b/services/inputflinger/tests/InstrumentedInputReader.h
@@ -44,7 +44,7 @@
 
 protected:
     virtual std::shared_ptr<InputDevice> createDeviceLocked(
-            nsecs_t when, int32_t eventHubId, const InputDeviceIdentifier& identifier);
+            int32_t eventHubId, const InputDeviceIdentifier& identifier);
 
     class FakeInputReaderContext : public ContextImpl {
     public: