diff options
164 files changed, 2923 insertions, 1527 deletions
diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto index 03a2709075..a177027e5c 100644 --- a/cmds/surfacereplayer/proto/src/trace.proto +++ b/cmds/surfacereplayer/proto/src/trace.proto @@ -101,6 +101,10 @@ message LayerStackChange {      required uint32 layer_stack = 1;  } +message DisplayFlagsChange { +    required uint32 flags = 1; +} +  message HiddenFlagChange {      required bool hidden_flag = 1;  } @@ -121,6 +125,7 @@ message DisplayChange {          LayerStackChange  layer_stack = 3;          SizeChange        size        = 4;          ProjectionChange  projection  = 5; +        DisplayFlagsChange flags      = 6;      }  } @@ -217,4 +222,4 @@ message BlurRegionChange {  message Origin {      required int32 pid = 1;      required int32 uid = 2; -}
\ No newline at end of file +} diff --git a/data/etc/Android.bp b/data/etc/Android.bp index 9d88ca64e6..c0cbad8d4f 100644 --- a/data/etc/Android.bp +++ b/data/etc/Android.bp @@ -14,3 +14,11 @@ prebuilt_etc {      src: "android.hardware.biometrics.face.xml",      filename_from_src: true,  } + +prebuilt_etc { +    name: "android.software.app_compat_overrides.xml", +    product_specific: true, +    sub_dir: "permissions", +    src: "android.software.app_compat_overrides.xml", +    filename_from_src: true, +} diff --git a/data/etc/android.software.app_compat_overrides.xml b/data/etc/android.software.app_compat_overrides.xml new file mode 100644 index 0000000000..2f9726a3f0 --- /dev/null +++ b/data/etc/android.software.app_compat_overrides.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2021 The Android Open Source Project + +     Licensed under the Apache License, Version 2.0 (the "License"); +     you may not use this file except in compliance with the License. +     You may obtain a copy of the License at + +          http://www.apache.org/licenses/LICENSE-2.0 + +     Unless required by applicable law or agreed to in writing, software +     distributed under the License is distributed on an "AS IS" BASIS, +     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +     See the License for the specific language governing permissions and +     limitations under the License. +--> + +<!-- Feature for devices that are opted-in to receive per-app compatibility +     overrides. --> +<permissions> +  <feature name="android.software.app_compat_overrides" /> +</permissions> diff --git a/include/input/Flags.h b/include/ftl/Flags.h index b12a9ed2c5..27c84769cb 100644 --- a/include/input/Flags.h +++ b/include/ftl/Flags.h @@ -22,11 +22,10 @@  #include <string>  #include <type_traits> -#include "NamedEnum.h" +#include <ftl/NamedEnum.h>  #include "utils/BitSet.h" -#ifndef __UI_INPUT_FLAGS_H -#define __UI_INPUT_FLAGS_H +#pragma once  namespace android { @@ -279,5 +278,3 @@ Flags<F> operator|(F lhs, F rhs) {  } // namespace flag_operators  } // namespace android - -#endif // __UI_INPUT_FLAGS_H diff --git a/include/input/NamedEnum.h b/include/ftl/NamedEnum.h index 6562348701..f50ff46fe2 100644 --- a/include/input/NamedEnum.h +++ b/include/ftl/NamedEnum.h @@ -21,8 +21,7 @@  #include <optional>  #include <string> -#ifndef __UI_INPUT_NAMEDENUM_H -#define __UI_INPUT_NAMEDENUM_H +#pragma once  namespace android { @@ -124,5 +123,3 @@ public:  };  } // namespace android - -#endif // __UI_INPUT_NAMEDENUM_H
\ No newline at end of file diff --git a/include/input/DisplayViewport.h b/include/input/DisplayViewport.h index 5e40ca7ece..a6213f3ddd 100644 --- a/include/input/DisplayViewport.h +++ b/include/input/DisplayViewport.h @@ -18,8 +18,9 @@  #define _LIBINPUT_DISPLAY_VIEWPORT_H  #include <android-base/stringprintf.h> +#include <ftl/NamedEnum.h> +#include <gui/constants.h>  #include <input/Input.h> -#include <input/NamedEnum.h>  #include <cinttypes>  #include <optional> diff --git a/include/input/Input.h b/include/input/Input.h index 2e326cb102..cd110e8c39 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -124,15 +124,6 @@ constexpr int32_t VERIFIED_MOTION_EVENT_FLAGS = AMOTION_EVENT_FLAG_WINDOW_IS_OBS  constexpr int32_t AMOTION_EVENT_FLAG_CANCELED = 0x20;  enum { -    /* Used when a motion event is not associated with any display. -     * Typically used for non-pointer events. */ -    ADISPLAY_ID_NONE = -1, - -    /* The default display id. */ -    ADISPLAY_ID_DEFAULT = 0, -}; - -enum {      /*       * Indicates that an input device has switches.       * This input source flag is hidden from the API because switches are only used by the system @@ -354,12 +345,6 @@ private:   */  constexpr float AMOTION_EVENT_INVALID_CURSOR_POSITION = std::numeric_limits<float>::quiet_NaN(); -/** - * Invalid value for display size. Used when display size isn't available for an event or doesn't - * matter. This is just a constant 0 so that it has no effect if unused. - */ -constexpr int32_t AMOTION_EVENT_INVALID_DISPLAY_SIZE = 0; -  /*   * Pointer coordinate data.   */ @@ -592,6 +577,8 @@ public:      void setCursorPosition(float x, float y); +    uint32_t getDisplayOrientation() const { return mDisplayOrientation; } +      int2 getDisplaySize() const { return {mDisplayWidth, mDisplayHeight}; }      static inline bool isValidCursorPosition(float x, float y) { return !isnan(x) && !isnan(y); } @@ -768,8 +755,8 @@ public:                      int32_t flags, int32_t edgeFlags, int32_t metaState, int32_t buttonState,                      MotionClassification classification, const ui::Transform& transform,                      float xPrecision, float yPrecision, float rawXCursorPosition, -                    float rawYCursorPosition, int32_t displayWidth, int32_t displayHeight, -                    nsecs_t downTime, nsecs_t eventTime, size_t pointerCount, +                    float rawYCursorPosition, uint32_t displayOrientation, int32_t displayWidth, +                    int32_t displayHeight, nsecs_t downTime, nsecs_t eventTime, size_t pointerCount,                      const PointerProperties* pointerProperties, const PointerCoords* pointerCoords);      void copyFrom(const MotionEvent* other, bool keepHistory); @@ -827,6 +814,7 @@ protected:      float mYPrecision;      float mRawXCursorPosition;      float mRawYCursorPosition; +    uint32_t mDisplayOrientation;      int32_t mDisplayWidth;      int32_t mDisplayHeight;      nsecs_t mDownTime; diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index 360dfbfd73..a790b5637f 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -136,10 +136,10 @@ struct InputMessage {              float yPrecision;              float xCursorPosition;              float yCursorPosition; +            uint32_t displayOrientation;              int32_t displayWidth;              int32_t displayHeight;              uint32_t pointerCount; -            uint32_t empty3;              /**               * The "pointers" field must be the last field of the struct InputMessage.               * When we send the struct InputMessage across the socket, we are not @@ -355,8 +355,9 @@ public:                                  int32_t metaState, int32_t buttonState,                                  MotionClassification classification, const ui::Transform& transform,                                  float xPrecision, float yPrecision, float xCursorPosition, -                                float yCursorPosition, int32_t displayWidth, int32_t displayHeight, -                                nsecs_t downTime, nsecs_t eventTime, uint32_t pointerCount, +                                float yCursorPosition, uint32_t displayOrientation, +                                int32_t displayWidth, int32_t displayHeight, nsecs_t downTime, +                                nsecs_t eventTime, uint32_t pointerCount,                                  const PointerProperties* pointerProperties,                                  const PointerCoords* pointerCoords); diff --git a/libs/ftl/Android.bp b/libs/ftl/Android.bp index 97626bec7d..2524c5f6d2 100644 --- a/libs/ftl/Android.bp +++ b/libs/ftl/Android.bp @@ -14,7 +14,9 @@ cc_test {          address: true,      },      srcs: [ +        "Flags_test.cpp",          "future_test.cpp", +        "NamedEnum_test.cpp",          "small_map_test.cpp",          "small_vector_test.cpp",          "static_vector_test.cpp", @@ -25,4 +27,12 @@ cc_test {          "-Wextra",          "-Wpedantic",      ], + +    header_libs: [ +        "libbase_headers", +    ], + +    shared_libs: [ +        "libbase", +    ],  } diff --git a/libs/input/tests/Flags_test.cpp b/libs/ftl/Flags_test.cpp index 6de030f7cf..8c00b5299b 100644 --- a/libs/input/tests/Flags_test.cpp +++ b/libs/ftl/Flags_test.cpp @@ -15,7 +15,7 @@   */  #include <gtest/gtest.h> -#include <input/Flags.h> +#include <ftl/Flags.h>  #include <type_traits> diff --git a/libs/input/tests/NamedEnum_test.cpp b/libs/ftl/NamedEnum_test.cpp index 74a0044387..dff2b8aaa1 100644 --- a/libs/input/tests/NamedEnum_test.cpp +++ b/libs/ftl/NamedEnum_test.cpp @@ -15,7 +15,7 @@   */  #include <gtest/gtest.h> -#include <input/NamedEnum.h> +#include <ftl/NamedEnum.h>  namespace android { diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 64203f78a8..5cf7a5fe53 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -51,6 +51,58 @@ cc_library_headers {      ],  } +// AIDL files that should be exposed to java +filegroup { +    name: "guiconstants_aidl", +    srcs: [ +        "android/**/TouchOcclusionMode.aidl", +    ], +} + +cc_library_static { +    name: "libgui_window_info_static", +    vendor_available: true, +    host_supported: true, +    srcs: [ +        ":guiconstants_aidl", +        "android/gui/FocusRequest.aidl", +        "android/gui/InputApplicationInfo.aidl", +        "android/gui/IWindowInfosListener.aidl", +        "android/gui/WindowInfo.aidl", +        "WindowInfo.cpp", +    ], + +    shared_libs: [ +        "libbinder", +    ], + +    local_include_dirs: [ +        "include", +    ], + +    export_shared_lib_headers: [ +        "libbinder", +    ], + +    static_libs: [ +        "libui-types", +    ], + +    aidl: { +        export_aidl_headers: true +    }, + +    include_dirs: [ +        "frameworks/native/include", +    ], + +    target: { +        darwin: { +            enabled: false, +        }, +    }, +} +  filegroup {      name: "libgui_aidl",      srcs: ["aidl/**/*.aidl"], @@ -77,12 +129,15 @@ cc_library_static {          "libbinder",      ], +    static_libs: [ +        "libui-types", +    ], +      aidl: {          export_aidl_headers: true      }  } -  cc_library_shared {      name: "libgui",      vendor_available: true, @@ -96,9 +151,11 @@ cc_library_shared {      static_libs: [          "libgui_aidl_static", +        "libgui_window_info_static",      ],      export_static_lib_headers: [          "libgui_aidl_static", +        "libgui_window_info_static",      ],      srcs: [ @@ -139,6 +196,7 @@ cc_library_shared {          "SyncFeatures.cpp",          "TransactionTracing.cpp",          "view/Surface.cpp", +        "WindowInfosListenerReporter.cpp",          "bufferqueue/1.0/B2HProducerListener.cpp",          "bufferqueue/1.0/H2BGraphicBufferProducer.cpp",          "bufferqueue/2.0/B2HProducerListener.cpp", @@ -150,13 +208,11 @@ cc_library_shared {          "libbinder",          "libbufferhub",          "libbufferhubqueue", // TODO(b/70046255): Remove this once BufferHub is integrated into libgui. -        "libinput",          "libpdx_default_transport",      ],      export_shared_lib_headers: [          "libbinder", -        "libinput",      ],      export_header_lib_headers: [ @@ -168,7 +224,6 @@ cc_library_shared {          vendor: {              cflags: [                  "-DNO_BUFFERHUB", -                "-DNO_INPUT",              ],              exclude_srcs: [                  "BufferHubConsumer.cpp", @@ -178,7 +233,6 @@ cc_library_shared {                  "android.frameworks.bufferhub@1.0",                  "libbufferhub",                  "libbufferhubqueue", -                "libinput",                  "libpdx_default_transport",              ],          }, diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 7d57d8b02c..d9024fa672 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -38,7 +38,7 @@  using namespace std::chrono_literals;  namespace { -inline const char* toString(bool b) { +inline const char* boolToString(bool b) {      return b ? "true" : "false";  }  } // namespace @@ -521,7 +521,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) {      BQA_LOGV("processNextBufferLocked size=%dx%d mFrameNumber=%" PRIu64               " applyTransaction=%s mTimestamp=%" PRId64 "%s mPendingTransactions.size=%d"               " graphicBufferId=%" PRIu64 "%s transform=%d", -             mSize.width, mSize.height, bufferItem.mFrameNumber, toString(applyTransaction), +             mSize.width, mSize.height, bufferItem.mFrameNumber, boolToString(applyTransaction),               bufferItem.mTimestamp, bufferItem.mIsAutoTimestamp ? "(auto)" : "",               static_cast<uint32_t>(mPendingTransactions.size()), bufferItem.mGraphicBuffer->getId(),               bufferItem.mAutoRefresh ? " mAutoRefresh" : "", bufferItem.mTransform); @@ -551,7 +551,7 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) {                 mNumFrameAvailable + mNumAcquired - mPendingRelease.size());      BQA_LOGV("onFrameAvailable framenumber=%" PRIu64 " nextTransactionSet=%s", item.mFrameNumber, -             toString(nextTransactionSet)); +             boolToString(nextTransactionSet));      processNextBufferLocked(nextTransactionSet /* useNextTransaction */);  } diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp index 5023b6bb81..2930154ad4 100644 --- a/libs/gui/BufferQueueCore.cpp +++ b/libs/gui/BufferQueueCore.cpp @@ -34,7 +34,6 @@  #include <gui/BufferQueueCore.h>  #include <gui/IConsumerListener.h>  #include <gui/IProducerListener.h> -#include <gui/ISurfaceComposer.h>  #include <private/gui/ComposerService.h>  #include <system/window.h> diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 0d7795e1ba..2a980bd118 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -44,6 +44,7 @@  namespace android { +using gui::IWindowInfosListener;  using ui::ColorMode;  class BpSurfaceComposer : public BpInterface<ISurfaceComposer> @@ -1227,6 +1228,22 @@ public:          return reply.readInt32(buffers);      } + +    status_t addWindowInfosListener( +            const sp<IWindowInfosListener>& windowInfosListener) const override { +        Parcel data, reply; +        SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor()); +        SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(windowInfosListener)); +        return remote()->transact(BnSurfaceComposer::ADD_WINDOW_INFOS_LISTENER, data, &reply); +    } + +    status_t removeWindowInfosListener( +            const sp<IWindowInfosListener>& windowInfosListener) const override { +        Parcel data, reply; +        SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor()); +        SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(windowInfosListener)); +        return remote()->transact(BnSurfaceComposer::REMOVE_WINDOW_INFOS_LISTENER, data, &reply); +    }  };  // Out-of-line virtual method definition to trigger vtable emission in this @@ -2107,6 +2124,20 @@ status_t BnSurfaceComposer::onTransact(              SAFE_PARCEL(reply->writeBool, success);              return err;          } +        case ADD_WINDOW_INFOS_LISTENER: { +            CHECK_INTERFACE(ISurfaceComposer, data, reply); +            sp<IWindowInfosListener> listener; +            SAFE_PARCEL(data.readStrongBinder, &listener); + +            return addWindowInfosListener(listener); +        } +        case REMOVE_WINDOW_INFOS_LISTENER: { +            CHECK_INTERFACE(ISurfaceComposer, data, reply); +            sp<IWindowInfosListener> listener; +            SAFE_PARCEL(data.readStrongBinder, &listener); + +            return removeWindowInfosListener(listener); +        }          default: {              return BBinder::onTransact(code, data, reply, flags);          } diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 076c90dd23..837e5b35f7 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -31,6 +31,9 @@  namespace android { +using gui::FocusRequest; +using gui::WindowInfoHandle; +  layer_state_t::layer_state_t()        : what(0),          x(0), @@ -95,9 +98,7 @@ status_t layer_state_t::write(Parcel& output) const      SAFE_PARCEL(output.writeFloat, color.r);      SAFE_PARCEL(output.writeFloat, color.g);      SAFE_PARCEL(output.writeFloat, color.b); -#ifndef NO_INPUT -    SAFE_PARCEL(inputHandle->writeToParcel, &output); -#endif +    SAFE_PARCEL(windowInfoHandle->writeToParcel, &output);      SAFE_PARCEL(output.write, transparentRegion);      SAFE_PARCEL(output.writeUint32, transform);      SAFE_PARCEL(output.writeBool, transformToDisplayInverse); @@ -207,9 +208,7 @@ status_t layer_state_t::read(const Parcel& input)      color.g = tmpFloat;      SAFE_PARCEL(input.readFloat, &tmpFloat);      color.b = tmpFloat; -#ifndef NO_INPUT -    SAFE_PARCEL(inputHandle->readFromParcel, &input); -#endif +    SAFE_PARCEL(windowInfoHandle->readFromParcel, &input);      SAFE_PARCEL(input.read, transparentRegion);      SAFE_PARCEL(input.readUint32, &transform); @@ -318,6 +317,7 @@ status_t ComposerState::read(const Parcel& input) {  DisplayState::DisplayState()        : what(0),          layerStack(0), +        flags(0),          layerStackSpaceRect(Rect::EMPTY_RECT),          orientedDisplaySpaceRect(Rect::EMPTY_RECT),          width(0), @@ -328,6 +328,7 @@ status_t DisplayState::write(Parcel& output) const {      SAFE_PARCEL(output.writeStrongBinder, IInterface::asBinder(surface));      SAFE_PARCEL(output.writeUint32, what);      SAFE_PARCEL(output.writeUint32, layerStack); +    SAFE_PARCEL(output.writeUint32, flags);      SAFE_PARCEL(output.writeUint32, toRotationInt(orientation));      SAFE_PARCEL(output.write, layerStackSpaceRect);      SAFE_PARCEL(output.write, orientedDisplaySpaceRect); @@ -344,6 +345,7 @@ status_t DisplayState::read(const Parcel& input) {      SAFE_PARCEL(input.readUint32, &what);      SAFE_PARCEL(input.readUint32, &layerStack); +    SAFE_PARCEL(input.readUint32, &flags);      uint32_t tmpUint = 0;      SAFE_PARCEL(input.readUint32, &tmpUint);      orientation = ui::toRotation(tmpUint); @@ -364,6 +366,10 @@ void DisplayState::merge(const DisplayState& other) {          what |= eLayerStackChanged;          layerStack = other.layerStack;      } +    if (other.what & eFlagsChanged) { +        what |= eFlagsChanged; +        flags = other.flags; +    }      if (other.what & eDisplayProjectionChanged) {          what |= eDisplayProjectionChanged;          orientation = other.orientation; @@ -487,14 +493,10 @@ void layer_state_t::merge(const layer_state_t& other) {      if (other.what & eHasListenerCallbacksChanged) {          what |= eHasListenerCallbacksChanged;      } - -#ifndef NO_INPUT      if (other.what & eInputInfoChanged) {          what |= eInputInfoChanged; -        inputHandle = new InputWindowHandle(*other.inputHandle); +        windowInfoHandle = new WindowInfoHandle(*other.windowInfoHandle);      } -#endif -      if (other.what & eCachedBufferChanged) {          what |= eCachedBufferChanged;          cachedBuffer = other.cachedBuffer; @@ -593,11 +595,9 @@ status_t layer_state_t::matrix22_t::read(const Parcel& input) {  bool InputWindowCommands::merge(const InputWindowCommands& other) {      bool changes = false; -#ifndef NO_INPUT      changes |= !other.focusRequests.empty();      focusRequests.insert(focusRequests.end(), std::make_move_iterator(other.focusRequests.begin()),                           std::make_move_iterator(other.focusRequests.end())); -#endif      changes |= other.syncInputWindows && !syncInputWindows;      syncInputWindows |= other.syncInputWindows;      return changes; @@ -605,31 +605,23 @@ bool InputWindowCommands::merge(const InputWindowCommands& other) {  bool InputWindowCommands::empty() const {      bool empty = true; -#ifndef NO_INPUT      empty = focusRequests.empty() && !syncInputWindows; -#endif      return empty;  }  void InputWindowCommands::clear() { -#ifndef NO_INPUT      focusRequests.clear(); -#endif      syncInputWindows = false;  }  status_t InputWindowCommands::write(Parcel& output) const { -#ifndef NO_INPUT      SAFE_PARCEL(output.writeParcelableVector, focusRequests); -#endif      SAFE_PARCEL(output.writeBool, syncInputWindows);      return NO_ERROR;  }  status_t InputWindowCommands::read(const Parcel& input) { -#ifndef NO_INPUT      SAFE_PARCEL(input.readParcelableVector, &focusRequests); -#endif      SAFE_PARCEL(input.readBool, &syncInputWindows);      return NO_ERROR;  } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 96da8efd19..ce9a1f7918 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -19,6 +19,7 @@  #include <stdint.h>  #include <sys/types.h> +#include <android/gui/IWindowInfosListener.h>  #include <utils/Errors.h>  #include <utils/Log.h>  #include <utils/SortedVector.h> @@ -39,14 +40,11 @@  #include <gui/LayerState.h>  #include <gui/Surface.h>  #include <gui/SurfaceComposerClient.h> +#include <gui/WindowInfo.h>  #include <private/gui/ParcelUtils.h>  #include <ui/DisplayMode.h>  #include <ui/DynamicDisplayInfo.h> -#ifndef NO_INPUT -#include <input/InputWindow.h> -#endif -  #include <private/gui/ComposerService.h>  // This server size should always be smaller than the server cache size @@ -54,6 +52,10 @@  namespace android { +using gui::FocusRequest; +using gui::WindowInfo; +using gui::WindowInfoHandle; +using gui::WindowInfosListener;  using ui::ColorMode;  // --------------------------------------------------------------------------- @@ -95,6 +97,7 @@ bool ComposerService::connectLocked() {      if (instance.mComposerService == nullptr) {          if (ComposerService::getInstance().connectLocked()) {              ALOGD("ComposerService reconnected"); +            WindowInfosListenerReporter::getInstance()->reconnect(instance.mComposerService);          }      }      return instance.mComposerService; @@ -1491,16 +1494,14 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrame      return *this;  } -#ifndef NO_INPUT  SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInputWindowInfo( -        const sp<SurfaceControl>& sc, -        const InputWindowInfo& info) { +        const sp<SurfaceControl>& sc, const WindowInfo& info) {      layer_state_t* s = getLayerState(sc);      if (!s) {          mStatus = BAD_INDEX;          return *this;      } -    s->inputHandle = new InputWindowHandle(info); +    s->windowInfoHandle = new WindowInfoHandle(info);      s->what |= layer_state_t::eInputInfoChanged;      return *this;  } @@ -1516,8 +1517,6 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::syncInpu      return *this;  } -#endif -  SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColorTransform(      const sp<SurfaceControl>& sc, const mat3& matrix, const vec3& translation) {      layer_state_t* s = getLayerState(sc); @@ -1758,6 +1757,12 @@ void SurfaceComposerClient::Transaction::setDisplayLayerStack(const sp<IBinder>&      s.what |= DisplayState::eLayerStackChanged;  } +void SurfaceComposerClient::Transaction::setDisplayFlags(const sp<IBinder>& token, uint32_t flags) { +    DisplayState& s(getDisplayState(token)); +    s.flags = flags; +    s.what |= DisplayState::eFlagsChanged; +} +  void SurfaceComposerClient::Transaction::setDisplayProjection(const sp<IBinder>& token,                                                                ui::Rotation orientation,                                                                const Rect& layerStackRect, @@ -1779,15 +1784,10 @@ void SurfaceComposerClient::Transaction::setDisplaySize(const sp<IBinder>& token  // --------------------------------------------------------------------------- -SurfaceComposerClient::SurfaceComposerClient() -    : mStatus(NO_INIT) -{ -} +SurfaceComposerClient::SurfaceComposerClient() : mStatus(NO_INIT) {}  SurfaceComposerClient::SurfaceComposerClient(const sp<ISurfaceComposerClient>& client) -    : mStatus(NO_ERROR), mClient(client) -{ -} +      : mStatus(NO_ERROR), mClient(client) {}  void SurfaceComposerClient::onFirstRef() {      sp<ISurfaceComposer> sf(ComposerService::getComposerService()); @@ -2153,6 +2153,18 @@ int SurfaceComposerClient::getGPUContextPriority() {      return ComposerService::getComposerService()->getGPUContextPriority();  } +status_t SurfaceComposerClient::addWindowInfosListener( +        const sp<WindowInfosListener>& windowInfosListener) { +    return WindowInfosListenerReporter::getInstance() +            ->addWindowInfosListener(windowInfosListener, ComposerService::getComposerService()); +} + +status_t SurfaceComposerClient::removeWindowInfosListener( +        const sp<WindowInfosListener>& windowInfosListener) { +    return WindowInfosListenerReporter::getInstance() +            ->removeWindowInfosListener(windowInfosListener, ComposerService::getComposerService()); +} +  // ----------------------------------------------------------------------------  status_t ScreenshotClient::captureDisplay(const DisplayCaptureArgs& captureArgs, diff --git a/libs/input/InputWindow.cpp b/libs/gui/WindowInfo.cpp index 99477200db..ff0bb8aa55 100644 --- a/libs/input/InputWindow.cpp +++ b/libs/gui/WindowInfo.cpp @@ -15,43 +15,40 @@   */  #include <type_traits> -#define LOG_TAG "InputWindow" +#define LOG_TAG "WindowInfo"  #define LOG_NDEBUG 0  #include <android-base/stringprintf.h>  #include <binder/Parcel.h> -#include <input/InputTransport.h> -#include <input/InputWindow.h> +#include <gui/WindowInfo.h>  #include <log/log.h> -namespace android { +namespace android::gui { - -// --- InputWindowInfo --- -void InputWindowInfo::addTouchableRegion(const Rect& region) { +// --- WindowInfo --- +void WindowInfo::addTouchableRegion(const Rect& region) {      touchableRegion.orSelf(region);  } -bool InputWindowInfo::touchableRegionContainsPoint(int32_t x, int32_t y) const { -    return touchableRegion.contains(x,y); +bool WindowInfo::touchableRegionContainsPoint(int32_t x, int32_t y) const { +    return touchableRegion.contains(x, y);  } -bool InputWindowInfo::frameContainsPoint(int32_t x, int32_t y) const { -    return x >= frameLeft && x < frameRight -            && y >= frameTop && y < frameBottom; +bool WindowInfo::frameContainsPoint(int32_t x, int32_t y) const { +    return x >= frameLeft && x < frameRight && y >= frameTop && y < frameBottom;  } -bool InputWindowInfo::supportsSplitTouch() const { +bool WindowInfo::supportsSplitTouch() const {      return flags.test(Flag::SPLIT_TOUCH);  } -bool InputWindowInfo::overlaps(const InputWindowInfo* other) const { -    return frameLeft < other->frameRight && frameRight > other->frameLeft -            && frameTop < other->frameBottom && frameBottom > other->frameTop; +bool WindowInfo::overlaps(const WindowInfo* other) const { +    return frameLeft < other->frameRight && frameRight > other->frameLeft && +            frameTop < other->frameBottom && frameBottom > other->frameTop;  } -bool InputWindowInfo::operator==(const InputWindowInfo& info) const { +bool WindowInfo::operator==(const WindowInfo& info) const {      return info.token == token && info.id == id && info.name == name && info.flags == flags &&              info.type == type && info.dispatchingTimeout == dispatchingTimeout &&              info.frameLeft == frameLeft && info.frameTop == frameTop && @@ -69,7 +66,7 @@ bool InputWindowInfo::operator==(const InputWindowInfo& info) const {              info.applicationInfo == applicationInfo;  } -status_t InputWindowInfo::writeToParcel(android::Parcel* parcel) const { +status_t WindowInfo::writeToParcel(android::Parcel* parcel) const {      if (parcel == nullptr) {          ALOGE("%s: Null parcel", __func__);          return BAD_VALUE; @@ -86,7 +83,7 @@ status_t InputWindowInfo::writeToParcel(android::Parcel* parcel) const {          parcel->writeInt32(id) ?:          parcel->writeUtf8AsUtf16(name) ?:          parcel->writeInt32(flags.get()) ?: -        parcel->writeInt32(static_cast<std::underlying_type_t<InputWindowInfo::Type>>(type)) ?: +        parcel->writeInt32(static_cast<std::underlying_type_t<WindowInfo::Type>>(type)) ?:          parcel->writeInt32(frameLeft) ?:          parcel->writeInt32(frameTop) ?:          parcel->writeInt32(frameRight) ?: @@ -122,7 +119,7 @@ status_t InputWindowInfo::writeToParcel(android::Parcel* parcel) const {      return status;  } -status_t InputWindowInfo::readFromParcel(const android::Parcel* parcel) { +status_t WindowInfo::readFromParcel(const android::Parcel* parcel) {      if (parcel == nullptr) {          ALOGE("%s: Null parcel", __func__);          return BAD_VALUE; @@ -176,11 +173,13 @@ status_t InputWindowInfo::readFromParcel(const android::Parcel* parcel) {      touchOcclusionMode = static_cast<TouchOcclusionMode>(touchOcclusionModeInt);      inputFeatures = Flags<Feature>(parcel->readInt32()); +    // clang-format off      status = parcel->readInt32(&displayId) ?:          parcel->readInt32(&portalToDisplayId) ?:          applicationInfo.readFromParcel(parcel) ?:          parcel->read(touchableRegion) ?:          parcel->readBool(&replaceTouchableRegionWithCrop); +    // clang-format on      if (status != OK) {          return status; @@ -192,33 +191,33 @@ status_t InputWindowInfo::readFromParcel(const android::Parcel* parcel) {      return OK;  } -// --- InputWindowHandle --- +// --- WindowInfoHandle --- -InputWindowHandle::InputWindowHandle() {} +WindowInfoHandle::WindowInfoHandle() {} -InputWindowHandle::~InputWindowHandle() {} +WindowInfoHandle::~WindowInfoHandle() {} -InputWindowHandle::InputWindowHandle(const InputWindowHandle& other) : mInfo(other.mInfo) {} +WindowInfoHandle::WindowInfoHandle(const WindowInfoHandle& other) : mInfo(other.mInfo) {} -InputWindowHandle::InputWindowHandle(const InputWindowInfo& other) : mInfo(other) {} +WindowInfoHandle::WindowInfoHandle(const WindowInfo& other) : mInfo(other) {} -status_t InputWindowHandle::writeToParcel(android::Parcel* parcel) const { +status_t WindowInfoHandle::writeToParcel(android::Parcel* parcel) const {      return mInfo.writeToParcel(parcel);  } -status_t InputWindowHandle::readFromParcel(const android::Parcel* parcel) { +status_t WindowInfoHandle::readFromParcel(const android::Parcel* parcel) {      return mInfo.readFromParcel(parcel);  } -void InputWindowHandle::releaseChannel() { +void WindowInfoHandle::releaseChannel() {      mInfo.token.clear();  } -sp<IBinder> InputWindowHandle::getToken() const { +sp<IBinder> WindowInfoHandle::getToken() const {      return mInfo.token;  } -void InputWindowHandle::updateFrom(sp<InputWindowHandle> handle) { +void WindowInfoHandle::updateFrom(sp<WindowInfoHandle> handle) {      mInfo = handle->mInfo;  } -} // namespace android +} // namespace android::gui diff --git a/libs/gui/WindowInfosListenerReporter.cpp b/libs/gui/WindowInfosListenerReporter.cpp new file mode 100644 index 0000000000..834e2b8433 --- /dev/null +++ b/libs/gui/WindowInfosListenerReporter.cpp @@ -0,0 +1,92 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gui/ISurfaceComposer.h> +#include <gui/WindowInfosListenerReporter.h> + +namespace android { + +using gui::WindowInfo; +using gui::WindowInfosListener; + +sp<WindowInfosListenerReporter> WindowInfosListenerReporter::getInstance() { +    static sp<WindowInfosListenerReporter> sInstance = new WindowInfosListenerReporter; +    return sInstance; +} + +status_t WindowInfosListenerReporter::addWindowInfosListener( +        const sp<WindowInfosListener>& windowInfosListener, +        const sp<ISurfaceComposer>& surfaceComposer) { +    status_t status = OK; +    { +        std::scoped_lock lock(mListenersMutex); +        if (mWindowInfosListeners.empty()) { +            status = surfaceComposer->addWindowInfosListener(this); +        } + +        if (status == OK) { +            mWindowInfosListeners.insert(windowInfosListener); +        } +    } + +    return status; +} + +status_t WindowInfosListenerReporter::removeWindowInfosListener( +        const sp<WindowInfosListener>& windowInfosListener, +        const sp<ISurfaceComposer>& surfaceComposer) { +    status_t status = OK; +    { +        std::scoped_lock lock(mListenersMutex); +        if (mWindowInfosListeners.size() == 1) { +            status = surfaceComposer->removeWindowInfosListener(this); +        } + +        if (status == OK) { +            mWindowInfosListeners.erase(windowInfosListener); +        } +    } + +    return status; +} + +binder::Status WindowInfosListenerReporter::onWindowInfosChanged( +        const std::vector<WindowInfo>& windowInfos) { +    std::unordered_set<sp<WindowInfosListener>, ISurfaceComposer::SpHash<WindowInfosListener>> +            windowInfosListeners; + +    { +        std::scoped_lock lock(mListenersMutex); +        for (auto listener : mWindowInfosListeners) { +            windowInfosListeners.insert(listener); +        } +    } + +    for (auto listener : windowInfosListeners) { +        listener->onWindowInfosChanged(windowInfos); +    } + +    return binder::Status::ok(); +} + +void WindowInfosListenerReporter::reconnect(const sp<ISurfaceComposer>& composerService) { +    std::scoped_lock lock(mListenersMutex); +    if (!mWindowInfosListeners.empty()) { +        composerService->addWindowInfosListener(this); +    } +} + +} // namespace android
\ No newline at end of file diff --git a/libs/input/android/FocusRequest.aidl b/libs/gui/android/gui/FocusRequest.aidl index 8812d34a72..90186351c5 100644 --- a/libs/input/android/FocusRequest.aidl +++ b/libs/gui/android/gui/FocusRequest.aidl @@ -14,7 +14,7 @@   * limitations under the License.   */ -package android; +package android.gui;  /** @hide */  parcelable FocusRequest { diff --git a/libs/gui/android/gui/IWindowInfosListener.aidl b/libs/gui/android/gui/IWindowInfosListener.aidl new file mode 100644 index 0000000000..500d928a5a --- /dev/null +++ b/libs/gui/android/gui/IWindowInfosListener.aidl @@ -0,0 +1,25 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gui; + +import android.gui.WindowInfo; + +/** @hide */ +oneway interface IWindowInfosListener +{ +    void onWindowInfosChanged(in WindowInfo[] windowInfos); +} diff --git a/libs/input/android/InputApplicationInfo.aidl b/libs/gui/android/gui/InputApplicationInfo.aidl index 933603916d..c0fd666543 100644 --- a/libs/input/android/InputApplicationInfo.aidl +++ b/libs/gui/android/gui/InputApplicationInfo.aidl @@ -14,7 +14,7 @@   * limitations under the License.   */ -package android; +package android.gui;  parcelable InputApplicationInfo {      @nullable IBinder token; diff --git a/libs/input/android/os/TouchOcclusionMode.aidl b/libs/gui/android/gui/TouchOcclusionMode.aidl index 106f159a50..d91d052135 100644 --- a/libs/input/android/os/TouchOcclusionMode.aidl +++ b/libs/gui/android/gui/TouchOcclusionMode.aidl @@ -14,7 +14,7 @@   * limitations under the License.   */ -package android.os; +package android.gui;  /** diff --git a/libs/input/android/InputWindowInfo.aidl b/libs/gui/android/gui/WindowInfo.aidl index eeaf400227..2c85d155a8 100644 --- a/libs/input/android/InputWindowInfo.aidl +++ b/libs/gui/android/gui/WindowInfo.aidl @@ -1,5 +1,4 @@ -/* //device/java/android/android/view/InputChannel.aidl -** +/*  ** Copyright 2020, The Android Open Source Project  **  ** Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,6 +14,6 @@  ** limitations under the License.  */ -package android; +package android.gui; -parcelable InputWindowInfo cpp_header "input/InputWindow.h"; +parcelable WindowInfo cpp_header "gui/WindowInfo.h"; diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 2a3f6a43d9..ad7bcb7d12 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -22,11 +22,12 @@  #include <android/gui/IScreenCaptureListener.h>  #include <android/gui/ITransactionTraceListener.h>  #include <android/gui/ITunnelModeEnabledListener.h> +#include <android/gui/IWindowInfosListener.h>  #include <binder/IBinder.h>  #include <binder/IInterface.h> +#include <ftl/Flags.h>  #include <gui/FrameTimelineInfo.h>  #include <gui/ITransactionCompletedListener.h> -#include <input/Flags.h>  #include <math/vec4.h>  #include <stdint.h>  #include <sys/types.h> @@ -552,6 +553,11 @@ public:       * in MIN_UNDEQUEUED_BUFFERS.       */      virtual status_t getMaxAcquiredBufferCount(int* buffers) const = 0; + +    virtual status_t addWindowInfosListener( +            const sp<gui::IWindowInfosListener>& windowInfosListener) const = 0; +    virtual status_t removeWindowInfosListener( +            const sp<gui::IWindowInfosListener>& windowInfosListener) const = 0;  };  // ---------------------------------------------------------------------------- @@ -624,6 +630,8 @@ public:          ON_PULL_ATOM,          ADD_TUNNEL_MODE_ENABLED_LISTENER,          REMOVE_TUNNEL_MODE_ENABLED_LISTENER, +        ADD_WINDOW_INFOS_LISTENER, +        REMOVE_WINDOW_INFOS_LISTENER,          // Always append new enum to the end.      }; diff --git a/include/input/InputApplication.h b/libs/gui/include/gui/InputApplication.h index 8e4fe796a5..679c2a1754 100644 --- a/include/input/InputApplication.h +++ b/libs/gui/include/gui/InputApplication.h @@ -19,17 +19,17 @@  #include <string> -#include <android/InputApplicationInfo.h> +#include <android/gui/InputApplicationInfo.h>  #include <binder/IBinder.h>  #include <binder/Parcel.h>  #include <binder/Parcelable.h> -#include <input/Input.h>  #include <utils/RefBase.h>  #include <utils/Timers.h>  namespace android { +  /*   * Handle for an application that can receive input.   * @@ -38,13 +38,9 @@ namespace android {   */  class InputApplicationHandle {  public: -    inline const InputApplicationInfo* getInfo() const { -        return &mInfo; -    } +    inline const gui::InputApplicationInfo* getInfo() const { return &mInfo; } -    inline std::string getName() const { -        return !mInfo.name.empty() ? mInfo.name : "<invalid>"; -    } +    inline std::string getName() const { return !mInfo.name.empty() ? mInfo.name : "<invalid>"; }      inline std::chrono::nanoseconds getDispatchingTimeout(              std::chrono::nanoseconds defaultValue) const { @@ -52,9 +48,7 @@ public:                             : defaultValue;      } -    inline sp<IBinder> getApplicationToken() const { -        return mInfo.token; -    } +    inline sp<IBinder> getApplicationToken() const { return mInfo.token; }      bool operator==(const InputApplicationHandle& other) const {          return getName() == other.getName() && getApplicationToken() == other.getApplicationToken(); @@ -77,7 +71,7 @@ protected:      InputApplicationHandle() = default;      virtual ~InputApplicationHandle() = default; -    InputApplicationInfo mInfo; +    gui::InputApplicationInfo mInfo;  };  } // namespace android diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 3e57ff611e..b27d9cf2bc 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -26,14 +26,12 @@  #include <gui/ITransactionCompletedListener.h>  #include <math/mat4.h> -#ifndef NO_INPUT -#include <android/FocusRequest.h> -#include <input/InputWindow.h> -#endif +#include <android/gui/FocusRequest.h>  #include <gui/ISurfaceComposer.h>  #include <gui/LayerMetadata.h>  #include <gui/SurfaceControl.h> +#include <gui/WindowInfo.h>  #include <math/vec3.h>  #include <ui/BlurRegion.h>  #include <ui/GraphicTypes.h> @@ -178,9 +176,7 @@ struct layer_state_t {      mat4 colorTransform;      std::vector<BlurRegion> blurRegions; -#ifndef NO_INPUT -    sp<InputWindowHandle> inputHandle = new InputWindowHandle(); -#endif +    sp<gui::WindowInfoHandle> windowInfoHandle = new gui::WindowInfoHandle();      client_cache_t cachedBuffer; @@ -259,7 +255,8 @@ struct DisplayState {          eSurfaceChanged = 0x01,          eLayerStackChanged = 0x02,          eDisplayProjectionChanged = 0x04, -        eDisplaySizeChanged = 0x08 +        eDisplaySizeChanged = 0x08, +        eFlagsChanged = 0x10      };      DisplayState(); @@ -269,6 +266,7 @@ struct DisplayState {      sp<IBinder> token;      sp<IGraphicBufferProducer> surface;      uint32_t layerStack; +    uint32_t flags;      // These states define how layers are projected onto the physical display.      // @@ -292,9 +290,7 @@ struct DisplayState {  };  struct InputWindowCommands { -#ifndef NO_INPUT -    std::vector<FocusRequest> focusRequests; -#endif +    std::vector<gui::FocusRequest> focusRequests;      bool syncInputWindows{false};      // Merges the passed in commands and returns true if there were any changes. diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index baa0567617..8993891398 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -42,6 +42,7 @@  #include <gui/ITransactionCompletedListener.h>  #include <gui/LayerState.h>  #include <gui/SurfaceControl.h> +#include <gui/WindowInfosListenerReporter.h>  #include <math/vec3.h>  namespace android { @@ -502,11 +503,9 @@ public:          // Set the framenumber generated by the graphics producer to mimic BufferQueue behaviour.          Transaction& setFrameNumber(const sp<SurfaceControl>& sc, uint64_t frameNumber); -#ifndef NO_INPUT -        Transaction& setInputWindowInfo(const sp<SurfaceControl>& sc, const InputWindowInfo& info); -        Transaction& setFocusedWindow(const FocusRequest& request); +        Transaction& setInputWindowInfo(const sp<SurfaceControl>& sc, const gui::WindowInfo& info); +        Transaction& setFocusedWindow(const gui::FocusRequest& request);          Transaction& syncInputWindows(); -#endif          // Set a color transform matrix on the given layer on the built-in display.          Transaction& setColorTransform(const sp<SurfaceControl>& sc, const mat3& matrix, @@ -569,6 +568,8 @@ public:          void setDisplayLayerStack(const sp<IBinder>& token, uint32_t layerStack); +        void setDisplayFlags(const sp<IBinder>& token, uint32_t flags); +          /* setDisplayProjection() defines the projection of layer stacks           * to a given display.           * @@ -622,6 +623,9 @@ public:      static status_t removeTunnelModeEnabledListener(              const sp<gui::ITunnelModeEnabledListener>& listener); +    status_t addWindowInfosListener(const sp<gui::WindowInfosListener>& windowInfosListener); +    status_t removeWindowInfosListener(const sp<gui::WindowInfosListener>& windowInfosListener); +  private:      virtual void onFirstRef(); diff --git a/include/input/InputWindow.h b/libs/gui/include/gui/WindowInfo.h index 121be6d963..7af1f0e95a 100644 --- a/include/input/InputWindow.h +++ b/libs/gui/include/gui/WindowInfo.h @@ -14,15 +14,13 @@   * limitations under the License.   */ -#ifndef _UI_INPUT_WINDOW_H -#define _UI_INPUT_WINDOW_H +#pragma once -#include <android/os/TouchOcclusionMode.h> +#include <android/gui/TouchOcclusionMode.h>  #include <binder/Parcel.h>  #include <binder/Parcelable.h> -#include <input/Flags.h> -#include <input/Input.h> -#include <input/InputTransport.h> +#include <ftl/Flags.h> +#include <gui/constants.h>  #include <ui/Rect.h>  #include <ui/Region.h>  #include <ui/Transform.h> @@ -31,15 +29,13 @@  #include "InputApplication.h" -using android::os::TouchOcclusionMode; - -namespace android { +namespace android::gui {  /*   * Describes the properties of a window that can receive input.   */ -struct InputWindowInfo : public Parcelable { -    InputWindowInfo() = default; +struct WindowInfo : public Parcelable { +    WindowInfo() = default;      // Window flags from WindowManager.LayoutParams      enum class Flag : uint32_t { @@ -168,9 +164,12 @@ struct InputWindowInfo : public Parcelable {      // Transform applied to individual windows.      ui::Transform transform; +    // Display orientation. Used for compatibility raw coordinates. +    uint32_t displayOrientation = ui::Transform::ROT_0; +      // Display size in its natural rotation. Used to rotate raw coordinates for compatibility. -    int32_t displayWidth = AMOTION_EVENT_INVALID_DISPLAY_SIZE; -    int32_t displayHeight = AMOTION_EVENT_INVALID_DISPLAY_SIZE; +    int32_t displayWidth = 0; +    int32_t displayHeight = 0;      /*       * This is filled in by the WM relative to the frame and then translated @@ -206,9 +205,9 @@ struct InputWindowInfo : public Parcelable {      bool supportsSplitTouch() const; -    bool overlaps(const InputWindowInfo* other) const; +    bool overlaps(const WindowInfo* other) const; -    bool operator==(const InputWindowInfo& inputChannel) const; +    bool operator==(const WindowInfo& inputChannel) const;      status_t writeToParcel(android::Parcel* parcel) const override; @@ -221,13 +220,13 @@ struct InputWindowInfo : public Parcelable {   * Used by the native input dispatcher to indirectly refer to the window manager objects   * that describe a window.   */ -class InputWindowHandle : public RefBase { +class WindowInfoHandle : public RefBase {  public: -    explicit InputWindowHandle(); -    InputWindowHandle(const InputWindowHandle& other); -    InputWindowHandle(const InputWindowInfo& other); +    explicit WindowInfoHandle(); +    WindowInfoHandle(const WindowInfoHandle& other); +    WindowInfoHandle(const WindowInfo& other); -    inline const InputWindowInfo* getInfo() const { return &mInfo; } +    inline const WindowInfo* getInfo() const { return &mInfo; }      sp<IBinder> getToken() const; @@ -243,21 +242,9 @@ public:      }      /** -     * Requests that the state of this object be updated to reflect -     * the most current available information about the application. -     * As this class is created as RefBase object, no pure virtual function is allowed. -     * -     * This method should only be called from within the input dispatcher's -     * critical section. -     * -     * Returns true on success, or false if the handle is no longer valid. -     */ -    virtual bool updateInfo() { return false; } - -    /**       * Updates from another input window handle.       */ -    void updateFrom(const sp<InputWindowHandle> handle); +    void updateFrom(const sp<WindowInfoHandle> handle);      /**       * Releases the channel used by the associated information when it is @@ -270,10 +257,8 @@ public:      status_t writeToParcel(android::Parcel* parcel) const;  protected: -    virtual ~InputWindowHandle(); +    virtual ~WindowInfoHandle(); -    InputWindowInfo mInfo; +    WindowInfo mInfo;  }; -} // namespace android - -#endif // _UI_INPUT_WINDOW_H +} // namespace android::gui
\ No newline at end of file diff --git a/libs/gui/include/gui/WindowInfosListener.h b/libs/gui/include/gui/WindowInfosListener.h new file mode 100644 index 0000000000..8a70b9bb57 --- /dev/null +++ b/libs/gui/include/gui/WindowInfosListener.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <gui/WindowInfo.h> +#include <utils/RefBase.h> + +namespace android::gui { + +class WindowInfosListener : public virtual RefBase { +public: +    virtual void onWindowInfosChanged(const std::vector<WindowInfo>& /*windowInfos*/) = 0; +}; +} // namespace android::gui
\ No newline at end of file diff --git a/libs/gui/include/gui/WindowInfosListenerReporter.h b/libs/gui/include/gui/WindowInfosListenerReporter.h new file mode 100644 index 0000000000..3e346de069 --- /dev/null +++ b/libs/gui/include/gui/WindowInfosListenerReporter.h @@ -0,0 +1,47 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <android/gui/BnWindowInfosListener.h> +#include <binder/IBinder.h> +#include <gui/ISurfaceComposer.h> +#include <gui/WindowInfosListener.h> +#include <utils/Mutex.h> +#include <unordered_set> + +namespace android { +class ISurfaceComposer; + +class WindowInfosListenerReporter : public gui::BnWindowInfosListener { +public: +    static sp<WindowInfosListenerReporter> getInstance(); + +    binder::Status onWindowInfosChanged(const std::vector<gui::WindowInfo>& windowInfos) override; + +    status_t addWindowInfosListener(const sp<gui::WindowInfosListener>& windowInfosListener, +                                    const sp<ISurfaceComposer>&); +    status_t removeWindowInfosListener(const sp<gui::WindowInfosListener>& windowInfosListener, +                                       const sp<ISurfaceComposer>&); +    void reconnect(const sp<ISurfaceComposer>&); + +private: +    std::mutex mListenersMutex; +    std::unordered_set<sp<gui::WindowInfosListener>, +                       ISurfaceComposer::SpHash<gui::WindowInfosListener>> +            mWindowInfosListeners GUARDED_BY(mListenersMutex); +}; +} // namespace android
\ No newline at end of file diff --git a/libs/gui/include/gui/constants.h b/libs/gui/include/gui/constants.h new file mode 100644 index 0000000000..8eab3783e9 --- /dev/null +++ b/libs/gui/include/gui/constants.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <stdint.h> + +namespace android { + +/** + * Invalid value for display size. Used when display size isn't available. + */ +constexpr int32_t INVALID_DISPLAY_SIZE = 0; + +enum { +    /* Used when an event is not associated with any display. +     * Typically used for non-pointer events. */ +    ADISPLAY_ID_NONE = -1, + +    /* The default display id. */ +    ADISPLAY_ID_DEFAULT = 0, +}; + +} // namespace android
\ No newline at end of file diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp index c801c6243a..3d26c3d858 100644 --- a/libs/gui/tests/Android.bp +++ b/libs/gui/tests/Android.bp @@ -43,6 +43,7 @@ cc_test {          "SurfaceTextureMultiContextGL_test.cpp",          "Surface_test.cpp",          "TextureRenderer.cpp", +        "WindowInfo_test.cpp",      ],      shared_libs: [ diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index 49c44a78d1..fc84c1b619 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -37,9 +37,9 @@  #include <gui/SurfaceControl.h>  #include <android/os/IInputFlinger.h> +#include <gui/WindowInfo.h>  #include <input/Input.h>  #include <input/InputTransport.h> -#include <input/InputWindow.h>  #include <ui/DisplayMode.h>  #include <ui/Rect.h> @@ -49,6 +49,11 @@ using android::os::IInputFlinger;  using android::hardware::graphics::common::V1_1::BufferUsage; +using android::gui::FocusRequest; +using android::gui::InputApplicationInfo; +using android::gui::TouchOcclusionMode; +using android::gui::WindowInfo; +  namespace android::test {  using Transaction = SurfaceComposerClient::Transaction; @@ -221,8 +226,8 @@ private:      void populateInputInfo(int width, int height) {          mInputInfo.token = mClientChannel->getConnectionToken();          mInputInfo.name = "Test info"; -        mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCH_MODAL; -        mInputInfo.type = InputWindowInfo::Type::BASE_APPLICATION; +        mInputInfo.flags = WindowInfo::Flag::NOT_TOUCH_MODAL; +        mInputInfo.type = WindowInfo::Type::BASE_APPLICATION;          mInputInfo.dispatchingTimeout = 5s;          mInputInfo.globalScaleFactor = 1.0;          mInputInfo.focusable = true; @@ -249,7 +254,7 @@ public:      std::shared_ptr<InputChannel> mClientChannel;      sp<IInputFlinger> mInputFlinger; -    InputWindowInfo mInputInfo; +    WindowInfo mInputInfo;      PreallocatedInputEventFactory mInputEventFactory;      InputConsumer* mInputConsumer; @@ -686,7 +691,7 @@ TEST_F(InputSurfacesTest, touch_flag_obscured) {      // Add non touchable window to fully cover touchable window. Window behind gets touch, but      // with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED      std::unique_ptr<InputSurface> nonTouchableSurface = makeSurface(100, 100); -    nonTouchableSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE; +    nonTouchableSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE;      nonTouchableSurface->mInputInfo.ownerUid = 22222;      // Overriding occlusion mode otherwise the touch would be discarded at InputDispatcher by      // the default obscured/untrusted touch filter introduced in S. @@ -706,8 +711,8 @@ TEST_F(InputSurfacesTest, touch_flag_partially_obscured_with_crop) {      // AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED      std::unique_ptr<InputSurface> parentSurface = makeSurface(100, 100);      std::unique_ptr<InputSurface> nonTouchableSurface = makeSurface(100, 100); -    nonTouchableSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE; -    parentSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE; +    nonTouchableSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE; +    parentSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE;      nonTouchableSurface->mInputInfo.ownerUid = 22222;      parentSurface->mInputInfo.ownerUid = 22222;      nonTouchableSurface->showAt(0, 0); @@ -730,8 +735,8 @@ TEST_F(InputSurfacesTest, touch_not_obscured_with_crop) {      // the touchable window. Window behind gets touch with no obscured flags.      std::unique_ptr<InputSurface> parentSurface = makeSurface(100, 100);      std::unique_ptr<InputSurface> nonTouchableSurface = makeSurface(100, 100); -    nonTouchableSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE; -    parentSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE; +    nonTouchableSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE; +    parentSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE;      nonTouchableSurface->mInputInfo.ownerUid = 22222;      parentSurface->mInputInfo.ownerUid = 22222;      nonTouchableSurface->showAt(0, 0); @@ -751,7 +756,7 @@ TEST_F(InputSurfacesTest, touch_not_obscured_with_zero_sized_bql) {      std::unique_ptr<InputSurface> bufferSurface =              InputSurface::makeBufferInputSurface(mComposerClient, 0, 0); -    bufferSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE; +    bufferSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE;      bufferSurface->mInputInfo.ownerUid = 22222;      surface->showAt(10, 10); @@ -766,7 +771,7 @@ TEST_F(InputSurfacesTest, touch_not_obscured_with_zero_sized_blast) {      std::unique_ptr<BlastInputSurface> bufferSurface =              BlastInputSurface::makeBlastInputSurface(mComposerClient, 0, 0); -    bufferSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE; +    bufferSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE;      bufferSurface->mInputInfo.ownerUid = 22222;      surface->showAt(10, 10); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 59b0c04bc3..a02970c9bc 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -904,6 +904,16 @@ public:      status_t getMaxAcquiredBufferCount(int* /*buffers*/) const override { return NO_ERROR; } +    status_t addWindowInfosListener( +            const sp<gui::IWindowInfosListener>& /*windowInfosListener*/) const override { +        return NO_ERROR; +    } + +    status_t removeWindowInfosListener( +            const sp<gui::IWindowInfosListener>& /*windowInfosListener*/) const override { +        return NO_ERROR; +    } +  protected:      IBinder* onAsBinder() override { return nullptr; } diff --git a/libs/input/tests/InputWindow_test.cpp b/libs/gui/tests/WindowInfo_test.cpp index 493f2f4495..58f3981db2 100644 --- a/libs/input/tests/InputWindow_test.cpp +++ b/libs/gui/tests/WindowInfo_test.cpp @@ -19,16 +19,20 @@  #include <binder/Binder.h>  #include <binder/Parcel.h> -#include <input/InputWindow.h> -#include <input/InputTransport.h> +#include <gui/WindowInfo.h>  using std::chrono_literals::operator""s;  namespace android { + +using gui::InputApplicationInfo; +using gui::TouchOcclusionMode; +using gui::WindowInfo; +  namespace test { -TEST(InputWindowInfo, ParcellingWithoutToken) { -    InputWindowInfo i, i2; +TEST(WindowInfo, ParcellingWithoutToken) { +    WindowInfo i, i2;      i.token = nullptr;      Parcel p; @@ -38,14 +42,14 @@ TEST(InputWindowInfo, ParcellingWithoutToken) {      ASSERT_TRUE(i2.token == nullptr);  } -TEST(InputWindowInfo, Parcelling) { +TEST(WindowInfo, Parcelling) {      sp<IBinder> touchableRegionCropHandle = new BBinder(); -    InputWindowInfo i; +    WindowInfo i;      i.token = new BBinder();      i.id = 1;      i.name = "Foobar"; -    i.flags = InputWindowInfo::Flag::SLIPPERY; -    i.type = InputWindowInfo::Type::INPUT_METHOD; +    i.flags = WindowInfo::Flag::SLIPPERY; +    i.type = WindowInfo::Type::INPUT_METHOD;      i.dispatchingTimeout = 12s;      i.frameLeft = 93;      i.frameTop = 34; @@ -55,6 +59,7 @@ TEST(InputWindowInfo, Parcelling) {      i.globalScaleFactor = 0.3;      i.alpha = 0.7;      i.transform.set({0.4, -1, 100, 0.5, 0, 40, 0, 0, 1}); +    i.displayOrientation = ui::Transform::ROT_0;      i.displayWidth = 1000;      i.displayHeight = 2000;      i.visible = false; @@ -65,7 +70,7 @@ TEST(InputWindowInfo, Parcelling) {      i.ownerPid = 19;      i.ownerUid = 24;      i.packageName = "com.example.package"; -    i.inputFeatures = InputWindowInfo::Feature::DISABLE_USER_ACTIVITY; +    i.inputFeatures = WindowInfo::Feature::DISABLE_USER_ACTIVITY;      i.displayId = 34;      i.portalToDisplayId = 2;      i.replaceTouchableRegionWithCrop = true; @@ -77,7 +82,7 @@ TEST(InputWindowInfo, Parcelling) {      Parcel p;      i.writeToParcel(&p);      p.setDataPosition(0); -    InputWindowInfo i2; +    WindowInfo i2;      i2.readFromParcel(&p);      ASSERT_EQ(i.token, i2.token);      ASSERT_EQ(i.id, i2.id); diff --git a/libs/input/Android.bp b/libs/input/Android.bp index a63ec8fb2a..02cf9ebc26 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -30,7 +30,6 @@ filegroup {          "android/os/IInputConstants.aidl",          "android/os/InputEventInjectionResult.aidl",          "android/os/InputEventInjectionSync.aidl", -        "android/os/TouchOcclusionMode.aidl",      ],  } @@ -79,16 +78,12 @@ cc_library {          android: {              srcs: [                  "InputTransport.cpp", -                "InputWindow.cpp", -                "android/FocusRequest.aidl", -                "android/InputApplicationInfo.aidl",                  "android/os/BlockUntrustedTouchesMode.aidl",                  "android/os/IInputConstants.aidl",                  "android/os/IInputFlinger.aidl",                  "android/os/InputEventInjectionResult.aidl",                  "android/os/InputEventInjectionSync.aidl",                  "android/os/ISetInputWindowsListener.aidl", -                "android/os/TouchOcclusionMode.aidl",              ],              export_shared_lib_headers: ["libbinder"], @@ -99,6 +94,14 @@ cc_library {                  "libui",              ], +            static_libs: [ +                "libgui_window_info_static", +            ], + +            export_static_lib_headers: [ +                "libgui_window_info_static", +            ], +              sanitize: {                  misc_undefined: ["integer"],              }, @@ -114,26 +117,30 @@ cc_library {          linux_glibc: {              srcs: [                  "InputTransport.cpp", -                "InputWindow.cpp", -                "android/FocusRequest.aidl", -                "android/InputApplicationInfo.aidl",                  "android/os/IInputConstants.aidl",                  "android/os/IInputFlinger.aidl",                  "android/os/ISetInputWindowsListener.aidl", -                "android/os/TouchOcclusionMode.aidl",              ],              static_libs: [                  "libhostgraphics", +                "libgui_window_info_static",              ],              shared_libs: [                  "libbinder",              ], + +            export_static_lib_headers: [ +                "libgui_window_info_static", +            ],          },      },      aidl: {          local_include_dirs: ["."],          export_aidl_headers: true, +        include_dirs: [ +            "frameworks/native/libs/gui", +        ],      },  } diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp index d954d23507..35209f7a07 100644 --- a/libs/input/Input.cpp +++ b/libs/input/Input.cpp @@ -25,6 +25,7 @@  #include <android-base/properties.h>  #include <android-base/stringprintf.h> +#include <gui/constants.h>  #include <input/Input.h>  #include <input/InputDevice.h>  #include <input/InputEventLabels.h> @@ -75,14 +76,11 @@ float transformAngle(const ui::Transform& transform, float angleRadians) {      return result;  } -// Rotates the given point to the transform's orientation. If the display width and height are +// Rotates the given point to the specified orientation. If the display width and height are  // provided, the point is rotated in the screen space. Otherwise, the point is rotated about the  // origin. This helper is used to avoid the extra overhead of creating new Transforms. -vec2 rotatePoint(const ui::Transform& transform, float x, float y, int32_t displayWidth = 0, +vec2 rotatePoint(uint32_t orientation, float x, float y, int32_t displayWidth = 0,                   int32_t displayHeight = 0) { -    // 0x7 encapsulates all 3 rotations (see ui::Transform::RotationFlags) -    static const int ALL_ROTATIONS_MASK = 0x7; -    const uint32_t orientation = (transform.getOrientation() & ALL_ROTATIONS_MASK);      if (orientation == ui::Transform::ROT_0) {          return {x, y};      } @@ -101,6 +99,19 @@ vec2 rotatePoint(const ui::Transform& transform, float x, float y, int32_t displ      return xy;  } +vec2 applyTransformWithoutTranslation(const ui::Transform& transform, float x, float y) { +    const vec2 transformedXy = transform.transform(x, y); +    const vec2 transformedOrigin = transform.transform(0, 0); +    return transformedXy - transformedOrigin; +} + +bool shouldDisregardWindowTranslation(uint32_t source) { +    // Pointer events are the only type of events that refer to absolute coordinates on the display, +    // so we should apply the entire window transform. For other types of events, we should make +    // sure to not apply the window translation/offset. +    return (source & AINPUT_SOURCE_CLASS_POINTER) == 0; +} +  } // namespace  const char* motionClassificationToString(MotionClassification classification) { @@ -315,6 +326,8 @@ void PointerCoords::scale(float globalScaleFactor, float windowXScale, float win      scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MINOR, globalScaleFactor);      scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MAJOR, globalScaleFactor);      scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MINOR, globalScaleFactor); +    scaleAxisValue(*this, AMOTION_EVENT_AXIS_RELATIVE_X, windowXScale); +    scaleAxisValue(*this, AMOTION_EVENT_AXIS_RELATIVE_Y, windowYScale);  }  void PointerCoords::scale(float globalScaleFactor) { @@ -383,6 +396,15 @@ void PointerCoords::transform(const ui::Transform& transform) {      setAxisValue(AMOTION_EVENT_AXIS_X, xy.x);      setAxisValue(AMOTION_EVENT_AXIS_Y, xy.y); +    if (BitSet64::hasBit(bits, AMOTION_EVENT_AXIS_RELATIVE_X) || +        BitSet64::hasBit(bits, AMOTION_EVENT_AXIS_RELATIVE_Y)) { +        const ui::Transform rotation(transform.getOrientation()); +        const vec2 relativeXy = rotation.transform(getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X), +                                                   getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y)); +        setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, relativeXy.x); +        setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, relativeXy.y); +    } +      if (BitSet64::hasBit(bits, AMOTION_EVENT_AXIS_ORIENTATION)) {          const float val = getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);          setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, transformAngle(transform, val)); @@ -410,9 +432,9 @@ void MotionEvent::initialize(int32_t id, int32_t deviceId, uint32_t source, int3                               int32_t buttonState, MotionClassification classification,                               const ui::Transform& transform, float xPrecision, float yPrecision,                               float rawXCursorPosition, float rawYCursorPosition, -                             int32_t displayWidth, int32_t displayHeight, nsecs_t downTime, -                             nsecs_t eventTime, size_t pointerCount, -                             const PointerProperties* pointerProperties, +                             uint32_t displayOrientation, int32_t displayWidth, +                             int32_t displayHeight, nsecs_t downTime, nsecs_t eventTime, +                             size_t pointerCount, const PointerProperties* pointerProperties,                               const PointerCoords* pointerCoords) {      InputEvent::initialize(id, deviceId, source, displayId, hmac);      mAction = action; @@ -427,6 +449,7 @@ void MotionEvent::initialize(int32_t id, int32_t deviceId, uint32_t source, int3      mYPrecision = yPrecision;      mRawXCursorPosition = rawXCursorPosition;      mRawYCursorPosition = rawYCursorPosition; +    mDisplayOrientation = displayOrientation;      mDisplayWidth = displayWidth;      mDisplayHeight = displayHeight;      mDownTime = downTime; @@ -452,6 +475,7 @@ void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) {      mYPrecision = other->mYPrecision;      mRawXCursorPosition = other->mRawXCursorPosition;      mRawYCursorPosition = other->mRawYCursorPosition; +    mDisplayOrientation = other->mDisplayOrientation;      mDisplayWidth = other->mDisplayWidth;      mDisplayHeight = other->mDisplayHeight;      mDownTime = other->mDownTime; @@ -521,25 +545,48 @@ float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex,      if (axis == AMOTION_EVENT_AXIS_X || axis == AMOTION_EVENT_AXIS_Y) {          // For compatibility, convert raw coordinates into "oriented screen space". Once app          // developers are educated about getRaw, we can consider removing this. -        const vec2 xy = rotatePoint(mTransform, coords->getX(), coords->getY(), mDisplayWidth, -                                    mDisplayHeight); +        const vec2 xy = shouldDisregardWindowTranslation(mSource) +                ? rotatePoint(mDisplayOrientation, coords->getX(), coords->getY()) +                : rotatePoint(mDisplayOrientation, coords->getX(), coords->getY(), mDisplayWidth, +                              mDisplayHeight);          static_assert(AMOTION_EVENT_AXIS_X == 0 && AMOTION_EVENT_AXIS_Y == 1);          return xy[axis];      } +    if (axis == AMOTION_EVENT_AXIS_RELATIVE_X || axis == AMOTION_EVENT_AXIS_RELATIVE_Y) { +        // For compatibility, since we convert raw coordinates into "oriented screen space", we +        // need to convert the relative axes into the same orientation for consistency. +        const vec2 relativeXy = rotatePoint(mDisplayOrientation, +                                            coords->getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X), +                                            coords->getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y)); +        return axis == AMOTION_EVENT_AXIS_RELATIVE_X ? relativeXy.x : relativeXy.y; +    } +      return coords->getAxisValue(axis);  }  float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex, -        size_t historicalIndex) const { +                                          size_t historicalIndex) const {      const PointerCoords* coords = getHistoricalRawPointerCoords(pointerIndex, historicalIndex);      if (axis == AMOTION_EVENT_AXIS_X || axis == AMOTION_EVENT_AXIS_Y) { -        const vec2 xy = mTransform.transform(coords->getXYValue()); +        const vec2 xy = shouldDisregardWindowTranslation(mSource) +                ? applyTransformWithoutTranslation(mTransform, coords->getX(), coords->getY()) +                : mTransform.transform(coords->getXYValue());          static_assert(AMOTION_EVENT_AXIS_X == 0 && AMOTION_EVENT_AXIS_Y == 1);          return xy[axis];      } +    if (axis == AMOTION_EVENT_AXIS_RELATIVE_X || axis == AMOTION_EVENT_AXIS_RELATIVE_Y) { +        const vec2 relativeXy = +                applyTransformWithoutTranslation(mTransform, +                                                 coords->getAxisValue( +                                                         AMOTION_EVENT_AXIS_RELATIVE_X), +                                                 coords->getAxisValue( +                                                         AMOTION_EVENT_AXIS_RELATIVE_Y)); +        return axis == AMOTION_EVENT_AXIS_RELATIVE_X ? relativeXy.x : relativeXy.y; +    } +      return coords->getAxisValue(axis);  } @@ -595,6 +642,13 @@ void MotionEvent::applyTransform(const std::array<float, 9>& matrix) {      // Apply the transformation to all samples.      std::for_each(mSamplePointerCoords.begin(), mSamplePointerCoords.end(),                    [&transform](PointerCoords& c) { c.transform(transform); }); + +    if (mRawXCursorPosition != AMOTION_EVENT_INVALID_CURSOR_POSITION && +        mRawYCursorPosition != AMOTION_EVENT_INVALID_CURSOR_POSITION) { +        const vec2 cursor = transform.transform(mRawXCursorPosition, mRawYCursorPosition); +        mRawXCursorPosition = cursor.x; +        mRawYCursorPosition = cursor.y; +    }  }  #ifdef __linux__ @@ -655,6 +709,7 @@ status_t MotionEvent::readFromParcel(Parcel* parcel) {      mYPrecision = parcel->readFloat();      mRawXCursorPosition = parcel->readFloat();      mRawYCursorPosition = parcel->readFloat(); +    mDisplayOrientation = parcel->readUint32();      mDisplayWidth = parcel->readInt32();      mDisplayHeight = parcel->readInt32();      mDownTime = parcel->readInt64(); @@ -716,6 +771,7 @@ status_t MotionEvent::writeToParcel(Parcel* parcel) const {      parcel->writeFloat(mYPrecision);      parcel->writeFloat(mRawXCursorPosition);      parcel->writeFloat(mRawYCursorPosition); +    parcel->writeUint32(mDisplayOrientation);      parcel->writeInt32(mDisplayWidth);      parcel->writeInt32(mDisplayHeight);      parcel->writeInt64(mDownTime); diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp index 30c42a3daa..220c8e1e6e 100644 --- a/libs/input/InputDevice.cpp +++ b/libs/input/InputDevice.cpp @@ -21,9 +21,9 @@  #include <ctype.h>  #include <android-base/stringprintf.h> +#include <ftl/NamedEnum.h>  #include <input/InputDevice.h>  #include <input/InputEventLabels.h> -#include <input/NamedEnum.h>  using android::base::StringPrintf; diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index dd1c46265c..ea8b9a7ec8 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -33,8 +33,8 @@ static constexpr bool DEBUG_TRANSPORT_ACTIONS = false;  #include <log/log.h>  #include <utils/Trace.h> +#include <ftl/NamedEnum.h>  #include <input/InputTransport.h> -#include <input/NamedEnum.h>  using android::base::StringPrintf; @@ -242,9 +242,11 @@ void InputMessage::getSanitizedCopy(InputMessage* msg) const {              msg->body.motion.xCursorPosition = body.motion.xCursorPosition;              // float yCursorPosition              msg->body.motion.yCursorPosition = body.motion.yCursorPosition; -            // int32_t displayW +            // uint32_t displayOrientation +            msg->body.motion.displayOrientation = body.motion.displayOrientation; +            // int32_t displayWidth              msg->body.motion.displayWidth = body.motion.displayWidth; -            // int32_t displayH +            // int32_t displayHeight              msg->body.motion.displayHeight = body.motion.displayHeight;              // uint32_t pointerCount              msg->body.motion.pointerCount = body.motion.pointerCount; @@ -533,9 +535,10 @@ status_t InputPublisher::publishMotionEvent(          std::array<uint8_t, 32> hmac, int32_t action, int32_t actionButton, int32_t flags,          int32_t edgeFlags, int32_t metaState, int32_t buttonState,          MotionClassification classification, const ui::Transform& transform, float xPrecision, -        float yPrecision, float xCursorPosition, float yCursorPosition, int32_t displayWidth, -        int32_t displayHeight, nsecs_t downTime, nsecs_t eventTime, uint32_t pointerCount, -        const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) { +        float yPrecision, float xCursorPosition, float yCursorPosition, uint32_t displayOrientation, +        int32_t displayWidth, int32_t displayHeight, nsecs_t downTime, nsecs_t eventTime, +        uint32_t pointerCount, const PointerProperties* pointerProperties, +        const PointerCoords* pointerCoords) {      if (ATRACE_ENABLED()) {          std::string message = StringPrintf(                  "publishMotionEvent(inputChannel=%s, action=%" PRId32 ")", @@ -593,6 +596,7 @@ status_t InputPublisher::publishMotionEvent(      msg.body.motion.yPrecision = yPrecision;      msg.body.motion.xCursorPosition = xCursorPosition;      msg.body.motion.yCursorPosition = yCursorPosition; +    msg.body.motion.displayOrientation = displayOrientation;      msg.body.motion.displayWidth = displayWidth;      msg.body.motion.displayHeight = displayHeight;      msg.body.motion.downTime = downTime; @@ -1361,9 +1365,9 @@ void InputConsumer::initializeMotionEvent(MotionEvent* event, const InputMessage                        msg->body.motion.buttonState, msg->body.motion.classification, transform,                        msg->body.motion.xPrecision, msg->body.motion.yPrecision,                        msg->body.motion.xCursorPosition, msg->body.motion.yCursorPosition, -                      msg->body.motion.displayWidth, msg->body.motion.displayHeight, -                      msg->body.motion.downTime, msg->body.motion.eventTime, pointerCount, -                      pointerProperties, pointerCoords); +                      msg->body.motion.displayOrientation, msg->body.motion.displayWidth, +                      msg->body.motion.displayHeight, msg->body.motion.downTime, +                      msg->body.motion.eventTime, pointerCount, pointerProperties, pointerCoords);  }  void InputConsumer::addSample(MotionEvent* event, const InputMessage* msg) { diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp index 44f3f34994..3baeb55009 100644 --- a/libs/input/KeyCharacterMap.cpp +++ b/libs/input/KeyCharacterMap.cpp @@ -28,10 +28,11 @@  #include <input/KeyCharacterMap.h>  #include <input/Keyboard.h> -#include <utils/Log.h> +#include <gui/constants.h>  #include <utils/Errors.h> -#include <utils/Tokenizer.h> +#include <utils/Log.h>  #include <utils/Timers.h> +#include <utils/Tokenizer.h>  // Enables debug output for the parser.  #define DEBUG_PARSER 0 diff --git a/libs/input/KeyLayoutMap.cpp b/libs/input/KeyLayoutMap.cpp index fa5a5412e6..c365ab070e 100644 --- a/libs/input/KeyLayoutMap.cpp +++ b/libs/input/KeyLayoutMap.cpp @@ -19,10 +19,10 @@  #include <stdlib.h>  #include <android/keycodes.h> +#include <ftl/NamedEnum.h>  #include <input/InputEventLabels.h>  #include <input/KeyLayoutMap.h>  #include <input/Keyboard.h> -#include <input/NamedEnum.h>  #include <utils/Errors.h>  #include <utils/Log.h>  #include <utils/Timers.h> diff --git a/libs/input/android/os/IInputFlinger.aidl b/libs/input/android/os/IInputFlinger.aidl index 1771d192af..43b262f238 100644 --- a/libs/input/android/os/IInputFlinger.aidl +++ b/libs/input/android/os/IInputFlinger.aidl @@ -16,9 +16,9 @@  package android.os; -import android.FocusRequest;  import android.InputChannel; -import android.InputWindowInfo; +import android.gui.FocusRequest; +import android.gui.WindowInfo;  import android.os.ISetInputWindowsListener;  /** @hide */ @@ -28,7 +28,7 @@ interface IInputFlinger      // ordering when needed.      // SurfaceFlinger calls this only every VSync, so overflow of binder's oneway buffer      // shouldn't be a concern. -    oneway void setInputWindows(in InputWindowInfo[] inputHandles, +    oneway void setInputWindows(in WindowInfo[] windowInfoHandles,              in @nullable ISetInputWindowsListener setInputWindowsListener);      InputChannel createInputChannel(in @utf8InCpp String name);      void removeInputChannel(in IBinder connectionToken); diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp index 6ffc6a8926..18ab1cb522 100644 --- a/libs/input/tests/Android.bp +++ b/libs/input/tests/Android.bp @@ -11,26 +11,24 @@ package {  cc_test {      name: "libinput_tests",      srcs: [ -        "NamedEnum_test.cpp", -        "Flags_test.cpp",          "IdGenerator_test.cpp",          "InputChannel_test.cpp",          "InputDevice_test.cpp",          "InputEvent_test.cpp",          "InputPublisherAndConsumer_test.cpp", -        "InputWindow_test.cpp",          "TouchVideoFrame_test.cpp",          "VelocityTracker_test.cpp",          "VerifiedInputEvent_test.cpp",      ], +    static_libs: [ +        "libgui_window_info_static", +        "libinput", +    ],      cflags: [          "-Wall",          "-Wextra",          "-Werror",      ], -    static_libs: [ -        "libinput", -    ],      shared_libs: [          "libbase",          "libbinder", diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp index 3b76ddbb7c..b1ef7534e4 100644 --- a/libs/input/tests/InputEvent_test.cpp +++ b/libs/input/tests/InputEvent_test.cpp @@ -21,6 +21,7 @@  #include <attestation/HmacKeyManager.h>  #include <binder/Parcel.h>  #include <gtest/gtest.h> +#include <gui/constants.h>  #include <input/Input.h>  namespace android { @@ -293,7 +294,7 @@ void MotionEventTest::initializeEventWithHistory(MotionEvent* event) {                        AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY,                        MotionClassification::NONE, mTransform, 2.0f, 2.1f,                        AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, -                      AMOTION_EVENT_INVALID_DISPLAY_SIZE, AMOTION_EVENT_INVALID_DISPLAY_SIZE, +                      ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE,                        ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME, 2, pointerProperties,                        pointerCoords); @@ -610,12 +611,12 @@ TEST_F(MotionEventTest, Transform) {      }      MotionEvent event;      ui::Transform identityTransform; -    event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_UNKNOWN, DISPLAY_ID, +    event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,                       INVALID_HMAC, AMOTION_EVENT_ACTION_MOVE, 0 /*actionButton*/, 0 /*flags*/,                       AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0 /*buttonState*/,                       MotionClassification::NONE, identityTransform, 0 /*xPrecision*/,                       0 /*yPrecision*/, 3 + RADIUS /*xCursorPosition*/, 2 /*yCursorPosition*/, -                     AMOTION_EVENT_INVALID_DISPLAY_SIZE, AMOTION_EVENT_INVALID_DISPLAY_SIZE, +                     ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE,                       0 /*downTime*/, 0 /*eventTime*/, pointerCount, pointerProperties,                       pointerCoords);      float originalRawX = 0 + 3; @@ -658,13 +659,17 @@ TEST_F(MotionEventTest, Transform) {      ASSERT_NEAR(originalRawY, event.getRawY(0), 0.001);  } -MotionEvent createTouchDownEvent(int x, int y, ui::Transform transform) { +MotionEvent createTouchDownEvent(float x, float y, float dx, float dy, +                                 const ui::Transform& transform, +                                 uint32_t displayOrientation = ui::Transform::ROT_0) {      std::vector<PointerProperties> pointerProperties;      pointerProperties.push_back(PointerProperties{/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER});      std::vector<PointerCoords> pointerCoords;      pointerCoords.emplace_back().clear();      pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_X, x);      pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_Y, y); +    pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, dx); +    pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, dy);      nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);      MotionEvent event;      event.initialize(InputEvent::nextId(), /* deviceId */ 1, AINPUT_SOURCE_TOUCHSCREEN, @@ -672,7 +677,8 @@ MotionEvent createTouchDownEvent(int x, int y, ui::Transform transform) {                       /* actionButton */ 0, /* flags */ 0, /* edgeFlags */ 0, AMETA_NONE,                       /* buttonState */ 0, MotionClassification::NONE, transform,                       /* xPrecision */ 0, /* yPrecision */ 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, -                     AMOTION_EVENT_INVALID_CURSOR_POSITION, /* displayWidth */ 400, +                     AMOTION_EVENT_INVALID_CURSOR_POSITION, displayOrientation, +                     /* displayWidth */ 400,                       /* displayHeight */ 800, eventTime, eventTime, pointerCoords.size(),                       pointerProperties.data(), pointerCoords.data());      return event; @@ -683,26 +689,56 @@ TEST_F(MotionEventTest, ApplyTransform) {      ui::Transform identity;      ui::Transform xform(ui::Transform::ROT_90, 800, 400);      xform.set(xform.tx() + 20, xform.ty() + 40); -    MotionEvent event = createTouchDownEvent(60, 100, xform); +    MotionEvent event = createTouchDownEvent(60, 100, 42, 96, xform, ui::Transform::ROT_90);      ASSERT_EQ(700, event.getRawX(0));      ASSERT_EQ(60, event.getRawY(0));      ASSERT_NE(event.getRawX(0), event.getX(0));      ASSERT_NE(event.getRawY(0), event.getY(0)); +    // Relative values should be rotated but not translated. +    ASSERT_EQ(-96, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0)); +    ASSERT_EQ(42, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0)); -    MotionEvent changedEvent = createTouchDownEvent(60, 100, identity); +    MotionEvent changedEvent = createTouchDownEvent(60, 100, 42, 96, identity);      const std::array<float, 9> rowMajor{xform[0][0], xform[1][0], xform[2][0],                                          xform[0][1], xform[1][1], xform[2][1],                                          xform[0][2], xform[1][2], xform[2][2]};      changedEvent.applyTransform(rowMajor);      // transformContent effectively rotates the raw coordinates, so those should now include -    // both rotation AND offset +    // both rotation AND offset.      ASSERT_EQ(720, changedEvent.getRawX(0));      ASSERT_EQ(100, changedEvent.getRawY(0)); +    // Relative values should be rotated but not translated. +    ASSERT_EQ(-96, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0)); +    ASSERT_EQ(42, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0)); -    // The transformed output should be the same then +    // The transformed output should be the same then.      ASSERT_NEAR(event.getX(0), changedEvent.getX(0), 0.001);      ASSERT_NEAR(event.getY(0), changedEvent.getY(0), 0.001); +    ASSERT_NEAR(event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0), +                changedEvent.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0), 0.001); +    ASSERT_NEAR(event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0), +                changedEvent.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0), 0.001); +} + +TEST_F(MotionEventTest, NonPointerSourcesAreNotTranslated) { +    constexpr static auto NON_POINTER_SOURCES = {AINPUT_SOURCE_TRACKBALL, +                                                 AINPUT_SOURCE_MOUSE_RELATIVE, +                                                 AINPUT_SOURCE_JOYSTICK}; +    for (uint32_t source : NON_POINTER_SOURCES) { +        // Create a rotate-90 transform with an offset (like a window which isn't fullscreen). +        ui::Transform xform(ui::Transform::ROT_90, 800, 400); +        xform.set(xform.tx() + 20, xform.ty() + 40); +        MotionEvent event = createTouchDownEvent(60, 100, 42, 96, xform, ui::Transform::ROT_90); +        event.setSource(source); + +        // Since this event comes from a non-pointer source, it should include rotation but not +        // translation/offset. +        ASSERT_EQ(-100, event.getX(0)); +        ASSERT_EQ(60, event.getY(0)); +        ASSERT_EQ(event.getRawX(0), event.getX(0)); +        ASSERT_EQ(event.getRawY(0), event.getY(0)); +    }  }  TEST_F(MotionEventTest, RawCompatTransform) { @@ -710,11 +746,14 @@ TEST_F(MotionEventTest, RawCompatTransform) {          // Make sure raw is raw regardless of transform translation.          ui::Transform xform;          xform.set(20, 40); -        MotionEvent event = createTouchDownEvent(60, 100, xform); +        MotionEvent event = createTouchDownEvent(60, 100, 42, 96, xform);          ASSERT_EQ(60, event.getRawX(0));          ASSERT_EQ(100, event.getRawY(0));          ASSERT_NE(event.getRawX(0), event.getX(0));          ASSERT_NE(event.getRawY(0), event.getY(0)); +        // Relative values should not be modified. +        ASSERT_EQ(42, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0)); +        ASSERT_EQ(96, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0));      }      // Next check that getRaw contains rotation (for compatibility) but otherwise is still @@ -723,29 +762,50 @@ TEST_F(MotionEventTest, RawCompatTransform) {          // Create a rotate-90 transform with an offset (like a window which isn't fullscreen).          ui::Transform xform(ui::Transform::ROT_90, 800, 400);          xform.set(xform.tx() + 20, xform.ty() + 40); -        MotionEvent event = createTouchDownEvent(60, 100, xform); +        MotionEvent event = createTouchDownEvent(60, 100, 42, 96, xform, ui::Transform::ROT_90);          ASSERT_EQ(700, event.getRawX(0));          ASSERT_EQ(60, event.getRawY(0));          ASSERT_NE(event.getRawX(0), event.getX(0));          ASSERT_NE(event.getRawY(0), event.getY(0)); +        // Relative values should be rotated but not translated. +        ASSERT_EQ(-96, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0)); +        ASSERT_EQ(42, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0));      }      {          // Same as above, but check rotate-180.          ui::Transform xform(ui::Transform::ROT_180, 400, 800);          xform.set(xform.tx() + 20, xform.ty() + 40); -        MotionEvent event = createTouchDownEvent(60, 100, xform); +        MotionEvent event = createTouchDownEvent(60, 100, 42, 96, xform, ui::Transform::ROT_180);          ASSERT_EQ(340, event.getRawX(0));          ASSERT_EQ(700, event.getRawY(0)); +        // Relative values should be rotated but not translated. +        ASSERT_EQ(-42, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0)); +        ASSERT_EQ(-96, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0));      }      {          // Same as above, but check rotate-270.          ui::Transform xform(ui::Transform::ROT_270, 800, 400);          xform.set(xform.tx() + 20, xform.ty() + 40); -        MotionEvent event = createTouchDownEvent(60, 100, xform); +        MotionEvent event = createTouchDownEvent(60, 100, 42, 96, xform, ui::Transform::ROT_270);          ASSERT_EQ(100, event.getRawX(0));          ASSERT_EQ(340, event.getRawY(0)); +        // Relative values should be rotated but not translated. +        ASSERT_EQ(96, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0)); +        ASSERT_EQ(-42, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0)); +    } + +    { +        // Finally, check that raw isn't effected by transform +        ui::Transform xform(ui::Transform::ROT_270, 800, 400); +        xform.set(xform.tx() + 20, xform.ty() + 40); +        MotionEvent event = createTouchDownEvent(60, 100, 42, 96, xform, ui::Transform::ROT_90); +        ASSERT_EQ(700, event.getRawX(0)); +        ASSERT_EQ(60, event.getRawY(0)); +        // Relative values should be rotated but not translated. +        ASSERT_EQ(96, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0)); +        ASSERT_EQ(-42, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0));      }  } @@ -772,9 +832,9 @@ TEST_F(MotionEventTest, Initialize_SetsClassification) {                           DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,                           AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, classification,                           identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, -                         AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_DISPLAY_SIZE, -                         AMOTION_EVENT_INVALID_DISPLAY_SIZE, 0 /*downTime*/, 0 /*eventTime*/, -                         pointerCount, pointerProperties, pointerCoords); +                         AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0, +                         INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, 0 /*downTime*/, +                         0 /*eventTime*/, pointerCount, pointerProperties, pointerCoords);          ASSERT_EQ(classification, event.getClassification());      }  } @@ -794,10 +854,9 @@ TEST_F(MotionEventTest, Initialize_SetsCursorPosition) {      event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_MOUSE, DISPLAY_ID,                       INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0, AMOTION_EVENT_EDGE_FLAG_NONE,                       AMETA_NONE, 0, MotionClassification::NONE, identityTransform, 0, 0, -                     280 /*xCursorPosition*/, 540 /*yCursorPosition*/, -                     AMOTION_EVENT_INVALID_DISPLAY_SIZE, AMOTION_EVENT_INVALID_DISPLAY_SIZE, -                     0 /*downTime*/, 0 /*eventTime*/, pointerCount, pointerProperties, -                     pointerCoords); +                     280 /*xCursorPosition*/, 540 /*yCursorPosition*/, ui::Transform::ROT_0, +                     INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, 0 /*downTime*/, 0 /*eventTime*/, +                     pointerCount, pointerProperties, pointerCoords);      event.offsetLocation(20, 60);      ASSERT_EQ(280, event.getRawXCursorPosition());      ASSERT_EQ(540, event.getRawYCursorPosition()); diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp index a2cfaa1cc0..5d1f2c3bfc 100644 --- a/libs/input/tests/InputPublisherAndConsumer_test.cpp +++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp @@ -23,6 +23,7 @@  #include <attestation/HmacKeyManager.h>  #include <cutils/ashmem.h>  #include <gtest/gtest.h> +#include <gui/constants.h>  #include <input/InputTransport.h>  #include <utils/StopWatch.h>  #include <utils/Timers.h> @@ -162,6 +163,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent() {      constexpr float yPrecision = 0.5;      constexpr float xCursorPosition = 1.3;      constexpr float yCursorPosition = 50.6; +    constexpr uint32_t displayOrientation = ui::Transform::ROT_0;      constexpr int32_t displayWidth = 1000;      constexpr int32_t displayHeight = 2000;      constexpr nsecs_t downTime = 3; @@ -192,9 +194,9 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent() {      status = mPublisher->publishMotionEvent(seq, eventId, deviceId, source, displayId, hmac, action,                                              actionButton, flags, edgeFlags, metaState, buttonState,                                              classification, transform, xPrecision, yPrecision, -                                            xCursorPosition, yCursorPosition, displayWidth, -                                            displayHeight, downTime, eventTime, pointerCount, -                                            pointerProperties, pointerCoords); +                                            xCursorPosition, yCursorPosition, displayOrientation, +                                            displayWidth, displayHeight, downTime, eventTime, +                                            pointerCount, pointerProperties, pointerCoords);      ASSERT_EQ(OK, status)              << "publisher publishMotionEvent should return OK"; @@ -231,6 +233,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent() {      EXPECT_EQ(yCursorPosition, motionEvent->getRawYCursorPosition());      EXPECT_EQ(xCursorPosition * xScale + xOffset, motionEvent->getXCursorPosition());      EXPECT_EQ(yCursorPosition * yScale + yOffset, motionEvent->getYCursorPosition()); +    EXPECT_EQ(displayOrientation, motionEvent->getDisplayOrientation());      EXPECT_EQ(displayWidth, motionEvent->getDisplaySize().x);      EXPECT_EQ(displayHeight, motionEvent->getDisplaySize().y);      EXPECT_EQ(downTime, motionEvent->getDownTime()); @@ -460,8 +463,9 @@ TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenSequenceNumberIsZer      status = mPublisher->publishMotionEvent(0, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,                                              0, 0, 0, MotionClassification::NONE, identityTransform,                                              0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, -                                            AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0, 0, 0, -                                            pointerCount, pointerProperties, pointerCoords); +                                            AMOTION_EVENT_INVALID_CURSOR_POSITION, +                                            ui::Transform::ROT_0, 0, 0, 0, 0, pointerCount, +                                            pointerProperties, pointerCoords);      ASSERT_EQ(BAD_VALUE, status)              << "publisher publishMotionEvent should return BAD_VALUE";  } @@ -476,8 +480,9 @@ TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountLessTha      status = mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,                                              0, 0, 0, MotionClassification::NONE, identityTransform,                                              0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, -                                            AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0, 0, 0, -                                            pointerCount, pointerProperties, pointerCoords); +                                            AMOTION_EVENT_INVALID_CURSOR_POSITION, +                                            ui::Transform::ROT_0, 0, 0, 0, 0, pointerCount, +                                            pointerProperties, pointerCoords);      ASSERT_EQ(BAD_VALUE, status)              << "publisher publishMotionEvent should return BAD_VALUE";  } @@ -497,8 +502,9 @@ TEST_F(InputPublisherAndConsumerTest,      status = mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,                                              0, 0, 0, MotionClassification::NONE, identityTransform,                                              0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, -                                            AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0, 0, 0, -                                            pointerCount, pointerProperties, pointerCoords); +                                            AMOTION_EVENT_INVALID_CURSOR_POSITION, +                                            ui::Transform::ROT_0, 0, 0, 0, 0, pointerCount, +                                            pointerProperties, pointerCoords);      ASSERT_EQ(BAD_VALUE, status)              << "publisher publishMotionEvent should return BAD_VALUE";  } diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp index 5861d55156..59fed1fb41 100644 --- a/libs/input/tests/StructLayout_test.cpp +++ b/libs/input/tests/StructLayout_test.cpp @@ -74,10 +74,10 @@ void TestInputMessageAlignment() {    CHECK_OFFSET(InputMessage::Body::Motion, yPrecision, 124);    CHECK_OFFSET(InputMessage::Body::Motion, xCursorPosition, 128);    CHECK_OFFSET(InputMessage::Body::Motion, yCursorPosition, 132); -  CHECK_OFFSET(InputMessage::Body::Motion, displayWidth, 136); -  CHECK_OFFSET(InputMessage::Body::Motion, displayHeight, 140); -  CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 144); -  CHECK_OFFSET(InputMessage::Body::Motion, empty3, 148); +  CHECK_OFFSET(InputMessage::Body::Motion, displayOrientation, 136); +  CHECK_OFFSET(InputMessage::Body::Motion, displayWidth, 140); +  CHECK_OFFSET(InputMessage::Body::Motion, displayHeight, 144); +  CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 148);    CHECK_OFFSET(InputMessage::Body::Motion, pointers, 152);    CHECK_OFFSET(InputMessage::Body::Focus, eventId, 0); diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp index aefc2ec47d..13e2b02ca4 100644 --- a/libs/input/tests/VelocityTracker_test.cpp +++ b/libs/input/tests/VelocityTracker_test.cpp @@ -23,6 +23,7 @@  #include <android-base/stringprintf.h>  #include <attestation/HmacKeyManager.h>  #include <gtest/gtest.h> +#include <gui/constants.h>  #include <input/VelocityTracker.h>  using namespace std::chrono_literals; @@ -183,8 +184,8 @@ static std::vector<MotionEvent> createMotionEventStream(                           AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0 /*buttonState*/,                           MotionClassification::NONE, identityTransform, 0 /*xPrecision*/,                           0 /*yPrecision*/, AMOTION_EVENT_INVALID_CURSOR_POSITION, -                         AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_DISPLAY_SIZE, -                         AMOTION_EVENT_INVALID_DISPLAY_SIZE, 0 /*downTime*/, +                         AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0, +                         INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, 0 /*downTime*/,                           entry.eventTime.count(), pointerCount, properties, coords);          events.emplace_back(event); diff --git a/libs/input/tests/VerifiedInputEvent_test.cpp b/libs/input/tests/VerifiedInputEvent_test.cpp index f79098c63c..b29c9a4877 100644 --- a/libs/input/tests/VerifiedInputEvent_test.cpp +++ b/libs/input/tests/VerifiedInputEvent_test.cpp @@ -16,6 +16,7 @@  #include <attestation/HmacKeyManager.h>  #include <gtest/gtest.h> +#include <gui/constants.h>  #include <input/Input.h>  namespace android { @@ -46,10 +47,9 @@ static MotionEvent getMotionEventWithFlags(int32_t flags) {                       INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0 /*actionButton*/, flags,                       AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0 /*buttonState*/,                       MotionClassification::NONE, transform, 0.1 /*xPrecision*/, 0.2 /*yPrecision*/, -                     280 /*xCursorPosition*/, 540 /*yCursorPosition*/, -                     AMOTION_EVENT_INVALID_DISPLAY_SIZE, AMOTION_EVENT_INVALID_DISPLAY_SIZE, -                     100 /*downTime*/, 200 /*eventTime*/, pointerCount, pointerProperties, -                     pointerCoords); +                     280 /*xCursorPosition*/, 540 /*yCursorPosition*/, ui::Transform::ROT_0, +                     INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, 100 /*downTime*/, +                     200 /*eventTime*/, pointerCount, pointerProperties, pointerCoords);      return event;  } diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp index 0edb213089..2dd6c4fcaa 100644 --- a/libs/nativedisplay/AChoreographer.cpp +++ b/libs/nativedisplay/AChoreographer.cpp @@ -20,7 +20,6 @@  #include <android-base/thread_annotations.h>  #include <gui/DisplayEventDispatcher.h>  #include <gui/ISurfaceComposer.h> -#include <gui/SurfaceComposerClient.h>  #include <jni.h>  #include <private/android/choreographer.h>  #include <utils/Looper.h> diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h index 4cb1b4259b..14627ce0ce 100644 --- a/libs/renderengine/gl/GLESRenderEngine.h +++ b/libs/renderengine/gl/GLESRenderEngine.h @@ -71,7 +71,7 @@ public:      void cleanupPostRender() override;      int getContextPriority() override;      bool supportsBackgroundBlur() override { return mBlurFilter != nullptr; } -    void onPrimaryDisplaySizeChanged(ui::Size size) override {} +    void onActiveDisplaySizeChanged(ui::Size size) override {}      EGLDisplay getEGLDisplay() const { return mEGLDisplay; }      // Creates an output image for rendering to diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index 5964bc3927..967cf5deff 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -129,9 +129,9 @@ public:      // Attempt to switch RenderEngine into and out of protectedContext mode      virtual void useProtectedContext(bool useProtectedContext) = 0; -    // Notify RenderEngine of changes to the dimensions of the primary display +    // Notify RenderEngine of changes to the dimensions of the active display      // so that it can configure its internal caches accordingly. -    virtual void onPrimaryDisplaySizeChanged(ui::Size size) = 0; +    virtual void onActiveDisplaySizeChanged(ui::Size size) = 0;      // Renders layers for a particular display via GPU composition. This method      // should be called for every display that needs to be rendered via the GPU. diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h index a4aa9ea488..0be3ba6b11 100644 --- a/libs/renderengine/include/renderengine/mock/RenderEngine.h +++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h @@ -54,7 +54,7 @@ public:      MOCK_METHOD0(cleanFramebufferCache, void());      MOCK_METHOD0(getContextPriority, int());      MOCK_METHOD0(supportsBackgroundBlur, bool()); -    MOCK_METHOD1(onPrimaryDisplaySizeChanged, void(ui::Size)); +    MOCK_METHOD1(onActiveDisplaySizeChanged, void(ui::Size));  protected:      // mock renderengine still needs to implement these, but callers should never need to call them. diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp index 3c59f11395..f4b07d06a5 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp @@ -1398,7 +1398,7 @@ int SkiaGLRenderEngine::getContextPriority() {      return value;  } -void SkiaGLRenderEngine::onPrimaryDisplaySizeChanged(ui::Size size) { +void SkiaGLRenderEngine::onActiveDisplaySizeChanged(ui::Size size) {      // This cache multiplier was selected based on review of cache sizes relative      // to the screen resolution. Looking at the worst case memory needed by blur (~1.5x),      // shadows (~1x), and general data structures (e.g. vertex buffers) we selected this as a diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h index a852bbcaf8..cc91948ac9 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.h +++ b/libs/renderengine/skia/SkiaGLRenderEngine.h @@ -67,7 +67,7 @@ public:      void useProtectedContext(bool useProtectedContext) override;      bool supportsBackgroundBlur() override { return mBlurFilter != nullptr; }      void assertShadersCompiled(int numShaders) override; -    void onPrimaryDisplaySizeChanged(ui::Size size) override; +    void onActiveDisplaySizeChanged(ui::Size size) override;      int reportShadersCompiled() override;  protected: diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp index b9dabc1d05..8e666d5733 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.cpp +++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp @@ -361,14 +361,14 @@ bool RenderEngineThreaded::supportsBackgroundBlur() {      return mRenderEngine->supportsBackgroundBlur();  } -void RenderEngineThreaded::onPrimaryDisplaySizeChanged(ui::Size size) { +void RenderEngineThreaded::onActiveDisplaySizeChanged(ui::Size size) {      // This function is designed so it can run asynchronously, so we do not need to wait      // for the futures.      {          std::lock_guard lock(mThreadMutex);          mFunctionCalls.push([size](renderengine::RenderEngine& instance) { -            ATRACE_NAME("REThreaded::onPrimaryDisplaySizeChanged"); -            instance.onPrimaryDisplaySizeChanged(size); +            ATRACE_NAME("REThreaded::onActiveDisplaySizeChanged"); +            instance.onActiveDisplaySizeChanged(size);          });      }      mCondition.notify_one(); diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h index f2f5c0f7cd..b197df7e0f 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.h +++ b/libs/renderengine/threaded/RenderEngineThreaded.h @@ -65,7 +65,7 @@ public:      void cleanFramebufferCache() override;      int getContextPriority() override;      bool supportsBackgroundBlur() override; -    void onPrimaryDisplaySizeChanged(ui::Size size) override; +    void onActiveDisplaySizeChanged(ui::Size size) override;  protected:      void mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, bool isRenderable) override; diff --git a/libs/vibrator/ExternalVibrationUtils.cpp b/libs/vibrator/ExternalVibrationUtils.cpp index 749c568457..980b08ba36 100644 --- a/libs/vibrator/ExternalVibrationUtils.cpp +++ b/libs/vibrator/ExternalVibrationUtils.cpp @@ -56,6 +56,36 @@ float getHapticMaxAmplitudeRatio(HapticScale scale) {      }  } +void applyHapticScale(float* buffer, size_t length, HapticScale scale) { +    if (scale == HapticScale::MUTE) { +        memset(buffer, 0, length * sizeof(float)); +        return; +    } +    if (scale == HapticScale::NONE) { +        return; +    } +    float gamma = getHapticScaleGamma(scale); +    float maxAmplitudeRatio = getHapticMaxAmplitudeRatio(scale); +    for (size_t i = 0; i < length; i++) { +        float sign = buffer[i] >= 0 ? 1.0 : -1.0; +        buffer[i] = powf(fabsf(buffer[i] / HAPTIC_MAX_AMPLITUDE_FLOAT), gamma) +                * maxAmplitudeRatio * HAPTIC_MAX_AMPLITUDE_FLOAT * sign; +    } +} + +void clipHapticData(float* buffer, size_t length, float limit) { +    if (isnan(limit) || limit == 0) { +        return; +    } +    limit = fabsf(limit); +    for (size_t i = 0; i < length; i++) { +        float sign = buffer[i] >= 0 ? 1.0 : -1.0; +        if (fabsf(buffer[i]) > limit) { +            buffer[i] = limit * sign; +        } +    } +} +  } // namespace  bool isValidHapticScale(HapticScale scale) { @@ -71,21 +101,11 @@ bool isValidHapticScale(HapticScale scale) {      return false;  } -void scaleHapticData(float* buffer, size_t length, HapticScale scale) { -    if (!isValidHapticScale(scale) || scale == HapticScale::NONE) { -        return; -    } -    if (scale == HapticScale::MUTE) { -        memset(buffer, 0, length * sizeof(float)); -        return; -    } -    float gamma = getHapticScaleGamma(scale); -    float maxAmplitudeRatio = getHapticMaxAmplitudeRatio(scale); -    for (size_t i = 0; i < length; i++) { -        float sign = buffer[i] >= 0 ? 1.0 : -1.0; -        buffer[i] = powf(fabsf(buffer[i] / HAPTIC_MAX_AMPLITUDE_FLOAT), gamma) -                * maxAmplitudeRatio * HAPTIC_MAX_AMPLITUDE_FLOAT * sign; +void scaleHapticData(float* buffer, size_t length, HapticScale scale, float limit) { +    if (isValidHapticScale(scale)) { +        applyHapticScale(buffer, length, scale);      } +    clipHapticData(buffer, length, limit);  }  } // namespace android::os diff --git a/libs/vibrator/include/vibrator/ExternalVibrationUtils.h b/libs/vibrator/include/vibrator/ExternalVibrationUtils.h index 20045d0769..84357fcb35 100644 --- a/libs/vibrator/include/vibrator/ExternalVibrationUtils.h +++ b/libs/vibrator/include/vibrator/ExternalVibrationUtils.h @@ -32,7 +32,11 @@ enum class HapticScale {  bool isValidHapticScale(HapticScale scale); -void scaleHapticData(float* buffer, size_t length, HapticScale scale); +/* Scales the haptic data in given buffer using the selected HapticScale and ensuring no absolute + * value will be larger than the absolute of given limit. + * The limit will be ignored if it is NaN or zero. + */ +void scaleHapticData(float* buffer, size_t length, HapticScale scale, float limit);  } // namespace android::os diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp index 6612a932a0..73e57495e6 100644 --- a/services/inputflinger/Android.bp +++ b/services/inputflinger/Android.bp @@ -73,6 +73,7 @@ cc_defaults {          "libui",          "lib-platform-compat-native-api",          "server_configurable_flags", +        "InputFlingerProperties",      ],      static_libs: [          "libattestation", @@ -95,6 +96,7 @@ cc_library_shared {          "libinputflinger_base",          "libinputreporter",          "libinputreader", +        "libgui",      ],      static_libs: [          "libinputdispatcher", diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp index a50e5c70f7..693b1f977f 100644 --- a/services/inputflinger/InputManager.cpp +++ b/services/inputflinger/InputManager.cpp @@ -31,6 +31,10 @@  namespace android { +using gui::FocusRequest; +using gui::WindowInfo; +using gui::WindowInfoHandle; +  static int32_t exceptionCodeFromStatusT(status_t status) {      switch (status) {          case OK: @@ -110,24 +114,15 @@ sp<InputDispatcherInterface> InputManager::getDispatcher() {      return mDispatcher;  } -class BinderWindowHandle : public InputWindowHandle { -public: -    BinderWindowHandle(const InputWindowInfo& info) { mInfo = info; } - -    bool updateInfo() override { -        return true; -    } -}; -  binder::Status InputManager::setInputWindows( -        const std::vector<InputWindowInfo>& infos, +        const std::vector<WindowInfo>& infos,          const sp<ISetInputWindowsListener>& setInputWindowsListener) { -    std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>> handlesPerDisplay; +    std::unordered_map<int32_t, std::vector<sp<WindowInfoHandle>>> handlesPerDisplay; -    std::vector<sp<InputWindowHandle>> handles; +    std::vector<sp<WindowInfoHandle>> handles;      for (const auto& info : infos) { -        handlesPerDisplay.emplace(info.displayId, std::vector<sp<InputWindowHandle>>()); -        handlesPerDisplay[info.displayId].push_back(new BinderWindowHandle(info)); +        handlesPerDisplay.emplace(info.displayId, std::vector<sp<WindowInfoHandle>>()); +        handlesPerDisplay[info.displayId].push_back(new WindowInfoHandle(info));      }      mDispatcher->setInputWindows(handlesPerDisplay); diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h index 49bea132c8..035a9a32f7 100644 --- a/services/inputflinger/InputManager.h +++ b/services/inputflinger/InputManager.h @@ -105,12 +105,12 @@ public:      status_t dump(int fd, const Vector<String16>& args) override;      binder::Status setInputWindows( -            const std::vector<InputWindowInfo>& handles, +            const std::vector<gui::WindowInfo>& handles,              const sp<ISetInputWindowsListener>& setInputWindowsListener) override;      binder::Status createInputChannel(const std::string& name, InputChannel* outChannel) override;      binder::Status removeInputChannel(const sp<IBinder>& connectionToken) override; -    binder::Status setFocusedWindow(const FocusRequest&) override; +    binder::Status setFocusedWindow(const gui::FocusRequest&) override;  private:      sp<InputReaderInterface> mReader; diff --git a/services/inputflinger/InputReaderBase.cpp b/services/inputflinger/InputReaderBase.cpp index 9cc777d450..f26a9a986d 100644 --- a/services/inputflinger/InputReaderBase.cpp +++ b/services/inputflinger/InputReaderBase.cpp @@ -19,9 +19,9 @@  //#define LOG_NDEBUG 0  #include "InputReaderBase.h" +#include <ftl/NamedEnum.h>  #include "input/DisplayViewport.h"  #include "input/Input.h" -#include "input/NamedEnum.h"  #include <android/log.h>  #include <android-base/stringprintf.h> diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp index bc77b8aef4..5e9facf47e 100644 --- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp +++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp @@ -18,8 +18,11 @@  #include <android/os/IInputConstants.h>  #include <binder/Binder.h> +#include <gui/constants.h>  #include "../dispatcher/InputDispatcher.h" +using android::gui::WindowInfo; +using android::gui::WindowInfoHandle;  using android::os::IInputConstants;  using android::os::InputEventInjectionResult;  using android::os::InputEventInjectionSync; @@ -173,7 +176,7 @@ protected:      PreallocatedInputEventFactory mEventFactory;  }; -class FakeWindowHandle : public InputWindowHandle, public FakeInputReceiver { +class FakeWindowHandle : public WindowInfoHandle, public FakeInputReceiver {  public:      static const int32_t WIDTH = 200;      static const int32_t HEIGHT = 200; @@ -182,13 +185,14 @@ public:                       const sp<InputDispatcher>& dispatcher, const std::string name)            : FakeInputReceiver(dispatcher, name), mFrame(Rect(0, 0, WIDTH, HEIGHT)) {          inputApplicationHandle->updateInfo(); +        updateInfo();          mInfo.applicationInfo = *inputApplicationHandle->getInfo();      } -    virtual bool updateInfo() override { +    void updateInfo() {          mInfo.token = mClientChannel->getConnectionToken();          mInfo.name = "FakeWindowHandle"; -        mInfo.type = InputWindowInfo::Type::APPLICATION; +        mInfo.type = WindowInfo::Type::APPLICATION;          mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;          mInfo.frameLeft = mFrame.left;          mInfo.frameTop = mFrame.top; @@ -204,8 +208,6 @@ public:          mInfo.ownerPid = INJECTOR_PID;          mInfo.ownerUid = INJECTOR_UID;          mInfo.displayId = ADISPLAY_ID_DEFAULT; - -        return true;      }  protected: @@ -234,8 +236,8 @@ static MotionEvent generateMotionEvent() {                       /* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,                       identityTransform, /* xPrecision */ 0,                       /* yPrecision */ 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, -                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_DISPLAY_SIZE, -                     AMOTION_EVENT_INVALID_DISPLAY_SIZE, currentTime, currentTime, +                     AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0, +                     INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, currentTime, currentTime,                       /*pointerCount*/ 1, pointerProperties, pointerCoords);      return event;  } diff --git a/services/inputflinger/dispatcher/Android.bp b/services/inputflinger/dispatcher/Android.bp index 1b3888b340..171f2b5ce8 100644 --- a/services/inputflinger/dispatcher/Android.bp +++ b/services/inputflinger/dispatcher/Android.bp @@ -64,9 +64,11 @@ cc_defaults {          "libstatspull",          "libstatssocket",          "libui", +        "libgui",          "libutils",          "lib-platform-compat-native-api",          "server_configurable_flags", +        "InputFlingerProperties",      ],      static_libs: [          "libattestation", diff --git a/services/inputflinger/dispatcher/DragState.cpp b/services/inputflinger/dispatcher/DragState.cpp index 2e2df43009..e1844a4a3a 100644 --- a/services/inputflinger/dispatcher/DragState.cpp +++ b/services/inputflinger/dispatcher/DragState.cpp @@ -16,9 +16,7 @@  #include "DragState.h"  #include <android-base/stringprintf.h> -#include <input/InputWindow.h> -using android::InputWindowHandle;  using android::base::StringPrintf;  namespace android::inputdispatcher { diff --git a/services/inputflinger/dispatcher/DragState.h b/services/inputflinger/dispatcher/DragState.h index 06453d8eee..b3c5709cbc 100644 --- a/services/inputflinger/dispatcher/DragState.h +++ b/services/inputflinger/dispatcher/DragState.h @@ -17,22 +17,22 @@  #ifndef _UI_INPUT_INPUTDISPATCHER_DRAGSTATE_H  #define _UI_INPUT_INPUTDISPATCHER_DRAGSTATE_H +#include <gui/WindowInfo.h>  #include <utils/RefBase.h>  #include <string>  namespace android { -class InputWindowHandle; -  namespace inputdispatcher { +  struct DragState { -    DragState(const sp<android::InputWindowHandle>& windowHandle) : dragWindow(windowHandle) {} +    DragState(const sp<android::gui::WindowInfoHandle>& windowHandle) : dragWindow(windowHandle) {}      void dump(std::string& dump, const char* prefix = "");      // The window being dragged. -    const sp<InputWindowHandle> dragWindow; +    const sp<android::gui::WindowInfoHandle> dragWindow;      // The last drag hover window which could receive the drag event. -    sp<InputWindowHandle> dragHoverWindowHandle; +    sp<android::gui::WindowInfoHandle> dragHoverWindowHandle;      // Indicates the if received first event to check for button state.      bool isStartDrag = false;      // Indicate if the stylus button is down at the start of the drag. diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp index 881024fc6e..b5ed0640cd 100644 --- a/services/inputflinger/dispatcher/Entry.cpp +++ b/services/inputflinger/dispatcher/Entry.cpp @@ -296,12 +296,14 @@ std::string SensorEntry::getDescription() const {  volatile int32_t DispatchEntry::sNextSeqAtomic;  DispatchEntry::DispatchEntry(std::shared_ptr<EventEntry> eventEntry, int32_t targetFlags, -                             ui::Transform transform, float globalScaleFactor, int2 displaySize) +                             ui::Transform transform, float globalScaleFactor, +                             uint32_t displayOrientation, int2 displaySize)        : seq(nextSeq()),          eventEntry(std::move(eventEntry)),          targetFlags(targetFlags),          transform(transform),          globalScaleFactor(globalScaleFactor), +        displayOrientation(displayOrientation),          displaySize(displaySize),          deliveryTime(0),          resolvedAction(0), diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h index ebbd8e93bf..1b7fcf2f75 100644 --- a/services/inputflinger/dispatcher/Entry.h +++ b/services/inputflinger/dispatcher/Entry.h @@ -20,8 +20,8 @@  #include "InjectionState.h"  #include "InputTarget.h" +#include <gui/InputApplication.h>  #include <input/Input.h> -#include <input/InputApplication.h>  #include <stdint.h>  #include <utils/Timers.h>  #include <functional> @@ -215,6 +215,7 @@ struct DispatchEntry {      int32_t targetFlags;      ui::Transform transform;      float globalScaleFactor; +    uint32_t displayOrientation;      int2 displaySize;      // Both deliveryTime and timeoutTime are only populated when the entry is sent to the app,      // and will be undefined before that. @@ -228,7 +229,8 @@ struct DispatchEntry {      int32_t resolvedFlags;      DispatchEntry(std::shared_ptr<EventEntry> eventEntry, int32_t targetFlags, -                  ui::Transform transform, float globalScaleFactor, int2 displaySize); +                  ui::Transform transform, float globalScaleFactor, uint32_t displayOrientation, +                  int2 displaySize);      inline bool hasForegroundTarget() const { return targetFlags & InputTarget::FLAG_FOREGROUND; } diff --git a/services/inputflinger/dispatcher/FocusResolver.cpp b/services/inputflinger/dispatcher/FocusResolver.cpp index fb194355ba..4a75773201 100644 --- a/services/inputflinger/dispatcher/FocusResolver.cpp +++ b/services/inputflinger/dispatcher/FocusResolver.cpp @@ -27,12 +27,15 @@ static constexpr bool DEBUG_FOCUS = false;  #include <android-base/stringprintf.h>  #include <binder/Binder.h> -#include <input/InputWindow.h> -#include <input/NamedEnum.h> +#include <ftl/NamedEnum.h> +#include <gui/WindowInfo.h>  #include <log/log.h>  #include "FocusResolver.h" +using android::gui::FocusRequest; +using android::gui::WindowInfoHandle; +  namespace android::inputdispatcher {  sp<IBinder> FocusResolver::getFocusedWindowToken(int32_t displayId) const { @@ -52,7 +55,7 @@ std::optional<FocusRequest> FocusResolver::getFocusRequest(int32_t displayId) {   * we will check if the previous focus request is eligible to receive focus.   */  std::optional<FocusResolver::FocusChanges> FocusResolver::setInputWindows( -        int32_t displayId, const std::vector<sp<InputWindowHandle>>& windows) { +        int32_t displayId, const std::vector<sp<WindowInfoHandle>>& windows) {      std::string removeFocusReason;      // Check if the currently focused window is still focusable. @@ -87,7 +90,7 @@ std::optional<FocusResolver::FocusChanges> FocusResolver::setInputWindows(  }  std::optional<FocusResolver::FocusChanges> FocusResolver::setFocusedWindow( -        const FocusRequest& request, const std::vector<sp<InputWindowHandle>>& windows) { +        const FocusRequest& request, const std::vector<sp<WindowInfoHandle>>& windows) {      const int32_t displayId = request.displayId;      const sp<IBinder> currentFocus = getFocusedWindowToken(displayId);      if (currentFocus == request.token) { @@ -136,11 +139,11 @@ std::optional<FocusResolver::FocusChanges> FocusResolver::setFocusedWindow(  }  FocusResolver::Focusability FocusResolver::isTokenFocusable( -        const sp<IBinder>& token, const std::vector<sp<InputWindowHandle>>& windows) { +        const sp<IBinder>& token, const std::vector<sp<WindowInfoHandle>>& windows) {      bool allWindowsAreFocusable = true;      bool visibleWindowFound = false;      bool windowFound = false; -    for (const sp<InputWindowHandle>& window : windows) { +    for (const sp<WindowInfoHandle>& window : windows) {          if (window->getToken() != token) {              continue;          } diff --git a/services/inputflinger/dispatcher/FocusResolver.h b/services/inputflinger/dispatcher/FocusResolver.h index afe16b3b45..1d6cd9a5fa 100644 --- a/services/inputflinger/dispatcher/FocusResolver.h +++ b/services/inputflinger/dispatcher/FocusResolver.h @@ -20,9 +20,9 @@  #include <optional>  #include <unordered_map> -#include <android/FocusRequest.h> +#include <android/gui/FocusRequest.h>  #include <binder/Binder.h> -#include <input/InputWindow.h> +#include <gui/WindowInfo.h>  namespace android::inputdispatcher { @@ -58,9 +58,10 @@ public:          std::string reason;      };      std::optional<FocusResolver::FocusChanges> setInputWindows( -            int32_t displayId, const std::vector<sp<InputWindowHandle>>& windows); +            int32_t displayId, const std::vector<sp<android::gui::WindowInfoHandle>>& windows);      std::optional<FocusResolver::FocusChanges> setFocusedWindow( -            const FocusRequest& request, const std::vector<sp<InputWindowHandle>>& windows); +            const android::gui::FocusRequest& request, +            const std::vector<sp<android::gui::WindowInfoHandle>>& windows);      // Display has been removed from the system, clean up old references.      void displayRemoved(int32_t displayId); @@ -87,8 +88,9 @@ private:      // we expect the focusability of the windows to match since its hard to reason why one window      // can receive focus events and the other cannot when both are backed by the same input channel.      // -    static Focusability isTokenFocusable(const sp<IBinder>& token, -                                         const std::vector<sp<InputWindowHandle>>& windows); +    static Focusability isTokenFocusable( +            const sp<IBinder>& token, +            const std::vector<sp<android::gui::WindowInfoHandle>>& windows);      // Focus tracking for keys, trackball, etc. A window token can be associated with one or      // more InputWindowHandles. If a window is mirrored, the window and its mirror will share @@ -99,7 +101,7 @@ private:      // This map will store the focus request per display. When the input window handles are updated,      // the current request will be checked to see if it can be processed at that time. -    std::unordered_map<int32_t /* displayId */, FocusRequest> mFocusRequestByDisplay; +    std::unordered_map<int32_t /* displayId */, android::gui::FocusRequest> mFocusRequestByDisplay;      // Last reason for not granting a focus request. This is used to add more debug information      // in the event logs. @@ -108,7 +110,7 @@ private:      std::optional<FocusResolver::FocusChanges> updateFocusedWindow(              int32_t displayId, const std::string& reason, const sp<IBinder>& token,              const std::string& tokenName = ""); -    std::optional<FocusRequest> getFocusRequest(int32_t displayId); +    std::optional<android::gui::FocusRequest> getFocusRequest(int32_t displayId);  };  } // namespace android::inputdispatcher
\ No newline at end of file diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index a51978627f..aa667803dd 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -47,6 +47,7 @@ static constexpr bool DEBUG_TOUCH_OCCLUSION = true;  // Log debug messages about hover events.  #define DEBUG_HOVER 0 +#include <InputFlingerProperties.sysprop.h>  #include <android-base/chrono_utils.h>  #include <android-base/properties.h>  #include <android-base/stringprintf.h> @@ -54,8 +55,8 @@ static constexpr bool DEBUG_TOUCH_OCCLUSION = true;  #include <binder/Binder.h>  #include <binder/IServiceManager.h>  #include <com/android/internal/compat/IPlatformCompatNative.h> +#include <gui/SurfaceComposerClient.h>  #include <input/InputDevice.h> -#include <input/InputWindow.h>  #include <log/log.h>  #include <log/log_event_list.h>  #include <powermanager/PowerManager.h> @@ -81,6 +82,10 @@ static constexpr bool DEBUG_TOUCH_OCCLUSION = true;  using android::base::HwTimeoutMultiplier;  using android::base::Result;  using android::base::StringPrintf; +using android::gui::FocusRequest; +using android::gui::TouchOcclusionMode; +using android::gui::WindowInfo; +using android::gui::WindowInfoHandle;  using android::os::BlockUntrustedTouchesMode;  using android::os::IInputConstants;  using android::os::InputEventInjectionResult; @@ -93,7 +98,8 @@ namespace android::inputdispatcher {  // coordinates and SurfaceFlinger includes the display rotation in the input window transforms.  static bool isPerWindowInputRotationEnabled() {      static const bool PER_WINDOW_INPUT_ROTATION = -            base::GetBoolProperty("persist.debug.per_window_input_rotation", false); +            sysprop::InputFlingerProperties::per_window_input_rotation().value_or(false); +      return PER_WINDOW_INPUT_ROTATION;  } @@ -290,7 +296,7 @@ static V getValueByKey(const std::unordered_map<K, V>& map, K key) {      return it != map.end() ? it->second : V{};  } -static bool haveSameToken(const sp<InputWindowHandle>& first, const sp<InputWindowHandle>& second) { +static bool haveSameToken(const sp<WindowInfoHandle>& first, const sp<WindowInfoHandle>& second) {      if (first == second) {          return true;      } @@ -302,7 +308,7 @@ static bool haveSameToken(const sp<InputWindowHandle>& first, const sp<InputWind      return first->getToken() == second->getToken();  } -static bool haveSameApplicationToken(const InputWindowInfo* first, const InputWindowInfo* second) { +static bool haveSameApplicationToken(const WindowInfo* first, const WindowInfo* second) {      if (first == nullptr || second == nullptr) {          return false;      } @@ -319,13 +325,14 @@ static std::unique_ptr<DispatchEntry> createDispatchEntry(const InputTarget& inp                                                            int32_t inputTargetFlags) {      if (eventEntry->type == EventEntry::Type::MOTION) {          const MotionEntry& motionEntry = static_cast<const MotionEntry&>(*eventEntry); -        if ((motionEntry.source & AINPUT_SOURCE_CLASS_POINTER) == 0) { +        if ((motionEntry.source & AINPUT_SOURCE_CLASS_JOYSTICK) || +            (motionEntry.source & AINPUT_SOURCE_CLASS_POSITION)) {              const ui::Transform identityTransform; -            // Use identity transform for events that are not pointer events because their axes -            // values do not represent on-screen coordinates, so they should not have any window -            // transformations applied to them. +            // Use identity transform for joystick and position-based (touchpad) events because they +            // don't depend on the window transform.              return std::make_unique<DispatchEntry>(eventEntry, inputTargetFlags, identityTransform,                                                     1.0f /*globalScaleFactor*/, +                                                   inputTarget.displayOrientation,                                                     inputTarget.displaySize);          }      } @@ -334,6 +341,7 @@ static std::unique_ptr<DispatchEntry> createDispatchEntry(const InputTarget& inp          const ui::Transform& transform = inputTarget.getDefaultPointerTransform();          return std::make_unique<DispatchEntry>(eventEntry, inputTargetFlags, transform,                                                 inputTarget.globalScaleFactor, +                                               inputTarget.displayOrientation,                                                 inputTarget.displaySize);      } @@ -386,6 +394,7 @@ static std::unique_ptr<DispatchEntry> createDispatchEntry(const InputTarget& inp      std::unique_ptr<DispatchEntry> dispatchEntry =              std::make_unique<DispatchEntry>(std::move(combinedMotionEntry), inputTargetFlags,                                              firstPointerTransform, inputTarget.globalScaleFactor, +                                            inputTarget.displayOrientation,                                              inputTarget.displaySize);      return dispatchEntry;  } @@ -551,6 +560,10 @@ InputDispatcher::~InputDispatcher() {      }  } +void InputDispatcher::onFirstRef() { +    SurfaceComposerClient::getDefault()->addWindowInfosListener(this); +} +  status_t InputDispatcher::start() {      if (mThread) {          return ALREADY_EXISTS; @@ -624,7 +637,7 @@ void InputDispatcher::processNoFocusedWindowAnrLocked() {          return; // The focused application has changed.      } -    const sp<InputWindowHandle>& focusedWindowHandle = +    const sp<WindowInfoHandle>& focusedWindowHandle =              getFocusedWindowHandleLocked(mAwaitedApplicationDisplayId);      if (focusedWindowHandle != nullptr) {          return; // We now have a focused window. No need for ANR. @@ -673,7 +686,7 @@ nsecs_t InputDispatcher::processAnrsLocked() {  }  std::chrono::nanoseconds InputDispatcher::getDispatchingTimeoutLocked(const sp<IBinder>& token) { -    sp<InputWindowHandle> window = getWindowHandleLocked(token); +    sp<WindowInfoHandle> window = getWindowHandleLocked(token);      if (window != nullptr) {          return window->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);      } @@ -885,7 +898,7 @@ bool InputDispatcher::shouldPruneInboundQueueLocked(const MotionEntry& motionEnt                  motionEntry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X));          int32_t y = static_cast<int32_t>(                  motionEntry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y)); -        sp<InputWindowHandle> touchedWindowHandle = +        sp<WindowInfoHandle> touchedWindowHandle =                  findTouchedWindowAtLocked(displayId, x, y, nullptr);          if (touchedWindowHandle != nullptr &&              touchedWindowHandle->getApplicationToken() != @@ -990,29 +1003,29 @@ void InputDispatcher::addRecentEventLocked(std::shared_ptr<EventEntry> entry) {      }  } -sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId, int32_t x, -                                                                 int32_t y, TouchState* touchState, -                                                                 bool addOutsideTargets, -                                                                 bool addPortalWindows, -                                                                 bool ignoreDragWindow) { +sp<WindowInfoHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId, int32_t x, +                                                                int32_t y, TouchState* touchState, +                                                                bool addOutsideTargets, +                                                                bool addPortalWindows, +                                                                bool ignoreDragWindow) {      if ((addPortalWindows || addOutsideTargets) && touchState == nullptr) {          LOG_ALWAYS_FATAL(                  "Must provide a valid touch state if adding portal windows or outside targets");      }      // Traverse windows from front to back to find touched window. -    const std::vector<sp<InputWindowHandle>>& windowHandles = getWindowHandlesLocked(displayId); -    for (const sp<InputWindowHandle>& windowHandle : windowHandles) { +    const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId); +    for (const sp<WindowInfoHandle>& windowHandle : windowHandles) {          if (ignoreDragWindow && haveSameToken(windowHandle, mDragState->dragWindow)) {              continue;          } -        const InputWindowInfo* windowInfo = windowHandle->getInfo(); +        const WindowInfo* windowInfo = windowHandle->getInfo();          if (windowInfo->displayId == displayId) {              auto flags = windowInfo->flags;              if (windowInfo->visible) { -                if (!flags.test(InputWindowInfo::Flag::NOT_TOUCHABLE)) { -                    bool isTouchModal = !flags.test(InputWindowInfo::Flag::NOT_FOCUSABLE) && -                            !flags.test(InputWindowInfo::Flag::NOT_TOUCH_MODAL); +                if (!flags.test(WindowInfo::Flag::NOT_TOUCHABLE)) { +                    bool isTouchModal = !flags.test(WindowInfo::Flag::NOT_FOCUSABLE) && +                            !flags.test(WindowInfo::Flag::NOT_TOUCH_MODAL);                      if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {                          int32_t portalToDisplayId = windowInfo->portalToDisplayId;                          if (portalToDisplayId != ADISPLAY_ID_NONE && @@ -1029,7 +1042,7 @@ sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t display                      }                  } -                if (addOutsideTargets && flags.test(InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH)) { +                if (addOutsideTargets && flags.test(WindowInfo::Flag::WATCH_OUTSIDE_TOUCH)) {                      touchState->addOrUpdateWindow(windowHandle,                                                    InputTarget::FLAG_DISPATCH_AS_OUTSIDE,                                                    BitSet32(0)); @@ -1041,13 +1054,13 @@ sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t display  }  std::vector<TouchedMonitor> InputDispatcher::findTouchedGestureMonitorsLocked( -        int32_t displayId, const std::vector<sp<InputWindowHandle>>& portalWindows) const { +        int32_t displayId, const std::vector<sp<WindowInfoHandle>>& portalWindows) const {      std::vector<TouchedMonitor> touchedMonitors;      std::vector<Monitor> monitors = getValueByKey(mGestureMonitorsByDisplay, displayId);      addGestureMonitors(monitors, touchedMonitors); -    for (const sp<InputWindowHandle>& portalWindow : portalWindows) { -        const InputWindowInfo* windowInfo = portalWindow->getInfo(); +    for (const sp<WindowInfoHandle>& portalWindow : portalWindows) { +        const WindowInfo* windowInfo = portalWindow->getInfo();          monitors = getValueByKey(mGestureMonitorsByDisplay, windowInfo->portalToDisplayId);          addGestureMonitors(monitors, touchedMonitors, -windowInfo->frameLeft,                             -windowInfo->frameTop); @@ -1596,7 +1609,7 @@ bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr<                  // The event has gone through these portal windows, so we add monitoring targets of                  // the corresponding displays as well.                  for (size_t i = 0; i < state.portalWindows.size(); i++) { -                    const InputWindowInfo* windowInfo = state.portalWindows[i]->getInfo(); +                    const WindowInfo* windowInfo = state.portalWindows[i]->getInfo();                      addGlobalMonitoringTargetsLocked(inputTargets, windowInfo->portalToDisplayId,                                                       -windowInfo->frameLeft, -windowInfo->frameTop);                  } @@ -1614,7 +1627,7 @@ bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr<      return true;  } -void InputDispatcher::enqueueDragEventLocked(const sp<InputWindowHandle>& windowHandle, +void InputDispatcher::enqueueDragEventLocked(const sp<WindowInfoHandle>& windowHandle,                                               bool isExiting, const MotionEntry& motionEntry) {      // If the window needs enqueue a drag event, the pointerCount should be 1 and the action should      // be AMOTION_EVENT_ACTION_MOVE, that could guarantee the first pointer is always valid. @@ -1794,7 +1807,7 @@ InputEventInjectionResult InputDispatcher::findFocusedWindowTargetsLocked(      std::string reason;      int32_t displayId = getTargetDisplayId(entry); -    sp<InputWindowHandle> focusedWindowHandle = getFocusedWindowHandleLocked(displayId); +    sp<WindowInfoHandle> focusedWindowHandle = getFocusedWindowHandleLocked(displayId);      std::shared_ptr<InputApplicationHandle> focusedApplicationHandle =              getValueByKey(mFocusedApplicationHandlesByDisplay, displayId); @@ -1921,8 +1934,8 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked(      // Update the touch state as needed based on the properties of the touch event.      InputEventInjectionResult injectionResult = InputEventInjectionResult::PENDING;      InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN; -    sp<InputWindowHandle> newHoverWindowHandle(mLastHoverWindowHandle); -    sp<InputWindowHandle> newTouchedWindowHandle; +    sp<WindowInfoHandle> newHoverWindowHandle(mLastHoverWindowHandle); +    sp<WindowInfoHandle> newTouchedWindowHandle;      // Copy current touch state into tempTouchState.      // This state will be used to update mTouchStatesByDisplay at the end of this function. @@ -2115,7 +2128,7 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked(              int32_t x = int32_t(entry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X));              int32_t y = int32_t(entry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y)); -            sp<InputWindowHandle> oldTouchedWindowHandle = +            sp<WindowInfoHandle> oldTouchedWindowHandle =                      tempTouchState.getFirstForegroundWindowHandle();              newTouchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y, &tempTouchState);              if (oldTouchedWindowHandle != newTouchedWindowHandle && @@ -2214,15 +2227,15 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked(      // Check whether windows listening for outside touches are owned by the same UID. If it is      // set the policy flag that we will not reveal coordinate information to this window.      if (maskedAction == AMOTION_EVENT_ACTION_DOWN) { -        sp<InputWindowHandle> foregroundWindowHandle = +        sp<WindowInfoHandle> foregroundWindowHandle =                  tempTouchState.getFirstForegroundWindowHandle();          if (foregroundWindowHandle) {              const int32_t foregroundWindowUid = foregroundWindowHandle->getInfo()->ownerUid;              for (const TouchedWindow& touchedWindow : tempTouchState.windows) {                  if (touchedWindow.targetFlags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) { -                    sp<InputWindowHandle> inputWindowHandle = touchedWindow.windowHandle; -                    if (inputWindowHandle->getInfo()->ownerUid != foregroundWindowUid) { -                        tempTouchState.addOrUpdateWindow(inputWindowHandle, +                    sp<WindowInfoHandle> windowInfoHandle = touchedWindow.windowHandle; +                    if (windowInfoHandle->getInfo()->ownerUid != foregroundWindowUid) { +                        tempTouchState.addOrUpdateWindow(windowInfoHandle,                                                           InputTarget::FLAG_ZERO_COORDS,                                                           BitSet32(0));                      } @@ -2238,15 +2251,15 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked(      // engine only supports touch events.  We would need to add a mechanism similar      // to View.onGenericMotionEvent to enable wallpapers to handle these events.      if (maskedAction == AMOTION_EVENT_ACTION_DOWN) { -        sp<InputWindowHandle> foregroundWindowHandle = +        sp<WindowInfoHandle> foregroundWindowHandle =                  tempTouchState.getFirstForegroundWindowHandle();          if (foregroundWindowHandle && foregroundWindowHandle->getInfo()->hasWallpaper) { -            const std::vector<sp<InputWindowHandle>>& windowHandles = +            const std::vector<sp<WindowInfoHandle>>& windowHandles =                      getWindowHandlesLocked(displayId); -            for (const sp<InputWindowHandle>& windowHandle : windowHandles) { -                const InputWindowInfo* info = windowHandle->getInfo(); +            for (const sp<WindowInfoHandle>& windowHandle : windowHandles) { +                const WindowInfo* info = windowHandle->getInfo();                  if (info->displayId == displayId && -                    windowHandle->getInfo()->type == InputWindowInfo::Type::WALLPAPER) { +                    windowHandle->getInfo()->type == WindowInfo::Type::WALLPAPER) {                      tempTouchState                              .addOrUpdateWindow(windowHandle,                                                 InputTarget::FLAG_WINDOW_IS_OBSCURED | @@ -2365,7 +2378,7 @@ Failed:  }  void InputDispatcher::finishDragAndDrop(int32_t displayId, float x, float y) { -    const sp<InputWindowHandle> dropWindow = +    const sp<WindowInfoHandle> dropWindow =              findTouchedWindowAtLocked(displayId, x, y, nullptr /*touchState*/,                                        false /*addOutsideTargets*/, false /*addPortalWindows*/,                                        true /*ignoreDragWindow*/); @@ -2400,7 +2413,7 @@ void InputDispatcher::addDragEventLocked(const MotionEntry& entry) {              return;          } -        const sp<InputWindowHandle> hoverWindowHandle = +        const sp<WindowInfoHandle> hoverWindowHandle =                  findTouchedWindowAtLocked(entry.displayId, x, y, nullptr /*touchState*/,                                            false /*addOutsideTargets*/, false /*addPortalWindows*/,                                            true /*ignoreDragWindow*/); @@ -2425,7 +2438,7 @@ void InputDispatcher::addDragEventLocked(const MotionEntry& entry) {      }  } -void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle, +void InputDispatcher::addWindowTargetLocked(const sp<WindowInfoHandle>& windowHandle,                                              int32_t targetFlags, BitSet32 pointerIds,                                              std::vector<InputTarget>& inputTargets) {      std::vector<InputTarget>::iterator it = @@ -2435,7 +2448,7 @@ void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowH                                       windowHandle->getToken();                           }); -    const InputWindowInfo* windowInfo = windowHandle->getInfo(); +    const WindowInfo* windowInfo = windowHandle->getInfo();      if (it == inputTargets.end()) {          InputTarget inputTarget; @@ -2448,6 +2461,7 @@ void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowH          inputTarget.inputChannel = inputChannel;          inputTarget.flags = targetFlags;          inputTarget.globalScaleFactor = windowInfo->globalScaleFactor; +        inputTarget.displayOrientation = windowInfo->displayOrientation;          inputTarget.displaySize =                  int2(windowHandle->getInfo()->displayWidth, windowHandle->getInfo()->displayHeight);          inputTargets.push_back(inputTarget); @@ -2486,7 +2500,7 @@ void InputDispatcher::addMonitoringTargetLocked(const Monitor& monitor, float xO      inputTargets.push_back(target);  } -bool InputDispatcher::checkInjectionPermission(const sp<InputWindowHandle>& windowHandle, +bool InputDispatcher::checkInjectionPermission(const sp<WindowInfoHandle>& windowHandle,                                                 const InjectionState* injectionState) {      if (injectionState &&          (windowHandle == nullptr || @@ -2511,8 +2525,8 @@ bool InputDispatcher::checkInjectionPermission(const sp<InputWindowHandle>& wind   * another window handle. We only check a few preconditions. Actually   * checking the bounds is left to the caller.   */ -static bool canBeObscuredBy(const sp<InputWindowHandle>& windowHandle, -                            const sp<InputWindowHandle>& otherHandle) { +static bool canBeObscuredBy(const sp<WindowInfoHandle>& windowHandle, +                            const sp<WindowInfoHandle>& otherHandle) {      // Compare by token so cloned layers aren't counted      if (haveSameToken(windowHandle, otherHandle)) {          return false; @@ -2521,8 +2535,7 @@ static bool canBeObscuredBy(const sp<InputWindowHandle>& windowHandle,      auto otherInfo = otherHandle->getInfo();      if (!otherInfo->visible) {          return false; -    } else if (otherInfo->alpha == 0 && -               otherInfo->flags.test(InputWindowInfo::Flag::NOT_TOUCHABLE)) { +    } else if (otherInfo->alpha == 0 && otherInfo->flags.test(WindowInfo::Flag::NOT_TOUCHABLE)) {          // Those act as if they were invisible, so we don't need to flag them.          // We do want to potentially flag touchable windows even if they have 0          // opacity, since they can consume touches and alter the effects of the @@ -2560,20 +2573,20 @@ static bool canBeObscuredBy(const sp<InputWindowHandle>& windowHandle,   * If neither of those is true, then it means the touch can be allowed.   */  InputDispatcher::TouchOcclusionInfo InputDispatcher::computeTouchOcclusionInfoLocked( -        const sp<InputWindowHandle>& windowHandle, int32_t x, int32_t y) const { -    const InputWindowInfo* windowInfo = windowHandle->getInfo(); +        const sp<WindowInfoHandle>& windowHandle, int32_t x, int32_t y) const { +    const WindowInfo* windowInfo = windowHandle->getInfo();      int32_t displayId = windowInfo->displayId; -    const std::vector<sp<InputWindowHandle>>& windowHandles = getWindowHandlesLocked(displayId); +    const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId);      TouchOcclusionInfo info;      info.hasBlockingOcclusion = false;      info.obscuringOpacity = 0;      info.obscuringUid = -1;      std::map<int32_t, float> opacityByUid; -    for (const sp<InputWindowHandle>& otherHandle : windowHandles) { +    for (const sp<WindowInfoHandle>& otherHandle : windowHandles) {          if (windowHandle == otherHandle) {              break; // All future windows are below us. Exit early.          } -        const InputWindowInfo* otherInfo = otherHandle->getInfo(); +        const WindowInfo* otherInfo = otherHandle->getInfo();          if (canBeObscuredBy(windowHandle, otherHandle) && otherInfo->frameContainsPoint(x, y) &&              !haveSameApplicationToken(windowInfo, otherInfo)) {              if (DEBUG_TOUCH_OCCLUSION) { @@ -2612,7 +2625,7 @@ InputDispatcher::TouchOcclusionInfo InputDispatcher::computeTouchOcclusionInfoLo      return info;  } -std::string InputDispatcher::dumpWindowForTouchOcclusion(const InputWindowInfo* info, +std::string InputDispatcher::dumpWindowForTouchOcclusion(const WindowInfo* info,                                                           bool isTouchedWindow) const {      return StringPrintf(INDENT2                          "* %stype=%s, package=%s/%" PRId32 ", id=%" PRId32 ", mode=%s, alpha=%.2f, " @@ -2646,15 +2659,15 @@ bool InputDispatcher::isTouchTrustedLocked(const TouchOcclusionInfo& occlusionIn      return true;  } -bool InputDispatcher::isWindowObscuredAtPointLocked(const sp<InputWindowHandle>& windowHandle, +bool InputDispatcher::isWindowObscuredAtPointLocked(const sp<WindowInfoHandle>& windowHandle,                                                      int32_t x, int32_t y) const {      int32_t displayId = windowHandle->getInfo()->displayId; -    const std::vector<sp<InputWindowHandle>>& windowHandles = getWindowHandlesLocked(displayId); -    for (const sp<InputWindowHandle>& otherHandle : windowHandles) { +    const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId); +    for (const sp<WindowInfoHandle>& otherHandle : windowHandles) {          if (windowHandle == otherHandle) {              break; // All future windows are below us. Exit early.          } -        const InputWindowInfo* otherInfo = otherHandle->getInfo(); +        const WindowInfo* otherInfo = otherHandle->getInfo();          if (canBeObscuredBy(windowHandle, otherHandle) &&              otherInfo->frameContainsPoint(x, y)) {              return true; @@ -2663,15 +2676,15 @@ bool InputDispatcher::isWindowObscuredAtPointLocked(const sp<InputWindowHandle>&      return false;  } -bool InputDispatcher::isWindowObscuredLocked(const sp<InputWindowHandle>& windowHandle) const { +bool InputDispatcher::isWindowObscuredLocked(const sp<WindowInfoHandle>& windowHandle) const {      int32_t displayId = windowHandle->getInfo()->displayId; -    const std::vector<sp<InputWindowHandle>>& windowHandles = getWindowHandlesLocked(displayId); -    const InputWindowInfo* windowInfo = windowHandle->getInfo(); -    for (const sp<InputWindowHandle>& otherHandle : windowHandles) { +    const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId); +    const WindowInfo* windowInfo = windowHandle->getInfo(); +    for (const sp<WindowInfoHandle>& otherHandle : windowHandles) {          if (windowHandle == otherHandle) {              break; // All future windows are below us. Exit early.          } -        const InputWindowInfo* otherInfo = otherHandle->getInfo(); +        const WindowInfo* otherInfo = otherHandle->getInfo();          if (canBeObscuredBy(windowHandle, otherHandle) &&              otherInfo->overlaps(windowInfo)) {              return true; @@ -2681,8 +2694,7 @@ bool InputDispatcher::isWindowObscuredLocked(const sp<InputWindowHandle>& window  }  std::string InputDispatcher::getApplicationWindowLabel( -        const InputApplicationHandle* applicationHandle, -        const sp<InputWindowHandle>& windowHandle) { +        const InputApplicationHandle* applicationHandle, const sp<WindowInfoHandle>& windowHandle) {      if (applicationHandle != nullptr) {          if (windowHandle != nullptr) {              return applicationHandle->getName() + " - " + windowHandle->getName(); @@ -2705,10 +2717,10 @@ void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) {          return;      }      int32_t displayId = getTargetDisplayId(eventEntry); -    sp<InputWindowHandle> focusedWindowHandle = getFocusedWindowHandleLocked(displayId); +    sp<WindowInfoHandle> focusedWindowHandle = getFocusedWindowHandleLocked(displayId);      if (focusedWindowHandle != nullptr) { -        const InputWindowInfo* info = focusedWindowHandle->getInfo(); -        if (info->inputFeatures.test(InputWindowInfo::Feature::DISABLE_USER_ACTIVITY)) { +        const WindowInfo* info = focusedWindowHandle->getInfo(); +        if (info->inputFeatures.test(WindowInfo::Feature::DISABLE_USER_ACTIVITY)) {  #if DEBUG_DISPATCH_CYCLE              ALOGD("Not poking user activity: disabled by window '%s'.", info->name.c_str());  #endif @@ -3163,6 +3175,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,                                                       motionEntry.xPrecision, motionEntry.yPrecision,                                                       motionEntry.xCursorPosition,                                                       motionEntry.yCursorPosition, +                                                     dispatchEntry->displayOrientation,                                                       dispatchEntry->displaySize.x,                                                       dispatchEntry->displaySize.y,                                                       motionEntry.downTime, motionEntry.eventTime, @@ -3479,10 +3492,10 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(  #endif      InputTarget target; -    sp<InputWindowHandle> windowHandle = +    sp<WindowInfoHandle> windowHandle =              getWindowHandleLocked(connection->inputChannel->getConnectionToken());      if (windowHandle != nullptr) { -        const InputWindowInfo* windowInfo = windowHandle->getInfo(); +        const WindowInfo* windowInfo = windowHandle->getInfo();          target.setDefaultPointerTransform(windowInfo->transform);          target.globalScaleFactor = windowInfo->globalScaleFactor;      } @@ -3546,10 +3559,10 @@ void InputDispatcher::synthesizePointerDownEventsForConnectionLocked(  #endif      InputTarget target; -    sp<InputWindowHandle> windowHandle = +    sp<WindowInfoHandle> windowHandle =              getWindowHandleLocked(connection->inputChannel->getConnectionToken());      if (windowHandle != nullptr) { -        const InputWindowInfo* windowInfo = windowHandle->getInfo(); +        const WindowInfo* windowInfo = windowHandle->getInfo();          target.setDefaultPointerTransform(windowInfo->transform);          target.globalScaleFactor = windowInfo->globalScaleFactor;      } @@ -3875,8 +3888,8 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {                               args->action, args->actionButton, args->flags, args->edgeFlags,                               args->metaState, args->buttonState, args->classification, transform,                               args->xPrecision, args->yPrecision, args->xCursorPosition, -                             args->yCursorPosition, AMOTION_EVENT_INVALID_DISPLAY_SIZE, -                             AMOTION_EVENT_INVALID_DISPLAY_SIZE, args->downTime, args->eventTime, +                             args->yCursorPosition, ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, +                             INVALID_DISPLAY_SIZE, args->downTime, args->eventTime,                               args->pointerCount, args->pointerProperties, args->pointerCoords);              policyFlags |= POLICY_FLAG_FILTERED; @@ -4320,22 +4333,22 @@ void InputDispatcher::decrementPendingForegroundDispatches(EventEntry& entry) {      }  } -const std::vector<sp<InputWindowHandle>>& InputDispatcher::getWindowHandlesLocked( +const std::vector<sp<WindowInfoHandle>>& InputDispatcher::getWindowHandlesLocked(          int32_t displayId) const { -    static const std::vector<sp<InputWindowHandle>> EMPTY_WINDOW_HANDLES; +    static const std::vector<sp<WindowInfoHandle>> EMPTY_WINDOW_HANDLES;      auto it = mWindowHandlesByDisplay.find(displayId);      return it != mWindowHandlesByDisplay.end() ? it->second : EMPTY_WINDOW_HANDLES;  } -sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked( +sp<WindowInfoHandle> InputDispatcher::getWindowHandleLocked(          const sp<IBinder>& windowHandleToken) const {      if (windowHandleToken == nullptr) {          return nullptr;      }      for (auto& it : mWindowHandlesByDisplay) { -        const std::vector<sp<InputWindowHandle>>& windowHandles = it.second; -        for (const sp<InputWindowHandle>& windowHandle : windowHandles) { +        const std::vector<sp<WindowInfoHandle>>& windowHandles = it.second; +        for (const sp<WindowInfoHandle>& windowHandle : windowHandles) {              if (windowHandle->getToken() == windowHandleToken) {                  return windowHandle;              } @@ -4344,13 +4357,13 @@ sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(      return nullptr;  } -sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(const sp<IBinder>& windowHandleToken, -                                                             int displayId) const { +sp<WindowInfoHandle> InputDispatcher::getWindowHandleLocked(const sp<IBinder>& windowHandleToken, +                                                            int displayId) const {      if (windowHandleToken == nullptr) {          return nullptr;      } -    for (const sp<InputWindowHandle>& windowHandle : getWindowHandlesLocked(displayId)) { +    for (const sp<WindowInfoHandle>& windowHandle : getWindowHandlesLocked(displayId)) {          if (windowHandle->getToken() == windowHandleToken) {              return windowHandle;          } @@ -4358,11 +4371,11 @@ sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(const sp<IBinder>&      return nullptr;  } -sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked( -        const sp<InputWindowHandle>& windowHandle) const { +sp<WindowInfoHandle> InputDispatcher::getWindowHandleLocked( +        const sp<WindowInfoHandle>& windowHandle) const {      for (auto& it : mWindowHandlesByDisplay) { -        const std::vector<sp<InputWindowHandle>>& windowHandles = it.second; -        for (const sp<InputWindowHandle>& handle : windowHandles) { +        const std::vector<sp<WindowInfoHandle>>& windowHandles = it.second; +        for (const sp<WindowInfoHandle>& handle : windowHandles) {              if (handle->getId() == windowHandle->getId() &&                  handle->getToken() == windowHandle->getToken()) {                  if (windowHandle->getInfo()->displayId != it.first) { @@ -4378,15 +4391,15 @@ sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(      return nullptr;  } -sp<InputWindowHandle> InputDispatcher::getFocusedWindowHandleLocked(int displayId) const { +sp<WindowInfoHandle> InputDispatcher::getFocusedWindowHandleLocked(int displayId) const {      sp<IBinder> focusedToken = mFocusResolver.getFocusedWindowToken(displayId);      return getWindowHandleLocked(focusedToken, displayId);  } -bool InputDispatcher::hasResponsiveConnectionLocked(InputWindowHandle& windowHandle) const { +bool InputDispatcher::hasResponsiveConnectionLocked(WindowInfoHandle& windowHandle) const {      sp<Connection> connection = getConnectionLocked(windowHandle.getToken());      const bool noInputChannel = -            windowHandle.getInfo()->inputFeatures.test(InputWindowInfo::Feature::NO_INPUT_CHANNEL); +            windowHandle.getInfo()->inputFeatures.test(WindowInfo::Feature::NO_INPUT_CHANNEL);      if (connection != nullptr && noInputChannel) {          ALOGW("%s has feature NO_INPUT_CHANNEL, but it matched to connection %s",                windowHandle.getName().c_str(), connection->inputChannel->getName().c_str()); @@ -4416,8 +4429,8 @@ std::shared_ptr<InputChannel> InputDispatcher::getInputChannelLocked(  }  void InputDispatcher::updateWindowHandlesForDisplayLocked( -        const std::vector<sp<InputWindowHandle>>& inputWindowHandles, int32_t displayId) { -    if (inputWindowHandles.empty()) { +        const std::vector<sp<WindowInfoHandle>>& windowInfoHandles, int32_t displayId) { +    if (windowInfoHandles.empty()) {          // Remove all handles on a display if there are no windows left.          mWindowHandlesByDisplay.erase(displayId);          return; @@ -4425,26 +4438,21 @@ void InputDispatcher::updateWindowHandlesForDisplayLocked(      // Since we compare the pointer of input window handles across window updates, we need      // to make sure the handle object for the same window stays unchanged across updates. -    const std::vector<sp<InputWindowHandle>>& oldHandles = getWindowHandlesLocked(displayId); -    std::unordered_map<int32_t /*id*/, sp<InputWindowHandle>> oldHandlesById; -    for (const sp<InputWindowHandle>& handle : oldHandles) { +    const std::vector<sp<WindowInfoHandle>>& oldHandles = getWindowHandlesLocked(displayId); +    std::unordered_map<int32_t /*id*/, sp<WindowInfoHandle>> oldHandlesById; +    for (const sp<WindowInfoHandle>& handle : oldHandles) {          oldHandlesById[handle->getId()] = handle;      } -    std::vector<sp<InputWindowHandle>> newHandles; -    for (const sp<InputWindowHandle>& handle : inputWindowHandles) { -        if (!handle->updateInfo()) { -            // handle no longer valid -            continue; -        } - -        const InputWindowInfo* info = handle->getInfo(); +    std::vector<sp<WindowInfoHandle>> newHandles; +    for (const sp<WindowInfoHandle>& handle : windowInfoHandles) { +        const WindowInfo* info = handle->getInfo();          if ((getInputChannelLocked(handle->getToken()) == nullptr &&               info->portalToDisplayId == ADISPLAY_ID_NONE)) {              const bool noInputChannel = -                    info->inputFeatures.test(InputWindowInfo::Feature::NO_INPUT_CHANNEL); -            const bool canReceiveInput = !info->flags.test(InputWindowInfo::Flag::NOT_TOUCHABLE) || -                    !info->flags.test(InputWindowInfo::Flag::NOT_FOCUSABLE); +                    info->inputFeatures.test(WindowInfo::Feature::NO_INPUT_CHANNEL); +            const bool canReceiveInput = !info->flags.test(WindowInfo::Flag::NOT_TOUCHABLE) || +                    !info->flags.test(WindowInfo::Flag::NOT_FOCUSABLE);              if (canReceiveInput && !noInputChannel) {                  ALOGV("Window handle %s has no registered input channel",                        handle->getName().c_str()); @@ -4460,7 +4468,7 @@ void InputDispatcher::updateWindowHandlesForDisplayLocked(          if ((oldHandlesById.find(handle->getId()) != oldHandlesById.end()) &&                  (oldHandlesById.at(handle->getId())->getToken() == handle->getToken())) { -            const sp<InputWindowHandle>& oldHandle = oldHandlesById.at(handle->getId()); +            const sp<WindowInfoHandle>& oldHandle = oldHandlesById.at(handle->getId());              oldHandle->updateFrom(handle);              newHandles.push_back(oldHandle);          } else { @@ -4473,7 +4481,7 @@ void InputDispatcher::updateWindowHandlesForDisplayLocked(  }  void InputDispatcher::setInputWindows( -        const std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>>& handlesPerDisplay) { +        const std::unordered_map<int32_t, std::vector<sp<WindowInfoHandle>>>& handlesPerDisplay) {      { // acquire lock          std::scoped_lock _l(mLock);          for (const auto& [displayId, handles] : handlesPerDisplay) { @@ -4492,19 +4500,19 @@ void InputDispatcher::setInputWindows(   * For removed handle, check if need to send a cancel event if already in touch.   */  void InputDispatcher::setInputWindowsLocked( -        const std::vector<sp<InputWindowHandle>>& inputWindowHandles, int32_t displayId) { +        const std::vector<sp<WindowInfoHandle>>& windowInfoHandles, int32_t displayId) {      if (DEBUG_FOCUS) {          std::string windowList; -        for (const sp<InputWindowHandle>& iwh : inputWindowHandles) { +        for (const sp<WindowInfoHandle>& iwh : windowInfoHandles) {              windowList += iwh->getName() + " ";          }          ALOGD("setInputWindows displayId=%" PRId32 " %s", displayId, windowList.c_str());      }      // Ensure all tokens are null if the window has feature NO_INPUT_CHANNEL -    for (const sp<InputWindowHandle>& window : inputWindowHandles) { +    for (const sp<WindowInfoHandle>& window : windowInfoHandles) {          const bool noInputWindow = -                window->getInfo()->inputFeatures.test(InputWindowInfo::Feature::NO_INPUT_CHANNEL); +                window->getInfo()->inputFeatures.test(WindowInfo::Feature::NO_INPUT_CHANNEL);          if (noInputWindow && window->getToken() != nullptr) {              ALOGE("%s has feature NO_INPUT_WINDOW, but a non-null token. Clearing",                    window->getName().c_str()); @@ -4513,18 +4521,18 @@ void InputDispatcher::setInputWindowsLocked(      }      // Copy old handles for release if they are no longer present. -    const std::vector<sp<InputWindowHandle>> oldWindowHandles = getWindowHandlesLocked(displayId); +    const std::vector<sp<WindowInfoHandle>> oldWindowHandles = getWindowHandlesLocked(displayId);      // Save the old windows' orientation by ID before it gets updated.      std::unordered_map<int32_t, uint32_t> oldWindowOrientations; -    for (const sp<InputWindowHandle>& handle : oldWindowHandles) { +    for (const sp<WindowInfoHandle>& handle : oldWindowHandles) {          oldWindowOrientations.emplace(handle->getId(),                                        handle->getInfo()->transform.getOrientation());      } -    updateWindowHandlesForDisplayLocked(inputWindowHandles, displayId); +    updateWindowHandlesForDisplayLocked(windowInfoHandles, displayId); -    const std::vector<sp<InputWindowHandle>>& windowHandles = getWindowHandlesLocked(displayId); +    const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId);      if (mLastHoverWindowHandle &&          std::find(windowHandles.begin(), windowHandles.end(), mLastHoverWindowHandle) ==                  windowHandles.end()) { @@ -4573,8 +4581,8 @@ void InputDispatcher::setInputWindowsLocked(      if (isPerWindowInputRotationEnabled()) {          // Determine if the orientation of any of the input windows have changed, and cancel all          // pointer events if necessary. -        for (const sp<InputWindowHandle>& oldWindowHandle : oldWindowHandles) { -            const sp<InputWindowHandle> newWindowHandle = getWindowHandleLocked(oldWindowHandle); +        for (const sp<WindowInfoHandle>& oldWindowHandle : oldWindowHandles) { +            const sp<WindowInfoHandle> newWindowHandle = getWindowHandleLocked(oldWindowHandle);              if (newWindowHandle != nullptr &&                  newWindowHandle->getInfo()->transform.getOrientation() !=                          oldWindowOrientations[oldWindowHandle->getId()]) { @@ -4593,7 +4601,7 @@ void InputDispatcher::setInputWindowsLocked(      // This ensures that unused input channels are released promptly.      // Otherwise, they might stick around until the window handle is destroyed      // which might not happen until the next GC. -    for (const sp<InputWindowHandle>& oldWindowHandle : oldWindowHandles) { +    for (const sp<WindowInfoHandle>& oldWindowHandle : oldWindowHandles) {          if (getWindowHandleLocked(oldWindowHandle) == nullptr) {              if (DEBUG_FOCUS) {                  ALOGD("Window went away: %s", oldWindowHandle->getName().c_str()); @@ -4603,7 +4611,7 @@ void InputDispatcher::setInputWindowsLocked(              // check for window flags when windows are going away.              // TODO(b/157929241) : delete this. This is only needed temporarily              // in order to gather some data about the flag usage -            if (oldWindowHandle->getInfo()->flags.test(InputWindowInfo::Flag::SLIPPERY)) { +            if (oldWindowHandle->getInfo()->flags.test(WindowInfo::Flag::SLIPPERY)) {                  ALOGW("%s has FLAG_SLIPPERY. Please report this in b/157929241",                        oldWindowHandle->getName().c_str());                  if (mCompatService != nullptr) { @@ -4793,8 +4801,8 @@ bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp<      { // acquire lock          std::scoped_lock _l(mLock); -        sp<InputWindowHandle> fromWindowHandle = getWindowHandleLocked(fromToken); -        sp<InputWindowHandle> toWindowHandle = getWindowHandleLocked(toToken); +        sp<WindowInfoHandle> fromWindowHandle = getWindowHandleLocked(fromToken); +        sp<WindowInfoHandle> toWindowHandle = getWindowHandleLocked(toToken);          if (fromWindowHandle == nullptr || toWindowHandle == nullptr) {              ALOGW("Cannot transfer focus because from or to window not found.");              return false; @@ -4872,7 +4880,7 @@ bool InputDispatcher::transferTouch(const sp<IBinder>& destChannelToken) {      { // acquire lock          std::scoped_lock _l(mLock); -        sp<InputWindowHandle> toWindowHandle = getWindowHandleLocked(destChannelToken); +        sp<WindowInfoHandle> toWindowHandle = getWindowHandleLocked(destChannelToken);          if (toWindowHandle == nullptr) {              ALOGW("Could not find window associated with token=%p", destChannelToken.get());              return false; @@ -4939,7 +4947,7 @@ std::string InputDispatcher::dumpPointerCaptureStateLocked() {      std::string windowName = "None";      if (mWindowTokenWithPointerCapture) { -        const sp<InputWindowHandle> captureWindowHandle = +        const sp<WindowInfoHandle> captureWindowHandle =                  getWindowHandleLocked(mWindowTokenWithPointerCapture);          windowName = captureWindowHandle ? captureWindowHandle->getName().c_str()                                           : "token has capture without window"; @@ -4995,7 +5003,7 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {              if (!state.portalWindows.empty()) {                  dump += INDENT3 "Portal windows:\n";                  for (size_t i = 0; i < state.portalWindows.size(); i++) { -                    const sp<InputWindowHandle> portalWindowHandle = state.portalWindows[i]; +                    const sp<WindowInfoHandle> portalWindowHandle = state.portalWindows[i];                      dump += StringPrintf(INDENT4 "%zu: name='%s'\n", i,                                           portalWindowHandle->getName().c_str());                  } @@ -5012,13 +5020,13 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {      if (!mWindowHandlesByDisplay.empty()) {          for (auto& it : mWindowHandlesByDisplay) { -            const std::vector<sp<InputWindowHandle>> windowHandles = it.second; +            const std::vector<sp<WindowInfoHandle>> windowHandles = it.second;              dump += StringPrintf(INDENT "Display: %" PRId32 "\n", it.first);              if (!windowHandles.empty()) {                  dump += INDENT2 "Windows:\n";                  for (size_t i = 0; i < windowHandles.size(); i++) { -                    const sp<InputWindowHandle>& windowHandle = windowHandles[i]; -                    const InputWindowInfo* windowInfo = windowHandle->getInfo(); +                    const sp<WindowInfoHandle>& windowHandle = windowHandles[i]; +                    const WindowInfo* windowInfo = windowHandle->getInfo();                      dump += StringPrintf(INDENT3 "%zu: name='%s', id=%" PRId32 ", displayId=%d, "                                                   "portalToDisplayId=%d, paused=%s, focusable=%s, " @@ -5399,7 +5407,7 @@ void InputDispatcher::requestPointerCapture(const sp<IBinder>& windowToken, bool      { // acquire lock          std::scoped_lock _l(mLock);          if (DEBUG_FOCUS) { -            const sp<InputWindowHandle> windowHandle = getWindowHandleLocked(windowToken); +            const sp<WindowInfoHandle> windowHandle = getWindowHandleLocked(windowToken);              ALOGI("Request to %s Pointer Capture from: %s.", enabled ? "enable" : "disable",                    windowHandle != nullptr ? windowHandle->getName().c_str()                                            : "token without window"); @@ -5570,7 +5578,7 @@ void InputDispatcher::onUntrustedTouchLocked(const std::string& obscuringPackage      postCommandLocked(std::move(commandEntry));  } -void InputDispatcher::updateLastAnrStateLocked(const sp<InputWindowHandle>& window, +void InputDispatcher::updateLastAnrStateLocked(const sp<WindowInfoHandle>& window,                                                 const std::string& reason) {      const std::string windowLabel = getApplicationWindowLabel(nullptr, window);      updateLastAnrStateLocked(windowLabel, reason); @@ -6237,4 +6245,16 @@ void InputDispatcher::displayRemoved(int32_t displayId) {      mLooper->wake();  } +void InputDispatcher::onWindowInfosChanged(const std::vector<gui::WindowInfo>& windowInfos) { +    // The listener sends the windows as a flattened array. Separate the windows by display for +    // more convenient parsing. +    std::unordered_map<int32_t, std::vector<sp<WindowInfoHandle>>> handlesPerDisplay; + +    for (const auto& info : windowInfos) { +        handlesPerDisplay.emplace(info.displayId, std::vector<sp<WindowInfoHandle>>()); +        handlesPerDisplay[info.displayId].push_back(new WindowInfoHandle(info)); +    } +    setInputWindows(handlesPerDisplay); +} +  } // namespace android::inputdispatcher diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index 9edf41c9c0..2436e73367 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -37,10 +37,10 @@  #include <attestation/HmacKeyManager.h>  #include <com/android/internal/compat/IPlatformCompatNative.h> +#include <gui/InputApplication.h> +#include <gui/WindowInfo.h>  #include <input/Input.h> -#include <input/InputApplication.h>  #include <input/InputTransport.h> -#include <input/InputWindow.h>  #include <limits.h>  #include <stddef.h>  #include <ui/Region.h> @@ -58,6 +58,7 @@  #include <InputListener.h>  #include <InputReporterInterface.h> +#include <gui/WindowInfosListener.h>  namespace android::inputdispatcher { @@ -80,7 +81,7 @@ class Connection;   *   *     A 'LockedInterruptible' method may called a 'Locked' method, but NOT vice-versa.   */ -class InputDispatcher : public android::InputDispatcherInterface { +class InputDispatcher : public android::InputDispatcherInterface, public gui::WindowInfosListener {  protected:      ~InputDispatcher() override; @@ -109,8 +110,9 @@ public:      std::unique_ptr<VerifiedInputEvent> verifyInputEvent(const InputEvent& event) override; -    void setInputWindows(const std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>>& -                                 handlesPerDisplay) override; +    void setInputWindows( +            const std::unordered_map<int32_t, std::vector<sp<android::gui::WindowInfoHandle>>>& +                    handlesPerDisplay) override;      void setFocusedApplication(              int32_t displayId,              const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) override; @@ -127,7 +129,7 @@ public:      base::Result<std::unique_ptr<InputChannel>> createInputChannel(              const std::string& name) override; -    void setFocusedWindow(const FocusRequest&) override; +    void setFocusedWindow(const android::gui::FocusRequest&) override;      base::Result<std::unique_ptr<InputChannel>> createInputMonitor(int32_t displayId,                                                                     bool isGestureMonitor,                                                                     const std::string& name, @@ -141,6 +143,8 @@ public:      void displayRemoved(int32_t displayId) override; +    void onWindowInfosChanged(const std::vector<gui::WindowInfo>& windowInfos) override; +  private:      enum class DropReason {          NOT_DROPPED, @@ -190,8 +194,8 @@ private:      void enqueueFocusEventLocked(const sp<IBinder>& windowToken, bool hasFocus,                                   const std::string& reason) REQUIRES(mLock);      // Enqueues a drag event. -    void enqueueDragEventLocked(const sp<InputWindowHandle>& windowToken, bool isExiting, -                                const MotionEntry& motionEntry) REQUIRES(mLock); +    void enqueueDragEventLocked(const sp<android::gui::WindowInfoHandle>& windowToken, +                                bool isExiting, const MotionEntry& motionEntry) REQUIRES(mLock);      // Adds an event to a queue of recent events for debugging purposes.      void addRecentEventLocked(std::shared_ptr<EventEntry> entry) REQUIRES(mLock); @@ -208,11 +212,12 @@ private:      // to transfer focus to a new application.      std::shared_ptr<EventEntry> mNextUnblockedEvent GUARDED_BY(mLock); -    sp<InputWindowHandle> findTouchedWindowAtLocked(int32_t displayId, int32_t x, int32_t y, -                                                    TouchState* touchState, -                                                    bool addOutsideTargets = false, -                                                    bool addPortalWindows = false, -                                                    bool ignoreDragWindow = false) REQUIRES(mLock); +    sp<android::gui::WindowInfoHandle> findTouchedWindowAtLocked(int32_t displayId, int32_t x, +                                                                 int32_t y, TouchState* touchState, +                                                                 bool addOutsideTargets = false, +                                                                 bool addPortalWindows = false, +                                                                 bool ignoreDragWindow = false) +            REQUIRES(mLock);      sp<Connection> getConnectionLocked(const sp<IBinder>& inputConnectionToken) const              REQUIRES(mLock); @@ -314,33 +319,36 @@ private:      float mMaximumObscuringOpacityForTouch GUARDED_BY(mLock);      android::os::BlockUntrustedTouchesMode mBlockUntrustedTouchesMode GUARDED_BY(mLock); -    std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>> mWindowHandlesByDisplay -            GUARDED_BY(mLock); -    void setInputWindowsLocked(const std::vector<sp<InputWindowHandle>>& inputWindowHandles, -                               int32_t displayId) REQUIRES(mLock); +    std::unordered_map<int32_t, std::vector<sp<android::gui::WindowInfoHandle>>> +            mWindowHandlesByDisplay GUARDED_BY(mLock); +    void setInputWindowsLocked( +            const std::vector<sp<android::gui::WindowInfoHandle>>& inputWindowHandles, +            int32_t displayId) REQUIRES(mLock);      // Get a reference to window handles by display, return an empty vector if not found. -    const std::vector<sp<InputWindowHandle>>& getWindowHandlesLocked(int32_t displayId) const -            REQUIRES(mLock); -    sp<InputWindowHandle> getWindowHandleLocked(const sp<IBinder>& windowHandleToken) const -            REQUIRES(mLock); +    const std::vector<sp<android::gui::WindowInfoHandle>>& getWindowHandlesLocked( +            int32_t displayId) const REQUIRES(mLock); +    sp<android::gui::WindowInfoHandle> getWindowHandleLocked( +            const sp<IBinder>& windowHandleToken) const REQUIRES(mLock);      // Same function as above, but faster. Since displayId is provided, this avoids the need      // to loop through all displays. -    sp<InputWindowHandle> getWindowHandleLocked(const sp<IBinder>& windowHandleToken, -                                                int displayId) const REQUIRES(mLock); -    sp<InputWindowHandle> getWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const -            REQUIRES(mLock); +    sp<android::gui::WindowInfoHandle> getWindowHandleLocked(const sp<IBinder>& windowHandleToken, +                                                             int displayId) const REQUIRES(mLock); +    sp<android::gui::WindowInfoHandle> getWindowHandleLocked( +            const sp<android::gui::WindowInfoHandle>& windowHandle) const REQUIRES(mLock);      std::shared_ptr<InputChannel> getInputChannelLocked(const sp<IBinder>& windowToken) const              REQUIRES(mLock); -    sp<InputWindowHandle> getFocusedWindowHandleLocked(int displayId) const REQUIRES(mLock); -    bool hasResponsiveConnectionLocked(InputWindowHandle& windowHandle) const REQUIRES(mLock); +    sp<android::gui::WindowInfoHandle> getFocusedWindowHandleLocked(int displayId) const +            REQUIRES(mLock); +    bool hasResponsiveConnectionLocked(android::gui::WindowInfoHandle& windowHandle) const +            REQUIRES(mLock);      /*       * Validate and update InputWindowHandles for a given display.       */      void updateWindowHandlesForDisplayLocked( -            const std::vector<sp<InputWindowHandle>>& inputWindowHandles, int32_t displayId) -            REQUIRES(mLock); +            const std::vector<sp<android::gui::WindowInfoHandle>>& inputWindowHandles, +            int32_t displayId) REQUIRES(mLock);      std::unordered_map<int32_t, TouchState> mTouchStatesByDisplay GUARDED_BY(mLock);      std::unique_ptr<DragState> mDragState GUARDED_BY(mLock); @@ -471,7 +479,7 @@ private:      AnrTracker mAnrTracker GUARDED_BY(mLock);      // Contains the last window which received a hover event. -    sp<InputWindowHandle> mLastHoverWindowHandle GUARDED_BY(mLock); +    sp<android::gui::WindowInfoHandle> mLastHoverWindowHandle GUARDED_BY(mLock);      void cancelEventsForAnrLocked(const sp<Connection>& connection) REQUIRES(mLock);      nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime) REQUIRES(mLock); @@ -490,20 +498,21 @@ private:              nsecs_t currentTime, const MotionEntry& entry, std::vector<InputTarget>& inputTargets,              nsecs_t* nextWakeupTime, bool* outConflictingPointerActions) REQUIRES(mLock);      std::vector<TouchedMonitor> findTouchedGestureMonitorsLocked( -            int32_t displayId, const std::vector<sp<InputWindowHandle>>& portalWindows) const +            int32_t displayId, +            const std::vector<sp<android::gui::WindowInfoHandle>>& portalWindows) const              REQUIRES(mLock);      std::vector<TouchedMonitor> selectResponsiveMonitorsLocked(              const std::vector<TouchedMonitor>& gestureMonitors) const REQUIRES(mLock); -    void addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle, int32_t targetFlags, -                               BitSet32 pointerIds, std::vector<InputTarget>& inputTargets) -            REQUIRES(mLock); +    void addWindowTargetLocked(const sp<android::gui::WindowInfoHandle>& windowHandle, +                               int32_t targetFlags, BitSet32 pointerIds, +                               std::vector<InputTarget>& inputTargets) REQUIRES(mLock);      void addMonitoringTargetLocked(const Monitor& monitor, float xOffset, float yOffset,                                     std::vector<InputTarget>& inputTargets) REQUIRES(mLock);      void addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets, int32_t displayId,                                            float xOffset = 0, float yOffset = 0) REQUIRES(mLock);      void pokeUserActivityLocked(const EventEntry& eventEntry) REQUIRES(mLock); -    bool checkInjectionPermission(const sp<InputWindowHandle>& windowHandle, +    bool checkInjectionPermission(const sp<android::gui::WindowInfoHandle>& windowHandle,                                    const InjectionState* injectionState);      // Enqueue a drag event if needed, and update the touch state.      // Uses findTouchedWindowTargetsLocked to make the decision @@ -518,15 +527,18 @@ private:          std::vector<std::string> debugInfo;      }; -    TouchOcclusionInfo computeTouchOcclusionInfoLocked(const sp<InputWindowHandle>& windowHandle, -                                                       int32_t x, int32_t y) const REQUIRES(mLock); +    TouchOcclusionInfo computeTouchOcclusionInfoLocked( +            const sp<android::gui::WindowInfoHandle>& windowHandle, int32_t x, int32_t y) const +            REQUIRES(mLock);      bool isTouchTrustedLocked(const TouchOcclusionInfo& occlusionInfo) const REQUIRES(mLock); -    bool isWindowObscuredAtPointLocked(const sp<InputWindowHandle>& windowHandle, int32_t x, -                                       int32_t y) const REQUIRES(mLock); -    bool isWindowObscuredLocked(const sp<InputWindowHandle>& windowHandle) const REQUIRES(mLock); -    std::string dumpWindowForTouchOcclusion(const InputWindowInfo* info, bool isTouchWindow) const; +    bool isWindowObscuredAtPointLocked(const sp<android::gui::WindowInfoHandle>& windowHandle, +                                       int32_t x, int32_t y) const REQUIRES(mLock); +    bool isWindowObscuredLocked(const sp<android::gui::WindowInfoHandle>& windowHandle) const +            REQUIRES(mLock); +    std::string dumpWindowForTouchOcclusion(const android::gui::WindowInfo* info, +                                            bool isTouchWindow) const;      std::string getApplicationWindowLabel(const InputApplicationHandle* applicationHandle, -                                          const sp<InputWindowHandle>& windowHandle); +                                          const sp<android::gui::WindowInfoHandle>& windowHandle);      // Manage the dispatch cycle for a single connection.      // These methods are deliberately not Interruptible because doing all of the work @@ -605,8 +617,8 @@ private:      void onAnrLocked(const sp<Connection>& connection) REQUIRES(mLock);      void onAnrLocked(std::shared_ptr<InputApplicationHandle> application) REQUIRES(mLock);      void onUntrustedTouchLocked(const std::string& obscuringPackage) REQUIRES(mLock); -    void updateLastAnrStateLocked(const sp<InputWindowHandle>& window, const std::string& reason) -            REQUIRES(mLock); +    void updateLastAnrStateLocked(const sp<android::gui::WindowInfoHandle>& window, +                                  const std::string& reason) REQUIRES(mLock);      void updateLastAnrStateLocked(const InputApplicationHandle& application,                                    const std::string& reason) REQUIRES(mLock);      void updateLastAnrStateLocked(const std::string& windowLabel, const std::string& reason) @@ -650,6 +662,8 @@ private:      sp<InputReporterInterface> mReporter;      sp<com::android::internal::compat::IPlatformCompatNative> mCompatService; + +    void onFirstRef() override;  };  } // namespace android::inputdispatcher diff --git a/services/inputflinger/dispatcher/InputTarget.h b/services/inputflinger/dispatcher/InputTarget.h index 1c4980b302..7c463c8697 100644 --- a/services/inputflinger/dispatcher/InputTarget.h +++ b/services/inputflinger/dispatcher/InputTarget.h @@ -17,6 +17,7 @@  #ifndef _UI_INPUT_INPUTDISPATCHER_INPUTTARGET_H  #define _UI_INPUT_INPUTDISPATCHER_INPUTTARGET_H +#include <gui/constants.h>  #include <input/InputTransport.h>  #include <ui/Transform.h>  #include <utils/BitSet.h> @@ -100,8 +101,11 @@ struct InputTarget {      // (ignored for KeyEvents)      float globalScaleFactor = 1.0f; +    // Current display orientation +    uint32_t displayOrientation = ui::Transform::ROT_0; +      // Display-size in its natural rotation. Used for compatibility transform of raw coordinates. -    int2 displaySize = {AMOTION_EVENT_INVALID_DISPLAY_SIZE, AMOTION_EVENT_INVALID_DISPLAY_SIZE}; +    int2 displaySize = {INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE};      // The subset of pointer ids to include in motion events dispatched to this input target      // if FLAG_SPLIT is set. diff --git a/services/inputflinger/dispatcher/TouchState.cpp b/services/inputflinger/dispatcher/TouchState.cpp index 81b3cf025b..20b6eadf5b 100644 --- a/services/inputflinger/dispatcher/TouchState.cpp +++ b/services/inputflinger/dispatcher/TouchState.cpp @@ -14,13 +14,14 @@   * limitations under the License.   */ -#include <input/InputWindow.h> +#include <gui/WindowInfo.h>  #include "InputTarget.h"  #include "TouchState.h" -using android::InputWindowHandle; +using android::gui::WindowInfo; +using android::gui::WindowInfoHandle;  namespace android::inputdispatcher { @@ -51,7 +52,7 @@ void TouchState::copyFrom(const TouchState& other) {      gestureMonitors = other.gestureMonitors;  } -void TouchState::addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle, int32_t targetFlags, +void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle, int32_t targetFlags,                                     BitSet32 pointerIds) {      if (targetFlags & InputTarget::FLAG_SPLIT) {          split = true; @@ -76,7 +77,7 @@ void TouchState::addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle, in      windows.push_back(touchedWindow);  } -void TouchState::addPortalWindow(const sp<InputWindowHandle>& windowHandle) { +void TouchState::addPortalWindow(const sp<android::gui::WindowInfoHandle>& windowHandle) {      size_t numWindows = portalWindows.size();      for (size_t i = 0; i < numWindows; i++) {          if (portalWindows[i] == windowHandle) { @@ -121,7 +122,7 @@ void TouchState::filterNonMonitors() {      portalWindows.clear();  } -sp<InputWindowHandle> TouchState::getFirstForegroundWindowHandle() const { +sp<WindowInfoHandle> TouchState::getFirstForegroundWindowHandle() const {      for (size_t i = 0; i < windows.size(); i++) {          const TouchedWindow& window = windows[i];          if (window.targetFlags & InputTarget::FLAG_FOREGROUND) { @@ -137,7 +138,7 @@ bool TouchState::isSlippery() const {      for (const TouchedWindow& window : windows) {          if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {              if (haveSlipperyForegroundWindow || -                !window.windowHandle->getInfo()->flags.test(InputWindowInfo::Flag::SLIPPERY)) { +                !window.windowHandle->getInfo()->flags.test(WindowInfo::Flag::SLIPPERY)) {                  return false;              }              haveSlipperyForegroundWindow = true; diff --git a/services/inputflinger/dispatcher/TouchState.h b/services/inputflinger/dispatcher/TouchState.h index 623c6a824f..a4e52b0d83 100644 --- a/services/inputflinger/dispatcher/TouchState.h +++ b/services/inputflinger/dispatcher/TouchState.h @@ -22,7 +22,9 @@  namespace android { -class InputWindowHandle; +namespace gui { +class WindowInfoHandle; +}  namespace inputdispatcher { @@ -37,7 +39,7 @@ struct TouchState {      // This collects the portal windows that the touch has gone through. Each portal window      // targets a display (embedded display for most cases). With this info, we can add the      // monitoring channels of the displays touched. -    std::vector<sp<android::InputWindowHandle>> portalWindows; +    std::vector<sp<android::gui::WindowInfoHandle>> portalWindows;      std::vector<TouchedMonitor> gestureMonitors; @@ -45,14 +47,14 @@ struct TouchState {      ~TouchState();      void reset();      void copyFrom(const TouchState& other); -    void addOrUpdateWindow(const sp<android::InputWindowHandle>& windowHandle, int32_t targetFlags, -                           BitSet32 pointerIds); -    void addPortalWindow(const sp<android::InputWindowHandle>& windowHandle); +    void addOrUpdateWindow(const sp<android::gui::WindowInfoHandle>& windowHandle, +                           int32_t targetFlags, BitSet32 pointerIds); +    void addPortalWindow(const sp<android::gui::WindowInfoHandle>& windowHandle);      void addGestureMonitors(const std::vector<TouchedMonitor>& monitors);      void removeWindowByToken(const sp<IBinder>& token);      void filterNonAsIsTouchWindows();      void filterNonMonitors(); -    sp<InputWindowHandle> getFirstForegroundWindowHandle() const; +    sp<android::gui::WindowInfoHandle> getFirstForegroundWindowHandle() const;      bool isSlippery() const;  }; diff --git a/services/inputflinger/dispatcher/TouchedWindow.h b/services/inputflinger/dispatcher/TouchedWindow.h index 8713aa3f56..4c31ec3acd 100644 --- a/services/inputflinger/dispatcher/TouchedWindow.h +++ b/services/inputflinger/dispatcher/TouchedWindow.h @@ -19,13 +19,15 @@  namespace android { -class InputWindowHandle; +namespace gui { +class WindowInfoHandle; +}  namespace inputdispatcher {  // Focus tracking for touch.  struct TouchedWindow { -    sp<android::InputWindowHandle> windowHandle; +    sp<gui::WindowInfoHandle> windowHandle;      int32_t targetFlags;      BitSet32 pointerIds; // zero unless target flag FLAG_SPLIT is set  }; diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h index 43428a0130..80db035ac4 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h @@ -19,18 +19,17 @@  #include <InputListener.h>  #include <android-base/result.h> -#include <android/FocusRequest.h> +#include <android/gui/FocusRequest.h>  #include <android/os/BlockUntrustedTouchesMode.h>  #include <android/os/ISetInputWindowsListener.h>  #include <android/os/InputEventInjectionResult.h>  #include <android/os/InputEventInjectionSync.h> -#include <input/InputApplication.h> +#include <gui/InputApplication.h> +#include <gui/WindowInfo.h>  #include <input/InputDevice.h>  #include <input/InputTransport.h> -#include <input/InputWindow.h>  #include <unordered_map> -  namespace android {  /* Notifies the system about input events generated by the input reader. @@ -91,7 +90,7 @@ public:       * This method may be called on any thread (usually by the input manager).       */      virtual void setInputWindows( -            const std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>>& +            const std::unordered_map<int32_t, std::vector<sp<gui::WindowInfoHandle>>>&                      handlesPerDisplay) = 0;      /* Sets the focused application on the given display. @@ -162,7 +161,7 @@ public:      /**       * Sets focus on the specified window.       */ -    virtual void setFocusedWindow(const FocusRequest&) = 0; +    virtual void setFocusedWindow(const gui::FocusRequest&) = 0;      /**       * Creates an input channel that may be used as targets for input events. diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h index 219f45a7c3..ebfcbe17b2 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h @@ -20,8 +20,8 @@  #include "InputDispatcherConfiguration.h"  #include <binder/IBinder.h> +#include <gui/InputApplication.h>  #include <input/Input.h> -#include <input/InputApplication.h>  #include <utils/RefBase.h>  namespace android { diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h index 8112038b16..c05ff39630 100644 --- a/services/inputflinger/host/InputFlinger.h +++ b/services/inputflinger/host/InputFlinger.h @@ -30,6 +30,8 @@  #include <utils/String8.h>  #include <utils/StrongPointer.h> +using android::gui::FocusRequest; +using android::gui::WindowInfo;  using android::os::BnInputFlinger;  using android::os::ISetInputWindowsListener; @@ -44,7 +46,7 @@ public:      InputFlinger() ANDROID_API;      status_t dump(int fd, const Vector<String16>& args) override; -    binder::Status setInputWindows(const std::vector<InputWindowInfo>&, +    binder::Status setInputWindows(const std::vector<WindowInfo>&,                                     const sp<ISetInputWindowsListener>&) override {          return binder::Status::ok();      } diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp index 7db32e3071..ee7b392bcd 100644 --- a/services/inputflinger/reader/Android.bp +++ b/services/inputflinger/reader/Android.bp @@ -71,6 +71,7 @@ cc_defaults {          "libstatslog",          "libui",          "libutils", +        "InputFlingerProperties",      ],      static_libs: [          "libc++fs", diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp index 7af014cb34..1e9ec54d5d 100644 --- a/services/inputflinger/reader/InputDevice.cpp +++ b/services/inputflinger/reader/InputDevice.cpp @@ -18,7 +18,7 @@  #include "InputDevice.h" -#include <input/Flags.h> +#include <ftl/Flags.h>  #include <algorithm>  #include "CursorInputMapper.h" diff --git a/services/inputflinger/reader/controller/PeripheralController.cpp b/services/inputflinger/reader/controller/PeripheralController.cpp index 16251ee0ca..9c8a29a059 100644 --- a/services/inputflinger/reader/controller/PeripheralController.cpp +++ b/services/inputflinger/reader/controller/PeripheralController.cpp @@ -19,8 +19,8 @@  #include "../Macros.h" +#include <ftl/NamedEnum.h>  #include "PeripheralController.h" -#include "input/NamedEnum.h"  // Log detailed debug messages about input device lights.  static constexpr bool DEBUG_LIGHT_DETAILS = false; diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h index d88b1bd704..3c3f88e36e 100644 --- a/services/inputflinger/reader/include/EventHub.h +++ b/services/inputflinger/reader/include/EventHub.h @@ -22,7 +22,7 @@  #include <unordered_map>  #include <vector> -#include <input/Flags.h> +#include <ftl/Flags.h>  #include <filesystem>  #include <batteryservice/BatteryService.h> diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h index 2f2eba78b1..f32472d37b 100644 --- a/services/inputflinger/reader/include/InputDevice.h +++ b/services/inputflinger/reader/include/InputDevice.h @@ -17,8 +17,8 @@  #ifndef _UI_INPUTREADER_INPUT_DEVICE_H  #define _UI_INPUTREADER_INPUT_DEVICE_H +#include <ftl/Flags.h>  #include <input/DisplayViewport.h> -#include <input/Flags.h>  #include <input/InputDevice.h>  #include <input/PropertyMap.h>  #include <stdint.h> diff --git a/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h b/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h index da0fea4616..4c5ff63f02 100644 --- a/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h +++ b/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h @@ -17,7 +17,7 @@  #ifndef _UI_INPUTREADER_TOUCH_CURSOR_INPUT_MAPPER_COMMON_H  #define _UI_INPUTREADER_TOUCH_CURSOR_INPUT_MAPPER_COMMON_H -#include <android-base/properties.h> +#include <InputFlingerProperties.sysprop.h>  #include <input/DisplayViewport.h>  #include <stdint.h> @@ -34,7 +34,7 @@ namespace android {  // un-rotated coordinate space.  static bool isPerWindowInputRotationEnabled() {      static const bool PER_WINDOW_INPUT_ROTATION = -            base::GetBoolProperty("persist.debug.per_window_input_rotation", false); +            sysprop::InputFlingerProperties::per_window_input_rotation().value_or(false);      return PER_WINDOW_INPUT_ROTATION;  } diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp index 962d8d2935..af028446b9 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp @@ -18,7 +18,7 @@  #include "../Macros.h"  // clang-format on -#include <input/NamedEnum.h> +#include <ftl/NamedEnum.h>  #include "TouchInputMapper.h"  #include "CursorButtonAccumulator.h" diff --git a/services/inputflinger/sysprop/Android.bp b/services/inputflinger/sysprop/Android.bp new file mode 100644 index 0000000000..b9d65ee246 --- /dev/null +++ b/services/inputflinger/sysprop/Android.bp @@ -0,0 +1,15 @@ +package { +    // See: http://go/android-license-faq +    // A large-scale-change added 'default_applicable_licenses' to import +    // all of the 'license_kinds' from "frameworks_native_license" +    // to get the below license kinds: +    //   SPDX-license-identifier-Apache-2.0 +    default_applicable_licenses: ["frameworks_native_license"], +} + +sysprop_library { +    name: "InputFlingerProperties", +    srcs: ["*.sysprop"], +    api_packages: ["android.sysprop"], +    property_owner: "Platform", +} diff --git a/services/inputflinger/sysprop/InputFlingerProperties.sysprop b/services/inputflinger/sysprop/InputFlingerProperties.sysprop new file mode 100644 index 0000000000..1c7e724332 --- /dev/null +++ b/services/inputflinger/sysprop/InputFlingerProperties.sysprop @@ -0,0 +1,27 @@ +# Copyright (C) 2021 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the License); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +#      http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +module: "android.sysprop.InputFlingerProperties" +owner: Platform + +# When per-window-input-rotation is enabled, InputReader works in the un-rotated +# display coordinate space, and the display rotation is encoded as part of the +# input window transform that is sent from SurfaceFlinger to InputDispatcher. +prop { +    api_name: "per_window_input_rotation" +    type: Boolean +    scope: Internal +    access: ReadWrite +    prop_name: "persist.debug.per_window_input_rotation" +} diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp index 918e1bef7a..e68692474d 100644 --- a/services/inputflinger/tests/Android.bp +++ b/services/inputflinger/tests/Android.bp @@ -52,6 +52,7 @@ cc_test {      ],      aidl: {          include_dirs: [ +            "frameworks/native/libs/gui",              "frameworks/native/libs/input",          ],      }, diff --git a/services/inputflinger/tests/FocusResolver_test.cpp b/services/inputflinger/tests/FocusResolver_test.cpp index 9051ff12c2..662be8063e 100644 --- a/services/inputflinger/tests/FocusResolver_test.cpp +++ b/services/inputflinger/tests/FocusResolver_test.cpp @@ -26,9 +26,12 @@  // atest inputflinger_tests:FocusResolverTest +using android::gui::FocusRequest; +using android::gui::WindowInfoHandle; +  namespace android::inputdispatcher { -class FakeWindowHandle : public InputWindowHandle { +class FakeWindowHandle : public WindowInfoHandle {  public:      FakeWindowHandle(const std::string& name, const sp<IBinder>& token, bool focusable,                       bool visible) { @@ -38,7 +41,6 @@ public:          mInfo.focusable = focusable;      } -    bool updateInfo() { return true; }      void setFocusable(bool focusable) { mInfo.focusable = focusable; }      void setVisible(bool visible) { mInfo.visible = visible; }  }; @@ -47,7 +49,7 @@ TEST(FocusResolverTest, SetFocusedWindow) {      sp<IBinder> focusableWindowToken = new BBinder();      sp<IBinder> invisibleWindowToken = new BBinder();      sp<IBinder> unfocusableWindowToken = new BBinder(); -    std::vector<sp<InputWindowHandle>> windows; +    std::vector<sp<WindowInfoHandle>> windows;      windows.push_back(new FakeWindowHandle("Focusable", focusableWindowToken, true /* focusable */,                                             true /* visible */));      windows.push_back(new FakeWindowHandle("Invisible", invisibleWindowToken, true /* focusable */, @@ -82,7 +84,7 @@ TEST(FocusResolverTest, SetFocusedMirroredWindow) {      sp<IBinder> focusableWindowToken = new BBinder();      sp<IBinder> invisibleWindowToken = new BBinder();      sp<IBinder> unfocusableWindowToken = new BBinder(); -    std::vector<sp<InputWindowHandle>> windows; +    std::vector<sp<WindowInfoHandle>> windows;      windows.push_back(new FakeWindowHandle("Mirror1", focusableWindowToken, true /* focusable */,                                             true /* visible */));      windows.push_back(new FakeWindowHandle("Mirror1", focusableWindowToken, true /* focusable */, @@ -120,7 +122,7 @@ TEST(FocusResolverTest, SetFocusedMirroredWindow) {  TEST(FocusResolverTest, SetInputWindows) {      sp<IBinder> focusableWindowToken = new BBinder(); -    std::vector<sp<InputWindowHandle>> windows; +    std::vector<sp<WindowInfoHandle>> windows;      sp<FakeWindowHandle> window = new FakeWindowHandle("Focusable", focusableWindowToken,                                                         true /* focusable */, true /* visible */);      windows.push_back(window); @@ -142,7 +144,7 @@ TEST(FocusResolverTest, SetInputWindows) {  TEST(FocusResolverTest, FocusRequestsCanBePending) {      sp<IBinder> invisibleWindowToken = new BBinder(); -    std::vector<sp<InputWindowHandle>> windows; +    std::vector<sp<WindowInfoHandle>> windows;      sp<FakeWindowHandle> invisibleWindow =              new FakeWindowHandle("Invisible", invisibleWindowToken, true /* focusable */, @@ -166,7 +168,7 @@ TEST(FocusResolverTest, FocusRequestsCanBePending) {  TEST(FocusResolverTest, FocusRequestsArePersistent) {      sp<IBinder> windowToken = new BBinder(); -    std::vector<sp<InputWindowHandle>> windows; +    std::vector<sp<WindowInfoHandle>> windows;      sp<FakeWindowHandle> window = new FakeWindowHandle("Test Window", windowToken,                                                         false /* focusable */, true /* visible */); @@ -207,7 +209,7 @@ TEST(FocusResolverTest, FocusRequestsArePersistent) {  TEST(FocusResolverTest, ConditionalFocusRequestsAreNotPersistent) {      sp<IBinder> hostWindowToken = new BBinder(); -    std::vector<sp<InputWindowHandle>> windows; +    std::vector<sp<WindowInfoHandle>> windows;      sp<FakeWindowHandle> hostWindow =              new FakeWindowHandle("Host Window", hostWindowToken, true /* focusable */, @@ -258,7 +260,7 @@ TEST(FocusResolverTest, ConditionalFocusRequestsAreNotPersistent) {  }  TEST(FocusResolverTest, FocusRequestsAreClearedWhenWindowIsRemoved) {      sp<IBinder> windowToken = new BBinder(); -    std::vector<sp<InputWindowHandle>> windows; +    std::vector<sp<WindowInfoHandle>> windows;      sp<FakeWindowHandle> window = new FakeWindowHandle("Test Window", windowToken,                                                         true /* focusable */, true /* visible */); diff --git a/services/inputflinger/tests/IInputFlingerQuery.aidl b/services/inputflinger/tests/IInputFlingerQuery.aidl index 5c8a8da612..aff03bf947 100644 --- a/services/inputflinger/tests/IInputFlingerQuery.aidl +++ b/services/inputflinger/tests/IInputFlingerQuery.aidl @@ -14,16 +14,16 @@   * limitations under the License.   */ -import android.FocusRequest;  import android.InputChannel; -import android.InputWindowInfo; +import android.gui.FocusRequest; +import android.gui.WindowInfo;  import android.os.ISetInputWindowsListener;  /** @hide */  interface IInputFlingerQuery  {      /* Test interfaces */ -    void getInputWindows(out InputWindowInfo[] inputHandles); +    void getInputWindows(out WindowInfo[] inputHandles);      void getInputChannels(out InputChannel[] channels);      void getLastFocusRequest(out FocusRequest request);      void resetInputManager(); diff --git a/services/inputflinger/tests/InputClassifierConverter_test.cpp b/services/inputflinger/tests/InputClassifierConverter_test.cpp index c0ada9d517..f626d56b8c 100644 --- a/services/inputflinger/tests/InputClassifierConverter_test.cpp +++ b/services/inputflinger/tests/InputClassifierConverter_test.cpp @@ -17,9 +17,9 @@  #include "../InputClassifierConverter.h"  #include <gtest/gtest.h> +#include <gui/constants.h>  #include <utils/BitSet.h> -  using namespace android::hardware::input;  namespace android { diff --git a/services/inputflinger/tests/InputClassifier_test.cpp b/services/inputflinger/tests/InputClassifier_test.cpp index a72df01ce6..3a9994eed9 100644 --- a/services/inputflinger/tests/InputClassifier_test.cpp +++ b/services/inputflinger/tests/InputClassifier_test.cpp @@ -16,6 +16,7 @@  #include "../InputClassifier.h"  #include <gtest/gtest.h> +#include <gui/constants.h>  #include "TestInputListener.h" diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index dff0752b59..50e185469f 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -29,9 +29,12 @@  #include <vector>  using android::base::StringPrintf; +using android::gui::FocusRequest; +using android::gui::TouchOcclusionMode; +using android::gui::WindowInfo; +using android::gui::WindowInfoHandle;  using android::os::InputEventInjectionResult;  using android::os::InputEventInjectionSync; -using android::os::TouchOcclusionMode;  using namespace android::flag_operators;  namespace android::inputdispatcher { @@ -469,8 +472,8 @@ protected:          }      } -    void setFocusedWindow(const sp<InputWindowHandle>& window, -                          const sp<InputWindowHandle>& focusedWindow = nullptr) { +    void setFocusedWindow(const sp<WindowInfoHandle>& window, +                          const sp<WindowInfoHandle>& focusedWindow = nullptr) {          FocusRequest request;          request.token = window->getToken();          request.windowName = window->getName(); @@ -527,8 +530,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {      event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,                       /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,                       identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, -                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_DISPLAY_SIZE, -                     AMOTION_EVENT_INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME, +                     AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0, +                     INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,                       /*pointerCount*/ 1, pointerProperties, pointerCoords);      ASSERT_EQ(InputEventInjectionResult::FAILED,                mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, @@ -541,9 +544,9 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {                               (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),                       0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,                       AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, -                     AMOTION_EVENT_INVALID_DISPLAY_SIZE, AMOTION_EVENT_INVALID_DISPLAY_SIZE, -                     ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, -                     pointerCoords); +                     ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, +                     ARBITRARY_TIME, ARBITRARY_TIME, +                     /*pointerCount*/ 1, pointerProperties, pointerCoords);      ASSERT_EQ(InputEventInjectionResult::FAILED,                mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,                                              InputEventInjectionSync::NONE, 0ms, 0)) @@ -554,9 +557,9 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {                               (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),                       0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,                       AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, -                     AMOTION_EVENT_INVALID_DISPLAY_SIZE, AMOTION_EVENT_INVALID_DISPLAY_SIZE, -                     ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, -                     pointerCoords); +                     ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, +                     ARBITRARY_TIME, ARBITRARY_TIME, +                     /*pointerCount*/ 1, pointerProperties, pointerCoords);      ASSERT_EQ(InputEventInjectionResult::FAILED,                mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,                                              InputEventInjectionSync::NONE, 0ms, 0)) @@ -568,9 +571,9 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {                               (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),                       0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,                       AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, -                     AMOTION_EVENT_INVALID_DISPLAY_SIZE, AMOTION_EVENT_INVALID_DISPLAY_SIZE, -                     ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, -                     pointerCoords); +                     ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, +                     ARBITRARY_TIME, ARBITRARY_TIME, +                     /*pointerCount*/ 1, pointerProperties, pointerCoords);      ASSERT_EQ(InputEventInjectionResult::FAILED,                mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,                                              InputEventInjectionSync::NONE, 0ms, 0)) @@ -581,9 +584,9 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {                               (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),                       0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,                       AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, -                     AMOTION_EVENT_INVALID_DISPLAY_SIZE, AMOTION_EVENT_INVALID_DISPLAY_SIZE, -                     ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, -                     pointerCoords); +                     ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, +                     ARBITRARY_TIME, ARBITRARY_TIME, +                     /*pointerCount*/ 1, pointerProperties, pointerCoords);      ASSERT_EQ(InputEventInjectionResult::FAILED,                mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,                                              InputEventInjectionSync::NONE, 0ms, 0)) @@ -593,8 +596,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {      event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,                       AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,                       identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, -                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_DISPLAY_SIZE, -                     AMOTION_EVENT_INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME, +                     AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0, +                     INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,                       /*pointerCount*/ 0, pointerProperties, pointerCoords);      ASSERT_EQ(InputEventInjectionResult::FAILED,                mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, @@ -604,8 +607,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {      event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,                       AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,                       identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, -                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_DISPLAY_SIZE, -                     AMOTION_EVENT_INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME, +                     AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0, +                     INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,                       /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);      ASSERT_EQ(InputEventInjectionResult::FAILED,                mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, @@ -617,8 +620,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {      event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,                       AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,                       identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, -                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_DISPLAY_SIZE, -                     AMOTION_EVENT_INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME, +                     AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0, +                     INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,                       /*pointerCount*/ 1, pointerProperties, pointerCoords);      ASSERT_EQ(InputEventInjectionResult::FAILED,                mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, @@ -629,8 +632,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {      event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,                       AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,                       identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, -                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_DISPLAY_SIZE, -                     AMOTION_EVENT_INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME, +                     AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0, +                     INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,                       /*pointerCount*/ 1, pointerProperties, pointerCoords);      ASSERT_EQ(InputEventInjectionResult::FAILED,                mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, @@ -643,8 +646,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {      event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,                       AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,                       identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, -                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_DISPLAY_SIZE, -                     AMOTION_EVENT_INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME, +                     AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0, +                     INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,                       /*pointerCount*/ 2, pointerProperties, pointerCoords);      ASSERT_EQ(InputEventInjectionResult::FAILED,                mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, @@ -892,7 +895,7 @@ protected:      std::string mName;  }; -class FakeWindowHandle : public InputWindowHandle { +class FakeWindowHandle : public WindowInfoHandle {  public:      static const int32_t WIDTH = 600;      static const int32_t HEIGHT = 800; @@ -914,7 +917,7 @@ public:          mInfo.token = *token;          mInfo.id = sId++;          mInfo.name = name; -        mInfo.type = InputWindowInfo::Type::APPLICATION; +        mInfo.type = WindowInfo::Type::APPLICATION;          mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;          mInfo.alpha = 1.0;          mInfo.frameLeft = 0; @@ -934,8 +937,6 @@ public:          mInfo.displayId = displayId;      } -    virtual bool updateInfo() { return true; } -      void setFocusable(bool focusable) { mInfo.focusable = focusable; }      void setVisible(bool visible) { mInfo.visible = visible; } @@ -948,9 +949,7 @@ public:      void setAlpha(float alpha) { mInfo.alpha = alpha; } -    void setTouchOcclusionMode(android::os::TouchOcclusionMode mode) { -        mInfo.touchOcclusionMode = mode; -    } +    void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }      void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; } @@ -964,11 +963,11 @@ public:          mInfo.addTouchableRegion(frame);      } -    void addFlags(Flags<InputWindowInfo::Flag> flags) { mInfo.flags |= flags; } +    void addFlags(Flags<WindowInfo::Flag> flags) { mInfo.flags |= flags; } -    void setFlags(Flags<InputWindowInfo::Flag> flags) { mInfo.flags = flags; } +    void setFlags(Flags<WindowInfo::Flag> flags) { mInfo.flags = flags; } -    void setInputFeatures(InputWindowInfo::Feature features) { mInfo.inputFeatures = features; } +    void setInputFeatures(WindowInfo::Feature features) { mInfo.inputFeatures = features; }      void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {          mInfo.transform.set(dsdx, dtdx, dtdy, dsdy); @@ -1102,7 +1101,7 @@ public:      void assertNoEvents() {          if (mInputReceiver == nullptr && -            mInfo.inputFeatures.test(InputWindowInfo::Feature::NO_INPUT_CHANNEL)) { +            mInfo.inputFeatures.test(WindowInfo::Feature::NO_INPUT_CHANNEL)) {              return; // Can't receive events if the window does not have input channel          }          ASSERT_NE(nullptr, mInputReceiver) @@ -1267,8 +1266,9 @@ public:                           mAction, mActionButton, mFlags, /* edgeFlags */ 0, AMETA_NONE,                           mButtonState, MotionClassification::NONE, identityTransform,                           /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition, -                         mRawYCursorPosition, mDisplayWidth, mDisplayHeight, mEventTime, mEventTime, -                         mPointers.size(), pointerProperties.data(), pointerCoords.data()); +                         mRawYCursorPosition, mDisplayOrientation, mDisplayWidth, mDisplayHeight, +                         mEventTime, mEventTime, mPointers.size(), pointerProperties.data(), +                         pointerCoords.data());          return event;      } @@ -1283,8 +1283,9 @@ private:      int32_t mFlags{0};      float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};      float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION}; -    int32_t mDisplayWidth{AMOTION_EVENT_INVALID_DISPLAY_SIZE}; -    int32_t mDisplayHeight{AMOTION_EVENT_INVALID_DISPLAY_SIZE}; +    uint32_t mDisplayOrientation{ui::Transform::ROT_0}; +    int32_t mDisplayWidth{INVALID_DISPLAY_SIZE}; +    int32_t mDisplayHeight{INVALID_DISPLAY_SIZE};      std::vector<PointerBuilder> mPointers;  }; @@ -1410,7 +1411,7 @@ TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {      sp<FakeWindowHandle> window =              new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);      window->setFrame(Rect(0, 0, 100, 100)); -    window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL); +    window->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);      mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});      ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, @@ -1433,7 +1434,7 @@ TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {      sp<FakeWindowHandle> window =              new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);      window->setFrame(Rect(0, 0, 100, 100)); -    window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL); +    window->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);      mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});      mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); @@ -1469,11 +1470,11 @@ TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {      sp<FakeWindowHandle> windowLeft =              new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);      windowLeft->setFrame(Rect(0, 0, 600, 800)); -    windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL); +    windowLeft->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);      sp<FakeWindowHandle> windowRight =              new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);      windowRight->setFrame(Rect(600, 0, 1200, 800)); -    windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL); +    windowRight->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);      mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); @@ -1580,7 +1581,7 @@ TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {      sp<FakeWindowHandle> window =              new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);      window->setFrame(Rect(0, 0, 1200, 800)); -    window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL); +    window->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);      mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); @@ -1662,11 +1663,11 @@ TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {      sp<FakeWindowHandle> windowLeft =              new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);      windowLeft->setFrame(Rect(0, 0, 600, 800)); -    windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL); +    windowLeft->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);      sp<FakeWindowHandle> windowRight =              new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);      windowRight->setFrame(Rect(600, 0, 1200, 800)); -    windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL); +    windowRight->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);      mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); @@ -1860,15 +1861,13 @@ TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {      sp<FakeWindowHandle> firstWindow =              new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);      firstWindow->setFrame(Rect(0, 0, 600, 400)); -    firstWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL | -                          InputWindowInfo::Flag::SPLIT_TOUCH); +    firstWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);      // Create a non touch modal window that supports split touch      sp<FakeWindowHandle> secondWindow =              new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);      secondWindow->setFrame(Rect(0, 400, 600, 800)); -    secondWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL | -                           InputWindowInfo::Flag::SPLIT_TOUCH); +    secondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);      // Add the windows to the dispatcher      mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}}); @@ -1934,15 +1933,13 @@ TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {      sp<FakeWindowHandle> firstWindow =              new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);      firstWindow->setFrame(Rect(0, 0, 600, 400)); -    firstWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL | -                          InputWindowInfo::Flag::SPLIT_TOUCH); +    firstWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);      // Create a non touch modal window that supports split touch      sp<FakeWindowHandle> secondWindow =              new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);      secondWindow->setFrame(Rect(0, 400, 600, 800)); -    secondWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL | -                           InputWindowInfo::Flag::SPLIT_TOUCH); +    secondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);      // Add the windows to the dispatcher      mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}}); @@ -2060,15 +2057,13 @@ TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {      sp<FakeWindowHandle> firstWindow =              new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);      firstWindow->setFrame(Rect(0, 0, 600, 400)); -    firstWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL | -                          InputWindowInfo::Flag::SPLIT_TOUCH); +    firstWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);      // Create second non touch modal window that supports split touch      sp<FakeWindowHandle> secondWindow =              new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);      secondWindow->setFrame(Rect(0, 400, 600, 800)); -    secondWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL | -                           InputWindowInfo::Flag::SPLIT_TOUCH); +    secondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);      // Add the windows to the dispatcher      mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}}); @@ -2432,7 +2427,7 @@ TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {      EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);  } -TEST_F(InputDispatcherTest, NonPointerMotionEvent_NotTransformed) { +TEST_F(InputDispatcherTest, NonPointerMotionEvent_JoystickAndTouchpadNotTransformed) {      std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();      sp<FakeWindowHandle> window =              new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT); @@ -2452,20 +2447,19 @@ TEST_F(InputDispatcherTest, NonPointerMotionEvent_NotTransformed) {      // Second, we consume focus event if it is right or wrong according to onFocusChangedLocked.      window->consumeFocusEvent(true); -    constexpr const std::array nonPointerSources = {AINPUT_SOURCE_TRACKBALL, -                                                    AINPUT_SOURCE_MOUSE_RELATIVE, -                                                    AINPUT_SOURCE_JOYSTICK}; -    for (const int source : nonPointerSources) { -        // Notify motion with a non-pointer source. -        NotifyMotionArgs motionArgs = -                generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, source, ADISPLAY_ID_DEFAULT); +    constexpr const std::array nonTransformedSources = {std::pair(AINPUT_SOURCE_TOUCHPAD, +                                                                  AMOTION_EVENT_ACTION_DOWN), +                                                        std::pair(AINPUT_SOURCE_JOYSTICK, +                                                                  AMOTION_EVENT_ACTION_MOVE)}; +    for (const auto& [source, action] : nonTransformedSources) { +        const NotifyMotionArgs motionArgs = generateMotionArgs(action, source, ADISPLAY_ID_DEFAULT);          mDispatcher->notifyMotion(&motionArgs);          MotionEvent* event = window->consumeMotion();          ASSERT_NE(event, nullptr);          const MotionEvent& motionEvent = *event; -        EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, motionEvent.getAction()); +        EXPECT_EQ(action, motionEvent.getAction());          EXPECT_EQ(motionArgs.pointerCount, motionEvent.getPointerCount());          float expectedX = motionArgs.pointerCoords[0].getX(); @@ -2737,8 +2731,7 @@ TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {      sp<FakeWindowHandle> slipperyExitWindow =              new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT); -    slipperyExitWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL | -                                 InputWindowInfo::Flag::SLIPPERY); +    slipperyExitWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SLIPPERY);      // Make sure this one overlaps the bottom window      slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));      // Change the owner uid/pid of the window so that it is considered to be occluding the bottom @@ -3221,9 +3214,9 @@ protected:                           DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,                           AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,                           identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, -                         AMOTION_EVENT_INVALID_CURSOR_POSITION, -                         0 /*AMOTION_EVENT_INVALID_DISPLAY_SIZE*/, -                         0 /*AMOTION_EVENT_INVALID_DISPLAY_SIZE*/, eventTime, eventTime, +                         AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0, +                         0 /*INVALID_DISPLAY_SIZE*/, 0 /*INVALID_DISPLAY_SIZE*/, eventTime, +                         eventTime,                           /*pointerCount*/ 1, pointerProperties, pointerCoords);          const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER; @@ -3281,12 +3274,12 @@ class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {          mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));          // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this          // window. -        mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL); +        mUnfocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);          mFocusedWindow =                  new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);          mFocusedWindow->setFrame(Rect(50, 50, 100, 100)); -        mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL); +        mFocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);          // Set focused application.          mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); @@ -3395,14 +3388,12 @@ class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {                                          ADISPLAY_ID_DEFAULT);          // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.          // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows. -        mWindow1->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL | -                           InputWindowInfo::Flag::SPLIT_TOUCH); +        mWindow1->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);          mWindow1->setFrame(Rect(0, 0, 100, 100));          mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",                                          ADISPLAY_ID_DEFAULT, mWindow1->getToken()); -        mWindow2->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL | -                           InputWindowInfo::Flag::SPLIT_TOUCH); +        mWindow2->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);          mWindow2->setFrame(Rect(100, 100, 200, 200));          mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}}); @@ -3413,7 +3404,7 @@ protected:      sp<FakeWindowHandle> mWindow2;      // Helper function to convert the point from screen coordinates into the window's space -    static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) { +    static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {          vec2 vals = windowInfo->transform.transform(point.x, point.y);          return {vals.x, vals.y};      } @@ -3601,7 +3592,7 @@ class InputDispatcherSingleWindowAnr : public InputDispatcherTest {          mWindow->setFocusable(true);          // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this          // window. -        mWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL); +        mWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);          // Set focused application.          mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication); @@ -4002,16 +3993,15 @@ class InputDispatcherMultiWindowAnr : public InputDispatcherTest {          // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this          // window.          // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped -        mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL | -                                   InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH | -                                   InputWindowInfo::Flag::SPLIT_TOUCH); +        mUnfocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | +                                   WindowInfo::Flag::WATCH_OUTSIDE_TOUCH | +                                   WindowInfo::Flag::SPLIT_TOUCH);          mFocusedWindow =                  new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT);          mFocusedWindow->setDispatchingTimeout(30ms);          mFocusedWindow->setFrame(Rect(50, 50, 100, 100)); -        mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL | -                                 InputWindowInfo::Flag::SPLIT_TOUCH); +        mFocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);          // Set focused application.          mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication); @@ -4379,7 +4369,7 @@ class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {                                                "Window without input channel", ADISPLAY_ID_DEFAULT,                                                std::make_optional<sp<IBinder>>(nullptr) /*token*/); -        mNoInputWindow->setInputFeatures(InputWindowInfo::Feature::NO_INPUT_CHANNEL); +        mNoInputWindow->setInputFeatures(WindowInfo::Feature::NO_INPUT_CHANNEL);          mNoInputWindow->setFrame(Rect(0, 0, 100, 100));          // It's perfectly valid for this window to not have an associated input channel @@ -4421,7 +4411,7 @@ TEST_F(InputDispatcherMultiWindowOcclusionTests,                                            "Window with input channel and NO_INPUT_CHANNEL",                                            ADISPLAY_ID_DEFAULT); -    mNoInputWindow->setInputFeatures(InputWindowInfo::Feature::NO_INPUT_CHANNEL); +    mNoInputWindow->setInputFeatures(WindowInfo::Feature::NO_INPUT_CHANNEL);      mNoInputWindow->setFrame(Rect(0, 0, 100, 100));      mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}}); @@ -4721,10 +4711,10 @@ protected:          mTouchWindow.clear();      } -    sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, -                                            os::TouchOcclusionMode mode, float alpha = 1.0f) { +    sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode, +                                            float alpha = 1.0f) {          sp<FakeWindowHandle> window = getWindow(uid, name); -        window->setFlags(InputWindowInfo::Flag::NOT_TOUCHABLE); +        window->setFlags(WindowInfo::Flag::NOT_TOUCHABLE);          window->setTouchOcclusionMode(mode);          window->setAlpha(alpha);          return window; @@ -4838,7 +4828,7 @@ TEST_F(InputDispatcherUntrustedTouchesTest,         WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {      const sp<FakeWindowHandle>& w =              getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f); -    w->addFlags(InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH); +    w->addFlags(WindowInfo::Flag::WATCH_OUTSIDE_TOUCH);      mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});      touch(); @@ -4849,7 +4839,7 @@ TEST_F(InputDispatcherUntrustedTouchesTest,  TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {      const sp<FakeWindowHandle>& w =              getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f); -    w->addFlags(InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH); +    w->addFlags(WindowInfo::Flag::WATCH_OUTSIDE_TOUCH);      mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});      touch(); @@ -5103,11 +5093,11 @@ protected:          mApp = std::make_shared<FakeApplicationHandle>();          mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);          mWindow->setFrame(Rect(0, 0, 100, 100)); -        mWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL); +        mWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);          mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);          mSecondWindow->setFrame(Rect(100, 0, 200, 100)); -        mSecondWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL); +        mSecondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);          mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);          mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}}); diff --git a/services/inputflinger/tests/InputFlingerService_test.cpp b/services/inputflinger/tests/InputFlingerService_test.cpp index c368e79f41..d2a98df612 100644 --- a/services/inputflinger/tests/InputFlingerService_test.cpp +++ b/services/inputflinger/tests/InputFlingerService_test.cpp @@ -28,9 +28,9 @@  #include <binder/Parcel.h>  #include <binder/ProcessState.h> +#include <gui/WindowInfo.h>  #include <input/Input.h>  #include <input/InputTransport.h> -#include <input/InputWindow.h>  #include <gtest/gtest.h>  #include <inttypes.h> @@ -44,6 +44,9 @@  #define TAG "InputFlingerServiceTest" +using android::gui::FocusRequest; +using android::gui::WindowInfo; +using android::gui::WindowInfoHandle;  using android::os::BnInputFlinger;  using android::os::BnSetInputWindowsListener;  using android::os::IInputFlinger; @@ -58,8 +61,8 @@ static const sp<IBinder> TestInfoToken = new BBinder();  static const sp<IBinder> FocusedTestInfoToken = new BBinder();  static constexpr int32_t TestInfoId = 1;  static const std::string TestInfoName = "InputFlingerServiceTestInputWindowInfo"; -static constexpr Flags<InputWindowInfo::Flag> TestInfoFlags = InputWindowInfo::Flag::NOT_FOCUSABLE; -static constexpr InputWindowInfo::Type TestInfoType = InputWindowInfo::Type::INPUT_METHOD; +static constexpr Flags<WindowInfo::Flag> TestInfoFlags = WindowInfo::Flag::NOT_FOCUSABLE; +static constexpr WindowInfo::Type TestInfoType = WindowInfo::Type::INPUT_METHOD;  static constexpr std::chrono::duration TestInfoDispatchingTimeout = 2532ms;  static constexpr int32_t TestInfoFrameLeft = 93;  static constexpr int32_t TestInfoFrameTop = 34; @@ -79,8 +82,7 @@ static constexpr bool TestInfoHasWallpaper = false;  static constexpr bool TestInfoPaused = false;  static constexpr int32_t TestInfoOwnerPid = 19;  static constexpr int32_t TestInfoOwnerUid = 24; -static constexpr InputWindowInfo::Feature TestInfoInputFeatures = -        InputWindowInfo::Feature::NO_INPUT_CHANNEL; +static constexpr WindowInfo::Feature TestInfoInputFeatures = WindowInfo::Feature::NO_INPUT_CHANNEL;  static constexpr int32_t TestInfoDisplayId = 34;  static constexpr int32_t TestInfoPortalToDisplayId = 2;  static constexpr bool TestInfoReplaceTouchableRegionWithCrop = true; @@ -102,13 +104,13 @@ public:  protected:      void InitializeInputFlinger(); -    void setInputWindowsByInfos(const std::vector<InputWindowInfo>& infos); +    void setInputWindowsByInfos(const std::vector<WindowInfo>& infos);      void setFocusedWindow(const sp<IBinder> token, const sp<IBinder> focusedToken,                            nsecs_t timestampNanos);      void setInputWindowsFinished(); -    void verifyInputWindowInfo(const InputWindowInfo& info) const; -    InputWindowInfo& getInfo() const { return const_cast<InputWindowInfo&>(mInfo); } +    void verifyInputWindowInfo(const WindowInfo& info) const; +    WindowInfo& getInfo() const { return const_cast<WindowInfo&>(mInfo); }      sp<IInputFlinger> mService;      sp<IInputFlingerQuery> mQuery; @@ -116,7 +118,7 @@ protected:  private:      sp<SetInputWindowsListener> mSetInputWindowsListener;      std::unique_ptr<InputChannel> mServerChannel, mClientChannel; -    InputWindowInfo mInfo; +    WindowInfo mInfo;      std::mutex mLock;      std::condition_variable mSetInputWindowsFinishedCondition;  }; @@ -136,14 +138,14 @@ protected:  public:      TestInputManager(){}; -    binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles); +    binder::Status getInputWindows(std::vector<WindowInfo>* inputHandles);      binder::Status getInputChannels(std::vector<::android::InputChannel>* channels);      binder::Status getLastFocusRequest(FocusRequest*);      status_t dump(int fd, const Vector<String16>& args) override;      binder::Status setInputWindows( -            const std::vector<InputWindowInfo>& handles, +            const std::vector<WindowInfo>& handles,              const sp<ISetInputWindowsListener>& setInputWindowsListener) override;      binder::Status createInputChannel(const std::string& name, InputChannel* outChannel) override; @@ -154,7 +156,7 @@ public:  private:      mutable Mutex mLock; -    std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>> mHandlesPerDisplay; +    std::unordered_map<int32_t, std::vector<sp<WindowInfoHandle>>> mHandlesPerDisplay;      std::vector<std::shared_ptr<InputChannel>> mInputChannels;      FocusRequest mFocusRequest;  }; @@ -162,7 +164,7 @@ private:  class TestInputQuery : public BnInputFlingerQuery {  public:      TestInputQuery(sp<android::TestInputManager> manager) : mManager(manager){}; -    binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles) override; +    binder::Status getInputWindows(std::vector<WindowInfo>* inputHandles) override;      binder::Status getInputChannels(std::vector<::android::InputChannel>* channels) override;      binder::Status getLastFocusRequest(FocusRequest*) override;      binder::Status resetInputManager() override; @@ -171,8 +173,7 @@ private:      sp<android::TestInputManager> mManager;  }; -binder::Status TestInputQuery::getInputWindows( -        std::vector<::android::InputWindowInfo>* inputHandles) { +binder::Status TestInputQuery::getInputWindows(std::vector<WindowInfo>* inputHandles) {      return mManager->getInputWindows(inputHandles);  } @@ -197,13 +198,13 @@ binder::Status SetInputWindowsListener::onSetInputWindowsFinished() {  }  binder::Status TestInputManager::setInputWindows( -        const std::vector<InputWindowInfo>& infos, +        const std::vector<WindowInfo>& infos,          const sp<ISetInputWindowsListener>& setInputWindowsListener) {      AutoMutex _l(mLock);      for (const auto& info : infos) { -        mHandlesPerDisplay.emplace(info.displayId, std::vector<sp<InputWindowHandle>>()); -        mHandlesPerDisplay[info.displayId].push_back(new InputWindowHandle(info)); +        mHandlesPerDisplay.emplace(info.displayId, std::vector<sp<WindowInfoHandle>>()); +        mHandlesPerDisplay[info.displayId].push_back(new WindowInfoHandle(info));      }      if (setInputWindowsListener) {          setInputWindowsListener->onSetInputWindowsFinished(); @@ -248,8 +249,7 @@ status_t TestInputManager::dump(int fd, const Vector<String16>& args) {      return NO_ERROR;  } -binder::Status TestInputManager::getInputWindows( -        std::vector<::android::InputWindowInfo>* inputInfos) { +binder::Status TestInputManager::getInputWindows(std::vector<WindowInfo>* inputInfos) {      for (auto& [displayId, inputHandles] : mHandlesPerDisplay) {          for (auto& inputHandle : inputHandles) {              inputInfos->push_back(*inputHandle->getInfo()); @@ -331,7 +331,7 @@ void InputFlingerServiceTest::TearDown() {      mQuery->resetInputManager();  } -void InputFlingerServiceTest::verifyInputWindowInfo(const InputWindowInfo& info) const { +void InputFlingerServiceTest::verifyInputWindowInfo(const WindowInfo& info) const {      EXPECT_EQ(mInfo, info);  } @@ -345,7 +345,7 @@ void InputFlingerServiceTest::InitializeInputFlinger() {      mQuery = interface_cast<IInputFlingerQuery>(input);  } -void InputFlingerServiceTest::setInputWindowsByInfos(const std::vector<InputWindowInfo>& infos) { +void InputFlingerServiceTest::setInputWindowsByInfos(const std::vector<WindowInfo>& infos) {      std::unique_lock<std::mutex> lock(mLock);      mService->setInputWindows(infos, mSetInputWindowsListener);      // Verify listener call @@ -361,20 +361,20 @@ void InputFlingerServiceTest::setFocusedWindow(const sp<IBinder> token,      request.timestamp = timestampNanos;      mService->setFocusedWindow(request);      // call set input windows and wait for the callback to drain the queue. -    setInputWindowsByInfos(std::vector<InputWindowInfo>()); +    setInputWindowsByInfos(std::vector<WindowInfo>());  }  /**   *  Test InputFlinger service interface SetInputWindows   */  TEST_F(InputFlingerServiceTest, InputWindow_SetInputWindows) { -    std::vector<InputWindowInfo> infos = {getInfo()}; +    std::vector<WindowInfo> infos = {getInfo()};      setInputWindowsByInfos(infos);      // Verify input windows from service -    std::vector<::android::InputWindowInfo> windowInfos; +    std::vector<WindowInfo> windowInfos;      mQuery->getInputWindows(&windowInfos); -    for (const ::android::InputWindowInfo& windowInfo : windowInfos) { +    for (const WindowInfo& windowInfo : windowInfos) {          verifyInputWindowInfo(windowInfo);      }  } diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index 997cbe88a1..778f6e65b0 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -32,6 +32,7 @@  #include <VibratorInputMapper.h>  #include <android-base/thread_annotations.h>  #include <gtest/gtest.h> +#include <gui/constants.h>  #include <inttypes.h>  #include <math.h> diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index eb31e92645..eeb3f3a288 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -158,6 +158,7 @@ filegroup {          "FrameTracer/FrameTracer.cpp",          "FrameTracker.cpp",          "HdrLayerInfoReporter.cpp", +        "WindowInfosListenerInvoker.cpp",          "Layer.cpp",          "LayerProtoHelper.cpp",          "LayerRejecter.cpp", @@ -212,7 +213,6 @@ cc_defaults {          "libcutils",          "libdisplayservicehidl",          "libhidlbase", -        "libinput",          "liblayers_proto",          "liblog",          "libprocessgroup", diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 23779be73a..71db330f01 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -58,6 +58,8 @@  namespace android { +using gui::WindowInfo; +  static constexpr float defaultMaxLuminance = 1000.0;  BufferLayer::BufferLayer(const LayerCreationArgs& args) @@ -419,33 +421,35 @@ bool BufferLayer::onPostComposition(const DisplayDevice* display,          mFrameTracker.setFrameReadyTime(desiredPresentTime);      } -    const Fps refreshRate = mFlinger->mRefreshRateConfigs->getCurrentRefreshRate().getFps(); -    const std::optional<Fps> renderRate = mFlinger->mScheduler->getFrameRateOverride(getOwnerUid()); -    if (presentFence->isValid()) { -        mFlinger->mTimeStats->setPresentFence(layerId, mCurrentFrameNumber, presentFence, -                                              refreshRate, renderRate, -                                              frameRateToSetFrameRateVotePayload( -                                                      mDrawingState.frameRate), -                                              getGameMode()); -        mFlinger->mFrameTracer->traceFence(layerId, getCurrentBufferId(), mCurrentFrameNumber, -                                           presentFence, FrameTracer::FrameEvent::PRESENT_FENCE); -        mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence)); -    } else if (!display) { -        // Do nothing. -    } else if (const auto displayId = PhysicalDisplayId::tryCast(display->getId()); -               displayId && mFlinger->getHwComposer().isConnected(*displayId)) { -        // The HWC doesn't support present fences, so use the refresh -        // timestamp instead. -        const nsecs_t actualPresentTime = display->getRefreshTimestamp(); -        mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime, -                                             refreshRate, renderRate, -                                             frameRateToSetFrameRateVotePayload( -                                                     mDrawingState.frameRate), -                                             getGameMode()); -        mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(), mCurrentFrameNumber, -                                               actualPresentTime, +    if (display) { +        const Fps refreshRate = display->refreshRateConfigs().getCurrentRefreshRate().getFps(); +        const std::optional<Fps> renderRate = +                mFlinger->mScheduler->getFrameRateOverride(getOwnerUid()); +        if (presentFence->isValid()) { +            mFlinger->mTimeStats->setPresentFence(layerId, mCurrentFrameNumber, presentFence, +                                                  refreshRate, renderRate, +                                                  frameRateToSetFrameRateVotePayload( +                                                          mDrawingState.frameRate), +                                                  getGameMode()); +            mFlinger->mFrameTracer->traceFence(layerId, getCurrentBufferId(), mCurrentFrameNumber, +                                               presentFence,                                                 FrameTracer::FrameEvent::PRESENT_FENCE); -        mFrameTracker.setActualPresentTime(actualPresentTime); +            mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence)); +        } else if (const auto displayId = PhysicalDisplayId::tryCast(display->getId()); +                   displayId && mFlinger->getHwComposer().isConnected(*displayId)) { +            // The HWC doesn't support present fences, so use the refresh +            // timestamp instead. +            const nsecs_t actualPresentTime = display->getRefreshTimestamp(); +            mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime, +                                                 refreshRate, renderRate, +                                                 frameRateToSetFrameRateVotePayload( +                                                         mDrawingState.frameRate), +                                                 getGameMode()); +            mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(), +                                                   mCurrentFrameNumber, actualPresentTime, +                                                   FrameTracer::FrameEvent::PRESENT_FENCE); +            mFrameTracker.setActualPresentTime(actualPresentTime); +        }      }      mFrameTracker.advanceFrame(); @@ -825,7 +829,7 @@ void BufferLayer::updateCloneBufferInfo() {      wp<Layer> tmpZOrderRelativeOf = mDrawingState.zOrderRelativeOf;      SortedVector<wp<Layer>> tmpZOrderRelatives = mDrawingState.zOrderRelatives;      wp<Layer> tmpTouchableRegionCrop = mDrawingState.touchableRegionCrop; -    InputWindowInfo tmpInputInfo = mDrawingState.inputInfo; +    WindowInfo tmpInputInfo = mDrawingState.inputInfo;      mDrawingState = clonedFrom->mDrawingState; diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 6b6d43425d..99e470dfe6 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -515,13 +515,10 @@ void BufferQueueLayer::onFirstRef() {  }  status_t BufferQueueLayer::setDefaultBufferProperties(uint32_t w, uint32_t h, PixelFormat format) { -    uint32_t const maxSurfaceDims = -          std::min(mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims()); -      // never allow a surface larger than what our underlying GL implementation      // can handle. -    if ((uint32_t(w) > maxSurfaceDims) || (uint32_t(h) > maxSurfaceDims)) { -        ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h)); +    if (mFlinger->exceedsMaxRenderTargetSize(w, h)) { +        ALOGE("dimensions too large %" PRIu32 " x %" PRIu32, w, h);          return BAD_VALUE;      } diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h index 1416b1e3c0..0ef0b995c3 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h @@ -166,6 +166,9 @@ public:      // Enables (or disables) layer caching on this output      virtual void setLayerCachingEnabled(bool) = 0; +    // Enables (or disables) layer caching texture pool on this output +    virtual void setLayerCachingTexturePoolEnabled(bool) = 0; +      // Sets the projection state to use      virtual void setProjection(ui::Rotation orientation, const Rect& layerStackSpaceRect,                                 const Rect& orientedDisplaySpaceRect) = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h index f832084f39..ddcc907a91 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h @@ -41,6 +41,7 @@ public:      std::optional<DisplayId> getDisplayId() const override;      void setCompositionEnabled(bool) override;      void setLayerCachingEnabled(bool) override; +    void setLayerCachingTexturePoolEnabled(bool) override;      void setProjection(ui::Rotation orientation, const Rect& layerStackSpaceRect,                         const Rect& orientedDisplaySpaceRect) override;      void setDisplaySize(const ui::Size&) override; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h index 7534548d4a..8ec15edf12 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h @@ -80,6 +80,8 @@ public:      void renderCachedSets(const OutputCompositionState& outputState,                            std::optional<std::chrono::steady_clock::time_point> renderDeadline); +    void setTexturePoolEnabled(bool enabled) { mTexturePool.setEnabled(enabled); } +      void dump(std::string& result) const;      void dumpLayers(std::string& result) const; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h index bce438fa13..523752719d 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h @@ -21,7 +21,7 @@  #include <compositionengine/LayerFECompositionState.h>  #include <compositionengine/OutputLayer.h>  #include <compositionengine/impl/OutputLayerCompositionState.h> -#include <input/Flags.h> +#include <ftl/Flags.h>  #include <string> diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Planner.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Planner.h index be34153d31..76d5e81a88 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Planner.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Planner.h @@ -64,6 +64,8 @@ public:      void renderCachedSets(const OutputCompositionState& outputState,                            std::optional<std::chrono::steady_clock::time_point> renderDeadline); +    void setTexturePoolEnabled(bool enabled) { mFlattener.setTexturePoolEnabled(enabled); } +      void dump(const Vector<String16>& args, std::string&);  private: diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/TexturePool.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/TexturePool.h index fb53ee04cd..d607c75325 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/TexturePool.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/TexturePool.h @@ -63,7 +63,8 @@ public:          sp<Fence> mFence;      }; -    TexturePool(renderengine::RenderEngine& renderEngine) : mRenderEngine(renderEngine) {} +    TexturePool(renderengine::RenderEngine& renderEngine) +          : mRenderEngine(renderEngine), mEnabled(false) {}      virtual ~TexturePool() = default; @@ -78,6 +79,12 @@ public:      // to the pool.      std::shared_ptr<AutoTexture> borrowTexture(); +    // Enables or disables the pool. When the pool is disabled, no buffers will +    // be held by the pool. This is useful when the active display changes. +    void setEnabled(bool enable); + +    void dump(std::string& out) const; +  protected:      // Proteted visibility so that they can be used for testing      const static constexpr size_t kMinPoolSize = 3; @@ -95,8 +102,10 @@ private:      // Returns a previously borrowed texture to the pool.      void returnTexture(std::shared_ptr<renderengine::ExternalTexture>&& texture,                         const sp<Fence>& fence); +    void allocatePool();      renderengine::RenderEngine& mRenderEngine;      ui::Size mSize; +    bool mEnabled;  };  } // namespace android::compositionengine::impl::planner diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h index 8e777e3c9f..8fdf3ae887 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h @@ -37,6 +37,7 @@ public:      MOCK_METHOD1(setCompositionEnabled, void(bool));      MOCK_METHOD1(setLayerCachingEnabled, void(bool)); +    MOCK_METHOD1(setLayerCachingTexturePoolEnabled, void(bool));      MOCK_METHOD3(setProjection, void(ui::Rotation, const Rect&, const Rect&));      MOCK_METHOD1(setDisplaySize, void(const ui::Size&));      MOCK_METHOD2(setLayerStackFilter, void(uint32_t, bool)); diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index cafcb40e80..3310a71c79 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -146,6 +146,12 @@ void Output::setLayerCachingEnabled(bool enabled) {      }  } +void Output::setLayerCachingTexturePoolEnabled(bool enabled) { +    if (mPlanner) { +        mPlanner->setTexturePoolEnabled(enabled); +    } +} +  void Output::setProjection(ui::Rotation orientation, const Rect& layerStackSpaceRect,                             const Rect& orientedDisplaySpaceRect) {      auto& outputState = editState(); diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp index f033279caa..8e2c1821cb 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp @@ -205,6 +205,9 @@ void Flattener::dump(std::string& result) const {                          durationString(lastUpdate).c_str());      dumpLayers(result); + +    base::StringAppendF(&result, "\n"); +    mTexturePool.dump(result);  }  size_t Flattener::calculateDisplayCost(const std::vector<const LayerState*>& layers) const { diff --git a/services/surfaceflinger/CompositionEngine/src/planner/TexturePool.cpp b/services/surfaceflinger/CompositionEngine/src/planner/TexturePool.cpp index e3772a22d2..497c433c76 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/TexturePool.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/TexturePool.cpp @@ -24,14 +24,22 @@  namespace android::compositionengine::impl::planner { +void TexturePool::allocatePool() { +    mPool.clear(); +    if (mEnabled && mSize.isValid()) { +        mPool.resize(kMinPoolSize); +        std::generate_n(mPool.begin(), kMinPoolSize, [&]() { +            return Entry{genTexture(), nullptr}; +        }); +    } +} +  void TexturePool::setDisplaySize(ui::Size size) {      if (mSize == size) {          return;      }      mSize = size; -    mPool.clear(); -    mPool.resize(kMinPoolSize); -    std::generate_n(mPool.begin(), kMinPoolSize, [&]() { return Entry{genTexture(), nullptr}; }); +    allocatePool();  }  std::shared_ptr<TexturePool::AutoTexture> TexturePool::borrowTexture() { @@ -46,7 +54,12 @@ std::shared_ptr<TexturePool::AutoTexture> TexturePool::borrowTexture() {  void TexturePool::returnTexture(std::shared_ptr<renderengine::ExternalTexture>&& texture,                                  const sp<Fence>& fence) { -    // Drop the texture on the floor if the pool is no longer tracking textures of the same size. +    // Drop the texture on the floor if the pool is not enabled +    if (!mEnabled) { +        return; +    } + +    // Or the texture on the floor if the pool is no longer tracking textures of the same size.      if (static_cast<int32_t>(texture->getBuffer()->getWidth()) != mSize.getWidth() ||          static_cast<int32_t>(texture->getBuffer()->getHeight()) != mSize.getHeight()) {          ALOGV("Deallocating texture from Planner's pool - display size changed (previous: (%dx%d), " @@ -81,4 +94,15 @@ std::shared_ptr<renderengine::ExternalTexture> TexturePool::genTexture() {                                                     renderengine::ExternalTexture::Usage::WRITEABLE);  } +void TexturePool::setEnabled(bool enabled) { +    mEnabled = enabled; +    allocatePool(); +} + +void TexturePool::dump(std::string& out) const { +    base::StringAppendF(&out, +                        "TexturePool (%s) has %zu buffers of size [%" PRId32 ", %" PRId32 "]\n", +                        mEnabled ? "enabled" : "disabled", mPool.size(), mSize.width, mSize.height); +} +  } // namespace android::compositionengine::impl::planner
\ No newline at end of file diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h index a195e5808a..ada5adfa12 100644 --- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h +++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h @@ -47,9 +47,7 @@ public:      MOCK_CONST_METHOD0(getMaxVirtualDisplayCount, size_t());      MOCK_CONST_METHOD0(getMaxVirtualDisplayDimension, size_t()); -    MOCK_METHOD4(allocateVirtualDisplay, -                 bool(HalVirtualDisplayId, ui::Size, ui::PixelFormat*, -                      std::optional<PhysicalDisplayId>)); +    MOCK_METHOD3(allocateVirtualDisplay, bool(HalVirtualDisplayId, ui::Size, ui::PixelFormat*));      MOCK_METHOD2(allocatePhysicalDisplay, void(hal::HWDisplayId, PhysicalDisplayId));      MOCK_METHOD1(createLayer, std::shared_ptr<HWC2::Layer>(HalDisplayId));      MOCK_METHOD5(getDeviceCompositionChanges, diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/TexturePoolTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/TexturePoolTest.cpp index b802e51234..6fc90fe5e5 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/TexturePoolTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/TexturePoolTest.cpp @@ -42,6 +42,7 @@ struct TexturePoolTest : public testing::Test {          const ::testing::TestInfo* const test_info =                  ::testing::UnitTest::GetInstance()->current_test_info();          ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); +        mTexturePool.setEnabled(true);          mTexturePool.setDisplaySize(kDisplaySize);      } @@ -130,5 +131,44 @@ TEST_F(TexturePoolTest, reallocatesWhenDisplaySizeChanges) {                static_cast<int32_t>(texture->get()->getBuffer()->getHeight()));  } +TEST_F(TexturePoolTest, freesBuffersWhenDisabled) { +    EXPECT_EQ(mTexturePool.getPoolSize(), mTexturePool.getMinPoolSize()); + +    std::deque<std::shared_ptr<TexturePool::AutoTexture>> textures; +    for (size_t i = 0; i < mTexturePool.getMinPoolSize() - 1; i++) { +        textures.emplace_back(mTexturePool.borrowTexture()); +    } + +    EXPECT_EQ(mTexturePool.getPoolSize(), 1u); +    mTexturePool.setEnabled(false); +    EXPECT_EQ(mTexturePool.getPoolSize(), 0u); + +    textures.clear(); +    EXPECT_EQ(mTexturePool.getPoolSize(), 0u); +} + +TEST_F(TexturePoolTest, doesNotHoldBuffersWhenDisabled) { +    EXPECT_EQ(mTexturePool.getPoolSize(), mTexturePool.getMinPoolSize()); +    mTexturePool.setEnabled(false); +    EXPECT_EQ(mTexturePool.getPoolSize(), 0u); + +    std::deque<std::shared_ptr<TexturePool::AutoTexture>> textures; +    for (size_t i = 0; i < mTexturePool.getMinPoolSize() - 1; i++) { +        textures.emplace_back(mTexturePool.borrowTexture()); +    } + +    EXPECT_EQ(mTexturePool.getPoolSize(), 0u); +    textures.clear(); +    EXPECT_EQ(mTexturePool.getPoolSize(), 0u); +} + +TEST_F(TexturePoolTest, reallocatesWhenReEnabled) { +    EXPECT_EQ(mTexturePool.getPoolSize(), mTexturePool.getMinPoolSize()); +    mTexturePool.setEnabled(false); +    EXPECT_EQ(mTexturePool.getPoolSize(), 0u); +    mTexturePool.setEnabled(true); +    EXPECT_EQ(mTexturePool.getPoolSize(), mTexturePool.getMinPoolSize()); +} +  } // namespace  } // namespace android::compositionengine::impl::planner diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index ca4b6abc03..4445eea604 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -22,6 +22,8 @@  #undef LOG_TAG  #define LOG_TAG "DisplayDevice" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS +  #include <android-base/stringprintf.h>  #include <compositionengine/CompositionEngine.h>  #include <compositionengine/Display.h> @@ -40,6 +42,7 @@  #include "DisplayDevice.h"  #include "Layer.h" +#include "RefreshRateOverlay.h"  #include "SurfaceFlinger.h"  namespace android { @@ -65,9 +68,12 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs& args)          mSequenceId(args.sequenceId),          mConnectionType(args.connectionType),          mCompositionDisplay{args.compositionDisplay}, +        mActiveModeFPSTrace("ActiveModeFPS -" + to_string(getId())), +        mActiveModeFPSHwcTrace("ActiveModeFPS_HWC -" + to_string(getId())),          mPhysicalOrientation(args.physicalOrientation),          mSupportedModes(std::move(args.supportedModes)), -        mIsPrimary(args.isPrimary) { +        mIsPrimary(args.isPrimary), +        mRefreshRateConfigs(std::move(args.refreshRateConfigs)) {      mCompositionDisplay->editState().isSecure = args.isSecure;      mCompositionDisplay->createRenderSurface(              compositionengine::RenderSurfaceCreationArgsBuilder() @@ -154,20 +160,29 @@ bool DisplayDevice::isPoweredOn() const {  void DisplayDevice::setActiveMode(DisplayModeId id) {      const auto mode = getMode(id);      LOG_FATAL_IF(!mode, "Cannot set active mode which is not supported."); +    ATRACE_INT(mActiveModeFPSTrace.c_str(), mode->getFps().getIntValue());      mActiveMode = mode; +    if (mRefreshRateConfigs) { +        mRefreshRateConfigs->setCurrentModeId(mActiveMode->getId()); +    } +    if (mRefreshRateOverlay) { +        mRefreshRateOverlay->changeRefreshRate(mActiveMode->getFps()); +    }  } -status_t DisplayDevice::initiateModeChange(DisplayModeId modeId, +status_t DisplayDevice::initiateModeChange(const ActiveModeInfo& info,                                             const hal::VsyncPeriodChangeConstraints& constraints, -                                           hal::VsyncPeriodChangeTimeline* outTimeline) const { -    const auto mode = getMode(modeId); -    if (!mode) { +                                           hal::VsyncPeriodChangeTimeline* outTimeline) { +    if (!info.mode || info.mode->getPhysicalDisplayId() != getPhysicalId()) {          ALOGE("Trying to initiate a mode change to invalid mode %s on display %s", -              std::to_string(modeId.value()).c_str(), to_string(getId()).c_str()); +              info.mode ? std::to_string(info.mode->getId().value()).c_str() : "null", +              to_string(getId()).c_str());          return BAD_VALUE;      } -    return mHwComposer.setActiveModeWithConstraints(getPhysicalId(), mode->getHwcId(), constraints, -                                                    outTimeline); +    mUpcomingActiveMode = info; +    ATRACE_INT(mActiveModeFPSHwcTrace.c_str(), info.mode->getFps().getIntValue()); +    return mHwComposer.setActiveModeWithConstraints(getPhysicalId(), info.mode->getHwcId(), +                                                    constraints, outTimeline);  }  const DisplayModePtr& DisplayDevice::getActiveMode() const { @@ -217,12 +232,23 @@ ui::Dataspace DisplayDevice::getCompositionDataSpace() const {  }  void DisplayDevice::setLayerStack(ui::LayerStack stack) { -    mCompositionDisplay->setLayerStackFilter(stack, isPrimary()); +    mCompositionDisplay->setLayerStackFilter(stack, isInternal()); +    if (mRefreshRateOverlay) { +        mRefreshRateOverlay->setLayerStack(stack); +    } +} + +void DisplayDevice::setFlags(uint32_t flags) { +    mFlags = flags;  }  void DisplayDevice::setDisplaySize(int width, int height) {      LOG_FATAL_IF(!isVirtual(), "Changing the display size is supported only for virtual displays."); -    mCompositionDisplay->setDisplaySize(ui::Size(width, height)); +    const auto size = ui::Size(width, height); +    mCompositionDisplay->setDisplaySize(size); +    if (mRefreshRateOverlay) { +        mRefreshRateOverlay->setViewport(size); +    }  }  void DisplayDevice::setProjection(ui::Rotation orientation, Rect layerStackSpaceRect, @@ -262,7 +288,7 @@ ui::Transform::RotationFlags DisplayDevice::getPrimaryDisplayRotationFlags() {  std::string DisplayDevice::getDebugName() const {      const char* type = "virtual";      if (mConnectionType) { -        type = *mConnectionType == ui::DisplayConnectionType::Internal ? "internal" : "external"; +        type = isInternal() ? "internal" : "external";      }      return base::StringPrintf("DisplayDevice{%s, %s%s, \"%s\"}", to_string(getId()).c_str(), type, @@ -292,6 +318,10 @@ void DisplayDevice::dump(std::string& result) const {      }      result.append("\n");      getCompositionDisplay()->dump(result); + +    if (mRefreshRateConfigs) { +        mRefreshRateConfigs->dump(result); +    }  }  bool DisplayDevice::hasRenderIntent(ui::RenderIntent intent) const { @@ -378,6 +408,80 @@ HdrCapabilities DisplayDevice::getHdrCapabilities() const {                             capabilities.getDesiredMinLuminance());  } +void DisplayDevice::enableRefreshRateOverlay(bool enable, bool showSpinnner) { +    if (!enable) { +        mRefreshRateOverlay.reset(); +        return; +    } + +    const auto [lowFps, highFps] = mRefreshRateConfigs->getSupportedRefreshRateRange(); +    mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*mFlinger, lowFps.getIntValue(), +                                                               highFps.getIntValue(), showSpinnner); +    mRefreshRateOverlay->setLayerStack(getLayerStack()); +    mRefreshRateOverlay->setViewport(getSize()); +    mRefreshRateOverlay->changeRefreshRate(getActiveMode()->getFps()); +} + +bool DisplayDevice::onKernelTimerChanged(std::optional<DisplayModeId> desiredModeId, +                                         bool timerExpired) { +    if (mRefreshRateConfigs && mRefreshRateOverlay) { +        const auto newRefreshRate = +                mRefreshRateConfigs->onKernelTimerChanged(desiredModeId, timerExpired); +        if (newRefreshRate) { +            mRefreshRateOverlay->changeRefreshRate(*newRefreshRate); +            return true; +        } +    } + +    return false; +} + +void DisplayDevice::onInvalidate() { +    if (mRefreshRateOverlay) { +        mRefreshRateOverlay->onInvalidate(); +    } +} + +bool DisplayDevice::setDesiredActiveMode(const ActiveModeInfo& info) { +    ATRACE_CALL(); + +    LOG_ALWAYS_FATAL_IF(!info.mode, "desired mode not provided"); +    LOG_ALWAYS_FATAL_IF(getPhysicalId() != info.mode->getPhysicalDisplayId(), "DisplayId mismatch"); + +    ALOGV("%s(%s)", __func__, to_string(*info.mode).c_str()); + +    std::scoped_lock lock(mActiveModeLock); +    if (mDesiredActiveModeChanged) { +        // If a mode change is pending, just cache the latest request in mDesiredActiveMode +        const Scheduler::ModeEvent prevConfig = mDesiredActiveMode.event; +        mDesiredActiveMode = info; +        mDesiredActiveMode.event = mDesiredActiveMode.event | prevConfig; +        return false; +    } + +    // Check if we are already at the desired mode +    if (getActiveMode()->getId() == info.mode->getId()) { +        return false; +    } + +    // Initiate a mode change. +    mDesiredActiveModeChanged = true; +    mDesiredActiveMode = info; +    return true; +} + +std::optional<DisplayDevice::ActiveModeInfo> DisplayDevice::getDesiredActiveMode() const { +    std::scoped_lock lock(mActiveModeLock); +    if (mDesiredActiveModeChanged) return mDesiredActiveMode; +    return std::nullopt; +} + +void DisplayDevice::clearDesiredActiveModeState() { +    std::scoped_lock lock(mActiveModeLock); +    mDesiredActiveMode.event = Scheduler::ModeEvent::None; +    mDesiredActiveModeChanged = false; +} +  std::atomic<int32_t> DisplayDeviceState::sNextSequenceId(1);  }  // namespace android diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 7e4d92308c..4d435c7e47 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -39,17 +39,24 @@  #include <utils/RefBase.h>  #include <utils/Timers.h> +#include "MainThreadGuard.h" +  #include "DisplayHardware/DisplayIdentification.h"  #include "DisplayHardware/DisplayMode.h"  #include "DisplayHardware/Hal.h"  #include "DisplayHardware/PowerAdvisor.h" +#include "Scheduler/RefreshRateConfigs.h" + +#include "TracedOrdinal.h" +  namespace android {  class Fence;  class HWComposer;  class IGraphicBufferProducer;  class Layer; +class RefreshRateOverlay;  class SurfaceFlinger;  struct CompositionInfo; @@ -64,6 +71,7 @@ class DisplayDevice : public RefBase {  public:      constexpr static float sDefaultMinLumiance = 0.0;      constexpr static float sDefaultMaxLumiance = 500.0; +    enum { eReceivesInput = 0x01 };      explicit DisplayDevice(DisplayDeviceCreationArgs& args); @@ -78,6 +86,9 @@ public:      bool isVirtual() const { return !mConnectionType; }      bool isPrimary() const { return mIsPrimary; } +    bool isInternal() const { +        return !isVirtual() && mConnectionType == ui::DisplayConnectionType::Internal; +    }      // isSecure indicates whether this display can be trusted to display      // secure surfaces. @@ -90,6 +101,7 @@ public:      void setLayerStack(ui::LayerStack);      void setDisplaySize(int width, int height);      void setProjection(ui::Rotation orientation, Rect viewport, Rect frame); +    void setFlags(uint32_t flags);      ui::Rotation getPhysicalOrientation() const { return mPhysicalOrientation; }      ui::Rotation getOrientation() const { return mOrientation; } @@ -102,6 +114,7 @@ public:      const Rect& getOrientedDisplaySpaceRect() const;      bool needsFiltering() const;      ui::LayerStack getLayerStack() const; +    bool receivesInput() const { return mFlags & eReceivesInput; }      DisplayId getId() const; @@ -172,10 +185,28 @@ public:       * Display mode management.       */      const DisplayModePtr& getActiveMode() const; -    void setActiveMode(DisplayModeId); -    status_t initiateModeChange(DisplayModeId modeId, + +    struct ActiveModeInfo { +        DisplayModePtr mode; +        scheduler::RefreshRateConfigEvent event = scheduler::RefreshRateConfigEvent::None; + +        bool operator!=(const ActiveModeInfo& other) const { +            return mode != other.mode || event != other.event; +        } +    }; + +    bool setDesiredActiveMode(const ActiveModeInfo&) EXCLUDES(mActiveModeLock); +    std::optional<ActiveModeInfo> getDesiredActiveMode() const EXCLUDES(mActiveModeLock); +    void clearDesiredActiveModeState() EXCLUDES(mActiveModeLock); +    ActiveModeInfo getUpcomingActiveMode() const REQUIRES(SF_MAIN_THREAD) { +        return mUpcomingActiveMode; +    } + +    void setActiveMode(DisplayModeId) REQUIRES(SF_MAIN_THREAD); +    status_t initiateModeChange(const ActiveModeInfo&,                                  const hal::VsyncPeriodChangeConstraints& constraints, -                                hal::VsyncPeriodChangeTimeline* outTimeline) const; +                                hal::VsyncPeriodChangeTimeline* outTimeline) +            REQUIRES(SF_MAIN_THREAD);      // Return the immutable list of supported display modes. The HWC may report different modes      // after a hotplug reconnect event, in which case the DisplayDevice object will be recreated. @@ -187,6 +218,22 @@ public:      // set-top boxes after a hotplug reconnect.      DisplayModePtr getMode(DisplayModeId) const; +    // Returns the refresh rate configs for this display. +    scheduler::RefreshRateConfigs& refreshRateConfigs() const { return *mRefreshRateConfigs; } + +    // Returns a shared pointer to the refresh rate configs for this display. +    // Clients can store this refresh rate configs and use it even if the DisplayDevice +    // is destroyed. +    std::shared_ptr<scheduler::RefreshRateConfigs> holdRefreshRateConfigs() const { +        return mRefreshRateConfigs; +    } + +    // Enables an overlay to be displayed with the current refresh rate +    void enableRefreshRateOverlay(bool enable, bool showSpinner); +    bool isRefreshRateOverlayEnabled() const { return mRefreshRateOverlay != nullptr; } +    bool onKernelTimerChanged(std::optional<DisplayModeId>, bool timerExpired); +    void onInvalidate(); +      void onVsync(nsecs_t timestamp);      nsecs_t getVsyncPeriodFromHWC() const;      nsecs_t getRefreshTimestamp() const; @@ -211,6 +258,8 @@ private:      const std::shared_ptr<compositionengine::Display> mCompositionDisplay;      std::string mDisplayName; +    std::string mActiveModeFPSTrace; +    std::string mActiveModeFPSHwcTrace;      const ui::Rotation mPhysicalOrientation;      ui::Rotation mOrientation = ui::ROTATION_0; @@ -227,9 +276,20 @@ private:      // TODO(b/74619554): Remove special cases for primary display.      const bool mIsPrimary; +    uint32_t mFlags = 0; +      std::optional<DeviceProductInfo> mDeviceProductInfo;      std::vector<ui::Hdr> mOverrideHdrTypes; + +    std::shared_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs; +    std::unique_ptr<RefreshRateOverlay> mRefreshRateOverlay; + +    mutable std::mutex mActiveModeLock; +    ActiveModeInfo mDesiredActiveMode GUARDED_BY(mActiveModeLock); +    TracedOrdinal<bool> mDesiredActiveModeChanged +            GUARDED_BY(mActiveModeLock) = {"DesiredActiveModeChanged", false}; +    ActiveModeInfo mUpcomingActiveMode GUARDED_BY(SF_MAIN_THREAD);  };  struct DisplayDeviceState { @@ -252,6 +312,7 @@ struct DisplayDeviceState {      std::optional<Physical> physical;      sp<IGraphicBufferProducer> surface;      ui::LayerStack layerStack = ui::NO_LAYER_STACK; +    uint32_t flags = 0;      Rect layerStackSpaceRect;      Rect orientedDisplaySpaceRect;      ui::Rotation orientation = ui::ROTATION_0; @@ -274,6 +335,7 @@ struct DisplayDeviceCreationArgs {      HWComposer& hwComposer;      const wp<IBinder> displayToken;      const std::shared_ptr<compositionengine::Display> compositionDisplay; +    std::shared_ptr<scheduler::RefreshRateConfigs> refreshRateConfigs;      int32_t sequenceId{0};      std::optional<ui::DisplayConnectionType> connectionType; @@ -289,6 +351,7 @@ struct DisplayDeviceCreationArgs {              hardware::graphics::composer::hal::PowerMode::ON};      bool isPrimary{false};      DisplayModes supportedModes; +    DisplayModeId activeModeId;  };  // Predicates for display lookup. diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp index caf0294a56..09734c275f 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp @@ -212,7 +212,7 @@ uint32_t Composer::getMaxVirtualDisplayCount()  }  Error Composer::createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat* format, -                                     std::optional<Display>, Display* outDisplay) { +                                     Display* outDisplay) {      const uint32_t bufferSlotCount = 1;      Error error = kDefaultError;      if (mClient_2_2) { diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h index b525e63c66..fe114b9512 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h @@ -96,7 +96,7 @@ public:      virtual uint32_t getMaxVirtualDisplayCount() = 0;      virtual Error createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat*, -                                       std::optional<Display> mirror, Display* outDisplay) = 0; +                                       Display* outDisplay) = 0;      virtual Error destroyVirtualDisplay(Display display) = 0;      virtual Error acceptDisplayChanges(Display display) = 0; @@ -342,7 +342,7 @@ public:      uint32_t getMaxVirtualDisplayCount() override;      Error createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat* format, -                               std::optional<Display> mirror, Display* outDisplay) override; +                               Display* outDisplay) override;      Error destroyVirtualDisplay(Display display) override;      Error acceptDisplayChanges(Display display) override; diff --git a/services/surfaceflinger/DisplayHardware/DisplayMode.h b/services/surfaceflinger/DisplayHardware/DisplayMode.h index 85cc993c67..5de622b318 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayMode.h +++ b/services/surfaceflinger/DisplayHardware/DisplayMode.h @@ -22,6 +22,7 @@  #include <android-base/stringprintf.h>  #include <android/configuration.h> +#include <ui/DisplayId.h>  #include <ui/DisplayMode.h>  #include <ui/Size.h>  #include <utils/Timers.h> @@ -54,6 +55,11 @@ public:              return *this;          } +        Builder& setPhysicalDisplayId(PhysicalDisplayId id) { +            mDisplayMode->mPhysicalDisplayId = id; +            return *this; +        } +          Builder& setWidth(int32_t width) {              mDisplayMode->mWidth = width;              return *this; @@ -112,6 +118,7 @@ public:      DisplayModeId getId() const { return mId; }      hal::HWConfigId getHwcId() const { return mHwcId; } +    PhysicalDisplayId getPhysicalDisplayId() const { return mPhysicalDisplayId; }      int32_t getWidth() const { return mWidth; }      int32_t getHeight() const { return mHeight; } @@ -136,6 +143,7 @@ private:      hal::HWConfigId mHwcId;      DisplayModeId mId; +    PhysicalDisplayId mPhysicalDisplayId;      int32_t mWidth = -1;      int32_t mHeight = -1; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 7e45dabdea..a790b4c11e 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -245,8 +245,7 @@ size_t HWComposer::getMaxVirtualDisplayDimension() const {  }  bool HWComposer::allocateVirtualDisplay(HalVirtualDisplayId displayId, ui::Size resolution, -                                        ui::PixelFormat* format, -                                        std::optional<PhysicalDisplayId> mirror) { +                                        ui::PixelFormat* format) {      if (!resolution.isValid()) {          ALOGE("%s: Invalid resolution %dx%d", __func__, resolution.width, resolution.height);          return false; @@ -262,14 +261,9 @@ bool HWComposer::allocateVirtualDisplay(HalVirtualDisplayId displayId, ui::Size          return false;      } -    std::optional<hal::HWDisplayId> hwcMirrorId; -    if (mirror) { -        hwcMirrorId = fromPhysicalDisplayId(*mirror); -    } -      hal::HWDisplayId hwcDisplayId;      const auto error = static_cast<hal::Error>( -            mComposer->createVirtualDisplay(width, height, format, hwcMirrorId, &hwcDisplayId)); +            mComposer->createVirtualDisplay(width, height, format, &hwcDisplayId));      RETURN_IF_HWC_ERROR_FOR("createVirtualDisplay", error, displayId, false);      auto display = std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities, diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index b1849e8c11..49f96d9614 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -113,11 +113,7 @@ public:      // Attempts to allocate a virtual display on the HWC. The maximum number of virtual displays      // supported by the HWC can be queried in advance, but allocation may fail for other reasons. -    // For virtualized compositors, the PhysicalDisplayId is a hint that this virtual display is -    // a mirror of a physical display, and that the screen should be captured by the host rather -    // than guest compositor. -    virtual bool allocateVirtualDisplay(HalVirtualDisplayId, ui::Size, ui::PixelFormat*, -                                        std::optional<PhysicalDisplayId> mirror) = 0; +    virtual bool allocateVirtualDisplay(HalVirtualDisplayId, ui::Size, ui::PixelFormat*) = 0;      virtual void allocatePhysicalDisplay(hal::HWDisplayId, PhysicalDisplayId) = 0; @@ -265,8 +261,7 @@ public:      size_t getMaxVirtualDisplayCount() const override;      size_t getMaxVirtualDisplayDimension() const override; -    bool allocateVirtualDisplay(HalVirtualDisplayId, ui::Size, ui::PixelFormat*, -                                std::optional<PhysicalDisplayId>) override; +    bool allocateVirtualDisplay(HalVirtualDisplayId, ui::Size, ui::PixelFormat*) override;      // Called from SurfaceFlinger, when the state for a new physical display needs to be recreated.      void allocatePhysicalDisplay(hal::HWDisplayId, PhysicalDisplayId) override; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index dbd2793276..7523362087 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -71,7 +71,6 @@  #include "SurfaceFlinger.h"  #include "TimeStats/TimeStats.h"  #include "TunnelModeEnabledReporter.h" -#include "input/InputWindow.h"  #define DEBUG_RESIZE 0 @@ -83,6 +82,7 @@ constexpr int kDumpTableRowLength = 159;  using base::StringAppendF;  using namespace android::flag_operators;  using PresentState = frametimeline::SurfaceFrame::PresentState; +using gui::WindowInfo;  std::atomic<int32_t> Layer::sSequence{1}; @@ -90,8 +90,8 @@ Layer::Layer(const LayerCreationArgs& args)        : mFlinger(args.flinger),          mName(args.name),          mClientRef(args.client), -        mWindowType(static_cast<InputWindowInfo::Type>( -                args.metadata.getInt32(METADATA_WINDOW_TYPE, 0))) { +        mWindowType( +                static_cast<WindowInfo::Type>(args.metadata.getInt32(METADATA_WINDOW_TYPE, 0))) {      uint32_t layerFlags = 0;      if (args.flags & ISurfaceComposerClient::eHidden) layerFlags |= layer_state_t::eLayerHidden;      if (args.flags & ISurfaceComposerClient::eOpaque) layerFlags |= layer_state_t::eLayerOpaque; @@ -2006,7 +2006,7 @@ static wp<Layer> extractLayerFromBinder(const wp<IBinder>& weakBinderHandle) {      return handle->owner;  } -void Layer::setInputInfo(const InputWindowInfo& info) { +void Layer::setInputInfo(const WindowInfo& info) {      mDrawingState.inputInfo = info;      mDrawingState.touchableRegionCrop = extractLayerFromBinder(info.touchableRegionCropHandle);      mDrawingState.modified = true; @@ -2157,7 +2157,7 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet      }      if (traceFlags & SurfaceTracing::TRACE_INPUT) { -        InputWindowInfo info; +        WindowInfo info;          if (useDrawing) {              info = fillInputInfo({nullptr});          } else { @@ -2188,7 +2188,7 @@ Rect Layer::getInputBounds() const {      return getCroppedBufferSize(getDrawingState());  } -void Layer::fillInputFrameInfo(InputWindowInfo& info, const ui::Transform& toPhysicalDisplay) { +void Layer::fillInputFrameInfo(WindowInfo& info, const ui::Transform& toPhysicalDisplay) {      // Transform layer size to screen space and inset it by surface insets.      // If this is a portal window, set the touchableRegion to the layerBounds.      Rect layerBounds = info.portalToDisplayId == ADISPLAY_ID_NONE @@ -2283,7 +2283,7 @@ void Layer::fillInputFrameInfo(InputWindowInfo& info, const ui::Transform& toPhy      info.touchableRegion = inputTransform.transform(info.touchableRegion);  } -void Layer::fillTouchOcclusionMode(InputWindowInfo& info) { +void Layer::fillTouchOcclusionMode(WindowInfo& info) {      sp<Layer> p = this;      while (p != nullptr && !p->hasInputInfo()) {          p = p->mDrawingParent.promote(); @@ -2293,17 +2293,17 @@ void Layer::fillTouchOcclusionMode(InputWindowInfo& info) {      }  } -InputWindowInfo Layer::fillInputInfo(const sp<DisplayDevice>& display) { +WindowInfo Layer::fillInputInfo(const sp<DisplayDevice>& display) {      if (!hasInputInfo()) {          mDrawingState.inputInfo.name = getName();          mDrawingState.inputInfo.ownerUid = mOwnerUid;          mDrawingState.inputInfo.ownerPid = mOwnerPid; -        mDrawingState.inputInfo.inputFeatures = InputWindowInfo::Feature::NO_INPUT_CHANNEL; -        mDrawingState.inputInfo.flags = InputWindowInfo::Flag::NOT_TOUCH_MODAL; +        mDrawingState.inputInfo.inputFeatures = WindowInfo::Feature::NO_INPUT_CHANNEL; +        mDrawingState.inputInfo.flags = WindowInfo::Flag::NOT_TOUCH_MODAL;          mDrawingState.inputInfo.displayId = getLayerStack();      } -    InputWindowInfo info = mDrawingState.inputInfo; +    WindowInfo info = mDrawingState.inputInfo;      info.id = sequence;      if (info.displayId == ADISPLAY_ID_NONE) { @@ -2315,6 +2315,10 @@ InputWindowInfo Layer::fillInputInfo(const sp<DisplayDevice>& display) {      ui::Transform toPhysicalDisplay;      if (display) {          toPhysicalDisplay = display->getTransform(); +        // getOrientation() without masking can contain more-significant bits (eg. ROT_INVALID). +        static constexpr uint32_t ALL_ROTATIONS_MASK = +                ui::Transform::ROT_90 | ui::Transform::ROT_180 | ui::Transform::ROT_270; +        info.displayOrientation = toPhysicalDisplay.getOrientation() & ALL_ROTATIONS_MASK;          info.displayWidth = display->getWidth();          info.displayHeight = display->getHeight();      } @@ -2482,7 +2486,7 @@ void Layer::updateClonedInputInfo(const std::map<sp<Layer>, sp<Layer>>& clonedLa      }      // Cloned layers shouldn't handle watch outside since their z order is not determined by      // WM or the client. -    mDrawingState.inputInfo.flags &= ~InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH; +    mDrawingState.inputInfo.flags &= ~WindowInfo::Flag::WATCH_OUTSIDE_TOUCH;  }  void Layer::updateClonedRelatives(const std::map<sp<Layer>, sp<Layer>>& clonedLayersMap) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index c5cb17ffc7..d9ab0a6026 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -21,7 +21,7 @@  #include <gui/BufferQueue.h>  #include <gui/ISurfaceComposerClient.h>  #include <gui/LayerState.h> -#include <input/InputWindow.h> +#include <gui/WindowInfo.h>  #include <layerproto/LayerProtoHeader.h>  #include <math/vec4.h>  #include <renderengine/Mesh.h> @@ -186,7 +186,7 @@ public:          float cornerRadius;          int backgroundBlurRadius; -        InputWindowInfo inputInfo; +        gui::WindowInfo inputInfo;          wp<Layer> touchableRegionCrop;          // dataspace is only used by BufferStateLayer and EffectLayer @@ -690,7 +690,7 @@ public:      void writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet,                                   uint32_t traceFlags = SurfaceTracing::TRACE_ALL); -    InputWindowInfo::Type getWindowType() const { return mWindowType; } +    gui::WindowInfo::Type getWindowType() const { return mWindowType; }      bool getPrimaryDisplayOnly() const; @@ -847,9 +847,9 @@ public:      sp<IBinder> getHandle();      const std::string& getName() const { return mName; }      bool getPremultipledAlpha() const; -    void setInputInfo(const InputWindowInfo& info); +    void setInputInfo(const gui::WindowInfo& info); -    InputWindowInfo fillInputInfo(const sp<DisplayDevice>& display); +    gui::WindowInfo fillInputInfo(const sp<DisplayDevice>& display);      /**       * Returns whether this layer has an explicitly set input-info.       */ @@ -1014,7 +1014,7 @@ protected:      wp<Layer> mDrawingParent;      // Window types from WindowManager.LayoutParams -    const InputWindowInfo::Type mWindowType; +    const gui::WindowInfo::Type mWindowType;      // The owner of the layer. If created from a non system process, it will be the calling uid.      // If created from a system process, the value can be passed in. @@ -1066,10 +1066,10 @@ private:      // Fills in the touch occlusion mode of the first parent (including this layer) that      // hasInputInfo() or no-op if no such parent is found. -    void fillTouchOcclusionMode(InputWindowInfo& info); +    void fillTouchOcclusionMode(gui::WindowInfo& info); -    // Fills in the frame and transform info for the InputWindowInfo -    void fillInputFrameInfo(InputWindowInfo& info, const ui::Transform& toPhysicalDisplay); +    // Fills in the frame and transform info for the gui::WindowInfo +    void fillInputFrameInfo(gui::WindowInfo& info, const ui::Transform& toPhysicalDisplay);      bool updateFrameRateForLayerTree(bool treeHasFrameRateVote); diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp index b1db6d34a3..79f7b1f1e8 100644 --- a/services/surfaceflinger/LayerProtoHelper.cpp +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -22,6 +22,9 @@  #include "LayerProtoHelper.h"  namespace android { + +using gui::WindowInfo; +  namespace surfaceflinger {  void LayerProtoHelper::writePositionToProto(const float x, const float y, @@ -125,7 +128,7 @@ void LayerProtoHelper::writeToProto(const sp<GraphicBuffer>& buffer,  }  void LayerProtoHelper::writeToProto( -        const InputWindowInfo& inputInfo, const wp<Layer>& touchableRegionBounds, +        const WindowInfo& inputInfo, const wp<Layer>& touchableRegionBounds,          std::function<InputWindowInfoProto*()> getInputWindowInfoProto) {      if (inputInfo.token == nullptr) {          return; @@ -133,7 +136,7 @@ void LayerProtoHelper::writeToProto(      InputWindowInfoProto* proto = getInputWindowInfoProto();      proto->set_layout_params_flags(inputInfo.flags.get()); -    using U = std::underlying_type_t<InputWindowInfo::Type>; +    using U = std::underlying_type_t<WindowInfo::Type>;      // TODO(b/129481165): This static assert can be safely removed once conversion warnings      // are re-enabled.      static_assert(std::is_same_v<U, int32_t>); diff --git a/services/surfaceflinger/LayerProtoHelper.h b/services/surfaceflinger/LayerProtoHelper.h index 502238d389..187ce3d134 100644 --- a/services/surfaceflinger/LayerProtoHelper.h +++ b/services/surfaceflinger/LayerProtoHelper.h @@ -17,7 +17,7 @@  #include <layerproto/LayerProtoHeader.h>  #include <Layer.h> -#include <input/InputWindow.h> +#include <gui/WindowInfo.h>  #include <math/vec4.h>  #include <ui/GraphicBuffer.h>  #include <ui/Rect.h> @@ -40,7 +40,7 @@ public:      static void writeToProto(const ui::Transform& transform, TransformProto* transformProto);      static void writeToProto(const sp<GraphicBuffer>& buffer,                               std::function<ActiveBufferProto*()> getActiveBufferProto); -    static void writeToProto(const InputWindowInfo& inputInfo, +    static void writeToProto(const gui::WindowInfo& inputInfo,                               const wp<Layer>& touchableRegionBounds,                               std::function<InputWindowInfoProto*()> getInputWindowInfoProto);      static void writeToProto(const mat4 matrix, ColorTransformProto* colorTransformProto); diff --git a/services/surfaceflinger/MainThreadGuard.h b/services/surfaceflinger/MainThreadGuard.h new file mode 100644 index 0000000000..c1aa118492 --- /dev/null +++ b/services/surfaceflinger/MainThreadGuard.h @@ -0,0 +1,35 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <utils/Mutex.h> + +namespace android { +namespace { + +// Helps to ensure that some functions runs on SF's main thread by using the +// clang thread safety annotations. +class CAPABILITY("mutex") MainThreadGuard { +} SF_MAIN_THREAD; + +struct SCOPED_CAPABILITY MainThreadScopedGuard { +public: +    explicit MainThreadScopedGuard(MainThreadGuard& mutex) ACQUIRE(mutex) {} +    ~MainThreadScopedGuard() RELEASE() {} +}; +} // namespace +} // namespace android diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 27a1c280fb..8704c88a75 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -175,10 +175,14 @@ std::vector<sp<GraphicBuffer>> RefreshRateOverlay::SevenSegmentDrawer::drawNumbe      return buffers;  } -RefreshRateOverlay::RefreshRateOverlay(SurfaceFlinger& flinger, bool showSpinner) -      : mFlinger(flinger), mClient(new Client(&mFlinger)), mShowSpinner(showSpinner) { +RefreshRateOverlay::RefreshRateOverlay(SurfaceFlinger& flinger, uint32_t lowFps, uint32_t highFps, +                                       bool showSpinner) +      : mFlinger(flinger), +        mClient(new Client(&mFlinger)), +        mShowSpinner(showSpinner), +        mLowFps(lowFps), +        mHighFps(highFps) {      createLayer(); -    reset();  }  bool RefreshRateOverlay::createLayer() { @@ -194,7 +198,6 @@ bool RefreshRateOverlay::createLayer() {          return false;      } -    Mutex::Autolock _l(mFlinger.mStateLock);      mLayer = mClient->getLayerUser(mIBinder);      mLayer->setFrameRate(Layer::FrameRate(Fps(0.0f), Layer::FrameRateCompatibility::NoVote));      mLayer->setIsAtRoot(true); @@ -241,8 +244,11 @@ RefreshRateOverlay::getOrCreateBuffers(uint32_t fps) {  }  void RefreshRateOverlay::setViewport(ui::Size viewport) { -    Rect frame((3 * viewport.width) >> 4, viewport.height >> 5); -    frame.offsetBy(viewport.width >> 5, viewport.height >> 4); +    constexpr int32_t kMaxWidth = 1000; +    const auto width = std::min(kMaxWidth, std::min(viewport.width, viewport.height)); +    const auto height = 2 * width; +    Rect frame((3 * width) >> 4, height >> 5); +    frame.offsetBy(width >> 5, height >> 4);      layer_state_t::matrix22_t matrix;      matrix.dsdx = frame.getWidth() / static_cast<float>(SevenSegmentDrawer::getWidth()); @@ -254,6 +260,11 @@ void RefreshRateOverlay::setViewport(ui::Size viewport) {      mFlinger.mTransactionFlags.fetch_or(eTransactionMask);  } +void RefreshRateOverlay::setLayerStack(uint32_t stack) { +    mLayer->setLayerStack(stack); +    mFlinger.mTransactionFlags.fetch_or(eTransactionMask); +} +  void RefreshRateOverlay::changeRefreshRate(const Fps& fps) {      mCurrentFps = fps.getIntValue();      auto buffer = getOrCreateBuffers(*mCurrentFps)[mFrame]; @@ -279,13 +290,6 @@ void RefreshRateOverlay::onInvalidate() {      mFlinger.mTransactionFlags.fetch_or(eTransactionMask);  } -void RefreshRateOverlay::reset() { -    mBufferCache.clear(); -    const auto range = mFlinger.mRefreshRateConfigs->getSupportedRefreshRateRange(); -    mLowFps = range.min.getIntValue(); -    mHighFps = range.max.getIntValue(); -} -  } // namespace android  // TODO(b/129481165): remove the #pragma below and fix conversion issues diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h index aa8329c46a..f9baa898dc 100644 --- a/services/surfaceflinger/RefreshRateOverlay.h +++ b/services/surfaceflinger/RefreshRateOverlay.h @@ -37,12 +37,12 @@ class SurfaceFlinger;  class RefreshRateOverlay {  public: -    RefreshRateOverlay(SurfaceFlinger&, bool showSpinner); +    RefreshRateOverlay(SurfaceFlinger&, uint32_t lowFps, uint32_t highFps, bool showSpinner); +    void setLayerStack(uint32_t stack);      void setViewport(ui::Size);      void changeRefreshRate(const Fps&);      void onInvalidate(); -    void reset();  private:      class SevenSegmentDrawer { @@ -91,8 +91,8 @@ private:      const bool mShowSpinner;      // Interpolate the colors between these values. -    uint32_t mLowFps; -    uint32_t mHighFps; +    const uint32_t mLowFps; +    const uint32_t mHighFps;  };  } // namespace android diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp index 2321e2d082..2bdcaf6ad0 100644 --- a/services/surfaceflinger/Scheduler/EventThread.cpp +++ b/services/surfaceflinger/Scheduler/EventThread.cpp @@ -118,12 +118,12 @@ DisplayEventReceiver::Event makeVSync(PhysicalDisplayId displayId, nsecs_t times      return event;  } -DisplayEventReceiver::Event makeModeChanged(PhysicalDisplayId displayId, DisplayModeId modeId, -                                            nsecs_t vsyncPeriod) { +DisplayEventReceiver::Event makeModeChanged(DisplayModePtr mode) {      DisplayEventReceiver::Event event; -    event.header = {DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE, displayId, systemTime()}; -    event.modeChange.modeId = modeId.value(); -    event.modeChange.vsyncPeriod = vsyncPeriod; +    event.header = {DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE, mode->getPhysicalDisplayId(), +                    systemTime()}; +    event.modeChange.modeId = mode->getId().value(); +    event.modeChange.vsyncPeriod = mode->getVsyncPeriod();      return event;  } @@ -375,11 +375,10 @@ void EventThread::onHotplugReceived(PhysicalDisplayId displayId, bool connected)      mCondition.notify_all();  } -void EventThread::onModeChanged(PhysicalDisplayId displayId, DisplayModeId modeId, -                                nsecs_t vsyncPeriod) { +void EventThread::onModeChanged(DisplayModePtr mode) {      std::lock_guard<std::mutex> lock(mMutex); -    mPendingEvents.push_back(makeModeChanged(displayId, modeId, vsyncPeriod)); +    mPendingEvents.push_back(makeModeChanged(mode));      mCondition.notify_all();  } diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h index 1e6793f77c..9265a25b86 100644 --- a/services/surfaceflinger/Scheduler/EventThread.h +++ b/services/surfaceflinger/Scheduler/EventThread.h @@ -124,8 +124,7 @@ public:      virtual void onHotplugReceived(PhysicalDisplayId displayId, bool connected) = 0;      // called when SF changes the active mode and apps needs to be notified about the change -    virtual void onModeChanged(PhysicalDisplayId displayId, DisplayModeId modeId, -                               nsecs_t vsyncPeriod) = 0; +    virtual void onModeChanged(DisplayModePtr) = 0;      // called when SF updates the Frame Rate Override list      virtual void onFrameRateOverridesChanged(PhysicalDisplayId displayId, @@ -174,8 +173,7 @@ public:      void onHotplugReceived(PhysicalDisplayId displayId, bool connected) override; -    void onModeChanged(PhysicalDisplayId displayId, DisplayModeId modeId, -                       nsecs_t vsyncPeriod) override; +    void onModeChanged(DisplayModePtr) override;      void onFrameRateOverridesChanged(PhysicalDisplayId displayId,                                       std::vector<FrameRateOverride> overrides) override; diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index 0563795c79..84e3548b6e 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -75,10 +75,9 @@ void trace(const LayerInfo& info, LayerHistory::LayerVoteType type, int fps) {  }  } // namespace -LayerHistory::LayerHistory(const RefreshRateConfigs& refreshRateConfigs) +LayerHistory::LayerHistory()        : mTraceEnabled(traceEnabled()), mUseFrameRatePriority(useFrameRatePriority()) {      LayerInfo::setTraceEnabled(mTraceEnabled); -    LayerInfo::setRefreshRateConfigs(refreshRateConfigs);  }  LayerHistory::~LayerHistory() = default; @@ -138,7 +137,8 @@ void LayerHistory::record(Layer* layer, nsecs_t presentTime, nsecs_t now,      }  } -LayerHistory::Summary LayerHistory::summarize(nsecs_t now) { +LayerHistory::Summary LayerHistory::summarize(const RefreshRateConfigs& refreshRateConfigs, +                                              nsecs_t now) {      LayerHistory::Summary summary;      std::lock_guard lock(mLock); @@ -151,7 +151,7 @@ LayerHistory::Summary LayerHistory::summarize(nsecs_t now) {          ALOGV("%s has priority: %d %s focused", info->getName().c_str(), frameRateSelectionPriority,                layerFocused ? "" : "not"); -        const auto vote = info->getRefreshRateVote(now); +        const auto vote = info->getRefreshRateVote(refreshRateConfigs, now);          // Skip NoVote layer as those don't have any requirements          if (vote.type == LayerHistory::LayerVoteType::NoVote) {              continue; diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h index 82f6c3907b..92236f560a 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.h +++ b/services/surfaceflinger/Scheduler/LayerHistory.h @@ -42,7 +42,7 @@ class LayerHistory {  public:      using LayerVoteType = RefreshRateConfigs::LayerVoteType; -    LayerHistory(const RefreshRateConfigs&); +    LayerHistory();      ~LayerHistory();      // Layers are unregistered when the weak reference expires. @@ -67,7 +67,7 @@ public:      using Summary = std::vector<RefreshRateConfigs::LayerRequirement>;      // Rebuilds sets of active/inactive layers, and accumulates stats for active layers. -    Summary summarize(nsecs_t now); +    Summary summarize(const RefreshRateConfigs&, nsecs_t now);      void clear(); diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp index 989bf4ef19..8a45b66b60 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp @@ -34,7 +34,6 @@  namespace android::scheduler { -const RefreshRateConfigs* LayerInfo::sRefreshRateConfigs = nullptr;  bool LayerInfo::sTraceEnabled = false;  LayerInfo::LayerInfo(const std::string& name, uid_t ownerUid, @@ -184,7 +183,8 @@ std::optional<nsecs_t> LayerInfo::calculateAverageFrameTime() const {      return static_cast<nsecs_t>(averageFrameTime);  } -std::optional<Fps> LayerInfo::calculateRefreshRateIfPossible(nsecs_t now) { +std::optional<Fps> LayerInfo::calculateRefreshRateIfPossible( +        const RefreshRateConfigs& refreshRateConfigs, nsecs_t now) {      static constexpr float MARGIN = 1.0f; // 1Hz      if (!hasEnoughDataForHeuristic()) {          ALOGV("Not enough data"); @@ -196,9 +196,7 @@ std::optional<Fps> LayerInfo::calculateRefreshRateIfPossible(nsecs_t now) {          const auto refreshRate = Fps::fromPeriodNsecs(*averageFrameTime);          const bool refreshRateConsistent = mRefreshRateHistory.add(refreshRate, now);          if (refreshRateConsistent) { -            const auto knownRefreshRate = -                    sRefreshRateConfigs->findClosestKnownFrameRate(refreshRate); - +            const auto knownRefreshRate = refreshRateConfigs.findClosestKnownFrameRate(refreshRate);              // To avoid oscillation, use the last calculated refresh rate if it is              // close enough              if (std::abs(mLastRefreshRate.calculated.getValue() - refreshRate.getValue()) > @@ -220,7 +218,8 @@ std::optional<Fps> LayerInfo::calculateRefreshRateIfPossible(nsecs_t now) {                                                 : std::nullopt;  } -LayerInfo::LayerVote LayerInfo::getRefreshRateVote(nsecs_t now) { +LayerInfo::LayerVote LayerInfo::getRefreshRateVote(const RefreshRateConfigs& refreshRateConfigs, +                                                   nsecs_t now) {      if (mLayerVote.type != LayerHistory::LayerVoteType::Heuristic) {          ALOGV("%s voted %d ", mName.c_str(), static_cast<int>(mLayerVote.type));          return mLayerVote; @@ -247,7 +246,7 @@ LayerInfo::LayerVote LayerInfo::getRefreshRateVote(nsecs_t now) {          clearHistory(now);      } -    auto refreshRate = calculateRefreshRateIfPossible(now); +    auto refreshRate = calculateRefreshRateIfPossible(refreshRateConfigs, now);      if (refreshRate.has_value()) {          ALOGV("%s calculated refresh rate: %s", mName.c_str(), to_string(*refreshRate).c_str());          return {LayerHistory::LayerVoteType::Heuristic, refreshRate.value()}; diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h index 34cc3890d3..ce9783c5a9 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.h +++ b/services/surfaceflinger/Scheduler/LayerInfo.h @@ -122,10 +122,6 @@ public:      static void setTraceEnabled(bool enabled) { sTraceEnabled = enabled; } -    static void setRefreshRateConfigs(const RefreshRateConfigs& refreshRateConfigs) { -        sRefreshRateConfigs = &refreshRateConfigs; -    } -      LayerInfo(const std::string& name, uid_t ownerUid, LayerHistory::LayerVoteType defaultVote);      LayerInfo(const LayerInfo&) = delete; @@ -161,7 +157,7 @@ public:      uid_t getOwnerUid() const { return mOwnerUid; } -    LayerVote getRefreshRateVote(nsecs_t now); +    LayerVote getRefreshRateVote(const RefreshRateConfigs&, nsecs_t now);      // Return the last updated time. If the present time is farther in the future than the      // updated time, the updated time is the present time. @@ -263,7 +259,7 @@ private:      bool isFrequent(nsecs_t now) const;      bool isAnimating(nsecs_t now) const;      bool hasEnoughDataForHeuristic() const; -    std::optional<Fps> calculateRefreshRateIfPossible(nsecs_t now); +    std::optional<Fps> calculateRefreshRateIfPossible(const RefreshRateConfigs&, nsecs_t now);      std::optional<nsecs_t> calculateAverageFrameTime() const;      bool isFrameTimeValid(const FrameTimeData&) const; @@ -300,7 +296,6 @@ private:      mutable std::unordered_map<LayerHistory::LayerVoteType, std::string> mTraceTags;      // Shared for all LayerInfo instances -    static const RefreshRateConfigs* sRefreshRateConfigs;      static bool sTraceEnabled;  }; diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 0334d70bd5..c38cd68cd7 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -113,7 +113,7 @@ bool RefreshRateConfigs::isVoteAllowed(const LayerRequirement& layer,          case LayerVoteType::ExplicitExactOrMultiple:          case LayerVoteType::Heuristic:              if (mConfig.frameRateMultipleThreshold != 0 && -                refreshRate.fps.greaterThanOrEqualWithMargin( +                refreshRate.getFps().greaterThanOrEqualWithMargin(                          Fps(mConfig.frameRateMultipleThreshold)) &&                  layer.desiredRefreshRate.lessThanWithMargin(                          Fps(mConfig.frameRateMultipleThreshold / 2))) { @@ -146,8 +146,8 @@ float RefreshRateConfigs::calculateLayerScoreLocked(const LayerRequirement& laye      // If the layer wants Max, give higher score to the higher refresh rate      if (layer.vote == LayerVoteType::Max) { -        const auto ratio = -                refreshRate.fps.getValue() / mAppRequestRefreshRates.back()->fps.getValue(); +        const auto ratio = refreshRate.getFps().getValue() / +                mAppRequestRefreshRates.back()->getFps().getValue();          // use ratio^2 to get a lower score the more we get further from peak          return ratio * ratio;      } @@ -463,7 +463,7 @@ RefreshRate RefreshRateConfigs::getBestRefreshRateLocked(          }      }();      if (globalSignals.touch && explicitDefaultVoteLayers == 0 && touchBoostForExplicitExact && -        bestRefreshRate->fps.lessThanWithMargin(touchRefreshRate.fps)) { +        bestRefreshRate->getFps().lessThanWithMargin(touchRefreshRate.getFps())) {          setTouchConsidered();          ALOGV("TouchBoost - choose %s", touchRefreshRate.getName().c_str());          return touchRefreshRate; @@ -699,8 +699,7 @@ void RefreshRateConfigs::updateDisplayModes(const DisplayModes& modes,      for (const auto& mode : modes) {          const auto modeId = mode->getId();          mRefreshRates.emplace(modeId, -                              std::make_unique<RefreshRate>(modeId, mode, mode->getFps(), -                                                            RefreshRate::ConstructorTag(0))); +                              std::make_unique<RefreshRate>(mode, RefreshRate::ConstructorTag(0)));          if (modeId == currentModeId) {              mCurrentRefreshRate = mRefreshRates.at(modeId).get();          } @@ -793,7 +792,7 @@ RefreshRateConfigs::Policy RefreshRateConfigs::getDisplayManagerPolicy() const {  bool RefreshRateConfigs::isModeAllowed(DisplayModeId modeId) const {      std::lock_guard lock(mLock);      for (const RefreshRate* refreshRate : mAppRequestRefreshRates) { -        if (refreshRate->modeId == modeId) { +        if (refreshRate->getModeId() == modeId) {              return true;          }      } @@ -808,7 +807,7 @@ void RefreshRateConfigs::getSortedRefreshRateListLocked(      for (const auto& [type, refreshRate] : mRefreshRates) {          if (shouldAddRefreshRate(*refreshRate)) {              ALOGV("getSortedRefreshRateListLocked: mode %d added to list policy", -                  refreshRate->modeId.value()); +                  refreshRate->getModeId().value());              outRefreshRates->push_back(refreshRate.get());          }      } diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index dfd13953e7..4a9a1fd9fc 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -64,25 +64,23 @@ public:          };      public: -        RefreshRate(DisplayModeId modeId, DisplayModePtr mode, Fps fps, ConstructorTag) -              : modeId(modeId), mode(mode), fps(std::move(fps)) {} +        RefreshRate(DisplayModePtr mode, ConstructorTag) : mode(mode) {} -        DisplayModeId getModeId() const { return modeId; } +        DisplayModeId getModeId() const { return mode->getId(); }          nsecs_t getVsyncPeriod() const { return mode->getVsyncPeriod(); }          int32_t getModeGroup() const { return mode->getGroup(); } -        std::string getName() const { return to_string(fps); } -        Fps getFps() const { return fps; } +        std::string getName() const { return to_string(getFps()); } +        Fps getFps() const { return mode->getFps(); } +        DisplayModePtr getMode() const { return mode; }          // Checks whether the fps of this RefreshRate struct is within a given min and max refresh          // rate passed in. Margin of error is applied to the boundaries for approximation.          bool inPolicy(Fps minRefreshRate, Fps maxRefreshRate) const { -            return minRefreshRate.lessThanOrEqualWithMargin(fps) && -                    fps.lessThanOrEqualWithMargin(maxRefreshRate); +            return minRefreshRate.lessThanOrEqualWithMargin(getFps()) && +                    getFps().lessThanOrEqualWithMargin(maxRefreshRate);          } -        bool operator!=(const RefreshRate& other) const { -            return modeId != other.modeId || mode != other.mode; -        } +        bool operator!=(const RefreshRate& other) const { return mode != other.mode; }          bool operator<(const RefreshRate& other) const {              return getFps().getValue() < other.getFps().getValue(); @@ -99,10 +97,7 @@ public:          friend RefreshRateConfigs;          friend class RefreshRateConfigsTest; -        const DisplayModeId modeId;          DisplayModePtr mode; -        // Refresh rate in frames per second -        const Fps fps{0.0f};      };      using AllRefreshRatesMapType = @@ -316,8 +311,6 @@ public:                         Config config = {.enableFrameRateOverride = false,                                          .frameRateMultipleThreshold = 0}); -    void updateDisplayModes(const DisplayModes& mode, DisplayModeId currentModeId) EXCLUDES(mLock); -      // Returns whether switching modes (refresh rate or resolution) is possible.      // TODO(b/158780872): Consider HAL support, and skip frame rate detection if the modes only      // differ in resolution. @@ -354,6 +347,9 @@ public:      void dump(std::string& result) const EXCLUDES(mLock); +    RefreshRateConfigs(const RefreshRateConfigs&) = delete; +    void operator=(const RefreshRateConfigs&) = delete; +  private:      friend class RefreshRateConfigsTest; @@ -405,6 +401,8 @@ private:      float calculateLayerScoreLocked(const LayerRequirement&, const RefreshRate&,                                      bool isSeamlessSwitch) const REQUIRES(mLock); +    void updateDisplayModes(const DisplayModes& mode, DisplayModeId currentModeId) EXCLUDES(mLock); +      // The list of refresh rates, indexed by display modes ID. This may change after this      // object is initialized.      AllRefreshRatesMapType mRefreshRates GUARDED_BY(mLock); diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index e0b364020b..f808981d0f 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -25,7 +25,7 @@  #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>  #include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>  #include <configstore/Utils.h> -#include <input/InputWindow.h> +#include <gui/WindowInfo.h>  #include <system/window.h>  #include <ui/DisplayStatInfo.h>  #include <utils/Timers.h> @@ -64,6 +64,8 @@ using namespace std::string_literals;  namespace android { +using gui::WindowInfo; +  namespace {  std::unique_ptr<scheduler::VSyncTracker> createVSyncTracker() { @@ -115,16 +117,17 @@ private:      }  }; -Scheduler::Scheduler(const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback) +Scheduler::Scheduler(const std::shared_ptr<scheduler::RefreshRateConfigs>& configs, +                     ISchedulerCallback& callback)        : Scheduler(configs, callback,                    {.supportKernelTimer = sysprop::support_kernel_idle_timer(false),                     .useContentDetection = sysprop::use_content_detection_for_refresh_rate(false)}) {  } -Scheduler::Scheduler(const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback, -                     Options options) +Scheduler::Scheduler(const std::shared_ptr<scheduler::RefreshRateConfigs>& configs, +                     ISchedulerCallback& callback, Options options)        : Scheduler(createVsyncSchedule(options.supportKernelTimer), configs, callback, -                  createLayerHistory(configs), options) { +                  createLayerHistory(), options) {      using namespace sysprop;      const int setIdleTimerMs = base::GetIntProperty("debug.sf.set_idle_timer_ms"s, 0); @@ -157,7 +160,8 @@ Scheduler::Scheduler(const scheduler::RefreshRateConfigs& configs, ISchedulerCal      }  } -Scheduler::Scheduler(VsyncSchedule schedule, const scheduler::RefreshRateConfigs& configs, +Scheduler::Scheduler(VsyncSchedule schedule, +                     const std::shared_ptr<scheduler::RefreshRateConfigs>& configs,                       ISchedulerCallback& schedulerCallback,                       std::unique_ptr<LayerHistory> layerHistory, Options options)        : mOptions(options), @@ -192,9 +196,8 @@ Scheduler::VsyncSchedule Scheduler::createVsyncSchedule(bool supportKernelTimer)      return {std::move(controller), std::move(tracker), std::move(dispatch)};  } -std::unique_ptr<LayerHistory> Scheduler::createLayerHistory( -        const scheduler::RefreshRateConfigs& configs) { -    return std::make_unique<scheduler::LayerHistory>(configs); +std::unique_ptr<LayerHistory> Scheduler::createLayerHistory() { +    return std::make_unique<scheduler::LayerHistory>();  }  std::unique_ptr<VSyncSource> Scheduler::makePrimaryDispSyncSource( @@ -205,11 +208,14 @@ std::unique_ptr<VSyncSource> Scheduler::makePrimaryDispSyncSource(  }  std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const { -    if (!mRefreshRateConfigs.supportsFrameRateOverride()) { -        return std::nullopt; +    { +        std::scoped_lock lock(mRefreshRateConfigsLock); +        if (!mRefreshRateConfigs->supportsFrameRateOverride()) { +            return std::nullopt; +        }      } -    std::lock_guard lock(mFrameRateOverridesMutex); +    std::lock_guard lock(mFrameRateOverridesLock);      {          const auto iter = mFrameRateOverridesFromBackdoor.find(uid);          if (iter != mFrameRateOverridesFromBackdoor.end()) { @@ -237,7 +243,8 @@ bool Scheduler::isVsyncValid(nsecs_t expectedVsyncTimestamp, uid_t uid) const {  }  impl::EventThread::ThrottleVsyncCallback Scheduler::makeThrottleVsyncCallback() const { -    if (!mRefreshRateConfigs.supportsFrameRateOverride()) { +    std::scoped_lock lock(mRefreshRateConfigsLock); +    if (!mRefreshRateConfigs->supportsFrameRateOverride()) {          return {};      } @@ -248,14 +255,18 @@ impl::EventThread::ThrottleVsyncCallback Scheduler::makeThrottleVsyncCallback()  impl::EventThread::GetVsyncPeriodFunction Scheduler::makeGetVsyncPeriodFunction() const {      return [this](uid_t uid) { -        nsecs_t basePeriod = mRefreshRateConfigs.getCurrentRefreshRate().getVsyncPeriod(); +        const auto refreshRateConfigs = holdRefreshRateConfigs(); +        nsecs_t basePeriod = refreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();          const auto frameRate = getFrameRateOverride(uid);          if (!frameRate.has_value()) {              return basePeriod;          } -        const auto divider = scheduler::RefreshRateConfigs::getFrameRateDivider( -            mRefreshRateConfigs.getCurrentRefreshRate().getFps(), *frameRate); +        const auto divider = +                scheduler::RefreshRateConfigs::getFrameRateDivider(refreshRateConfigs +                                                                           ->getCurrentRefreshRate() +                                                                           .getFps(), +                                                                   *frameRate);          if (divider <= 1) {              return basePeriod;          } @@ -341,7 +352,7 @@ void Scheduler::onScreenReleased(ConnectionHandle handle) {  void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDisplayId displayId) {      std::vector<FrameRateOverride> overrides;      { -        std::lock_guard lock(mFrameRateOverridesMutex); +        std::lock_guard lock(mFrameRateOverridesLock);          for (const auto& [uid, frameRate] : mFrameRateOverridesFromBackdoor) {              overrides.emplace_back(FrameRateOverride{uid, frameRate.getValue()});          } @@ -360,23 +371,22 @@ void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDis      thread->onFrameRateOverridesChanged(displayId, std::move(overrides));  } -void Scheduler::onPrimaryDisplayModeChanged(ConnectionHandle handle, PhysicalDisplayId displayId, -                                            DisplayModeId modeId, nsecs_t vsyncPeriod) { +void Scheduler::onPrimaryDisplayModeChanged(ConnectionHandle handle, DisplayModePtr mode) {      {          std::lock_guard<std::mutex> lock(mFeatureStateLock);          // Cache the last reported modes for primary display. -        mFeatures.cachedModeChangedParams = {handle, displayId, modeId, vsyncPeriod}; +        mFeatures.cachedModeChangedParams = {handle, mode};          // Invalidate content based refresh rate selection so it could be calculated          // again for the new refresh rate.          mFeatures.contentRequirements.clear();      } -    onNonPrimaryDisplayModeChanged(handle, displayId, modeId, vsyncPeriod); +    onNonPrimaryDisplayModeChanged(handle, mode);  }  void Scheduler::dispatchCachedReportedMode() {      // Check optional fields first. -    if (!mFeatures.modeId.has_value()) { +    if (!mFeatures.mode) {          ALOGW("No mode ID found, not dispatching cached mode.");          return;      } @@ -385,32 +395,24 @@ void Scheduler::dispatchCachedReportedMode() {          return;      } -    const auto modeId = *mFeatures.modeId; -    const auto vsyncPeriod = mRefreshRateConfigs.getRefreshRateFromModeId(modeId).getVsyncPeriod(); -      // If there is no change from cached mode, there is no need to dispatch an event -    if (modeId == mFeatures.cachedModeChangedParams->modeId && -        vsyncPeriod == mFeatures.cachedModeChangedParams->vsyncPeriod) { +    if (mFeatures.mode == mFeatures.cachedModeChangedParams->mode) {          return;      } -    mFeatures.cachedModeChangedParams->modeId = modeId; -    mFeatures.cachedModeChangedParams->vsyncPeriod = vsyncPeriod; +    mFeatures.cachedModeChangedParams->mode = mFeatures.mode;      onNonPrimaryDisplayModeChanged(mFeatures.cachedModeChangedParams->handle, -                                   mFeatures.cachedModeChangedParams->displayId, -                                   mFeatures.cachedModeChangedParams->modeId, -                                   mFeatures.cachedModeChangedParams->vsyncPeriod); +                                   mFeatures.cachedModeChangedParams->mode);  } -void Scheduler::onNonPrimaryDisplayModeChanged(ConnectionHandle handle, PhysicalDisplayId displayId, -                                               DisplayModeId modeId, nsecs_t vsyncPeriod) { +void Scheduler::onNonPrimaryDisplayModeChanged(ConnectionHandle handle, DisplayModePtr mode) {      android::EventThread* thread;      {          std::lock_guard<std::mutex> lock(mConnectionsLock);          RETURN_IF_INVALID_HANDLE(handle);          thread = mConnections[handle].thread.get();      } -    thread->onModeChanged(displayId, modeId, vsyncPeriod); +    thread->onModeChanged(mode);  }  size_t Scheduler::getEventThreadConnectionCount(ConnectionHandle handle) { @@ -530,7 +532,11 @@ void Scheduler::resync() {      const nsecs_t last = mLastResyncTime.exchange(now);      if (now - last > kIgnoreDelay) { -        resyncToHardwareVsync(false, mRefreshRateConfigs.getCurrentRefreshRate().getVsyncPeriod()); +        const auto vsyncPeriod = [&] { +            std::scoped_lock lock(mRefreshRateConfigsLock); +            return mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod(); +        }(); +        resyncToHardwareVsync(false, vsyncPeriod);      }  } @@ -579,10 +585,9 @@ void Scheduler::setIgnorePresentFences(bool ignore) {  void Scheduler::registerLayer(Layer* layer) {      scheduler::LayerHistory::LayerVoteType voteType; -    if (!mOptions.useContentDetection || -        layer->getWindowType() == InputWindowInfo::Type::STATUS_BAR) { +    if (!mOptions.useContentDetection || layer->getWindowType() == WindowInfo::Type::STATUS_BAR) {          voteType = scheduler::LayerHistory::LayerVoteType::NoVote; -    } else if (layer->getWindowType() == InputWindowInfo::Type::WALLPAPER) { +    } else if (layer->getWindowType() == WindowInfo::Type::WALLPAPER) {          // Running Wallpaper at Min is considered as part of content detection.          voteType = scheduler::LayerHistory::LayerVoteType::Min;      } else { @@ -601,9 +606,12 @@ void Scheduler::deregisterLayer(Layer* layer) {  void Scheduler::recordLayerHistory(Layer* layer, nsecs_t presentTime,                                     LayerHistory::LayerUpdateType updateType) { -    if (mRefreshRateConfigs.canSwitch()) { -        mLayerHistory->record(layer, presentTime, systemTime(), updateType); +    { +        std::scoped_lock lock(mRefreshRateConfigsLock); +        if (!mRefreshRateConfigs->canSwitch()) return;      } + +    mLayerHistory->record(layer, presentTime, systemTime(), updateType);  }  void Scheduler::setModeChangePending(bool pending) { @@ -611,25 +619,28 @@ void Scheduler::setModeChangePending(bool pending) {  }  void Scheduler::chooseRefreshRateForContent() { -    if (!mRefreshRateConfigs.canSwitch()) return; +    { +        std::scoped_lock lock(mRefreshRateConfigsLock); +        if (!mRefreshRateConfigs->canSwitch()) return; +    }      ATRACE_CALL(); -    scheduler::LayerHistory::Summary summary = mLayerHistory->summarize(systemTime()); +    const auto refreshRateConfigs = holdRefreshRateConfigs(); +    scheduler::LayerHistory::Summary summary = +            mLayerHistory->summarize(*refreshRateConfigs, systemTime());      scheduler::RefreshRateConfigs::GlobalSignals consideredSignals; -    DisplayModeId newModeId; +    DisplayModePtr newMode;      bool frameRateChanged;      bool frameRateOverridesChanged;      {          std::lock_guard<std::mutex> lock(mFeatureStateLock);          mFeatures.contentRequirements = summary; -        newModeId = calculateRefreshRateModeId(&consideredSignals); -        auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromModeId(newModeId); -        frameRateOverridesChanged = -                updateFrameRateOverrides(consideredSignals, newRefreshRate.getFps()); +        newMode = calculateRefreshRateModeId(&consideredSignals); +        frameRateOverridesChanged = updateFrameRateOverrides(consideredSignals, newMode->getFps()); -        if (mFeatures.modeId == newModeId) { +        if (mFeatures.mode == newMode) {              // We don't need to change the display mode, but we might need to send an event              // about a mode change, since it was suppressed due to a previous idleConsidered              if (!consideredSignals.idle) { @@ -637,12 +648,12 @@ void Scheduler::chooseRefreshRateForContent() {              }              frameRateChanged = false;          } else { -            mFeatures.modeId = newModeId; +            mFeatures.mode = newMode;              frameRateChanged = true;          }      }      if (frameRateChanged) { -        auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromModeId(newModeId); +        auto newRefreshRate = refreshRateConfigs->getRefreshRateFromModeId(newMode->getId());          mSchedulerCallback.changeRefreshRate(newRefreshRate,                                               consideredSignals.idle ? ModeEvent::None                                                                      : ModeEvent::Changed); @@ -688,7 +699,11 @@ void Scheduler::kernelIdleTimerCallback(TimerState state) {      // TODO(145561154): cleanup the kernel idle timer implementation and the refresh rate      // magic number -    const auto& refreshRate = mRefreshRateConfigs.getCurrentRefreshRate(); +    const auto refreshRate = [&] { +        std::scoped_lock lock(mRefreshRateConfigsLock); +        return mRefreshRateConfigs->getCurrentRefreshRate(); +    }(); +      constexpr Fps FPS_THRESHOLD_FOR_KERNEL_TIMER{65.0f};      if (state == TimerState::Reset &&          refreshRate.getFps().greaterThanWithMargin(FPS_THRESHOLD_FOR_KERNEL_TIMER)) { @@ -740,7 +755,7 @@ void Scheduler::dump(std::string& result) const {                    mLayerHistory ? mLayerHistory->dump().c_str() : "(no layer history)");      { -        std::lock_guard lock(mFrameRateOverridesMutex); +        std::lock_guard lock(mFrameRateOverridesLock);          StringAppendF(&result, "Frame Rate Overrides (backdoor): {");          for (const auto& [uid, frameRate] : mFrameRateOverridesFromBackdoor) {              StringAppendF(&result, "[uid: %d frameRate: %s], ", uid, to_string(frameRate).c_str()); @@ -766,16 +781,17 @@ void Scheduler::dumpVsync(std::string& s) const {  bool Scheduler::updateFrameRateOverrides(          scheduler::RefreshRateConfigs::GlobalSignals consideredSignals, Fps displayRefreshRate) { -    if (!mRefreshRateConfigs.supportsFrameRateOverride()) { +    const auto refreshRateConfigs = holdRefreshRateConfigs(); +    if (!refreshRateConfigs->supportsFrameRateOverride()) {          return false;      }      if (!consideredSignals.idle) {          const auto frameRateOverrides = -                mRefreshRateConfigs.getFrameRateOverrides(mFeatures.contentRequirements, +                refreshRateConfigs->getFrameRateOverrides(mFeatures.contentRequirements,                                                            displayRefreshRate,                                                            consideredSignals.touch); -        std::lock_guard lock(mFrameRateOverridesMutex); +        std::lock_guard lock(mFrameRateOverridesLock);          if (!std::equal(mFrameRateOverridesByContent.begin(), mFrameRateOverridesByContent.end(),                          frameRateOverrides.begin(), frameRateOverrides.end(),                          [](const std::pair<uid_t, Fps>& a, const std::pair<uid_t, Fps>& b) { @@ -790,33 +806,33 @@ bool Scheduler::updateFrameRateOverrides(  template <class T>  bool Scheduler::handleTimerStateChanged(T* currentState, T newState) { -    DisplayModeId newModeId; +    DisplayModePtr newMode;      bool refreshRateChanged = false;      bool frameRateOverridesChanged;      scheduler::RefreshRateConfigs::GlobalSignals consideredSignals; +    const auto refreshRateConfigs = holdRefreshRateConfigs();      {          std::lock_guard<std::mutex> lock(mFeatureStateLock);          if (*currentState == newState) {              return false;          }          *currentState = newState; -        newModeId = calculateRefreshRateModeId(&consideredSignals); -        const RefreshRate& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromModeId(newModeId); -        frameRateOverridesChanged = -                updateFrameRateOverrides(consideredSignals, newRefreshRate.getFps()); -        if (mFeatures.modeId == newModeId) { +        newMode = calculateRefreshRateModeId(&consideredSignals); +        frameRateOverridesChanged = updateFrameRateOverrides(consideredSignals, newMode->getFps()); +        if (mFeatures.mode == newMode) {              // We don't need to change the display mode, but we might need to send an event              // about a mode change, since it was suppressed due to a previous idleConsidered              if (!consideredSignals.idle) {                  dispatchCachedReportedMode();              }          } else { -            mFeatures.modeId = newModeId; +            mFeatures.mode = newMode;              refreshRateChanged = true;          }      }      if (refreshRateChanged) { -        const RefreshRate& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromModeId(newModeId); +        const RefreshRate& newRefreshRate = +                refreshRateConfigs->getRefreshRateFromModeId(newMode->getId());          mSchedulerCallback.changeRefreshRate(newRefreshRate,                                               consideredSignals.idle ? ModeEvent::None @@ -828,35 +844,36 @@ bool Scheduler::handleTimerStateChanged(T* currentState, T newState) {      return consideredSignals.touch;  } -DisplayModeId Scheduler::calculateRefreshRateModeId( +DisplayModePtr Scheduler::calculateRefreshRateModeId(          scheduler::RefreshRateConfigs::GlobalSignals* consideredSignals) {      ATRACE_CALL();      if (consideredSignals) *consideredSignals = {}; +    const auto refreshRateConfigs = holdRefreshRateConfigs();      // If Display Power is not in normal operation we want to be in performance mode. When coming      // back to normal mode, a grace period is given with DisplayPowerTimer.      if (mDisplayPowerTimer &&          (!mFeatures.isDisplayPowerStateNormal ||           mFeatures.displayPowerTimer == TimerState::Reset)) { -        return mRefreshRateConfigs.getMaxRefreshRateByPolicy().getModeId(); +        return refreshRateConfigs->getMaxRefreshRateByPolicy().getMode();      }      const bool touchActive = mTouchTimer && mFeatures.touch == TouchState::Active;      const bool idle = mIdleTimer && mFeatures.idleTimer == TimerState::Expired; -    return mRefreshRateConfigs -            .getBestRefreshRate(mFeatures.contentRequirements, {.touch = touchActive, .idle = idle}, -                                consideredSignals) -            .getModeId(); +    return refreshRateConfigs +            ->getBestRefreshRate(mFeatures.contentRequirements, +                                 {.touch = touchActive, .idle = idle}, consideredSignals) +            .getMode();  } -std::optional<DisplayModeId> Scheduler::getPreferredModeId() { +DisplayModePtr Scheduler::getPreferredDisplayMode() {      std::lock_guard<std::mutex> lock(mFeatureStateLock);      // Make sure that the default mode ID is first updated, before returned. -    if (mFeatures.modeId.has_value()) { -        mFeatures.modeId = calculateRefreshRateModeId(); +    if (mFeatures.mode) { +        mFeatures.mode = calculateRefreshRateModeId();      } -    return mFeatures.modeId; +    return mFeatures.mode;  }  void Scheduler::onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline) { @@ -892,7 +909,7 @@ void Scheduler::onDisplayRefreshed(nsecs_t timestamp) {      }  } -void Scheduler::onPrimaryDisplayAreaChanged(uint32_t displayArea) { +void Scheduler::onActiveDisplayAreaChanged(uint32_t displayArea) {      mLayerHistory->setDisplayArea(displayArea);  } @@ -901,7 +918,7 @@ void Scheduler::setPreferredRefreshRateForUid(FrameRateOverride frameRateOverrid          return;      } -    std::lock_guard lock(mFrameRateOverridesMutex); +    std::lock_guard lock(mFrameRateOverridesLock);      if (frameRateOverride.frameRateHz != 0.f) {          mFrameRateOverridesFromBackdoor[frameRateOverride.uid] = Fps(frameRateOverride.frameRateHz);      } else { diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 30a32537ad..4b6905bc6d 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -72,7 +72,7 @@ public:      using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate;      using ModeEvent = scheduler::RefreshRateConfigEvent; -    Scheduler(const scheduler::RefreshRateConfigs&, ISchedulerCallback&); +    Scheduler(const std::shared_ptr<scheduler::RefreshRateConfigs>&, ISchedulerCallback&);      ~Scheduler();      using ConnectionHandle = scheduler::ConnectionHandle; @@ -87,15 +87,13 @@ public:      sp<EventThreadConnection> getEventConnection(ConnectionHandle);      void onHotplugReceived(ConnectionHandle, PhysicalDisplayId, bool connected); -    void onPrimaryDisplayModeChanged(ConnectionHandle, PhysicalDisplayId, DisplayModeId, -                                     nsecs_t vsyncPeriod) EXCLUDES(mFeatureStateLock); -    void onNonPrimaryDisplayModeChanged(ConnectionHandle, PhysicalDisplayId, DisplayModeId, -                                        nsecs_t vsyncPeriod); +    void onPrimaryDisplayModeChanged(ConnectionHandle, DisplayModePtr) EXCLUDES(mFeatureStateLock); +    void onNonPrimaryDisplayModeChanged(ConnectionHandle, DisplayModePtr);      void onScreenAcquired(ConnectionHandle);      void onScreenReleased(ConnectionHandle);      void onFrameRateOverridesChanged(ConnectionHandle, PhysicalDisplayId) -            EXCLUDES(mFrameRateOverridesMutex) EXCLUDES(mConnectionsLock); +            EXCLUDES(mFrameRateOverridesLock) EXCLUDES(mConnectionsLock);      // Modifies work duration in the event thread.      void setDuration(ConnectionHandle, std::chrono::nanoseconds workDuration, @@ -116,7 +114,7 @@ public:      // no-op.      // The period is the vsync period from the current display configuration.      void resyncToHardwareVsync(bool makeAvailable, nsecs_t period); -    void resync(); +    void resync() EXCLUDES(mRefreshRateConfigsLock);      // Passes a vsync sample to VsyncController. periodFlushed will be true if      // VsyncController detected that the vsync period changed, and false otherwise. @@ -127,12 +125,13 @@ public:      // Layers are registered on creation, and unregistered when the weak reference expires.      void registerLayer(Layer*); -    void recordLayerHistory(Layer*, nsecs_t presentTime, LayerHistory::LayerUpdateType updateType); +    void recordLayerHistory(Layer*, nsecs_t presentTime, LayerHistory::LayerUpdateType updateType) +            EXCLUDES(mRefreshRateConfigsLock);      void setModeChangePending(bool pending);      void deregisterLayer(Layer*);      // Detects content using layer history, and selects a matching refresh rate. -    void chooseRefreshRateForContent(); +    void chooseRefreshRateForContent() EXCLUDES(mRefreshRateConfigsLock);      bool isIdleTimerEnabled() const { return mIdleTimer.has_value(); }      void resetIdleTimer(); @@ -147,7 +146,7 @@ public:      // Returns true if a given vsync timestamp is considered valid vsync      // for a given uid      bool isVsyncValid(nsecs_t expectedVsyncTimestamp, uid_t uid) const -            EXCLUDES(mFrameRateOverridesMutex); +            EXCLUDES(mFrameRateOverridesLock);      std::chrono::steady_clock::time_point getPreviousVsyncFrom(nsecs_t expectedPresentTime) const; @@ -156,7 +155,7 @@ public:      void dumpVsync(std::string&) const;      // Get the appropriate refresh for current conditions. -    std::optional<DisplayModeId> getPreferredModeId(); +    DisplayModePtr getPreferredDisplayMode();      // Notifies the scheduler about a refresh rate timeline change.      void onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline); @@ -165,7 +164,7 @@ public:      void onDisplayRefreshed(nsecs_t timestamp);      // Notifies the scheduler when the display size has changed. Called from SF's main thread -    void onPrimaryDisplayAreaChanged(uint32_t displayArea); +    void onActiveDisplayAreaChanged(uint32_t displayArea);      size_t getEventThreadConnectionCount(ConnectionHandle handle); @@ -176,9 +175,21 @@ public:      // Stores the preferred refresh rate that an app should run at.      // FrameRateOverride.refreshRateHz == 0 means no preference. -    void setPreferredRefreshRateForUid(FrameRateOverride) EXCLUDES(mFrameRateOverridesMutex); +    void setPreferredRefreshRateForUid(FrameRateOverride) EXCLUDES(mFrameRateOverridesLock);      // Retrieves the overridden refresh rate for a given uid. -    std::optional<Fps> getFrameRateOverride(uid_t uid) const EXCLUDES(mFrameRateOverridesMutex); +    std::optional<Fps> getFrameRateOverride(uid_t uid) const +            EXCLUDES(mRefreshRateConfigsLock, mFrameRateOverridesLock); + +    void setRefreshRateConfigs(std::shared_ptr<scheduler::RefreshRateConfigs> refreshRateConfigs) +            EXCLUDES(mRefreshRateConfigsLock) { +        std::scoped_lock lock(mRefreshRateConfigsLock); +        mRefreshRateConfigs = std::move(refreshRateConfigs); +    } + +    nsecs_t getVsyncPeriodFromRefreshRateConfigs() const EXCLUDES(mRefreshRateConfigsLock) { +        std::scoped_lock lock(mRefreshRateConfigsLock); +        return mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod(); +    }  private:      friend class TestableScheduler; @@ -203,14 +214,14 @@ private:      };      // Unlike the testing constructor, this creates the VsyncSchedule, LayerHistory, and timers. -    Scheduler(const scheduler::RefreshRateConfigs&, ISchedulerCallback&, Options); +    Scheduler(const std::shared_ptr<scheduler::RefreshRateConfigs>&, ISchedulerCallback&, Options);      // Used by tests to inject mocks. -    Scheduler(VsyncSchedule, const scheduler::RefreshRateConfigs&, ISchedulerCallback&, -              std::unique_ptr<LayerHistory>, Options); +    Scheduler(VsyncSchedule, const std::shared_ptr<scheduler::RefreshRateConfigs>&, +              ISchedulerCallback&, std::unique_ptr<LayerHistory>, Options);      static VsyncSchedule createVsyncSchedule(bool supportKernelIdleTimer); -    static std::unique_ptr<LayerHistory> createLayerHistory(const scheduler::RefreshRateConfigs&); +    static std::unique_ptr<LayerHistory> createLayerHistory();      // Create a connection on the given EventThread.      ConnectionHandle createConnection(std::unique_ptr<EventThread>); @@ -218,7 +229,7 @@ private:              EventThread*, ISurfaceComposer::EventRegistrationFlags eventRegistration = {});      // Update feature state machine to given state when corresponding timer resets or expires. -    void kernelIdleTimerCallback(TimerState); +    void kernelIdleTimerCallback(TimerState) EXCLUDES(mRefreshRateConfigsLock);      void idleTimerCallback(TimerState);      void touchTimerCallback(TimerState);      void displayPowerTimerCallback(TimerState); @@ -232,18 +243,25 @@ private:      // This function checks whether individual features that are affecting the refresh rate      // selection were initialized, prioritizes them, and calculates the DisplayModeId      // for the suggested refresh rate. -    DisplayModeId calculateRefreshRateModeId( +    DisplayModePtr calculateRefreshRateModeId(              scheduler::RefreshRateConfigs::GlobalSignals* consideredSignals = nullptr)              REQUIRES(mFeatureStateLock); -    void dispatchCachedReportedMode() REQUIRES(mFeatureStateLock); +    void dispatchCachedReportedMode() REQUIRES(mFeatureStateLock) EXCLUDES(mRefreshRateConfigsLock);      bool updateFrameRateOverrides(scheduler::RefreshRateConfigs::GlobalSignals consideredSignals,                                    Fps displayRefreshRate) REQUIRES(mFeatureStateLock) -            EXCLUDES(mFrameRateOverridesMutex); +            EXCLUDES(mFrameRateOverridesLock); -    impl::EventThread::ThrottleVsyncCallback makeThrottleVsyncCallback() const; +    impl::EventThread::ThrottleVsyncCallback makeThrottleVsyncCallback() const +            EXCLUDES(mRefreshRateConfigsLock);      impl::EventThread::GetVsyncPeriodFunction makeGetVsyncPeriodFunction() const; +    std::shared_ptr<scheduler::RefreshRateConfigs> holdRefreshRateConfigs() const +            EXCLUDES(mRefreshRateConfigsLock) { +        std::scoped_lock lock(mRefreshRateConfigsLock); +        return mRefreshRateConfigs; +    } +      // Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection.      struct Connection {          sp<EventThreadConnection> connection; @@ -288,7 +306,7 @@ private:          TouchState touch = TouchState::Inactive;          TimerState displayPowerTimer = TimerState::Expired; -        std::optional<DisplayModeId> modeId; +        DisplayModePtr mode;          LayerHistory::Summary contentRequirements;          bool isDisplayPowerStateNormal = true; @@ -296,15 +314,15 @@ private:          // Used to cache the last parameters of onPrimaryDisplayModeChanged          struct ModeChangedParams {              ConnectionHandle handle; -            PhysicalDisplayId displayId; -            DisplayModeId modeId; -            nsecs_t vsyncPeriod; +            DisplayModePtr mode;          };          std::optional<ModeChangedParams> cachedModeChangedParams;      } mFeatures GUARDED_BY(mFeatureStateLock); -    const scheduler::RefreshRateConfigs& mRefreshRateConfigs; +    mutable std::mutex mRefreshRateConfigsLock; +    std::shared_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs +            GUARDED_BY(mRefreshRateConfigsLock);      std::mutex mVsyncTimelineLock;      std::optional<hal::VsyncPeriodChangeTimeline> mLastVsyncPeriodChangeTimeline @@ -315,14 +333,14 @@ private:      // The frame rate override lists need their own mutex as they are being read      // by SurfaceFlinger, Scheduler and EventThread (as a callback) to prevent deadlocks -    mutable std::mutex mFrameRateOverridesMutex; +    mutable std::mutex mFrameRateOverridesLock;      // mappings between a UID and a preferred refresh rate that this app would      // run at.      scheduler::RefreshRateConfigs::UidToFrameRateOverride mFrameRateOverridesByContent -            GUARDED_BY(mFrameRateOverridesMutex); +            GUARDED_BY(mFrameRateOverridesLock);      scheduler::RefreshRateConfigs::UidToFrameRateOverride mFrameRateOverridesFromBackdoor -            GUARDED_BY(mFrameRateOverridesMutex); +            GUARDED_BY(mFrameRateOverridesLock);  };  } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 230810c936..a2e7ccb465 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -133,6 +133,7 @@  #include "SurfaceInterceptor.h"  #include "TimeStats/TimeStats.h"  #include "TunnelModeEnabledReporter.h" +#include "WindowInfosListenerInvoker.h"  #include "android-base/parseint.h"  #include "android-base/stringprintf.h"  #include "android-base/strings.h" @@ -146,6 +147,13 @@          return (expr);                                             \      }() +#define MAIN_THREAD_GUARD(expr)                                    \ +    [&] {                                                          \ +        LOG_FATAL_IF(std::this_thread::get_id() != mMainThreadId); \ +        MainThreadScopedGuard lock(SF_MAIN_THREAD);                \ +        return (expr);                                             \ +    }() +  #undef NO_THREAD_SAFETY_ANALYSIS  #define NO_THREAD_SAFETY_ANALYSIS \      _Pragma("GCC error \"Prefer MAIN_THREAD macros or {Conditional,Timed,Unnecessary}Lock.\"") @@ -160,6 +168,8 @@ using namespace android::sysprop;  using android::hardware::power::Boost;  using base::StringAppendF; +using gui::IWindowInfosListener; +using gui::WindowInfo;  using ui::ColorMode;  using ui::Dataspace;  using ui::DisplayPrimaries; @@ -347,7 +357,8 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag)          mTunnelModeEnabledReporter(new TunnelModeEnabledReporter()),          mInternalDisplayDensity(getDensityFromProperty("ro.sf.lcd_density", true)),          mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)), -        mPowerAdvisor(*this) { +        mPowerAdvisor(*this), +        mWindowInfosListenerInvoker(new WindowInfosListenerInvoker()) {      ALOGI("Using HWComposer service: %s", mHwcServiceName.c_str());      mSetInputWindowsListener = new SetInputWindowsListener([&]() { setInputWindowsFinished(); }); @@ -590,19 +601,11 @@ void SurfaceFlinger::enableHalVirtualDisplays(bool enable) {      }  } -VirtualDisplayId SurfaceFlinger::acquireVirtualDisplay(ui::Size resolution, ui::PixelFormat format, -                                                       ui::LayerStack layerStack) { +VirtualDisplayId SurfaceFlinger::acquireVirtualDisplay(ui::Size resolution, +                                                       ui::PixelFormat format) {      if (auto& generator = mVirtualDisplayIdGenerators.hal) {          if (const auto id = generator->generateId()) { -            std::optional<PhysicalDisplayId> mirror; - -            if (const auto display = findDisplay([layerStack](const auto& display) { -                    return !display.isVirtual() && display.getLayerStack() == layerStack; -                })) { -                mirror = display->getPhysicalId(); -            } - -            if (getHwComposer().allocateVirtualDisplay(*id, resolution, &format, mirror)) { +            if (getHwComposer().allocateVirtualDisplay(*id, resolution, &format)) {                  return *id;              } @@ -632,9 +635,7 @@ void SurfaceFlinger::releaseVirtualDisplay(VirtualDisplayId displayId) {      mVirtualDisplayIdGenerators.gpu.releaseId(*id);  } -std::vector<PhysicalDisplayId> SurfaceFlinger::getPhysicalDisplayIds() const { -    Mutex::Autolock lock(mStateLock); - +std::vector<PhysicalDisplayId> SurfaceFlinger::getPhysicalDisplayIdsLocked() const {      const auto internalDisplayId = getInternalDisplayIdLocked();      if (!internalDisplayId) {          return {}; @@ -728,7 +729,7 @@ void SurfaceFlinger::bootFinished() {          mBootStage = BootStage::FINISHED;          if (property_get_bool("sf.debug.show_refresh_rate_overlay", false)) { -            enableRefreshRateOverlay(true); +            ON_MAIN_THREAD(enableRefreshRateOverlay(true));          }      }));  } @@ -792,6 +793,8 @@ void SurfaceFlinger::init() {                                      ? renderengine::RenderEngine::ContextPriority::REALTIME                                      : renderengine::RenderEngine::ContextPriority::MEDIUM)                      .build())); +    mMaxRenderTargetSize = +            std::min(getRenderEngine().getMaxTextureSize(), getRenderEngine().getMaxViewportDims());      // Set SF main policy after initializing RenderEngine which has its own policy.      if (!SetTaskProfiles(0, {"SFMainPolicy"})) { @@ -837,7 +840,7 @@ void SurfaceFlinger::init() {          }      } -    getRenderEngine().onPrimaryDisplaySizeChanged(display->getSize()); +    onActiveDisplaySizeChanged(display);      // Inform native graphics APIs whether the present timestamp is supported: @@ -879,14 +882,6 @@ void SurfaceFlinger::startBootAnim() {      }  } -size_t SurfaceFlinger::getMaxTextureSize() const { -    return getRenderEngine().getMaxTextureSize(); -} - -size_t SurfaceFlinger::getMaxViewportDims() const { -    return getRenderEngine().getMaxViewportDims(); -} -  // ----------------------------------------------------------------------------  bool SurfaceFlinger::authenticateSurfaceTexture( @@ -1075,36 +1070,28 @@ status_t SurfaceFlinger::getDisplayStats(const sp<IBinder>&, DisplayStatInfo* st  void SurfaceFlinger::setDesiredActiveMode(const ActiveModeInfo& info) {      ATRACE_CALL(); -    auto refreshRate = mRefreshRateConfigs->getRefreshRateFromModeId(info.modeId); -    ALOGV("%s(%s)", __func__, refreshRate.getName().c_str()); - -    std::lock_guard<std::mutex> lock(mActiveModeLock); -    if (mDesiredActiveModeChanged) { -        // If a mode change is pending, just cache the latest request in mDesiredActiveMode -        const Scheduler::ModeEvent prevConfig = mDesiredActiveMode.event; -        mDesiredActiveMode = info; -        mDesiredActiveMode.event = mDesiredActiveMode.event | prevConfig; -    } else { -        // Check if we are already at the desired mode -        const auto display = getDefaultDisplayDeviceLocked(); -        if (!display || display->getActiveMode()->getId() == refreshRate.getModeId()) { -            return; -        } -        // Initiate a mode change. -        mDesiredActiveModeChanged = true; -        mDesiredActiveMode = info; +    if (!info.mode) { +        ALOGW("requested display mode is null"); +        return; +    } +    auto display = getDisplayDeviceLocked(info.mode->getPhysicalDisplayId()); +    if (!display) { +        ALOGW("%s: display is no longer valid", __func__); +        return; +    } +    if (display->setDesiredActiveMode(info)) {          // This will trigger HWC refresh without resetting the idle timer.          repaintEverythingForHWC();          // Start receiving vsync samples now, so that we can detect a period          // switch. -        mScheduler->resyncToHardwareVsync(true, refreshRate.getVsyncPeriod()); +        mScheduler->resyncToHardwareVsync(true, info.mode->getVsyncPeriod());          // As we called to set period, we will call to onRefreshRateChangeCompleted once          // VsyncController model is locked.          modulateVsync(&VsyncModulator::onRefreshRateChangeInitiated); -        updatePhaseConfiguration(refreshRate.getFps()); +        updatePhaseConfiguration(info.mode->getFps());          mScheduler->setModeChangePending(true);      }  } @@ -1138,7 +1125,7 @@ status_t SurfaceFlinger::setActiveMode(const sp<IBinder>& displayToken, int mode          const auto fps = mode->getFps();          // Keep the old switching type.          const auto allowGroupSwitching = -                mRefreshRateConfigs->getCurrentPolicy().allowGroupSwitching; +                display->refreshRateConfigs().getCurrentPolicy().allowGroupSwitching;          const scheduler::RefreshRateConfigs::Policy policy{mode->getId(),                                                             allowGroupSwitching,                                                             {fps, fps}}; @@ -1158,63 +1145,49 @@ void SurfaceFlinger::setActiveModeInternal() {          return;      } -    const auto upcomingMode = display->getMode(mUpcomingActiveMode.modeId); -    if (!upcomingMode) { -        ALOGW("Upcoming active mode is no longer supported. Mode ID = %d", -              mUpcomingActiveMode.modeId.value()); -        // TODO(b/159590486) Handle the error better. Some parts of SurfaceFlinger may -        // have been already updated with the upcoming active mode. +    const auto upcomingModeInfo = MAIN_THREAD_GUARD(display->getUpcomingActiveMode()); +    if (!upcomingModeInfo.mode) { +        // There is no pending mode change. This can happen if the active +        // display changed and the mode change happened on a different display.          return;      } -    if (display->getActiveMode()->getSize() != upcomingMode->getSize()) { +    if (display->getActiveMode()->getSize() != upcomingModeInfo.mode->getSize()) {          auto& state = mCurrentState.displays.editValueFor(display->getDisplayToken());          // We need to generate new sequenceId in order to recreate the display (and this          // way the framebuffer).          state.sequenceId = DisplayDeviceState{}.sequenceId; -        state.physical->activeMode = upcomingMode; +        state.physical->activeMode = upcomingModeInfo.mode;          processDisplayChangesLocked();          // processDisplayChangesLocked will update all necessary components so we're done here.          return;      } -    std::lock_guard<std::mutex> lock(mActiveModeLock); -    mRefreshRateConfigs->setCurrentModeId(mUpcomingActiveMode.modeId); -    display->setActiveMode(mUpcomingActiveMode.modeId); - -    const Fps refreshRate = upcomingMode->getFps(); +    // We just created this display so we can call even if we are not on +    // the main thread +    MainThreadScopedGuard fakeMainThreadGuard(SF_MAIN_THREAD); +    display->setActiveMode(upcomingModeInfo.mode->getId()); +    const Fps refreshRate = upcomingModeInfo.mode->getFps();      mRefreshRateStats->setRefreshRate(refreshRate); -      updatePhaseConfiguration(refreshRate); -    ATRACE_INT("ActiveConfigFPS", refreshRate.getValue()); -    if (mRefreshRateOverlay) { -        mRefreshRateOverlay->changeRefreshRate(upcomingMode->getFps()); -    } - -    if (mUpcomingActiveMode.event != Scheduler::ModeEvent::None) { -        const nsecs_t vsyncPeriod = refreshRate.getPeriodNsecs(); -        const auto physicalId = display->getPhysicalId(); -        mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, physicalId, -                                                mUpcomingActiveMode.modeId, vsyncPeriod); +    if (upcomingModeInfo.event != Scheduler::ModeEvent::None) { +        mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, upcomingModeInfo.mode);      }  } -void SurfaceFlinger::clearDesiredActiveModeState() { -    std::lock_guard<std::mutex> lock(mActiveModeLock); -    mDesiredActiveMode.event = Scheduler::ModeEvent::None; -    mDesiredActiveModeChanged = false; -    mScheduler->setModeChangePending(false); +void SurfaceFlinger::clearDesiredActiveModeState(const sp<DisplayDevice>& display) { +    display->clearDesiredActiveModeState(); +    if (isDisplayActiveLocked(display)) { +        mScheduler->setModeChangePending(false); +    }  } -void SurfaceFlinger::desiredActiveModeChangeDone() { -    const auto modeId = getDesiredActiveMode()->modeId; - -    clearDesiredActiveModeState(); - -    const auto refreshRate = getDefaultDisplayDeviceLocked()->getMode(modeId)->getFps(); +void SurfaceFlinger::desiredActiveModeChangeDone(const sp<DisplayDevice>& display) { +    const auto refreshRate = display->getDesiredActiveMode()->mode->getFps(); +    clearDesiredActiveModeState(display);      mScheduler->resyncToHardwareVsync(true, refreshRate.getPeriodNsecs());      updatePhaseConfiguration(refreshRate);  } @@ -1222,63 +1195,75 @@ void SurfaceFlinger::desiredActiveModeChangeDone() {  void SurfaceFlinger::performSetActiveMode() {      ATRACE_CALL();      ALOGV("%s", __FUNCTION__); -    // Store the local variable to release the lock. -    const auto desiredActiveMode = getDesiredActiveMode(); -    if (!desiredActiveMode) { -        // No desired active mode pending to be applied -        return; -    } -    const auto display = getDefaultDisplayDeviceLocked(); -    const auto desiredMode = display->getMode(desiredActiveMode->modeId); -    if (!desiredMode) { -        ALOGW("Desired display mode is no longer supported. Mode ID = %d", -              desiredActiveMode->modeId.value()); -        clearDesiredActiveModeState(); -        return; -    } -    const auto refreshRate = desiredMode->getFps(); -    ALOGV("%s changing active mode to %d(%s)", __FUNCTION__, desiredMode->getId().value(), -          to_string(refreshRate).c_str()); +    for (const auto& iter : mDisplays) { +        const auto& display = iter.second; +        if (!display || !display->isInternal()) { +            continue; +        } -    if (!display || display->getActiveMode()->getId() == desiredActiveMode->modeId) { -        // display is not valid or we are already in the requested mode -        // on both cases there is nothing left to do -        desiredActiveModeChangeDone(); -        return; -    } +        // Store the local variable to release the lock. +        const auto desiredActiveMode = display->getDesiredActiveMode(); +        if (!desiredActiveMode) { +            // No desired active mode pending to be applied +            continue; +        } -    // Desired active mode was set, it is different than the mode currently in use, however -    // allowed modes might have changed by the time we process the refresh. -    // Make sure the desired mode is still allowed -    if (!isDisplayModeAllowed(desiredActiveMode->modeId)) { -        desiredActiveModeChangeDone(); -        return; -    } +        if (!isDisplayActiveLocked(display)) { +            // display is no longer the active display, so abort the mode change +            clearDesiredActiveModeState(display); +            continue; +        } -    mUpcomingActiveMode = *desiredActiveMode; +        const auto desiredMode = display->getMode(desiredActiveMode->mode->getId()); +        if (!desiredMode) { +            ALOGW("Desired display mode is no longer supported. Mode ID = %d", +                  desiredActiveMode->mode->getId().value()); +            clearDesiredActiveModeState(display); +            continue; +        } -    ATRACE_INT("ActiveModeFPS_HWC", refreshRate.getValue()); +        const auto refreshRate = desiredMode->getFps(); +        ALOGV("%s changing active mode to %d(%s) for display %s", __func__, +              desiredMode->getId().value(), to_string(refreshRate).c_str(), +              to_string(display->getId()).c_str()); -    // TODO(b/142753666) use constrains -    hal::VsyncPeriodChangeConstraints constraints; -    constraints.desiredTimeNanos = systemTime(); -    constraints.seamlessRequired = false; +        if (display->getActiveMode()->getId() == desiredActiveMode->mode->getId()) { +            // display is not valid or we are already in the requested mode +            // on both cases there is nothing left to do +            desiredActiveModeChangeDone(display); +            continue; +        } -    hal::VsyncPeriodChangeTimeline outTimeline; -    const auto status = -            display->initiateModeChange(mUpcomingActiveMode.modeId, constraints, &outTimeline); -    if (status != NO_ERROR) { -        // initiateModeChange may fail if a hotplug event is just about -        // to be sent. We just log the error in this case. -        ALOGW("initiateModeChange failed: %d", status); -        return; -    } +        // Desired active mode was set, it is different than the mode currently in use, however +        // allowed modes might have changed by the time we process the refresh. +        // Make sure the desired mode is still allowed +        const auto displayModeAllowed = +                display->refreshRateConfigs().isModeAllowed(desiredActiveMode->mode->getId()); +        if (!displayModeAllowed) { +            desiredActiveModeChangeDone(display); +            continue; +        } -    mScheduler->onNewVsyncPeriodChangeTimeline(outTimeline); +        // TODO(b/142753666) use constrains +        hal::VsyncPeriodChangeConstraints constraints; +        constraints.desiredTimeNanos = systemTime(); +        constraints.seamlessRequired = false; +        hal::VsyncPeriodChangeTimeline outTimeline; + +        const auto status = MAIN_THREAD_GUARD( +                display->initiateModeChange(*desiredActiveMode, constraints, &outTimeline)); +        if (status != NO_ERROR) { +            // initiateModeChange may fail if a hotplug event is just about +            // to be sent. We just log the error in this case. +            ALOGW("initiateModeChange failed: %d", status); +            continue; +        } +        mScheduler->onNewVsyncPeriodChangeTimeline(outTimeline); -    // Scheduler will submit an empty frame to HWC if needed. -    mSetActiveModePending = true; +        // Scheduler will submit an empty frame to HWC if needed. +        mSetActiveModePending = true; +    }  }  void SurfaceFlinger::disableExpensiveRendering() { @@ -1720,10 +1705,10 @@ void SurfaceFlinger::onComposerHalVsync(hal::HWDisplayId hwcDisplayId, int64_t t      ATRACE_CALL();      Mutex::Autolock lock(mStateLock); - -    if (const auto displayId = getHwComposer().toPhysicalDisplayId(hwcDisplayId)) { -        auto token = getPhysicalDisplayTokenLocked(*displayId); -        auto display = getDisplayDeviceLocked(token); +    const auto displayId = getHwComposer().toPhysicalDisplayId(hwcDisplayId); +    if (displayId) { +        const auto token = getPhysicalDisplayTokenLocked(*displayId); +        const auto display = getDisplayDeviceLocked(token);          display->onVsync(timestamp);      } @@ -1731,8 +1716,10 @@ void SurfaceFlinger::onComposerHalVsync(hal::HWDisplayId hwcDisplayId, int64_t t          return;      } -    if (hwcDisplayId != getHwComposer().getInternalHwcDisplayId()) { -        // For now, we don't do anything with external display vsyncs. +    const bool isActiveDisplay = +            displayId && getPhysicalDisplayTokenLocked(*displayId) == mActiveDisplayToken; +    if (!isActiveDisplay) { +        // For now, we don't do anything with non active display vsyncs.          return;      } @@ -1748,10 +1735,6 @@ void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) {      *compositorTiming = getBE().mCompositorTiming;  } -bool SurfaceFlinger::isDisplayModeAllowed(DisplayModeId modeId) const { -    return mRefreshRateConfigs->isModeAllowed(modeId); -} -  void SurfaceFlinger::changeRefreshRateLocked(const RefreshRate& refreshRate,                                               Scheduler::ModeEvent event) {      const auto display = getDefaultDisplayDeviceLocked(); @@ -1761,13 +1744,13 @@ void SurfaceFlinger::changeRefreshRateLocked(const RefreshRate& refreshRate,      ATRACE_CALL();      // Don't do any updating if the current fps is the same as the new one. -    if (!isDisplayModeAllowed(refreshRate.getModeId())) { +    if (!display->refreshRateConfigs().isModeAllowed(refreshRate.getModeId())) {          ALOGV("Skipping mode %d as it is not part of allowed modes",                refreshRate.getModeId().value());          return;      } -    setDesiredActiveMode({refreshRate.getModeId(), event}); +    setDesiredActiveMode({refreshRate.getMode(), event});  }  void SurfaceFlinger::onComposerHalHotplug(hal::HWDisplayId hwcDisplayId, @@ -1965,8 +1948,13 @@ void SurfaceFlinger::onMessageInvalidate(int64_t vsyncId, nsecs_t expectedVSyncT      }      if (mRefreshRateOverlaySpinner) { -        if (Mutex::Autolock lock(mStateLock); mRefreshRateOverlay) { -            mRefreshRateOverlay->onInvalidate(); +        if (Mutex::Autolock lock(mStateLock); +            const auto display = getDefaultDisplayDeviceLocked()) { +            if (display) { +                display->onInvalidate(); +            } else { +                ALOGW("%s: default display is null", __func__); +            }          }      } @@ -2352,7 +2340,7 @@ void SurfaceFlinger::postComposition() {      mTransactionCallbackInvoker.addPresentFence(mPreviousPresentFences[0].fence);      mTransactionCallbackInvoker.sendCallbacks(); -    if (display && display->isPrimary() && display->getPowerMode() == hal::PowerMode::ON && +    if (display && display->isInternal() && display->getPowerMode() == hal::PowerMode::ON &&          mPreviousPresentFences[0].fenceTime->isValid()) {          mScheduler->addPresentFence(mPreviousPresentFences[0].fenceTime);      } @@ -2489,7 +2477,6 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) {      // We call getTransactionFlags(), which will also clear the flags,      // with mStateLock held to guarantee that mCurrentState won't change      // until the transaction is committed. -      modulateVsync(&VsyncModulator::onTransactionCommit);      transactionFlags = getTransactionFlags(eTransactionMask);      handleTransactionLocked(transactionFlags); @@ -2540,6 +2527,7 @@ void SurfaceFlinger::loadDisplayModes(PhysicalDisplayId displayId, DisplayModes&      for (const auto& hwcMode : hwcModes) {          newModes.push_back(DisplayMode::Builder(hwcMode.hwcId)                                     .setId(DisplayModeId{nextModeId++}) +                                   .setPhysicalDisplayId(displayId)                                     .setWidth(hwcMode.width)                                     .setHeight(hwcMode.height)                                     .setVsyncPeriod(hwcMode.vsyncPeriod) @@ -2601,11 +2589,6 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() {                  sp<IBinder> token = new BBinder();                  mCurrentState.displays.add(token, state);                  mPhysicalDisplayTokens.emplace(displayId, std::move(token)); - -                if (event.hwcDisplayId == getHwComposer().getInternalHwcDisplayId()) { -                    initScheduler(state); -                } -                  mInterceptor->saveDisplayCreation(state);              } else {                  ALOGV("Recreating display %s", to_string(displayId).c_str()); @@ -2660,6 +2643,14 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(      if (const auto& physical = state.physical) {          creationArgs.connectionType = physical->type;          creationArgs.supportedModes = physical->supportedModes; +        creationArgs.activeModeId = physical->activeMode->getId(); +        scheduler::RefreshRateConfigs::Config config = +                {.enableFrameRateOverride = android::sysprop::enable_frame_rate_override(false), +                 .frameRateMultipleThreshold = +                         base::GetIntProperty("debug.sf.frame_rate_multiple_threshold", 0)}; +        creationArgs.refreshRateConfigs = +                std::make_shared<scheduler::RefreshRateConfigs>(creationArgs.supportedModes, +                                                                creationArgs.activeModeId, config);      }      if (const auto id = PhysicalDisplayId::tryCast(compositionDisplay->getId())) { @@ -2716,7 +2707,7 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(                                                      RenderIntent::COLORIMETRIC,                                                      Dataspace::UNKNOWN});      if (!state.isVirtual()) { -        display->setActiveMode(state.physical->activeMode->getId()); +        MAIN_THREAD_GUARD(display->setActiveMode(state.physical->activeMode->getId()));          display->setDeviceProductInfo(state.physical->deviceProductInfo);      } @@ -2756,7 +2747,7 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,          builder.setId(physical->id);          builder.setConnectionType(physical->type);      } else { -        builder.setId(acquireVirtualDisplay(resolution, pixelFormat, state.layerStack)); +        builder.setId(acquireVirtualDisplay(resolution, pixelFormat));      }      builder.setPixels(resolution); @@ -2798,14 +2789,12 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,      const auto display = setupNewDisplayDeviceInternal(displayToken, std::move(compositionDisplay),                                                         state, displaySurface, producer);      mDisplays.emplace(displayToken, display); +    if (display->isPrimary()) { +        initScheduler(display); +    }      if (!state.isVirtual()) {          dispatchDisplayHotplugEvent(display->getPhysicalId(), true);      } - -    if (display->isPrimary()) { -        mScheduler->onPrimaryDisplayAreaChanged(display->getWidth() * display->getHeight()); -        getRenderEngine().onPrimaryDisplaySizeChanged(display->getSize()); -    }  }  void SurfaceFlinger::processDisplayRemoved(const wp<IBinder>& displayToken) { @@ -2870,16 +2859,7 @@ void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken,              // TODO(b/175678251) Call a listener instead.              if (currentState.physical->hwcDisplayId == getHwComposer().getInternalHwcDisplayId()) { -                mRefreshRateConfigs->updateDisplayModes(currentState.physical->supportedModes, -                                                        currentState.physical->activeMode->getId()); -                mVsyncConfiguration->reset(); -                const Fps refreshRate = currentState.physical->activeMode->getFps(); -                updatePhaseConfiguration(refreshRate); -                mRefreshRateStats->setRefreshRate(refreshRate); - -                if (mRefreshRateOverlay) { -                    mRefreshRateOverlay->reset(); -                } +                updateInternalDisplayVsyncLocked(display);              }          }          return; @@ -2889,6 +2869,9 @@ void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken,          if (currentState.layerStack != drawingState.layerStack) {              display->setLayerStack(currentState.layerStack);          } +        if (currentState.flags != drawingState.flags) { +            display->setFlags(currentState.flags); +        }          if ((currentState.orientation != drawingState.orientation) ||              (currentState.layerStackSpaceRect != drawingState.layerStackSpaceRect) ||              (currentState.orientedDisplaySpaceRect != drawingState.orientedDisplaySpaceRect)) { @@ -2902,16 +2885,18 @@ void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken,              currentState.height != drawingState.height) {              display->setDisplaySize(currentState.width, currentState.height); -            if (display->isPrimary()) { -                mScheduler->onPrimaryDisplayAreaChanged(currentState.width * currentState.height); -            } - -            if (mRefreshRateOverlay) { -                mRefreshRateOverlay->setViewport(display->getSize()); +            if (isDisplayActiveLocked(display)) { +                onActiveDisplaySizeChanged(display);              }          }      }  } +void SurfaceFlinger::updateInternalDisplayVsyncLocked(const sp<DisplayDevice>& activeDisplay) { +    mVsyncConfiguration->reset(); +    const Fps refreshRate = activeDisplay->refreshRateConfigs().getCurrentRefreshRate().getFps(); +    updatePhaseConfiguration(refreshRate); +    mRefreshRateStats->setRefreshRate(refreshRate); +}  void SurfaceFlinger::processDisplayChangesLocked() {      // here we take advantage of Vector's copy-on-write semantics to @@ -3093,22 +3078,13 @@ bool enablePerWindowInputRotation() {  }  void SurfaceFlinger::updateInputWindowInfo() { -    std::vector<InputWindowInfo> inputInfos; +    std::vector<WindowInfo> inputInfos;      mDrawingState.traverseInReverseZOrder([&](Layer* layer) {          if (!layer->needsInputInfo()) return; -        sp<DisplayDevice> display; -        if (enablePerWindowInputRotation()) { -            for (const auto& pair : ON_MAIN_THREAD(mDisplays)) { -                const auto& displayDevice = pair.second; -                if (!displayDevice->getCompositionDisplay() -                             ->belongsInOutput(layer->getLayerStack(), -                                               layer->getPrimaryDisplayOnly())) { -                    continue; -                } -                display = displayDevice; -            } -        } +        sp<DisplayDevice> display = enablePerWindowInputRotation() +                ? ON_MAIN_THREAD(getDisplayWithInputByLayer(layer)) +                : nullptr;          // When calculating the screen bounds we ignore the transparent region since it may          // result in an unwanted offset.          inputInfos.push_back(layer->fillInputInfo(display)); @@ -3148,24 +3124,16 @@ void SurfaceFlinger::triggerOnFrameRateOverridesChanged() {      mScheduler->onFrameRateOverridesChanged(mAppConnectionHandle, displayId);  } -void SurfaceFlinger::initScheduler(const DisplayDeviceState& displayState) { +void SurfaceFlinger::initScheduler(const sp<DisplayDevice>& display) {      if (mScheduler) { -        // In practice it's not allowed to hotplug in/out the primary display once it's been -        // connected during startup, but some tests do it, so just warn and return. -        ALOGW("Can't re-init scheduler"); +        // If the scheduler is already initialized, this means that we received +        // a hotplug(connected) on the primary display. In that case we should +        // update the scheduler with the most recent display information. +        ALOGW("Scheduler already initialized, updating instead"); +        mScheduler->setRefreshRateConfigs(display->holdRefreshRateConfigs());          return;      } -    const auto displayId = displayState.physical->id; -    scheduler::RefreshRateConfigs::Config config = -            {.enableFrameRateOverride = android::sysprop::enable_frame_rate_override(false), -             .frameRateMultipleThreshold = -                     base::GetIntProperty("debug.sf.frame_rate_multiple_threshold", 0)}; -    mRefreshRateConfigs = -            std::make_unique<scheduler::RefreshRateConfigs>(displayState.physical->supportedModes, -                                                            displayState.physical->activeMode -                                                                    ->getId(), -                                                            config); -    const auto currRefreshRate = displayState.physical->activeMode->getFps(); +    const auto currRefreshRate = display->getActiveMode()->getFps();      mRefreshRateStats = std::make_unique<scheduler::RefreshRateStats>(*mTimeStats, currRefreshRate,                                                                        hal::PowerMode::OFF); @@ -3173,7 +3141,7 @@ void SurfaceFlinger::initScheduler(const DisplayDeviceState& displayState) {      mVsyncModulator = sp<VsyncModulator>::make(mVsyncConfiguration->getCurrentConfigs());      // start the EventThread -    mScheduler = getFactory().createScheduler(*mRefreshRateConfigs, *this); +    mScheduler = getFactory().createScheduler(display->holdRefreshRateConfigs(), *this);      const auto configs = mVsyncConfiguration->getCurrentConfigs();      const nsecs_t vsyncPeriod = currRefreshRate.getPeriodNsecs();      mAppConnectionHandle = @@ -3202,9 +3170,7 @@ void SurfaceFlinger::initScheduler(const DisplayDeviceState& displayState) {      // This is a bit hacky, but this avoids a back-pointer into the main SF      // classes from EventThread, and there should be no run-time binder cost      // anyway since there are no connected apps at this point. -    mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, displayId, -                                            displayState.physical->activeMode->getId(), -                                            vsyncPeriod); +    mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, display->getActiveMode());      static auto ignorePresentFences =              base::GetBoolProperty("debug.sf.vsync_reactor_ignore_present_fences"s, false);      mScheduler->setIgnorePresentFences( @@ -3857,6 +3823,12 @@ uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s) {              flags |= eDisplayTransactionNeeded;          }      } +    if (what & DisplayState::eFlagsChanged) { +        if (state.flags != s.flags) { +            state.flags = s.flags; +            flags |= eDisplayTransactionNeeded; +        } +    }      if (what & DisplayState::eDisplayProjectionChanged) {          if (state.orientation != s.orientation) {              state.orientation = s.orientation; @@ -4117,10 +4089,10 @@ uint32_t SurfaceFlinger::setClientStateLocked(      }      if (what & layer_state_t::eInputInfoChanged) {          if (privileged) { -            layer->setInputInfo(*s.inputHandle->getInfo()); +            layer->setInputInfo(*s.windowInfoHandle->getInfo());              flags |= eTraversalNeeded;          } else { -            ALOGE("Attempt to update InputWindowInfo without permission ACCESS_SURFACE_FLINGER"); +            ALOGE("Attempt to update WindowInfo without permission ACCESS_SURFACE_FLINGER");          }      }      std::optional<nsecs_t> dequeueBufferTimestamp; @@ -4218,17 +4190,30 @@ uint32_t SurfaceFlinger::setClientStateLocked(      }      bool bufferChanged = what & layer_state_t::eBufferChanged;      bool cacheIdChanged = what & layer_state_t::eCachedBufferChanged; +    bool bufferSizeExceedsLimit = false;      std::shared_ptr<renderengine::ExternalTexture> buffer;      if (bufferChanged && cacheIdChanged && s.buffer != nullptr) { -        ClientCache::getInstance().add(s.cachedBuffer, s.buffer); -        buffer = ClientCache::getInstance().get(s.cachedBuffer); +        bufferSizeExceedsLimit = +                exceedsMaxRenderTargetSize(s.buffer->getWidth(), s.buffer->getHeight()); +        if (!bufferSizeExceedsLimit) { +            ClientCache::getInstance().add(s.cachedBuffer, s.buffer); +            buffer = ClientCache::getInstance().get(s.cachedBuffer); +        }      } else if (cacheIdChanged) {          buffer = ClientCache::getInstance().get(s.cachedBuffer);      } else if (bufferChanged && s.buffer != nullptr) { -        buffer = std::make_shared< -                renderengine::ExternalTexture>(s.buffer, getRenderEngine(), -                                               renderengine::ExternalTexture::Usage::READABLE); -    } +        bufferSizeExceedsLimit = +                exceedsMaxRenderTargetSize(s.buffer->getWidth(), s.buffer->getHeight()); +        if (!bufferSizeExceedsLimit) { +            buffer = std::make_shared< +                    renderengine::ExternalTexture>(s.buffer, getRenderEngine(), +                                                   renderengine::ExternalTexture::Usage::READABLE); +        } +    } +    ALOGE_IF(bufferSizeExceedsLimit, +             "Attempted to create an ExternalTexture for layer %s that exceeds render target size " +             "limit.", +             layer->getDebugName());      if (buffer) {          const bool frameNumberChanged = what & layer_state_t::eFrameNumberChanged;          const uint64_t frameNumber = frameNumberChanged @@ -4521,7 +4506,8 @@ void SurfaceFlinger::onInitializeDisplays() {                            {}, getpid(), getuid(), 0 /* Undefined transactionId */);      setPowerModeInternal(display, hal::PowerMode::ON); -    const nsecs_t vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod(); +    const nsecs_t vsyncPeriod = +            display->refreshRateConfigs().getCurrentRefreshRate().getVsyncPeriod();      mAnimFrameTracker.setDisplayRefreshPeriod(vsyncPeriod);      mDefaultDisplayTransformHint = display->getTransformHint();      // Use phase of 0 since phase is not known. @@ -4535,6 +4521,26 @@ void SurfaceFlinger::initializeDisplays() {      static_cast<void>(schedule([this]() MAIN_THREAD { onInitializeDisplays(); }));  } +sp<DisplayDevice> SurfaceFlinger::getDisplayWithInputByLayer(Layer* layer) const { +    sp<DisplayDevice> display; +    for (const auto& pair : mDisplays) { +        const auto& displayDevice = pair.second; +        if (!displayDevice->receivesInput() || +            !displayDevice->getCompositionDisplay() +                     ->belongsInOutput(layer->getLayerStack(), layer->getPrimaryDisplayOnly())) { +            continue; +        } +        // Don't return immediately so that we can log duplicates. +        if (display) { +            ALOGE("Multiple display devices claim to accept input for the same layerstack: %d", +                  layer->getLayerStack()); +            continue; +        } +        display = displayDevice; +    } +    return display; +} +  void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal::PowerMode mode) {      if (display->isVirtual()) {          ALOGE("%s: Invalid operation on virtual display", __FUNCTION__); @@ -4554,8 +4560,12 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal:      if (mInterceptor->isEnabled()) {          mInterceptor->savePowerModeUpdate(display->getSequenceId(), static_cast<int32_t>(mode));      } -    const auto vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod(); +    const auto vsyncPeriod = display->refreshRateConfigs().getCurrentRefreshRate().getVsyncPeriod();      if (currentMode == hal::PowerMode::OFF) { +        const auto activeDisplay = getDisplayDeviceLocked(mActiveDisplayToken); +        if (display->isInternal() && (!activeDisplay || !activeDisplay->isPoweredOn())) { +            onActiveDisplayChangedLocked(display); +        }          // Keep uclamp in a separate syscall and set it before changing to RT due to b/190237315.          // We can merge the syscall later.          if (SurfaceFlinger::setSchedAttr(true) != NO_ERROR) { @@ -4565,7 +4575,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal:              ALOGW("Couldn't set SCHED_FIFO on display on: %s\n", strerror(errno));          }          getHwComposer().setPowerMode(displayId, mode); -        if (display->isPrimary() && mode != hal::PowerMode::DOZE_SUSPEND) { +        if (display->isInternal() && mode != hal::PowerMode::DOZE_SUSPEND) {              getHwComposer().setVsyncEnabled(displayId, mHWCVsyncPendingState);              mScheduler->onScreenAcquired(mAppConnectionHandle);              mScheduler->resyncToHardwareVsync(true, vsyncPeriod); @@ -4582,7 +4592,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal:          if (SurfaceFlinger::setSchedAttr(false) != NO_ERROR) {              ALOGW("Couldn't set uclamp.min on display off: %s\n", strerror(errno));          } -        if (display->isPrimary() && currentMode != hal::PowerMode::DOZE_SUSPEND) { +        if (display->isInternal() && currentMode != hal::PowerMode::DOZE_SUSPEND) {              mScheduler->disableHardwareVsync(true);              mScheduler->onScreenReleased(mAppConnectionHandle);          } @@ -4596,13 +4606,13 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal:      } else if (mode == hal::PowerMode::DOZE || mode == hal::PowerMode::ON) {          // Update display while dozing          getHwComposer().setPowerMode(displayId, mode); -        if (display->isPrimary() && currentMode == hal::PowerMode::DOZE_SUSPEND) { +        if (display->isInternal() && currentMode == hal::PowerMode::DOZE_SUSPEND) {              mScheduler->onScreenAcquired(mAppConnectionHandle);              mScheduler->resyncToHardwareVsync(true, vsyncPeriod);          }      } else if (mode == hal::PowerMode::DOZE_SUSPEND) {          // Leave display going to doze -        if (display->isPrimary()) { +        if (display->isInternal()) {              mScheduler->disableHardwareVsync(true);              mScheduler->onScreenReleased(mAppConnectionHandle);          } @@ -4612,7 +4622,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal:          getHwComposer().setPowerMode(displayId, mode);      } -    if (display->isPrimary()) { +    if (display->isInternal()) {          mTimeStats->setPowerMode(mode);          mRefreshRateStats->setPowerMode(mode);          mScheduler->setDisplayPowerState(mode == hal::PowerMode::ON); @@ -4781,8 +4791,6 @@ void SurfaceFlinger::dumpVSync(std::string& result) const {                    "      present offset: %9" PRId64 " ns\t     VSYNC period: %9" PRId64 " ns\n\n",                    dispSyncPresentTimeOffset, getVsyncPeriodFromHWC()); -    mRefreshRateConfigs->dump(result); -      StringAppendF(&result, "(mode override by backdoor: %s)\n\n",                    mDebugDisplayModeSetByBackdoor ? "yes" : "no"); @@ -5345,6 +5353,14 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) {              }              return PERMISSION_DENIED;          } +        case ADD_WINDOW_INFOS_LISTENER: +        case REMOVE_WINDOW_INFOS_LISTENER: { +            const int uid = IPCThreadState::self()->getCallingUid(); +            if (uid == AID_SYSTEM || uid == AID_GRAPHICS) { +                return OK; +            } +            return PERMISSION_DENIED; +        }      }      // These codes are used for the IBinder protocol to either interrogate the recipient @@ -5658,16 +5674,17 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r                  return NO_ERROR;              }              case 1034: { -                switch (n = data.readInt32()) { -                    case 0: -                    case 1: -                        enableRefreshRateOverlay(static_cast<bool>(n)); -                        break; -                    default: { -                        Mutex::Autolock lock(mStateLock); -                        reply->writeBool(mRefreshRateOverlay != nullptr); +                schedule([&] { +                    switch (n = data.readInt32()) { +                        case 0: +                        case 1: +                            ON_MAIN_THREAD(enableRefreshRateOverlay(static_cast<bool>(n))); +                            break; +                        default: { +                            reply->writeBool(ON_MAIN_THREAD(isRefreshRateOverlayEnabled())); +                        }                      } -                } +                }).get();                  return NO_ERROR;              }              case 1035: { @@ -5687,7 +5704,7 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r                          return std::make_optional<PhysicalDisplayId>(inputDisplayId);                      } -                    return getInternalDisplayId(); +                    return getDefaultDisplayDevice()->getPhysicalId();                  }();                  if (!displayId) { @@ -5813,22 +5830,25 @@ void SurfaceFlinger::kernelTimerChanged(bool expired) {      static bool updateOverlay =              property_get_bool("debug.sf.kernel_idle_timer_update_overlay", true);      if (!updateOverlay) return; -    if (Mutex::Autolock lock(mStateLock); !mRefreshRateOverlay) return; +    if (Mutex::Autolock lock(mStateLock); !isRefreshRateOverlayEnabled()) return;      // Update the overlay on the main thread to avoid race conditions with      // mRefreshRateConfigs->getCurrentRefreshRate()      static_cast<void>(schedule([=] { -        const auto desiredActiveMode = getDesiredActiveMode(); -        const std::optional<DisplayModeId> desiredModeId = -                desiredActiveMode ? std::make_optional(desiredActiveMode->modeId) : std::nullopt; +        const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()); +        if (!display) { +            ALOGW("%s: default display is null", __func__); +            return; +        } + +        const auto desiredActiveMode = display->getDesiredActiveMode(); +        const std::optional<DisplayModeId> desiredModeId = desiredActiveMode +                ? std::make_optional(desiredActiveMode->mode->getId()) +                : std::nullopt;          const bool timerExpired = mKernelIdleTimerEnabled && expired; -        const auto newRefreshRate = -                mRefreshRateConfigs->onKernelTimerChanged(desiredModeId, timerExpired); -        if (newRefreshRate) { -            if (Mutex::Autolock lock(mStateLock); mRefreshRateOverlay) { -                mRefreshRateOverlay->changeRefreshRate(*newRefreshRate); -            } + +        if (display->onKernelTimerChanged(desiredModeId, timerExpired)) {              mEventQueue->invalidate();          }      })); @@ -5841,8 +5861,13 @@ void SurfaceFlinger::toggleKernelIdleTimer() {      if (!mSupportKernelIdleTimer) {          return;      } -    const KernelIdleTimerAction action = mRefreshRateConfigs->getIdleTimerAction(); +    const auto display = getDefaultDisplayDeviceLocked(); +    if (!display) { +        ALOGW("%s: default display is null", __func__); +        return; +    } +    const KernelIdleTimerAction action = display->refreshRateConfigs().getIdleTimerAction();      switch (action) {          case KernelIdleTimerAction::TurnOff:              if (mKernelIdleTimerEnabled) { @@ -6198,6 +6223,13 @@ status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture,                                               const sp<IScreenCaptureListener>& captureListener) {      ATRACE_CALL(); +    if (exceedsMaxRenderTargetSize(bufferSize.getWidth(), bufferSize.getHeight())) { +        ALOGE("Attempted to capture screen with size (%" PRId32 ", %" PRId32 +              ") that exceeds render target size limit.", +              bufferSize.getWidth(), bufferSize.getHeight()); +        return BAD_VALUE; +    } +      // Loop over all visible layers to see whether there's any protected layer. A protected layer is      // typically a layer with DRM contents, or have the GRALLOC_USAGE_PROTECTED set on the buffer.      // A protected layer has no implication on whether it's secure, which is explicitly set by @@ -6460,78 +6492,55 @@ status_t SurfaceFlinger::setDesiredDisplayModeSpecsInternal(          const std::optional<scheduler::RefreshRateConfigs::Policy>& policy, bool overridePolicy) {      Mutex::Autolock lock(mStateLock); -    LOG_ALWAYS_FATAL_IF(!display->isPrimary() && overridePolicy, -                        "Can only set override policy on the primary display"); -    LOG_ALWAYS_FATAL_IF(!policy && !overridePolicy, "Can only clear the override policy"); -      if (mDebugDisplayModeSetByBackdoor) {          // ignore this request as mode is overridden by backdoor          return NO_ERROR;      } -    if (!display->isPrimary()) { -        // TODO(b/144711714): For non-primary displays we should be able to set an active mode -        // as well. For now, just call directly to initiateModeChange but ideally -        // it should go thru setDesiredActiveMode, similar to primary display. -        ALOGV("%s for non-primary display", __func__); -        const auto displayId = display->getPhysicalId(); - -        hal::VsyncPeriodChangeConstraints constraints; -        constraints.desiredTimeNanos = systemTime(); -        constraints.seamlessRequired = false; - -        hal::VsyncPeriodChangeTimeline timeline = {0, 0, 0}; -        if (display->initiateModeChange(policy->defaultMode, constraints, &timeline) != NO_ERROR) { -            return BAD_VALUE; -        } -        if (timeline.refreshRequired) { -            repaintEverythingForHWC(); -        } - -        display->setActiveMode(policy->defaultMode); -        const nsecs_t vsyncPeriod = display->getMode(policy->defaultMode)->getVsyncPeriod(); -        mScheduler->onNonPrimaryDisplayModeChanged(mAppConnectionHandle, displayId, -                                                   policy->defaultMode, vsyncPeriod); -        return NO_ERROR; -    } -      status_t setPolicyResult = overridePolicy -            ? mRefreshRateConfigs->setOverridePolicy(policy) -            : mRefreshRateConfigs->setDisplayManagerPolicy(*policy); +            ? display->refreshRateConfigs().setOverridePolicy(policy) +            : display->refreshRateConfigs().setDisplayManagerPolicy(*policy);      if (setPolicyResult < 0) {          return BAD_VALUE;      }      if (setPolicyResult == scheduler::RefreshRateConfigs::CURRENT_POLICY_UNCHANGED) {          return NO_ERROR;      } -    scheduler::RefreshRateConfigs::Policy currentPolicy = mRefreshRateConfigs->getCurrentPolicy(); + +    scheduler::RefreshRateConfigs::Policy currentPolicy = +            display->refreshRateConfigs().getCurrentPolicy();      ALOGV("Setting desired display mode specs: %s", currentPolicy.toString().c_str());      // TODO(b/140204874): Leave the event in until we do proper testing with all apps that might      // be depending in this callback.      const auto activeMode = display->getActiveMode(); -    const nsecs_t vsyncPeriod = activeMode->getVsyncPeriod(); -    const auto physicalId = display->getPhysicalId(); -    mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, physicalId, activeMode->getId(), -                                            vsyncPeriod); -    toggleKernelIdleTimer(); - -    auto modeId = mScheduler->getPreferredModeId(); -    auto preferredRefreshRate = modeId -            ? mRefreshRateConfigs->getRefreshRateFromModeId(*modeId) -            // NOTE: Choose the default mode ID, if Scheduler doesn't have one in mind. -            : mRefreshRateConfigs->getRefreshRateFromModeId(currentPolicy.defaultMode); +    if (isDisplayActiveLocked(display)) { +        mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, activeMode); +        toggleKernelIdleTimer(); +    } else { +        mScheduler->onNonPrimaryDisplayModeChanged(mAppConnectionHandle, activeMode); +    } + +    const DisplayModePtr preferredDisplayMode = [&] { +        const auto schedulerMode = mScheduler->getPreferredDisplayMode(); +        if (schedulerMode && schedulerMode->getPhysicalDisplayId() == display->getPhysicalId()) { +            return schedulerMode; +        } + +        return display->getMode(currentPolicy.defaultMode); +    }(); +      ALOGV("trying to switch to Scheduler preferred mode %d (%s)", -          preferredRefreshRate.getModeId().value(), preferredRefreshRate.getName().c_str()); +          preferredDisplayMode->getId().value(), to_string(preferredDisplayMode->getFps()).c_str()); -    if (isDisplayModeAllowed(preferredRefreshRate.getModeId())) { +    if (display->refreshRateConfigs().isModeAllowed(preferredDisplayMode->getId())) {          ALOGV("switching to Scheduler preferred display mode %d", -              preferredRefreshRate.getModeId().value()); -        setDesiredActiveMode({preferredRefreshRate.getModeId(), Scheduler::ModeEvent::Changed}); +              preferredDisplayMode->getId().value()); +        setDesiredActiveMode({preferredDisplayMode, Scheduler::ModeEvent::Changed});      } else {          LOG_ALWAYS_FATAL("Desired display mode not allowed: %d", -                         preferredRefreshRate.getModeId().value()); +                         preferredDisplayMode->getId().value());      }      return NO_ERROR; @@ -6591,29 +6600,19 @@ status_t SurfaceFlinger::getDesiredDisplayModeSpecs(const sp<IBinder>& displayTo          return NAME_NOT_FOUND;      } -    if (display->isPrimary()) { -        scheduler::RefreshRateConfigs::Policy policy = -                mRefreshRateConfigs->getDisplayManagerPolicy(); -        *outDefaultMode = policy.defaultMode.value(); -        *outAllowGroupSwitching = policy.allowGroupSwitching; -        *outPrimaryRefreshRateMin = policy.primaryRange.min.getValue(); -        *outPrimaryRefreshRateMax = policy.primaryRange.max.getValue(); -        *outAppRequestRefreshRateMin = policy.appRequestRange.min.getValue(); -        *outAppRequestRefreshRateMax = policy.appRequestRange.max.getValue(); -        return NO_ERROR; -    } else if (display->isVirtual()) { +    if (display->isVirtual()) {          return INVALID_OPERATION; -    } else { -        const auto activeMode = display->getActiveMode(); -        *outDefaultMode = activeMode->getId().value(); -        *outAllowGroupSwitching = false; -        auto vsyncPeriod = activeMode->getVsyncPeriod(); -        *outPrimaryRefreshRateMin = Fps::fromPeriodNsecs(vsyncPeriod).getValue(); -        *outPrimaryRefreshRateMax = Fps::fromPeriodNsecs(vsyncPeriod).getValue(); -        *outAppRequestRefreshRateMin = Fps::fromPeriodNsecs(vsyncPeriod).getValue(); -        *outAppRequestRefreshRateMax = Fps::fromPeriodNsecs(vsyncPeriod).getValue(); -        return NO_ERROR;      } + +    scheduler::RefreshRateConfigs::Policy policy = +            display->refreshRateConfigs().getDisplayManagerPolicy(); +    *outDefaultMode = policy.defaultMode.value(); +    *outAllowGroupSwitching = policy.allowGroupSwitching; +    *outPrimaryRefreshRateMin = policy.primaryRange.min.getValue(); +    *outPrimaryRefreshRateMax = policy.primaryRange.max.getValue(); +    *outAppRequestRefreshRateMin = policy.appRequestRange.min.getValue(); +    *outAppRequestRefreshRateMax = policy.appRequestRange.max.getValue(); +    return NO_ERROR;  }  wp<Layer> SurfaceFlinger::fromHandle(const sp<IBinder>& handle) { @@ -6748,7 +6747,8 @@ status_t SurfaceFlinger::acquireFrameRateFlexibilityToken(sp<IBinder>* outToken)              // matter for the override policy though, since we set allowGroupSwitching to              // true, so it's not a problem.              scheduler::RefreshRateConfigs::Policy overridePolicy; -            overridePolicy.defaultMode = mRefreshRateConfigs->getDisplayManagerPolicy().defaultMode; +            overridePolicy.defaultMode = +                    display->refreshRateConfigs().getDisplayManagerPolicy().defaultMode;              overridePolicy.allowGroupSwitching = true;              constexpr bool kOverridePolicy = true;              result = setDesiredDisplayModeSpecsInternal(display, overridePolicy, kOverridePolicy); @@ -6816,25 +6816,11 @@ status_t SurfaceFlinger::setFrameTimelineInfo(const sp<IGraphicBufferProducer>&  }  void SurfaceFlinger::enableRefreshRateOverlay(bool enable) { -    static_cast<void>(schedule([=] { -        std::unique_ptr<RefreshRateOverlay> overlay; -        if (enable) { -            overlay = std::make_unique<RefreshRateOverlay>(*this, mRefreshRateOverlaySpinner); -        } - -        { -            Mutex::Autolock lock(mStateLock); - -            // Destroy the layer of the current overlay, if any, outside the lock. -            mRefreshRateOverlay.swap(overlay); -            if (!mRefreshRateOverlay) return; - -            if (const auto display = getDefaultDisplayDeviceLocked()) { -                mRefreshRateOverlay->setViewport(display->getSize()); -                mRefreshRateOverlay->changeRefreshRate(display->getActiveMode()->getFps()); -            } +    for (const auto& [ignored, display] : mDisplays) { +        if (display->isInternal()) { +            display->enableRefreshRateOverlay(enable, mRefreshRateOverlaySpinner);          } -    })); +    }  }  status_t SurfaceFlinger::addTransactionTraceListener( @@ -6862,7 +6848,14 @@ int SurfaceFlinger::calculateMaxAcquiredBufferCount(Fps refreshRate,  }  status_t SurfaceFlinger::getMaxAcquiredBufferCount(int* buffers) const { -    const auto maxSupportedRefreshRate = mRefreshRateConfigs->getSupportedRefreshRateRange().max; +    const auto maxSupportedRefreshRate = [&] { +        const auto display = getDefaultDisplayDevice(); +        if (display) { +            return display->refreshRateConfigs().getSupportedRefreshRateRange().max; +        } +        ALOGW("%s: default display is null", __func__); +        return Fps(60); +    }();      *buffers = getMaxAcquiredBufferCountForRefreshRate(maxSupportedRefreshRate);      return NO_ERROR;  } @@ -6873,7 +6866,14 @@ int SurfaceFlinger::getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t uid) co          if (frameRateOverride.has_value()) {              return frameRateOverride.value();          } -        return mRefreshRateConfigs->getCurrentRefreshRate().getFps(); + +        const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()); +        if (display) { +            return display->refreshRateConfigs().getCurrentRefreshRate().getFps(); +        } + +        ALOGW("%s: default display is null", __func__); +        return Fps(60);      }();      return getMaxAcquiredBufferCountForRefreshRate(refreshRate);  } @@ -6990,6 +6990,43 @@ void SurfaceFlinger::notifyRegionSamplingThread() {      mRegionSamplingThread->onCompositionComplete(mEventQueue->nextExpectedInvalidate());  } +void SurfaceFlinger::onActiveDisplaySizeChanged(const sp<DisplayDevice>& activeDisplay) { +    mScheduler->onActiveDisplayAreaChanged(activeDisplay->getWidth() * activeDisplay->getHeight()); +    getRenderEngine().onActiveDisplaySizeChanged(activeDisplay->getSize()); +} + +void SurfaceFlinger::onActiveDisplayChangedLocked(const sp<DisplayDevice>& activeDisplay) { +    ATRACE_CALL(); + +    if (const auto display = getDisplayDeviceLocked(mActiveDisplayToken)) { +        display->getCompositionDisplay()->setLayerCachingTexturePoolEnabled(false); +    } + +    if (!activeDisplay) { +        ALOGE("%s: activeDisplay is null", __func__); +        return; +    } +    mActiveDisplayToken = activeDisplay->getDisplayToken(); + +    activeDisplay->getCompositionDisplay()->setLayerCachingTexturePoolEnabled(true); +    updateInternalDisplayVsyncLocked(activeDisplay); +    mScheduler->setModeChangePending(false); +    mScheduler->setRefreshRateConfigs(activeDisplay->holdRefreshRateConfigs()); +    onActiveDisplaySizeChanged(activeDisplay); +} + +status_t SurfaceFlinger::addWindowInfosListener( +        const sp<IWindowInfosListener>& windowInfosListener) const { +    mWindowInfosListenerInvoker->addWindowInfosListener(windowInfosListener); +    return NO_ERROR; +} + +status_t SurfaceFlinger::removeWindowInfosListener( +        const sp<IWindowInfosListener>& windowInfosListener) const { +    mWindowInfosListenerInvoker->removeWindowInfosListener(windowInfosListener); +    return NO_ERROR; +} +  } // namespace android  #if defined(__gl_h_) diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 380f444221..b2e5e7dc93 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -102,6 +102,7 @@ class RegionSamplingThread;  class RenderArea;  class TimeStats;  class FrameTracer; +class WindowInfosListenerInvoker;  using gui::ScreenCaptureResults; @@ -358,6 +359,15 @@ protected:      // display.      virtual FloatRect getLayerClipBoundsForDisplay(const DisplayDevice&) const; +    virtual void processDisplayAdded(const wp<IBinder>& displayToken, const DisplayDeviceState&) +            REQUIRES(mStateLock); + +    // Returns true if any display matches a `bool(const DisplayDevice&)` predicate. +    template <typename Predicate> +    bool hasDisplay(Predicate p) const REQUIRES(mStateLock) { +        return static_cast<bool>(findDisplay(p)); +    } +  private:      friend class BufferLayer;      friend class BufferQueueLayer; @@ -456,14 +466,7 @@ private:                  mCounterByLayerHandle GUARDED_BY(mLock);      }; -    struct ActiveModeInfo { -        DisplayModeId modeId; -        Scheduler::ModeEvent event = Scheduler::ModeEvent::None; - -        bool operator!=(const ActiveModeInfo& other) const { -            return modeId != other.modeId || event != other.event; -        } -    }; +    using ActiveModeInfo = DisplayDevice::ActiveModeInfo;      enum class BootStage {          BOOTLOADER, @@ -594,7 +597,7 @@ private:                typename Handler = VsyncModulator::VsyncConfigOpt (VsyncModulator::*)(Args...)>      void modulateVsync(Handler handler, Args... args) {          if (const auto config = (*mVsyncModulator.*handler)(args...)) { -            const auto vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod(); +            const auto vsyncPeriod = mScheduler->getVsyncPeriodFromRefreshRateConfigs();              setVsyncConfig(*config, vsyncPeriod);          }      } @@ -613,7 +616,10 @@ private:      sp<ISurfaceComposerClient> createConnection() override;      sp<IBinder> createDisplay(const String8& displayName, bool secure) override;      void destroyDisplay(const sp<IBinder>& displayToken) override; -    std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const override; +    std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const override EXCLUDES(mStateLock) { +        Mutex::Autolock lock(mStateLock); +        return getPhysicalDisplayIdsLocked(); +    }      sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId displayId) const override;      status_t setTransactionState(const FrameTimelineInfo& frameTimelineInfo,                                   const Vector<ComposerState>& state, @@ -721,6 +727,11 @@ private:      status_t getMaxAcquiredBufferCount(int* buffers) const override; +    status_t addWindowInfosListener( +            const sp<gui::IWindowInfosListener>& windowInfosListener) const override; +    status_t removeWindowInfosListener( +            const sp<gui::IWindowInfosListener>& windowInfosListener) const override; +      // Implements IBinder::DeathRecipient.      void binderDied(const wp<IBinder>& who) override; @@ -751,7 +762,7 @@ private:      // Called when the frame rate override list changed to trigger an event.      void triggerOnFrameRateOverridesChanged() override;      // Toggles the kernel idle timer on or off depending the policy decisions around refresh rates. -    void toggleKernelIdleTimer(); +    void toggleKernelIdleTimer() REQUIRES(mStateLock);      // Keeps track of whether the kernel idle timer is currently enabled, so we don't have to      // make calls to sys prop each time.      bool mKernelIdleTimerEnabled = false; @@ -780,9 +791,9 @@ private:      // Calls to setActiveMode on the main thread if there is a pending mode change      // that needs to be applied.      void performSetActiveMode() REQUIRES(mStateLock); -    void clearDesiredActiveModeState() REQUIRES(mStateLock) EXCLUDES(mActiveModeLock); +    void clearDesiredActiveModeState(const sp<DisplayDevice>&) REQUIRES(mStateLock);      // Called when active mode is no longer is progress -    void desiredActiveModeChangeDone() REQUIRES(mStateLock); +    void desiredActiveModeChangeDone(const sp<DisplayDevice>&) REQUIRES(mStateLock);      // Called on the main thread in response to setPowerMode()      void setPowerModeInternal(const sp<DisplayDevice>& display, hal::PowerMode mode)              REQUIRES(mStateLock); @@ -815,7 +826,7 @@ private:      void commitInputWindowCommands() REQUIRES(mStateLock);      void updateCursorAsync(); -    void initScheduler(const DisplayDeviceState&) REQUIRES(mStateLock); +    void initScheduler(const sp<DisplayDevice>& display) REQUIRES(mStateLock);      void updatePhaseConfiguration(const Fps&) REQUIRES(mStateLock);      void setVsyncConfig(const VsyncModulator::VsyncConfig&, nsecs_t vsyncPeriod); @@ -931,8 +942,9 @@ private:      void readPersistentProperties(); -    size_t getMaxTextureSize() const; -    size_t getMaxViewportDims() const; +    bool exceedsMaxRenderTargetSize(uint32_t width, uint32_t height) const { +        return width > mMaxRenderTargetSize || height > mMaxRenderTargetSize; +    }      int getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t uid) const; @@ -954,6 +966,10 @@ private:      sp<const DisplayDevice> getDisplayDeviceLocked(PhysicalDisplayId id) const              REQUIRES(mStateLock) { +        return const_cast<SurfaceFlinger*>(this)->getDisplayDeviceLocked(id); +    } + +    sp<DisplayDevice> getDisplayDeviceLocked(PhysicalDisplayId id) REQUIRES(mStateLock) {          if (const auto token = getPhysicalDisplayTokenLocked(id)) {              return getDisplayDeviceLocked(token);          } @@ -965,13 +981,18 @@ private:      }      sp<DisplayDevice> getDefaultDisplayDeviceLocked() REQUIRES(mStateLock) { +        if (const auto display = getDisplayDeviceLocked(mActiveDisplayToken)) { +            return display; +        } +        // The active display is outdated, fall back to the internal display +        mActiveDisplayToken.clear();          if (const auto token = getInternalDisplayTokenLocked()) {              return getDisplayDeviceLocked(token);          }          return nullptr;      } -    sp<const DisplayDevice> getDefaultDisplayDevice() EXCLUDES(mStateLock) { +    sp<const DisplayDevice> getDefaultDisplayDevice() const EXCLUDES(mStateLock) {          Mutex::Autolock lock(mStateLock);          return getDefaultDisplayDeviceLocked();      } @@ -990,10 +1011,18 @@ private:          return findDisplay([id](const auto& display) { return display.getId() == id; });      } +    std::vector<PhysicalDisplayId> getPhysicalDisplayIdsLocked() const REQUIRES(mStateLock); +      // mark a region of a layer stack dirty. this updates the dirty      // region of all screens presenting this layer stack.      void invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty); +    sp<DisplayDevice> getDisplayWithInputByLayer(Layer* layer) const REQUIRES(mStateLock); + +    bool isDisplayActiveLocked(const sp<const DisplayDevice>& display) REQUIRES(mStateLock) { +        return display->getDisplayToken() == mActiveDisplayToken; +    } +      /*       * H/W composer       */ @@ -1031,8 +1060,6 @@ private:              const sp<compositionengine::DisplaySurface>& displaySurface,              const sp<IGraphicBufferProducer>& producer) REQUIRES(mStateLock);      void processDisplayChangesLocked() REQUIRES(mStateLock); -    void processDisplayAdded(const wp<IBinder>& displayToken, const DisplayDeviceState&) -            REQUIRES(mStateLock);      void processDisplayRemoved(const wp<IBinder>& displayToken) REQUIRES(mStateLock);      void processDisplayChanged(const wp<IBinder>& displayToken,                                 const DisplayDeviceState& currentState, @@ -1050,8 +1077,6 @@ private:      // the desired refresh rate.      void changeRefreshRateLocked(const RefreshRate&, Scheduler::ModeEvent) REQUIRES(mStateLock); -    bool isDisplayModeAllowed(DisplayModeId) const REQUIRES(mStateLock); -      struct FenceWithFenceTime {          sp<Fence> fence = Fence::NO_FENCE;          std::shared_ptr<FenceTime> fenceTime = FenceTime::NO_FENCE; @@ -1112,10 +1137,13 @@ private:      void enableHalVirtualDisplays(bool);      // Virtual display lifecycle for ID generation and HAL allocation. -    VirtualDisplayId acquireVirtualDisplay(ui::Size, ui::PixelFormat, ui::LayerStack) -            REQUIRES(mStateLock); +    VirtualDisplayId acquireVirtualDisplay(ui::Size, ui::PixelFormat) REQUIRES(mStateLock);      void releaseVirtualDisplay(VirtualDisplayId); +    void onActiveDisplayChangedLocked(const sp<DisplayDevice>& activeDisplay) REQUIRES(mStateLock); + +    void onActiveDisplaySizeChanged(const sp<DisplayDevice>& activeDisplay); +      /*       * Debugging & dumpsys       */ @@ -1181,13 +1209,6 @@ private:      /*       * Misc       */ - -    std::optional<ActiveModeInfo> getDesiredActiveMode() EXCLUDES(mActiveModeLock) { -        std::lock_guard<std::mutex> lock(mActiveModeLock); -        if (mDesiredActiveModeChanged) return mDesiredActiveMode; -        return std::nullopt; -    } -      std::vector<ui::ColorMode> getDisplayColorModes(PhysicalDisplayId displayId)              REQUIRES(mStateLock); @@ -1195,6 +1216,9 @@ private:                                                 std::chrono::nanoseconds presentLatency);      int getMaxAcquiredBufferCountForRefreshRate(Fps refreshRate) const; +    void updateInternalDisplayVsyncLocked(const sp<DisplayDevice>& activeDisplay) +            REQUIRES(mStateLock); +      sp<StartPropertySetThread> mStartPropertySetThread;      surfaceflinger::Factory& mFactory; @@ -1381,6 +1405,9 @@ private:      SurfaceFlingerBE mBE;      std::unique_ptr<compositionengine::CompositionEngine> mCompositionEngine; +    // mMaxRenderTargetSize is only set once in init() so it doesn't need to be protected by +    // any mutex. +    size_t mMaxRenderTargetSize{1};      const std::string mHwcServiceName; @@ -1399,24 +1426,13 @@ private:      // Optional to defer construction until PhaseConfiguration is created.      sp<VsyncModulator> mVsyncModulator; -    std::unique_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs;      std::unique_ptr<scheduler::RefreshRateStats> mRefreshRateStats;      std::atomic<nsecs_t> mExpectedPresentTime = 0;      nsecs_t mScheduledPresentTime = 0;      hal::Vsync mHWCVsyncPendingState = hal::Vsync::DISABLE; -    std::mutex mActiveModeLock; -    // This bit is set once we start setting the mode. We read from this bit during the -    // process. If at the end, this bit is different than mDesiredActiveMode, we restart -    // the process. -    ActiveModeInfo mUpcomingActiveMode; // Always read and written on the main thread. -    // This bit can be set at any point in time when the system wants the new mode. -    ActiveModeInfo mDesiredActiveMode GUARDED_BY(mActiveModeLock); -      // below flags are set by main thread only -    TracedOrdinal<bool> mDesiredActiveModeChanged -            GUARDED_BY(mActiveModeLock) = {"DesiredActiveModeChanged", false};      bool mSetActiveModePending = false;      bool mLumaSampling = true; @@ -1439,8 +1455,7 @@ private:      // This should only be accessed on the main thread.      nsecs_t mFrameStartTime = 0; -    void enableRefreshRateOverlay(bool enable); -    std::unique_ptr<RefreshRateOverlay> mRefreshRateOverlay GUARDED_BY(mStateLock); +    void enableRefreshRateOverlay(bool enable) REQUIRES(mStateLock);      // Flag used to set override desired display mode from backdoor      bool mDebugDisplayModeSetByBackdoor = false; @@ -1495,6 +1510,17 @@ private:      void scheduleRegionSamplingThread();      void notifyRegionSamplingThread(); + +    bool isRefreshRateOverlayEnabled() const REQUIRES(mStateLock) { +        return std::any_of(mDisplays.begin(), mDisplays.end(), +                           [](std::pair<wp<IBinder>, sp<DisplayDevice>> display) { +                               return display.second->isRefreshRateOverlayEnabled(); +                           }); +    } + +    wp<IBinder> mActiveDisplayToken GUARDED_BY(mStateLock); + +    const sp<WindowInfosListenerInvoker> mWindowInfosListenerInvoker;  };  } // namespace android diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp index 4a7518066f..89d1c4d327 100644 --- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp +++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp @@ -65,8 +65,9 @@ std::unique_ptr<scheduler::VsyncConfiguration> DefaultFactory::createVsyncConfig  }  std::unique_ptr<Scheduler> DefaultFactory::createScheduler( -        const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback) { -    return std::make_unique<Scheduler>(configs, callback); +        const std::shared_ptr<scheduler::RefreshRateConfigs>& refreshRateConfigs, +        ISchedulerCallback& callback) { +    return std::make_unique<Scheduler>(std::move(refreshRateConfigs), callback);  }  sp<SurfaceInterceptor> DefaultFactory::createSurfaceInterceptor() { diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h index 24148ddf9d..b8bf2baa33 100644 --- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h +++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h @@ -30,8 +30,8 @@ public:      std::unique_ptr<MessageQueue> createMessageQueue() override;      std::unique_ptr<scheduler::VsyncConfiguration> createVsyncConfiguration(              Fps currentRefreshRate) override; -    std::unique_ptr<Scheduler> createScheduler(const scheduler::RefreshRateConfigs&, -                                               ISchedulerCallback&) override; +    std::unique_ptr<Scheduler> createScheduler( +            const std::shared_ptr<scheduler::RefreshRateConfigs>&, ISchedulerCallback&) override;      sp<SurfaceInterceptor> createSurfaceInterceptor() override;      sp<StartPropertySetThread> createStartPropertySetThread(bool timestampPropertyValue) override;      sp<DisplayDevice> createDisplayDevice(DisplayDeviceCreationArgs&) override; diff --git a/services/surfaceflinger/SurfaceFlingerFactory.h b/services/surfaceflinger/SurfaceFlingerFactory.h index 885297fc30..13c95ddd15 100644 --- a/services/surfaceflinger/SurfaceFlingerFactory.h +++ b/services/surfaceflinger/SurfaceFlingerFactory.h @@ -79,8 +79,8 @@ public:      virtual std::unique_ptr<MessageQueue> createMessageQueue() = 0;      virtual std::unique_ptr<scheduler::VsyncConfiguration> createVsyncConfiguration(              Fps currentRefreshRate) = 0; -    virtual std::unique_ptr<Scheduler> createScheduler(const scheduler::RefreshRateConfigs&, -                                                       ISchedulerCallback&) = 0; +    virtual std::unique_ptr<Scheduler> createScheduler( +            const std::shared_ptr<scheduler::RefreshRateConfigs>&, ISchedulerCallback&) = 0;      virtual sp<SurfaceInterceptor> createSurfaceInterceptor() = 0;      virtual sp<StartPropertySetThread> createStartPropertySetThread( diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 23ab7c8bab..1f08a1db8b 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -161,6 +161,7 @@ void SurfaceInterceptor::addInitialDisplayStateLocked(Increment* increment,      addDisplaySurfaceLocked(transaction, display.sequenceId, display.surface);      addDisplayLayerStackLocked(transaction, display.sequenceId, display.layerStack); +    addDisplayFlagsLocked(transaction, display.sequenceId, display.flags);      addDisplaySizeLocked(transaction, display.sequenceId, display.width, display.height);      addDisplayProjectionLocked(transaction, display.sequenceId, toRotationInt(display.orientation),                                 display.layerStackSpaceRect, display.orientedDisplaySpaceRect); @@ -485,6 +486,9 @@ void SurfaceInterceptor::addDisplayChangesLocked(Transaction* transaction,      if (state.what & DisplayState::eLayerStackChanged) {          addDisplayLayerStackLocked(transaction, sequenceId, state.layerStack);      } +    if (state.what & DisplayState::eFlagsChanged) { +        addDisplayFlagsLocked(transaction, sequenceId, state.flags); +    }      if (state.what & DisplayState::eDisplaySizeChanged) {          addDisplaySizeLocked(transaction, sequenceId, state.width, state.height);      } @@ -576,6 +580,13 @@ void SurfaceInterceptor::addDisplayLayerStackLocked(Transaction* transaction,      layerStackChange->set_layer_stack(layerStack);  } +void SurfaceInterceptor::addDisplayFlagsLocked(Transaction* transaction, int32_t sequenceId, +                                               uint32_t flags) { +    DisplayChange* dispChange(createDisplayChangeLocked(transaction, sequenceId)); +    DisplayFlagsChange* flagsChange(dispChange->mutable_flags()); +    flagsChange->set_flags(flags); +} +  void SurfaceInterceptor::addDisplaySizeLocked(Transaction* transaction, int32_t sequenceId,          uint32_t w, uint32_t h)  { diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h index 673f9e789d..cc7e26e4d1 100644 --- a/services/surfaceflinger/SurfaceInterceptor.h +++ b/services/surfaceflinger/SurfaceInterceptor.h @@ -185,6 +185,7 @@ private:              const sp<const IGraphicBufferProducer>& surface);      void addDisplayLayerStackLocked(Transaction* transaction, int32_t sequenceId,              uint32_t layerStack); +    void addDisplayFlagsLocked(Transaction* transaction, int32_t sequenceId, uint32_t flags);      void addDisplaySizeLocked(Transaction* transaction, int32_t sequenceId, uint32_t w,              uint32_t h);      void addDisplayProjectionLocked(Transaction* transaction, int32_t sequenceId, diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.cpp b/services/surfaceflinger/WindowInfosListenerInvoker.cpp new file mode 100644 index 0000000000..55136fb835 --- /dev/null +++ b/services/surfaceflinger/WindowInfosListenerInvoker.cpp @@ -0,0 +1,65 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "WindowInfosListenerInvoker.h" +#include <gui/ISurfaceComposer.h> +#include <unordered_set> + +namespace android { + +using gui::IWindowInfosListener; +using gui::WindowInfo; + +void WindowInfosListenerInvoker::addWindowInfosListener( +        const sp<IWindowInfosListener>& windowInfosListener) { +    sp<IBinder> asBinder = IInterface::asBinder(windowInfosListener); + +    asBinder->linkToDeath(this); +    std::scoped_lock lock(mListenersMutex); +    mWindowInfosListeners.emplace(asBinder, windowInfosListener); +} + +void WindowInfosListenerInvoker::removeWindowInfosListener( +        const sp<IWindowInfosListener>& windowInfosListener) { +    sp<IBinder> asBinder = IInterface::asBinder(windowInfosListener); + +    std::scoped_lock lock(mListenersMutex); +    asBinder->unlinkToDeath(this); +    mWindowInfosListeners.erase(asBinder); +} + +void WindowInfosListenerInvoker::binderDied(const wp<IBinder>& who) { +    std::scoped_lock lock(mListenersMutex); +    mWindowInfosListeners.erase(who); +} + +void WindowInfosListenerInvoker::windowInfosChanged(const std::vector<WindowInfo>& windowInfos) { +    std::unordered_set<sp<IWindowInfosListener>, ISurfaceComposer::SpHash<IWindowInfosListener>> +            windowInfosListeners; + +    { +        std::scoped_lock lock(mListenersMutex); +        for (const auto& [_, listener] : mWindowInfosListeners) { +            windowInfosListeners.insert(listener); +        } +    } + +    for (const auto& listener : windowInfosListeners) { +        listener->onWindowInfosChanged(windowInfos); +    } +} + +} // namespace android
\ No newline at end of file diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.h b/services/surfaceflinger/WindowInfosListenerInvoker.h new file mode 100644 index 0000000000..b979de1f70 --- /dev/null +++ b/services/surfaceflinger/WindowInfosListenerInvoker.h @@ -0,0 +1,47 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <android/gui/IWindowInfosListener.h> +#include <binder/IBinder.h> +#include <utils/Mutex.h> +#include <unordered_map> + +namespace android { + +class WindowInfosListenerInvoker : public IBinder::DeathRecipient { +public: +    void addWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener); +    void removeWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener); + +    void windowInfosChanged(const std::vector<gui::WindowInfo>& windowInfos); + +protected: +    void binderDied(const wp<IBinder>& who) override; + +private: +    struct WpHash { +        size_t operator()(const wp<IBinder>& p) const { +            return std::hash<IBinder*>()(p.unsafe_get()); +        } +    }; + +    std::mutex mListenersMutex; +    std::unordered_map<wp<IBinder>, const sp<gui::IWindowInfosListener>, WpHash> +            mWindowInfosListeners GUARDED_BY(mListenersMutex); +}; +} // namespace android
\ No newline at end of file diff --git a/services/surfaceflinger/tests/RefreshRateOverlay_test.cpp b/services/surfaceflinger/tests/RefreshRateOverlay_test.cpp index 05858bf839..fb4458a27e 100644 --- a/services/surfaceflinger/tests/RefreshRateOverlay_test.cpp +++ b/services/surfaceflinger/tests/RefreshRateOverlay_test.cpp @@ -20,6 +20,10 @@  #include <gui/SurfaceComposerClient.h>  #include <private/gui/ComposerService.h> +#include <chrono> + +using ::std::literals::chrono_literals::operator""ms; +using ::std::literals::chrono_literals::operator""s;  static constexpr int kRefreshRateOverlayCode = 1034;  static constexpr int kRefreshRateOverlayEnable = 1; diff --git a/services/surfaceflinger/tests/ScreenCapture_test.cpp b/services/surfaceflinger/tests/ScreenCapture_test.cpp index 6912fcf219..ab2064efd0 100644 --- a/services/surfaceflinger/tests/ScreenCapture_test.cpp +++ b/services/surfaceflinger/tests/ScreenCapture_test.cpp @@ -515,7 +515,8 @@ TEST_F(ScreenCaptureTest, CaptureSize) {  }  TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { -    sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0); +    sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, +                                              ISurfaceComposerClient::eFXSurfaceBufferState);      ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); @@ -532,6 +533,21 @@ TEST_F(ScreenCaptureTest, CaptureInvalidLayer) {      ASSERT_EQ(NAME_NOT_FOUND, ScreenCapture::captureLayers(args, captureResults));  } +TEST_F(ScreenCaptureTest, CaptureTooLargeLayer) { +    sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60); +    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); + +    Transaction().show(redLayer).setLayer(redLayer, INT32_MAX).apply(true); + +    LayerCaptureArgs captureArgs; +    captureArgs.layerHandle = redLayer->getHandle(); +    captureArgs.frameScaleX = INT32_MAX / 60; +    captureArgs.frameScaleY = INT32_MAX / 60; + +    ScreenCaptureResults captureResults; +    ASSERT_EQ(BAD_VALUE, ScreenCapture::captureLayers(captureArgs, captureResults)); +} +  TEST_F(ScreenCaptureTest, CaptureSecureLayer) {      sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60,                                                ISurfaceComposerClient::eFXSurfaceBufferState); diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index b5086fafb7..9e704c32fc 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -51,6 +51,7 @@ cc_test {          "DisplayIdGeneratorTest.cpp",          "DisplayTransactionTest.cpp",          "DisplayDevice_GetBestColorModeTest.cpp", +        "DisplayDevice_InitiateModeChange.cpp",          "DisplayDevice_SetProjectionTest.cpp",          "EventThreadTest.cpp",          "FpsReporterTest.cpp", diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 560f139719..52a36a2719 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -108,6 +108,8 @@ public:          mComposer = new Hwc2::mock::Composer();          mFlinger.setupComposer(std::unique_ptr<Hwc2::Composer>(mComposer)); + +        mFlinger.mutableMaxRenderTargetSize() = 16384;      }      ~CompositionTest() { @@ -519,8 +521,6 @@ struct BaseLayerProperties {      static void setupLatchedBuffer(CompositionTest* test, sp<BufferQueueLayer> layer) {          // TODO: Eliminate the complexity of actually creating a buffer -        EXPECT_CALL(*test->mRenderEngine, getMaxTextureSize()).WillOnce(Return(16384)); -        EXPECT_CALL(*test->mRenderEngine, getMaxViewportDims()).WillOnce(Return(16384));          status_t err =                  layer->setDefaultBufferProperties(LayerProperties::WIDTH, LayerProperties::HEIGHT,                                                    LayerProperties::FORMAT); diff --git a/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp b/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp new file mode 100644 index 0000000000..d4cfbbbe0c --- /dev/null +++ b/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp @@ -0,0 +1,173 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#undef LOG_TAG +#define LOG_TAG "LibSurfaceFlingerUnittests" + +#include "DisplayTransactionTestHelpers.h" + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +namespace android { +namespace { + +using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector; + +class InitiateModeChangeTest : public DisplayTransactionTest { +public: +    using Event = scheduler::RefreshRateConfigEvent; + +    void SetUp() override { +        injectFakeBufferQueueFactory(); +        injectFakeNativeWindowSurfaceFactory(); + +        PrimaryDisplayVariant::setupHwcHotplugCallExpectations(this); +        PrimaryDisplayVariant::setupFramebufferConsumerBufferQueueCallExpectations(this); +        PrimaryDisplayVariant::setupFramebufferProducerBufferQueueCallExpectations(this); +        PrimaryDisplayVariant::setupNativeWindowSurfaceCreationCallExpectations(this); +        PrimaryDisplayVariant::setupHwcGetActiveConfigCallExpectations(this); + +        mFlinger.onComposerHalHotplug(PrimaryDisplayVariant::HWC_DISPLAY_ID, Connection::CONNECTED); + +        mDisplay = PrimaryDisplayVariant::makeFakeExistingDisplayInjector(this) +                           .setSupportedModes({kDisplayMode60, kDisplayMode90, kDisplayMode120}) +                           .setActiveMode(kDisplayModeId60) +                           .inject(); +    } + +protected: +    sp<DisplayDevice> mDisplay; + +    const DisplayModeId kDisplayModeId60 = DisplayModeId(0); +    const DisplayModePtr kDisplayMode60 = +            DisplayMode::Builder(hal::HWConfigId(kDisplayModeId60.value())) +                    .setId(kDisplayModeId60) +                    .setPhysicalDisplayId(PrimaryDisplayVariant::DISPLAY_ID::get()) +                    .setVsyncPeriod(int32_t(16'666'667)) +                    .setGroup(0) +                    .setHeight(1000) +                    .setWidth(1000) +                    .build(); + +    const DisplayModeId kDisplayModeId90 = DisplayModeId(1); +    const DisplayModePtr kDisplayMode90 = +            DisplayMode::Builder(hal::HWConfigId(kDisplayModeId90.value())) +                    .setId(kDisplayModeId90) +                    .setPhysicalDisplayId(PrimaryDisplayVariant::DISPLAY_ID::get()) +                    .setVsyncPeriod(int32_t(11'111'111)) +                    .setGroup(0) +                    .setHeight(1000) +                    .setWidth(1000) +                    .build(); + +    const DisplayModeId kDisplayModeId120 = DisplayModeId(2); +    const DisplayModePtr kDisplayMode120 = +            DisplayMode::Builder(hal::HWConfigId(kDisplayModeId120.value())) +                    .setId(kDisplayModeId120) +                    .setPhysicalDisplayId(PrimaryDisplayVariant::DISPLAY_ID::get()) +                    .setVsyncPeriod(int32_t(8'333'333)) +                    .setGroup(0) +                    .setHeight(1000) +                    .setWidth(1000) +                    .build(); +}; + +TEST_F(InitiateModeChangeTest, setDesiredActiveMode_setCurrentMode) { +    EXPECT_FALSE(mDisplay->setDesiredActiveMode({kDisplayMode60, Event::None})); +    EXPECT_EQ(std::nullopt, mDisplay->getDesiredActiveMode()); +} + +TEST_F(InitiateModeChangeTest, setDesiredActiveMode_setNewMode) { +    EXPECT_TRUE(mDisplay->setDesiredActiveMode({kDisplayMode90, Event::None})); +    ASSERT_NE(std::nullopt, mDisplay->getDesiredActiveMode()); +    EXPECT_EQ(kDisplayMode90, mDisplay->getDesiredActiveMode()->mode); +    EXPECT_EQ(Event::None, mDisplay->getDesiredActiveMode()->event); + +    // Setting another mode should be cached but return false +    EXPECT_FALSE(mDisplay->setDesiredActiveMode({kDisplayMode120, Event::None})); +    ASSERT_NE(std::nullopt, mDisplay->getDesiredActiveMode()); +    EXPECT_EQ(kDisplayMode120, mDisplay->getDesiredActiveMode()->mode); +    EXPECT_EQ(Event::None, mDisplay->getDesiredActiveMode()->event); +} + +TEST_F(InitiateModeChangeTest, clearDesiredActiveModeState) { +    EXPECT_TRUE(mDisplay->setDesiredActiveMode({kDisplayMode90, Event::None})); +    ASSERT_NE(std::nullopt, mDisplay->getDesiredActiveMode()); + +    mDisplay->clearDesiredActiveModeState(); +    ASSERT_EQ(std::nullopt, mDisplay->getDesiredActiveMode()); +} + +TEST_F(InitiateModeChangeTest, initiateModeChange) NO_THREAD_SAFETY_ANALYSIS { +    EXPECT_TRUE(mDisplay->setDesiredActiveMode({kDisplayMode90, Event::None})); +    ASSERT_NE(std::nullopt, mDisplay->getDesiredActiveMode()); +    EXPECT_EQ(kDisplayMode90, mDisplay->getDesiredActiveMode()->mode); +    EXPECT_EQ(Event::None, mDisplay->getDesiredActiveMode()->event); + +    hal::VsyncPeriodChangeConstraints constraints{ +            .desiredTimeNanos = systemTime(), +            .seamlessRequired = false, +    }; +    hal::VsyncPeriodChangeTimeline timeline; +    EXPECT_EQ(OK, +              mDisplay->initiateModeChange(*mDisplay->getDesiredActiveMode(), constraints, +                                           &timeline)); +    EXPECT_EQ(kDisplayMode90, mDisplay->getUpcomingActiveMode().mode); +    EXPECT_EQ(Event::None, mDisplay->getUpcomingActiveMode().event); + +    mDisplay->clearDesiredActiveModeState(); +    ASSERT_EQ(std::nullopt, mDisplay->getDesiredActiveMode()); +} + +TEST_F(InitiateModeChangeTest, getUpcomingActiveMode_desiredActiveModeChanged) +NO_THREAD_SAFETY_ANALYSIS { +    EXPECT_TRUE(mDisplay->setDesiredActiveMode({kDisplayMode90, Event::None})); +    ASSERT_NE(std::nullopt, mDisplay->getDesiredActiveMode()); +    EXPECT_EQ(kDisplayMode90, mDisplay->getDesiredActiveMode()->mode); +    EXPECT_EQ(Event::None, mDisplay->getDesiredActiveMode()->event); + +    hal::VsyncPeriodChangeConstraints constraints{ +            .desiredTimeNanos = systemTime(), +            .seamlessRequired = false, +    }; +    hal::VsyncPeriodChangeTimeline timeline; +    EXPECT_EQ(OK, +              mDisplay->initiateModeChange(*mDisplay->getDesiredActiveMode(), constraints, +                                           &timeline)); +    EXPECT_EQ(kDisplayMode90, mDisplay->getUpcomingActiveMode().mode); +    EXPECT_EQ(Event::None, mDisplay->getUpcomingActiveMode().event); + +    EXPECT_FALSE(mDisplay->setDesiredActiveMode({kDisplayMode120, Event::None})); +    ASSERT_NE(std::nullopt, mDisplay->getDesiredActiveMode()); +    EXPECT_EQ(kDisplayMode120, mDisplay->getDesiredActiveMode()->mode); +    EXPECT_EQ(Event::None, mDisplay->getDesiredActiveMode()->event); + +    EXPECT_EQ(kDisplayMode90, mDisplay->getUpcomingActiveMode().mode); +    EXPECT_EQ(Event::None, mDisplay->getUpcomingActiveMode().event); + +    EXPECT_EQ(OK, +              mDisplay->initiateModeChange(*mDisplay->getDesiredActiveMode(), constraints, +                                           &timeline)); +    EXPECT_EQ(kDisplayMode120, mDisplay->getUpcomingActiveMode().mode); +    EXPECT_EQ(Event::None, mDisplay->getUpcomingActiveMode().event); + +    mDisplay->clearDesiredActiveModeState(); +    ASSERT_EQ(std::nullopt, mDisplay->getDesiredActiveMode()); +} + +} // namespace +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h index 6ce281d403..de058a4f68 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h @@ -615,8 +615,8 @@ struct HwcVirtualDisplayVariant      }      static void setupHwcVirtualDisplayCreationCallExpectations(DisplayTransactionTest* test) { -        EXPECT_CALL(*test->mComposer, createVirtualDisplay(Base::WIDTH, Base::HEIGHT, _, _, _)) -                .WillOnce(DoAll(SetArgPointee<4>(Self::HWC_DISPLAY_ID), Return(Error::NONE))); +        EXPECT_CALL(*test->mComposer, createVirtualDisplay(Base::WIDTH, Base::HEIGHT, _, _)) +                .WillOnce(DoAll(SetArgPointee<3>(Self::HWC_DISPLAY_ID), Return(Error::NONE)));          EXPECT_CALL(*test->mComposer, setClientTargetSlotCount(_)).WillOnce(Return(Error::NONE));      }  }; diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp index b4a1481e9c..4ff7592b71 100644 --- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp +++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp @@ -543,17 +543,34 @@ TEST_F(EventThreadTest, postHotplugExternalConnect) {  }  TEST_F(EventThreadTest, postConfigChangedPrimary) { -    mThread->onModeChanged(INTERNAL_DISPLAY_ID, DisplayModeId(7), 16666666); +    const auto mode = DisplayMode::Builder(hal::HWConfigId(0)) +                              .setPhysicalDisplayId(INTERNAL_DISPLAY_ID) +                              .setId(DisplayModeId(7)) +                              .setVsyncPeriod(16666666) +                              .build(); + +    mThread->onModeChanged(mode);      expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 7, 16666666);  }  TEST_F(EventThreadTest, postConfigChangedExternal) { -    mThread->onModeChanged(EXTERNAL_DISPLAY_ID, DisplayModeId(5), 16666666); +    const auto mode = DisplayMode::Builder(hal::HWConfigId(0)) +                              .setPhysicalDisplayId(EXTERNAL_DISPLAY_ID) +                              .setId(DisplayModeId(5)) +                              .setVsyncPeriod(16666666) +                              .build(); + +    mThread->onModeChanged(mode);      expectConfigChangedEventReceivedByConnection(EXTERNAL_DISPLAY_ID, 5, 16666666);  }  TEST_F(EventThreadTest, postConfigChangedPrimary64bit) { -    mThread->onModeChanged(DISPLAY_ID_64BIT, DisplayModeId(7), 16666666); +    const auto mode = DisplayMode::Builder(hal::HWConfigId(0)) +                              .setPhysicalDisplayId(DISPLAY_ID_64BIT) +                              .setId(DisplayModeId(7)) +                              .setVsyncPeriod(16666666) +                              .build(); +    mThread->onModeChanged(mode);      expectConfigChangedEventReceivedByConnection(DISPLAY_ID_64BIT, 7, 16666666);  } @@ -562,7 +579,13 @@ TEST_F(EventThreadTest, suppressConfigChanged) {      sp<MockEventThreadConnection> suppressConnection =              createConnection(suppressConnectionEventRecorder); -    mThread->onModeChanged(INTERNAL_DISPLAY_ID, DisplayModeId(9), 16666666); +    const auto mode = DisplayMode::Builder(hal::HWConfigId(0)) +                              .setPhysicalDisplayId(INTERNAL_DISPLAY_ID) +                              .setId(DisplayModeId(9)) +                              .setVsyncPeriod(16666666) +                              .build(); + +    mThread->onModeChanged(mode);      expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 9, 16666666);      auto args = suppressConnectionEventRecorder.waitForCall(); diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index b67ebcaa49..02ec7fc493 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -35,6 +35,7 @@  using testing::_;  using testing::Return; +using testing::ReturnRef;  namespace android { @@ -62,6 +63,10 @@ protected:      LayerHistory& history() { return *mScheduler->mutableLayerHistory(); }      const LayerHistory& history() const { return *mScheduler->mutableLayerHistory(); } +    LayerHistory::Summary summarizeLayerHistory(nsecs_t now) { +        return history().summarize(*mScheduler->refreshRateConfigs(), now); +    } +      size_t layerCount() const { return mScheduler->layerHistorySize(); }      size_t activeLayerCount() const NO_THREAD_SAFETY_ANALYSIS { return history().mActiveLayersEnd; } @@ -101,7 +106,7 @@ protected:              history().record(layer.get(), time, time, LayerHistory::LayerUpdateType::Buffer);              time += frameRate.getPeriodNsecs(); -            summary = history().summarize(time); +            summary = summarizeLayerHistory(time);          }          ASSERT_EQ(1, summary.size()); @@ -110,21 +115,24 @@ protected:                  << "Frame rate is " << frameRate;      } -    RefreshRateConfigs mConfigs{{DisplayMode::Builder(0) -                                         .setId(DisplayModeId(0)) -                                         .setVsyncPeriod(int32_t(LO_FPS_PERIOD)) -                                         .setGroup(0) -                                         .build(), -                                 DisplayMode::Builder(1) -                                         .setId(DisplayModeId(1)) -                                         .setVsyncPeriod(int32_t(HI_FPS_PERIOD)) -                                         .setGroup(0) -                                         .build()}, -                                DisplayModeId(0)}; - -    mock::NoOpSchedulerCallback mSchedulerCallback; - -    TestableScheduler* const mScheduler = new TestableScheduler(mConfigs, mSchedulerCallback); +    std::shared_ptr<RefreshRateConfigs> mConfigs = std::make_shared< +            RefreshRateConfigs>(DisplayModes{DisplayMode::Builder(0) +                                                     .setId(DisplayModeId(0)) +                                                     .setPhysicalDisplayId(PhysicalDisplayId(0)) +                                                     .setVsyncPeriod(int32_t(LO_FPS_PERIOD)) +                                                     .setGroup(0) +                                                     .build(), +                                             DisplayMode::Builder(1) +                                                     .setId(DisplayModeId(1)) +                                                     .setPhysicalDisplayId(PhysicalDisplayId(0)) +                                                     .setVsyncPeriod(int32_t(HI_FPS_PERIOD)) +                                                     .setGroup(0) +                                                     .build()}, +                                DisplayModeId(0)); + +    mock::SchedulerCallback mSchedulerCallback; + +    TestableScheduler* mScheduler = new TestableScheduler(mConfigs, mSchedulerCallback);      TestableSurfaceFlinger mFlinger;  }; @@ -142,22 +150,22 @@ TEST_F(LayerHistoryTest, oneLayer) {      const nsecs_t time = systemTime();      // No layers returned if no layers are active. -    EXPECT_TRUE(history().summarize(time).empty()); +    EXPECT_TRUE(summarizeLayerHistory(time).empty());      EXPECT_EQ(0, activeLayerCount());      // Max returned if active layers have insufficient history.      for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) {          history().record(layer.get(), 0, time, LayerHistory::LayerUpdateType::Buffer); -        ASSERT_EQ(1, history().summarize(time).size()); -        EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); +        ASSERT_EQ(1, summarizeLayerHistory(time).size()); +        EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);          EXPECT_EQ(1, activeLayerCount());      }      // Max is returned since we have enough history but there is no timestamp votes.      for (int i = 0; i < 10; i++) {          history().record(layer.get(), 0, time, LayerHistory::LayerUpdateType::Buffer); -        ASSERT_EQ(1, history().summarize(time).size()); -        EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); +        ASSERT_EQ(1, summarizeLayerHistory(time).size()); +        EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);          EXPECT_EQ(1, activeLayerCount());      }  } @@ -173,17 +181,17 @@ TEST_F(LayerHistoryTest, oneInvisibleLayer) {      nsecs_t time = systemTime();      history().record(layer.get(), 0, time, LayerHistory::LayerUpdateType::Buffer); -    auto summary = history().summarize(time); -    ASSERT_EQ(1, history().summarize(time).size()); +    auto summary = summarizeLayerHistory(time); +    ASSERT_EQ(1, summarizeLayerHistory(time).size());      // Layer is still considered inactive so we expect to get Min -    EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); +    EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);      EXPECT_EQ(1, activeLayerCount());      EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false));      history().record(layer.get(), 0, time, LayerHistory::LayerUpdateType::Buffer); -    summary = history().summarize(time); -    EXPECT_TRUE(history().summarize(time).empty()); +    summary = summarizeLayerHistory(time); +    EXPECT_TRUE(summarizeLayerHistory(time).empty());      EXPECT_EQ(0, activeLayerCount());  } @@ -201,9 +209,9 @@ TEST_F(LayerHistoryTest, explicitTimestamp) {          time += LO_FPS_PERIOD;      } -    ASSERT_EQ(1, history().summarize(time).size()); -    EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote); -    EXPECT_TRUE(LO_FPS.equalsWithMargin(history().summarize(time)[0].desiredRefreshRate)); +    ASSERT_EQ(1, summarizeLayerHistory(time).size()); +    EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summarizeLayerHistory(time)[0].vote); +    EXPECT_TRUE(LO_FPS.equalsWithMargin(summarizeLayerHistory(time)[0].desiredRefreshRate));      EXPECT_EQ(1, activeLayerCount());      EXPECT_EQ(1, frequentLayerCount(time));  } @@ -224,13 +232,13 @@ TEST_F(LayerHistoryTest, oneLayerNoVote) {          time += HI_FPS_PERIOD;      } -    ASSERT_TRUE(history().summarize(time).empty()); +    ASSERT_TRUE(summarizeLayerHistory(time).empty());      EXPECT_EQ(1, activeLayerCount());      EXPECT_EQ(1, frequentLayerCount(time));      // layer became inactive      time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); -    ASSERT_TRUE(history().summarize(time).empty()); +    ASSERT_TRUE(summarizeLayerHistory(time).empty());      EXPECT_EQ(0, activeLayerCount());      EXPECT_EQ(0, frequentLayerCount(time));  } @@ -251,14 +259,14 @@ TEST_F(LayerHistoryTest, oneLayerMinVote) {          time += HI_FPS_PERIOD;      } -    ASSERT_EQ(1, history().summarize(time).size()); -    EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); +    ASSERT_EQ(1, summarizeLayerHistory(time).size()); +    EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote);      EXPECT_EQ(1, activeLayerCount());      EXPECT_EQ(1, frequentLayerCount(time));      // layer became inactive      time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); -    ASSERT_TRUE(history().summarize(time).empty()); +    ASSERT_TRUE(summarizeLayerHistory(time).empty());      EXPECT_EQ(0, activeLayerCount());      EXPECT_EQ(0, frequentLayerCount(time));  } @@ -279,14 +287,14 @@ TEST_F(LayerHistoryTest, oneLayerMaxVote) {          time += LO_FPS_PERIOD;      } -    ASSERT_EQ(1, history().summarize(time).size()); -    EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); +    ASSERT_EQ(1, summarizeLayerHistory(time).size()); +    EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);      EXPECT_EQ(1, activeLayerCount());      EXPECT_EQ(1, frequentLayerCount(time));      // layer became inactive      time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); -    ASSERT_TRUE(history().summarize(time).empty()); +    ASSERT_TRUE(summarizeLayerHistory(time).empty());      EXPECT_EQ(0, activeLayerCount());      EXPECT_EQ(0, frequentLayerCount(time));  } @@ -307,18 +315,18 @@ TEST_F(LayerHistoryTest, oneLayerExplicitVote) {          time += HI_FPS_PERIOD;      } -    ASSERT_EQ(1, history().summarize(time).size()); -    EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, history().summarize(time)[0].vote); -    EXPECT_TRUE(Fps(73.4f).equalsWithMargin(history().summarize(time)[0].desiredRefreshRate)); +    ASSERT_EQ(1, summarizeLayerHistory(time).size()); +    EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, summarizeLayerHistory(time)[0].vote); +    EXPECT_TRUE(Fps(73.4f).equalsWithMargin(summarizeLayerHistory(time)[0].desiredRefreshRate));      EXPECT_EQ(1, activeLayerCount());      EXPECT_EQ(1, frequentLayerCount(time));      // layer became inactive, but the vote stays      setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Heuristic);      time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); -    ASSERT_EQ(1, history().summarize(time).size()); -    EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, history().summarize(time)[0].vote); -    EXPECT_TRUE(Fps(73.4f).equalsWithMargin(history().summarize(time)[0].desiredRefreshRate)); +    ASSERT_EQ(1, summarizeLayerHistory(time).size()); +    EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, summarizeLayerHistory(time)[0].vote); +    EXPECT_TRUE(Fps(73.4f).equalsWithMargin(summarizeLayerHistory(time)[0].desiredRefreshRate));      EXPECT_EQ(1, activeLayerCount());      EXPECT_EQ(0, frequentLayerCount(time));  } @@ -339,20 +347,20 @@ TEST_F(LayerHistoryTest, oneLayerExplicitExactVote) {          time += HI_FPS_PERIOD;      } -    ASSERT_EQ(1, history().summarize(time).size()); +    ASSERT_EQ(1, summarizeLayerHistory(time).size());      EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, -              history().summarize(time)[0].vote); -    EXPECT_TRUE(Fps(73.4f).equalsWithMargin(history().summarize(time)[0].desiredRefreshRate)); +              summarizeLayerHistory(time)[0].vote); +    EXPECT_TRUE(Fps(73.4f).equalsWithMargin(summarizeLayerHistory(time)[0].desiredRefreshRate));      EXPECT_EQ(1, activeLayerCount());      EXPECT_EQ(1, frequentLayerCount(time));      // layer became inactive, but the vote stays      setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Heuristic);      time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); -    ASSERT_EQ(1, history().summarize(time).size()); +    ASSERT_EQ(1, summarizeLayerHistory(time).size());      EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, -              history().summarize(time)[0].vote); -    EXPECT_TRUE(Fps(73.4f).equalsWithMargin(history().summarize(time)[0].desiredRefreshRate)); +              summarizeLayerHistory(time)[0].vote); +    EXPECT_TRUE(Fps(73.4f).equalsWithMargin(summarizeLayerHistory(time)[0].desiredRefreshRate));      EXPECT_EQ(1, activeLayerCount());      EXPECT_EQ(0, frequentLayerCount(time));  } @@ -383,7 +391,7 @@ TEST_F(LayerHistoryTest, multipleLayers) {      for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {          history().record(layer1.get(), time, time, LayerHistory::LayerUpdateType::Buffer);          time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); -        summary = history().summarize(time); +        summary = summarizeLayerHistory(time);      }      ASSERT_EQ(1, summary.size()); @@ -395,7 +403,7 @@ TEST_F(LayerHistoryTest, multipleLayers) {      for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {          history().record(layer2.get(), time, time, LayerHistory::LayerUpdateType::Buffer);          time += HI_FPS_PERIOD; -        summary = history().summarize(time); +        summary = summarizeLayerHistory(time);      }      // layer1 is still active but infrequent. @@ -404,7 +412,7 @@ TEST_F(LayerHistoryTest, multipleLayers) {      ASSERT_EQ(2, summary.size());      EXPECT_EQ(LayerHistory::LayerVoteType::Min, summary[0].vote);      ASSERT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[1].vote); -    EXPECT_TRUE(HI_FPS.equalsWithMargin(history().summarize(time)[1].desiredRefreshRate)); +    EXPECT_TRUE(HI_FPS.equalsWithMargin(summarizeLayerHistory(time)[1].desiredRefreshRate));      EXPECT_EQ(2, activeLayerCount());      EXPECT_EQ(1, frequentLayerCount(time)); @@ -414,7 +422,7 @@ TEST_F(LayerHistoryTest, multipleLayers) {      for (int i = 0; i < 2 * PRESENT_TIME_HISTORY_SIZE; i++) {          history().record(layer2.get(), time, time, LayerHistory::LayerUpdateType::Buffer);          time += LO_FPS_PERIOD; -        summary = history().summarize(time); +        summary = summarizeLayerHistory(time);      }      ASSERT_EQ(1, summary.size()); @@ -433,7 +441,7 @@ TEST_F(LayerHistoryTest, multipleLayers) {          history().record(layer3.get(), time, time, LayerHistory::LayerUpdateType::Buffer);          time += HI_FPS_PERIOD; -        summary = history().summarize(time); +        summary = summarizeLayerHistory(time);      }      ASSERT_EQ(2, summary.size()); @@ -445,7 +453,7 @@ TEST_F(LayerHistoryTest, multipleLayers) {      // layer3 becomes recently active.      history().record(layer3.get(), time, time, LayerHistory::LayerUpdateType::Buffer); -    summary = history().summarize(time); +    summary = summarizeLayerHistory(time);      ASSERT_EQ(2, summary.size());      EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote);      EXPECT_TRUE(LO_FPS.equalsWithMargin(summary[0].desiredRefreshRate)); @@ -456,7 +464,7 @@ TEST_F(LayerHistoryTest, multipleLayers) {      // layer1 expires.      layer1.clear(); -    summary = history().summarize(time); +    summary = summarizeLayerHistory(time);      ASSERT_EQ(2, summary.size());      EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote);      EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); @@ -472,7 +480,7 @@ TEST_F(LayerHistoryTest, multipleLayers) {      for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {          history().record(layer2.get(), time, time, LayerHistory::LayerUpdateType::Buffer);          time += LO_FPS_PERIOD; -        summary = history().summarize(time); +        summary = summarizeLayerHistory(time);      }      ASSERT_EQ(1, summary.size()); @@ -483,7 +491,7 @@ TEST_F(LayerHistoryTest, multipleLayers) {      // layer2 expires.      layer2.clear(); -    summary = history().summarize(time); +    summary = summarizeLayerHistory(time);      EXPECT_TRUE(summary.empty());      EXPECT_EQ(1, layerCount());      EXPECT_EQ(0, activeLayerCount()); @@ -493,7 +501,7 @@ TEST_F(LayerHistoryTest, multipleLayers) {      for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE + FREQUENT_LAYER_WINDOW_SIZE + 1; i++) {          history().record(layer3.get(), time, time, LayerHistory::LayerUpdateType::Buffer);          time += HI_FPS_PERIOD; -        summary = history().summarize(time); +        summary = summarizeLayerHistory(time);      }      ASSERT_EQ(1, summary.size()); @@ -505,7 +513,7 @@ TEST_F(LayerHistoryTest, multipleLayers) {      // layer3 expires.      layer3.clear(); -    summary = history().summarize(time); +    summary = summarizeLayerHistory(time);      EXPECT_TRUE(summary.empty());      EXPECT_EQ(0, layerCount());      EXPECT_EQ(0, activeLayerCount()); @@ -526,8 +534,8 @@ TEST_F(LayerHistoryTest, inactiveLayers) {          time += MAX_FREQUENT_LAYER_PERIOD_NS.count();          EXPECT_EQ(1, layerCount()); -        ASSERT_EQ(1, history().summarize(time).size()); -        EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); +        ASSERT_EQ(1, summarizeLayerHistory(time).size()); +        EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);          EXPECT_EQ(1, activeLayerCount());          EXPECT_EQ(1, frequentLayerCount(time));      } @@ -537,8 +545,8 @@ TEST_F(LayerHistoryTest, inactiveLayers) {      time += MAX_FREQUENT_LAYER_PERIOD_NS.count();      EXPECT_EQ(1, layerCount()); -    ASSERT_EQ(1, history().summarize(time).size()); -    EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); +    ASSERT_EQ(1, summarizeLayerHistory(time).size()); +    EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote);      EXPECT_EQ(1, activeLayerCount());      EXPECT_EQ(0, frequentLayerCount(time)); @@ -551,8 +559,8 @@ TEST_F(LayerHistoryTest, inactiveLayers) {          time += HI_FPS_PERIOD;          EXPECT_EQ(1, layerCount()); -        ASSERT_EQ(1, history().summarize(time).size()); -        EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); +        ASSERT_EQ(1, summarizeLayerHistory(time).size()); +        EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote);          EXPECT_EQ(1, activeLayerCount());          EXPECT_EQ(0, frequentLayerCount(time));      } @@ -562,8 +570,8 @@ TEST_F(LayerHistoryTest, inactiveLayers) {      time += HI_FPS_PERIOD;      EXPECT_EQ(1, layerCount()); -    ASSERT_EQ(1, history().summarize(time).size()); -    EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); +    ASSERT_EQ(1, summarizeLayerHistory(time).size()); +    EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);      EXPECT_EQ(1, activeLayerCount());      EXPECT_EQ(1, frequentLayerCount(time));  } @@ -590,10 +598,10 @@ TEST_F(LayerHistoryTest, invisibleExplicitLayer) {                       LayerHistory::LayerUpdateType::Buffer);      EXPECT_EQ(2, layerCount()); -    ASSERT_EQ(1, history().summarize(time).size()); +    ASSERT_EQ(1, summarizeLayerHistory(time).size());      EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, -              history().summarize(time)[0].vote); -    EXPECT_TRUE(Fps(60.0f).equalsWithMargin(history().summarize(time)[0].desiredRefreshRate)); +              summarizeLayerHistory(time)[0].vote); +    EXPECT_TRUE(Fps(60.0f).equalsWithMargin(summarizeLayerHistory(time)[0].desiredRefreshRate));      EXPECT_EQ(2, activeLayerCount());      EXPECT_EQ(2, frequentLayerCount(time));  } @@ -617,8 +625,8 @@ TEST_F(LayerHistoryTest, infrequentAnimatingLayer) {          time += MAX_FREQUENT_LAYER_PERIOD_NS.count();      } -    ASSERT_EQ(1, history().summarize(time).size()); -    EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); +    ASSERT_EQ(1, summarizeLayerHistory(time).size()); +    EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote);      EXPECT_EQ(1, activeLayerCount());      EXPECT_EQ(0, frequentLayerCount(time));      EXPECT_EQ(0, animatingLayerCount(time)); @@ -627,8 +635,8 @@ TEST_F(LayerHistoryTest, infrequentAnimatingLayer) {      history().record(layer.get(), time, time, LayerHistory::LayerUpdateType::Buffer);      time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); -    ASSERT_EQ(1, history().summarize(time).size()); -    EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); +    ASSERT_EQ(1, summarizeLayerHistory(time).size()); +    EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote);      EXPECT_EQ(1, activeLayerCount());      EXPECT_EQ(0, frequentLayerCount(time));      EXPECT_EQ(0, animatingLayerCount(time)); @@ -637,8 +645,8 @@ TEST_F(LayerHistoryTest, infrequentAnimatingLayer) {      history().record(layer.get(), time, time, LayerHistory::LayerUpdateType::AnimationTX);      time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); -    ASSERT_EQ(1, history().summarize(time).size()); -    EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); +    ASSERT_EQ(1, summarizeLayerHistory(time).size()); +    EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);      EXPECT_EQ(1, activeLayerCount());      EXPECT_EQ(0, frequentLayerCount(time));      EXPECT_EQ(1, animatingLayerCount(time)); @@ -727,13 +735,13 @@ TEST_P(LayerHistoryTestParameterized, HeuristicLayerWithInfrequentLayer) {          }          if (time - startTime > PRESENT_TIME_HISTORY_DURATION.count()) { -            ASSERT_NE(0, history().summarize(time).size()); -            ASSERT_GE(2, history().summarize(time).size()); +            ASSERT_NE(0, summarizeLayerHistory(time).size()); +            ASSERT_GE(2, summarizeLayerHistory(time).size());              bool max = false;              bool min = false;              Fps heuristic{0.0}; -            for (const auto& layer : history().summarize(time)) { +            for (const auto& layer : summarizeLayerHistory(time)) {                  if (layer.vote == LayerHistory::LayerVoteType::Heuristic) {                      heuristic = layer.desiredRefreshRate;                  } else if (layer.vote == LayerHistory::LayerVoteType::Max) { @@ -746,7 +754,7 @@ TEST_P(LayerHistoryTestParameterized, HeuristicLayerWithInfrequentLayer) {              if (infrequentLayerUpdates > FREQUENT_LAYER_WINDOW_SIZE) {                  EXPECT_TRUE(Fps(24.0f).equalsWithMargin(heuristic));                  EXPECT_FALSE(max); -                if (history().summarize(time).size() == 2) { +                if (summarizeLayerHistory(time).size() == 2) {                      EXPECT_TRUE(min);                  }              } diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index 3423bd590b..6870fd45fb 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -51,8 +51,7 @@ protected:      ~RefreshRateConfigsTest();      RefreshRate createRefreshRate(DisplayModePtr displayMode) { -        return {displayMode->getId(), displayMode, displayMode->getFps(), -                RefreshRate::ConstructorTag(0)}; +        return {displayMode, RefreshRate::ConstructorTag(0)};      }      Fps findClosestKnownFrameRate(const RefreshRateConfigs& refreshRateConfigs, Fps frameRate) { @@ -147,24 +146,17 @@ protected:      DisplayModes m60_120Device = {mConfig60, mConfig120};      // Expected RefreshRate objects -    RefreshRate mExpected60Config = {HWC_CONFIG_ID_60, mConfig60, Fps(60), -                                     RefreshRate::ConstructorTag(0)}; -    RefreshRate mExpectedAlmost60Config = {HWC_CONFIG_ID_60, -                                           createDisplayMode(HWC_CONFIG_ID_60, 0, 16666665), -                                           Fps(60), RefreshRate::ConstructorTag(0)}; -    RefreshRate mExpected90Config = {HWC_CONFIG_ID_90, mConfig90, Fps(90), -                                     RefreshRate::ConstructorTag(0)}; -    RefreshRate mExpected90DifferentGroupConfig = {HWC_CONFIG_ID_90, mConfig90DifferentGroup, -                                                   Fps(90), RefreshRate::ConstructorTag(0)}; -    RefreshRate mExpected90DifferentResolutionConfig = {HWC_CONFIG_ID_90, -                                                        mConfig90DifferentResolution, Fps(90), +    RefreshRate mExpected60Config = {mConfig60, RefreshRate::ConstructorTag(0)}; +    RefreshRate mExpectedAlmost60Config = {createDisplayMode(HWC_CONFIG_ID_60, 0, 16666665), +                                           RefreshRate::ConstructorTag(0)}; +    RefreshRate mExpected90Config = {mConfig90, RefreshRate::ConstructorTag(0)}; +    RefreshRate mExpected90DifferentGroupConfig = {mConfig90DifferentGroup, +                                                   RefreshRate::ConstructorTag(0)}; +    RefreshRate mExpected90DifferentResolutionConfig = {mConfig90DifferentResolution,                                                          RefreshRate::ConstructorTag(0)}; -    RefreshRate mExpected72Config = {HWC_CONFIG_ID_72, mConfig72, Fps(72.0f), -                                     RefreshRate::ConstructorTag(0)}; -    RefreshRate mExpected30Config = {HWC_CONFIG_ID_30, mConfig30, Fps(30), -                                     RefreshRate::ConstructorTag(0)}; -    RefreshRate mExpected120Config = {HWC_CONFIG_ID_120, mConfig120, Fps(120), -                                      RefreshRate::ConstructorTag(0)}; +    RefreshRate mExpected72Config = {mConfig72, RefreshRate::ConstructorTag(0)}; +    RefreshRate mExpected30Config = {mConfig30, RefreshRate::ConstructorTag(0)}; +    RefreshRate mExpected120Config = {mConfig120, RefreshRate::ConstructorTag(0)};  private:      DisplayModePtr createDisplayMode(DisplayModeId modeId, int32_t group, int64_t vsyncPeriod, @@ -189,6 +181,7 @@ DisplayModePtr RefreshRateConfigsTest::createDisplayMode(DisplayModeId modeId, i                                                           int64_t vsyncPeriod, ui::Size resolution) {      return DisplayMode::Builder(hal::HWConfigId(modeId.value()))              .setId(modeId) +            .setPhysicalDisplayId(PhysicalDisplayId(0))              .setVsyncPeriod(int32_t(vsyncPeriod))              .setGroup(group)              .setHeight(resolution.height) @@ -2272,26 +2265,6 @@ TEST_F(RefreshRateConfigsTest, getFrameRateOverrides_touch) {      ASSERT_TRUE(frameRateOverrides.empty());  } -TEST_F(RefreshRateConfigsTest, updateDisplayModes) { -    auto refreshRateConfigs = -            std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device, -                                                 /*currentConfigId=*/HWC_CONFIG_ID_30); -    refreshRateConfigs->setDisplayManagerPolicy({DisplayModeId(HWC_CONFIG_ID_30), -                                                 /* allowGroupSwitching */ false, -                                                 /* range */ {Fps(30.0f), Fps(30.0f)}}); - -    refreshRateConfigs->updateDisplayModes(m60_90Device, HWC_CONFIG_ID_60); - -    const auto currentRefreshRate = refreshRateConfigs->getCurrentRefreshRate(); -    EXPECT_TRUE(currentRefreshRate.getFps().equalsWithMargin(Fps(60.0))); -    EXPECT_EQ(currentRefreshRate.getModeId(), HWC_CONFIG_ID_60); - -    EXPECT_TRUE( -            getMaxSupportedRefreshRate(*refreshRateConfigs).getFps().equalsWithMargin(Fps(90.0))); -    EXPECT_TRUE( -            getMinSupportedRefreshRate(*refreshRateConfigs).getFps().equalsWithMargin(Fps(60.0))); -} -  } // namespace  } // namespace scheduler  } // namespace android diff --git a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp index bf07106afd..12b155bd2c 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp @@ -81,6 +81,7 @@ DisplayModePtr RefreshRateStatsTest::createDisplayMode(DisplayModeId modeId, int                                                         int64_t vsyncPeriod) {      return DisplayMode::Builder(static_cast<hal::HWConfigId>(modeId.value()))              .setId(modeId) +            .setPhysicalDisplayId(PhysicalDisplayId(0))              .setVsyncPeriod(static_cast<int32_t>(vsyncPeriod))              .setGroup(group)              .build(); diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index f680d802e6..5713c2f64a 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -53,16 +53,19 @@ protected:      const DisplayModePtr mode60 = DisplayMode::Builder(0)                                            .setId(DisplayModeId(0)) +                                          .setPhysicalDisplayId(PhysicalDisplayId(0))                                            .setVsyncPeriod(Fps(60.f).getPeriodNsecs())                                            .setGroup(0)                                            .build();      const DisplayModePtr mode120 = DisplayMode::Builder(1)                                             .setId(DisplayModeId(1)) +                                           .setPhysicalDisplayId(PhysicalDisplayId(0))                                             .setVsyncPeriod(Fps(120.f).getPeriodNsecs())                                             .setGroup(0)                                             .build(); -    scheduler::RefreshRateConfigs mConfigs{{mode60}, mode60->getId()}; +    std::shared_ptr<scheduler::RefreshRateConfigs> mConfigs = +            std::make_shared<scheduler::RefreshRateConfigs>(DisplayModes{mode60}, mode60->getId());      mock::SchedulerCallback mSchedulerCallback; @@ -171,7 +174,7 @@ TEST_F(SchedulerTest, chooseRefreshRateForContentIsNoopWhenModeSwitchingIsNotSup      mScheduler->setDisplayPowerState(kPowerStateNormal);      constexpr uint32_t kDisplayArea = 999'999; -    mScheduler->onPrimaryDisplayAreaChanged(kDisplayArea); +    mScheduler->onActiveDisplayAreaChanged(kDisplayArea);      EXPECT_CALL(mSchedulerCallback, changeRefreshRate(_, _)).Times(0);      mScheduler->chooseRefreshRateForContent(); @@ -182,7 +185,9 @@ TEST_F(SchedulerTest, updateDisplayModes) {      sp<mock::MockLayer> layer = sp<mock::MockLayer>::make(mFlinger.flinger());      ASSERT_EQ(static_cast<size_t>(1), mScheduler->layerHistorySize()); -    mConfigs.updateDisplayModes({mode60, mode120}, /* activeMode */ mode60->getId()); +    mScheduler->setRefreshRateConfigs( +            std::make_shared<scheduler::RefreshRateConfigs>(DisplayModes{mode60, mode120}, +                                                            mode60->getId()));      ASSERT_EQ(static_cast<size_t>(0), mScheduler->getNumActiveLayers());      mScheduler->recordLayerHistory(layer.get(), 0, LayerHistory::LayerUpdateType::Buffer); @@ -194,20 +199,21 @@ TEST_F(SchedulerTest, testDispatchCachedReportedMode) {      // onModeChange is called.      mScheduler->clearOptionalFieldsInFeatures();      EXPECT_NO_FATAL_FAILURE(mScheduler->dispatchCachedReportedMode()); -    EXPECT_CALL(*mEventThread, onModeChanged(_, _, _)).Times(0); +    EXPECT_CALL(*mEventThread, onModeChanged(_)).Times(0);  }  TEST_F(SchedulerTest, onNonPrimaryDisplayModeChanged_invalidParameters) { -    DisplayModeId modeId = DisplayModeId(111); -    nsecs_t vsyncPeriod = 111111; +    const auto mode = DisplayMode::Builder(hal::HWConfigId(0)) +                              .setId(DisplayModeId(111)) +                              .setPhysicalDisplayId(PHYSICAL_DISPLAY_ID) +                              .setVsyncPeriod(111111) +                              .build();      // If the handle is incorrect, the function should return before      // onModeChange is called.      Scheduler::ConnectionHandle invalidHandle = {.id = 123}; -    EXPECT_NO_FATAL_FAILURE(mScheduler->onNonPrimaryDisplayModeChanged(invalidHandle, -                                                                       PHYSICAL_DISPLAY_ID, modeId, -                                                                       vsyncPeriod)); -    EXPECT_CALL(*mEventThread, onModeChanged(_, _, _)).Times(0); +    EXPECT_NO_FATAL_FAILURE(mScheduler->onNonPrimaryDisplayModeChanged(invalidHandle, mode)); +    EXPECT_CALL(*mEventThread, onModeChanged(_)).Times(0);  }  TEST_F(SchedulerTest, calculateMaxAcquiredBufferCount) { @@ -225,7 +231,9 @@ MATCHER(Is120Hz, "") {  }  TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) { -    mConfigs.updateDisplayModes({mode60, mode120}, /* activeMode */ mode60->getId()); +    mScheduler->setRefreshRateConfigs( +            std::make_shared<scheduler::RefreshRateConfigs>(DisplayModes{mode60, mode120}, +                                                            mode60->getId()));      sp<mock::MockLayer> layer = sp<mock::MockLayer>::make(mFlinger.flinger()); @@ -235,7 +243,7 @@ TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) {      mScheduler->setDisplayPowerState(kPowerStateNormal);      constexpr uint32_t kDisplayArea = 999'999; -    mScheduler->onPrimaryDisplayAreaChanged(kDisplayArea); +    mScheduler->onActiveDisplayAreaChanged(kDisplayArea);      EXPECT_CALL(mSchedulerCallback, changeRefreshRate(Is120Hz(), _)).Times(1);      mScheduler->chooseRefreshRateForContent(); diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp index 1ed52ea389..8e7554b5ca 100644 --- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp +++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp @@ -479,7 +479,9 @@ TEST_P(SetFrameRateTest, SetOnParentActivatesTree) {              ->record(child.get(), 0, 0, LayerHistory::LayerUpdateType::Buffer);      const auto layerHistorySummary = -            mFlinger.mutableScheduler().mutableLayerHistory()->summarize(0); +            mFlinger.mutableScheduler() +                    .mutableLayerHistory() +                    ->summarize(*mFlinger.mutableScheduler().refreshRateConfigs(), 0);      ASSERT_EQ(2u, layerHistorySummary.size());      EXPECT_TRUE(FRAME_RATE_VOTE1.rate.equalsWithMargin(layerHistorySummary[0].desiredRefreshRate));      EXPECT_TRUE(FRAME_RATE_VOTE1.rate.equalsWithMargin(layerHistorySummary[1].desiredRefreshRate)); diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp index be019848fb..fc40818ad1 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp @@ -224,6 +224,74 @@ TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedRequestsUpdateIfLayerStac      EXPECT_EQ(456u, display.getCurrentDisplayState().layerStack);  } +TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedDoesNothingIfFlagsNotChanged) { +    using Case = SimplePrimaryDisplayCase; + +    // -------------------------------------------------------------------- +    // Preconditions + +    // A display is set up +    auto display = Case::Display::makeFakeExistingDisplayInjector(this); +    display.inject(); + +    // The display has flags set +    display.mutableCurrentDisplayState().flags = 1u; + +    // The incoming request sets a different layer stack +    DisplayState state; +    state.what = DisplayState::eFlagsChanged; +    state.token = display.token(); +    state.flags = 1u; + +    // -------------------------------------------------------------------- +    // Invocation + +    uint32_t flags = mFlinger.setDisplayStateLocked(state); + +    // -------------------------------------------------------------------- +    // Postconditions + +    // The returned flags are empty +    EXPECT_EQ(0u, flags); + +    // The desired display state has been set to the new value. +    EXPECT_EQ(1u, display.getCurrentDisplayState().flags); +} + +TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedRequestsUpdateIfFlagsChanged) { +    using Case = SimplePrimaryDisplayCase; + +    // -------------------------------------------------------------------- +    // Preconditions + +    // A display is set up +    auto display = Case::Display::makeFakeExistingDisplayInjector(this); +    display.inject(); + +    // The display has a layer stack set +    display.mutableCurrentDisplayState().flags = 0u; + +    // The incoming request sets a different layer stack +    DisplayState state; +    state.what = DisplayState::eFlagsChanged; +    state.token = display.token(); +    state.flags = 1u; + +    // -------------------------------------------------------------------- +    // Invocation + +    uint32_t flags = mFlinger.setDisplayStateLocked(state); + +    // -------------------------------------------------------------------- +    // Postconditions + +    // The returned flags indicate a transaction is needed +    EXPECT_EQ(eDisplayTransactionNeeded, flags); + +    // The desired display state has been set to the new value. +    EXPECT_EQ(1u, display.getCurrentDisplayState().flags); +} +  TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedDoesNothingIfProjectionDidNotChange) {      using Case = SimplePrimaryDisplayCase;      constexpr ui::Rotation initialOrientation = ui::ROTATION_180; diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h index 41fd6e316f..a99dabe420 100644 --- a/services/surfaceflinger/tests/unittests/TestableScheduler.h +++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h @@ -32,15 +32,18 @@ namespace android {  class TestableScheduler : public Scheduler {  public: -    TestableScheduler(const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback) +    TestableScheduler(const std::shared_ptr<scheduler::RefreshRateConfigs>& refreshRateConfigs, +                      ISchedulerCallback& callback)            : TestableScheduler(std::make_unique<mock::VsyncController>(), -                              std::make_unique<mock::VSyncTracker>(), configs, callback) {} +                              std::make_unique<mock::VSyncTracker>(), refreshRateConfigs, +                              callback) {}      TestableScheduler(std::unique_ptr<scheduler::VsyncController> vsyncController,                        std::unique_ptr<scheduler::VSyncTracker> vsyncTracker, -                      const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback) -          : Scheduler({std::move(vsyncController), std::move(vsyncTracker), nullptr}, configs, -                      callback, createLayerHistory(configs), +                      const std::shared_ptr<scheduler::RefreshRateConfigs>& refreshRateConfigs, +                      ISchedulerCallback& callback) +          : Scheduler({std::move(vsyncController), std::move(vsyncTracker), nullptr}, +                      refreshRateConfigs, callback, createLayerHistory(),                        {.supportKernelTimer = false, .useContentDetection = true}) {}      // Used to inject mock event thread. @@ -64,6 +67,8 @@ public:          return mutableLayerHistory()->mLayerInfos.size();      } +    auto refreshRateConfigs() { return holdRefreshRateConfigs(); } +      size_t getNumActiveLayers() NO_THREAD_SAFETY_ANALYSIS {          if (!mLayerHistory) return 0;          return mutableLayerHistory()->mActiveLayersEnd; @@ -95,9 +100,8 @@ public:          mFeatures.cachedModeChangedParams.reset();      } -    void onNonPrimaryDisplayModeChanged(ConnectionHandle handle, PhysicalDisplayId displayId, -                                        DisplayModeId modeId, nsecs_t vsyncPeriod) { -        return Scheduler::onNonPrimaryDisplayModeChanged(handle, displayId, modeId, vsyncPeriod); +    void onNonPrimaryDisplayModeChanged(ConnectionHandle handle, DisplayModePtr mode) { +        return Scheduler::onNonPrimaryDisplayModeChanged(handle, mode);      }      ~TestableScheduler() { diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index cf67593174..40c881e902 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -82,8 +82,8 @@ public:          return std::make_unique<scheduler::FakePhaseOffsets>();      } -    std::unique_ptr<Scheduler> createScheduler(const scheduler::RefreshRateConfigs&, -                                               ISchedulerCallback&) override { +    std::unique_ptr<Scheduler> createScheduler( +            const std::shared_ptr<scheduler::RefreshRateConfigs>&, ISchedulerCallback&) override {          return nullptr;      } @@ -209,6 +209,7 @@ public:                          ISchedulerCallback* callback = nullptr, bool hasMultipleModes = false) {          DisplayModes modes{DisplayMode::Builder(0)                                     .setId(DisplayModeId(0)) +                                   .setPhysicalDisplayId(PhysicalDisplayId(0))                                     .setVsyncPeriod(16'666'667)                                     .setGroup(0)                                     .build()}; @@ -216,25 +217,24 @@ public:          if (hasMultipleModes) {              modes.emplace_back(DisplayMode::Builder(1)                                         .setId(DisplayModeId(1)) +                                       .setPhysicalDisplayId(PhysicalDisplayId(0))                                         .setVsyncPeriod(11'111'111)                                         .setGroup(0)                                         .build());          }          const auto currMode = DisplayModeId(0); -        mFlinger->mRefreshRateConfigs = -                std::make_unique<scheduler::RefreshRateConfigs>(modes, currMode); -        const auto currFps = -                mFlinger->mRefreshRateConfigs->getRefreshRateFromModeId(currMode).getFps(); -        mFlinger->mRefreshRateStats = -                std::make_unique<scheduler::RefreshRateStats>(*mFlinger->mTimeStats, currFps, -                                                              /*powerMode=*/hal::PowerMode::OFF); +        mRefreshRateConfigs = std::make_shared<scheduler::RefreshRateConfigs>(modes, currMode); +        const auto currFps = mRefreshRateConfigs->getCurrentRefreshRate().getFps();          mFlinger->mVsyncConfiguration = mFactory.createVsyncConfiguration(currFps);          mFlinger->mVsyncModulator = sp<scheduler::VsyncModulator>::make(                  mFlinger->mVsyncConfiguration->getCurrentConfigs()); +        mFlinger->mRefreshRateStats = +                std::make_unique<scheduler::RefreshRateStats>(*mFlinger->mTimeStats, currFps, +                                                              /*powerMode=*/hal::PowerMode::OFF);          mScheduler = new TestableScheduler(std::move(vsyncController), std::move(vsyncTracker), -                                           *mFlinger->mRefreshRateConfigs, *(callback ?: this)); +                                           mRefreshRateConfigs, *(callback ?: this));          mFlinger->mAppConnectionHandle = mScheduler->createConnection(std::move(appEventThread));          mFlinger->mSfConnectionHandle = mScheduler->createConnection(std::move(sfEventThread)); @@ -435,6 +435,7 @@ public:      auto& mutableTransactionFlags() { return mFlinger->mTransactionFlags; }      auto& mutablePowerAdvisor() { return mFlinger->mPowerAdvisor; }      auto& mutableDebugDisableHWC() { return mFlinger->mDebugDisableHWC; } +    auto& mutableMaxRenderTargetSize() { return mFlinger->mMaxRenderTargetSize; }      auto& mutableHwcDisplayData() { return getHwComposer().mDisplayData; }      auto& mutableHwcPhysicalDisplayIdMap() { return getHwComposer().mPhysicalDisplayIdMap; } @@ -644,6 +645,7 @@ public:              DisplayModePtr activeMode =                      DisplayMode::Builder(FakeHwcDisplayInjector::DEFAULT_ACTIVE_CONFIG)                              .setId(mActiveModeId) +                            .setPhysicalDisplayId(PhysicalDisplayId(0))                              .setWidth(FakeHwcDisplayInjector::DEFAULT_WIDTH)                              .setHeight(FakeHwcDisplayInjector::DEFAULT_HEIGHT)                              .setVsyncPeriod(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD) @@ -654,6 +656,7 @@ public:              DisplayModes modes{activeMode};              mCreationArgs.supportedModes = modes; +            mCreationArgs.refreshRateConfigs = flinger.mRefreshRateConfigs;          }          sp<IBinder> token() const { return mDisplayToken; } @@ -723,7 +726,7 @@ public:              return *this;          } -        sp<DisplayDevice> inject() { +        sp<DisplayDevice> inject() NO_THREAD_SAFETY_ANALYSIS {              const auto displayId = mCreationArgs.compositionDisplay->getDisplayId();              DisplayDeviceState state; @@ -770,6 +773,7 @@ private:      surfaceflinger::test::Factory mFactory;      sp<SurfaceFlinger> mFlinger = new SurfaceFlinger(mFactory, SurfaceFlinger::SkipInitialization);      TestableScheduler* mScheduler = nullptr; +    std::shared_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs;  };  } // namespace android diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp index 7c431a077b..1a50427b93 100644 --- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp @@ -74,6 +74,7 @@ public:          EXPECT_CALL(*mVSyncTracker, currentPeriod())                  .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)); +        mFlinger.setupComposer(std::make_unique<Hwc2::mock::Composer>());          mFlinger.setupScheduler(std::unique_ptr<mock::VsyncController>(mVsyncController),                                  std::unique_ptr<mock::VSyncTracker>(mVSyncTracker),                                  std::move(eventThread), std::move(sfEventThread)); diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h index cb3bd73920..1ba3c0f56e 100644 --- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h @@ -54,8 +54,7 @@ public:      MOCK_METHOD0(resetCommands, void());      MOCK_METHOD0(executeCommands, Error());      MOCK_METHOD0(getMaxVirtualDisplayCount, uint32_t()); -    MOCK_METHOD5(createVirtualDisplay, -                 Error(uint32_t, uint32_t, PixelFormat*, std::optional<Display>, Display*)); +    MOCK_METHOD4(createVirtualDisplay, Error(uint32_t, uint32_t, PixelFormat*, Display*));      MOCK_METHOD1(destroyVirtualDisplay, Error(Display));      MOCK_METHOD1(acceptDisplayChanges, Error(Display));      MOCK_METHOD2(createLayer, Error(Display, Layer* outLayer)); diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h index 485b4acdce..d25973e1ce 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h +++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h @@ -33,7 +33,7 @@ public:      MOCK_METHOD0(onScreenReleased, void());      MOCK_METHOD0(onScreenAcquired, void());      MOCK_METHOD2(onHotplugReceived, void(PhysicalDisplayId, bool)); -    MOCK_METHOD3(onModeChanged, void(PhysicalDisplayId, DisplayModeId, nsecs_t)); +    MOCK_METHOD1(onModeChanged, void(DisplayModePtr));      MOCK_METHOD2(onFrameRateOverridesChanged,                   void(PhysicalDisplayId, std::vector<FrameRateOverride>));      MOCK_CONST_METHOD1(dump, void(std::string&)); diff --git a/services/surfaceflinger/tests/utils/CallbackUtils.h b/services/surfaceflinger/tests/utils/CallbackUtils.h index 459b35c544..f4a3425b6a 100644 --- a/services/surfaceflinger/tests/utils/CallbackUtils.h +++ b/services/surfaceflinger/tests/utils/CallbackUtils.h @@ -20,8 +20,12 @@  #include <gui/SurfaceControl.h>  #include <ui/Fence.h>  #include <utils/Timers.h> +#include <chrono>  #include <thread> +using ::std::literals::chrono_literals::operator""ms; +using ::std::literals::chrono_literals::operator""s; +  namespace android {  namespace {  |