Merge "Delete unused API for legacy fs-verity"
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 269b086..1821729 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -368,7 +368,7 @@
int32_t s = android_atomic_add(1, &mThreadPoolSeq);
pid_t pid = getpid();
String8 name;
- name.appendFormat("Binder:%d_%X", pid, s);
+ name.appendFormat("%d_%X:%s", pid, s, mDriverName.c_str());
return name;
}
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index e17b2c8..d634c58 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -37,6 +37,12 @@
"android.hardware.graphics.bufferqueue@2.0",
],
min_sdk_version: "29",
+ // TODO(b/218719284) can media use be constrained to libgui_bufferqueue_static?
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media.swcodec",
+ "test_com.android.media.swcodec",
+ ],
}
cc_library_headers {
@@ -339,6 +345,7 @@
"android.hardware.graphics.bufferqueue@2.0",
"android.hardware.graphics.common@1.1",
"android.hardware.graphics.common@1.2",
+ "android.hardware.graphics.common-V3-ndk",
"android.hidl.token@1.0-utils",
"libbase",
"libcutils",
diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp
index 36e7d80..bb659bf 100644
--- a/libs/gui/DisplayEventReceiver.cpp
+++ b/libs/gui/DisplayEventReceiver.cpp
@@ -40,7 +40,13 @@
mEventConnection = sf->createDisplayEventConnection(vsyncSource, eventRegistration);
if (mEventConnection != nullptr) {
mDataChannel = std::make_unique<gui::BitTube>();
- mEventConnection->stealReceiveChannel(mDataChannel.get());
+ const auto status = mEventConnection->stealReceiveChannel(mDataChannel.get());
+ if (!status.isOk()) {
+ ALOGE("stealReceiveChannel failed: %s", status.toString8().c_str());
+ mInitError = std::make_optional<status_t>(status.transactionError());
+ mDataChannel.reset();
+ mEventConnection.clear();
+ }
}
}
}
@@ -51,12 +57,11 @@
status_t DisplayEventReceiver::initCheck() const {
if (mDataChannel != nullptr)
return NO_ERROR;
- return NO_INIT;
+ return mInitError.has_value() ? mInitError.value() : NO_INIT;
}
int DisplayEventReceiver::getFd() const {
- if (mDataChannel == nullptr)
- return NO_INIT;
+ if (mDataChannel == nullptr) return mInitError.has_value() ? mInitError.value() : NO_INIT;
return mDataChannel->getFd();
}
@@ -69,7 +74,7 @@
mEventConnection->setVsyncRate(count);
return NO_ERROR;
}
- return NO_INIT;
+ return mInitError.has_value() ? mInitError.value() : NO_INIT;
}
status_t DisplayEventReceiver::requestNextVsync() {
@@ -77,7 +82,7 @@
mEventConnection->requestNextVsync();
return NO_ERROR;
}
- return NO_INIT;
+ return mInitError.has_value() ? mInitError.value() : NO_INIT;
}
status_t DisplayEventReceiver::getLatestVsyncEventData(VsyncEventData* outVsyncEventData) const {
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index fb9ed22..75c5e26 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -42,6 +42,8 @@
// ---------------------------------------------------------------------------
+using namespace aidl::android::hardware::graphics;
+
namespace android {
using gui::IDisplayEventConnection;
@@ -1201,8 +1203,9 @@
return NO_ERROR;
}
- status_t getDisplayDecorationSupport(const sp<IBinder>& displayToken,
- bool* outSupport) const override {
+ status_t getDisplayDecorationSupport(
+ const sp<IBinder>& displayToken,
+ std::optional<common::DisplayDecorationSupport>* outSupport) const override {
Parcel data, reply;
status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (error != NO_ERROR) {
@@ -1225,7 +1228,26 @@
ALOGE("getDisplayDecorationSupport: failed to read support: %d", error);
return error;
}
- *outSupport = support;
+
+ if (support) {
+ int32_t format, alphaInterpretation;
+ error = reply.readInt32(&format);
+ if (error != NO_ERROR) {
+ ALOGE("getDisplayDecorationSupport: failed to read format: %d", error);
+ return error;
+ }
+ error = reply.readInt32(&alphaInterpretation);
+ if (error != NO_ERROR) {
+ ALOGE("getDisplayDecorationSupport: failed to read alphaInterpretation: %d", error);
+ return error;
+ }
+ outSupport->emplace();
+ outSupport->value().format = static_cast<common::PixelFormat>(format);
+ outSupport->value().alphaInterpretation =
+ static_cast<common::AlphaInterpretation>(alphaInterpretation);
+ } else {
+ outSupport->reset();
+ }
return NO_ERROR;
}
@@ -2164,14 +2186,18 @@
case GET_DISPLAY_DECORATION_SUPPORT: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IBinder> displayToken;
- status_t error = data.readNullableStrongBinder(&displayToken);
+ SAFE_PARCEL(data.readNullableStrongBinder, &displayToken);
+ std::optional<common::DisplayDecorationSupport> support;
+ auto error = getDisplayDecorationSupport(displayToken, &support);
if (error != NO_ERROR) {
- ALOGE("getDisplayDecorationSupport: failed to read display token: %d", error);
+ ALOGE("getDisplayDecorationSupport failed with error %d", error);
return error;
}
- bool support = false;
- error = getDisplayDecorationSupport(displayToken, &support);
- reply->writeBool(support);
+ reply->writeBool(support.has_value());
+ if (support) {
+ reply->writeInt32(static_cast<int32_t>(support.value().format));
+ reply->writeInt32(static_cast<int32_t>(support.value().alphaInterpretation));
+ }
return error;
}
case SET_FRAME_RATE: {
diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp
index aa7ebc9..f7392d4 100644
--- a/libs/gui/ITransactionCompletedListener.cpp
+++ b/libs/gui/ITransactionCompletedListener.cpp
@@ -111,7 +111,14 @@
status_t SurfaceStats::writeToParcel(Parcel* output) const {
SAFE_PARCEL(output->writeStrongBinder, surfaceControl);
- SAFE_PARCEL(output->writeInt64, acquireTime);
+ if (const auto* acquireFence = std::get_if<sp<Fence>>(&acquireTimeOrFence)) {
+ SAFE_PARCEL(output->writeBool, true);
+ SAFE_PARCEL(output->write, **acquireFence);
+ } else {
+ SAFE_PARCEL(output->writeBool, false);
+ SAFE_PARCEL(output->writeInt64, std::get<nsecs_t>(acquireTimeOrFence));
+ }
+
if (previousReleaseFence) {
SAFE_PARCEL(output->writeBool, true);
SAFE_PARCEL(output->write, *previousReleaseFence);
@@ -131,10 +138,20 @@
status_t SurfaceStats::readFromParcel(const Parcel* input) {
SAFE_PARCEL(input->readStrongBinder, &surfaceControl);
- SAFE_PARCEL(input->readInt64, &acquireTime);
+
bool hasFence = false;
SAFE_PARCEL(input->readBool, &hasFence);
if (hasFence) {
+ acquireTimeOrFence = sp<Fence>::make();
+ SAFE_PARCEL(input->read, *std::get<sp<Fence>>(acquireTimeOrFence));
+ } else {
+ nsecs_t acquireTime;
+ SAFE_PARCEL(input->readInt64, &acquireTime);
+ acquireTimeOrFence = acquireTime;
+ }
+
+ SAFE_PARCEL(input->readBool, &hasFence);
+ if (hasFence) {
previousReleaseFence = new Fence();
SAFE_PARCEL(input->read, *previousReleaseFence);
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 91b2fb1..9269c3e 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -52,6 +52,7 @@
namespace android {
+using aidl::android::hardware::graphics::common::DisplayDecorationSupport;
using gui::FocusRequest;
using gui::IRegionSamplingListener;
using gui::WindowInfo;
@@ -296,7 +297,7 @@
surfaceControlStats
.emplace_back(callbacksMap[callbackId]
.surfaceControls[surfaceStats.surfaceControl],
- transactionStats.latchTime, surfaceStats.acquireTime,
+ transactionStats.latchTime, surfaceStats.acquireTimeOrFence,
transactionStats.presentFence,
surfaceStats.previousReleaseFence, surfaceStats.transformHint,
surfaceStats.eventStats);
@@ -321,7 +322,7 @@
surfaceControlStats
.emplace_back(callbacksMap[callbackId]
.surfaceControls[surfaceStats.surfaceControl],
- transactionStats.latchTime, surfaceStats.acquireTime,
+ transactionStats.latchTime, surfaceStats.acquireTimeOrFence,
transactionStats.presentFence,
surfaceStats.previousReleaseFence, surfaceStats.transformHint,
surfaceStats.eventStats);
@@ -2239,8 +2240,9 @@
lightRadius);
}
-bool SurfaceComposerClient::getDisplayDecorationSupport(const sp<IBinder>& displayToken) {
- bool support = false;
+std::optional<DisplayDecorationSupport> SurfaceComposerClient::getDisplayDecorationSupport(
+ const sp<IBinder>& displayToken) {
+ std::optional<DisplayDecorationSupport> support;
ComposerService::getComposerService()->getDisplayDecorationSupport(displayToken, &support);
return support;
}
diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h
index 4e04db3..740d825 100644
--- a/libs/gui/include/gui/DisplayEventReceiver.h
+++ b/libs/gui/include/gui/DisplayEventReceiver.h
@@ -180,6 +180,7 @@
private:
sp<IDisplayEventConnection> mEventConnection;
std::unique_ptr<gui::BitTube> mDataChannel;
+ std::optional<status_t> mInitError;
};
// ----------------------------------------------------------------------------
diff --git a/libs/gui/include/gui/HdrMetadata.h b/libs/gui/include/gui/HdrMetadata.h
index 1e9c3e7..0bdffac 100644
--- a/libs/gui/include/gui/HdrMetadata.h
+++ b/libs/gui/include/gui/HdrMetadata.h
@@ -44,6 +44,7 @@
status_t unflatten(void const* buffer, size_t size);
bool operator==(const HdrMetadata& rhs) const;
+ bool operator!=(const HdrMetadata& rhs) const { return !(*this == rhs); }
};
} // namespace android
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 90b2a0e..0a59f52 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -52,6 +52,8 @@
#include <unordered_set>
#include <vector>
+#include <aidl/android/hardware/graphics/common/DisplayDecorationSupport.h>
+
namespace android {
struct client_cache_t;
@@ -533,15 +535,17 @@
* displayToken
* The token of the display.
* outSupport
- * An output parameter for whether the display supports
+ * An output parameter for whether/how the display supports
* DISPLAY_DECORATION layers.
*
* 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 getDisplayDecorationSupport(const sp<IBinder>& displayToken,
- bool* outSupport) const = 0;
+ virtual status_t getDisplayDecorationSupport(
+ const sp<IBinder>& displayToken,
+ std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
+ outSupport) const = 0;
/*
* Sets the intended frame rate for a surface. See ANativeWindow_setFrameRate() for more info.
diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h
index 0df5822..a791c66 100644
--- a/libs/gui/include/gui/ITransactionCompletedListener.h
+++ b/libs/gui/include/gui/ITransactionCompletedListener.h
@@ -30,6 +30,7 @@
#include <cstdint>
#include <unordered_map>
#include <unordered_set>
+#include <variant>
namespace android {
@@ -130,12 +131,12 @@
status_t readFromParcel(const Parcel* input) override;
SurfaceStats() = default;
- SurfaceStats(const sp<IBinder>& sc, nsecs_t time, const sp<Fence>& prevReleaseFence,
- uint32_t hint, uint32_t currentMaxAcquiredBuffersCount,
- FrameEventHistoryStats frameEventStats, std::vector<JankData> jankData,
- ReleaseCallbackId previousReleaseCallbackId)
+ SurfaceStats(const sp<IBinder>& sc, std::variant<nsecs_t, sp<Fence>> acquireTimeOrFence,
+ const sp<Fence>& prevReleaseFence, uint32_t hint,
+ uint32_t currentMaxAcquiredBuffersCount, FrameEventHistoryStats frameEventStats,
+ std::vector<JankData> jankData, ReleaseCallbackId previousReleaseCallbackId)
: surfaceControl(sc),
- acquireTime(time),
+ acquireTimeOrFence(std::move(acquireTimeOrFence)),
previousReleaseFence(prevReleaseFence),
transformHint(hint),
currentMaxAcquiredBufferCount(currentMaxAcquiredBuffersCount),
@@ -144,7 +145,7 @@
previousReleaseCallbackId(previousReleaseCallbackId) {}
sp<IBinder> surfaceControl;
- nsecs_t acquireTime = -1;
+ std::variant<nsecs_t, sp<Fence>> acquireTimeOrFence = -1;
sp<Fence> previousReleaseFence;
uint32_t transformHint = 0;
uint32_t currentMaxAcquiredBufferCount = 0;
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 61eeab3..25637ef 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -47,6 +47,8 @@
#include <gui/WindowInfosListenerReporter.h>
#include <math/vec3.h>
+#include <aidl/android/hardware/graphics/common/DisplayDecorationSupport.h>
+
namespace android {
class HdrCapabilities;
@@ -58,12 +60,13 @@
using gui::IRegionSamplingListener;
struct SurfaceControlStats {
- SurfaceControlStats(const sp<SurfaceControl>& sc, nsecs_t latchTime, nsecs_t acquireTime,
+ SurfaceControlStats(const sp<SurfaceControl>& sc, nsecs_t latchTime,
+ std::variant<nsecs_t, sp<Fence>> acquireTimeOrFence,
const sp<Fence>& presentFence, const sp<Fence>& prevReleaseFence,
uint32_t hint, FrameEventHistoryStats eventStats)
: surfaceControl(sc),
latchTime(latchTime),
- acquireTime(acquireTime),
+ acquireTimeOrFence(std::move(acquireTimeOrFence)),
presentFence(presentFence),
previousReleaseFence(prevReleaseFence),
transformHint(hint),
@@ -71,7 +74,7 @@
sp<SurfaceControl> surfaceControl;
nsecs_t latchTime = -1;
- nsecs_t acquireTime = -1;
+ std::variant<nsecs_t, sp<Fence>> acquireTimeOrFence = -1;
sp<Fence> presentFence;
sp<Fence> previousReleaseFence;
uint32_t transformHint = 0;
@@ -285,14 +288,16 @@
float lightPosY, float lightPosZ, float lightRadius);
/*
- * Returns whether a display supports DISPLAY_DECORATION layers.
+ * Returns whether and how a display supports DISPLAY_DECORATION layers.
*
* displayToken
* The token of the display.
*
- * Returns whether a display supports DISPLAY_DECORATION layers.
+ * Returns how a display supports DISPLAY_DECORATION layers, or nullopt if
+ * it does not.
*/
- static bool getDisplayDecorationSupport(const sp<IBinder>& displayToken);
+ static std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>
+ getDisplayDecorationSupport(const sp<IBinder>& displayToken);
// ------------------------------------------------------------------------
// surface creation / destruction
diff --git a/libs/gui/include/gui/test/CallbackUtils.h b/libs/gui/include/gui/test/CallbackUtils.h
index 6403208..62d1496 100644
--- a/libs/gui/include/gui/test/CallbackUtils.h
+++ b/libs/gui/include/gui/test/CallbackUtils.h
@@ -134,12 +134,15 @@
void verifySurfaceControlStats(const SurfaceControlStats& surfaceControlStats,
nsecs_t latchTime) const {
- const auto& [surfaceControl, latch, acquireTime, presentFence, previousReleaseFence,
- transformHint, frameEvents] = surfaceControlStats;
+ const auto& [surfaceControl, latch, acquireTimeOrFence, presentFence,
+ previousReleaseFence, transformHint, frameEvents] = surfaceControlStats;
- ASSERT_EQ(acquireTime > 0, mBufferResult == ExpectedResult::Buffer::ACQUIRED)
+ ASSERT_TRUE(std::holds_alternative<nsecs_t>(acquireTimeOrFence));
+ ASSERT_EQ(std::get<nsecs_t>(acquireTimeOrFence) > 0,
+ mBufferResult == ExpectedResult::Buffer::ACQUIRED)
<< "bad acquire time";
- ASSERT_LE(acquireTime, latchTime) << "acquire time should be <= latch time";
+ ASSERT_LE(std::get<nsecs_t>(acquireTimeOrFence), latchTime)
+ << "acquire time should be <= latch time";
if (mPreviousBufferResult == ExpectedResult::PreviousBuffer::RELEASED) {
ASSERT_NE(previousReleaseFence, nullptr)
diff --git a/libs/gui/sysprop/Android.bp b/libs/gui/sysprop/Android.bp
index bddb0ac..cc33e4c 100644
--- a/libs/gui/sysprop/Android.bp
+++ b/libs/gui/sysprop/Android.bp
@@ -16,4 +16,9 @@
cpp: {
min_sdk_version: "29",
},
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media.swcodec",
+ "test_com.android.media.swcodec",
+ ],
}
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 120ed48..6056280 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -47,6 +47,7 @@
// retrieve wide-color and hdr settings from configstore
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
+using aidl::android::hardware::graphics::common::DisplayDecorationSupport;
using gui::IDisplayEventConnection;
using gui::IRegionSamplingListener;
using ui::ColorMode;
@@ -889,8 +890,9 @@
return NO_ERROR;
}
- status_t getDisplayDecorationSupport(const sp<IBinder>& /*displayToken*/,
- bool* /*outSupport*/) const override {
+ status_t getDisplayDecorationSupport(
+ const sp<IBinder>& /*displayToken*/,
+ std::optional<DisplayDecorationSupport>* /*outSupport*/) const override {
return NO_ERROR;
}
diff --git a/libs/nativebase/Android.bp b/libs/nativebase/Android.bp
index 1a4729c..77b23db 100644
--- a/libs/nativebase/Android.bp
+++ b/libs/nativebase/Android.bp
@@ -45,5 +45,9 @@
enabled: true,
},
},
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media.swcodec",
+ ],
min_sdk_version: "29",
}
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index 9286009..d30efa1 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -47,6 +47,11 @@
// TODO(b/153609531): remove when no longer needed.
native_bridge_supported: true,
min_sdk_version: "29",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media.swcodec",
+ "test_com.android.media.swcodec",
+ ],
host_supported: true,
}
@@ -64,7 +69,7 @@
symbol_file: "libnativewindow.map.txt",
unversioned: true,
override_export_include_dirs: [
- "include"
+ "include",
],
},
export_include_dirs: [
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index faa84fc..3e7f69c 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -194,6 +194,8 @@
// Returns the tid of the renderengine thread if it's threaded, and std::nullopt otherwise
virtual std::optional<pid_t> getRenderEngineTid() const { return std::nullopt; }
+ virtual void setEnableTracing(bool /*tracingEnabled*/) {}
+
protected:
RenderEngine() : RenderEngine(RenderEngineType::GLES) {}
diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp
index 29175a2..1fb24f5 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaRenderEngine.cpp
@@ -20,15 +20,15 @@
#include "SkiaRenderEngine.h"
-#include <android-base/properties.h>
#include <src/core/SkTraceEventCommon.h>
namespace android {
namespace renderengine {
namespace skia {
-SkiaRenderEngine::SkiaRenderEngine(RenderEngineType type) : RenderEngine(type) {
- SkAndroidFrameworkTraceUtil::setEnableTracing(
- base::GetBoolProperty(PROPERTY_SKIA_ATRACE_ENABLED, false));
+SkiaRenderEngine::SkiaRenderEngine(RenderEngineType type) : RenderEngine(type) {}
+
+void SkiaRenderEngine::setEnableTracing(bool tracingEnabled) {
+ SkAndroidFrameworkTraceUtil::setEnableTracing(tracingEnabled);
}
} // namespace skia
} // namespace renderengine
diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h
index eb65e83..5d10b6f 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.h
+++ b/libs/renderengine/skia/SkiaRenderEngine.h
@@ -47,6 +47,7 @@
virtual int getContextPriority() override { return 0; }
virtual void assertShadersCompiled(int numShaders) {}
virtual int reportShadersCompiled() { return 0; }
+ virtual void setEnableTracing(bool tracingEnabled) override;
protected:
virtual void mapExternalTextureBuffer(const sp<GraphicBuffer>& /*buffer*/,
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp
index a7176d3..203bb54 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.cpp
+++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp
@@ -403,6 +403,18 @@
return std::make_optional(tidFuture.get());
}
+void RenderEngineThreaded::setEnableTracing(bool tracingEnabled) {
+ // This function is designed so it can run asynchronously, so we do not need to wait
+ // for the futures.
+ {
+ std::lock_guard lock(mThreadMutex);
+ mFunctionCalls.push([tracingEnabled](renderengine::RenderEngine& instance) {
+ ATRACE_NAME("REThreaded::setEnableTracing");
+ instance.setEnableTracing(tracingEnabled);
+ });
+ }
+ mCondition.notify_one();
+}
} // namespace threaded
} // namespace renderengine
} // namespace android
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h
index 1ba72dd..1340902 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.h
+++ b/libs/renderengine/threaded/RenderEngineThreaded.h
@@ -67,6 +67,7 @@
bool supportsBackgroundBlur() override;
void onActiveDisplaySizeChanged(ui::Size size) override;
std::optional<pid_t> getRenderEngineTid() const override;
+ void setEnableTracing(bool tracingEnabled) override;
protected:
void mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, bool isRenderable) override;
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index f5a22ec..a9380c6 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -235,6 +235,12 @@
"libui_headers",
],
min_sdk_version: "29",
+ // TODO(b/214400477) to remove use of GraphicBuffer
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media.swcodec",
+ "test_com.android.media.swcodec",
+ ],
afdo: true,
}
@@ -258,6 +264,11 @@
"libmath_headers",
],
min_sdk_version: "29",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media.swcodec",
+ "test_com.android.media.swcodec",
+ ],
}
// defaults to enable VALIDATE_REGIONS traces
diff --git a/libs/ui/include/ui/StretchEffect.h b/libs/ui/include/ui/StretchEffect.h
index cf08acb..123b275 100644
--- a/libs/ui/include/ui/StretchEffect.h
+++ b/libs/ui/include/ui/StretchEffect.h
@@ -44,6 +44,8 @@
mappedChildBounds == other.mappedChildBounds;
}
+ bool operator!=(const StretchEffect& other) const { return !(*this == other); }
+
static bool isZero(float value) {
constexpr float NON_ZERO_EPSILON = 0.001f;
return fabsf(value) <= NON_ZERO_EPSILON;
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 22a69e5..ed9bfd2 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -22,6 +22,10 @@
default_applicable_licenses: ["frameworks_native_license"],
}
+inputflinger_tidy_checks = [
+ "android-*",
+]
+
cc_defaults {
name: "inputflinger_defaults",
cpp_std: "c++20",
@@ -38,6 +42,11 @@
sanitize: {
misc_undefined: ["bounds"],
},
+ tidy: true,
+ tidy_checks: [
+ "-*", // Disable all checks not explicitly enabled for now
+ ] + inputflinger_tidy_checks,
+ tidy_checks_as_errors: inputflinger_tidy_checks,
}
/////////////////////////////////////////////////
@@ -48,7 +57,7 @@
name: "libinputflinger_sources",
srcs: [
"InputClassifier.cpp",
- "InputClassifierConverter.cpp",
+ "InputCommonConverter.cpp",
"UnwantedInteractionBlocker.cpp",
"InputManager.cpp",
],
@@ -58,9 +67,10 @@
name: "libinputflinger_defaults",
srcs: [":libinputflinger_sources"],
shared_libs: [
- "android.hardware.input.classifier@1.0",
+ "android.hardware.input.processor-V1-ndk",
"libbase",
"libbinder",
+ "libbinder_ndk",
"libchrome",
"libcrypto",
"libcutils",
diff --git a/services/inputflinger/InputClassifier.cpp b/services/inputflinger/InputClassifier.cpp
index 6c4b11e..3ea0986 100644
--- a/services/inputflinger/InputClassifier.cpp
+++ b/services/inputflinger/InputClassifier.cpp
@@ -17,13 +17,15 @@
#define LOG_TAG "InputClassifier"
#include "InputClassifier.h"
-#include "InputClassifierConverter.h"
+#include "InputCommonConverter.h"
-#include <algorithm>
#include <android-base/stringprintf.h>
-#include <cmath>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
#include <inttypes.h>
#include <log/log.h>
+#include <algorithm>
+#include <cmath>
#if defined(__linux__)
#include <pthread.h>
#endif
@@ -36,10 +38,9 @@
#define INDENT5 " "
using android::base::StringPrintf;
-using android::hardware::hidl_bitfield;
-using android::hardware::hidl_vec;
-using android::hardware::Return;
-using namespace android::hardware::input;
+using namespace std::chrono_literals;
+using namespace ::aidl::android::hardware::input;
+using aidl::android::hardware::input::processor::IInputProcessor;
namespace android {
@@ -55,13 +56,13 @@
return it->second;
}
-static MotionClassification getMotionClassification(common::V1_0::Classification classification) {
+static MotionClassification getMotionClassification(common::Classification classification) {
static_assert(MotionClassification::NONE ==
- static_cast<MotionClassification>(common::V1_0::Classification::NONE));
+ static_cast<MotionClassification>(common::Classification::NONE));
static_assert(MotionClassification::AMBIGUOUS_GESTURE ==
- static_cast<MotionClassification>(common::V1_0::Classification::AMBIGUOUS_GESTURE));
+ static_cast<MotionClassification>(common::Classification::AMBIGUOUS_GESTURE));
static_assert(MotionClassification::DEEP_PRESS ==
- static_cast<MotionClassification>(common::V1_0::Classification::DEEP_PRESS));
+ static_cast<MotionClassification>(common::Classification::DEEP_PRESS));
return static_cast<MotionClassification>(classification);
}
@@ -70,6 +71,56 @@
isFromSource(args.source, AINPUT_SOURCE_TOUCHSCREEN);
}
+static void setCurrentThreadName(const char* name) {
+#if defined(__linux__)
+ // Set the thread name for debugging
+ pthread_setname_np(pthread_self(), name);
+#else
+ (void*)(name); // prevent unused variable warning
+#endif
+}
+
+static std::shared_ptr<IInputProcessor> getService() {
+ const std::string aidl_instance_name = std::string(IInputProcessor::descriptor) + "/default";
+
+ if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
+ ALOGI("HAL %s is not declared", aidl_instance_name.c_str());
+ return nullptr;
+ }
+
+ ndk::SpAIBinder binder(AServiceManager_waitForService(aidl_instance_name.c_str()));
+ return IInputProcessor::fromBinder(binder);
+}
+
+// Temporarily releases a held mutex for the lifetime of the instance.
+// Named to match std::scoped_lock
+class scoped_unlock {
+public:
+ explicit scoped_unlock(std::mutex& mutex) : mMutex(mutex) { mMutex.unlock(); }
+ ~scoped_unlock() { mMutex.lock(); }
+
+private:
+ std::mutex& mMutex;
+};
+
+// --- ScopedDeathRecipient ---
+ScopedDeathRecipient::ScopedDeathRecipient(AIBinder_DeathRecipient_onBinderDied onBinderDied,
+ void* cookie)
+ : mCookie(cookie) {
+ mRecipient = AIBinder_DeathRecipient_new(onBinderDied);
+}
+
+void ScopedDeathRecipient::linkToDeath(AIBinder* binder) {
+ binder_status_t linked = AIBinder_linkToDeath(binder, mRecipient, mCookie);
+ if (linked != STATUS_OK) {
+ ALOGE("Could not link death recipient to the HAL death");
+ }
+}
+
+ScopedDeathRecipient::~ScopedDeathRecipient() {
+ AIBinder_DeathRecipient_delete(mRecipient);
+}
+
// --- ClassifierEvent ---
ClassifierEvent::ClassifierEvent(std::unique_ptr<NotifyMotionArgs> args) :
@@ -118,9 +169,8 @@
// --- MotionClassifier ---
-MotionClassifier::MotionClassifier(
- sp<android::hardware::input::classifier::V1_0::IInputClassifier> service)
- : mEvents(MAX_EVENTS), mService(service) {
+MotionClassifier::MotionClassifier(std::shared_ptr<IInputProcessor> service)
+ : mEvents(MAX_EVENTS), mService(std::move(service)) {
// Under normal operation, we do not need to reset the HAL here. But in the case where system
// crashed, but HAL didn't, we may be connecting to an existing HAL process that might already
// have received events in the past. That means, that HAL could be in an inconsistent state
@@ -135,23 +185,10 @@
}
std::unique_ptr<MotionClassifierInterface> MotionClassifier::create(
- sp<android::hardware::hidl_death_recipient> deathRecipient) {
- sp<android::hardware::input::classifier::V1_0::IInputClassifier> service =
- classifier::V1_0::IInputClassifier::getService();
- if (!service) {
- // Not really an error, maybe the device does not have this HAL,
- // but somehow the feature flag is flipped
- ALOGI("Could not obtain InputClassifier HAL");
- return nullptr;
- }
-
- const bool linked = service->linkToDeath(deathRecipient, 0 /* cookie */).withDefault(false);
- if (!linked) {
- ALOGE("Could not link death recipient to the HAL death");
- return nullptr;
- }
+ std::shared_ptr<IInputProcessor> service) {
+ LOG_ALWAYS_FATAL_IF(service == nullptr);
// Using 'new' to access a non-public constructor
- return std::unique_ptr<MotionClassifier>(new MotionClassifier(service));
+ return std::unique_ptr<MotionClassifier>(new MotionClassifier(std::move(service)));
}
MotionClassifier::~MotionClassifier() {
@@ -176,14 +213,12 @@
switch (event.type) {
case ClassifierEventType::MOTION: {
NotifyMotionArgs* motionArgs = static_cast<NotifyMotionArgs*>(event.args.get());
- common::V1_0::MotionEvent motionEvent =
- notifyMotionArgsToHalMotionEvent(*motionArgs);
- Return<common::V1_0::Classification> response = mService->classify(motionEvent);
- halResponseOk = response.isOk();
- if (halResponseOk) {
- common::V1_0::Classification halClassification = response;
+ common::MotionEvent motionEvent = notifyMotionArgsToHalMotionEvent(*motionArgs);
+ common::Classification classification;
+ ndk::ScopedAStatus response = mService->classify(motionEvent, &classification);
+ if (response.isOk()) {
updateClassification(motionArgs->deviceId, motionArgs->eventTime,
- getMotionClassification(halClassification));
+ getMotionClassification(classification));
}
break;
}
@@ -300,7 +335,8 @@
if (!mService) {
return "null";
}
- if (mService->ping().isOk()) {
+
+ if (AIBinder_ping(mService->asBinder().get()) == STATUS_OK) {
return "running";
}
return "not responding";
@@ -329,40 +365,53 @@
}
}
-// --- HalDeathRecipient
-
-InputClassifier::HalDeathRecipient::HalDeathRecipient(InputClassifier& parent) : mParent(parent) {}
-
-void InputClassifier::HalDeathRecipient::serviceDied(
- uint64_t cookie, const wp<android::hidl::base::V1_0::IBase>& who) {
- sp<android::hidl::base::V1_0::IBase> service = who.promote();
- if (service) {
- service->unlinkToDeath(this);
- }
- mParent.setMotionClassifier(nullptr);
-}
-
// --- InputClassifier ---
-InputClassifier::InputClassifier(InputListenerInterface& listener)
- : mListener(listener), mHalDeathRecipient(new HalDeathRecipient(*this)) {}
+InputClassifier::InputClassifier(InputListenerInterface& listener) : mListener(listener) {}
+
+void InputClassifier::onBinderDied(void* cookie) {
+ InputClassifier* classifier = static_cast<InputClassifier*>(cookie);
+ if (classifier == nullptr) {
+ LOG_ALWAYS_FATAL("Cookie is not valid");
+ return;
+ }
+ classifier->setMotionClassifierEnabled(false);
+}
void InputClassifier::setMotionClassifierEnabled(bool enabled) {
+ std::scoped_lock lock(mLock);
if (enabled) {
ALOGI("Enabling motion classifier");
- if (mInitializeMotionClassifierThread.joinable()) {
- mInitializeMotionClassifierThread.join();
+ if (mInitializeMotionClassifier.valid()) {
+ scoped_unlock unlock(mLock);
+ std::future_status status = mInitializeMotionClassifier.wait_for(5s);
+ if (status != std::future_status::ready) {
+ /**
+ * We don't have a better option here than to crash. We can't stop the thread,
+ * and we can't continue because 'mInitializeMotionClassifier' will block in its
+ * destructor.
+ */
+ LOG_ALWAYS_FATAL("The thread to load IInputClassifier is stuck!");
+ }
}
- mInitializeMotionClassifierThread = std::thread(
- [this] { setMotionClassifier(MotionClassifier::create(mHalDeathRecipient)); });
-#if defined(__linux__)
- // Set the thread name for debugging
- pthread_setname_np(mInitializeMotionClassifierThread.native_handle(),
- "Create MotionClassifier");
-#endif
+ mInitializeMotionClassifier = std::async(std::launch::async, [this] {
+ setCurrentThreadName("Create MotionClassifier");
+ std::shared_ptr<IInputProcessor> service = getService();
+ if (service == nullptr) {
+ // Keep the MotionClassifier null, no service was found
+ return;
+ }
+ { // acquire lock
+ std::scoped_lock threadLock(mLock);
+ mHalDeathRecipient =
+ std::make_unique<ScopedDeathRecipient>(onBinderDied, this /*cookie*/);
+ mHalDeathRecipient->linkToDeath(service->asBinder().get());
+ setMotionClassifierLocked(MotionClassifier::create(std::move(service)));
+ } // release lock
+ });
} else {
ALOGI("Disabling motion classifier");
- setMotionClassifier(nullptr);
+ setMotionClassifierLocked(nullptr);
}
}
@@ -419,9 +468,13 @@
mListener.notifyPointerCaptureChanged(args);
}
-void InputClassifier::setMotionClassifier(
- std::unique_ptr<MotionClassifierInterface> motionClassifier) {
- std::scoped_lock lock(mLock);
+void InputClassifier::setMotionClassifierLocked(
+ std::unique_ptr<MotionClassifierInterface> motionClassifier) REQUIRES(mLock) {
+ if (motionClassifier == nullptr) {
+ // Destroy the ScopedDeathRecipient object, which will cause it to unlinkToDeath.
+ // We can't call 'unlink' here because we don't have the binder handle.
+ mHalDeathRecipient = nullptr;
+ }
mMotionClassifier = std::move(motionClassifier);
}
@@ -438,9 +491,6 @@
}
InputClassifier::~InputClassifier() {
- if (mInitializeMotionClassifierThread.joinable()) {
- mInitializeMotionClassifierThread.join();
- }
}
} // namespace android
diff --git a/services/inputflinger/InputClassifier.h b/services/inputflinger/InputClassifier.h
index deeae7c..e2a0bc2 100644
--- a/services/inputflinger/InputClassifier.h
+++ b/services/inputflinger/InputClassifier.h
@@ -18,13 +18,13 @@
#define _UI_INPUT_CLASSIFIER_H
#include <android-base/thread_annotations.h>
+#include <future>
#include <thread>
#include <unordered_map>
+#include <aidl/android/hardware/input/processor/IInputProcessor.h>
#include "BlockingQueue.h"
#include "InputListener.h"
-#include <android/hardware/input/classifier/1.0/IInputClassifier.h>
-
namespace android {
enum class ClassifierEventType : uint8_t {
@@ -102,6 +102,19 @@
// --- Implementations ---
+class ScopedDeathRecipient {
+public:
+ explicit ScopedDeathRecipient(AIBinder_DeathRecipient_onBinderDied onBinderDied, void* cookie);
+ ScopedDeathRecipient(const ScopedDeathRecipient&) = delete;
+ ScopedDeathRecipient& operator=(ScopedDeathRecipient const&) = delete;
+ void linkToDeath(AIBinder* binder);
+ ~ScopedDeathRecipient();
+
+private:
+ AIBinder_DeathRecipient* mRecipient;
+ void* mCookie;
+};
+
/**
* Implementation of MotionClassifierInterface that calls the InputClassifier HAL
* in order to determine the classification for the current gesture.
@@ -121,7 +134,7 @@
* This function should be called asynchronously, because getService takes a long time.
*/
static std::unique_ptr<MotionClassifierInterface> create(
- sp<android::hardware::hidl_death_recipient> deathRecipient);
+ std::shared_ptr<aidl::android::hardware::input::processor::IInputProcessor> service);
~MotionClassifier();
@@ -143,7 +156,7 @@
private:
friend class MotionClassifierTest; // to create MotionClassifier with a test HAL implementation
explicit MotionClassifier(
- sp<android::hardware::input::classifier::V1_0::IInputClassifier> service);
+ std::shared_ptr<aidl::android::hardware::input::processor::IInputProcessor> service);
// The events that need to be sent to the HAL.
BlockingQueue<ClassifierEvent> mEvents;
@@ -162,14 +175,14 @@
*/
void processEvents();
/**
- * Access to the InputClassifier HAL. May be null if init() hasn't completed yet.
+ * Access to the InputProcessor HAL. May be null if init() hasn't completed yet.
* When init() successfully completes, mService is guaranteed to remain non-null and to not
* change its value until MotionClassifier is destroyed.
* This variable is *not* guarded by mLock in the InputClassifier thread, because
* that thread knows exactly when this variable is initialized.
* When accessed in any other thread, mService is checked for nullness with a lock.
*/
- sp<android::hardware::input::classifier::V1_0::IInputClassifier> mService;
+ std::shared_ptr<aidl::android::hardware::input::processor::IInputProcessor> mService;
std::mutex mLock;
/**
* Per-device input classifications. Should only be accessed using the
@@ -224,21 +237,21 @@
public:
explicit InputClassifier(InputListenerInterface& listener);
- virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
- virtual void notifyKey(const NotifyKeyArgs* args) override;
- virtual void notifyMotion(const NotifyMotionArgs* args) override;
- virtual void notifySwitch(const NotifySwitchArgs* args) override;
- virtual void notifySensor(const NotifySensorArgs* args) override;
- virtual void notifyVibratorState(const NotifyVibratorStateArgs* args) override;
- virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
+ void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
+ void notifyKey(const NotifyKeyArgs* args) override;
+ void notifyMotion(const NotifyMotionArgs* args) override;
+ void notifySwitch(const NotifySwitchArgs* args) override;
+ void notifySensor(const NotifySensorArgs* args) override;
+ void notifyVibratorState(const NotifyVibratorStateArgs* args) override;
+ void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override;
- virtual void dump(std::string& dump) override;
+ void dump(std::string& dump) override;
~InputClassifier();
// Called from InputManager
- virtual void setMotionClassifierEnabled(bool enabled) override;
+ void setMotionClassifierEnabled(bool enabled) override;
private:
// Protect access to mMotionClassifier, since it may become null via a hidl callback
@@ -247,7 +260,8 @@
InputListenerInterface& mListener;
std::unique_ptr<MotionClassifierInterface> mMotionClassifier GUARDED_BY(mLock);
- std::thread mInitializeMotionClassifierThread;
+ std::future<void> mInitializeMotionClassifier GUARDED_BY(mLock);
+
/**
* Set the value of mMotionClassifier.
* This is called from 2 different threads:
@@ -255,25 +269,12 @@
* 2) A binder thread of the HalDeathRecipient, which is created when HAL dies. This would cause
* mMotionClassifier to become nullptr.
*/
- void setMotionClassifier(std::unique_ptr<MotionClassifierInterface> motionClassifier);
+ void setMotionClassifierLocked(std::unique_ptr<MotionClassifierInterface> motionClassifier)
+ REQUIRES(mLock);
- /**
- * The deathRecipient will call setMotionClassifier(null) when the HAL dies.
- */
- class HalDeathRecipient : public android::hardware::hidl_death_recipient {
- public:
- explicit HalDeathRecipient(InputClassifier& parent);
- virtual void serviceDied(uint64_t cookie,
- const wp<android::hidl::base::V1_0::IBase>& who) override;
+ static void onBinderDied(void* cookie);
- private:
- InputClassifier& mParent;
- };
- // We retain a reference to death recipient, because the death recipient will be calling
- // ~MotionClassifier if the HAL dies.
- // If we don't retain a reference, and MotionClassifier is the only owner of the death
- // recipient, the serviceDied call will cause death recipient to call its own destructor.
- sp<HalDeathRecipient> mHalDeathRecipient;
+ std::unique_ptr<ScopedDeathRecipient> mHalDeathRecipient GUARDED_BY(mLock);
};
} // namespace android
diff --git a/services/inputflinger/InputClassifierConverter.cpp b/services/inputflinger/InputClassifierConverter.cpp
deleted file mode 100644
index b58a188..0000000
--- a/services/inputflinger/InputClassifierConverter.cpp
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * Copyright (C) 2019 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 "InputClassifierConverter.h"
-
-using android::hardware::hidl_bitfield;
-using namespace android::hardware::input;
-
-namespace android {
-
-static common::V1_0::Source getSource(uint32_t source) {
- static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_UNKNOWN) ==
- common::V1_0::Source::UNKNOWN, "SOURCE_UNKNOWN mismatch");
- static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_KEYBOARD) ==
- common::V1_0::Source::KEYBOARD, "SOURCE_KEYBOARD mismatch");
- static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_DPAD) ==
- common::V1_0::Source::DPAD, "SOURCE_DPAD mismatch");
- static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_GAMEPAD) ==
- common::V1_0::Source::GAMEPAD, "SOURCE_GAMEPAD mismatch");
- static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TOUCHSCREEN) ==
- common::V1_0::Source::TOUCHSCREEN, "SOURCE_TOUCHSCREEN mismatch");
- static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_MOUSE) ==
- common::V1_0::Source::MOUSE, "SOURCE_MOUSE mismatch");
- static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_STYLUS) ==
- common::V1_0::Source::STYLUS, "SOURCE_STYLUS mismatch");
- static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_BLUETOOTH_STYLUS) ==
- common::V1_0::Source::BLUETOOTH_STYLUS, "SOURCE_BLUETOOTH_STYLUS mismatch");
- static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TRACKBALL) ==
- common::V1_0::Source::TRACKBALL, "SOURCE_TRACKBALL mismatch");
- static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_MOUSE_RELATIVE) ==
- common::V1_0::Source::MOUSE_RELATIVE, "SOURCE_MOUSE_RELATIVE mismatch");
- static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TOUCHPAD) ==
- common::V1_0::Source::TOUCHPAD, "SOURCE_TOUCHPAD mismatch");
- static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TOUCH_NAVIGATION) ==
- common::V1_0::Source::TOUCH_NAVIGATION, "SOURCE_TOUCH_NAVIGATION mismatch");
- static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_JOYSTICK) ==
- common::V1_0::Source::JOYSTICK, "SOURCE_JOYSTICK mismatch");
- static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_ROTARY_ENCODER) ==
- common::V1_0::Source::ROTARY_ENCODER, "SOURCE_ROTARY_ENCODER mismatch");
- static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_ANY) ==
- common::V1_0::Source::ANY, "SOURCE_ANY mismatch");
- return static_cast<common::V1_0::Source>(source);
-}
-
-static common::V1_0::Action getAction(int32_t actionMasked) {
- static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_DOWN) ==
- common::V1_0::Action::DOWN, "ACTION_DOWN mismatch");
- static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_UP) ==
- common::V1_0::Action::UP, "ACTION_UP mismatch");
- static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_MOVE) ==
- common::V1_0::Action::MOVE, "ACTION_MOVE mismatch");
- static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_CANCEL) ==
- common::V1_0::Action::CANCEL, "ACTION_CANCEL mismatch");
- static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_OUTSIDE) ==
- common::V1_0::Action::OUTSIDE, "ACTION_OUTSIDE mismatch");
- static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_POINTER_DOWN) ==
- common::V1_0::Action::POINTER_DOWN, "ACTION_POINTER_DOWN mismatch");
- static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_POINTER_UP) ==
- common::V1_0::Action::POINTER_UP, "ACTION_POINTER_UP mismatch");
- static_assert(static_cast<common::V1_0::Action>( AMOTION_EVENT_ACTION_HOVER_MOVE) ==
- common::V1_0::Action::HOVER_MOVE, "ACTION_HOVER_MOVE mismatch");
- static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_SCROLL) ==
- common::V1_0::Action::SCROLL, "ACTION_SCROLL mismatch");
- static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_HOVER_ENTER) ==
- common::V1_0::Action::HOVER_ENTER, "ACTION_HOVER_ENTER mismatch");
- static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_HOVER_EXIT) ==
- common::V1_0::Action::HOVER_EXIT, "ACTION_HOVER_EXIT mismatch");
- static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_BUTTON_PRESS) ==
- common::V1_0::Action::BUTTON_PRESS, "ACTION_BUTTON_PRESS mismatch");
- static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_BUTTON_RELEASE) ==
- common::V1_0::Action::BUTTON_RELEASE, "ACTION_BUTTON_RELEASE mismatch");
- return static_cast<common::V1_0::Action>(actionMasked);
-}
-
-static common::V1_0::Button getActionButton(int32_t actionButton) {
- static_assert(static_cast<common::V1_0::Button>(0) ==
- common::V1_0::Button::NONE, "BUTTON_NONE mismatch");
- static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_PRIMARY) ==
- common::V1_0::Button::PRIMARY, "BUTTON_PRIMARY mismatch");
- static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_SECONDARY) ==
- common::V1_0::Button::SECONDARY, "BUTTON_SECONDARY mismatch");
- static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_TERTIARY) ==
- common::V1_0::Button::TERTIARY, "BUTTON_TERTIARY mismatch");
- static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_BACK) ==
- common::V1_0::Button::BACK, "BUTTON_BACK mismatch");
- static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_FORWARD) ==
- common::V1_0::Button::FORWARD, "BUTTON_FORWARD mismatch");
- static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY) ==
- common::V1_0::Button::STYLUS_PRIMARY, "BUTTON_STYLUS_PRIMARY mismatch");
- static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY) ==
- common::V1_0::Button::STYLUS_SECONDARY, "BUTTON_STYLUS_SECONDARY mismatch");
- return static_cast<common::V1_0::Button>(actionButton);
-}
-
-static hidl_bitfield<common::V1_0::Flag> getFlags(int32_t flags) {
- static_assert(static_cast<common::V1_0::Flag>(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED) ==
- common::V1_0::Flag::WINDOW_IS_OBSCURED);
- static_assert(static_cast<common::V1_0::Flag>(AMOTION_EVENT_FLAG_IS_GENERATED_GESTURE) ==
- common::V1_0::Flag::IS_GENERATED_GESTURE);
- static_assert(static_cast<common::V1_0::Flag>(AMOTION_EVENT_FLAG_TAINTED) ==
- common::V1_0::Flag::TAINTED);
- return static_cast<hidl_bitfield<common::V1_0::Flag>>(flags);
-}
-
-static hidl_bitfield<common::V1_0::PolicyFlag> getPolicyFlags(int32_t flags) {
- static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_WAKE) ==
- common::V1_0::PolicyFlag::WAKE);
- static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_VIRTUAL) ==
- common::V1_0::PolicyFlag::VIRTUAL);
- static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_FUNCTION) ==
- common::V1_0::PolicyFlag::FUNCTION);
- static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_GESTURE) ==
- common::V1_0::PolicyFlag::GESTURE);
- static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_INJECTED) ==
- common::V1_0::PolicyFlag::INJECTED);
- static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_TRUSTED) ==
- common::V1_0::PolicyFlag::TRUSTED);
- static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_FILTERED) ==
- common::V1_0::PolicyFlag::FILTERED);
- static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_DISABLE_KEY_REPEAT) ==
- common::V1_0::PolicyFlag::DISABLE_KEY_REPEAT);
- static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_INTERACTIVE) ==
- common::V1_0::PolicyFlag::INTERACTIVE);
- static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_PASS_TO_USER) ==
- common::V1_0::PolicyFlag::PASS_TO_USER);
- return static_cast<hidl_bitfield<common::V1_0::PolicyFlag>>(flags);
-}
-
-static hidl_bitfield<common::V1_0::EdgeFlag> getEdgeFlags(int32_t flags) {
- static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_NONE) ==
- common::V1_0::EdgeFlag::NONE);
- static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_TOP) ==
- common::V1_0::EdgeFlag::TOP);
- static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_BOTTOM) ==
- common::V1_0::EdgeFlag::BOTTOM);
- static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_LEFT) ==
- common::V1_0::EdgeFlag::LEFT);
- static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_RIGHT) ==
- common::V1_0::EdgeFlag::RIGHT);
- return static_cast<hidl_bitfield<common::V1_0::EdgeFlag>>(flags);
-}
-
-static hidl_bitfield<common::V1_0::Meta> getMetastate(int32_t state) {
- static_assert(static_cast<common::V1_0::Meta>(AMETA_NONE) ==
- common::V1_0::Meta::NONE);
- static_assert(static_cast<common::V1_0::Meta>(AMETA_ALT_ON) ==
- common::V1_0::Meta::ALT_ON);
- static_assert(static_cast<common::V1_0::Meta>(AMETA_ALT_LEFT_ON) ==
- common::V1_0::Meta::ALT_LEFT_ON);
- static_assert(static_cast<common::V1_0::Meta>(AMETA_ALT_RIGHT_ON) ==
- common::V1_0::Meta::ALT_RIGHT_ON);
- static_assert(static_cast<common::V1_0::Meta>(AMETA_SHIFT_ON) ==
- common::V1_0::Meta::SHIFT_ON);
- static_assert(static_cast<common::V1_0::Meta>(AMETA_SHIFT_LEFT_ON) ==
- common::V1_0::Meta::SHIFT_LEFT_ON);
- static_assert(static_cast<common::V1_0::Meta>(AMETA_SHIFT_RIGHT_ON) ==
- common::V1_0::Meta::SHIFT_RIGHT_ON);
- static_assert(static_cast<common::V1_0::Meta>(AMETA_SYM_ON) ==
- common::V1_0::Meta::SYM_ON);
- static_assert(static_cast<common::V1_0::Meta>(AMETA_FUNCTION_ON) ==
- common::V1_0::Meta::FUNCTION_ON);
- static_assert(static_cast<common::V1_0::Meta>(AMETA_CTRL_ON) ==
- common::V1_0::Meta::CTRL_ON);
- static_assert(static_cast<common::V1_0::Meta>(AMETA_CTRL_LEFT_ON) ==
- common::V1_0::Meta::CTRL_LEFT_ON);
- static_assert(static_cast<common::V1_0::Meta>(AMETA_CTRL_RIGHT_ON) ==
- common::V1_0::Meta::CTRL_RIGHT_ON);
- static_assert(static_cast<common::V1_0::Meta>(AMETA_META_ON) ==
- common::V1_0::Meta::META_ON);
- static_assert(static_cast<common::V1_0::Meta>(AMETA_META_LEFT_ON) ==
- common::V1_0::Meta::META_LEFT_ON);
- static_assert(static_cast<common::V1_0::Meta>(AMETA_META_RIGHT_ON) ==
- common::V1_0::Meta::META_RIGHT_ON);
- static_assert(static_cast<common::V1_0::Meta>(AMETA_CAPS_LOCK_ON) ==
- common::V1_0::Meta::CAPS_LOCK_ON);
- static_assert(static_cast<common::V1_0::Meta>(AMETA_NUM_LOCK_ON) ==
- common::V1_0::Meta::NUM_LOCK_ON);
- static_assert(static_cast<common::V1_0::Meta>(AMETA_SCROLL_LOCK_ON) ==
- common::V1_0::Meta::SCROLL_LOCK_ON);
- return static_cast<hidl_bitfield<common::V1_0::Meta>>(state);
-}
-
-static hidl_bitfield<common::V1_0::Button> getButtonState(int32_t buttonState) {
- // No need for static_assert here.
- // The button values have already been asserted in getActionButton(..) above
- return static_cast<hidl_bitfield<common::V1_0::Button>>(buttonState);
-}
-
-static common::V1_0::ToolType getToolType(int32_t toolType) {
- static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_UNKNOWN) ==
- common::V1_0::ToolType::UNKNOWN);
- static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_FINGER) ==
- common::V1_0::ToolType::FINGER);
- static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_STYLUS) ==
- common::V1_0::ToolType::STYLUS);
- static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_MOUSE) ==
- common::V1_0::ToolType::MOUSE);
- static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_ERASER) ==
- common::V1_0::ToolType::ERASER);
- return static_cast<common::V1_0::ToolType>(toolType);
-}
-
-// MotionEvent axes asserts
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_X) ==
- common::V1_0::Axis::X);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_Y) ==
- common::V1_0::Axis::Y);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_PRESSURE) ==
- common::V1_0::Axis::PRESSURE);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_SIZE) ==
- common::V1_0::Axis::SIZE);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOUCH_MAJOR) ==
- common::V1_0::Axis::TOUCH_MAJOR);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOUCH_MINOR) ==
- common::V1_0::Axis::TOUCH_MINOR);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOOL_MAJOR) ==
- common::V1_0::Axis::TOOL_MAJOR);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOOL_MINOR) ==
- common::V1_0::Axis::TOOL_MINOR);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_ORIENTATION) ==
- common::V1_0::Axis::ORIENTATION);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_VSCROLL) ==
- common::V1_0::Axis::VSCROLL);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_HSCROLL) ==
- common::V1_0::Axis::HSCROLL);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_Z) ==
- common::V1_0::Axis::Z);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RX) ==
- common::V1_0::Axis::RX);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RY) ==
- common::V1_0::Axis::RY);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RZ) ==
- common::V1_0::Axis::RZ);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_HAT_X) ==
- common::V1_0::Axis::HAT_X);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_HAT_Y) ==
- common::V1_0::Axis::HAT_Y);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_LTRIGGER) ==
- common::V1_0::Axis::LTRIGGER);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RTRIGGER) ==
- common::V1_0::Axis::RTRIGGER);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_THROTTLE) ==
- common::V1_0::Axis::THROTTLE);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RUDDER) ==
- common::V1_0::Axis::RUDDER);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_WHEEL) ==
- common::V1_0::Axis::WHEEL);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GAS) ==
- common::V1_0::Axis::GAS);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_BRAKE) ==
- common::V1_0::Axis::BRAKE);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_DISTANCE) ==
- common::V1_0::Axis::DISTANCE);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TILT) ==
- common::V1_0::Axis::TILT);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_SCROLL) ==
- common::V1_0::Axis::SCROLL);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RELATIVE_X) ==
- common::V1_0::Axis::RELATIVE_X);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RELATIVE_Y) ==
- common::V1_0::Axis::RELATIVE_Y);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_1) ==
- common::V1_0::Axis::GENERIC_1);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_2) ==
- common::V1_0::Axis::GENERIC_2);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_3) ==
- common::V1_0::Axis::GENERIC_3);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_4) ==
- common::V1_0::Axis::GENERIC_4);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_5) ==
- common::V1_0::Axis::GENERIC_5);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_6) ==
- common::V1_0::Axis::GENERIC_6);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_7) ==
- common::V1_0::Axis::GENERIC_7);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_8) ==
- common::V1_0::Axis::GENERIC_8);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_9) ==
- common::V1_0::Axis::GENERIC_9);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_10) ==
- common::V1_0::Axis::GENERIC_10);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_11) ==
- common::V1_0::Axis::GENERIC_11);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_12) ==
- common::V1_0::Axis::GENERIC_12);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_13) ==
- common::V1_0::Axis::GENERIC_13);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_14) ==
- common::V1_0::Axis::GENERIC_14);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_15) ==
- common::V1_0::Axis::GENERIC_15);
-static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_16) ==
- common::V1_0::Axis::GENERIC_16);
-
-static common::V1_0::VideoFrame getHalVideoFrame(const TouchVideoFrame& frame) {
- common::V1_0::VideoFrame out;
- out.width = frame.getWidth();
- out.height = frame.getHeight();
- out.data = frame.getData();
- struct timeval timestamp = frame.getTimestamp();
- out.timestamp = seconds_to_nanoseconds(timestamp.tv_sec) +
- microseconds_to_nanoseconds(timestamp.tv_usec);
- return out;
-}
-
-static std::vector<common::V1_0::VideoFrame> convertVideoFrames(
- const std::vector<TouchVideoFrame>& frames) {
- std::vector<common::V1_0::VideoFrame> out;
- for (const TouchVideoFrame& frame : frames) {
- out.push_back(getHalVideoFrame(frame));
- }
- return out;
-}
-
-static void getHidlPropertiesAndCoords(const NotifyMotionArgs& args,
- std::vector<common::V1_0::PointerProperties>* outPointerProperties,
- std::vector<common::V1_0::PointerCoords>* outPointerCoords) {
- outPointerProperties->reserve(args.pointerCount);
- outPointerCoords->reserve(args.pointerCount);
- for (size_t i = 0; i < args.pointerCount; i++) {
- common::V1_0::PointerProperties properties;
- properties.id = args.pointerProperties[i].id;
- properties.toolType = getToolType(args.pointerProperties[i].toolType);
- outPointerProperties->push_back(properties);
-
- common::V1_0::PointerCoords coords;
- // OK to copy bits because we have static_assert for pointerCoords axes
- coords.bits = args.pointerCoords[i].bits;
- coords.values = std::vector<float>(
- args.pointerCoords[i].values,
- args.pointerCoords[i].values + BitSet64::count(args.pointerCoords[i].bits));
- outPointerCoords->push_back(coords);
- }
-}
-
-common::V1_0::MotionEvent notifyMotionArgsToHalMotionEvent(const NotifyMotionArgs& args) {
- common::V1_0::MotionEvent event;
- event.deviceId = args.deviceId;
- event.source = getSource(args.source);
- event.displayId = args.displayId;
- event.downTime = args.downTime;
- event.eventTime = args.eventTime;
- event.deviceTimestamp = 0;
- event.action = getAction(args.action & AMOTION_EVENT_ACTION_MASK);
- event.actionIndex = MotionEvent::getActionIndex(args.action);
- event.actionButton = getActionButton(args.actionButton);
- event.flags = getFlags(args.flags);
- event.policyFlags = getPolicyFlags(args.policyFlags);
- event.edgeFlags = getEdgeFlags(args.edgeFlags);
- event.metaState = getMetastate(args.metaState);
- event.buttonState = getButtonState(args.buttonState);
- event.xPrecision = args.xPrecision;
- event.yPrecision = args.yPrecision;
-
- std::vector<common::V1_0::PointerProperties> pointerProperties;
- std::vector<common::V1_0::PointerCoords> pointerCoords;
- getHidlPropertiesAndCoords(args, /*out*/&pointerProperties, /*out*/&pointerCoords);
- event.pointerProperties = pointerProperties;
- event.pointerCoords = pointerCoords;
-
- event.frames = convertVideoFrames(args.videoFrames);
-
- return event;
-}
-
-} // namespace android
diff --git a/services/inputflinger/InputCommonConverter.cpp b/services/inputflinger/InputCommonConverter.cpp
new file mode 100644
index 0000000..8aee39f
--- /dev/null
+++ b/services/inputflinger/InputCommonConverter.cpp
@@ -0,0 +1,339 @@
+/*
+ * 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 "InputCommonConverter.h"
+
+using namespace ::aidl::android::hardware::input;
+
+namespace android {
+
+static common::Source getSource(uint32_t source) {
+ static_assert(static_cast<common::Source>(AINPUT_SOURCE_UNKNOWN) == common::Source::UNKNOWN,
+ "SOURCE_UNKNOWN mismatch");
+ static_assert(static_cast<common::Source>(AINPUT_SOURCE_KEYBOARD) == common::Source::KEYBOARD,
+ "SOURCE_KEYBOARD mismatch");
+ static_assert(static_cast<common::Source>(AINPUT_SOURCE_DPAD) == common::Source::DPAD,
+ "SOURCE_DPAD mismatch");
+ static_assert(static_cast<common::Source>(AINPUT_SOURCE_GAMEPAD) == common::Source::GAMEPAD,
+ "SOURCE_GAMEPAD mismatch");
+ static_assert(static_cast<common::Source>(AINPUT_SOURCE_TOUCHSCREEN) ==
+ common::Source::TOUCHSCREEN,
+ "SOURCE_TOUCHSCREEN mismatch");
+ static_assert(static_cast<common::Source>(AINPUT_SOURCE_MOUSE) == common::Source::MOUSE,
+ "SOURCE_MOUSE mismatch");
+ static_assert(static_cast<common::Source>(AINPUT_SOURCE_STYLUS) == common::Source::STYLUS,
+ "SOURCE_STYLUS mismatch");
+ static_assert(static_cast<common::Source>(AINPUT_SOURCE_BLUETOOTH_STYLUS) ==
+ common::Source::BLUETOOTH_STYLUS,
+ "SOURCE_BLUETOOTH_STYLUS mismatch");
+ static_assert(static_cast<common::Source>(AINPUT_SOURCE_TRACKBALL) == common::Source::TRACKBALL,
+ "SOURCE_TRACKBALL mismatch");
+ static_assert(static_cast<common::Source>(AINPUT_SOURCE_MOUSE_RELATIVE) ==
+ common::Source::MOUSE_RELATIVE,
+ "SOURCE_MOUSE_RELATIVE mismatch");
+ static_assert(static_cast<common::Source>(AINPUT_SOURCE_TOUCHPAD) == common::Source::TOUCHPAD,
+ "SOURCE_TOUCHPAD mismatch");
+ static_assert(static_cast<common::Source>(AINPUT_SOURCE_TOUCH_NAVIGATION) ==
+ common::Source::TOUCH_NAVIGATION,
+ "SOURCE_TOUCH_NAVIGATION mismatch");
+ static_assert(static_cast<common::Source>(AINPUT_SOURCE_JOYSTICK) == common::Source::JOYSTICK,
+ "SOURCE_JOYSTICK mismatch");
+ static_assert(static_cast<common::Source>(AINPUT_SOURCE_ROTARY_ENCODER) ==
+ common::Source::ROTARY_ENCODER,
+ "SOURCE_ROTARY_ENCODER mismatch");
+ static_assert(static_cast<common::Source>(AINPUT_SOURCE_HDMI) == common::Source::HDMI);
+ static_assert(static_cast<common::Source>(AINPUT_SOURCE_SENSOR) == common::Source::SENSOR);
+ static_assert(static_cast<common::Source>(AINPUT_SOURCE_ANY) == common::Source::ANY,
+ "SOURCE_ANY mismatch");
+ return static_cast<common::Source>(source);
+}
+
+static common::Action getAction(int32_t actionMasked) {
+ static_assert(static_cast<common::Action>(AMOTION_EVENT_ACTION_DOWN) == common::Action::DOWN,
+ "ACTION_DOWN mismatch");
+ static_assert(static_cast<common::Action>(AMOTION_EVENT_ACTION_UP) == common::Action::UP,
+ "ACTION_UP mismatch");
+ static_assert(static_cast<common::Action>(AMOTION_EVENT_ACTION_MOVE) == common::Action::MOVE,
+ "ACTION_MOVE mismatch");
+ static_assert(static_cast<common::Action>(AMOTION_EVENT_ACTION_CANCEL) ==
+ common::Action::CANCEL,
+ "ACTION_CANCEL mismatch");
+ static_assert(static_cast<common::Action>(AMOTION_EVENT_ACTION_OUTSIDE) ==
+ common::Action::OUTSIDE,
+ "ACTION_OUTSIDE mismatch");
+ static_assert(static_cast<common::Action>(AMOTION_EVENT_ACTION_POINTER_DOWN) ==
+ common::Action::POINTER_DOWN,
+ "ACTION_POINTER_DOWN mismatch");
+ static_assert(static_cast<common::Action>(AMOTION_EVENT_ACTION_POINTER_UP) ==
+ common::Action::POINTER_UP,
+ "ACTION_POINTER_UP mismatch");
+ static_assert(static_cast<common::Action>(AMOTION_EVENT_ACTION_HOVER_MOVE) ==
+ common::Action::HOVER_MOVE,
+ "ACTION_HOVER_MOVE mismatch");
+ static_assert(static_cast<common::Action>(AMOTION_EVENT_ACTION_SCROLL) ==
+ common::Action::SCROLL,
+ "ACTION_SCROLL mismatch");
+ static_assert(static_cast<common::Action>(AMOTION_EVENT_ACTION_HOVER_ENTER) ==
+ common::Action::HOVER_ENTER,
+ "ACTION_HOVER_ENTER mismatch");
+ static_assert(static_cast<common::Action>(AMOTION_EVENT_ACTION_HOVER_EXIT) ==
+ common::Action::HOVER_EXIT,
+ "ACTION_HOVER_EXIT mismatch");
+ static_assert(static_cast<common::Action>(AMOTION_EVENT_ACTION_BUTTON_PRESS) ==
+ common::Action::BUTTON_PRESS,
+ "ACTION_BUTTON_PRESS mismatch");
+ static_assert(static_cast<common::Action>(AMOTION_EVENT_ACTION_BUTTON_RELEASE) ==
+ common::Action::BUTTON_RELEASE,
+ "ACTION_BUTTON_RELEASE mismatch");
+ return static_cast<common::Action>(actionMasked);
+}
+
+static common::Button getActionButton(int32_t actionButton) {
+ static_assert(static_cast<common::Button>(0) == common::Button::NONE, "BUTTON_NONE mismatch");
+ static_assert(static_cast<common::Button>(AMOTION_EVENT_BUTTON_PRIMARY) ==
+ common::Button::PRIMARY,
+ "BUTTON_PRIMARY mismatch");
+ static_assert(static_cast<common::Button>(AMOTION_EVENT_BUTTON_SECONDARY) ==
+ common::Button::SECONDARY,
+ "BUTTON_SECONDARY mismatch");
+ static_assert(static_cast<common::Button>(AMOTION_EVENT_BUTTON_TERTIARY) ==
+ common::Button::TERTIARY,
+ "BUTTON_TERTIARY mismatch");
+ static_assert(static_cast<common::Button>(AMOTION_EVENT_BUTTON_BACK) == common::Button::BACK,
+ "BUTTON_BACK mismatch");
+ static_assert(static_cast<common::Button>(AMOTION_EVENT_BUTTON_FORWARD) ==
+ common::Button::FORWARD,
+ "BUTTON_FORWARD mismatch");
+ static_assert(static_cast<common::Button>(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY) ==
+ common::Button::STYLUS_PRIMARY,
+ "BUTTON_STYLUS_PRIMARY mismatch");
+ static_assert(static_cast<common::Button>(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY) ==
+ common::Button::STYLUS_SECONDARY,
+ "BUTTON_STYLUS_SECONDARY mismatch");
+ return static_cast<common::Button>(actionButton);
+}
+
+static common::Flag getFlags(int32_t flags) {
+ static_assert(static_cast<common::Flag>(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED) ==
+ common::Flag::WINDOW_IS_OBSCURED);
+ static_assert(static_cast<common::Flag>(AMOTION_EVENT_FLAG_IS_GENERATED_GESTURE) ==
+ common::Flag::IS_GENERATED_GESTURE);
+ static_assert(static_cast<common::Flag>(AMOTION_EVENT_FLAG_TAINTED) == common::Flag::TAINTED);
+ return static_cast<common::Flag>(flags);
+}
+
+static common::PolicyFlag getPolicyFlags(int32_t flags) {
+ static_assert(static_cast<common::PolicyFlag>(POLICY_FLAG_WAKE) == common::PolicyFlag::WAKE);
+ static_assert(static_cast<common::PolicyFlag>(POLICY_FLAG_VIRTUAL) ==
+ common::PolicyFlag::VIRTUAL);
+ static_assert(static_cast<common::PolicyFlag>(POLICY_FLAG_FUNCTION) ==
+ common::PolicyFlag::FUNCTION);
+ static_assert(static_cast<common::PolicyFlag>(POLICY_FLAG_GESTURE) ==
+ common::PolicyFlag::GESTURE);
+ static_assert(static_cast<common::PolicyFlag>(POLICY_FLAG_INJECTED) ==
+ common::PolicyFlag::INJECTED);
+ static_assert(static_cast<common::PolicyFlag>(POLICY_FLAG_TRUSTED) ==
+ common::PolicyFlag::TRUSTED);
+ static_assert(static_cast<common::PolicyFlag>(POLICY_FLAG_FILTERED) ==
+ common::PolicyFlag::FILTERED);
+ static_assert(static_cast<common::PolicyFlag>(POLICY_FLAG_DISABLE_KEY_REPEAT) ==
+ common::PolicyFlag::DISABLE_KEY_REPEAT);
+ static_assert(static_cast<common::PolicyFlag>(POLICY_FLAG_INTERACTIVE) ==
+ common::PolicyFlag::INTERACTIVE);
+ static_assert(static_cast<common::PolicyFlag>(POLICY_FLAG_PASS_TO_USER) ==
+ common::PolicyFlag::PASS_TO_USER);
+ return static_cast<common::PolicyFlag>(flags);
+}
+
+static common::EdgeFlag getEdgeFlags(int32_t flags) {
+ static_assert(static_cast<common::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_NONE) ==
+ common::EdgeFlag::NONE);
+ static_assert(static_cast<common::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_TOP) ==
+ common::EdgeFlag::TOP);
+ static_assert(static_cast<common::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_BOTTOM) ==
+ common::EdgeFlag::BOTTOM);
+ static_assert(static_cast<common::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_LEFT) ==
+ common::EdgeFlag::LEFT);
+ static_assert(static_cast<common::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_RIGHT) ==
+ common::EdgeFlag::RIGHT);
+ return static_cast<common::EdgeFlag>(flags);
+}
+
+static common::Meta getMetastate(int32_t state) {
+ static_assert(static_cast<common::Meta>(AMETA_NONE) == common::Meta::NONE);
+ static_assert(static_cast<common::Meta>(AMETA_ALT_ON) == common::Meta::ALT_ON);
+ static_assert(static_cast<common::Meta>(AMETA_ALT_LEFT_ON) == common::Meta::ALT_LEFT_ON);
+ static_assert(static_cast<common::Meta>(AMETA_ALT_RIGHT_ON) == common::Meta::ALT_RIGHT_ON);
+ static_assert(static_cast<common::Meta>(AMETA_SHIFT_ON) == common::Meta::SHIFT_ON);
+ static_assert(static_cast<common::Meta>(AMETA_SHIFT_LEFT_ON) == common::Meta::SHIFT_LEFT_ON);
+ static_assert(static_cast<common::Meta>(AMETA_SHIFT_RIGHT_ON) == common::Meta::SHIFT_RIGHT_ON);
+ static_assert(static_cast<common::Meta>(AMETA_SYM_ON) == common::Meta::SYM_ON);
+ static_assert(static_cast<common::Meta>(AMETA_FUNCTION_ON) == common::Meta::FUNCTION_ON);
+ static_assert(static_cast<common::Meta>(AMETA_CTRL_ON) == common::Meta::CTRL_ON);
+ static_assert(static_cast<common::Meta>(AMETA_CTRL_LEFT_ON) == common::Meta::CTRL_LEFT_ON);
+ static_assert(static_cast<common::Meta>(AMETA_CTRL_RIGHT_ON) == common::Meta::CTRL_RIGHT_ON);
+ static_assert(static_cast<common::Meta>(AMETA_META_ON) == common::Meta::META_ON);
+ static_assert(static_cast<common::Meta>(AMETA_META_LEFT_ON) == common::Meta::META_LEFT_ON);
+ static_assert(static_cast<common::Meta>(AMETA_META_RIGHT_ON) == common::Meta::META_RIGHT_ON);
+ static_assert(static_cast<common::Meta>(AMETA_CAPS_LOCK_ON) == common::Meta::CAPS_LOCK_ON);
+ static_assert(static_cast<common::Meta>(AMETA_NUM_LOCK_ON) == common::Meta::NUM_LOCK_ON);
+ static_assert(static_cast<common::Meta>(AMETA_SCROLL_LOCK_ON) == common::Meta::SCROLL_LOCK_ON);
+ return static_cast<common::Meta>(state);
+}
+
+static common::Button getButtonState(int32_t buttonState) {
+ // No need for static_assert here.
+ // The button values have already been asserted in getActionButton(..) above
+ return static_cast<common::Button>(buttonState);
+}
+
+static common::ToolType getToolType(int32_t toolType) {
+ static_assert(static_cast<common::ToolType>(AMOTION_EVENT_TOOL_TYPE_UNKNOWN) ==
+ common::ToolType::UNKNOWN);
+ static_assert(static_cast<common::ToolType>(AMOTION_EVENT_TOOL_TYPE_FINGER) ==
+ common::ToolType::FINGER);
+ static_assert(static_cast<common::ToolType>(AMOTION_EVENT_TOOL_TYPE_STYLUS) ==
+ common::ToolType::STYLUS);
+ static_assert(static_cast<common::ToolType>(AMOTION_EVENT_TOOL_TYPE_MOUSE) ==
+ common::ToolType::MOUSE);
+ static_assert(static_cast<common::ToolType>(AMOTION_EVENT_TOOL_TYPE_ERASER) ==
+ common::ToolType::ERASER);
+ return static_cast<common::ToolType>(toolType);
+}
+
+// MotionEvent axes asserts
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_X) == common::Axis::X);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_Y) == common::Axis::Y);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_PRESSURE) == common::Axis::PRESSURE);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_SIZE) == common::Axis::SIZE);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_TOUCH_MAJOR) ==
+ common::Axis::TOUCH_MAJOR);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_TOUCH_MINOR) ==
+ common::Axis::TOUCH_MINOR);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_TOOL_MAJOR) == common::Axis::TOOL_MAJOR);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_TOOL_MINOR) == common::Axis::TOOL_MINOR);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_ORIENTATION) ==
+ common::Axis::ORIENTATION);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_VSCROLL) == common::Axis::VSCROLL);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_HSCROLL) == common::Axis::HSCROLL);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_Z) == common::Axis::Z);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_RX) == common::Axis::RX);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_RY) == common::Axis::RY);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_RZ) == common::Axis::RZ);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_HAT_X) == common::Axis::HAT_X);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_HAT_Y) == common::Axis::HAT_Y);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_LTRIGGER) == common::Axis::LTRIGGER);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_RTRIGGER) == common::Axis::RTRIGGER);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_THROTTLE) == common::Axis::THROTTLE);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_RUDDER) == common::Axis::RUDDER);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_WHEEL) == common::Axis::WHEEL);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GAS) == common::Axis::GAS);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_BRAKE) == common::Axis::BRAKE);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_DISTANCE) == common::Axis::DISTANCE);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_TILT) == common::Axis::TILT);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_SCROLL) == common::Axis::SCROLL);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_RELATIVE_X) == common::Axis::RELATIVE_X);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_RELATIVE_Y) == common::Axis::RELATIVE_Y);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_1) == common::Axis::GENERIC_1);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_2) == common::Axis::GENERIC_2);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_3) == common::Axis::GENERIC_3);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_4) == common::Axis::GENERIC_4);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_5) == common::Axis::GENERIC_5);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_6) == common::Axis::GENERIC_6);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_7) == common::Axis::GENERIC_7);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_8) == common::Axis::GENERIC_8);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_9) == common::Axis::GENERIC_9);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_10) == common::Axis::GENERIC_10);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_11) == common::Axis::GENERIC_11);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_12) == common::Axis::GENERIC_12);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_13) == common::Axis::GENERIC_13);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_14) == common::Axis::GENERIC_14);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_15) == common::Axis::GENERIC_15);
+static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_16) == common::Axis::GENERIC_16);
+
+static common::VideoFrame getHalVideoFrame(const TouchVideoFrame& frame) {
+ common::VideoFrame out;
+ out.width = frame.getWidth();
+ out.height = frame.getHeight();
+ std::vector<char16_t> unsignedData(frame.getData().begin(), frame.getData().end());
+ out.data = unsignedData;
+ struct timeval timestamp = frame.getTimestamp();
+ out.timestamp = seconds_to_nanoseconds(timestamp.tv_sec) +
+ microseconds_to_nanoseconds(timestamp.tv_usec);
+ return out;
+}
+
+static std::vector<common::VideoFrame> convertVideoFrames(
+ const std::vector<TouchVideoFrame>& frames) {
+ std::vector<common::VideoFrame> out;
+ for (const TouchVideoFrame& frame : frames) {
+ out.push_back(getHalVideoFrame(frame));
+ }
+ return out;
+}
+
+static void getHalPropertiesAndCoords(const NotifyMotionArgs& args,
+ std::vector<common::PointerProperties>& outPointerProperties,
+ std::vector<common::PointerCoords>& outPointerCoords) {
+ outPointerProperties.reserve(args.pointerCount);
+ outPointerCoords.reserve(args.pointerCount);
+ for (size_t i = 0; i < args.pointerCount; i++) {
+ common::PointerProperties properties;
+ properties.id = args.pointerProperties[i].id;
+ properties.toolType = getToolType(args.pointerProperties[i].toolType);
+ outPointerProperties.push_back(properties);
+
+ common::PointerCoords coords;
+ // OK to copy bits because we have static_assert for pointerCoords axes
+ coords.bits = args.pointerCoords[i].bits;
+ coords.values = std::vector<float>(args.pointerCoords[i].values,
+ args.pointerCoords[i].values +
+ BitSet64::count(args.pointerCoords[i].bits));
+ outPointerCoords.push_back(coords);
+ }
+}
+
+common::MotionEvent notifyMotionArgsToHalMotionEvent(const NotifyMotionArgs& args) {
+ common::MotionEvent event;
+ event.deviceId = args.deviceId;
+ event.source = getSource(args.source);
+ event.displayId = args.displayId;
+ event.downTime = args.downTime;
+ event.eventTime = args.eventTime;
+ event.deviceTimestamp = 0;
+ event.action = getAction(args.action & AMOTION_EVENT_ACTION_MASK);
+ event.actionIndex = MotionEvent::getActionIndex(args.action);
+ event.actionButton = getActionButton(args.actionButton);
+ event.flags = getFlags(args.flags);
+ event.policyFlags = getPolicyFlags(args.policyFlags);
+ event.edgeFlags = getEdgeFlags(args.edgeFlags);
+ event.metaState = getMetastate(args.metaState);
+ event.buttonState = getButtonState(args.buttonState);
+ event.xPrecision = args.xPrecision;
+ event.yPrecision = args.yPrecision;
+
+ std::vector<common::PointerProperties> pointerProperties;
+ std::vector<common::PointerCoords> pointerCoords;
+ getHalPropertiesAndCoords(args, /*out*/ pointerProperties, /*out*/ pointerCoords);
+ event.pointerProperties = pointerProperties;
+ event.pointerCoords = pointerCoords;
+
+ event.frames = convertVideoFrames(args.videoFrames);
+
+ return event;
+}
+
+} // namespace android
diff --git a/services/inputflinger/InputClassifierConverter.h b/services/inputflinger/InputCommonConverter.h
similarity index 65%
rename from services/inputflinger/InputClassifierConverter.h
rename to services/inputflinger/InputCommonConverter.h
index 5154b0b..4d3b768 100644
--- a/services/inputflinger/InputClassifierConverter.h
+++ b/services/inputflinger/InputCommonConverter.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,21 +14,18 @@
* limitations under the License.
*/
-#ifndef _UI_INPUT_CLASSIFIER_CONVERTER_H
-#define _UI_INPUT_CLASSIFIER_CONVERTER_H
+#pragma once
+#include <aidl/android/hardware/input/common/Axis.h>
+#include <aidl/android/hardware/input/common/MotionEvent.h>
#include "InputListener.h"
-#include <android/hardware/input/common/1.0/types.h>
-
namespace android {
/**
- * Convert from framework's NotifyMotionArgs to hidl's common::V1_0::MotionEvent
+ * Convert from framework's NotifyMotionArgs to hidl's common::MotionEvent
*/
-::android::hardware::input::common::V1_0::MotionEvent notifyMotionArgsToHalMotionEvent(
+::aidl::android::hardware::input::common::MotionEvent notifyMotionArgsToHalMotionEvent(
const NotifyMotionArgs& args);
} // namespace android
-
-#endif // _UI_INPUT_CLASSIFIER_CONVERTER_H
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index 7a9862d..7b03631 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -33,8 +33,6 @@
namespace android {
using gui::FocusRequest;
-using gui::WindowInfo;
-using gui::WindowInfoHandle;
static int32_t exceptionCodeFromStatusT(status_t status) {
switch (status) {
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index db67877..8bd3899 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -685,7 +685,7 @@
mEpollFd = epoll_create1(EPOLL_CLOEXEC);
LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance: %s", strerror(errno));
- mINotifyFd = inotify_init();
+ mINotifyFd = inotify_init1(IN_CLOEXEC);
std::error_code errorCode;
bool isDeviceInotifyAdded = false;
@@ -713,7 +713,7 @@
LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance. errno=%d", errno);
int wakeFds[2];
- result = pipe(wakeFds);
+ result = pipe2(wakeFds, O_CLOEXEC);
LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno);
mWakeReadPipeFd = wakeFds[0];
diff --git a/services/inputflinger/reader/TouchVideoDevice.cpp b/services/inputflinger/reader/TouchVideoDevice.cpp
index c7c8e28..2f8138b 100644
--- a/services/inputflinger/reader/TouchVideoDevice.cpp
+++ b/services/inputflinger/reader/TouchVideoDevice.cpp
@@ -49,7 +49,7 @@
};
std::unique_ptr<TouchVideoDevice> TouchVideoDevice::create(std::string devicePath) {
- unique_fd fd(open(devicePath.c_str(), O_RDWR | O_NONBLOCK));
+ unique_fd fd(open(devicePath.c_str(), O_RDWR | O_NONBLOCK | O_CLOEXEC));
if (fd.get() == INVALID_FD) {
ALOGE("Could not open video device %s: %s", devicePath.c_str(), strerror(errno));
return nullptr;
diff --git a/services/inputflinger/tests/InputClassifierConverter_test.cpp b/services/inputflinger/tests/InputClassifierConverter_test.cpp
index f626d56..81ef9b9 100644
--- a/services/inputflinger/tests/InputClassifierConverter_test.cpp
+++ b/services/inputflinger/tests/InputClassifierConverter_test.cpp
@@ -14,13 +14,13 @@
* limitations under the License.
*/
-#include "../InputClassifierConverter.h"
+#include "../InputCommonConverter.h"
#include <gtest/gtest.h>
#include <gui/constants.h>
#include <utils/BitSet.h>
-using namespace android::hardware::input;
+using namespace aidl::android::hardware::input;
namespace android {
@@ -50,8 +50,7 @@
return motionArgs;
}
-static float getMotionEventAxis(common::V1_0::PointerCoords coords,
- common::V1_0::Axis axis) {
+static float getMotionEventAxis(common::PointerCoords coords, common::Axis axis) {
uint32_t index = BitSet64::getIndexOfBit(static_cast<uint64_t>(coords.bits),
static_cast<uint64_t>(axis));
return coords.values[index];
@@ -68,14 +67,14 @@
ASSERT_EQ(0.5, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_SIZE));
ASSERT_EQ(3U, BitSet64::count(motionArgs.pointerCoords[0].bits));
- common::V1_0::MotionEvent motionEvent = notifyMotionArgsToHalMotionEvent(motionArgs);
+ common::MotionEvent motionEvent = notifyMotionArgsToHalMotionEvent(motionArgs);
- ASSERT_EQ(getMotionEventAxis(motionEvent.pointerCoords[0], common::V1_0::Axis::X),
- motionArgs.pointerCoords[0].getX());
- ASSERT_EQ(getMotionEventAxis(motionEvent.pointerCoords[0], common::V1_0::Axis::Y),
- motionArgs.pointerCoords[0].getY());
- ASSERT_EQ(getMotionEventAxis(motionEvent.pointerCoords[0], common::V1_0::Axis::SIZE),
- motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_SIZE));
+ ASSERT_EQ(getMotionEventAxis(motionEvent.pointerCoords[0], common::Axis::X),
+ motionArgs.pointerCoords[0].getX());
+ ASSERT_EQ(getMotionEventAxis(motionEvent.pointerCoords[0], common::Axis::Y),
+ motionArgs.pointerCoords[0].getY());
+ ASSERT_EQ(getMotionEventAxis(motionEvent.pointerCoords[0], common::Axis::SIZE),
+ motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_SIZE));
ASSERT_EQ(BitSet64::count(motionArgs.pointerCoords[0].bits),
BitSet64::count(motionEvent.pointerCoords[0].bits));
}
diff --git a/services/inputflinger/tests/InputClassifier_test.cpp b/services/inputflinger/tests/InputClassifier_test.cpp
index f13187d..3a77127 100644
--- a/services/inputflinger/tests/InputClassifier_test.cpp
+++ b/services/inputflinger/tests/InputClassifier_test.cpp
@@ -20,12 +20,14 @@
#include "TestInputListener.h"
-#include <android/hardware/input/classifier/1.0/IInputClassifier.h>
+#include <aidl/android/hardware/input/processor/BnInputProcessor.h>
+#include <aidl/android/hardware/input/processor/IInputProcessor.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
-using namespace android::hardware::input;
-using android::hardware::Return;
-using android::hardware::Void;
-using android::hardware::input::common::V1_0::Classification;
+using namespace aidl::android::hardware::input;
+using aidl::android::hardware::input::common::Classification;
+using aidl::android::hardware::input::processor::IInputProcessor;
namespace android {
@@ -154,22 +156,17 @@
/**
* A minimal implementation of IInputClassifier.
*/
-struct TestHal : public android::hardware::input::classifier::V1_0::IInputClassifier {
- Return<Classification> classify(
- const android::hardware::input::common::V1_0::MotionEvent& event) override {
- return Classification::NONE;
- };
- Return<void> reset() override { return Void(); };
- Return<void> resetDevice(int32_t deviceId) override { return Void(); };
-};
-
-/**
- * An entity that will be subscribed to the HAL death.
- */
-class TestDeathRecipient : public android::hardware::hidl_death_recipient {
-public:
- virtual void serviceDied(uint64_t cookie,
- const wp<android::hidl::base::V1_0::IBase>& who) override{};
+class TestHal : public aidl::android::hardware::input::processor::BnInputProcessor {
+ ::ndk::ScopedAStatus classify(
+ const ::aidl::android::hardware::input::common::MotionEvent& in_event,
+ ::aidl::android::hardware::input::common::Classification* _aidl_return) override {
+ *_aidl_return = Classification::NONE;
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus reset() override { return ndk::ScopedAStatus::ok(); }
+ ::ndk::ScopedAStatus resetDevice(int32_t in_deviceId) override {
+ return ndk::ScopedAStatus::ok();
+ }
};
// --- MotionClassifierTest ---
@@ -178,15 +175,9 @@
protected:
std::unique_ptr<MotionClassifierInterface> mMotionClassifier;
- virtual void SetUp() override {
- mMotionClassifier = MotionClassifier::create(new TestDeathRecipient());
- if (mMotionClassifier == nullptr) {
- // If the device running this test does not have IInputClassifier service,
- // use the test HAL instead.
- // Using 'new' to access non-public constructor
- mMotionClassifier =
- std::unique_ptr<MotionClassifier>(new MotionClassifier(new TestHal()));
- }
+ void SetUp() override {
+ std::shared_ptr<IInputProcessor> service = ndk::SharedRefBase::make<TestHal>();
+ mMotionClassifier = MotionClassifier::create(std::move(service));
}
};
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 872882e..813acd8 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -21,6 +21,7 @@
#include <android-base/stringprintf.h>
#include <android-base/thread_annotations.h>
#include <binder/Binder.h>
+#include <fcntl.h>
#include <gtest/gtest.h>
#include <input/Input.h>
#include <linux/input.h>
@@ -6224,33 +6225,57 @@
mApp = std::make_shared<FakeApplicationHandle>();
mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
mWindow->setFocusable(true);
+ setFocusedWindow(mWindow);
mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
mSecondWindow->setFocusable(true);
mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
-
- setFocusedWindow(mWindow);
mWindow->consumeFocusEvent(true);
+
+ // Set initial touch mode to InputDispatcher::kDefaultInTouchMode.
+ mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, INJECTOR_PID,
+ INJECTOR_UID, /* hasPermission */ true);
}
void changeAndVerifyTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool hasPermission) {
- mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission);
+ ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission));
mWindow->consumeTouchModeEvent(inTouchMode);
mSecondWindow->consumeTouchModeEvent(inTouchMode);
}
};
-TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchModeOnFocusedWindow) {
+TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
const WindowInfo& windowInfo = *mWindow->getInfo();
changeAndVerifyTouchMode(!InputDispatcher::kDefaultInTouchMode, windowInfo.ownerPid,
windowInfo.ownerUid, /* hasPermission */ false);
}
+TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
+ const WindowInfo& windowInfo = *mWindow->getInfo();
+ int32_t ownerPid = windowInfo.ownerPid;
+ int32_t ownerUid = windowInfo.ownerUid;
+ mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
+ ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
+ ownerUid, /* hasPermission */ false));
+ mWindow->assertNoEvents();
+ mSecondWindow->assertNoEvents();
+}
+
+TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
+ const WindowInfo& windowInfo = *mWindow->getInfo();
+ int32_t ownerPid = windowInfo.ownerPid;
+ int32_t ownerUid = windowInfo.ownerUid;
+ mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
+ changeAndVerifyTouchMode(!InputDispatcher::kDefaultInTouchMode, ownerPid, ownerUid,
+ /* hasPermission */ true);
+}
+
TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
const WindowInfo& windowInfo = *mWindow->getInfo();
- mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, windowInfo.ownerPid,
- windowInfo.ownerUid, /* hasPermission */ true);
+ ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
+ windowInfo.ownerPid, windowInfo.ownerUid,
+ /* hasPermission */ true));
mWindow->assertNoEvents();
mSecondWindow->assertNoEvents();
}
@@ -6331,7 +6356,7 @@
const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
const size_t numChannels = channels.size();
- base::unique_fd epollFd(epoll_create1(0 /*flags*/));
+ base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
if (!epollFd.ok()) {
FAIL() << "Failed to create epoll fd";
}
@@ -6820,7 +6845,4 @@
window->assertNoEvents();
}
-// TODO(b/198487159): Add permission tests for touch mode switch once the validation is put in
-// place.
-
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/tests/UinputDevice.cpp b/services/inputflinger/tests/UinputDevice.cpp
index 132b877..9c93919 100644
--- a/services/inputflinger/tests/UinputDevice.cpp
+++ b/services/inputflinger/tests/UinputDevice.cpp
@@ -17,6 +17,7 @@
#include "UinputDevice.h"
#include <android-base/stringprintf.h>
+#include <fcntl.h>
namespace android {
@@ -32,7 +33,7 @@
}
void UinputDevice::init() {
- mDeviceFd = android::base::unique_fd(open("/dev/uinput", O_WRONLY | O_NONBLOCK));
+ mDeviceFd = android::base::unique_fd(open("/dev/uinput", O_WRONLY | O_NONBLOCK | O_CLOEXEC));
if (mDeviceFd < 0) {
FAIL() << "Can't open /dev/uinput :" << strerror(errno);
}
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 40fc342..02e444d 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -416,8 +416,14 @@
? bufferData.acquireFence
: Fence::NO_FENCE;
mDrawingState.acquireFenceTime = std::make_unique<FenceTime>(mDrawingState.acquireFence);
- // The acquire fences of BufferStateLayers have already signaled before they are set
- mCallbackHandleAcquireTime = mDrawingState.acquireFenceTime->getSignalTime();
+ if (mDrawingState.acquireFenceTime->getSignalTime() == Fence::SIGNAL_TIME_PENDING) {
+ // We latched this buffer unsiganled, so we need to pass the acquire fence
+ // on the callback instead of just the acquire time, since it's unknown at
+ // this point.
+ mCallbackHandleAcquireTimeOrFence = mDrawingState.acquireFence;
+ } else {
+ mCallbackHandleAcquireTimeOrFence = mDrawingState.acquireFenceTime->getSignalTime();
+ }
mDrawingState.modified = true;
setTransactionFlags(eTransactionNeeded);
@@ -527,7 +533,7 @@
// If this layer will be presented in this frame
if (willPresent) {
// If this transaction set an acquire fence on this layer, set its acquire time
- handle->acquireTime = mCallbackHandleAcquireTime;
+ handle->acquireTimeOrFence = mCallbackHandleAcquireTimeOrFence;
handle->frameNumber = mDrawingState.frameNumber;
// Store so latched time and release fence can be set
@@ -540,7 +546,7 @@
}
mReleasePreviousBuffer = false;
- mCallbackHandleAcquireTime = -1;
+ mCallbackHandleAcquireTimeOrFence = -1;
return willPresent;
}
@@ -918,4 +924,183 @@
return mDrawingState.transform.transform(bufferBounds);
}
+bool BufferStateLayer::simpleBufferUpdate(const layer_state_t& s) const {
+ const uint64_t requiredFlags = layer_state_t::eBufferChanged;
+
+ const uint64_t deniedFlags = layer_state_t::eProducerDisconnect | layer_state_t::eLayerChanged |
+ layer_state_t::eRelativeLayerChanged | layer_state_t::eTransparentRegionChanged |
+ layer_state_t::eFlagsChanged | layer_state_t::eBlurRegionsChanged |
+ layer_state_t::eLayerStackChanged | layer_state_t::eAutoRefreshChanged |
+ layer_state_t::eReparent;
+
+ const uint64_t allowedFlags = layer_state_t::eHasListenerCallbacksChanged |
+ layer_state_t::eFrameRateSelectionPriority | layer_state_t::eFrameRateChanged |
+ layer_state_t::eSurfaceDamageRegionChanged | layer_state_t::eApiChanged |
+ layer_state_t::eMetadataChanged | layer_state_t::eDropInputModeChanged |
+ layer_state_t::eInputInfoChanged;
+
+ if ((s.what & requiredFlags) != requiredFlags) {
+ ALOGV("%s: false [missing required flags 0x%" PRIx64 "]", __func__,
+ (s.what | requiredFlags) & ~s.what);
+ return false;
+ }
+
+ if (s.what & deniedFlags) {
+ ALOGV("%s: false [has denied flags 0x%" PRIx64 "]", __func__, s.what & deniedFlags);
+ return false;
+ }
+
+ if (s.what & allowedFlags) {
+ ALOGV("%s: [has allowed flags 0x%" PRIx64 "]", __func__, s.what & allowedFlags);
+ }
+
+ if (s.what & layer_state_t::ePositionChanged) {
+ if (mRequestedTransform.tx() != s.x || mRequestedTransform.ty() != s.y) {
+ ALOGV("%s: false [ePositionChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eAlphaChanged) {
+ if (mDrawingState.color.a != s.alpha) {
+ ALOGV("%s: false [eAlphaChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eColorTransformChanged) {
+ if (mDrawingState.colorTransform != s.colorTransform) {
+ ALOGV("%s: false [eColorTransformChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eBackgroundColorChanged) {
+ if (mDrawingState.bgColorLayer || s.bgColorAlpha != 0) {
+ ALOGV("%s: false [eBackgroundColorChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eMatrixChanged) {
+ if (mRequestedTransform.dsdx() != s.matrix.dsdx ||
+ mRequestedTransform.dtdy() != s.matrix.dtdy ||
+ mRequestedTransform.dtdx() != s.matrix.dtdx ||
+ mRequestedTransform.dsdy() != s.matrix.dsdy) {
+ ALOGV("%s: false [eMatrixChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eCornerRadiusChanged) {
+ if (mDrawingState.cornerRadius != s.cornerRadius) {
+ ALOGV("%s: false [eCornerRadiusChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eBackgroundBlurRadiusChanged) {
+ if (mDrawingState.backgroundBlurRadius != static_cast<int>(s.backgroundBlurRadius)) {
+ ALOGV("%s: false [eBackgroundBlurRadiusChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eTransformChanged) {
+ if (mDrawingState.bufferTransform != s.transform) {
+ ALOGV("%s: false [eTransformChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eTransformToDisplayInverseChanged) {
+ if (mDrawingState.transformToDisplayInverse != s.transformToDisplayInverse) {
+ ALOGV("%s: false [eTransformToDisplayInverseChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eCropChanged) {
+ if (mDrawingState.crop != s.crop) {
+ ALOGV("%s: false [eCropChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eDataspaceChanged) {
+ if (mDrawingState.dataspace != s.dataspace) {
+ ALOGV("%s: false [eDataspaceChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eHdrMetadataChanged) {
+ if (mDrawingState.hdrMetadata != s.hdrMetadata) {
+ ALOGV("%s: false [eHdrMetadataChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eSidebandStreamChanged) {
+ if (mDrawingState.sidebandStream != s.sidebandStream) {
+ ALOGV("%s: false [eSidebandStreamChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eColorSpaceAgnosticChanged) {
+ if (mDrawingState.colorSpaceAgnostic != s.colorSpaceAgnostic) {
+ ALOGV("%s: false [eColorSpaceAgnosticChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eShadowRadiusChanged) {
+ if (mDrawingState.shadowRadius != s.shadowRadius) {
+ ALOGV("%s: false [eShadowRadiusChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eFixedTransformHintChanged) {
+ if (mDrawingState.fixedTransformHint != s.fixedTransformHint) {
+ ALOGV("%s: false [eFixedTransformHintChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eTrustedOverlayChanged) {
+ if (mDrawingState.isTrustedOverlay != s.isTrustedOverlay) {
+ ALOGV("%s: false [eTrustedOverlayChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eStretchChanged) {
+ StretchEffect temp = s.stretchEffect;
+ temp.sanitize();
+ if (mDrawingState.stretchEffect != temp) {
+ ALOGV("%s: false [eStretchChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eBufferCropChanged) {
+ if (mDrawingState.bufferCrop != s.bufferCrop) {
+ ALOGV("%s: false [eBufferCropChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eDestinationFrameChanged) {
+ if (mDrawingState.destinationFrame != s.destinationFrame) {
+ ALOGV("%s: false [eDestinationFrameChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ ALOGV("%s: true", __func__);
+ return true;
+}
+
} // namespace android
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 248e013..669eaad 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -136,6 +136,8 @@
bool bufferNeedsFiltering() const override;
+ bool simpleBufferUpdate(const layer_state_t& s) const override;
+
ReleaseCallbackId mPreviousReleaseCallbackId = ReleaseCallbackId::INVALID_ID;
uint64_t mPreviousReleasedFrameNumber = 0;
@@ -143,7 +145,7 @@
// Stores the last set acquire fence signal time used to populate the callback handle's acquire
// time.
- nsecs_t mCallbackHandleAcquireTime = -1;
+ std::variant<nsecs_t, sp<Fence>> mCallbackHandleAcquireTimeOrFence = -1;
std::deque<std::shared_ptr<android::frametimeline::SurfaceFrame>> mPendingJankClassifications;
// An upper bound on the number of SurfaceFrames in the pending classifications deque.
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index 8ec8f00..719f15c 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -129,6 +129,10 @@
(const, override));
MOCK_METHOD(std::optional<hal::HWDisplayId>, fromPhysicalDisplayId, (PhysicalDisplayId),
(const, override));
+ MOCK_METHOD2(getDisplayDecorationSupport,
+ status_t(PhysicalDisplayId,
+ std::optional<aidl::android::hardware::graphics::common::
+ DisplayDecorationSupport>* support));
};
} // namespace mock
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
index d10468a..04723a2 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
@@ -1074,5 +1074,17 @@
translate<AidlRect>(blocking));
return Error::NONE;
}
+
+Error AidlComposer::getDisplayDecorationSupport(Display display,
+ std::optional<DisplayDecorationSupport>* support) {
+ const auto status =
+ mAidlComposerClient->getDisplayDecorationSupport(translate<int64_t>(display), support);
+ if (!status.isOk()) {
+ ALOGE("getDisplayDecorationSupport failed %s", status.getDescription().c_str());
+ support->reset();
+ return static_cast<Error>(status.getServiceSpecificError());
+ }
+ return Error::NONE;
+}
} // namespace Hwc2
} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
index a9f7606..ed8049a 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
@@ -45,6 +45,7 @@
namespace android::Hwc2 {
+using aidl::android::hardware::graphics::common::DisplayDecorationSupport;
using aidl::android::hardware::graphics::composer3::ComposerClientReader;
using aidl::android::hardware::graphics::composer3::ComposerClientWriter;
@@ -217,6 +218,8 @@
Error setBootDisplayConfig(Display displayId, Config) override;
Error clearBootDisplayConfig(Display displayId) override;
Error getPreferredBootDisplayConfig(Display displayId, Config*) override;
+ Error getDisplayDecorationSupport(Display display,
+ std::optional<DisplayDecorationSupport>* support) override;
private:
// Many public functions above simply write a command into the command
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 5cc5a12..2c5164d 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -31,12 +31,15 @@
#include <ui/GraphicBuffer.h>
#include <utils/StrongPointer.h>
+#include <aidl/android/hardware/graphics/common/DisplayDecorationSupport.h>
#include <aidl/android/hardware/graphics/composer3/Capability.h>
#include <aidl/android/hardware/graphics/composer3/Color.h>
#include <aidl/android/hardware/graphics/composer3/Composition.h>
#include <aidl/android/hardware/graphics/composer3/DisplayCapability.h>
#include <aidl/android/hardware/graphics/composer3/IComposerCallback.h>
+#include <optional>
+
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
@@ -267,6 +270,10 @@
virtual Error setBootDisplayConfig(Display displayId, Config) = 0;
virtual Error clearBootDisplayConfig(Display displayId) = 0;
virtual Error getPreferredBootDisplayConfig(Display displayId, Config*) = 0;
+ virtual Error getDisplayDecorationSupport(
+ Display display,
+ std::optional<::aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
+ support) = 0;
};
} // namespace Hwc2
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index b59b333..50a6604 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -581,6 +581,13 @@
return static_cast<Error>(error);
}
+Error Display::getDisplayDecorationSupport(
+ std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
+ support) {
+ const auto error = mComposer.getDisplayDecorationSupport(mId, support);
+ return static_cast<Error>(error);
+}
+
// For use by Device
void Display::setConnected(bool connected) {
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index b183924..f03aafc 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -37,6 +37,7 @@
#include "ComposerHal.h"
#include "Hal.h"
+#include <aidl/android/hardware/graphics/common/DisplayDecorationSupport.h>
#include <aidl/android/hardware/graphics/composer3/Capability.h>
#include <aidl/android/hardware/graphics/composer3/Color.h>
#include <aidl/android/hardware/graphics/composer3/Composition.h>
@@ -162,6 +163,9 @@
[[clang::warn_unused_result]] virtual hal::Error setContentType(hal::ContentType) = 0;
[[clang::warn_unused_result]] virtual hal::Error getClientTargetProperty(
hal::ClientTargetProperty* outClientTargetProperty, float* outWhitePointNits) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error getDisplayDecorationSupport(
+ std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
+ support) = 0;
};
namespace impl {
@@ -235,6 +239,9 @@
hal::Error setContentType(hal::ContentType) override;
hal::Error getClientTargetProperty(hal::ClientTargetProperty* outClientTargetProperty,
float* outWhitePointNits) override;
+ hal::Error getDisplayDecorationSupport(
+ std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
+ support) override;
// Other Display methods
hal::HWDisplayId getId() const override { return mId; }
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 0ed4ec9..6a3162e 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -785,6 +785,22 @@
return displayModeId;
}
+status_t HWComposer::getDisplayDecorationSupport(
+ PhysicalDisplayId displayId,
+ std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
+ support) {
+ RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
+ const auto error = mDisplayData[displayId].hwcDisplay->getDisplayDecorationSupport(support);
+ if (error == hal::Error::UNSUPPORTED) {
+ RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
+ }
+ if (error == hal::Error::BAD_PARAMETER) {
+ RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
+ }
+ RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
+ return NO_ERROR;
+}
+
status_t HWComposer::setAutoLowLatencyMode(PhysicalDisplayId displayId, bool on) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
const auto error = mDisplayData[displayId].hwcDisplay->setAutoLowLatencyMode(on);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 1376f51..916c4b7 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -43,6 +43,7 @@
#include "HWC2.h"
#include "Hal.h"
+#include <aidl/android/hardware/graphics/common/DisplayDecorationSupport.h>
#include <aidl/android/hardware/graphics/composer3/Capability.h>
#include <aidl/android/hardware/graphics/composer3/Composition.h>
#include <aidl/android/hardware/graphics/composer3/DisplayCapability.h>
@@ -262,6 +263,10 @@
virtual status_t setBootDisplayMode(PhysicalDisplayId, hal::HWConfigId) = 0;
virtual status_t clearBootDisplayMode(PhysicalDisplayId) = 0;
virtual std::optional<hal::HWConfigId> getPreferredBootDisplayMode(PhysicalDisplayId) = 0;
+ virtual status_t getDisplayDecorationSupport(
+ PhysicalDisplayId,
+ std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
+ support) = 0;
};
namespace impl {
@@ -393,6 +398,10 @@
status_t setBootDisplayMode(PhysicalDisplayId, hal::HWConfigId) override;
status_t clearBootDisplayMode(PhysicalDisplayId) override;
std::optional<hal::HWConfigId> getPreferredBootDisplayMode(PhysicalDisplayId) override;
+ status_t getDisplayDecorationSupport(
+ PhysicalDisplayId,
+ std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
+ support) override;
// for debugging ----------------------------------------------------------
void dump(std::string& out) const override;
diff --git a/services/surfaceflinger/DisplayHardware/Hal.h b/services/surfaceflinger/DisplayHardware/Hal.h
index 40c9761..4737034 100644
--- a/services/surfaceflinger/DisplayHardware/Hal.h
+++ b/services/surfaceflinger/DisplayHardware/Hal.h
@@ -135,8 +135,8 @@
return "AutoLowLatencyMode";
case aidl::android::hardware::graphics::composer3::DisplayCapability::SUSPEND:
return "Suspend";
- case aidl::android::hardware::graphics::composer3::DisplayCapability::DISPLAY_DECORATION:
- return "DisplayDecoration";
+ case aidl::android::hardware::graphics::composer3::DisplayCapability::DISPLAY_IDLE_TIMER:
+ return "DisplayIdleTimer";
default:
return "Unknown";
}
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
index 25f03be..e33f1e0 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
@@ -1312,6 +1312,14 @@
return Error::NONE;
}
+Error HidlComposer::getDisplayDecorationSupport(
+ Display,
+ std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
+ support) {
+ support->reset();
+ return Error::UNSUPPORTED;
+}
+
void HidlComposer::registerCallback(ComposerCallback& callback) {
const bool vsyncSwitchingSupported =
isSupported(Hwc2::Composer::OptionalFeature::RefreshRateSwitching);
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
index 0f15598..6b33945 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
@@ -327,6 +327,10 @@
Error setBootDisplayConfig(Display displayId, Config) override;
Error clearBootDisplayConfig(Display displayId) override;
Error getPreferredBootDisplayConfig(Display displayId, Config*) override;
+ Error getDisplayDecorationSupport(
+ Display display,
+ std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
+ support) override;
private:
class CommandWriter : public CommandWriterBase {
diff --git a/services/surfaceflinger/FlagManager.cpp b/services/surfaceflinger/FlagManager.cpp
index 7602e6d..e09a192 100644
--- a/services/surfaceflinger/FlagManager.cpp
+++ b/services/surfaceflinger/FlagManager.cpp
@@ -19,8 +19,10 @@
#include <SurfaceFlingerProperties.sysprop.h>
#include <android-base/parsebool.h>
#include <android-base/parseint.h>
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <log/log.h>
+#include <renderengine/RenderEngine.h>
#include <server_configurable_flags/get_flags.h>
#include <cinttypes>
@@ -34,6 +36,7 @@
base::StringAppendF(&result, "FlagManager values: \n");
base::StringAppendF(&result, "demo_flag: %" PRId64 "\n", demo_flag());
base::StringAppendF(&result, "use_adpf_cpu_hint: %s\n", use_adpf_cpu_hint() ? "true" : "false");
+ base::StringAppendF(&result, "use_skia_tracing: %s\n", use_skia_tracing() ? "true" : "false");
}
namespace {
@@ -97,4 +100,11 @@
return getValue("AdpfFeature__adpf_cpu_hint", sysPropVal, false);
}
+bool FlagManager::use_skia_tracing() const {
+ ALOGD("use_skia_tracing ?");
+ std::optional<bool> sysPropVal =
+ doParse<bool>(base::GetProperty(PROPERTY_SKIA_ATRACE_ENABLED, "").c_str());
+ return getValue("SkiaTracingFeature__use_skia_tracing", sysPropVal, false);
+}
+
} // namespace android
diff --git a/services/surfaceflinger/FlagManager.h b/services/surfaceflinger/FlagManager.h
index 24d83a2..e834142 100644
--- a/services/surfaceflinger/FlagManager.h
+++ b/services/surfaceflinger/FlagManager.h
@@ -33,6 +33,8 @@
bool use_adpf_cpu_hint() const;
+ bool use_skia_tracing() const;
+
private:
friend class FlagManagerTest;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index ddcd641..e51af1e 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -897,6 +897,8 @@
virtual std::string getPendingBufferCounterName() { return ""; }
virtual bool updateGeometry() { return false; }
+ virtual bool simpleBufferUpdate(const layer_state_t&) const { return false; }
+
protected:
friend class impl::SurfaceInterceptor;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index b76233c..980d1dc 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -141,6 +141,7 @@
#include "android-base/stringprintf.h"
#include "android-base/strings.h"
+#include <aidl/android/hardware/graphics/common/DisplayDecorationSupport.h>
#include <aidl/android/hardware/graphics/composer3/DisplayCapability.h>
#define MAIN_THREAD ACQUIRE(mStateLock) RELEASE(mStateLock)
@@ -163,6 +164,7 @@
#define NO_THREAD_SAFETY_ANALYSIS \
_Pragma("GCC error \"Prefer MAIN_THREAD macros or {Conditional,Timed,Unnecessary}Lock.\"")
+using aidl::android::hardware::graphics::common::DisplayDecorationSupport;
using aidl::android::hardware::graphics::composer3::Capability;
using aidl::android::hardware::graphics::composer3::DisplayCapability;
@@ -498,8 +500,6 @@
mRefreshRateOverlaySpinner = property_get_bool("sf.debug.show_refresh_rate_overlay_spinner", 0);
- enableLatchUnsignaledConfig = getLatchUnsignaledConfig();
-
if (!mIsUserBuild && base::GetBoolProperty("debug.sf.enable_transaction_tracing"s, true)) {
mTransactionTracing.emplace();
}
@@ -508,11 +508,13 @@
LatchUnsignaledConfig SurfaceFlinger::getLatchUnsignaledConfig() {
if (base::GetBoolProperty("debug.sf.latch_unsignaled"s, false)) {
return LatchUnsignaledConfig::Always;
- } else if (base::GetBoolProperty("debug.sf.auto_latch_unsignaled"s, false)) {
- return LatchUnsignaledConfig::Auto;
- } else {
- return LatchUnsignaledConfig::Disabled;
}
+
+ if (base::GetBoolProperty("debug.sf.auto_latch_unsignaled"s, false)) {
+ return LatchUnsignaledConfig::AutoSingleLayer;
+ }
+
+ return LatchUnsignaledConfig::Disabled;
}
SurfaceFlinger::~SurfaceFlinger() = default;
@@ -713,6 +715,7 @@
mFlagManager = std::make_unique<android::FlagManager>();
mFrameTracer->initialize();
mFrameTimeline->onBootFinished();
+ getRenderEngine().setEnableTracing(mFlagManager->use_skia_tracing());
// wait patiently for the window manager death
const String16 name("window");
@@ -853,6 +856,8 @@
mCompositionEngine->getHwComposer().setCallback(*this);
ClientCache::getInstance().setRenderEngine(&getRenderEngine());
+ enableLatchUnsignaledConfig = getLatchUnsignaledConfig();
+
if (base::GetBoolProperty("debug.sf.enable_hwc_vds"s, false)) {
enableHalVirtualDisplays(true);
}
@@ -1813,8 +1818,9 @@
return NO_ERROR;
}
-status_t SurfaceFlinger::getDisplayDecorationSupport(const sp<IBinder>& displayToken,
- bool* outSupport) const {
+status_t SurfaceFlinger::getDisplayDecorationSupport(
+ const sp<IBinder>& displayToken,
+ std::optional<DisplayDecorationSupport>* outSupport) const {
if (!displayToken || !outSupport) {
return BAD_VALUE;
}
@@ -1825,8 +1831,7 @@
if (!displayId) {
return NAME_NOT_FOUND;
}
- *outSupport =
- getHwComposer().hasDisplayCapability(*displayId, DisplayCapability::DISPLAY_DECORATION);
+ getHwComposer().getDisplayDecorationSupport(*displayId, outSupport);
return NO_ERROR;
}
@@ -2357,9 +2362,11 @@
// something (such as user input) to an accurate diasplay time.
// Snapping also allows an app to precisely calculate
// mVsyncConfiguration->getCurrentConfigs().late.sf with (presentLatency % interval).
- nsecs_t bias = stats.vsyncPeriod / 2;
- int64_t extraVsyncs = (compositeToPresentLatency - idealLatency + bias) / stats.vsyncPeriod;
- nsecs_t snappedCompositeToPresentLatency =
+ const nsecs_t bias = stats.vsyncPeriod / 2;
+ const int64_t extraVsyncs = (stats.vsyncPeriod) > 0 ?
+ ((compositeToPresentLatency - idealLatency + bias) / stats.vsyncPeriod) :
+ 0;
+ const nsecs_t snappedCompositeToPresentLatency =
(extraVsyncs > 0) ? idealLatency + (extraVsyncs * stats.vsyncPeriod) : idealLatency;
std::lock_guard<std::mutex> lock(getBE().mCompositorTimingLock);
@@ -3640,6 +3647,19 @@
return old;
}
+bool SurfaceFlinger::stopTransactionProcessing(
+ const std::unordered_set<sp<IBinder>, SpHash<IBinder>>&
+ applyTokensWithUnsignaledTransactions) const {
+ if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::AutoSingleLayer) {
+ // if we are in LatchUnsignaledConfig::AutoSingleLayer
+ // then we should have only one applyToken for processing.
+ // so we can stop further transactions on this applyToken.
+ return !applyTokensWithUnsignaledTransactions.empty();
+ }
+
+ return false;
+}
+
bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) {
// to prevent onHandleDestroyed from being called while the lock is held,
// we must keep a copy of the transactions (specifically the composer
@@ -3647,44 +3667,42 @@
std::vector<TransactionState> transactions;
// Layer handles that have transactions with buffers that are ready to be applied.
std::unordered_set<sp<IBinder>, SpHash<IBinder>> bufferLayersReadyToPresent;
+ std::unordered_set<sp<IBinder>, SpHash<IBinder>> applyTokensWithUnsignaledTransactions;
{
Mutex::Autolock _l(mStateLock);
{
Mutex::Autolock _l(mQueueLock);
- // allowLatchUnsignaled acts as a filter condition when latch unsignaled is either auto
- // or always. auto: in this case we let buffer latch unsignaled if we have only one
- // applyToken and if only first transaction is latch unsignaled. If more than one
- // applyToken we don't latch unsignaled.
- bool allowLatchUnsignaled = allowedLatchUnsignaled();
- bool isFirstUnsignaledTransactionApplied = false;
// Collect transactions from pending transaction queue.
auto it = mPendingTransactionQueues.begin();
while (it != mPendingTransactionQueues.end()) {
auto& [applyToken, transactionQueue] = *it;
while (!transactionQueue.empty()) {
+ if (stopTransactionProcessing(applyTokensWithUnsignaledTransactions)) {
+ break;
+ }
+
auto& transaction = transactionQueue.front();
- if (!transactionIsReadyToBeApplied(transaction.frameTimelineInfo,
- transaction.isAutoTimestamp,
- transaction.desiredPresentTime,
- transaction.originUid, transaction.states,
- bufferLayersReadyToPresent,
- allowLatchUnsignaled)) {
+ const auto ready =
+ transactionIsReadyToBeApplied(transaction.frameTimelineInfo,
+ transaction.isAutoTimestamp,
+ transaction.desiredPresentTime,
+ transaction.originUid, transaction.states,
+ bufferLayersReadyToPresent,
+ transactions.size());
+ if (ready == TransactionReadiness::NotReady) {
setTransactionFlags(eTransactionFlushNeeded);
break;
}
transaction.traverseStatesWithBuffers([&](const layer_state_t& state) {
bufferLayersReadyToPresent.insert(state.surface);
});
+ const bool appliedUnsignaled = (ready == TransactionReadiness::ReadyUnsignaled);
+ if (appliedUnsignaled) {
+ applyTokensWithUnsignaledTransactions.insert(transaction.applyToken);
+ }
+
transactions.emplace_back(std::move(transaction));
transactionQueue.pop();
- if (allowLatchUnsignaled &&
- enableLatchUnsignaledConfig == LatchUnsignaledConfig::Auto) {
- // if allowLatchUnsignaled && we are in LatchUnsignaledConfig::Auto
- // then we should have only one applyToken for processing.
- // so we can stop further transactions on this applyToken.
- isFirstUnsignaledTransactionApplied = true;
- break;
- }
}
if (transactionQueue.empty()) {
@@ -3702,25 +3720,34 @@
// Case 3: others are the transactions that are ready to apply.
while (!mTransactionQueue.empty()) {
auto& transaction = mTransactionQueue.front();
- bool pendingTransactions = mPendingTransactionQueues.find(transaction.applyToken) !=
+ const bool pendingTransactions =
+ mPendingTransactionQueues.find(transaction.applyToken) !=
mPendingTransactionQueues.end();
- if (isFirstUnsignaledTransactionApplied || pendingTransactions ||
- !transactionIsReadyToBeApplied(transaction.frameTimelineInfo,
- transaction.isAutoTimestamp,
- transaction.desiredPresentTime,
- transaction.originUid, transaction.states,
- bufferLayersReadyToPresent,
- allowLatchUnsignaled)) {
+ const auto ready = [&]() REQUIRES(mStateLock) {
+ if (pendingTransactions ||
+ stopTransactionProcessing(applyTokensWithUnsignaledTransactions)) {
+ return TransactionReadiness::NotReady;
+ }
+
+ return transactionIsReadyToBeApplied(transaction.frameTimelineInfo,
+ transaction.isAutoTimestamp,
+ transaction.desiredPresentTime,
+ transaction.originUid, transaction.states,
+ bufferLayersReadyToPresent,
+ transactions.size());
+ }();
+
+ if (ready == TransactionReadiness::NotReady) {
mPendingTransactionQueues[transaction.applyToken].push(std::move(transaction));
} else {
transaction.traverseStatesWithBuffers([&](const layer_state_t& state) {
bufferLayersReadyToPresent.insert(state.surface);
});
- transactions.emplace_back(std::move(transaction));
- if (allowLatchUnsignaled &&
- enableLatchUnsignaledConfig == LatchUnsignaledConfig::Auto) {
- isFirstUnsignaledTransactionApplied = true;
+ const bool appliedUnsignaled = (ready == TransactionReadiness::ReadyUnsignaled);
+ if (appliedUnsignaled) {
+ applyTokensWithUnsignaledTransactions.insert(transaction.applyToken);
}
+ transactions.emplace_back(std::move(transaction));
}
mTransactionQueue.pop_front();
ATRACE_INT("TransactionQueue", mTransactionQueue.size());
@@ -3757,62 +3784,6 @@
return needsTraversal;
}
-bool SurfaceFlinger::allowedLatchUnsignaled() {
- if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::Disabled) {
- return false;
- }
- // Always mode matches the current latch unsignaled behavior.
- // This behavior is currently used by the partners and we would like
- // to keep it until we are completely migrated to Auto mode successfully
- // and we we have our fallback based implementation in place.
- if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::Always) {
- return true;
- }
-
- // if enableLatchUnsignaledConfig == LatchUnsignaledConfig::Auto
- // we don't latch unsignaled if more than one applyToken, as it can backpressure
- // the other transactions.
- if (mPendingTransactionQueues.size() > 1) {
- return false;
- }
- std::optional<sp<IBinder>> applyToken = std::nullopt;
- bool isPendingTransactionQueuesItem = false;
- if (!mPendingTransactionQueues.empty()) {
- applyToken = mPendingTransactionQueues.begin()->first;
- isPendingTransactionQueuesItem = true;
- }
-
- for (const auto& item : mTransactionQueue) {
- if (!applyToken.has_value()) {
- applyToken = item.applyToken;
- } else if (applyToken.has_value() && applyToken != item.applyToken) {
- return false;
- }
- }
-
- if (isPendingTransactionQueuesItem) {
- return checkTransactionCanLatchUnsignaled(
- mPendingTransactionQueues.begin()->second.front());
- } else if (applyToken.has_value()) {
- return checkTransactionCanLatchUnsignaled((mTransactionQueue.front()));
- }
- return false;
-}
-
-bool SurfaceFlinger::checkTransactionCanLatchUnsignaled(const TransactionState& transaction) {
- if (transaction.states.size() == 1) {
- const auto& state = transaction.states.begin()->state;
- if ((state.flags & ~layer_state_t::eBufferChanged) == 0 &&
- state.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged) &&
- state.bufferData->acquireFence &&
- state.bufferData->acquireFence->getStatus() == Fence::Status::Unsignaled) {
- ATRACE_NAME("transactionCanLatchUnsignaled");
- return true;
- }
- }
- return false;
-}
-
bool SurfaceFlinger::transactionFlushNeeded() {
Mutex::Autolock _l(mQueueLock);
return !mPendingTransactionQueues.empty() || !mTransactionQueue.empty();
@@ -3839,12 +3810,46 @@
return prediction->presentTime >= expectedPresentTime &&
prediction->presentTime - expectedPresentTime >= earlyLatchVsyncThreshold;
}
+bool SurfaceFlinger::shouldLatchUnsignaled(const sp<Layer>& layer, const layer_state_t& state,
+ size_t numStates, size_t totalTXapplied) {
+ if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::Disabled) {
+ ALOGV("%s: false (LatchUnsignaledConfig::Disabled)", __func__);
+ return false;
+ }
-bool SurfaceFlinger::transactionIsReadyToBeApplied(
+ if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::Always) {
+ ALOGV("%s: true (LatchUnsignaledConfig::Always)", __func__);
+ return true;
+ }
+
+ // We only want to latch unsignaled when a single layer is updated in this
+ // transaction (i.e. not a blast sync transaction).
+ if (numStates != 1) {
+ ALOGV("%s: false (numStates=%zu)", __func__, numStates);
+ return false;
+ }
+
+ if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::AutoSingleLayer &&
+ totalTXapplied > 0) {
+ ALOGV("%s: false (LatchUnsignaledConfig::AutoSingleLayer; totalTXapplied=%zu)", __func__,
+ totalTXapplied);
+ return false;
+ }
+
+ if (!layer->simpleBufferUpdate(state)) {
+ ALOGV("%s: false (!simpleBufferUpdate)", __func__);
+ return false;
+ }
+
+ ALOGV("%s: true", __func__);
+ return true;
+}
+
+auto SurfaceFlinger::transactionIsReadyToBeApplied(
const FrameTimelineInfo& info, bool isAutoTimestamp, int64_t desiredPresentTime,
uid_t originUid, const Vector<ComposerState>& states,
const std::unordered_set<sp<IBinder>, SpHash<IBinder>>& bufferLayersReadyToPresent,
- bool allowLatchUnsignaled) const {
+ size_t totalTXapplied) const -> TransactionReadiness {
ATRACE_FORMAT("transactionIsReadyToBeApplied vsyncId: %" PRId64, info.vsyncId);
const nsecs_t expectedPresentTime = mExpectedPresentTime.load();
// Do not present if the desiredPresentTime has not passed unless it is more than one second
@@ -3852,31 +3857,24 @@
if (!isAutoTimestamp && desiredPresentTime >= expectedPresentTime &&
desiredPresentTime < expectedPresentTime + s2ns(1)) {
ATRACE_NAME("not current");
- return false;
+ return TransactionReadiness::NotReady;
}
if (!mScheduler->isVsyncValid(expectedPresentTime, originUid)) {
ATRACE_NAME("!isVsyncValid");
- return false;
+ return TransactionReadiness::NotReady;
}
// If the client didn't specify desiredPresentTime, use the vsyncId to determine the expected
// present time of this transaction.
if (isAutoTimestamp && frameIsEarly(expectedPresentTime, info.vsyncId)) {
ATRACE_NAME("frameIsEarly");
- return false;
+ return TransactionReadiness::NotReady;
}
+ bool fenceUnsignaled = false;
for (const ComposerState& state : states) {
const layer_state_t& s = state.state;
- const bool acquireFenceChanged = s.bufferData &&
- s.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged);
- if (acquireFenceChanged && s.bufferData->acquireFence && !allowLatchUnsignaled &&
- s.bufferData->acquireFence->getStatus() == Fence::Status::Unsignaled) {
- ATRACE_NAME("fence unsignaled");
- return false;
- }
-
sp<Layer> layer = nullptr;
if (s.surface) {
layer = fromHandle(s.surface).promote();
@@ -3890,6 +3888,22 @@
ATRACE_NAME(layer->getName().c_str());
+ const bool allowLatchUnsignaled =
+ shouldLatchUnsignaled(layer, s, states.size(), totalTXapplied);
+ ATRACE_INT("allowLatchUnsignaled", allowLatchUnsignaled);
+
+ const bool acquireFenceChanged = s.bufferData &&
+ s.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged) &&
+ s.bufferData->acquireFence;
+ fenceUnsignaled = fenceUnsignaled ||
+ (acquireFenceChanged &&
+ s.bufferData->acquireFence->getStatus() == Fence::Status::Unsignaled);
+
+ if (fenceUnsignaled && !allowLatchUnsignaled) {
+ ATRACE_NAME("fence unsignaled");
+ return TransactionReadiness::NotReady;
+ }
+
if (s.hasBufferChanges()) {
// If backpressure is enabled and we already have a buffer to commit, keep the
// transaction in the queue.
@@ -3897,11 +3911,11 @@
bufferLayersReadyToPresent.find(s.surface) != bufferLayersReadyToPresent.end();
if (layer->backpressureEnabled() && hasPendingBuffer && isAutoTimestamp) {
ATRACE_NAME("hasPendingBuffer");
- return false;
+ return TransactionReadiness::NotReady;
}
}
}
- return true;
+ return fenceUnsignaled ? TransactionReadiness::ReadyUnsignaled : TransactionReadiness::Ready;
}
void SurfaceFlinger::queueTransaction(TransactionState& state) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index b95cd91..9525573 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -85,6 +85,8 @@
#include <unordered_set>
#include <utility>
+#include <aidl/android/hardware/graphics/common/DisplayDecorationSupport.h>
+
using namespace android::surfaceflinger;
namespace android {
@@ -137,7 +139,20 @@
eTransactionMask = 0x1f,
};
-enum class LatchUnsignaledConfig { Always, Auto, Disabled };
+// Latch Unsignaled buffer behaviours
+enum class LatchUnsignaledConfig {
+ // All buffers are latched signaled.
+ Disabled,
+
+ // Latch unsignaled is permitted when a single layer is updated in a frame,
+ // and the update includes just a buffer update (i.e. no sync transactions
+ // or geometry changes).
+ AutoSingleLayer,
+
+ // All buffers are latched unsignaled. This behaviour is discouraged as it
+ // can break sync transactions, stall the display and cause undesired side effects.
+ Always,
+};
using DisplayColorSetting = compositionengine::OutputColorSetting;
@@ -596,8 +611,10 @@
status_t notifyPowerBoost(int32_t boostId) override;
status_t setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor,
float lightPosY, float lightPosZ, float lightRadius) override;
- status_t getDisplayDecorationSupport(const sp<IBinder>& displayToken,
- bool* outSupport) const override;
+ status_t getDisplayDecorationSupport(
+ const sp<IBinder>& displayToken,
+ std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
+ outSupport) const override;
status_t setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,
int8_t compatibility, int8_t changeFrameRateStrategy) override;
@@ -749,16 +766,21 @@
uint32_t setTransactionFlags(uint32_t mask, TransactionSchedule,
const sp<IBinder>& applyToken = {});
void commitOffscreenLayers();
- bool transactionIsReadyToBeApplied(
+ enum class TransactionReadiness {
+ NotReady,
+ Ready,
+ ReadyUnsignaled,
+ };
+ TransactionReadiness transactionIsReadyToBeApplied(
const FrameTimelineInfo& info, bool isAutoTimestamp, int64_t desiredPresentTime,
uid_t originUid, const Vector<ComposerState>& states,
const std::unordered_set<sp<IBinder>, SpHash<IBinder>>& bufferLayersReadyToPresent,
- bool allowLatchUnsignaled) const REQUIRES(mStateLock);
+ size_t totalTXapplied) const REQUIRES(mStateLock);
static LatchUnsignaledConfig getLatchUnsignaledConfig();
- bool latchUnsignaledIsAllowed(std::vector<TransactionState>& transactions) REQUIRES(mStateLock);
- bool allowedLatchUnsignaled() REQUIRES(mQueueLock, mStateLock);
- bool checkTransactionCanLatchUnsignaled(const TransactionState& transaction)
- REQUIRES(mStateLock);
+ static bool shouldLatchUnsignaled(const sp<Layer>& layer, const layer_state_t&,
+ size_t numStates, size_t totalTXapplied);
+ bool stopTransactionProcessing(const std::unordered_set<sp<IBinder>, SpHash<IBinder>>&
+ applyTokensWithUnsignaledTransactions) const;
bool applyTransactions(std::vector<TransactionState>& transactions, int64_t vsyncId)
REQUIRES(mStateLock);
uint32_t setDisplayStateLocked(const DisplayState& s) REQUIRES(mStateLock);
diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp
index b705d9c..e1f348f 100644
--- a/services/surfaceflinger/TransactionCallbackInvoker.cpp
+++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp
@@ -167,7 +167,7 @@
handle->gpuCompositionDoneFence->getSnapshot().fence,
handle->compositorTiming, handle->refreshStartTime,
handle->dequeueReadyTime);
- transactionStats->surfaceStats.emplace_back(surfaceControl, handle->acquireTime,
+ transactionStats->surfaceStats.emplace_back(surfaceControl, handle->acquireTimeOrFence,
handle->previousReleaseFence,
handle->transformHint,
handle->currentMaxAcquiredBufferCount,
diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h
index 5ef5475..a68cd87 100644
--- a/services/surfaceflinger/TransactionCallbackInvoker.h
+++ b/services/surfaceflinger/TransactionCallbackInvoker.h
@@ -47,7 +47,7 @@
std::string name;
sp<Fence> previousReleaseFence;
std::vector<std::shared_future<renderengine::RenderEngineResult>> previousReleaseFences;
- nsecs_t acquireTime = -1;
+ std::variant<nsecs_t, sp<Fence>> acquireTimeOrFence = -1;
nsecs_t latchTime = -1;
uint32_t transformHint = 0;
uint32_t currentMaxAcquiredBufferCount = 0;
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
index 4f89cd9..30a6fbd 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
@@ -25,7 +25,7 @@
static constexpr LatchUnsignaledConfig kLatchUnsignaledConfig[] = {
LatchUnsignaledConfig::Always,
- LatchUnsignaledConfig::Auto,
+ LatchUnsignaledConfig::AutoSingleLayer,
LatchUnsignaledConfig::Disabled,
};
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index ed23176..4683c51 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -72,13 +72,6 @@
EXPECT_CALL(*mVSyncTracker, currentPeriod())
.WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
- EXPECT_CALL(*mFenceUnsignaled, getStatus())
- .WillRepeatedly(Return(Fence::Status::Unsignaled));
- EXPECT_CALL(*mFenceUnsignaled2, getStatus())
- .WillRepeatedly(Return(Fence::Status::Unsignaled));
- EXPECT_CALL(*mFenceSignaled, getStatus()).WillRepeatedly(Return(Fence::Status::Signaled));
- EXPECT_CALL(*mFenceSignaled2, getStatus()).WillRepeatedly(Return(Fence::Status::Signaled));
-
mFlinger.setupComposer(std::make_unique<Hwc2::mock::Composer>());
mFlinger.setupScheduler(std::unique_ptr<mock::VsyncController>(mVsyncController),
std::unique_ptr<mock::VSyncTracker>(mVSyncTracker),
@@ -89,10 +82,6 @@
mock::VsyncController* mVsyncController = new mock::VsyncController();
mock::VSyncTracker* mVSyncTracker = new mock::VSyncTracker();
- sp<mock::MockFence> mFenceUnsignaled = sp<mock::MockFence>::make();
- sp<mock::MockFence> mFenceSignaled = sp<mock::MockFence>::make();
- sp<mock::MockFence> mFenceUnsignaled2 = sp<mock::MockFence>::make();
- sp<mock::MockFence> mFenceSignaled2 = sp<mock::MockFence>::make();
struct TransactionInfo {
Vector<ComposerState> states;
@@ -129,15 +118,6 @@
transaction.frameTimelineInfo = frameTimelineInfo;
}
- void setupSingleWithComposer(TransactionInfo& transaction, uint32_t flags,
- bool syncInputWindows, int64_t desiredPresentTime,
- bool isAutoTimestamp, const FrameTimelineInfo& frameTimelineInfo,
- const Vector<ComposerState>* states) {
- setupSingle(transaction, flags, syncInputWindows, desiredPresentTime, isAutoTimestamp,
- frameTimelineInfo);
- transaction.states = *states;
- }
-
void NotPlacedOnTransactionQueue(uint32_t flags, bool syncInputWindows) {
ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
@@ -263,189 +243,6 @@
EXPECT_EQ(0u, transactionQueue.size());
}
- void Flush_removesUnsignaledFromTheQueue(Vector<ComposerState> state1,
- Vector<ComposerState> state2,
- bool updateApplyToken = true) {
- ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
-
- TransactionInfo transactionA;
- setupSingleWithComposer(transactionA, ISurfaceComposer::eSynchronous,
- /*syncInputWindows*/ false,
- /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true,
- FrameTimelineInfo{}, &state1);
-
- mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
- transactionA.displays, transactionA.flags,
- transactionA.applyToken, transactionA.inputWindowCommands,
- transactionA.desiredPresentTime, transactionA.isAutoTimestamp,
- transactionA.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
- transactionA.id);
-
- TransactionInfo transactionB;
- if (updateApplyToken) {
- transactionB.applyToken = sp<IBinder>();
- }
- setupSingleWithComposer(transactionB, ISurfaceComposer::eSynchronous,
- /*syncInputWindows*/ false,
- /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true,
- FrameTimelineInfo{}, &state2);
- mFlinger.setTransactionState(transactionB.frameTimelineInfo, transactionB.states,
- transactionB.displays, transactionB.flags,
- transactionB.applyToken, transactionB.inputWindowCommands,
- transactionB.desiredPresentTime, transactionB.isAutoTimestamp,
- transactionB.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
- transactionB.id);
-
- mFlinger.flushTransactionQueues();
- EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size());
- EXPECT_EQ(0u, mFlinger.getTransactionQueue().size());
- EXPECT_EQ(2ul, mFlinger.getTransactionCommittedSignals().size());
- }
-
- void Flush_removesFromTheQueue(const Vector<ComposerState>& state) {
- ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
- EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size());
-
- TransactionInfo transaction;
- setupSingleWithComposer(transaction, ISurfaceComposer::eSynchronous,
- /*syncInputWindows*/ false,
- /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true,
- FrameTimelineInfo{}, &state);
-
- mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states,
- transaction.displays, transaction.flags,
- transaction.applyToken, transaction.inputWindowCommands,
- transaction.desiredPresentTime, transaction.isAutoTimestamp,
- transaction.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
- transaction.id);
-
- mFlinger.flushTransactionQueues();
- EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size());
- EXPECT_EQ(0u, mFlinger.getTransactionQueue().size());
- EXPECT_EQ(1u, mFlinger.getTransactionCommittedSignals().size());
- }
-
- void Flush_keepsInTheQueue(const Vector<ComposerState>& state) {
- ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
- EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size());
-
- TransactionInfo transaction;
- setupSingleWithComposer(transaction, ISurfaceComposer::eSynchronous,
- /*syncInputWindows*/ false,
- /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true,
- FrameTimelineInfo{}, &state);
-
- mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states,
- transaction.displays, transaction.flags,
- transaction.applyToken, transaction.inputWindowCommands,
- transaction.desiredPresentTime, transaction.isAutoTimestamp,
- transaction.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
- transaction.id);
-
- mFlinger.flushTransactionQueues();
- EXPECT_EQ(1u, mFlinger.getPendingTransactionQueue().size());
- EXPECT_EQ(0u, mFlinger.getTransactionQueue().size());
- EXPECT_EQ(0ul, mFlinger.getTransactionCommittedSignals().size());
- }
-
- void Flush_KeepsUnsignaledInTheQueue(const Vector<ComposerState>& state1,
- const Vector<ComposerState>& state2,
- bool updateApplyToken = true,
- uint32_t pendingTransactionQueueSize = 1u) {
- EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size());
- ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
- auto time = systemTime();
- TransactionInfo transactionA;
- TransactionInfo transactionB;
- setupSingleWithComposer(transactionA, ISurfaceComposer::eSynchronous,
- /*syncInputWindows*/ false,
- /*desiredPresentTime*/ time, /*isAutoTimestamp*/ true,
- FrameTimelineInfo{}, &state1);
- setupSingleWithComposer(transactionB, ISurfaceComposer::eSynchronous,
- /*syncInputWindows*/ false,
- /*desiredPresentTime*/ time, /*isAutoTimestamp*/ true,
- FrameTimelineInfo{}, &state2);
- mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
- transactionA.displays, transactionA.flags,
- transactionA.applyToken, transactionA.inputWindowCommands,
- transactionA.desiredPresentTime, transactionA.isAutoTimestamp,
- transactionA.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
- transactionA.id);
- if (updateApplyToken) {
- transactionB.applyToken = sp<IBinder>();
- }
- mFlinger.setTransactionState(transactionB.frameTimelineInfo, transactionB.states,
- transactionB.displays, transactionB.flags,
- transactionB.applyToken, transactionB.inputWindowCommands,
- transactionB.desiredPresentTime, transactionB.isAutoTimestamp,
- transactionB.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
- transactionB.id);
-
- mFlinger.flushTransactionQueues();
- EXPECT_EQ(pendingTransactionQueueSize, mFlinger.getPendingTransactionQueue().size());
- EXPECT_EQ(0u, mFlinger.getTransactionQueue().size());
- }
-
- void Flush_removesSignaledFromTheQueue(const Vector<ComposerState>& state1,
- const Vector<ComposerState>& state2) {
- ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
- EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size());
-
- auto time = systemTime();
- TransactionInfo transactionA;
- TransactionInfo transactionB;
- setupSingleWithComposer(transactionA, ISurfaceComposer::eSynchronous,
- /*syncInputWindows*/ false,
- /*desiredPresentTime*/ time, /*isAutoTimestamp*/ true,
- FrameTimelineInfo{}, &state1);
- setupSingleWithComposer(transactionB, ISurfaceComposer::eSynchronous,
- /*syncInputWindows*/ false,
- /*desiredPresentTime*/ time, /*isAutoTimestamp*/ true,
- FrameTimelineInfo{}, &state2);
- mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
- transactionA.displays, transactionA.flags,
- transactionA.applyToken, transactionA.inputWindowCommands,
- transactionA.desiredPresentTime, transactionA.isAutoTimestamp,
- transactionA.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
- transactionA.id);
- mFlinger.setTransactionState(transactionB.frameTimelineInfo, transactionB.states,
- transactionB.displays, transactionB.flags,
- transactionB.applyToken, transactionB.inputWindowCommands,
- transactionB.desiredPresentTime, transactionB.isAutoTimestamp,
- transactionB.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
- transactionB.id);
-
- mFlinger.flushTransactionQueues();
- EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size());
- EXPECT_EQ(0u, mFlinger.getTransactionQueue().size());
- EXPECT_EQ(2ul, mFlinger.getTransactionCommittedSignals().size());
- }
-
- static Vector<ComposerState> createComposerStateVector(const ComposerState& state1,
- const ComposerState& state2) {
- Vector<ComposerState> states;
- states.push_back(state1);
- states.push_back(state2);
- return states;
- }
-
- static Vector<ComposerState> createComposerStateVector(const ComposerState& state) {
- Vector<ComposerState> states;
- states.push_back(state);
- return states;
- }
-
- static ComposerState createComposerState(int layerId, sp<Fence> fence,
- uint32_t stateFlags = layer_state_t::eBufferChanged) {
- ComposerState composer_state;
- composer_state.state.bufferData = std::make_shared<BufferData>();
- composer_state.state.bufferData->acquireFence = std::move(fence);
- composer_state.state.layerId = layerId;
- composer_state.state.bufferData->flags = BufferData::BufferDataChange::fenceChanged;
- composer_state.state.flags = stateFlags;
- return composer_state;
- }
-
bool mHasListenerCallbacks = false;
std::vector<ListenerCallbacks> mCallbacks;
int mTransactionNumber = 0;
@@ -529,215 +326,677 @@
EXPECT_EQ(nullptr, ret.promote().get());
}
-TEST_F(TransactionApplicationTest, Flush_RemovesSingleSignaledFromTheQueue_LatchUnsignaled_Auto) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto;
- Flush_removesFromTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceSignaled)));
+class LatchUnsignaledTest : public TransactionApplicationTest {
+public:
+ void TearDown() override {
+ // Clear all transaction queues to release all transactions we sent
+ // in the tests. Otherwise, gmock complains about memory leaks.
+ mFlinger.getTransactionQueue().clear();
+ mFlinger.getPendingTransactionQueue().clear();
+ mFlinger.getTransactionCommittedSignals().clear();
+ mFlinger.commitTransactionsLocked(eTransactionMask);
+ mFlinger.mutableCurrentState().layersSortedByZ.clear();
+ mFlinger.mutableDrawingState().layersSortedByZ.clear();
+ }
+
+ static sp<Fence> fence(Fence::Status status) {
+ const auto fence = sp<mock::MockFence>::make();
+ EXPECT_CALL(*fence, getStatus()).WillRepeatedly(Return(status));
+ return fence;
+ }
+
+ ComposerState createComposerState(int layerId, sp<Fence> fence, uint64_t what) {
+ ComposerState state;
+ state.state.bufferData = std::make_shared<BufferData>();
+ state.state.bufferData->acquireFence = std::move(fence);
+ state.state.layerId = layerId;
+ state.state.surface =
+ sp<BufferStateLayer>::make(
+ LayerCreationArgs(mFlinger.flinger(), nullptr, "TestLayer", 0, {}))
+ ->getHandle();
+ state.state.bufferData->flags = BufferData::BufferDataChange::fenceChanged;
+
+ state.state.what = what;
+ if (what & layer_state_t::eCropChanged) {
+ state.state.crop = Rect(1, 2, 3, 4);
+ }
+ return state;
+ }
+
+ TransactionInfo createTransactionInfo(const sp<IBinder>& applyToken,
+ const std::vector<ComposerState>& states) {
+ TransactionInfo transaction;
+ const uint32_t kFlags = ISurfaceComposer::eSynchronous;
+ const bool kSyncInputWindows = false;
+ const nsecs_t kDesiredPresentTime = systemTime();
+ const bool kIsAutoTimestamp = true;
+ const auto kFrameTimelineInfo = FrameTimelineInfo{};
+
+ setupSingle(transaction, kFlags, kSyncInputWindows, kDesiredPresentTime, kIsAutoTimestamp,
+ kFrameTimelineInfo);
+ transaction.applyToken = applyToken;
+ for (const auto& state : states) {
+ transaction.states.push_back(state);
+ }
+
+ return transaction;
+ }
+
+ void setTransactionStates(const std::vector<TransactionInfo>& transactions,
+ size_t expectedTransactionsApplied,
+ size_t expectedTransactionsPending) {
+ EXPECT_EQ(0u, mFlinger.getTransactionQueue().size());
+ EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size());
+
+ for (const auto& transaction : transactions) {
+ mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states,
+ transaction.displays, transaction.flags,
+ transaction.applyToken, transaction.inputWindowCommands,
+ transaction.desiredPresentTime,
+ transaction.isAutoTimestamp, transaction.uncacheBuffer,
+ mHasListenerCallbacks, mCallbacks, transaction.id);
+ }
+ mFlinger.flushTransactionQueues();
+ EXPECT_EQ(0u, mFlinger.getTransactionQueue().size());
+ EXPECT_EQ(expectedTransactionsPending, mFlinger.getPendingTransactionQueue().size());
+ EXPECT_EQ(expectedTransactionsApplied, mFlinger.getTransactionCommittedSignals().size());
+ }
+};
+
+class LatchUnsignaledAutoSingleLayerTest : public LatchUnsignaledTest {
+public:
+ void SetUp() override {
+ LatchUnsignaledTest::SetUp();
+ SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::AutoSingleLayer;
+ }
+};
+
+TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemovesSingleSignaledFromTheQueue) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId = 1;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {createComposerState(kLayerId, fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged)});
+ setTransactionStates({signaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_RemovesSingleUnSignaledFromTheQueue_LatchUnsignaled_Auto) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto;
- Flush_removesFromTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled)));
+TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemovesSingleUnSignaledFromTheQueue) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId = 1;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({unsignaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest,
- Flush_KeepsUnSignaledInTheQueue_NonBufferCropChange_LatchUnsignaled_Auto) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto;
- Flush_keepsInTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceUnsignaled, layer_state_t::eCropChanged)));
+TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsUnSignaledInTheQueue_NonBufferCropChange) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId = 1;
+ const auto kExpectedTransactionsApplied = 0u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eCropChanged),
+ });
+ setTransactionStates({unsignaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest,
- Flush_KeepsUnSignaledInTheQueue_NonBufferChangeClubed_LatchUnsignaled_Auto) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto;
- Flush_keepsInTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceUnsignaled,
- layer_state_t::eCropChanged | layer_state_t::eBufferChanged)));
+TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsUnSignaledInTheQueue_NonBufferChangeClubed) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId = 1;
+ const auto kExpectedTransactionsApplied = 0u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eCropChanged |
+ layer_state_t::
+ eBufferChanged),
+ });
+ setTransactionStates({unsignaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest,
- Flush_KeepsInTheQueueSameApplyTokenMultiState_LatchUnsignaled_Auto) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto;
- Flush_keepsInTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled),
- createComposerState(/*layerId*/ 1, mFenceSignaled)));
+TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsInTheQueueSameApplyTokenMultiState) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId = 1;
+ const auto kExpectedTransactionsApplied = 0u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto mixedTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ createComposerState(kLayerId,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({mixedTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_KeepsInTheQueue_MultipleStateTransaction_Auto) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto;
- Flush_keepsInTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled),
- createComposerState(/*layerId*/ 2, mFenceSignaled)));
+TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsInTheQueue_MultipleStateTransaction) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 0u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto mixedTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({mixedTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_RemovesSignaledFromTheQueue_LatchUnsignaled_Auto) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto;
- Flush_removesSignaledFromTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceSignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2, mFenceSignaled2)));
+TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemovesSignaledFromTheQueue) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 2u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto signaledTransaction2 =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({signaledTransaction, signaledTransaction2}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_RemoveSignaledWithUnsignaledIntact_LatchUnsignaled_Auto) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto;
- Flush_KeepsUnsignaledInTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceSignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2, mFenceUnsignaled)));
- EXPECT_EQ(1ul, mFlinger.getTransactionCommittedSignals().size());
+TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemoveSignaledWithUnsignaledIntact) {
+ const sp<IBinder> kApplyToken1 =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken1,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken2,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({signaledTransaction, unsignaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest,
- Flush_KeepsTransactionInTheQueueSameApplyToken_LatchUnsignaled_Auto) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto;
- Flush_KeepsUnsignaledInTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceUnsignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2, mFenceSignaled)),
- /*updateApplyToken*/ false);
- EXPECT_EQ(1ul, mFlinger.getTransactionCommittedSignals().size());
+TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsTransactionInTheQueueSameApplyToken) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({unsignaledTransaction, signaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_KeepsTransactionInTheQueue_LatchUnsignaled_Auto) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto;
- Flush_KeepsUnsignaledInTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceUnsignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2, mFenceUnsignaled)),
- /*updateApplyToken*/ true,
- /*pendingTransactionQueueSize*/ 2u);
- EXPECT_EQ(0ul, mFlinger.getTransactionCommittedSignals().size());
+TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsTransactionInTheQueue) {
+ const sp<IBinder> kApplyToken1 =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken1,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto unsignaledTransaction2 =
+ createTransactionInfo(kApplyToken2,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({unsignaledTransaction, unsignaledTransaction2},
+ kExpectedTransactionsApplied, kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_RemovesSignaledFromTheQueue_LatchUnsignaled_Disabled) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled;
- Flush_removesFromTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceSignaled)));
+class LatchUnsignaledDisabledTest : public LatchUnsignaledTest {
+public:
+ void SetUp() override {
+ LatchUnsignaledTest::SetUp();
+ SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled;
+ }
+};
+
+TEST_F(LatchUnsignaledDisabledTest, Flush_RemovesSignaledFromTheQueue) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId = 1;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {createComposerState(kLayerId, fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged)});
+ setTransactionStates({signaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_KeepsInTheQueue_LatchUnsignaled_Disabled) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled;
- Flush_keepsInTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled)));
+TEST_F(LatchUnsignaledDisabledTest, Flush_KeepsInTheQueue) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId = 1;
+ const auto kExpectedTransactionsApplied = 0u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({unsignaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_KeepsInTheQueueSameLayerId_LatchUnsignaled_Disabled) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled;
- Flush_keepsInTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled),
- createComposerState(/*layerId*/ 1, mFenceUnsignaled)));
+TEST_F(LatchUnsignaledDisabledTest, Flush_KeepsInTheQueueSameLayerId) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId = 1;
+ const auto kExpectedTransactionsApplied = 0u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ createComposerState(kLayerId,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({unsignaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_KeepsInTheQueueDifferentLayerId_LatchUnsignaled_Disabled) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled;
- Flush_keepsInTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled),
- createComposerState(/*layerId*/ 2, mFenceUnsignaled)));
+TEST_F(LatchUnsignaledDisabledTest, Flush_KeepsInTheQueueDifferentLayerId) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 0u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({unsignaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_RemovesSignaledFromTheQueue_LatchUnSignaled_Disabled) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled;
- Flush_removesSignaledFromTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceSignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2, mFenceSignaled2)));
+TEST_F(LatchUnsignaledDisabledTest, Flush_RemovesSignaledFromTheQueue_MultipleLayers) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 2u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto signaledTransaction2 =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({signaledTransaction, signaledTransaction2}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest,
- Flush_KeepInTheQueueDifferentApplyToken_LatchUnsignaled_Disabled) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled;
- Flush_KeepsUnsignaledInTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceUnsignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2, mFenceSignaled)));
- EXPECT_EQ(1ul, mFlinger.getTransactionCommittedSignals().size());
+TEST_F(LatchUnsignaledDisabledTest, Flush_KeepInTheQueueDifferentApplyToken) {
+ const sp<IBinder> kApplyToken1 =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken1,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken2,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({unsignaledTransaction, signaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_KeepInTheQueueSameApplyToken_LatchUnsignaled_Disabled) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled;
- Flush_KeepsUnsignaledInTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceSignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2, mFenceUnsignaled)),
- /*updateApplyToken*/ false);
- EXPECT_EQ(1ul, mFlinger.getTransactionCommittedSignals().size());
+TEST_F(LatchUnsignaledDisabledTest, Flush_KeepInTheQueueSameApplyToken) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({signaledTransaction, unsignaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_KeepInTheUnsignaledTheQueue_LatchUnsignaled_Disabled) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled;
- Flush_KeepsUnsignaledInTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceUnsignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2, mFenceUnsignaled)),
- /*updateApplyToken*/ false);
- EXPECT_EQ(0ul, mFlinger.getTransactionCommittedSignals().size());
+TEST_F(LatchUnsignaledDisabledTest, Flush_KeepInTheUnsignaledTheQueue) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 0u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto unsignaledTransaction2 =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({unsignaledTransaction, unsignaledTransaction2},
+ kExpectedTransactionsApplied, kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_RemovesSignaledFromTheQueue_LatchUnsignaled_Always) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always;
- Flush_removesFromTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceSignaled)));
+class LatchUnsignaledAlwaysTest : public LatchUnsignaledTest {
+public:
+ void SetUp() override {
+ LatchUnsignaledTest::SetUp();
+ SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always;
+ }
+};
+
+TEST_F(LatchUnsignaledAlwaysTest, Flush_RemovesSignaledFromTheQueue) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId = 1;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {createComposerState(kLayerId, fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged)});
+ setTransactionStates({signaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_RemovesFromTheQueue_LatchUnsignaled_Always) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always;
- Flush_removesFromTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled)));
+TEST_F(LatchUnsignaledAlwaysTest, Flush_RemovesFromTheQueue) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId = 1;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {createComposerState(kLayerId, fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged)});
+ setTransactionStates({unsignaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_RemovesFromTheQueueSameLayerId_LatchUnsignaled_Always) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always;
- Flush_removesFromTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled),
- createComposerState(/*layerId*/ 1, mFenceSignaled)));
+TEST_F(LatchUnsignaledAlwaysTest, Flush_RemovesFromTheQueueSameLayerId) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId = 1;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto mixedTransaction =
+ createTransactionInfo(kApplyToken,
+ {createComposerState(kLayerId, fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ createComposerState(kLayerId, fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged)});
+ setTransactionStates({mixedTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest,
- Flush_RemovesFromTheQueueDifferentLayerId_LatchUnsignaled_Always) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always;
- Flush_removesFromTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled),
- createComposerState(/*layerId*/ 2, mFenceSignaled)));
+TEST_F(LatchUnsignaledAlwaysTest, Flush_RemovesFromTheQueueDifferentLayerId) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto mixedTransaction =
+ createTransactionInfo(kApplyToken,
+ {createComposerState(kLayerId1, fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ createComposerState(kLayerId2, fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged)});
+ setTransactionStates({mixedTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_RemovesSignaledFromTheQueue_LatchUnSignaled_Always) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always;
- Flush_removesSignaledFromTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceSignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2, mFenceSignaled2)));
+TEST_F(LatchUnsignaledAlwaysTest, Flush_RemovesSignaledFromTheQueue_MultipleLayers) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 2u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto signaledTransaction2 =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({signaledTransaction, signaledTransaction2}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest,
- Flush_RemovesFromTheQueueDifferentApplyToken_LatchUnsignaled_Always) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always;
- Flush_removesUnsignaledFromTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceSignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2,
- mFenceUnsignaled)));
+TEST_F(LatchUnsignaledAlwaysTest, Flush_RemovesFromTheQueueDifferentApplyToken) {
+ const sp<IBinder> kApplyToken1 =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 2u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken1,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken2,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({signaledTransaction, unsignaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest,
- Flush_RemovesUnsignaledFromTheQueueSameApplyToken_LatchUnsignaled_Always) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always;
- Flush_removesUnsignaledFromTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1,
- mFenceUnsignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2, mFenceSignaled)),
- /*updateApplyToken*/ false);
+TEST_F(LatchUnsignaledAlwaysTest, Flush_RemovesUnsignaledFromTheQueueSameApplyToken) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 2u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({unsignaledTransaction, signaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_RemovesUnsignaledFromTheQueue_LatchUnsignaled_Always) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always;
- Flush_removesUnsignaledFromTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1,
- mFenceUnsignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2,
- mFenceUnsignaled)));
+TEST_F(LatchUnsignaledAlwaysTest, Flush_RemovesUnsignaledFromTheQueue) {
+ const sp<IBinder> kApplyToken1 =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 2u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken1,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto unsignaledTransaction2 =
+ createTransactionInfo(kApplyToken2,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({unsignaledTransaction, unsignaledTransaction2},
+ kExpectedTransactionsApplied, kExpectedTransactionsPending);
}
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index ce9ec96..4a7d8eb 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -43,6 +43,8 @@
using android::hardware::graphics::composer::V2_4::IComposerCallback;
using android::hardware::graphics::composer::V2_4::IComposerClient;
+using aidl::android::hardware::graphics::common::DisplayDecorationSupport;
+
class Composer : public Hwc2::Composer {
public:
using Display = android::hardware::graphics::composer::V2_1::Display;
@@ -153,6 +155,8 @@
MOCK_METHOD3(setLayerWhitePointNits, Error(Display, Layer, float));
MOCK_METHOD3(setLayerBlockingRegion,
Error(Display, Layer, const std::vector<IComposerClient::Rect>&));
+ MOCK_METHOD2(getDisplayDecorationSupport,
+ Error(Display, std::optional<DisplayDecorationSupport>*));
};
} // namespace Hwc2::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
index 9015944..9be8cc7 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
@@ -95,6 +95,10 @@
MOCK_METHOD(hal::Error, setContentType, (hal::ContentType), (override));
MOCK_METHOD(hal::Error, getClientTargetProperty, (hal::ClientTargetProperty *, float *),
(override));
+ MOCK_METHOD(
+ hal::Error, getDisplayDecorationSupport,
+ (std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport> *),
+ (override));
};
class Layer : public HWC2::Layer {