diff options
44 files changed, 1582 insertions, 971 deletions
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 5ab0abc561..3c02e21aff 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -220,101 +220,6 @@ public: return result; } - sp<IBinder> createDisplay(const String8& displayName, bool secure) override { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - status_t status = data.writeString8(displayName); - if (status) { - return nullptr; - } - status = data.writeBool(secure); - if (status) { - return nullptr; - } - - status = remote()->transact(BnSurfaceComposer::CREATE_DISPLAY, data, &reply); - if (status) { - return nullptr; - } - sp<IBinder> display; - status = reply.readNullableStrongBinder(&display); - if (status) { - return nullptr; - } - return display; - } - - void destroyDisplay(const sp<IBinder>& display) override { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - data.writeStrongBinder(display); - remote()->transact(BnSurfaceComposer::DESTROY_DISPLAY, data, &reply); - } - - std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const override { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - if (remote()->transact(BnSurfaceComposer::GET_PHYSICAL_DISPLAY_IDS, data, &reply) == - NO_ERROR) { - std::vector<uint64_t> rawIds; - if (reply.readUint64Vector(&rawIds) == NO_ERROR) { - std::vector<PhysicalDisplayId> displayIds; - displayIds.reserve(rawIds.size()); - - for (const uint64_t rawId : rawIds) { - if (const auto id = DisplayId::fromValue<PhysicalDisplayId>(rawId)) { - displayIds.push_back(*id); - } - } - return displayIds; - } - } - - return {}; - } - - status_t getPrimaryPhysicalDisplayId(PhysicalDisplayId* displayId) const override { - Parcel data, reply; - SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor()); - SAFE_PARCEL(remote()->transact, BnSurfaceComposer::GET_PRIMARY_PHYSICAL_DISPLAY_ID, data, - &reply); - uint64_t rawId; - SAFE_PARCEL(reply.readUint64, &rawId); - if (const auto id = DisplayId::fromValue<PhysicalDisplayId>(rawId)) { - *displayId = *id; - return NO_ERROR; - } - return NAME_NOT_FOUND; - } - - sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId displayId) const override { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - data.writeUint64(displayId.value); - remote()->transact(BnSurfaceComposer::GET_PHYSICAL_DISPLAY_TOKEN, data, &reply); - return reply.readStrongBinder(); - } - - void setPowerMode(const sp<IBinder>& display, int mode) override { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - data.writeStrongBinder(display); - data.writeInt32(mode); - remote()->transact(BnSurfaceComposer::SET_POWER_MODE, data, &reply); - } - - status_t getDisplayState(const sp<IBinder>& display, ui::DisplayState* state) override { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - data.writeStrongBinder(display); - remote()->transact(BnSurfaceComposer::GET_DISPLAY_STATE, data, &reply); - const status_t result = reply.readInt32(); - if (result == NO_ERROR) { - memcpy(state, reply.readInplace(sizeof(ui::DisplayState)), sizeof(ui::DisplayState)); - } - return result; - } - status_t getStaticDisplayInfo(const sp<IBinder>& display, ui::StaticDisplayInfo* info) override { Parcel data, reply; @@ -337,20 +242,6 @@ public: return reply.read(*info); } - status_t getDisplayStats(const sp<IBinder>& display, DisplayStatInfo* stats) override { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - data.writeStrongBinder(display); - remote()->transact(BnSurfaceComposer::GET_DISPLAY_STATS, data, &reply); - status_t result = reply.readInt32(); - if (result == NO_ERROR) { - memcpy(stats, - reply.readInplace(sizeof(DisplayStatInfo)), - sizeof(DisplayStatInfo)); - } - return result; - } - status_t getDisplayNativePrimaries(const sp<IBinder>& display, ui::DisplayPrimaries& primaries) override { Parcel data, reply; @@ -402,29 +293,6 @@ public: return static_cast<status_t>(reply.readInt32()); } - // TODO(b/213909104) : Add unit tests to verify surface flinger boot time APIs - status_t getBootDisplayModeSupport(bool* outSupport) const override { - Parcel data, reply; - status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - if (error != NO_ERROR) { - ALOGE("getBootDisplayModeSupport: failed to write interface token: %d", error); - return error; - } - error = remote()->transact(BnSurfaceComposer::GET_BOOT_DISPLAY_MODE_SUPPORT, data, &reply); - if (error != NO_ERROR) { - ALOGE("getBootDisplayModeSupport: failed to transact: %d", error); - return error; - } - bool support; - error = reply.readBool(&support); - if (error != NO_ERROR) { - ALOGE("getBootDisplayModeSupport: failed to read support: %d", error); - return error; - } - *outSupport = support; - return NO_ERROR; - } - status_t setBootDisplayMode(const sp<IBinder>& display, ui::DisplayModeId displayModeId) override { Parcel data, reply; @@ -450,73 +318,6 @@ public: return result; } - status_t clearBootDisplayMode(const sp<IBinder>& display) override { - Parcel data, reply; - status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - if (result != NO_ERROR) { - ALOGE("clearBootDisplayMode failed to writeInterfaceToken: %d", result); - return result; - } - result = data.writeStrongBinder(display); - if (result != NO_ERROR) { - ALOGE("clearBootDisplayMode failed to writeStrongBinder: %d", result); - return result; - } - result = remote()->transact(BnSurfaceComposer::CLEAR_BOOT_DISPLAY_MODE, data, &reply); - if (result != NO_ERROR) { - ALOGE("clearBootDisplayMode failed to transact: %d", result); - } - return result; - } - - void setAutoLowLatencyMode(const sp<IBinder>& display, bool on) override { - Parcel data, reply; - status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - if (result != NO_ERROR) { - ALOGE("setAutoLowLatencyMode failed to writeInterfaceToken: %d", result); - return; - } - - result = data.writeStrongBinder(display); - if (result != NO_ERROR) { - ALOGE("setAutoLowLatencyMode failed to writeStrongBinder: %d", result); - return; - } - result = data.writeBool(on); - if (result != NO_ERROR) { - ALOGE("setAutoLowLatencyMode failed to writeBool: %d", result); - return; - } - result = remote()->transact(BnSurfaceComposer::SET_AUTO_LOW_LATENCY_MODE, data, &reply); - if (result != NO_ERROR) { - ALOGE("setAutoLowLatencyMode failed to transact: %d", result); - return; - } - } - - void setGameContentType(const sp<IBinder>& display, bool on) override { - Parcel data, reply; - status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - if (result != NO_ERROR) { - ALOGE("setGameContentType failed to writeInterfaceToken: %d", result); - return; - } - result = data.writeStrongBinder(display); - if (result != NO_ERROR) { - ALOGE("setGameContentType failed to writeStrongBinder: %d", result); - return; - } - result = data.writeBool(on); - if (result != NO_ERROR) { - ALOGE("setGameContentType failed to writeBool: %d", result); - return; - } - result = remote()->transact(BnSurfaceComposer::SET_GAME_CONTENT_TYPE, data, &reply); - if (result != NO_ERROR) { - ALOGE("setGameContentType failed to transact: %d", result); - } - } - status_t clearAnimationFrameStats() override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); @@ -791,26 +592,6 @@ public: return error; } - status_t isWideColorDisplay(const sp<IBinder>& token, - bool* outIsWideColorDisplay) const override { - Parcel data, reply; - status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - if (error != NO_ERROR) { - return error; - } - error = data.writeStrongBinder(token); - if (error != NO_ERROR) { - return error; - } - - error = remote()->transact(BnSurfaceComposer::IS_WIDE_COLOR_DISPLAY, data, &reply); - if (error != NO_ERROR) { - return error; - } - error = reply.readBool(outIsWideColorDisplay); - return error; - } - status_t addRegionSamplingListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle, const sp<IRegionSamplingListener>& listener) override { Parcel data, reply; @@ -1043,109 +824,6 @@ public: return reply.readInt32(); } - status_t getDisplayBrightnessSupport(const sp<IBinder>& displayToken, - bool* outSupport) const override { - Parcel data, reply; - status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - if (error != NO_ERROR) { - ALOGE("getDisplayBrightnessSupport: failed to write interface token: %d", error); - return error; - } - error = data.writeStrongBinder(displayToken); - if (error != NO_ERROR) { - ALOGE("getDisplayBrightnessSupport: failed to write display token: %d", error); - return error; - } - error = remote()->transact(BnSurfaceComposer::GET_DISPLAY_BRIGHTNESS_SUPPORT, data, &reply); - if (error != NO_ERROR) { - ALOGE("getDisplayBrightnessSupport: failed to transact: %d", error); - return error; - } - bool support; - error = reply.readBool(&support); - if (error != NO_ERROR) { - ALOGE("getDisplayBrightnessSupport: failed to read support: %d", error); - return error; - } - *outSupport = support; - return NO_ERROR; - } - - status_t setDisplayBrightness(const sp<IBinder>& displayToken, - const gui::DisplayBrightness& brightness) override { - Parcel data, reply; - status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - if (error != NO_ERROR) { - ALOGE("setDisplayBrightness: failed to write interface token: %d", error); - return error; - } - error = data.writeStrongBinder(displayToken); - if (error != NO_ERROR) { - ALOGE("setDisplayBrightness: failed to write display token: %d", error); - return error; - } - error = data.writeParcelable(brightness); - if (error != NO_ERROR) { - ALOGE("setDisplayBrightness: failed to write brightness: %d", error); - return error; - } - error = remote()->transact(BnSurfaceComposer::SET_DISPLAY_BRIGHTNESS, data, &reply); - if (error != NO_ERROR) { - ALOGE("setDisplayBrightness: failed to transact: %d", error); - return error; - } - return NO_ERROR; - } - - status_t addHdrLayerInfoListener(const sp<IBinder>& displayToken, - const sp<gui::IHdrLayerInfoListener>& listener) override { - Parcel data, reply; - SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor()); - SAFE_PARCEL(data.writeStrongBinder, displayToken); - SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(listener)); - const status_t error = - remote()->transact(BnSurfaceComposer::ADD_HDR_LAYER_INFO_LISTENER, data, &reply); - if (error != OK) { - ALOGE("addHdrLayerInfoListener: Failed to transact; error = %d", error); - } - return error; - } - - status_t removeHdrLayerInfoListener(const sp<IBinder>& displayToken, - const sp<gui::IHdrLayerInfoListener>& listener) override { - Parcel data, reply; - SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor()); - SAFE_PARCEL(data.writeStrongBinder, displayToken); - SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(listener)); - const status_t error = - remote()->transact(BnSurfaceComposer::REMOVE_HDR_LAYER_INFO_LISTENER, data, &reply); - if (error != OK) { - ALOGE("removeHdrLayerInfoListener: Failed to transact; error = %d", error); - } - return error; - } - - status_t notifyPowerBoost(int32_t boostId) override { - Parcel data, reply; - status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - if (error != NO_ERROR) { - ALOGE("notifyPowerBoost: failed to write interface token: %d", error); - return error; - } - error = data.writeInt32(boostId); - if (error != NO_ERROR) { - ALOGE("notifyPowerBoost: failed to write boostId: %d", error); - return error; - } - error = remote()->transact(BnSurfaceComposer::NOTIFY_POWER_BOOST, data, &reply, - IBinder::FLAG_ONEWAY); - if (error != NO_ERROR) { - ALOGE("notifyPowerBoost: failed to transact: %d", error); - return error; - } - return NO_ERROR; - } - status_t setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor, float lightPosY, float lightPosZ, float lightRadius) override { Parcel data, reply; @@ -1461,41 +1139,6 @@ status_t BnSurfaceComposer::onTransact( reply->writeStrongBinder(IInterface::asBinder(connection)); return NO_ERROR; } - case CREATE_DISPLAY: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - String8 displayName; - SAFE_PARCEL(data.readString8, &displayName); - bool secure = false; - SAFE_PARCEL(data.readBool, &secure); - sp<IBinder> display = createDisplay(displayName, secure); - SAFE_PARCEL(reply->writeStrongBinder, display); - return NO_ERROR; - } - case DESTROY_DISPLAY: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp<IBinder> display = data.readStrongBinder(); - destroyDisplay(display); - return NO_ERROR; - } - case GET_PHYSICAL_DISPLAY_TOKEN: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - const auto id = DisplayId::fromValue<PhysicalDisplayId>(data.readUint64()); - if (!id) return BAD_VALUE; - reply->writeStrongBinder(getPhysicalDisplayToken(*id)); - return NO_ERROR; - } - case GET_DISPLAY_STATE: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - ui::DisplayState state; - const sp<IBinder> display = data.readStrongBinder(); - const status_t result = getDisplayState(display, &state); - reply->writeInt32(result); - if (result == NO_ERROR) { - memcpy(reply->writeInplace(sizeof(ui::DisplayState)), &state, - sizeof(ui::DisplayState)); - } - return NO_ERROR; - } case GET_STATIC_DISPLAY_INFO: { CHECK_INTERFACE(ISurfaceComposer, data, reply); ui::StaticDisplayInfo info; @@ -1516,18 +1159,6 @@ status_t BnSurfaceComposer::onTransact( SAFE_PARCEL(reply->write, info); return NO_ERROR; } - case GET_DISPLAY_STATS: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - DisplayStatInfo stats; - sp<IBinder> display = data.readStrongBinder(); - status_t result = getDisplayStats(display, &stats); - reply->writeInt32(result); - if (result == NO_ERROR) { - memcpy(reply->writeInplace(sizeof(DisplayStatInfo)), - &stats, sizeof(DisplayStatInfo)); - } - return NO_ERROR; - } case GET_DISPLAY_NATIVE_PRIMARIES: { CHECK_INTERFACE(ISurfaceComposer, data, reply); ui::DisplayPrimaries primaries; @@ -1567,15 +1198,6 @@ status_t BnSurfaceComposer::onTransact( result = reply->writeInt32(result); return result; } - case GET_BOOT_DISPLAY_MODE_SUPPORT: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - bool support = false; - status_t result = getBootDisplayModeSupport(&support); - if (result == NO_ERROR) { - reply->writeBool(support); - } - return result; - } case SET_BOOT_DISPLAY_MODE: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp<IBinder> display = nullptr; @@ -1592,50 +1214,6 @@ status_t BnSurfaceComposer::onTransact( } return setBootDisplayMode(display, displayModeId); } - case CLEAR_BOOT_DISPLAY_MODE: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp<IBinder> display = nullptr; - status_t result = data.readStrongBinder(&display); - if (result != NO_ERROR) { - ALOGE("clearBootDisplayMode failed to readStrongBinder: %d", result); - return result; - } - return clearBootDisplayMode(display); - } - case SET_AUTO_LOW_LATENCY_MODE: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp<IBinder> display = nullptr; - status_t result = data.readStrongBinder(&display); - if (result != NO_ERROR) { - ALOGE("setAutoLowLatencyMode failed to readStrongBinder: %d", result); - return result; - } - bool setAllm = false; - result = data.readBool(&setAllm); - if (result != NO_ERROR) { - ALOGE("setAutoLowLatencyMode failed to readBool: %d", result); - return result; - } - setAutoLowLatencyMode(display, setAllm); - return result; - } - case SET_GAME_CONTENT_TYPE: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp<IBinder> display = nullptr; - status_t result = data.readStrongBinder(&display); - if (result != NO_ERROR) { - ALOGE("setGameContentType failed to readStrongBinder: %d", result); - return result; - } - bool setGameContentTypeOn = false; - result = data.readBool(&setGameContentTypeOn); - if (result != NO_ERROR) { - ALOGE("setGameContentType failed to readBool: %d", result); - return result; - } - setGameContentType(display, setGameContentTypeOn); - return result; - } case CLEAR_ANIMATION_FRAME_STATS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); status_t result = clearAnimationFrameStats(); @@ -1650,13 +1228,6 @@ status_t BnSurfaceComposer::onTransact( reply->writeInt32(result); return NO_ERROR; } - case SET_POWER_MODE: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp<IBinder> display = data.readStrongBinder(); - int32_t mode = data.readInt32(); - setPowerMode(display, mode); - return NO_ERROR; - } case ENABLE_VSYNC_INJECTIONS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); bool enable = false; @@ -1806,38 +1377,6 @@ status_t BnSurfaceComposer::onTransact( } return error; } - case IS_WIDE_COLOR_DISPLAY: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp<IBinder> display = nullptr; - status_t error = data.readStrongBinder(&display); - if (error != NO_ERROR) { - return error; - } - bool result; - error = isWideColorDisplay(display, &result); - if (error == NO_ERROR) { - reply->writeBool(result); - } - return error; - } - case GET_PHYSICAL_DISPLAY_IDS: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - std::vector<PhysicalDisplayId> ids = getPhysicalDisplayIds(); - std::vector<uint64_t> rawIds(ids.size()); - std::transform(ids.begin(), ids.end(), rawIds.begin(), - [](PhysicalDisplayId id) { return id.value; }); - return reply->writeUint64Vector(rawIds); - } - case GET_PRIMARY_PHYSICAL_DISPLAY_ID: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - PhysicalDisplayId id; - status_t result = getPrimaryPhysicalDisplayId(&id); - if (result != NO_ERROR) { - ALOGE("getPrimaryPhysicalDisplayId: Failed to get id"); - return result; - } - return reply->writeUint64(id.value); - } case ADD_REGION_SAMPLING_LISTENER: { CHECK_INTERFACE(ISurfaceComposer, data, reply); Rect samplingArea; @@ -2035,77 +1574,6 @@ status_t BnSurfaceComposer::onTransact( reply->writeInt32(result); return result; } - case GET_DISPLAY_BRIGHTNESS_SUPPORT: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp<IBinder> displayToken; - status_t error = data.readNullableStrongBinder(&displayToken); - if (error != NO_ERROR) { - ALOGE("getDisplayBrightnessSupport: failed to read display token: %d", error); - return error; - } - bool support = false; - error = getDisplayBrightnessSupport(displayToken, &support); - reply->writeBool(support); - return error; - } - case SET_DISPLAY_BRIGHTNESS: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp<IBinder> displayToken; - status_t error = data.readNullableStrongBinder(&displayToken); - if (error != NO_ERROR) { - ALOGE("setDisplayBrightness: failed to read display token: %d", error); - return error; - } - gui::DisplayBrightness brightness; - error = data.readParcelable(&brightness); - if (error != NO_ERROR) { - ALOGE("setDisplayBrightness: failed to read brightness: %d", error); - return error; - } - return setDisplayBrightness(displayToken, brightness); - } - case ADD_HDR_LAYER_INFO_LISTENER: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp<IBinder> displayToken; - status_t error = data.readNullableStrongBinder(&displayToken); - if (error != NO_ERROR) { - ALOGE("addHdrLayerInfoListener: Failed to read display token"); - return error; - } - sp<gui::IHdrLayerInfoListener> listener; - error = data.readNullableStrongBinder(&listener); - if (error != NO_ERROR) { - ALOGE("addHdrLayerInfoListener: Failed to read listener"); - return error; - } - return addHdrLayerInfoListener(displayToken, listener); - } - case REMOVE_HDR_LAYER_INFO_LISTENER: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp<IBinder> displayToken; - status_t error = data.readNullableStrongBinder(&displayToken); - if (error != NO_ERROR) { - ALOGE("removeHdrLayerInfoListener: Failed to read display token"); - return error; - } - sp<gui::IHdrLayerInfoListener> listener; - error = data.readNullableStrongBinder(&listener); - if (error != NO_ERROR) { - ALOGE("removeHdrLayerInfoListener: Failed to read listener"); - return error; - } - return removeHdrLayerInfoListener(displayToken, listener); - } - case NOTIFY_POWER_BOOST: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - int32_t boostId; - status_t error = data.readInt32(&boostId); - if (error != NO_ERROR) { - ALOGE("notifyPowerBoost: failed to read boostId: %d", error); - return error; - } - return notifyPowerBoost(boostId); - } case SET_GLOBAL_SHADOW_SETTINGS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 20c41460d4..0f0a5c8504 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -27,13 +27,13 @@ #include <inttypes.h> +#include <android/gui/DisplayStatInfo.h> #include <android/native_window.h> #include <utils/Log.h> #include <utils/Trace.h> #include <utils/NativeHandle.h> -#include <ui/DisplayStatInfo.h> #include <ui/DynamicDisplayInfo.h> #include <ui/Fence.h> #include <ui/GraphicBuffer.h> @@ -45,6 +45,7 @@ #include <gui/ISurfaceComposer.h> #include <gui/LayerState.h> #include <private/gui/ComposerService.h> +#include <private/gui/ComposerServiceAIDL.h> namespace android { @@ -125,6 +126,10 @@ sp<ISurfaceComposer> Surface::composerService() const { return ComposerService::getComposerService(); } +sp<gui::ISurfaceComposer> Surface::composerServiceAIDL() const { + return ComposerServiceAIDL::getComposerService(); +} + nsecs_t Surface::now() const { return systemTime(); } @@ -174,10 +179,10 @@ status_t Surface::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, status_t Surface::getDisplayRefreshCycleDuration(nsecs_t* outRefreshDuration) { ATRACE_CALL(); - DisplayStatInfo stats; - status_t result = composerService()->getDisplayStats(nullptr, &stats); - if (result != NO_ERROR) { - return result; + gui::DisplayStatInfo stats; + binder::Status status = composerServiceAIDL()->getDisplayStats(nullptr, &stats); + if (!status.isOk()) { + return status.transactionError(); } *outRefreshDuration = stats.vsyncPeriod; @@ -343,20 +348,20 @@ status_t Surface::getFrameTimestamps(uint64_t frameNumber, status_t Surface::getWideColorSupport(bool* supported) { ATRACE_CALL(); - const sp<IBinder> display = composerService()->getInternalDisplayToken(); + const sp<IBinder> display = ComposerServiceAIDL::getInstance().getInternalDisplayToken(); if (display == nullptr) { return NAME_NOT_FOUND; } *supported = false; - status_t error = composerService()->isWideColorDisplay(display, supported); - return error; + binder::Status status = composerServiceAIDL()->isWideColorDisplay(display, supported); + return status.transactionError(); } status_t Surface::getHdrSupport(bool* supported) { ATRACE_CALL(); - const sp<IBinder> display = composerService()->getInternalDisplayToken(); + const sp<IBinder> display = ComposerServiceAIDL::getInstance().getInternalDisplayToken(); if (display == nullptr) { return NAME_NOT_FOUND; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 26ccda580a..447b3ef0ab 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/DisplayState.h> #include <android/gui/IWindowInfosListener.h> #include <utils/Errors.h> #include <utils/Log.h> @@ -43,6 +44,7 @@ #include <gui/WindowInfo.h> #include <private/gui/ParcelUtils.h> #include <ui/DisplayMode.h> +#include <ui/DisplayState.h> #include <ui/DynamicDisplayInfo.h> #include <private/gui/ComposerService.h> @@ -1014,32 +1016,59 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { // --------------------------------------------------------------------------- sp<IBinder> SurfaceComposerClient::createDisplay(const String8& displayName, bool secure) { - return ComposerService::getComposerService()->createDisplay(displayName, - secure); + sp<IBinder> display = nullptr; + binder::Status status = + ComposerServiceAIDL::getComposerService()->createDisplay(std::string( + displayName.string()), + secure, &display); + return status.isOk() ? display : nullptr; } void SurfaceComposerClient::destroyDisplay(const sp<IBinder>& display) { - return ComposerService::getComposerService()->destroyDisplay(display); + ComposerServiceAIDL::getComposerService()->destroyDisplay(display); } std::vector<PhysicalDisplayId> SurfaceComposerClient::getPhysicalDisplayIds() { - return ComposerService::getComposerService()->getPhysicalDisplayIds(); + std::vector<int64_t> displayIds; + std::vector<PhysicalDisplayId> physicalDisplayIds; + binder::Status status = + ComposerServiceAIDL::getComposerService()->getPhysicalDisplayIds(&displayIds); + if (status.isOk()) { + physicalDisplayIds.reserve(displayIds.size()); + for (auto item : displayIds) { + auto id = DisplayId::fromValue<PhysicalDisplayId>(static_cast<uint64_t>(item)); + physicalDisplayIds.push_back(*id); + } + } + return physicalDisplayIds; } status_t SurfaceComposerClient::getPrimaryPhysicalDisplayId(PhysicalDisplayId* id) { - return ComposerService::getComposerService()->getPrimaryPhysicalDisplayId(id); + int64_t displayId; + binder::Status status = + ComposerServiceAIDL::getComposerService()->getPrimaryPhysicalDisplayId(&displayId); + if (status.isOk()) { + *id = *DisplayId::fromValue<PhysicalDisplayId>(static_cast<uint64_t>(displayId)); + } + return status.transactionError(); } std::optional<PhysicalDisplayId> SurfaceComposerClient::getInternalDisplayId() { - return ComposerService::getComposerService()->getInternalDisplayId(); + ComposerServiceAIDL& instance = ComposerServiceAIDL::getInstance(); + return instance.getInternalDisplayId(); } sp<IBinder> SurfaceComposerClient::getPhysicalDisplayToken(PhysicalDisplayId displayId) { - return ComposerService::getComposerService()->getPhysicalDisplayToken(displayId); + sp<IBinder> display = nullptr; + binder::Status status = + ComposerServiceAIDL::getComposerService()->getPhysicalDisplayToken(displayId.value, + &display); + return status.isOk() ? display : nullptr; } sp<IBinder> SurfaceComposerClient::getInternalDisplayToken() { - return ComposerService::getComposerService()->getInternalDisplayToken(); + ComposerServiceAIDL& instance = ComposerServiceAIDL::getInstance(); + return instance.getInternalDisplayToken(); } void SurfaceComposerClient::Transaction::setAnimationTransaction() { @@ -2067,7 +2096,16 @@ status_t SurfaceComposerClient::injectVSync(nsecs_t when) { status_t SurfaceComposerClient::getDisplayState(const sp<IBinder>& display, ui::DisplayState* state) { - return ComposerService::getComposerService()->getDisplayState(display, state); + gui::DisplayState ds; + binder::Status status = + ComposerServiceAIDL::getComposerService()->getDisplayState(display, &ds); + if (status.isOk()) { + state->layerStack = ui::LayerStack::fromValue(ds.layerStack); + state->orientation = static_cast<ui::Rotation>(ds.orientation); + state->layerStackSpaceRect = + ui::Size(ds.layerStackSpaceRect.width, ds.layerStackSpaceRect.height); + } + return status.transactionError(); } status_t SurfaceComposerClient::getStaticDisplayInfo(const sp<IBinder>& display, @@ -2131,7 +2169,9 @@ status_t SurfaceComposerClient::setActiveColorMode(const sp<IBinder>& display, } status_t SurfaceComposerClient::getBootDisplayModeSupport(bool* support) { - return ComposerService::getComposerService()->getBootDisplayModeSupport(support); + binder::Status status = + ComposerServiceAIDL::getComposerService()->getBootDisplayModeSupport(support); + return status.transactionError(); } status_t SurfaceComposerClient::setBootDisplayMode(const sp<IBinder>& display, @@ -2140,7 +2180,9 @@ status_t SurfaceComposerClient::setBootDisplayMode(const sp<IBinder>& display, } status_t SurfaceComposerClient::clearBootDisplayMode(const sp<IBinder>& display) { - return ComposerService::getComposerService()->clearBootDisplayMode(display); + binder::Status status = + ComposerServiceAIDL::getComposerService()->clearBootDisplayMode(display); + return status.transactionError(); } status_t SurfaceComposerClient::setOverrideFrameRate(uid_t uid, float frameRate) { @@ -2148,16 +2190,16 @@ status_t SurfaceComposerClient::setOverrideFrameRate(uid_t uid, float frameRate) } void SurfaceComposerClient::setAutoLowLatencyMode(const sp<IBinder>& display, bool on) { - ComposerService::getComposerService()->setAutoLowLatencyMode(display, on); + ComposerServiceAIDL::getComposerService()->setAutoLowLatencyMode(display, on); } void SurfaceComposerClient::setGameContentType(const sp<IBinder>& display, bool on) { - ComposerService::getComposerService()->setGameContentType(display, on); + ComposerServiceAIDL::getComposerService()->setGameContentType(display, on); } void SurfaceComposerClient::setDisplayPowerMode(const sp<IBinder>& token, int mode) { - ComposerService::getComposerService()->setPowerMode(token, mode); + ComposerServiceAIDL::getComposerService()->setPowerMode(token, mode); } status_t SurfaceComposerClient::getCompositionPreference( @@ -2218,8 +2260,10 @@ status_t SurfaceComposerClient::getDisplayedContentSample(const sp<IBinder>& dis status_t SurfaceComposerClient::isWideColorDisplay(const sp<IBinder>& display, bool* outIsWideColorDisplay) { - return ComposerService::getComposerService()->isWideColorDisplay(display, - outIsWideColorDisplay); + binder::Status status = + ComposerServiceAIDL::getComposerService()->isWideColorDisplay(display, + outIsWideColorDisplay); + return status.transactionError(); } status_t SurfaceComposerClient::addRegionSamplingListener( @@ -2256,28 +2300,39 @@ status_t SurfaceComposerClient::removeTunnelModeEnabledListener( bool SurfaceComposerClient::getDisplayBrightnessSupport(const sp<IBinder>& displayToken) { bool support = false; - ComposerService::getComposerService()->getDisplayBrightnessSupport(displayToken, &support); - return support; + binder::Status status = + ComposerServiceAIDL::getComposerService()->getDisplayBrightnessSupport(displayToken, + &support); + return status.isOk() ? support : false; } status_t SurfaceComposerClient::setDisplayBrightness(const sp<IBinder>& displayToken, const gui::DisplayBrightness& brightness) { - return ComposerService::getComposerService()->setDisplayBrightness(displayToken, brightness); + binder::Status status = + ComposerServiceAIDL::getComposerService()->setDisplayBrightness(displayToken, + brightness); + return status.transactionError(); } status_t SurfaceComposerClient::addHdrLayerInfoListener( const sp<IBinder>& displayToken, const sp<gui::IHdrLayerInfoListener>& listener) { - return ComposerService::getComposerService()->addHdrLayerInfoListener(displayToken, listener); + binder::Status status = + ComposerServiceAIDL::getComposerService()->addHdrLayerInfoListener(displayToken, + listener); + return status.transactionError(); } status_t SurfaceComposerClient::removeHdrLayerInfoListener( const sp<IBinder>& displayToken, const sp<gui::IHdrLayerInfoListener>& listener) { - return ComposerService::getComposerService()->removeHdrLayerInfoListener(displayToken, - listener); + binder::Status status = + ComposerServiceAIDL::getComposerService()->removeHdrLayerInfoListener(displayToken, + listener); + return status.transactionError(); } status_t SurfaceComposerClient::notifyPowerBoost(int32_t boostId) { - return ComposerService::getComposerService()->notifyPowerBoost(boostId); + binder::Status status = ComposerServiceAIDL::getComposerService()->notifyPowerBoost(boostId); + return status.transactionError(); } status_t SurfaceComposerClient::setGlobalShadowSettings(const half4& ambientColor, diff --git a/libs/gui/aidl/android/gui/DisplayStatInfo.aidl b/libs/gui/aidl/android/gui/DisplayStatInfo.aidl new file mode 100644 index 0000000000..68f394281e --- /dev/null +++ b/libs/gui/aidl/android/gui/DisplayStatInfo.aidl @@ -0,0 +1,23 @@ +/* + * Copyright 2022 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; + +/** @hide */ +parcelable DisplayStatInfo { + long vsyncTime; + long vsyncPeriod; +} diff --git a/libs/gui/aidl/android/gui/DisplayState.aidl b/libs/gui/aidl/android/gui/DisplayState.aidl new file mode 100644 index 0000000000..9589ab6b1a --- /dev/null +++ b/libs/gui/aidl/android/gui/DisplayState.aidl @@ -0,0 +1,27 @@ +/* + * Copyright 2022 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.Rotation; +import android.gui.Size; + +/** @hide */ +parcelable DisplayState { + int layerStack; + Rotation orientation = Rotation.Rotation0; + Size layerStackSpaceRect; +} diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl index 07921a59a5..a9977b0f45 100644 --- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl +++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl @@ -17,11 +17,88 @@ package android.gui; import android.gui.DisplayCaptureArgs; +import android.gui.DisplayBrightness; +import android.gui.DisplayState; +import android.gui.DisplayStatInfo; +import android.gui.IHdrLayerInfoListener; import android.gui.LayerCaptureArgs; import android.gui.IScreenCaptureListener; /** @hide */ interface ISurfaceComposer { + + /* create a virtual display + * requires ACCESS_SURFACE_FLINGER permission. + */ + @nullable IBinder createDisplay(@utf8InCpp String displayName, boolean secure); + + /* destroy a virtual display + * requires ACCESS_SURFACE_FLINGER permission. + */ + void destroyDisplay(IBinder display); + + /* get stable IDs for connected physical displays. + */ + long[] getPhysicalDisplayIds(); + + long getPrimaryPhysicalDisplayId(); + + /* get token for a physical display given its stable ID obtained via getPhysicalDisplayIds or a + * DisplayEventReceiver hotplug event. + */ + @nullable IBinder getPhysicalDisplayToken(long displayId); + + /* set display power mode. depending on the mode, it can either trigger + * screen on, off or low power mode and wait for it to complete. + * requires ACCESS_SURFACE_FLINGER permission. + */ + void setPowerMode(IBinder display, int mode); + + /* returns display statistics for a given display + * intended to be used by the media framework to properly schedule + * video frames */ + DisplayStatInfo getDisplayStats(IBinder display); + + /** + * Get transactional state of given display. + */ + DisplayState getDisplayState(IBinder display); + + /** + * Clears the user-preferred display mode. The device should now boot in system preferred + * display mode. + */ + void clearBootDisplayMode(IBinder display); + + /** + * Gets whether boot time display mode operations are supported on the device. + * + * outSupport + * An output parameter for whether boot time display mode operations are supported. + * + * Returns NO_ERROR upon success. Otherwise, + * NAME_NOT_FOUND if the display is invalid, or + * BAD_VALUE if the output parameter is invalid. + */ + // TODO(b/213909104) : Add unit tests to verify surface flinger boot time APIs + boolean getBootDisplayModeSupport(); + + /** + * Switches Auto Low Latency Mode on/off on the connected display, if it is + * available. This should only be called if the display supports Auto Low + * Latency Mode as reported in #getDynamicDisplayInfo. + * For more information, see the HDMI 2.1 specification. + */ + void setAutoLowLatencyMode(IBinder display, boolean on); + + /** + * This will start sending infoframes to the connected display with + * ContentType=Game (if on=true). This should only be called if the display + * Game Content Type as reported in #getDynamicDisplayInfo. + * For more information, see the HDMI 1.4 specification. + */ + void setGameContentType(IBinder display, boolean on); + /** * Capture the specified screen. This requires READ_FRAME_BUFFER * permission. This function will fail if there is a secure window on @@ -39,4 +116,67 @@ interface ISurfaceComposer { * is a secure window on screen */ void captureLayers(in LayerCaptureArgs args, IScreenCaptureListener listener); + + /* + * Queries whether the given display is a wide color display. + * Requires the ACCESS_SURFACE_FLINGER permission. + */ + boolean isWideColorDisplay(IBinder token); + + /* + * Gets whether brightness operations are supported on a display. + * + * displayToken + * The token of the display. + * outSupport + * An output parameter for whether brightness operations are supported. + * + * Returns NO_ERROR upon success. Otherwise, + * NAME_NOT_FOUND if the display is invalid, or + * BAD_VALUE if the output parameter is invalid. + */ + boolean getDisplayBrightnessSupport(IBinder displayToken); + + /* + * Sets the brightness of a display. + * + * displayToken + * The token of the display whose brightness is set. + * brightness + * The DisplayBrightness info to set on the desired display. + * + * Returns NO_ERROR upon success. Otherwise, + * NAME_NOT_FOUND if the display is invalid, or + * BAD_VALUE if the brightness is invalid, or + * INVALID_OPERATION if brightness operations are not supported. + */ + void setDisplayBrightness(IBinder displayToken, in DisplayBrightness brightness); + + /* + * Adds a listener that receives HDR layer information. This is used in combination + * with setDisplayBrightness to adjust the display brightness depending on factors such + * as whether or not HDR is in use. + * + * Returns NO_ERROR upon success or NAME_NOT_FOUND if the display is invalid. + */ + void addHdrLayerInfoListener(IBinder displayToken, IHdrLayerInfoListener listener); + + /* + * Removes a listener that was added with addHdrLayerInfoListener. + * + * Returns NO_ERROR upon success, NAME_NOT_FOUND if the display is invalid, and BAD_VALUE if + * the listener wasn't registered. + * + */ + void removeHdrLayerInfoListener(IBinder displayToken, IHdrLayerInfoListener listener); + + /* + * Sends a power boost to the composer. This function is asynchronous. + * + * boostId + * boost id according to android::hardware::power::Boost + * + * Returns NO_ERROR upon success. + */ + void notifyPowerBoost(int boostId); } diff --git a/libs/gui/aidl/android/gui/Rect.aidl b/libs/gui/aidl/android/gui/Rect.aidl new file mode 100644 index 0000000000..1b13761392 --- /dev/null +++ b/libs/gui/aidl/android/gui/Rect.aidl @@ -0,0 +1,35 @@ +/* + * Copyright 2022 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; + +// copied from libs/arect/include/android/rect.h +// TODO(b/221473398): +// use hardware/interfaces/graphics/common/aidl/android/hardware/graphics/common/Rect.aidl +/** @hide */ +parcelable Rect { + /// Minimum X coordinate of the rectangle. + int left; + + /// Minimum Y coordinate of the rectangle. + int top; + + /// Maximum X coordinate of the rectangle. + int right; + + /// Maximum Y coordinate of the rectangle. + int bottom; +} diff --git a/libs/gui/aidl/android/gui/Rotation.aidl b/libs/gui/aidl/android/gui/Rotation.aidl new file mode 100644 index 0000000000..451ff45ccf --- /dev/null +++ b/libs/gui/aidl/android/gui/Rotation.aidl @@ -0,0 +1,26 @@ +/* + * Copyright 2022 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; + +/** @hide */ +@Backing(type="int") +enum Rotation { + Rotation0 = 0, + Rotation90 = 1, + Rotation180 = 2, + Rotation270 = 3 +} diff --git a/libs/gui/aidl/android/gui/Size.aidl b/libs/gui/aidl/android/gui/Size.aidl new file mode 100644 index 0000000000..415fa36fee --- /dev/null +++ b/libs/gui/aidl/android/gui/Size.aidl @@ -0,0 +1,23 @@ +/* + * Copyright 2022 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; + +/** @hide */ +parcelable Size { + int width = -1; + int height = -1; +} diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 4dfc383b57..2e4d6b470c 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -137,40 +137,6 @@ public: VsyncSource vsyncSource = eVsyncSourceApp, EventRegistrationFlags eventRegistration = {}) = 0; - /* create a virtual display - * requires ACCESS_SURFACE_FLINGER permission. - */ - virtual sp<IBinder> createDisplay(const String8& displayName, - bool secure) = 0; - - /* destroy a virtual display - * requires ACCESS_SURFACE_FLINGER permission. - */ - virtual void destroyDisplay(const sp<IBinder>& display) = 0; - - /* get stable IDs for connected physical displays. - */ - virtual std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const = 0; - - virtual status_t getPrimaryPhysicalDisplayId(PhysicalDisplayId*) const = 0; - - // TODO(b/74619554): Remove this stopgap once the framework is display-agnostic. - std::optional<PhysicalDisplayId> getInternalDisplayId() const { - const auto displayIds = getPhysicalDisplayIds(); - return displayIds.empty() ? std::nullopt : std::make_optional(displayIds.front()); - } - - /* get token for a physical display given its stable ID obtained via getPhysicalDisplayIds or a - * DisplayEventReceiver hotplug event. - */ - virtual sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId displayId) const = 0; - - // TODO(b/74619554): Remove this stopgap once the framework is display-agnostic. - sp<IBinder> getInternalDisplayToken() const { - const auto displayId = getInternalDisplayId(); - return displayId ? getPhysicalDisplayToken(*displayId) : nullptr; - } - /* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */ virtual status_t setTransactionState( const FrameTimelineInfo& frameTimelineInfo, const Vector<ComposerState>& state, @@ -194,24 +160,6 @@ public: virtual status_t getSupportedFrameTimestamps( std::vector<FrameEvent>* outSupported) const = 0; - /* set display power mode. depending on the mode, it can either trigger - * screen on, off or low power mode and wait for it to complete. - * requires ACCESS_SURFACE_FLINGER permission. - */ - virtual void setPowerMode(const sp<IBinder>& display, int mode) = 0; - - - /* returns display statistics for a given display - * intended to be used by the media framework to properly schedule - * video frames */ - virtual status_t getDisplayStats(const sp<IBinder>& display, - DisplayStatInfo* stats) = 0; - - /** - * Get transactional state of given display. - */ - virtual status_t getDisplayState(const sp<IBinder>& display, ui::DisplayState*) = 0; - /** * Gets immutable information about given physical display. */ @@ -232,40 +180,6 @@ public: */ virtual status_t setBootDisplayMode(const sp<IBinder>& display, ui::DisplayModeId) = 0; - /** - * Clears the user-preferred display mode. The device should now boot in system preferred - * display mode. - */ - virtual status_t clearBootDisplayMode(const sp<IBinder>& display) = 0; - - /** - * Gets whether boot time display mode operations are supported on the device. - * - * outSupport - * An output parameter for whether boot time display mode operations are supported. - * - * Returns NO_ERROR upon success. Otherwise, - * NAME_NOT_FOUND if the display is invalid, or - * BAD_VALUE if the output parameter is invalid. - */ - virtual status_t getBootDisplayModeSupport(bool* outSupport) const = 0; - - /** - * Switches Auto Low Latency Mode on/off on the connected display, if it is - * available. This should only be called if the display supports Auto Low - * Latency Mode as reported in #getDynamicDisplayInfo. - * For more information, see the HDMI 2.1 specification. - */ - virtual void setAutoLowLatencyMode(const sp<IBinder>& display, bool on) = 0; - - /** - * This will start sending infoframes to the connected display with - * ContentType=Game (if on=true). This should only be called if the display - * Game Content Type as reported in #getDynamicDisplayInfo. - * For more information, see the HDMI 1.4 specification. - */ - virtual void setGameContentType(const sp<IBinder>& display, bool on) = 0; - /* Clears the frame statistics for animations. * * Requires the ACCESS_SURFACE_FLINGER permission. @@ -344,13 +258,6 @@ public: */ virtual status_t getProtectedContentSupport(bool* outSupported) const = 0; - /* - * Queries whether the given display is a wide color display. - * Requires the ACCESS_SURFACE_FLINGER permission. - */ - virtual status_t isWideColorDisplay(const sp<IBinder>& token, - bool* outIsWideColorDisplay) const = 0; - /* Registers a listener to stream median luma updates from SurfaceFlinger. * * The sampling area is bounded by both samplingArea and the given stopLayerHandle @@ -431,65 +338,6 @@ public: float* outPrimaryRefreshRateMax, float* outAppRequestRefreshRateMin, float* outAppRequestRefreshRateMax) = 0; - /* - * Gets whether brightness operations are supported on a display. - * - * displayToken - * The token of the display. - * outSupport - * An output parameter for whether brightness operations are supported. - * - * Returns NO_ERROR upon success. Otherwise, - * NAME_NOT_FOUND if the display is invalid, or - * BAD_VALUE if the output parameter is invalid. - */ - virtual status_t getDisplayBrightnessSupport(const sp<IBinder>& displayToken, - bool* outSupport) const = 0; - - /* - * Sets the brightness of a display. - * - * displayToken - * The token of the display whose brightness is set. - * brightness - * The DisplayBrightness info to set on the desired display. - * - * Returns NO_ERROR upon success. Otherwise, - * NAME_NOT_FOUND if the display is invalid, or - * BAD_VALUE if the brightness is invalid, or - * INVALID_OPERATION if brightness operations are not supported. - */ - virtual status_t setDisplayBrightness(const sp<IBinder>& displayToken, - const gui::DisplayBrightness& brightness) = 0; - - /* - * Adds a listener that receives HDR layer information. This is used in combination - * with setDisplayBrightness to adjust the display brightness depending on factors such - * as whether or not HDR is in use. - * - * Returns NO_ERROR upon success or NAME_NOT_FOUND if the display is invalid. - */ - virtual status_t addHdrLayerInfoListener(const sp<IBinder>& displayToken, - const sp<gui::IHdrLayerInfoListener>& listener) = 0; - /* - * Removes a listener that was added with addHdrLayerInfoListener. - * - * Returns NO_ERROR upon success, NAME_NOT_FOUND if the display is invalid, and BAD_VALUE if - * the listener wasn't registered. - * - */ - virtual status_t removeHdrLayerInfoListener(const sp<IBinder>& displayToken, - const sp<gui::IHdrLayerInfoListener>& listener) = 0; - - /* - * Sends a power boost to the composer. This function is asynchronous. - * - * boostId - * boost id according to android::hardware::power::Boost - * - * Returns NO_ERROR upon success. - */ - virtual status_t notifyPowerBoost(int32_t boostId) = 0; /* * Sets the global configuration for all the shadows drawn by SurfaceFlinger. Shadow follows @@ -596,9 +444,9 @@ public: CREATE_CONNECTION, GET_STATIC_DISPLAY_INFO, CREATE_DISPLAY_EVENT_CONNECTION, - CREATE_DISPLAY, - DESTROY_DISPLAY, - GET_PHYSICAL_DISPLAY_TOKEN, + CREATE_DISPLAY, // Deprecated. Autogenerated by .aidl now. + DESTROY_DISPLAY, // Deprecated. Autogenerated by .aidl now. + GET_PHYSICAL_DISPLAY_TOKEN, // Deprecated. Autogenerated by .aidl now. SET_TRANSACTION_STATE, AUTHENTICATE_SURFACE, GET_SUPPORTED_FRAME_TIMESTAMPS, @@ -609,7 +457,7 @@ public: CAPTURE_LAYERS, // Deprecated. Autogenerated by .aidl now. CLEAR_ANIMATION_FRAME_STATS, GET_ANIMATION_FRAME_STATS, - SET_POWER_MODE, + SET_POWER_MODE, // Deprecated. Autogenerated by .aidl now. GET_DISPLAY_STATS, GET_HDR_CAPABILITIES, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead. GET_DISPLAY_COLOR_MODES, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead. @@ -624,22 +472,22 @@ public: SET_DISPLAY_CONTENT_SAMPLING_ENABLED, GET_DISPLAYED_CONTENT_SAMPLE, GET_PROTECTED_CONTENT_SUPPORT, - IS_WIDE_COLOR_DISPLAY, + IS_WIDE_COLOR_DISPLAY, // Deprecated. Autogenerated by .aidl now. GET_DISPLAY_NATIVE_PRIMARIES, - GET_PHYSICAL_DISPLAY_IDS, + GET_PHYSICAL_DISPLAY_IDS, // Deprecated. Autogenerated by .aidl now. ADD_REGION_SAMPLING_LISTENER, REMOVE_REGION_SAMPLING_LISTENER, SET_DESIRED_DISPLAY_MODE_SPECS, GET_DESIRED_DISPLAY_MODE_SPECS, - GET_DISPLAY_BRIGHTNESS_SUPPORT, - SET_DISPLAY_BRIGHTNESS, - CAPTURE_DISPLAY_BY_ID, // Deprecated. Autogenerated by .aidl now. - NOTIFY_POWER_BOOST, + GET_DISPLAY_BRIGHTNESS_SUPPORT, // Deprecated. Autogenerated by .aidl now. + SET_DISPLAY_BRIGHTNESS, // Deprecated. Autogenerated by .aidl now. + CAPTURE_DISPLAY_BY_ID, // Deprecated. Autogenerated by .aidl now. + NOTIFY_POWER_BOOST, // Deprecated. Autogenerated by .aidl now. SET_GLOBAL_SHADOW_SETTINGS, GET_AUTO_LOW_LATENCY_MODE_SUPPORT, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead. - SET_AUTO_LOW_LATENCY_MODE, - GET_GAME_CONTENT_TYPE_SUPPORT, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead. - SET_GAME_CONTENT_TYPE, + SET_AUTO_LOW_LATENCY_MODE, // Deprecated. Autogenerated by .aidl now. + GET_GAME_CONTENT_TYPE_SUPPORT, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead. + SET_GAME_CONTENT_TYPE, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead. SET_FRAME_RATE, // Deprecated. Use DisplayManager.setShouldAlwaysRespectAppRequestedMode(true); ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN, @@ -651,18 +499,18 @@ public: ADD_FPS_LISTENER, REMOVE_FPS_LISTENER, OVERRIDE_HDR_TYPES, - ADD_HDR_LAYER_INFO_LISTENER, - REMOVE_HDR_LAYER_INFO_LISTENER, + ADD_HDR_LAYER_INFO_LISTENER, // Deprecated. Autogenerated by .aidl now. + REMOVE_HDR_LAYER_INFO_LISTENER, // Deprecated. Autogenerated by .aidl now. ON_PULL_ATOM, ADD_TUNNEL_MODE_ENABLED_LISTENER, REMOVE_TUNNEL_MODE_ENABLED_LISTENER, ADD_WINDOW_INFOS_LISTENER, REMOVE_WINDOW_INFOS_LISTENER, - GET_PRIMARY_PHYSICAL_DISPLAY_ID, + GET_PRIMARY_PHYSICAL_DISPLAY_ID, // Deprecated. Autogenerated by .aidl now. GET_DISPLAY_DECORATION_SUPPORT, - GET_BOOT_DISPLAY_MODE_SUPPORT, + GET_BOOT_DISPLAY_MODE_SUPPORT, // Deprecated. Autogenerated by .aidl now. SET_BOOT_DISPLAY_MODE, - CLEAR_BOOT_DISPLAY_MODE, + CLEAR_BOOT_DISPLAY_MODE, // Deprecated. Autogenerated by .aidl now. SET_OVERRIDE_FRAME_RATE, // Always append new enum to the end. }; diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index 40d096e1e5..ba9ee6c752 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -35,6 +35,10 @@ namespace android { +namespace gui { +class ISurfaceComposer; +} // namespace gui + class ISurfaceComposer; /* This is the same as ProducerListener except that onBuffersDiscarded is @@ -196,6 +200,7 @@ protected: // Virtual for testing. virtual sp<ISurfaceComposer> composerService() const; + virtual sp<gui::ISurfaceComposer> composerServiceAIDL() const; virtual nsecs_t now() const; private: diff --git a/libs/gui/include/private/gui/ComposerServiceAIDL.h b/libs/gui/include/private/gui/ComposerServiceAIDL.h index fee37eefe0..9a96976c0f 100644 --- a/libs/gui/include/private/gui/ComposerServiceAIDL.h +++ b/libs/gui/include/private/gui/ComposerServiceAIDL.h @@ -50,6 +50,28 @@ public: // Get a connection to the Composer Service. This will block until // a connection is established. Returns null if permission is denied. static sp<gui::ISurfaceComposer> getComposerService(); + + // the following two methods are moved from ISurfaceComposer.h + // TODO(b/74619554): Remove this stopgap once the framework is display-agnostic. + std::optional<PhysicalDisplayId> getInternalDisplayId() const { + std::vector<int64_t> displayIds; + binder::Status status = mComposerService->getPhysicalDisplayIds(&displayIds); + return (!status.isOk() || displayIds.empty()) + ? std::nullopt + : DisplayId::fromValue<PhysicalDisplayId>( + static_cast<uint64_t>(displayIds.front())); + } + + // TODO(b/74619554): Remove this stopgap once the framework is display-agnostic. + sp<IBinder> getInternalDisplayToken() const { + const auto displayId = getInternalDisplayId(); + if (!displayId) return nullptr; + sp<IBinder> display; + binder::Status status = + mComposerService->getPhysicalDisplayToken(static_cast<int64_t>(displayId->value), + &display); + return status.isOk() ? display : nullptr; + } }; // --------------------------------------------------------------------------- diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index a885e926a3..e0b86e02fb 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -20,6 +20,7 @@ #include <SurfaceFlingerProperties.h> #include <android/gui/IDisplayEventConnection.h> +#include <android/gui/ISurfaceComposer.h> #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h> #include <binder/ProcessState.h> #include <configstore/Utils.h> @@ -260,9 +261,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersDontSucceed) { sp<ANativeWindow> anw(mSurface); // Verify the screenshot works with no protected buffers. - sp<ISurfaceComposer> sf(ComposerService::getComposerService()); - - const sp<IBinder> display = sf->getInternalDisplayToken(); + const sp<IBinder> display = ComposerServiceAIDL::getInstance().getInternalDisplayToken(); ASSERT_FALSE(display == nullptr); DisplayCaptureArgs captureArgs; @@ -696,12 +695,6 @@ public: ISurfaceComposer::VsyncSource, ISurfaceComposer::EventRegistrationFlags) override { return nullptr; } - sp<IBinder> createDisplay(const String8& /*displayName*/, - bool /*secure*/) override { return nullptr; } - void destroyDisplay(const sp<IBinder>& /*display */) override {} - std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const override { return {}; } - status_t getPrimaryPhysicalDisplayId(PhysicalDisplayId*) const override { return NO_ERROR; } - sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId) const override { return nullptr; } status_t setTransactionState(const FrameTimelineInfo& /*frameTimelineInfo*/, const Vector<ComposerState>& /*state*/, const Vector<DisplayState>& /*displays*/, uint32_t /*flags*/, @@ -740,7 +733,6 @@ public: return NO_ERROR; } - void setPowerMode(const sp<IBinder>& /*display*/, int /*mode*/) override {} status_t getStaticDisplayInfo(const sp<IBinder>& /*display*/, ui::StaticDisplayInfo*) override { return NO_ERROR; } @@ -748,24 +740,15 @@ public: ui::DynamicDisplayInfo*) override { return NO_ERROR; } - status_t getDisplayState(const sp<IBinder>& /*display*/, ui::DisplayState*) override { - return NO_ERROR; - } - status_t getDisplayStats(const sp<IBinder>& /*display*/, - DisplayStatInfo* /*stats*/) override { return NO_ERROR; } status_t getDisplayNativePrimaries(const sp<IBinder>& /*display*/, ui::DisplayPrimaries& /*primaries*/) override { return NO_ERROR; } status_t setActiveColorMode(const sp<IBinder>& /*display*/, ColorMode /*colorMode*/) override { return NO_ERROR; } - status_t getBootDisplayModeSupport(bool* /*outSupport*/) const override { return NO_ERROR; } status_t setBootDisplayMode(const sp<IBinder>& /*display*/, ui::DisplayModeId /*id*/) override { return NO_ERROR; } - status_t clearBootDisplayMode(const sp<IBinder>& /*display*/) override { return NO_ERROR; } - void setAutoLowLatencyMode(const sp<IBinder>& /*display*/, bool /*on*/) override {} - void setGameContentType(const sp<IBinder>& /*display*/, bool /*on*/) override {} status_t clearAnimationFrameStats() override { return NO_ERROR; } status_t getAnimationFrameStats(FrameStats* /*outStats*/) const override { @@ -812,26 +795,6 @@ public: status_t getColorManagement(bool* /*outGetColorManagement*/) const override { return NO_ERROR; } status_t getProtectedContentSupport(bool* /*outSupported*/) const override { return NO_ERROR; } - status_t isWideColorDisplay(const sp<IBinder>&, bool*) const override { return NO_ERROR; } - status_t getDisplayBrightnessSupport(const sp<IBinder>& /*displayToken*/, - bool* /*outSupport*/) const override { - return NO_ERROR; - } - status_t setDisplayBrightness(const sp<IBinder>& /*displayToken*/, - const gui::DisplayBrightness& /*brightness*/) override { - return NO_ERROR; - } - - status_t addHdrLayerInfoListener(const sp<IBinder>&, - const sp<gui::IHdrLayerInfoListener>&) override { - return NO_ERROR; - } - - status_t removeHdrLayerInfoListener(const sp<IBinder>&, - const sp<gui::IHdrLayerInfoListener>&) override { - return NO_ERROR; - } - status_t addRegionSamplingListener(const Rect& /*samplingArea*/, const sp<IBinder>& /*stopLayerHandle*/, const sp<IRegionSamplingListener>& /*listener*/) override { @@ -873,7 +836,6 @@ public: float* /*outAppRequestRefreshRateMax*/) override { return NO_ERROR; }; - status_t notifyPowerBoost(int32_t /*boostId*/) override { return NO_ERROR; } status_t setGlobalShadowSettings(const half4& /*ambientColor*/, const half4& /*spotColor*/, float /*lightPosY*/, float /*lightPosZ*/, @@ -925,6 +887,114 @@ private: bool mSupportsPresent{true}; }; +class FakeSurfaceComposerAIDL : public gui::ISurfaceComposer { +public: + ~FakeSurfaceComposerAIDL() override {} + + void setSupportsPresent(bool supportsPresent) { mSupportsPresent = supportsPresent; } + + binder::Status createDisplay(const std::string& /*displayName*/, bool /*secure*/, + sp<IBinder>* /*outDisplay*/) override { + return binder::Status::ok(); + } + + binder::Status destroyDisplay(const sp<IBinder>& /*display*/) override { + return binder::Status::ok(); + } + + binder::Status getPhysicalDisplayIds(std::vector<int64_t>* /*outDisplayIds*/) override { + return binder::Status::ok(); + } + + binder::Status getPrimaryPhysicalDisplayId(int64_t* /*outDisplayId*/) override { + return binder::Status::ok(); + } + + binder::Status getPhysicalDisplayToken(int64_t /*displayId*/, + sp<IBinder>* /*outDisplay*/) override { + return binder::Status::ok(); + } + + binder::Status setPowerMode(const sp<IBinder>& /*display*/, int /*mode*/) override { + return binder::Status::ok(); + } + + binder::Status getDisplayStats(const sp<IBinder>& /*display*/, + gui::DisplayStatInfo* /*outStatInfo*/) override { + return binder::Status::ok(); + } + + binder::Status getDisplayState(const sp<IBinder>& /*display*/, + gui::DisplayState* /*outState*/) override { + return binder::Status::ok(); + } + + binder::Status clearBootDisplayMode(const sp<IBinder>& /*display*/) override { + return binder::Status::ok(); + } + + binder::Status getBootDisplayModeSupport(bool* /*outMode*/) override { + return binder::Status::ok(); + } + + binder::Status setAutoLowLatencyMode(const sp<IBinder>& /*display*/, bool /*on*/) override { + return binder::Status::ok(); + } + + binder::Status setGameContentType(const sp<IBinder>& /*display*/, bool /*on*/) override { + return binder::Status::ok(); + } + + binder::Status captureDisplay(const DisplayCaptureArgs&, + const sp<IScreenCaptureListener>&) override { + return binder::Status::ok(); + } + + binder::Status captureDisplayById(int64_t, const sp<IScreenCaptureListener>&) override { + return binder::Status::ok(); + } + + binder::Status captureLayers(const LayerCaptureArgs&, + const sp<IScreenCaptureListener>&) override { + return binder::Status::ok(); + } + + binder::Status isWideColorDisplay(const sp<IBinder>& /*token*/, + bool* /*outIsWideColorDisplay*/) override { + return binder::Status::ok(); + } + + binder::Status getDisplayBrightnessSupport(const sp<IBinder>& /*displayToken*/, + bool* /*outSupport*/) override { + return binder::Status::ok(); + } + + binder::Status setDisplayBrightness(const sp<IBinder>& /*displayToken*/, + const gui::DisplayBrightness& /*brightness*/) override { + return binder::Status::ok(); + } + + binder::Status addHdrLayerInfoListener( + const sp<IBinder>& /*displayToken*/, + const sp<gui::IHdrLayerInfoListener>& /*listener*/) override { + return binder::Status::ok(); + } + + binder::Status removeHdrLayerInfoListener( + const sp<IBinder>& /*displayToken*/, + const sp<gui::IHdrLayerInfoListener>& /*listener*/) override { + return binder::Status::ok(); + } + + binder::Status notifyPowerBoost(int /*boostId*/) override { return binder::Status::ok(); } + +protected: + IBinder* onAsBinder() override { return nullptr; } + +private: + bool mSupportsPresent{true}; +}; + class FakeProducerFrameEventHistory : public ProducerFrameEventHistory { public: explicit FakeProducerFrameEventHistory(FenceToFenceTimeMap* fenceMap) : mFenceMap(fenceMap) {} diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp index 381900e4ba..576941f06a 100644 --- a/libs/nativewindow/AHardwareBuffer.cpp +++ b/libs/nativewindow/AHardwareBuffer.cpp @@ -353,12 +353,12 @@ int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** out return INVALID_OPERATION; } - GraphicBuffer* gBuffer = new GraphicBuffer(); + sp<GraphicBuffer> gBuffer(new GraphicBuffer()); status_t err = gBuffer->unflatten(data, dataLen, fdData, fdCount); if (err != NO_ERROR) { return err; } - *outBuffer = AHardwareBuffer_from_GraphicBuffer(gBuffer); + *outBuffer = AHardwareBuffer_from_GraphicBuffer(gBuffer.get()); // Ensure the buffer has a positive ref-count. AHardwareBuffer_acquire(*outBuffer); diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp index b467b3538d..d05193a490 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp @@ -24,16 +24,34 @@ #include <EGL/egl.h> #include <EGL/eglext.h> #include <GrContextOptions.h> +#include <SkBlendMode.h> #include <SkCanvas.h> +#include <SkColor.h> #include <SkColorFilter.h> #include <SkColorMatrix.h> #include <SkColorSpace.h> +#include <SkData.h> #include <SkGraphics.h> #include <SkImage.h> #include <SkImageFilters.h> +#include <SkImageInfo.h> +#include <SkM44.h> +#include <SkMatrix.h> +#include <SkPaint.h> +#include <SkPath.h> +#include <SkPoint.h> +#include <SkRect.h> +#include <SkRefCnt.h> #include <SkRegion.h> +#include <SkRRect.h> +#include <SkRuntimeEffect.h> +#include <SkSamplingOptions.h> +#include <SkScalar.h> +#include <SkShader.h> #include <SkShadowUtils.h> +#include <SkString.h> #include <SkSurface.h> +#include <SkTileMode.h> #include <android-base/stringprintf.h> #include <gl/GrGLInterface.h> #include <gui/TraceUtils.h> @@ -51,8 +69,6 @@ #include "../gl/GLExtensions.h" #include "Cache.h" #include "ColorSpaces.h" -#include "SkBlendMode.h" -#include "SkImageInfo.h" #include "filters/BlurFilter.h" #include "filters/GaussianBlurFilter.h" #include "filters/KawaseBlurFilter.h" diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h index a650313648..c891a708d9 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.h +++ b/libs/renderengine/skia/SkiaGLRenderEngine.h @@ -41,6 +41,8 @@ #include "filters/LinearEffect.h" #include "filters/StretchShaderFactory.h" +class SkData; + namespace android { namespace renderengine { namespace skia { diff --git a/libs/renderengine/skia/debug/SkiaCapture.cpp b/libs/renderengine/skia/debug/SkiaCapture.cpp index 856fff4b01..b21b01cc1b 100644 --- a/libs/renderengine/skia/debug/SkiaCapture.cpp +++ b/libs/renderengine/skia/debug/SkiaCapture.cpp @@ -27,6 +27,9 @@ #include <utils/Trace.h> #include "CommonPool.h" +#include "SkCanvas.h" +#include "SkRect.h" +#include "SkTypeface.h" #include "src/utils/SkMultiPictureDocument.h" namespace android { diff --git a/libs/renderengine/skia/debug/SkiaCapture.h b/libs/renderengine/skia/debug/SkiaCapture.h index f1946290ca..d65a579916 100644 --- a/libs/renderengine/skia/debug/SkiaCapture.h +++ b/libs/renderengine/skia/debug/SkiaCapture.h @@ -19,13 +19,15 @@ #include <SkDocument.h> #include <SkNWayCanvas.h> #include <SkPictureRecorder.h> +#include <SkRefCnt.h> +#include <SkStream.h> #include <SkSurface.h> +#include "tools/SkSharingProc.h" #include <chrono> #include <mutex> #include "CaptureTimer.h" -#include "tools/SkSharingProc.h" namespace android { namespace renderengine { diff --git a/libs/renderengine/skia/filters/BlurFilter.cpp b/libs/renderengine/skia/filters/BlurFilter.cpp index 63cc02b7ea..2557ac9770 100644 --- a/libs/renderengine/skia/filters/BlurFilter.cpp +++ b/libs/renderengine/skia/filters/BlurFilter.cpp @@ -17,7 +17,6 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include "BlurFilter.h" #include <SkCanvas.h> -#include <SkData.h> #include <SkPaint.h> #include <SkRRect.h> #include <SkRuntimeEffect.h> diff --git a/libs/renderengine/skia/filters/GaussianBlurFilter.cpp b/libs/renderengine/skia/filters/GaussianBlurFilter.cpp index 55867a95cc..f3b6ab9885 100644 --- a/libs/renderengine/skia/filters/GaussianBlurFilter.cpp +++ b/libs/renderengine/skia/filters/GaussianBlurFilter.cpp @@ -18,7 +18,6 @@ #include "GaussianBlurFilter.h" #include <SkCanvas.h> -#include <SkData.h> #include <SkPaint.h> #include <SkRRect.h> #include <SkRuntimeEffect.h> diff --git a/libs/renderengine/skia/filters/KawaseBlurFilter.cpp b/libs/renderengine/skia/filters/KawaseBlurFilter.cpp index bfde06fd9a..e370c39a94 100644 --- a/libs/renderengine/skia/filters/KawaseBlurFilter.cpp +++ b/libs/renderengine/skia/filters/KawaseBlurFilter.cpp @@ -18,7 +18,6 @@ #include "KawaseBlurFilter.h" #include <SkCanvas.h> -#include <SkData.h> #include <SkPaint.h> #include <SkRRect.h> #include <SkRuntimeEffect.h> diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp index ed9bfd272f..41878e3487 100644 --- a/services/inputflinger/Android.bp +++ b/services/inputflinger/Android.bp @@ -58,6 +58,7 @@ filegroup { srcs: [ "InputClassifier.cpp", "InputCommonConverter.cpp", + "PreferStylusOverTouchBlocker.cpp", "UnwantedInteractionBlocker.cpp", "InputManager.cpp", ], diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp index 73b63e3141..3a4b6c599f 100644 --- a/services/inputflinger/InputListener.cpp +++ b/services/inputflinger/InputListener.cpp @@ -334,60 +334,50 @@ static inline void traceEvent(const char* functionName, int32_t id) { QueuedInputListener::QueuedInputListener(InputListenerInterface& innerListener) : mInnerListener(innerListener) {} -QueuedInputListener::~QueuedInputListener() { - size_t count = mArgsQueue.size(); - for (size_t i = 0; i < count; i++) { - delete mArgsQueue[i]; - } -} - void QueuedInputListener::notifyConfigurationChanged( const NotifyConfigurationChangedArgs* args) { traceEvent(__func__, args->id); - mArgsQueue.push_back(new NotifyConfigurationChangedArgs(*args)); + mArgsQueue.emplace_back(std::make_unique<NotifyConfigurationChangedArgs>(*args)); } void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) { traceEvent(__func__, args->id); - mArgsQueue.push_back(new NotifyKeyArgs(*args)); + mArgsQueue.emplace_back(std::make_unique<NotifyKeyArgs>(*args)); } void QueuedInputListener::notifyMotion(const NotifyMotionArgs* args) { traceEvent(__func__, args->id); - mArgsQueue.push_back(new NotifyMotionArgs(*args)); + mArgsQueue.emplace_back(std::make_unique<NotifyMotionArgs>(*args)); } void QueuedInputListener::notifySwitch(const NotifySwitchArgs* args) { traceEvent(__func__, args->id); - mArgsQueue.push_back(new NotifySwitchArgs(*args)); + mArgsQueue.emplace_back(std::make_unique<NotifySwitchArgs>(*args)); } void QueuedInputListener::notifySensor(const NotifySensorArgs* args) { traceEvent(__func__, args->id); - mArgsQueue.push_back(new NotifySensorArgs(*args)); + mArgsQueue.emplace_back(std::make_unique<NotifySensorArgs>(*args)); } void QueuedInputListener::notifyVibratorState(const NotifyVibratorStateArgs* args) { traceEvent(__func__, args->id); - mArgsQueue.push_back(new NotifyVibratorStateArgs(*args)); + mArgsQueue.emplace_back(std::make_unique<NotifyVibratorStateArgs>(*args)); } void QueuedInputListener::notifyDeviceReset(const NotifyDeviceResetArgs* args) { traceEvent(__func__, args->id); - mArgsQueue.push_back(new NotifyDeviceResetArgs(*args)); + mArgsQueue.emplace_back(std::make_unique<NotifyDeviceResetArgs>(*args)); } void QueuedInputListener::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) { traceEvent(__func__, args->id); - mArgsQueue.push_back(new NotifyPointerCaptureChangedArgs(*args)); + mArgsQueue.emplace_back(std::make_unique<NotifyPointerCaptureChangedArgs>(*args)); } void QueuedInputListener::flush() { - size_t count = mArgsQueue.size(); - for (size_t i = 0; i < count; i++) { - NotifyArgs* args = mArgsQueue[i]; + for (const std::unique_ptr<NotifyArgs>& args : mArgsQueue) { args->notify(mInnerListener); - delete args; } mArgsQueue.clear(); } diff --git a/services/inputflinger/PreferStylusOverTouchBlocker.cpp b/services/inputflinger/PreferStylusOverTouchBlocker.cpp new file mode 100644 index 0000000000..ad639b4ef8 --- /dev/null +++ b/services/inputflinger/PreferStylusOverTouchBlocker.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2022 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 "PreferStylusOverTouchBlocker.h" + +#include <android-base/stringprintf.h> + +using android::base::StringPrintf; + +static const char* toString(bool value) { + return value ? "true" : "false"; +} + +namespace android { + +ftl::StaticVector<NotifyMotionArgs, 2> PreferStylusOverTouchBlocker::processMotion( + const NotifyMotionArgs& args) { + const bool isStylusEvent = isFromSource(args.source, AINPUT_SOURCE_STYLUS); + if (isStylusEvent) { + for (size_t i = 0; i < args.pointerCount; i++) { + // Make sure we are canceling stylus pointers + const int32_t toolType = args.pointerProperties[i].toolType; + LOG_ALWAYS_FATAL_IF(toolType != AMOTION_EVENT_TOOL_TYPE_STYLUS && + toolType != AMOTION_EVENT_TOOL_TYPE_ERASER, + "The pointer %zu has toolType=%i, but the source is STYLUS. If " + "simultaneous touch and stylus is supported, " + "'PreferStylusOverTouchBlocker' should be disabled.", + i, toolType); + } + } + const bool isDown = args.action == AMOTION_EVENT_ACTION_DOWN; + const bool isUpOrCancel = + args.action == AMOTION_EVENT_ACTION_UP || args.action == AMOTION_EVENT_ACTION_CANCEL; + if (isStylusEvent) { + if (isDown) { + // Reject all touch while stylus is down + mIsStylusDown = true; + if (mIsTouchDown && !mCurrentTouchIsCanceled) { + // Cancel touch! + mCurrentTouchIsCanceled = true; + mLastTouchEvent.action = AMOTION_EVENT_ACTION_CANCEL; + mLastTouchEvent.flags |= AMOTION_EVENT_FLAG_CANCELED; + mLastTouchEvent.eventTime = systemTime(SYSTEM_TIME_MONOTONIC); + return {mLastTouchEvent, args}; + } + } + if (isUpOrCancel) { + mIsStylusDown = false; + } + // Never drop stylus events + return {args}; + } + + const bool isTouchEvent = + isFromSource(args.source, AINPUT_SOURCE_TOUCHSCREEN) && !isStylusEvent; + if (isTouchEvent) { + if (mIsStylusDown) { + mCurrentTouchIsCanceled = true; + } + // If we already canceled the current gesture, then continue to drop events from it, even if + // the stylus has been lifted. + if (mCurrentTouchIsCanceled) { + if (isUpOrCancel) { + mCurrentTouchIsCanceled = false; + } + return {}; + } + + // Update state + mLastTouchEvent = args; + if (isDown) { + mIsTouchDown = true; + } + if (isUpOrCancel) { + mIsTouchDown = false; + mCurrentTouchIsCanceled = false; + } + return {args}; + } + + // Not a touch or stylus event + return {args}; +} + +std::string PreferStylusOverTouchBlocker::dump() { + std::string out; + out += StringPrintf("mIsTouchDown: %s\n", toString(mIsTouchDown)); + out += StringPrintf("mIsStylusDown: %s\n", toString(mIsStylusDown)); + out += StringPrintf("mLastTouchEvent: %s\n", mLastTouchEvent.dump().c_str()); + out += StringPrintf("mCurrentTouchIsCanceled: %s\n", toString(mCurrentTouchIsCanceled)); + return out; +} + +} // namespace android diff --git a/services/inputflinger/PreferStylusOverTouchBlocker.h b/services/inputflinger/PreferStylusOverTouchBlocker.h new file mode 100644 index 0000000000..3f5616190b --- /dev/null +++ b/services/inputflinger/PreferStylusOverTouchBlocker.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2022 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 <ftl/static_vector.h> +#include <optional> +#include "InputListener.h" + +namespace android { + +/** + * When stylus is down, we ignore all touch. + * TODO(b/210159205): delete this when simultaneous stylus and touch is supported + */ +class PreferStylusOverTouchBlocker { +public: + /** + * Process the provided event and emit up to 2 events in response. + * In the majority of cases, the returned result will just be the provided args (array with + * only 1 element), unmodified. + * + * If the gesture should be blocked, the returned result may be: + * + * a) An empty array, if the current event should just be ignored completely + * b) An array of 2 elements, containing an event with ACTION_CANCEL and the current event. + * + * bool is set to 'true'. + * NotifyMotionArgs potentially contains an event that should be used to cancel the existing + * gesture. + * + * If the event should not be blocked, bool contains 'false'. + */ + ftl::StaticVector<NotifyMotionArgs, 2> processMotion(const NotifyMotionArgs& args); + std::string dump(); + +private: + bool mIsTouchDown = false; + bool mIsStylusDown = false; + // Provide some default values for the stored MotionEvent to allow printint the event before + // any real event is received. + NotifyMotionArgs mLastTouchEvent{0 /*id*/, + 0 /*eventTime*/, + 0 /*readTime*/, + 0 /*deviceId*/, + AINPUT_SOURCE_TOUCHSCREEN, + 0 /*displayId*/, + 0 /*policyFlags*/, + 0 /*action*/, + 0 /*actionButton*/, + 0 /*flags*/, + 0 /*metaState*/, + 0 /*buttonState*/, + MotionClassification::NONE, + AMOTION_EVENT_EDGE_FLAG_NONE, + 0 /*pointerCount*/, + nullptr /*properties*/, + nullptr /*coords*/, + 0. /*xPrecision*/, + 0. /*yPrecision*/, + AMOTION_EVENT_INVALID_CURSOR_POSITION, + AMOTION_EVENT_INVALID_CURSOR_POSITION, + 0 /*downTime*/, + {}}; + bool mCurrentTouchIsCanceled = false; +}; + +} // namespace android
\ No newline at end of file diff --git a/services/inputflinger/UnwantedInteractionBlocker.cpp b/services/inputflinger/UnwantedInteractionBlocker.cpp index 64dbb8ceb4..f904bfd82e 100644 --- a/services/inputflinger/UnwantedInteractionBlocker.cpp +++ b/services/inputflinger/UnwantedInteractionBlocker.cpp @@ -44,7 +44,8 @@ static std::string toLower(std::string s) { } static bool isFromTouchscreen(int32_t source) { - return isFromSource(source, AINPUT_SOURCE_TOUCHSCREEN); + return isFromSource(source, AINPUT_SOURCE_TOUCHSCREEN) && + !isFromSource(source, AINPUT_SOURCE_STYLUS); } static ::base::TimeTicks toChromeTimestamp(nsecs_t eventTime) { @@ -367,6 +368,14 @@ void UnwantedInteractionBlocker::notifyKey(const NotifyKeyArgs* args) { } void UnwantedInteractionBlocker::notifyMotion(const NotifyMotionArgs* args) { + ftl::StaticVector<NotifyMotionArgs, 2> processedArgs = + mPreferStylusOverTouchBlocker.processMotion(*args); + for (const NotifyMotionArgs& loopArgs : processedArgs) { + notifyMotionInner(&loopArgs); + } +} + +void UnwantedInteractionBlocker::notifyMotionInner(const NotifyMotionArgs* args) { auto it = mPalmRejectors.find(args->deviceId); const bool sendToPalmRejector = it != mPalmRejectors.end() && isFromTouchscreen(args->source); if (!sendToPalmRejector) { @@ -440,6 +449,8 @@ void UnwantedInteractionBlocker::notifyInputDevicesChanged( void UnwantedInteractionBlocker::dump(std::string& dump) { dump += "UnwantedInteractionBlocker:\n"; + dump += " mPreferStylusOverTouchBlocker:\n"; + dump += addPrefix(mPreferStylusOverTouchBlocker.dump(), " "); dump += StringPrintf(" mEnablePalmRejection: %s\n", toString(mEnablePalmRejection)); dump += StringPrintf(" isPalmRejectionEnabled (flag value): %s\n", toString(isPalmRejectionEnabled())); diff --git a/services/inputflinger/UnwantedInteractionBlocker.h b/services/inputflinger/UnwantedInteractionBlocker.h index 14068fd878..9e41995ac4 100644 --- a/services/inputflinger/UnwantedInteractionBlocker.h +++ b/services/inputflinger/UnwantedInteractionBlocker.h @@ -23,6 +23,8 @@ #include "ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.h" #include "ui/events/ozone/evdev/touch_filter/palm_detection_filter.h" +#include "PreferStylusOverTouchBlocker.h" + namespace android { // --- Functions for manipulation of event streams @@ -88,9 +90,13 @@ private: InputListenerInterface& mListener; const bool mEnablePalmRejection; + // When stylus is down, ignore touch + PreferStylusOverTouchBlocker mPreferStylusOverTouchBlocker; // Detect and reject unwanted palms on screen // Use a separate palm rejector for every touch device. std::map<int32_t /*deviceId*/, PalmRejector> mPalmRejectors; + // TODO(b/210159205): delete this when simultaneous stylus and touch is supported + void notifyMotionInner(const NotifyMotionArgs* args); }; class SlotState { diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index bfdd22c3df..06ad6a8f61 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -160,10 +160,7 @@ const std::chrono::duration DEFAULT_INPUT_DISPATCHING_TIMEOUT = std::chrono::mil // when an application takes too long to respond and the user has pressed an app switch key. constexpr nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec -// Amount of time to allow for an event to be dispatched (measured since its eventTime) -// before considering it stale and dropping it. -const nsecs_t STALE_EVENT_TIMEOUT = 10000 * 1000000LL // 10sec - * HwTimeoutMultiplier(); +const std::chrono::duration STALE_EVENT_TIMEOUT = std::chrono::seconds(10) * HwTimeoutMultiplier(); // Log a warning when an event takes longer than this to process, even if an ANR does not occur. constexpr nsecs_t SLOW_EVENT_PROCESSING_WARNING_TIMEOUT = 2000 * 1000000LL; // 2sec @@ -364,10 +361,6 @@ bool haveSameApplicationToken(const WindowInfo* first, const WindowInfo* second) first->applicationInfo.token == second->applicationInfo.token; } -bool isStaleEvent(nsecs_t currentTime, const EventEntry& entry) { - return currentTime - entry.eventTime >= STALE_EVENT_TIMEOUT; -} - std::unique_ptr<DispatchEntry> createDispatchEntry(const InputTarget& inputTarget, std::shared_ptr<EventEntry> eventEntry, int32_t inputTargetFlags) { @@ -568,6 +561,10 @@ bool isPointerFromStylus(const MotionEntry& entry, int32_t pointerIndex) { // --- InputDispatcher --- InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) + : InputDispatcher(policy, STALE_EVENT_TIMEOUT) {} + +InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy, + std::chrono::nanoseconds staleEventTimeout) : mPolicy(policy), mPendingEvent(nullptr), mLastDropReason(DropReason::NOT_DROPPED), @@ -586,6 +583,7 @@ InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& polic mMaximumObscuringOpacityForTouch(1.0f), mFocusedDisplayId(ADISPLAY_ID_DEFAULT), mWindowTokenWithPointerCapture(nullptr), + mStaleEventTimeout(staleEventTimeout), mLatencyAggregator(), mLatencyTracker(&mLatencyAggregator) { mLooper = new Looper(false); @@ -943,6 +941,10 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) { } } +bool InputDispatcher::isStaleEvent(nsecs_t currentTime, const EventEntry& entry) { + return std::chrono::nanoseconds(currentTime - entry.eventTime) >= mStaleEventTimeout; +} + /** * Return true if the events preceding this incoming motion event should be dropped * Return false otherwise (the default behaviour) diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index d3e171a2d8..3c79c988c4 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -84,6 +84,8 @@ public: static constexpr bool kDefaultInTouchMode = true; explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy); + explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy, + std::chrono::nanoseconds staleEventTimeout); ~InputDispatcher() override; void dump(std::string& dump) override; @@ -471,6 +473,11 @@ private: */ std::optional<nsecs_t> mNoFocusedWindowTimeoutTime GUARDED_BY(mLock); + // Amount of time to allow for an event to be dispatched (measured since its eventTime) + // before considering it stale and dropping it. + const std::chrono::nanoseconds mStaleEventTimeout; + bool isStaleEvent(nsecs_t currentTime, const EventEntry& entry); + bool shouldPruneInboundQueueLocked(const MotionEntry& motionEntry) REQUIRES(mLock); /** diff --git a/services/inputflinger/include/InputListener.h b/services/inputflinger/include/InputListener.h index dff58949a7..d9822ce156 100644 --- a/services/inputflinger/include/InputListener.h +++ b/services/inputflinger/include/InputListener.h @@ -274,7 +274,6 @@ class QueuedInputListener : public InputListenerInterface { public: explicit QueuedInputListener(InputListenerInterface& innerListener); - virtual ~QueuedInputListener(); virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override; virtual void notifyKey(const NotifyKeyArgs* args) override; @@ -289,7 +288,7 @@ public: private: InputListenerInterface& mInnerListener; - std::vector<NotifyArgs*> mArgsQueue; + std::vector<std::unique_ptr<NotifyArgs>> mArgsQueue; }; } // namespace android diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp index 41a8426e42..8f5dc9bfd5 100644 --- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp @@ -31,23 +31,15 @@ static constexpr size_t MAX_SLOTS = 32; MultiTouchMotionAccumulator::MultiTouchMotionAccumulator() : mCurrentSlot(-1), - mSlots(nullptr), - mSlotCount(0), mUsingSlotsProtocol(false), mHaveStylus(false) {} -MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() { - delete[] mSlots; -} - void MultiTouchMotionAccumulator::configure(InputDeviceContext& deviceContext, size_t slotCount, bool usingSlotsProtocol) { - mSlotCount = slotCount; mUsingSlotsProtocol = usingSlotsProtocol; mHaveStylus = deviceContext.hasAbsoluteAxis(ABS_MT_TOOL_TYPE); - delete[] mSlots; - mSlots = new Slot[slotCount]; + mSlots = std::vector<Slot>(slotCount); } void MultiTouchMotionAccumulator::reset(InputDeviceContext& deviceContext) { @@ -76,10 +68,8 @@ void MultiTouchMotionAccumulator::reset(InputDeviceContext& deviceContext) { } void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) { - if (mSlots) { - for (size_t i = 0; i < mSlotCount; i++) { - mSlots[i].clear(); - } + for (Slot& slot : mSlots) { + slot.clear(); } mCurrentSlot = initialSlot; } @@ -96,68 +86,68 @@ void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) { mCurrentSlot = 0; } - if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) { + if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlots.size()) { if (DEBUG_POINTERS) { if (newSlot) { ALOGW("MultiTouch device emitted invalid slot index %d but it " "should be between 0 and %zd; ignoring this slot.", - mCurrentSlot, mSlotCount - 1); + mCurrentSlot, mSlots.size() - 1); } } } else { - Slot* slot = &mSlots[mCurrentSlot]; + Slot& slot = mSlots[mCurrentSlot]; // If mUsingSlotsProtocol is true, it means the raw pointer has axis info of // ABS_MT_TRACKING_ID and ABS_MT_SLOT, so driver should send a valid trackingId while // updating the slot. if (!mUsingSlotsProtocol) { - slot->mInUse = true; + slot.mInUse = true; } switch (rawEvent->code) { case ABS_MT_POSITION_X: - slot->mAbsMTPositionX = rawEvent->value; - warnIfNotInUse(*rawEvent, *slot); + slot.mAbsMTPositionX = rawEvent->value; + warnIfNotInUse(*rawEvent, slot); break; case ABS_MT_POSITION_Y: - slot->mAbsMTPositionY = rawEvent->value; - warnIfNotInUse(*rawEvent, *slot); + slot.mAbsMTPositionY = rawEvent->value; + warnIfNotInUse(*rawEvent, slot); break; case ABS_MT_TOUCH_MAJOR: - slot->mAbsMTTouchMajor = rawEvent->value; + slot.mAbsMTTouchMajor = rawEvent->value; break; case ABS_MT_TOUCH_MINOR: - slot->mAbsMTTouchMinor = rawEvent->value; - slot->mHaveAbsMTTouchMinor = true; + slot.mAbsMTTouchMinor = rawEvent->value; + slot.mHaveAbsMTTouchMinor = true; break; case ABS_MT_WIDTH_MAJOR: - slot->mAbsMTWidthMajor = rawEvent->value; + slot.mAbsMTWidthMajor = rawEvent->value; break; case ABS_MT_WIDTH_MINOR: - slot->mAbsMTWidthMinor = rawEvent->value; - slot->mHaveAbsMTWidthMinor = true; + slot.mAbsMTWidthMinor = rawEvent->value; + slot.mHaveAbsMTWidthMinor = true; break; case ABS_MT_ORIENTATION: - slot->mAbsMTOrientation = rawEvent->value; + slot.mAbsMTOrientation = rawEvent->value; break; case ABS_MT_TRACKING_ID: if (mUsingSlotsProtocol && rawEvent->value < 0) { // The slot is no longer in use but it retains its previous contents, // which may be reused for subsequent touches. - slot->mInUse = false; + slot.mInUse = false; } else { - slot->mInUse = true; - slot->mAbsMTTrackingId = rawEvent->value; + slot.mInUse = true; + slot.mAbsMTTrackingId = rawEvent->value; } break; case ABS_MT_PRESSURE: - slot->mAbsMTPressure = rawEvent->value; + slot.mAbsMTPressure = rawEvent->value; break; case ABS_MT_DISTANCE: - slot->mAbsMTDistance = rawEvent->value; + slot.mAbsMTDistance = rawEvent->value; break; case ABS_MT_TOOL_TYPE: - slot->mAbsMTToolType = rawEvent->value; - slot->mHaveAbsMTToolType = true; + slot.mAbsMTToolType = rawEvent->value; + slot.mHaveAbsMTToolType = true; break; } } @@ -186,28 +176,6 @@ void MultiTouchMotionAccumulator::warnIfNotInUse(const RawEvent& event, const Sl // --- MultiTouchMotionAccumulator::Slot --- -MultiTouchMotionAccumulator::Slot::Slot() { - clear(); -} - -void MultiTouchMotionAccumulator::Slot::clear() { - mInUse = false; - mHaveAbsMTTouchMinor = false; - mHaveAbsMTWidthMinor = false; - mHaveAbsMTToolType = false; - mAbsMTPositionX = 0; - mAbsMTPositionY = 0; - mAbsMTTouchMajor = 0; - mAbsMTTouchMinor = 0; - mAbsMTWidthMajor = 0; - mAbsMTWidthMinor = 0; - mAbsMTOrientation = 0; - mAbsMTTrackingId = -1; - mAbsMTPressure = 0; - mAbsMTDistance = 0; - mAbsMTToolType = 0; -} - int32_t MultiTouchMotionAccumulator::Slot::getToolType() const { if (mHaveAbsMTToolType) { switch (mAbsMTToolType) { @@ -264,14 +232,14 @@ void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) { mHavePointerIds = true; for (size_t inIndex = 0; inIndex < inCount; inIndex++) { - const MultiTouchMotionAccumulator::Slot* inSlot = + const MultiTouchMotionAccumulator::Slot& inSlot = mMultiTouchMotionAccumulator.getSlot(inIndex); - if (!inSlot->isInUse()) { + if (!inSlot.isInUse()) { continue; } - if (inSlot->getToolType() == AMOTION_EVENT_TOOL_TYPE_PALM) { - std::optional<int32_t> id = getActiveBitId(*inSlot); + if (inSlot.getToolType() == AMOTION_EVENT_TOOL_TYPE_PALM) { + std::optional<int32_t> id = getActiveBitId(inSlot); if (id) { outState->rawPointerData.canceledIdBits.markBit(id.value()); } @@ -292,19 +260,19 @@ void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) { } RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[outCount]; - outPointer.x = inSlot->getX(); - outPointer.y = inSlot->getY(); - outPointer.pressure = inSlot->getPressure(); - outPointer.touchMajor = inSlot->getTouchMajor(); - outPointer.touchMinor = inSlot->getTouchMinor(); - outPointer.toolMajor = inSlot->getToolMajor(); - outPointer.toolMinor = inSlot->getToolMinor(); - outPointer.orientation = inSlot->getOrientation(); - outPointer.distance = inSlot->getDistance(); + outPointer.x = inSlot.getX(); + outPointer.y = inSlot.getY(); + outPointer.pressure = inSlot.getPressure(); + outPointer.touchMajor = inSlot.getTouchMajor(); + outPointer.touchMinor = inSlot.getTouchMinor(); + outPointer.toolMajor = inSlot.getToolMajor(); + outPointer.toolMinor = inSlot.getToolMinor(); + outPointer.orientation = inSlot.getOrientation(); + outPointer.distance = inSlot.getDistance(); outPointer.tiltX = 0; outPointer.tiltY = 0; - outPointer.toolType = inSlot->getToolType(); + outPointer.toolType = inSlot.getToolType(); if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) { outPointer.toolType = mTouchButtonAccumulator.getToolType(); if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) { @@ -318,12 +286,12 @@ void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) { bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE && (mTouchButtonAccumulator.isHovering() || - (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0)); + (mRawPointerAxes.pressure.valid && inSlot.getPressure() <= 0)); outPointer.isHovering = isHovering; // Assign pointer id using tracking id if available. if (mHavePointerIds) { - int32_t trackingId = inSlot->getTrackingId(); + int32_t trackingId = inSlot.getTrackingId(); int32_t id = -1; if (trackingId >= 0) { for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty();) { diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h index b7c3457285..fe8af5d818 100644 --- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h +++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h @@ -46,29 +46,27 @@ public: private: friend class MultiTouchMotionAccumulator; - bool mInUse; - bool mHaveAbsMTTouchMinor; - bool mHaveAbsMTWidthMinor; - bool mHaveAbsMTToolType; - - int32_t mAbsMTPositionX; - int32_t mAbsMTPositionY; - int32_t mAbsMTTouchMajor; - int32_t mAbsMTTouchMinor; - int32_t mAbsMTWidthMajor; - int32_t mAbsMTWidthMinor; - int32_t mAbsMTOrientation; - int32_t mAbsMTTrackingId; - int32_t mAbsMTPressure; - int32_t mAbsMTDistance; - int32_t mAbsMTToolType; - - Slot(); - void clear(); + bool mInUse = false; + bool mHaveAbsMTTouchMinor = false; + bool mHaveAbsMTWidthMinor = false; + bool mHaveAbsMTToolType = false; + + int32_t mAbsMTPositionX = 0; + int32_t mAbsMTPositionY = 0; + int32_t mAbsMTTouchMajor = 0; + int32_t mAbsMTTouchMinor = 0; + int32_t mAbsMTWidthMajor = 0; + int32_t mAbsMTWidthMinor = 0; + int32_t mAbsMTOrientation = 0; + int32_t mAbsMTTrackingId = -1; + int32_t mAbsMTPressure = 0; + int32_t mAbsMTDistance = 0; + int32_t mAbsMTToolType = 0; + + void clear() { *this = Slot(); } }; MultiTouchMotionAccumulator(); - ~MultiTouchMotionAccumulator(); void configure(InputDeviceContext& deviceContext, size_t slotCount, bool usingSlotsProtocol); void reset(InputDeviceContext& deviceContext); @@ -76,13 +74,15 @@ public: void finishSync(); bool hasStylus() const; - inline size_t getSlotCount() const { return mSlotCount; } - inline const Slot* getSlot(size_t index) const { return &mSlots[index]; } + inline size_t getSlotCount() const { return mSlots.size(); } + inline const Slot& getSlot(size_t index) const { + LOG_ALWAYS_FATAL_IF(index < 0 || index >= mSlots.size(), "Invalid index: %zu", index); + return mSlots[index]; + } private: int32_t mCurrentSlot; - Slot* mSlots; - size_t mSlotCount; + std::vector<Slot> mSlots; bool mUsingSlotsProtocol; bool mHaveStylus; diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp index 9d200bdeff..76a7c19086 100644 --- a/services/inputflinger/tests/Android.bp +++ b/services/inputflinger/tests/Android.bp @@ -47,6 +47,7 @@ cc_test { "InputReader_test.cpp", "InputFlingerService_test.cpp", "LatencyTracker_test.cpp", + "PreferStylusOverTouch_test.cpp", "TestInputListener.cpp", "UinputDevice.cpp", "UnwantedInteractionBlocker_test.cpp", diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 470d2f686d..9633932e75 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -65,6 +65,8 @@ static const int32_t INJECTOR_UID = 1001; // An arbitrary pid of the gesture monitor window static constexpr int32_t MONITOR_PID = 2001; +static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms; + struct PointF { float x; float y; @@ -489,7 +491,7 @@ protected: void SetUp() override { mFakePolicy = new FakeInputDispatcherPolicy(); - mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy); + mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy, STALE_EVENT_TIMEOUT); mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false); // Start InputDispatcher thread ASSERT_EQ(OK, mDispatcher->start()); @@ -4451,6 +4453,38 @@ TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) { ASSERT_TRUE(mDispatcher->waitForIdle()); } +/** + * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window, + * there will not be an ANR. + */ +TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) { + mWindow->setFocusable(false); + mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}}); + mWindow->consumeFocusEvent(false); + + KeyEvent event; + const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) - + std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count(); + + // Define a valid key down event that is stale (too old). + event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, + INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A, + AMETA_NONE, 1 /*repeatCount*/, eventTime, eventTime); + + const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER; + + InputEventInjectionResult result = + mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, + InputEventInjectionSync::WAIT_FOR_RESULT, + INJECT_EVENT_TIMEOUT, policyFlags); + ASSERT_EQ(InputEventInjectionResult::FAILED, result) + << "Injection should fail because the event is stale"; + + ASSERT_TRUE(mDispatcher->waitForIdle()); + mFakePolicy->assertNotifyAnrWasNotCalled(); + mWindow->assertNoEvents(); +} + // We have a focused application, but no focused window // Make sure that we don't notify policy twice about the same ANR. TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) { diff --git a/services/inputflinger/tests/PreferStylusOverTouch_test.cpp b/services/inputflinger/tests/PreferStylusOverTouch_test.cpp new file mode 100644 index 0000000000..70f40aa028 --- /dev/null +++ b/services/inputflinger/tests/PreferStylusOverTouch_test.cpp @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2022 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 <gtest/gtest.h> +#include "../PreferStylusOverTouchBlocker.h" + +namespace android { + +constexpr int32_t TOUCH_DEVICE_ID = 3; +constexpr int32_t STYLUS_DEVICE_ID = 4; + +constexpr int DOWN = AMOTION_EVENT_ACTION_DOWN; +constexpr int MOVE = AMOTION_EVENT_ACTION_MOVE; +constexpr int UP = AMOTION_EVENT_ACTION_UP; +constexpr int CANCEL = AMOTION_EVENT_ACTION_CANCEL; +constexpr int32_t TOUCHSCREEN = AINPUT_SOURCE_TOUCHSCREEN; +constexpr int32_t STYLUS = AINPUT_SOURCE_STYLUS; + +struct PointerData { + float x; + float y; +}; + +static NotifyMotionArgs generateMotionArgs(nsecs_t downTime, nsecs_t eventTime, int32_t action, + const std::vector<PointerData>& points, + uint32_t source) { + size_t pointerCount = points.size(); + if (action == DOWN || action == UP) { + EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer"; + } + + PointerProperties pointerProperties[pointerCount]; + PointerCoords pointerCoords[pointerCount]; + + const int32_t deviceId = isFromSource(source, TOUCHSCREEN) ? TOUCH_DEVICE_ID : STYLUS_DEVICE_ID; + const int32_t toolType = isFromSource(source, TOUCHSCREEN) ? AMOTION_EVENT_TOOL_TYPE_FINGER + : AMOTION_EVENT_TOOL_TYPE_STYLUS; + for (size_t i = 0; i < pointerCount; i++) { + pointerProperties[i].clear(); + pointerProperties[i].id = i; + pointerProperties[i].toolType = toolType; + + pointerCoords[i].clear(); + pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x); + pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y); + } + + // Currently, can't have STYLUS source without it also being a TOUCH source. Update the source + // accordingly. + if (isFromSource(source, STYLUS)) { + source |= TOUCHSCREEN; + } + + // Define a valid motion event. + NotifyMotionArgs args(/* id */ 0, eventTime, 0 /*readTime*/, deviceId, source, 0 /*displayId*/, + POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, + /* flags */ 0, AMETA_NONE, /* buttonState */ 0, + MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, + pointerProperties, pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0, + AMOTION_EVENT_INVALID_CURSOR_POSITION, + AMOTION_EVENT_INVALID_CURSOR_POSITION, downTime, /* videoFrames */ {}); + + return args; +} + +class PreferStylusOverTouchTest : public testing::Test { +protected: + void assertNotBlocked(const NotifyMotionArgs& args) { + ftl::StaticVector<NotifyMotionArgs, 2> processedArgs = mBlocker.processMotion(args); + ASSERT_EQ(1u, processedArgs.size()); + ASSERT_EQ(args, processedArgs[0]); + } + + void assertDropped(const NotifyMotionArgs& args) { + ftl::StaticVector<NotifyMotionArgs, 2> processedArgs = mBlocker.processMotion(args); + ASSERT_TRUE(processedArgs.empty()); + } + + void assertCanceled(const NotifyMotionArgs& args, + std::optional<NotifyMotionArgs> canceledArgs) { + ftl::StaticVector<NotifyMotionArgs, 2> processedArgs = mBlocker.processMotion(args); + ASSERT_EQ(2u, processedArgs.size()); + NotifyMotionArgs& cancelEvent = processedArgs[0]; + ASSERT_EQ(CANCEL, cancelEvent.action); + ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, cancelEvent.flags & AMOTION_EVENT_FLAG_CANCELED); + ASSERT_TRUE(isFromSource(cancelEvent.source, TOUCHSCREEN)); + ASSERT_FALSE(isFromSource(cancelEvent.source, STYLUS)); + + ASSERT_EQ(args, processedArgs[1]); + } + +private: + PreferStylusOverTouchBlocker mBlocker; +}; + +TEST_F(PreferStylusOverTouchTest, TouchGestureIsNotBlocked) { + NotifyMotionArgs args; + + args = generateMotionArgs(0 /*downTime*/, 0 /*eventTime*/, DOWN, {{1, 2}}, TOUCHSCREEN); + assertNotBlocked(args); + + args = generateMotionArgs(0 /*downTime*/, 1 /*eventTime*/, MOVE, {{1, 3}}, TOUCHSCREEN); + assertNotBlocked(args); + + args = generateMotionArgs(0 /*downTime*/, 2 /*eventTime*/, UP, {{1, 3}}, TOUCHSCREEN); + assertNotBlocked(args); +} + +TEST_F(PreferStylusOverTouchTest, StylusGestureIsNotBlocked) { + NotifyMotionArgs args; + + args = generateMotionArgs(0 /*downTime*/, 0 /*eventTime*/, DOWN, {{1, 2}}, STYLUS); + assertNotBlocked(args); + + args = generateMotionArgs(0 /*downTime*/, 1 /*eventTime*/, MOVE, {{1, 3}}, STYLUS); + assertNotBlocked(args); + + args = generateMotionArgs(0 /*downTime*/, 2 /*eventTime*/, UP, {{1, 3}}, STYLUS); + assertNotBlocked(args); +} + +/** + * Existing touch gesture should be canceled when stylus goes down. There should be an ACTION_CANCEL + * event generated. + */ +TEST_F(PreferStylusOverTouchTest, TouchIsCanceledWhenStylusGoesDown) { + NotifyMotionArgs args; + + args = generateMotionArgs(0 /*downTime*/, 0 /*eventTime*/, DOWN, {{1, 2}}, TOUCHSCREEN); + assertNotBlocked(args); + + args = generateMotionArgs(0 /*downTime*/, 1 /*eventTime*/, MOVE, {{1, 3}}, TOUCHSCREEN); + assertNotBlocked(args); + + args = generateMotionArgs(3 /*downTime*/, 3 /*eventTime*/, DOWN, {{10, 30}}, STYLUS); + NotifyMotionArgs cancelArgs = + generateMotionArgs(0 /*downTime*/, 1 /*eventTime*/, CANCEL, {{1, 3}}, TOUCHSCREEN); + assertCanceled(args, cancelArgs); + + // Both stylus and touch events continue. Stylus should be not blocked, and touch should be + // blocked + args = generateMotionArgs(3 /*downTime*/, 4 /*eventTime*/, MOVE, {{10, 31}}, STYLUS); + assertNotBlocked(args); + + args = generateMotionArgs(0 /*downTime*/, 5 /*eventTime*/, MOVE, {{1, 4}}, TOUCHSCREEN); + assertDropped(args); +} + +/** + * New touch events should be simply blocked (dropped) when stylus is down. No CANCEL event should + * be generated. + */ +TEST_F(PreferStylusOverTouchTest, NewTouchIsBlockedWhenStylusIsDown) { + NotifyMotionArgs args; + constexpr nsecs_t stylusDownTime = 0; + constexpr nsecs_t touchDownTime = 1; + + args = generateMotionArgs(stylusDownTime, 0 /*eventTime*/, DOWN, {{10, 30}}, STYLUS); + assertNotBlocked(args); + + args = generateMotionArgs(touchDownTime, 1 /*eventTime*/, DOWN, {{1, 2}}, TOUCHSCREEN); + assertDropped(args); + + // Stylus should continue to work + args = generateMotionArgs(stylusDownTime, 2 /*eventTime*/, MOVE, {{10, 31}}, STYLUS); + assertNotBlocked(args); + + // Touch should continue to be blocked + args = generateMotionArgs(touchDownTime, 1 /*eventTime*/, MOVE, {{1, 3}}, TOUCHSCREEN); + assertDropped(args); + + args = generateMotionArgs(0 /*downTime*/, 5 /*eventTime*/, MOVE, {{1, 4}}, TOUCHSCREEN); + assertDropped(args); +} + +/** + * New touch events should be simply blocked (dropped) when stylus is down. No CANCEL event should + * be generated. + */ +TEST_F(PreferStylusOverTouchTest, NewTouchWorksAfterStylusIsLifted) { + NotifyMotionArgs args; + constexpr nsecs_t stylusDownTime = 0; + constexpr nsecs_t touchDownTime = 4; + + // Stylus goes down and up + args = generateMotionArgs(stylusDownTime, 0 /*eventTime*/, DOWN, {{10, 30}}, STYLUS); + assertNotBlocked(args); + + args = generateMotionArgs(stylusDownTime, 2 /*eventTime*/, MOVE, {{10, 31}}, STYLUS); + assertNotBlocked(args); + + args = generateMotionArgs(stylusDownTime, 3 /*eventTime*/, UP, {{10, 31}}, STYLUS); + assertNotBlocked(args); + + // New touch goes down. It should not be blocked + args = generateMotionArgs(touchDownTime, touchDownTime, DOWN, {{1, 2}}, TOUCHSCREEN); + assertNotBlocked(args); + + args = generateMotionArgs(touchDownTime, 5 /*eventTime*/, MOVE, {{1, 3}}, TOUCHSCREEN); + assertNotBlocked(args); + + args = generateMotionArgs(touchDownTime, 6 /*eventTime*/, UP, {{1, 3}}, TOUCHSCREEN); + assertNotBlocked(args); +} + +/** + * Once a touch gesture is canceled, it should continue to be canceled, even if the stylus has been + * lifted. + */ +TEST_F(PreferStylusOverTouchTest, AfterStylusIsLiftedCurrentTouchIsBlocked) { + NotifyMotionArgs args; + constexpr nsecs_t stylusDownTime = 0; + constexpr nsecs_t touchDownTime = 1; + + assertNotBlocked(generateMotionArgs(stylusDownTime, 0 /*eventTime*/, DOWN, {{10, 30}}, STYLUS)); + + args = generateMotionArgs(touchDownTime, 1 /*eventTime*/, DOWN, {{1, 2}}, TOUCHSCREEN); + assertDropped(args); + + // Lift the stylus + args = generateMotionArgs(stylusDownTime, 2 /*eventTime*/, UP, {{10, 30}}, STYLUS); + assertNotBlocked(args); + + // Touch should continue to be blocked + args = generateMotionArgs(touchDownTime, 3 /*eventTime*/, MOVE, {{1, 3}}, TOUCHSCREEN); + assertDropped(args); + + args = generateMotionArgs(touchDownTime, 4 /*eventTime*/, UP, {{1, 3}}, TOUCHSCREEN); + assertDropped(args); + + // New touch should go through, though. + constexpr nsecs_t newTouchDownTime = 5; + args = generateMotionArgs(newTouchDownTime, 5 /*eventTime*/, DOWN, {{10, 20}}, TOUCHSCREEN); + assertNotBlocked(args); +} + +} // namespace android diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index 334d6ecbff..892d8dce03 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -87,7 +87,7 @@ public: virtual hal::HWDisplayId getId() const = 0; virtual bool isConnected() const = 0; - virtual void setConnected(bool connected) = 0; // For use by Device only + virtual void setConnected(bool connected) = 0; // For use by HWComposer only virtual bool hasCapability( aidl::android::hardware::graphics::composer3::DisplayCapability) const = 0; virtual bool isVsyncPeriodSwitchSupported() const = 0; @@ -246,7 +246,7 @@ public: // Other Display methods hal::HWDisplayId getId() const override { return mId; } bool isConnected() const override { return mIsConnected; } - void setConnected(bool connected) override; // For use by Device only + void setConnected(bool connected) override; bool hasCapability(aidl::android::hardware::graphics::composer3::DisplayCapability) const override EXCLUDES(mDisplayCapabilitiesMutex); bool isVsyncPeriodSwitchSupported() const override; @@ -262,7 +262,7 @@ private: // Member variables - // These are references to data owned by HWC2::Device, which will outlive + // These are references to data owned by HWComposer, which will outlive // this HWC2::Display, so these references are guaranteed to be valid for // the lifetime of this object. android::Hwc2::Composer& mComposer; @@ -380,7 +380,7 @@ public: hal::Error setBlockingRegion(const android::Region& region) override; private: - // These are references to data owned by HWC2::Device, which will outlive + // These are references to data owned by HWComposer, which will outlive // this HWC2::Layer, so these references are guaranteed to be valid for // the lifetime of this object. android::Hwc2::Composer& mComposer; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 350d7096aa..d264043a44 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5421,30 +5421,21 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { // access to SF. case BOOT_FINISHED: case CLEAR_ANIMATION_FRAME_STATS: - case CREATE_DISPLAY: - case DESTROY_DISPLAY: case GET_ANIMATION_FRAME_STATS: case OVERRIDE_HDR_TYPES: case GET_HDR_CAPABILITIES: case SET_DESIRED_DISPLAY_MODE_SPECS: case GET_DESIRED_DISPLAY_MODE_SPECS: case SET_ACTIVE_COLOR_MODE: - case GET_BOOT_DISPLAY_MODE_SUPPORT: case SET_BOOT_DISPLAY_MODE: - case CLEAR_BOOT_DISPLAY_MODE: case GET_AUTO_LOW_LATENCY_MODE_SUPPORT: - case SET_AUTO_LOW_LATENCY_MODE: case GET_GAME_CONTENT_TYPE_SUPPORT: - case SET_GAME_CONTENT_TYPE: - case SET_POWER_MODE: case GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES: case SET_DISPLAY_CONTENT_SAMPLING_ENABLED: case GET_DISPLAYED_CONTENT_SAMPLE: case ADD_TUNNEL_MODE_ENABLED_LISTENER: case REMOVE_TUNNEL_MODE_ENABLED_LISTENER: - case NOTIFY_POWER_BOOST: case SET_GLOBAL_SHADOW_SETTINGS: - case GET_PRIMARY_PHYSICAL_DISPLAY_ID: case ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN: { // OVERRIDE_HDR_TYPES is used by CTS tests, which acquire the necessary // permission dynamically. Don't use the permission cache for this check. @@ -5475,15 +5466,11 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case AUTHENTICATE_SURFACE: case GET_ACTIVE_COLOR_MODE: case GET_ACTIVE_DISPLAY_MODE: - case GET_PHYSICAL_DISPLAY_IDS: - case GET_PHYSICAL_DISPLAY_TOKEN: case GET_DISPLAY_COLOR_MODES: case GET_DISPLAY_NATIVE_PRIMARIES: case GET_STATIC_DISPLAY_INFO: case GET_DYNAMIC_DISPLAY_INFO: case GET_DISPLAY_MODES: - case GET_DISPLAY_STATE: - case GET_DISPLAY_STATS: case GET_SUPPORTED_FRAME_TIMESTAMPS: // Calling setTransactionState is safe, because you need to have been // granted a reference to Client* and Handle* to do anything with it. @@ -5492,11 +5479,9 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case GET_COLOR_MANAGEMENT: case GET_COMPOSITION_PREFERENCE: case GET_PROTECTED_CONTENT_SUPPORT: - case IS_WIDE_COLOR_DISPLAY: // setFrameRate() is deliberately available for apps to call without any // special permissions. case SET_FRAME_RATE: - case GET_DISPLAY_BRIGHTNESS_SUPPORT: case GET_DISPLAY_DECORATION_SUPPORT: case SET_FRAME_TIMELINE_INFO: case GET_GPU_CONTEXT_PRIORITY: @@ -5504,19 +5489,6 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { // This is not sensitive information, so should not require permission control. return OK; } - case SET_DISPLAY_BRIGHTNESS: - case ADD_HDR_LAYER_INFO_LISTENER: - case REMOVE_HDR_LAYER_INFO_LISTENER: { - IPCThreadState* ipc = IPCThreadState::self(); - const int pid = ipc->getCallingPid(); - const int uid = ipc->getCallingUid(); - if ((uid != AID_GRAPHICS) && - !PermissionCache::checkPermission(sControlDisplayBrightness, pid, uid)) { - ALOGE("Permission Denial: can't control brightness pid=%d, uid=%d", pid, uid); - return PERMISSION_DENIED; - } - return OK; - } case ADD_FPS_LISTENER: case REMOVE_FPS_LISTENER: case ADD_REGION_SAMPLING_LISTENER: @@ -5562,10 +5534,28 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { } return PERMISSION_DENIED; } + case CREATE_DISPLAY: + case DESTROY_DISPLAY: + case GET_PRIMARY_PHYSICAL_DISPLAY_ID: + case GET_PHYSICAL_DISPLAY_IDS: + case GET_PHYSICAL_DISPLAY_TOKEN: + case SET_POWER_MODE: + case GET_DISPLAY_STATE: + case GET_DISPLAY_STATS: + case CLEAR_BOOT_DISPLAY_MODE: + case GET_BOOT_DISPLAY_MODE_SUPPORT: + case SET_AUTO_LOW_LATENCY_MODE: + case SET_GAME_CONTENT_TYPE: case CAPTURE_LAYERS: case CAPTURE_DISPLAY: case CAPTURE_DISPLAY_BY_ID: - LOG_FATAL("Deprecated opcode: %d", code); + case IS_WIDE_COLOR_DISPLAY: + case GET_DISPLAY_BRIGHTNESS_SUPPORT: + case SET_DISPLAY_BRIGHTNESS: + case ADD_HDR_LAYER_INFO_LISTENER: + case REMOVE_HDR_LAYER_INFO_LISTENER: + case NOTIFY_POWER_BOOST: + LOG_FATAL("Deprecated opcode: %d, migrated to AIDL", code); return PERMISSION_DENIED; } @@ -7217,6 +7207,126 @@ bool SurfaceFlinger::commitCreatedLayers() { } // gui::ISurfaceComposer + +binder::Status SurfaceComposerAIDL::createDisplay(const std::string& displayName, bool secure, + sp<IBinder>* outDisplay) { + status_t status = checkAccessPermission(); + if (status != OK) { + return binder::Status::fromStatusT(status); + } + String8 displayName8 = String8::format("%s", displayName.c_str()); + *outDisplay = mFlinger->createDisplay(displayName8, secure); + return binder::Status::ok(); +} + +binder::Status SurfaceComposerAIDL::destroyDisplay(const sp<IBinder>& display) { + status_t status = checkAccessPermission(); + if (status != OK) { + return binder::Status::fromStatusT(status); + } + mFlinger->destroyDisplay(display); + return binder::Status::ok(); +} + +binder::Status SurfaceComposerAIDL::getPhysicalDisplayIds(std::vector<int64_t>* outDisplayIds) { + std::vector<PhysicalDisplayId> physicalDisplayIds = mFlinger->getPhysicalDisplayIds(); + std::vector<int64_t> displayIds; + displayIds.reserve(physicalDisplayIds.size()); + for (auto item : physicalDisplayIds) { + displayIds.push_back(static_cast<int64_t>(item.value)); + } + *outDisplayIds = displayIds; + return binder::Status::ok(); +} + +binder::Status SurfaceComposerAIDL::getPrimaryPhysicalDisplayId(int64_t* outDisplayId) { + status_t status = checkAccessPermission(); + if (status != OK) { + return binder::Status::fromStatusT(status); + } + + PhysicalDisplayId id; + status = mFlinger->getPrimaryPhysicalDisplayId(&id); + if (status == NO_ERROR) { + *outDisplayId = id.value; + } + return binder::Status::fromStatusT(status); +} + +binder::Status SurfaceComposerAIDL::getPhysicalDisplayToken(int64_t displayId, + sp<IBinder>* outDisplay) { + const auto id = DisplayId::fromValue<PhysicalDisplayId>(static_cast<uint64_t>(displayId)); + *outDisplay = mFlinger->getPhysicalDisplayToken(*id); + return binder::Status::ok(); +} + +binder::Status SurfaceComposerAIDL::setPowerMode(const sp<IBinder>& display, int mode) { + status_t status = checkAccessPermission(); + if (status != OK) { + return binder::Status::fromStatusT(status); + } + mFlinger->setPowerMode(display, mode); + return binder::Status::ok(); +} + +binder::Status SurfaceComposerAIDL::getDisplayStats(const sp<IBinder>& display, + gui::DisplayStatInfo* outStatInfo) { + DisplayStatInfo statInfo; + status_t status = mFlinger->getDisplayStats(display, &statInfo); + if (status == NO_ERROR) { + outStatInfo->vsyncTime = static_cast<long>(statInfo.vsyncTime); + outStatInfo->vsyncPeriod = static_cast<long>(statInfo.vsyncPeriod); + } + return binder::Status::fromStatusT(status); +} + +binder::Status SurfaceComposerAIDL::getDisplayState(const sp<IBinder>& display, + gui::DisplayState* outState) { + ui::DisplayState state; + status_t status = mFlinger->getDisplayState(display, &state); + if (status == NO_ERROR) { + outState->layerStack = state.layerStack.id; + outState->orientation = static_cast<gui::Rotation>(state.orientation); + outState->layerStackSpaceRect.width = state.layerStackSpaceRect.width; + outState->layerStackSpaceRect.height = state.layerStackSpaceRect.height; + } + return binder::Status::fromStatusT(status); +} + +binder::Status SurfaceComposerAIDL::clearBootDisplayMode(const sp<IBinder>& display) { + status_t status = checkAccessPermission(); + if (status == OK) { + status = mFlinger->clearBootDisplayMode(display); + } + return binder::Status::fromStatusT(status); +} + +binder::Status SurfaceComposerAIDL::getBootDisplayModeSupport(bool* outMode) { + status_t status = checkAccessPermission(); + if (status == OK) { + status = mFlinger->getBootDisplayModeSupport(outMode); + } + return binder::Status::fromStatusT(status); +} + +binder::Status SurfaceComposerAIDL::setAutoLowLatencyMode(const sp<IBinder>& display, bool on) { + status_t status = checkAccessPermission(); + if (status != OK) { + return binder::Status::fromStatusT(status); + } + mFlinger->setAutoLowLatencyMode(display, on); + return binder::Status::ok(); +} + +binder::Status SurfaceComposerAIDL::setGameContentType(const sp<IBinder>& display, bool on) { + status_t status = checkAccessPermission(); + if (status != OK) { + return binder::Status::fromStatusT(status); + } + mFlinger->setGameContentType(display, on); + return binder::Status::ok(); +} + binder::Status SurfaceComposerAIDL::captureDisplay( const DisplayCaptureArgs& args, const sp<IScreenCaptureListener>& captureListener) { status_t status = mFlinger->captureDisplay(args, captureListener); @@ -7243,6 +7353,75 @@ binder::Status SurfaceComposerAIDL::captureLayers( return binder::Status::fromStatusT(status); } +binder::Status SurfaceComposerAIDL::isWideColorDisplay(const sp<IBinder>& token, + bool* outIsWideColorDisplay) { + status_t status = mFlinger->isWideColorDisplay(token, outIsWideColorDisplay); + return binder::Status::fromStatusT(status); +} + +binder::Status SurfaceComposerAIDL::getDisplayBrightnessSupport(const sp<IBinder>& displayToken, + bool* outSupport) { + status_t status = mFlinger->getDisplayBrightnessSupport(displayToken, outSupport); + return binder::Status::fromStatusT(status); +} + +binder::Status SurfaceComposerAIDL::setDisplayBrightness(const sp<IBinder>& displayToken, + const gui::DisplayBrightness& brightness) { + status_t status = checkControlDisplayBrightnessPermission(); + if (status == OK) { + status = mFlinger->setDisplayBrightness(displayToken, brightness); + } + return binder::Status::fromStatusT(status); +} + +binder::Status SurfaceComposerAIDL::addHdrLayerInfoListener( + const sp<IBinder>& displayToken, const sp<gui::IHdrLayerInfoListener>& listener) { + status_t status = checkControlDisplayBrightnessPermission(); + if (status == OK) { + status = mFlinger->addHdrLayerInfoListener(displayToken, listener); + } + return binder::Status::fromStatusT(status); +} + +binder::Status SurfaceComposerAIDL::removeHdrLayerInfoListener( + const sp<IBinder>& displayToken, const sp<gui::IHdrLayerInfoListener>& listener) { + status_t status = checkControlDisplayBrightnessPermission(); + if (status == OK) { + status = mFlinger->removeHdrLayerInfoListener(displayToken, listener); + } + return binder::Status::fromStatusT(status); +} + +binder::Status SurfaceComposerAIDL::notifyPowerBoost(int boostId) { + status_t status = checkAccessPermission(); + if (status == OK) { + status = mFlinger->notifyPowerBoost(boostId); + } + return binder::Status::fromStatusT(status); +} + +status_t SurfaceComposerAIDL::checkAccessPermission(bool usePermissionCache) { + if (!mFlinger->callingThreadHasUnscopedSurfaceFlingerAccess(usePermissionCache)) { + IPCThreadState* ipc = IPCThreadState::self(); + ALOGE("Permission Denial: can't access SurfaceFlinger pid=%d, uid=%d", ipc->getCallingPid(), + ipc->getCallingUid()); + return PERMISSION_DENIED; + } + return OK; +} + +status_t SurfaceComposerAIDL::checkControlDisplayBrightnessPermission() { + IPCThreadState* ipc = IPCThreadState::self(); + const int pid = ipc->getCallingPid(); + const int uid = ipc->getCallingUid(); + if ((uid != AID_GRAPHICS) && + !PermissionCache::checkPermission(sControlDisplayBrightness, pid, uid)) { + ALOGE("Permission Denial: can't control brightness pid=%d, uid=%d", pid, uid); + return PERMISSION_DENIED; + } + return OK; +} + } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 58298387c1..047a71a935 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -7,7 +7,6 @@ * * 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 @@ -24,6 +23,8 @@ #include <android-base/thread_annotations.h> #include <android/gui/BnSurfaceComposer.h> +#include <android/gui/DisplayStatInfo.h> +#include <android/gui/DisplayState.h> #include <cutils/atomic.h> #include <cutils/compiler.h> #include <gui/BufferQueue.h> @@ -522,17 +523,30 @@ private: bool callingThreadHasUnscopedSurfaceFlingerAccess(bool usePermissionCache = true) EXCLUDES(mStateLock); + // the following two methods are moved from ISurfaceComposer.h + // TODO(b/74619554): Remove this stopgap once the framework is display-agnostic. + std::optional<PhysicalDisplayId> getInternalDisplayId() const { + const auto displayIds = getPhysicalDisplayIds(); + return displayIds.empty() ? std::nullopt : std::make_optional(displayIds.front()); + } + + // TODO(b/74619554): Remove this stopgap once the framework is display-agnostic. + sp<IBinder> getInternalDisplayToken() const { + const auto displayId = getInternalDisplayId(); + return displayId ? getPhysicalDisplayToken(*displayId) : nullptr; + } + // Implements ISurfaceComposer 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 EXCLUDES(mStateLock) { + sp<IBinder> createDisplay(const String8& displayName, bool secure); + void destroyDisplay(const sp<IBinder>& displayToken); + std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const EXCLUDES(mStateLock) { Mutex::Autolock lock(mStateLock); return getPhysicalDisplayIdsLocked(); } - status_t getPrimaryPhysicalDisplayId(PhysicalDisplayId*) const override EXCLUDES(mStateLock); + status_t getPrimaryPhysicalDisplayId(PhysicalDisplayId*) const EXCLUDES(mStateLock); - sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId displayId) const override; + sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId displayId) const; status_t setTransactionState(const FrameTimelineInfo& frameTimelineInfo, const Vector<ComposerState>& state, const Vector<DisplayState>& displays, uint32_t flags, @@ -554,9 +568,9 @@ private: status_t captureDisplay(DisplayId, const sp<IScreenCaptureListener>&); status_t captureLayers(const LayerCaptureArgs&, const sp<IScreenCaptureListener>&); - status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats) override; + status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats); status_t getDisplayState(const sp<IBinder>& displayToken, ui::DisplayState*) - EXCLUDES(mStateLock) override; + EXCLUDES(mStateLock); status_t getStaticDisplayInfo(const sp<IBinder>& displayToken, ui::StaticDisplayInfo*) EXCLUDES(mStateLock) override; status_t getDynamicDisplayInfo(const sp<IBinder>& displayToken, ui::DynamicDisplayInfo*) @@ -564,12 +578,12 @@ private: status_t getDisplayNativePrimaries(const sp<IBinder>& displayToken, ui::DisplayPrimaries&) override; status_t setActiveColorMode(const sp<IBinder>& displayToken, ui::ColorMode colorMode) override; - status_t getBootDisplayModeSupport(bool* outSupport) const override; + status_t getBootDisplayModeSupport(bool* outSupport) const; status_t setBootDisplayMode(const sp<IBinder>& displayToken, ui::DisplayModeId id) override; - status_t clearBootDisplayMode(const sp<IBinder>& displayToken) override; - void setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool on) override; - void setGameContentType(const sp<IBinder>& displayToken, bool on) override; - void setPowerMode(const sp<IBinder>& displayToken, int mode) override; + status_t clearBootDisplayMode(const sp<IBinder>& displayToken); + void setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool on); + void setGameContentType(const sp<IBinder>& displayToken, bool on); + void setPowerMode(const sp<IBinder>& displayToken, int mode); status_t clearAnimationFrameStats() override; status_t getAnimationFrameStats(FrameStats* outStats) const override; status_t overrideHdrTypes(const sp<IBinder>& displayToken, @@ -592,8 +606,7 @@ private: uint64_t timestamp, DisplayedFrameStats* outStats) const override; status_t getProtectedContentSupport(bool* outSupported) const override; - status_t isWideColorDisplay(const sp<IBinder>& displayToken, - bool* outIsWideColorDisplay) const override; + status_t isWideColorDisplay(const sp<IBinder>& displayToken, bool* outIsWideColorDisplay) const; status_t addRegionSamplingListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle, const sp<IRegionSamplingListener>& listener) override; status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) override; @@ -615,15 +628,14 @@ private: float* outPrimaryRefreshRateMax, float* outAppRequestRefreshRateMin, float* outAppRequestRefreshRateMax) override; - status_t getDisplayBrightnessSupport(const sp<IBinder>& displayToken, - bool* outSupport) const override; + status_t getDisplayBrightnessSupport(const sp<IBinder>& displayToken, bool* outSupport) const; status_t setDisplayBrightness(const sp<IBinder>& displayToken, - const gui::DisplayBrightness& brightness) override; + const gui::DisplayBrightness& brightness); status_t addHdrLayerInfoListener(const sp<IBinder>& displayToken, - const sp<gui::IHdrLayerInfoListener>& listener) override; + const sp<gui::IHdrLayerInfoListener>& listener); status_t removeHdrLayerInfoListener(const sp<IBinder>& displayToken, - const sp<gui::IHdrLayerInfoListener>& listener) override; - status_t notifyPowerBoost(int32_t boostId) override; + const sp<gui::IHdrLayerInfoListener>& listener); + status_t notifyPowerBoost(int32_t boostId); status_t setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor, float lightPosY, float lightPosZ, float lightRadius) override; status_t getDisplayDecorationSupport( @@ -1426,13 +1438,45 @@ private: class SurfaceComposerAIDL : public gui::BnSurfaceComposer { public: - SurfaceComposerAIDL(sp<SurfaceFlinger> sf) { mFlinger = sf; } - + SurfaceComposerAIDL(sp<SurfaceFlinger> sf) : mFlinger(std::move(sf)) {} + + binder::Status createDisplay(const std::string& displayName, bool secure, + sp<IBinder>* outDisplay) override; + binder::Status destroyDisplay(const sp<IBinder>& display) override; + binder::Status getPhysicalDisplayIds(std::vector<int64_t>* outDisplayIds) override; + binder::Status getPrimaryPhysicalDisplayId(int64_t* outDisplayId) override; + binder::Status getPhysicalDisplayToken(int64_t displayId, sp<IBinder>* outDisplay) override; + binder::Status setPowerMode(const sp<IBinder>& display, int mode) override; + binder::Status getDisplayStats(const sp<IBinder>& display, + gui::DisplayStatInfo* outStatInfo) override; + binder::Status getDisplayState(const sp<IBinder>& display, + gui::DisplayState* outState) override; + binder::Status clearBootDisplayMode(const sp<IBinder>& display) override; + binder::Status getBootDisplayModeSupport(bool* outMode) override; + binder::Status setAutoLowLatencyMode(const sp<IBinder>& display, bool on) override; + binder::Status setGameContentType(const sp<IBinder>& display, bool on) override; binder::Status captureDisplay(const DisplayCaptureArgs&, const sp<IScreenCaptureListener>&) override; binder::Status captureDisplayById(int64_t, const sp<IScreenCaptureListener>&) override; binder::Status captureLayers(const LayerCaptureArgs&, const sp<IScreenCaptureListener>&) override; + binder::Status isWideColorDisplay(const sp<IBinder>& token, + bool* outIsWideColorDisplay) override; + binder::Status getDisplayBrightnessSupport(const sp<IBinder>& displayToken, + bool* outSupport) override; + binder::Status setDisplayBrightness(const sp<IBinder>& displayToken, + const gui::DisplayBrightness& brightness) override; + binder::Status addHdrLayerInfoListener(const sp<IBinder>& displayToken, + const sp<gui::IHdrLayerInfoListener>& listener) override; + binder::Status removeHdrLayerInfoListener( + const sp<IBinder>& displayToken, + const sp<gui::IHdrLayerInfoListener>& listener) override; + binder::Status notifyPowerBoost(int boostId) override; + +private: + static const constexpr bool kUsePermissionCache = true; + status_t checkAccessPermission(bool usePermissionCache = kUsePermissionCache); + status_t checkControlDisplayBrightnessPermission(); private: sp<SurfaceFlinger> mFlinger; diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp index 1e5c3e70c8..4cd5ace45f 100644 --- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp +++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp @@ -15,6 +15,7 @@ */ #include <gui/SurfaceComposerClient.h> +#include <ui/Fence.h> #include <ui/Rect.h> #include "LayerProtoHelper.h" @@ -431,6 +432,7 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, layer_sta layer.bufferData->frameNumber = bufferProto.frame_number(); layer.bufferData->flags = Flags<BufferData::BufferDataChange>(bufferProto.flags()); layer.bufferData->cachedBuffer.id = bufferProto.cached_buffer_id(); + layer.bufferData->acquireFence = Fence::NO_FENCE; } if (proto.what() & layer_state_t::eApiChanged) { diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp index cf44effe50..eebb7cd2e5 100644 --- a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp +++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp @@ -181,6 +181,7 @@ public: bool LayerTraceGenerator::generate(const proto::TransactionTraceFile& traceFile, const char* outputLayersTracePath) { if (traceFile.entry_size() == 0) { + ALOGD("Trace file is empty"); return false; } diff --git a/services/surfaceflinger/fuzzer/Android.bp b/services/surfaceflinger/fuzzer/Android.bp index b0b6bf14ab..7350e09cb5 100644 --- a/services/surfaceflinger/fuzzer/Android.bp +++ b/services/surfaceflinger/fuzzer/Android.bp @@ -127,3 +127,13 @@ cc_fuzz { "surfaceflinger_layer_fuzzer.cpp", ], } + +cc_fuzz { + name: "surfaceflinger_frametracer_fuzzer", + defaults: [ + "surfaceflinger_fuzz_defaults", + ], + srcs: [ + "surfaceflinger_frametracer_fuzzer.cpp", + ], +} diff --git a/services/surfaceflinger/fuzzer/README.md b/services/surfaceflinger/fuzzer/README.md index 78a7596ef3..7a5f229ae9 100644 --- a/services/surfaceflinger/fuzzer/README.md +++ b/services/surfaceflinger/fuzzer/README.md @@ -4,6 +4,7 @@ + [DisplayHardware](#DisplayHardware) + [Scheduler](#Scheduler) + [Layer](#Layer) ++ [FrameTracer](#FrameTracer) # <a name="SurfaceFlinger"></a> Fuzzer for SurfaceFlinger @@ -93,3 +94,16 @@ You can find the possible values in the fuzzer's source code. $ adb sync data $ adb shell /data/fuzz/arm64/surfaceflinger_layer_fuzzer/surfaceflinger_layer_fuzzer ``` + +# <a name="FrameTracer"></a> Fuzzer for FrameTracer + +#### Steps to run +1. Build the fuzzer +``` + $ mm -j$(nproc) surfaceflinger_frametracer_fuzzer +``` +2. To run on device +``` + $ adb sync data + $ adb shell /data/fuzz/arm64/surfaceflinger_frametracer_fuzzer/surfaceflinger_frametracer_fuzzer +``` diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_frametracer_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_frametracer_fuzzer.cpp new file mode 100644 index 0000000000..a22a778989 --- /dev/null +++ b/services/surfaceflinger/fuzzer/surfaceflinger_frametracer_fuzzer.cpp @@ -0,0 +1,132 @@ +/* + * 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 <FrameTracer/FrameTracer.h> +#include <fuzzer/FuzzedDataProvider.h> +#include <perfetto/trace/trace.pb.h> + +namespace android::fuzz { + +using namespace google::protobuf; + +constexpr size_t kMaxStringSize = 100; +constexpr size_t kMinLayerIds = 1; +constexpr size_t kMaxLayerIds = 10; +constexpr int32_t kConfigDuration = 500; +constexpr int32_t kBufferSize = 1024; +constexpr int32_t kTimeOffset = 100000; + +class FrameTracerFuzzer { +public: + FrameTracerFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) { + // Fuzzer is single-threaded, so no need to be thread-safe. + static bool wasInitialized = false; + if (!wasInitialized) { + perfetto::TracingInitArgs args; + args.backends = perfetto::kInProcessBackend; + perfetto::Tracing::Initialize(args); + wasInitialized = true; + } + mFrameTracer = std::make_unique<android::FrameTracer>(); + } + ~FrameTracerFuzzer() { mFrameTracer.reset(); } + void process(); + +private: + std::unique_ptr<perfetto::TracingSession> getTracingSessionForTest(); + void traceTimestamp(); + std::vector<int32_t> generateLayerIds(size_t numLayerIds); + void traceTimestamp(std::vector<int32_t> layerIds, size_t numLayerIds); + void traceFence(std::vector<int32_t> layerIds, size_t numLayerIds); + std::unique_ptr<android::FrameTracer> mFrameTracer = nullptr; + FuzzedDataProvider mFdp; + android::FenceToFenceTimeMap mFenceFactory; +}; + +std::unique_ptr<perfetto::TracingSession> FrameTracerFuzzer::getTracingSessionForTest() { + perfetto::TraceConfig cfg; + cfg.set_duration_ms(kConfigDuration); + cfg.add_buffers()->set_size_kb(kBufferSize); + auto* dsCfg = cfg.add_data_sources()->mutable_config(); + dsCfg->set_name(android::FrameTracer::kFrameTracerDataSource); + + auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend); + tracingSession->Setup(cfg); + return tracingSession; +} + +std::vector<int32_t> FrameTracerFuzzer::generateLayerIds(size_t numLayerIds) { + std::vector<int32_t> layerIds; + for (size_t i = 0; i < numLayerIds; ++i) { + layerIds.push_back(mFdp.ConsumeIntegral<int32_t>()); + } + return layerIds; +} + +void FrameTracerFuzzer::traceTimestamp(std::vector<int32_t> layerIds, size_t numLayerIds) { + int32_t layerId = layerIds.at(mFdp.ConsumeIntegralInRange<size_t>(0, numLayerIds - 1)); + mFrameTracer->traceTimestamp(layerId, mFdp.ConsumeIntegral<uint64_t>() /*bufferID*/, + mFdp.ConsumeIntegral<uint64_t>() /*frameNumber*/, + mFdp.ConsumeIntegral<nsecs_t>() /*timestamp*/, + android::FrameTracer::FrameEvent::UNSPECIFIED, + mFdp.ConsumeIntegral<nsecs_t>() /*duration*/); +} + +void FrameTracerFuzzer::traceFence(std::vector<int32_t> layerIds, size_t numLayerIds) { + const nsecs_t signalTime = systemTime(); + const nsecs_t startTime = signalTime + kTimeOffset; + auto fence = mFenceFactory.createFenceTimeForTest(android::Fence::NO_FENCE); + mFenceFactory.signalAllForTest(android::Fence::NO_FENCE, signalTime); + int32_t layerId = layerIds.at(mFdp.ConsumeIntegralInRange<size_t>(0, numLayerIds - 1)); + mFrameTracer->traceFence(layerId, mFdp.ConsumeIntegral<uint64_t>() /*bufferID*/, + mFdp.ConsumeIntegral<uint64_t>() /*frameNumber*/, fence, + android::FrameTracer::FrameEvent::ACQUIRE_FENCE, startTime); +} + +void FrameTracerFuzzer::process() { + mFrameTracer->registerDataSource(); + + auto tracingSession = getTracingSessionForTest(); + tracingSession->StartBlocking(); + + size_t numLayerIds = mFdp.ConsumeIntegralInRange<size_t>(kMinLayerIds, kMaxLayerIds); + std::vector<int32_t> layerIds = generateLayerIds(numLayerIds); + + for (auto it = layerIds.begin(); it != layerIds.end(); ++it) { + mFrameTracer->traceNewLayer(*it /*layerId*/, + mFdp.ConsumeRandomLengthString(kMaxStringSize) /*layerName*/); + } + + traceTimestamp(layerIds, numLayerIds); + traceFence(layerIds, numLayerIds); + + mFenceFactory.signalAllForTest(android::Fence::NO_FENCE, systemTime()); + + tracingSession->StopBlocking(); + + for (auto it = layerIds.begin(); it != layerIds.end(); ++it) { + mFrameTracer->onDestroy(*it); + } +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + FrameTracerFuzzer frameTracerFuzzer(data, size); + frameTracerFuzzer.process(); + return 0; +} + +} // namespace android::fuzz diff --git a/services/surfaceflinger/tests/BootDisplayMode_test.cpp b/services/surfaceflinger/tests/BootDisplayMode_test.cpp index abdb16debf..d70908e390 100644 --- a/services/surfaceflinger/tests/BootDisplayMode_test.cpp +++ b/services/surfaceflinger/tests/BootDisplayMode_test.cpp @@ -20,28 +20,33 @@ #include <gui/SurfaceComposerClient.h> #include <private/gui/ComposerService.h> +#include <private/gui/ComposerServiceAIDL.h> #include <chrono> namespace android { TEST(BootDisplayModeTest, setBootDisplayMode) { sp<ISurfaceComposer> sf(ComposerService::getComposerService()); + sp<gui::ISurfaceComposer> sf_aidl(ComposerServiceAIDL::getComposerService()); auto displayToken = SurfaceComposerClient::getInternalDisplayToken(); bool bootModeSupport = false; - ASSERT_NO_FATAL_FAILURE(sf->getBootDisplayModeSupport(&bootModeSupport)); + binder::Status status = sf_aidl->getBootDisplayModeSupport(&bootModeSupport); + ASSERT_NO_FATAL_FAILURE(status.transactionError()); if (bootModeSupport) { ASSERT_EQ(NO_ERROR, sf->setBootDisplayMode(displayToken, 0)); } } TEST(BootDisplayModeTest, clearBootDisplayMode) { - sp<ISurfaceComposer> sf(ComposerService::getComposerService()); + sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService()); auto displayToken = SurfaceComposerClient::getInternalDisplayToken(); bool bootModeSupport = false; - ASSERT_NO_FATAL_FAILURE(sf->getBootDisplayModeSupport(&bootModeSupport)); + binder::Status status = sf->getBootDisplayModeSupport(&bootModeSupport); + ASSERT_NO_FATAL_FAILURE(status.transactionError()); if (bootModeSupport) { - ASSERT_EQ(NO_ERROR, sf->clearBootDisplayMode(displayToken)); + status = sf->clearBootDisplayMode(displayToken); + ASSERT_EQ(NO_ERROR, status.transactionError()); } } -} // namespace android
\ No newline at end of file +} // namespace android |