Merge "Increase injection timeout for InputFilterInjectionPolicyTest"
diff --git a/data/etc/input/Android.bp b/data/etc/input/Android.bp
index 90f3c6b..b662491 100644
--- a/data/etc/input/Android.bp
+++ b/data/etc/input/Android.bp
@@ -3,12 +3,21 @@
}
filegroup {
- name: "motion_predictor_model.fb",
- srcs: ["motion_predictor_model.fb"],
+ name: "motion_predictor_model",
+ srcs: [
+ "motion_predictor_model.tflite",
+ "motion_predictor_config.xml",
+ ],
}
prebuilt_etc {
name: "motion_predictor_model_prebuilt",
filename_from_src: true,
- src: "motion_predictor_model.fb",
+ src: "motion_predictor_model.tflite",
+}
+
+prebuilt_etc {
+ name: "motion_predictor_model_config",
+ filename_from_src: true,
+ src: "motion_predictor_config.xml",
}
diff --git a/data/etc/input/motion_predictor_config.xml b/data/etc/input/motion_predictor_config.xml
new file mode 100644
index 0000000..03dfd63
--- /dev/null
+++ b/data/etc/input/motion_predictor_config.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+<motion-predictor>
+ <!-- The time interval (ns) between the model's predictions. -->
+ <prediction-interval>4166666</prediction-interval> <!-- 4.167 ms = ~240 Hz -->
+</motion-predictor>
+
diff --git a/data/etc/input/motion_predictor_model.fb b/data/etc/input/motion_predictor_model.tflite
similarity index 100%
rename from data/etc/input/motion_predictor_model.fb
rename to data/etc/input/motion_predictor_model.tflite
Binary files differ
diff --git a/include/input/PrintTools.h b/include/input/PrintTools.h
index 0ca6fa3..0e3fbb1 100644
--- a/include/input/PrintTools.h
+++ b/include/input/PrintTools.h
@@ -27,6 +27,9 @@
template <size_t N>
std::string bitsetToString(const std::bitset<N>& bitset) {
+ if (bitset.none()) {
+ return "<none>";
+ }
return bitset.to_string();
}
diff --git a/include/input/TfLiteMotionPredictor.h b/include/input/TfLiteMotionPredictor.h
index a340bd0..fbd6026 100644
--- a/include/input/TfLiteMotionPredictor.h
+++ b/include/input/TfLiteMotionPredictor.h
@@ -25,6 +25,7 @@
#include <android-base/mapped_file.h>
#include <input/RingBuffer.h>
+#include <utils/Timers.h>
#include <tensorflow/lite/core/api/error_reporter.h>
#include <tensorflow/lite/interpreter.h>
@@ -109,6 +110,9 @@
// Returns the length of the model's output buffers.
size_t outputLength() const;
+ // Returns the time interval between predictions.
+ nsecs_t predictionInterval() const { return mPredictionInterval; }
+
// Executes the model.
// Returns true if the model successfully executed and the output tensors can be read.
bool invoke();
@@ -127,7 +131,8 @@
std::span<const float> outputPressure() const;
private:
- explicit TfLiteMotionPredictorModel(std::unique_ptr<android::base::MappedFile> model);
+ explicit TfLiteMotionPredictorModel(std::unique_ptr<android::base::MappedFile> model,
+ nsecs_t predictionInterval);
void allocateTensors();
void attachInputTensors();
@@ -148,6 +153,8 @@
std::unique_ptr<tflite::FlatBufferModel> mModel;
std::unique_ptr<tflite::Interpreter> mInterpreter;
tflite::SignatureRunner* mRunner = nullptr;
+
+ const nsecs_t mPredictionInterval = 0;
};
} // namespace android
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 582437f..b6b0cfb 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -399,45 +399,28 @@
return false;
}
- return (mShouldUseAngle == YES) ? true : false;
+ return mShouldUseAngle;
}
-void GraphicsEnv::updateShouldUseAngle() {
- const char* ANGLE_PREFER_ANGLE = "angle";
- const char* ANGLE_PREFER_NATIVE = "native";
-
- mShouldUseAngle = NO;
- if (mAngleDeveloperOptIn == ANGLE_PREFER_ANGLE) {
- ALOGV("User set \"Developer Options\" to force the use of ANGLE");
- mShouldUseAngle = YES;
- } else if (mAngleDeveloperOptIn == ANGLE_PREFER_NATIVE) {
- ALOGV("User set \"Developer Options\" to force the use of Native");
- } else {
- ALOGV("User set invalid \"Developer Options\": '%s'", mAngleDeveloperOptIn.c_str());
- }
-}
-
-void GraphicsEnv::setAngleInfo(const std::string& path, const std::string& packageName,
- const std::string& developerOptIn,
+void GraphicsEnv::setAngleInfo(const std::string& path, const bool useSystemAngle,
+ const std::string& packageName,
const std::vector<std::string> eglFeatures) {
- if (mShouldUseAngle != UNKNOWN) {
- // We've already figured out an answer for this app, so just return.
- ALOGV("Already evaluated the rules file for '%s': use ANGLE = %s", packageName.c_str(),
- (mShouldUseAngle == YES) ? "true" : "false");
+ if (mShouldUseAngle) {
+ // ANGLE is already set up for this application process, even if the application
+ // needs to switch from apk to system or vice versa, the application process must
+ // be killed and relaunch so that the loader can properly load ANGLE again.
+ // The architecture does not support runtime switch between drivers, so just return.
+ ALOGE("ANGLE is already set for %s", packageName.c_str());
return;
}
mAngleEglFeatures = std::move(eglFeatures);
-
ALOGV("setting ANGLE path to '%s'", path.c_str());
- mAnglePath = path;
+ mAnglePath = std::move(path);
ALOGV("setting app package name to '%s'", packageName.c_str());
- mPackageName = packageName;
- ALOGV("setting ANGLE application opt-in to '%s'", developerOptIn.c_str());
- mAngleDeveloperOptIn = developerOptIn;
-
- // Update the current status of whether we should use ANGLE or not
- updateShouldUseAngle();
+ mPackageName = std::move(packageName);
+ mShouldUseAngle = true;
+ mUseSystemAngle = useSystemAngle;
}
void GraphicsEnv::setLayerPaths(NativeLoaderNamespace* appNamespace,
@@ -484,13 +467,15 @@
}
// Return true if all the required libraries from vndk and sphal namespace are
-// linked to the updatable gfx driver namespace correctly.
-bool GraphicsEnv::linkDriverNamespaceLocked(android_namespace_t* vndkNamespace) {
+// linked to the driver namespace correctly.
+bool GraphicsEnv::linkDriverNamespaceLocked(android_namespace_t* destNamespace,
+ android_namespace_t* vndkNamespace,
+ const std::string& sharedSphalLibraries) {
const std::string llndkLibraries = getSystemNativeLibraries(NativeLibrary::LLNDK);
if (llndkLibraries.empty()) {
return false;
}
- if (!android_link_namespaces(mDriverNamespace, nullptr, llndkLibraries.c_str())) {
+ if (!android_link_namespaces(destNamespace, nullptr, llndkLibraries.c_str())) {
ALOGE("Failed to link default namespace[%s]", dlerror());
return false;
}
@@ -499,12 +484,12 @@
if (vndkspLibraries.empty()) {
return false;
}
- if (!android_link_namespaces(mDriverNamespace, vndkNamespace, vndkspLibraries.c_str())) {
+ if (!android_link_namespaces(destNamespace, vndkNamespace, vndkspLibraries.c_str())) {
ALOGE("Failed to link vndk namespace[%s]", dlerror());
return false;
}
- if (mSphalLibraries.empty()) {
+ if (sharedSphalLibraries.empty()) {
return true;
}
@@ -512,11 +497,11 @@
auto sphalNamespace = android_get_exported_namespace("sphal");
if (!sphalNamespace) {
ALOGE("Depend on these libraries[%s] in sphal, but failed to get sphal namespace",
- mSphalLibraries.c_str());
+ sharedSphalLibraries.c_str());
return false;
}
- if (!android_link_namespaces(mDriverNamespace, sphalNamespace, mSphalLibraries.c_str())) {
+ if (!android_link_namespaces(destNamespace, sphalNamespace, sharedSphalLibraries.c_str())) {
ALOGE("Failed to link sphal namespace[%s]", dlerror());
return false;
}
@@ -568,7 +553,7 @@
nullptr, // permitted_when_isolated_path
nullptr);
- if (!linkDriverNamespaceLocked(vndkNamespace)) {
+ if (!linkDriverNamespaceLocked(mDriverNamespace, vndkNamespace, mSphalLibraries)) {
mDriverNamespace = nullptr;
}
@@ -586,20 +571,48 @@
return mAngleNamespace;
}
- if (mAnglePath.empty()) {
- ALOGV("mAnglePath is empty, not creating ANGLE namespace");
+ if (mAnglePath.empty() && !mUseSystemAngle) {
+ ALOGV("mAnglePath is empty and not using system ANGLE, abort creating ANGLE namespace");
return nullptr;
}
- mAngleNamespace = android_create_namespace("ANGLE",
- nullptr, // ld_library_path
- mAnglePath.c_str(), // default_library_path
- ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED,
- nullptr, // permitted_when_isolated_path
- nullptr);
+ // Construct the search paths for system ANGLE.
+ const char* const defaultLibraryPaths =
+#if defined(__LP64__)
+ "/vendor/lib64/egl:/system/lib64/egl";
+#else
+ "/vendor/lib/egl:/system/lib/egl";
+#endif
+
+ // If the application process will run on top of system ANGLE, construct the namespace
+ // with sphal namespace being the parent namespace so that search paths and libraries
+ // are properly inherited.
+ mAngleNamespace =
+ android_create_namespace("ANGLE",
+ mUseSystemAngle ? defaultLibraryPaths
+ : mAnglePath.c_str(), // ld_library_path
+ mUseSystemAngle ? defaultLibraryPaths
+ : mAnglePath.c_str(), // default_library_path
+ ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED,
+ nullptr, // permitted_when_isolated_path
+ mUseSystemAngle ? android_get_exported_namespace("sphal")
+ : nullptr); // parent
ALOGD_IF(!mAngleNamespace, "Could not create ANGLE namespace from default");
+ if (!mUseSystemAngle) {
+ return mAngleNamespace;
+ }
+
+ auto vndkNamespace = android_get_exported_namespace("vndk");
+ if (!vndkNamespace) {
+ return nullptr;
+ }
+
+ if (!linkDriverNamespaceLocked(mAngleNamespace, vndkNamespace, "")) {
+ mAngleNamespace = nullptr;
+ }
+
return mAngleNamespace;
}
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index a1b5e50..e78d038 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -29,6 +29,11 @@
struct NativeLoaderNamespace;
+// The GraphicsEnv is a singleton per application process and is used to properly set up the
+// graphics drivers for the application process during application starts. The architecture of
+// the graphics driver loader does not support runtime switch and only supports switch to different
+// graphics drivers when application process launches and hence the only way to switch to different
+// graphics drivers is to completely kill the application process and relaunch the application.
class GraphicsEnv {
public:
static GraphicsEnv& getInstance();
@@ -103,8 +108,8 @@
// (libraries must be stored uncompressed and page aligned); such elements
// in the search path must have a '!' after the zip filename, e.g.
// /system/app/ANGLEPrebuilt/ANGLEPrebuilt.apk!/lib/arm64-v8a
- void setAngleInfo(const std::string& path, const std::string& packageName,
- const std::string& devOptIn, const std::vector<std::string> eglFeatures);
+ void setAngleInfo(const std::string& path, const bool useSystemAngle,
+ const std::string& packageName, const std::vector<std::string> eglFeatures);
// Get the ANGLE driver namespace.
android_namespace_t* getAngleNamespace();
// Get the app package name.
@@ -132,12 +137,10 @@
const std::string& getDebugLayersGLES();
private:
- enum UseAngle { UNKNOWN, YES, NO };
-
- // Update whether ANGLE should be used.
- void updateShouldUseAngle();
// Link updatable driver namespace with llndk and vndk-sp libs.
- bool linkDriverNamespaceLocked(android_namespace_t* vndkNamespace);
+ bool linkDriverNamespaceLocked(android_namespace_t* destNamespace,
+ android_namespace_t* vndkNamespace,
+ const std::string& sharedSphalLibraries);
// Check whether this process is ready to send stats.
bool readyToSendGpuStatsLocked();
// Send the initial complete GpuStats to GpuService.
@@ -165,12 +168,12 @@
std::string mAnglePath;
// App's package name.
std::string mPackageName;
- // ANGLE developer opt in status.
- std::string mAngleDeveloperOptIn;
// ANGLE EGL features;
std::vector<std::string> mAngleEglFeatures;
- // Use ANGLE flag.
- UseAngle mShouldUseAngle = UNKNOWN;
+ // Whether ANGLE should be used.
+ bool mShouldUseAngle = false;
+ // Whether loader should load system ANGLE.
+ bool mUseSystemAngle = false;
// ANGLE namespace.
android_namespace_t* mAngleNamespace = nullptr;
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 470f5ed..f777f2f 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -156,6 +156,7 @@
"libcutils",
"liblog",
"libPlatformProperties",
+ "libtinyxml2",
"libvintf",
],
@@ -212,6 +213,7 @@
required: [
"motion_predictor_model_prebuilt",
+ "motion_predictor_model_config",
],
},
host: {
diff --git a/libs/input/MotionPredictor.cpp b/libs/input/MotionPredictor.cpp
index a425b93..70a3081 100644
--- a/libs/input/MotionPredictor.cpp
+++ b/libs/input/MotionPredictor.cpp
@@ -36,9 +36,6 @@
namespace android {
namespace {
-const int64_t PREDICTION_INTERVAL_NANOS =
- 12500000 / 3; // TODO(b/266747937): Get this from the model.
-
/**
* Log debug messages about predictions.
* Enable this via "adb shell setprop log.tag.MotionPredictor DEBUG"
@@ -189,7 +186,7 @@
// TODO(b/266747654): Stop predictions if predicted pressure is < some threshold.
coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, predictedPressure[i]);
- predictionTime += PREDICTION_INTERVAL_NANOS;
+ predictionTime += mModel->predictionInterval();
if (i == 0) {
hasPredictions = true;
prediction->initialize(InputEvent::nextId(), event.getDeviceId(), event.getSource(),
@@ -208,7 +205,6 @@
axisFrom = axisTo;
axisTo = point;
}
- // TODO(b/266747511): Interpolate to futureTime?
if (!hasPredictions) {
return nullptr;
}
diff --git a/libs/input/TfLiteMotionPredictor.cpp b/libs/input/TfLiteMotionPredictor.cpp
index 85fa176..9f4aaa8 100644
--- a/libs/input/TfLiteMotionPredictor.cpp
+++ b/libs/input/TfLiteMotionPredictor.cpp
@@ -36,6 +36,7 @@
#define ATRACE_TAG ATRACE_TAG_INPUT
#include <cutils/trace.h>
#include <log/log.h>
+#include <utils/Timers.h>
#include "tensorflow/lite/core/api/error_reporter.h"
#include "tensorflow/lite/core/api/op_resolver.h"
@@ -44,6 +45,8 @@
#include "tensorflow/lite/model.h"
#include "tensorflow/lite/mutable_op_resolver.h"
+#include "tinyxml2.h"
+
namespace android {
namespace {
@@ -72,16 +75,31 @@
std::string getModelPath() {
#if defined(__ANDROID__)
- static const char* oemModel = "/vendor/etc/motion_predictor_model.fb";
+ static const char* oemModel = "/vendor/etc/motion_predictor_model.tflite";
if (fileExists(oemModel)) {
return oemModel;
}
- return "/system/etc/motion_predictor_model.fb";
+ return "/system/etc/motion_predictor_model.tflite";
#else
- return base::GetExecutableDirectory() + "/motion_predictor_model.fb";
+ return base::GetExecutableDirectory() + "/motion_predictor_model.tflite";
#endif
}
+std::string getConfigPath() {
+ // The config file should be alongside the model file.
+ return base::Dirname(getModelPath()) + "/motion_predictor_config.xml";
+}
+
+int64_t parseXMLInt64(const tinyxml2::XMLElement& configRoot, const char* elementName) {
+ const tinyxml2::XMLElement* element = configRoot.FirstChildElement(elementName);
+ LOG_ALWAYS_FATAL_IF(!element, "Could not find '%s' element", elementName);
+
+ int64_t value = 0;
+ LOG_ALWAYS_FATAL_IF(element->QueryInt64Text(&value) != tinyxml2::XML_SUCCESS,
+ "Failed to parse %s: %s", elementName, element->GetText());
+ return value;
+}
+
// A TFLite ErrorReporter that logs to logcat.
class LoggingErrorReporter : public tflite::ErrorReporter {
public:
@@ -246,13 +264,23 @@
PLOG(FATAL) << "Failed to mmap model";
}
+ const std::string configPath = getConfigPath();
+ tinyxml2::XMLDocument configDocument;
+ LOG_ALWAYS_FATAL_IF(configDocument.LoadFile(configPath.c_str()) != tinyxml2::XML_SUCCESS,
+ "Failed to load config file from %s", configPath.c_str());
+
+ // Parse configuration file.
+ const tinyxml2::XMLElement* configRoot = configDocument.FirstChildElement("motion-predictor");
+ LOG_ALWAYS_FATAL_IF(!configRoot);
+ const nsecs_t predictionInterval = parseXMLInt64(*configRoot, "prediction-interval");
+
return std::unique_ptr<TfLiteMotionPredictorModel>(
- new TfLiteMotionPredictorModel(std::move(modelBuffer)));
+ new TfLiteMotionPredictorModel(std::move(modelBuffer), predictionInterval));
}
TfLiteMotionPredictorModel::TfLiteMotionPredictorModel(
- std::unique_ptr<android::base::MappedFile> model)
- : mFlatBuffer(std::move(model)) {
+ std::unique_ptr<android::base::MappedFile> model, nsecs_t predictionInterval)
+ : mFlatBuffer(std::move(model)), mPredictionInterval(predictionInterval) {
CHECK(mFlatBuffer);
mErrorReporter = std::make_unique<LoggingErrorReporter>();
mModel = tflite::FlatBufferModel::VerifyAndBuildFromBuffer(mFlatBuffer->data(),
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index 6aae25d..cadac88 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -64,12 +64,13 @@
"libcutils",
"liblog",
"libPlatformProperties",
+ "libtinyxml2",
"libutils",
"libvintf",
],
data: [
"data/*",
- ":motion_predictor_model.fb",
+ ":motion_predictor_model",
],
test_options: {
unit_test: true,
diff --git a/libs/renderengine/skia/filters/KawaseBlurFilter.cpp b/libs/renderengine/skia/filters/KawaseBlurFilter.cpp
index 061ec5f..0c7335c 100644
--- a/libs/renderengine/skia/filters/KawaseBlurFilter.cpp
+++ b/libs/renderengine/skia/filters/KawaseBlurFilter.cpp
@@ -17,14 +17,20 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include "KawaseBlurFilter.h"
+#include <SkAlphaType.h>
+#include <SkBlendMode.h>
#include <SkCanvas.h>
+#include <SkImageInfo.h>
#include <SkPaint.h>
#include <SkRRect.h>
#include <SkRuntimeEffect.h>
+#include <SkShader.h>
#include <SkSize.h>
#include <SkString.h>
#include <SkSurface.h>
#include <SkTileMode.h>
+#include <include/gpu/GpuTypes.h>
+#include <include/gpu/ganesh/SkSurfaceGanesh.h>
#include <log/log.h>
#include <utils/Trace.h>
@@ -33,19 +39,18 @@
namespace skia {
KawaseBlurFilter::KawaseBlurFilter(): BlurFilter() {
- SkString blurString(R"(
- uniform shader child;
- uniform float in_blurOffset;
+ SkString blurString(
+ "uniform shader child;"
+ "uniform float in_blurOffset;"
- half4 main(float2 xy) {
- half4 c = child.eval(xy);
- c += child.eval(xy + float2(+in_blurOffset, +in_blurOffset));
- c += child.eval(xy + float2(+in_blurOffset, -in_blurOffset));
- c += child.eval(xy + float2(-in_blurOffset, -in_blurOffset));
- c += child.eval(xy + float2(-in_blurOffset, +in_blurOffset));
- return half4(c.rgb * 0.2, 1.0);
- }
- )");
+ "half4 main(float2 xy) {"
+ "half4 c = child.eval(xy);"
+ "c += child.eval(xy + float2(+in_blurOffset, +in_blurOffset));"
+ "c += child.eval(xy + float2(+in_blurOffset, -in_blurOffset));"
+ "c += child.eval(xy + float2(-in_blurOffset, -in_blurOffset));"
+ "c += child.eval(xy + float2(-in_blurOffset, +in_blurOffset));"
+ "return half4(c.rgb * 0.2, 1.0);"
+ "}");
auto [blurEffect, error] = SkRuntimeEffect::MakeForShader(blurString);
if (!blurEffect) {
@@ -54,10 +59,43 @@
mBlurEffect = std::move(blurEffect);
}
-sk_sp<SkImage> KawaseBlurFilter::generate(GrRecordingContext* context, const uint32_t blurRadius,
- const sk_sp<SkImage> input, const SkRect& blurRect)
- const {
+// Draws the given runtime shader on a GPU (Ganesh) surface and returns the result as an
+// SkImage.
+static sk_sp<SkImage> makeImage(GrRecordingContext* context, SkRuntimeShaderBuilder* builder,
+ const SkImageInfo& resultInfo) {
+ if (resultInfo.alphaType() == kUnpremul_SkAlphaType ||
+ resultInfo.alphaType() == kUnknown_SkAlphaType) {
+ return nullptr;
+ }
+ constexpr int kSampleCount = 1;
+ constexpr bool kMipmapped = false;
+ sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(context,
+ skgpu::Budgeted::kYes,
+ resultInfo,
+ kSampleCount,
+ kTopLeft_GrSurfaceOrigin,
+ nullptr,
+ kMipmapped);
+ if (!surface) {
+ return nullptr;
+ }
+ sk_sp<SkShader> shader = builder->makeShader(nullptr);
+ if (!shader) {
+ return nullptr;
+ }
+ SkPaint paint;
+ paint.setShader(std::move(shader));
+ paint.setBlendMode(SkBlendMode::kSrc);
+ surface->getCanvas()->drawPaint(paint);
+ return surface->makeImageSnapshot();
+}
+
+sk_sp<SkImage> KawaseBlurFilter::generate(GrRecordingContext* context,
+ const uint32_t blurRadius,
+ const sk_sp<SkImage> input,
+ const SkRect& blurRect) const {
+ LOG_ALWAYS_FATAL_IF(context == nullptr, "%s: Needs GPU context", __func__);
LOG_ALWAYS_FATAL_IF(input == nullptr, "%s: Invalid input image", __func__);
// Kawase is an approximation of Gaussian, but it behaves differently from it.
// A radius transformation is required for approximating them, and also to introduce
@@ -83,7 +121,7 @@
input->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, linear, blurMatrix);
blurBuilder.uniform("in_blurOffset") = radiusByPasses * kInputScale;
- sk_sp<SkImage> tmpBlur(blurBuilder.makeImage(context, nullptr, scaledInfo, false));
+ sk_sp<SkImage> tmpBlur = makeImage(context, &blurBuilder, scaledInfo);
// And now we'll build our chain of scaled blur stages
for (auto i = 1; i < numberOfPasses; i++) {
@@ -91,7 +129,7 @@
blurBuilder.child("child") =
tmpBlur->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, linear);
blurBuilder.uniform("in_blurOffset") = (float) i * radiusByPasses * kInputScale;
- tmpBlur = blurBuilder.makeImage(context, nullptr, scaledInfo, false);
+ tmpBlur = makeImage(context, &blurBuilder, scaledInfo);
}
return tmpBlur;
diff --git a/libs/ultrahdr/icc.cpp b/libs/ultrahdr/icc.cpp
index 1ab3c7c..e41b645 100644
--- a/libs/ultrahdr/icc.cpp
+++ b/libs/ultrahdr/icc.cpp
@@ -19,7 +19,6 @@
#endif
#include <ultrahdr/icc.h>
-#include <ultrahdr/gainmapmath.h>
#include <vector>
#include <utils/Log.h>
@@ -218,8 +217,8 @@
total_length = (((total_length + 2) >> 2) << 2); // 4 aligned
sp<DataStruct> dataStruct = sp<DataStruct>::make(total_length);
dataStruct->write32(Endian_SwapBE32(kTAG_CurveType)); // Type
- dataStruct->write32(0); // Reserved
- dataStruct->write32(Endian_SwapBE32(table_entries)); // Value count
+ dataStruct->write32(0); // Reserved
+ dataStruct->write32(Endian_SwapBE32(table_entries)); // Value count
for (size_t i = 0; i < table_entries; ++i) {
uint16_t value = reinterpret_cast<const uint16_t*>(table_16)[i];
dataStruct->write16(value);
@@ -227,14 +226,30 @@
return dataStruct;
}
-sp<DataStruct> IccHelper::write_trc_tag_for_linear() {
- int total_length = 16;
- sp<DataStruct> dataStruct = sp<DataStruct>::make(total_length);
- dataStruct->write32(Endian_SwapBE32(kTAG_ParaCurveType)); // Type
- dataStruct->write32(0); // Reserved
- dataStruct->write32(Endian_SwapBE16(kExponential_ParaCurveType));
- dataStruct->write32(Endian_SwapBE32(float_round_to_fixed(1.0)));
+sp<DataStruct> IccHelper::write_trc_tag(const TransferFunction& fn) {
+ if (fn.a == 1.f && fn.b == 0.f && fn.c == 0.f
+ && fn.d == 0.f && fn.e == 0.f && fn.f == 0.f) {
+ int total_length = 16;
+ sp<DataStruct> dataStruct = new DataStruct(total_length);
+ dataStruct->write32(Endian_SwapBE32(kTAG_ParaCurveType)); // Type
+ dataStruct->write32(0); // Reserved
+ dataStruct->write32(Endian_SwapBE16(kExponential_ParaCurveType));
+ dataStruct->write32(Endian_SwapBE32(float_round_to_fixed(fn.g)));
+ return dataStruct;
+ }
+ int total_length = 40;
+ sp<DataStruct> dataStruct = new DataStruct(total_length);
+ dataStruct->write32(Endian_SwapBE32(kTAG_ParaCurveType)); // Type
+ dataStruct->write32(0); // Reserved
+ dataStruct->write32(Endian_SwapBE16(kGABCDEF_ParaCurveType));
+ dataStruct->write32(Endian_SwapBE32(float_round_to_fixed(fn.g)));
+ dataStruct->write32(Endian_SwapBE32(float_round_to_fixed(fn.a)));
+ dataStruct->write32(Endian_SwapBE32(float_round_to_fixed(fn.b)));
+ dataStruct->write32(Endian_SwapBE32(float_round_to_fixed(fn.c)));
+ dataStruct->write32(Endian_SwapBE32(float_round_to_fixed(fn.d)));
+ dataStruct->write32(Endian_SwapBE32(float_round_to_fixed(fn.e)));
+ dataStruct->write32(Endian_SwapBE32(float_round_to_fixed(fn.f)));
return dataStruct;
}
@@ -349,7 +364,7 @@
// The "B" curve is required.
for (size_t i = 0; i < kNumChannels; ++i) {
- b_curves_data[i] = write_trc_tag_for_linear();
+ b_curves_data[i] = write_trc_tag(kLinear_TransFun);
}
// The "A" curve and CLUT are optional.
@@ -362,7 +377,7 @@
a_curves_offset = clut_offset + clut->getLength();
for (size_t i = 0; i < kNumChannels; ++i) {
- a_curves_data[i] = write_trc_tag_for_linear();
+ a_curves_data[i] = write_trc_tag(kLinear_TransFun);
}
}
@@ -460,9 +475,9 @@
tags.emplace_back(kTAG_bTRC,
write_trc_tag(kTrcTableSize, reinterpret_cast<uint8_t*>(trc_table.data())));
} else {
- tags.emplace_back(kTAG_rTRC, write_trc_tag_for_linear());
- tags.emplace_back(kTAG_gTRC, write_trc_tag_for_linear());
- tags.emplace_back(kTAG_bTRC, write_trc_tag_for_linear());
+ tags.emplace_back(kTAG_rTRC, write_trc_tag(kSRGB_TransFun));
+ tags.emplace_back(kTAG_gTRC, write_trc_tag(kSRGB_TransFun));
+ tags.emplace_back(kTAG_bTRC, write_trc_tag(kSRGB_TransFun));
}
}
diff --git a/libs/ultrahdr/include/ultrahdr/gainmapmath.h b/libs/ultrahdr/include/ultrahdr/gainmapmath.h
index edf152d..50b4d2f 100644
--- a/libs/ultrahdr/include/ultrahdr/gainmapmath.h
+++ b/libs/ultrahdr/include/ultrahdr/gainmapmath.h
@@ -51,6 +51,23 @@
typedef Color (*ColorTransformFn)(Color);
typedef float (*ColorCalculationFn)(Color);
+// A transfer function mapping encoded values to linear values,
+// represented by this 7-parameter piecewise function:
+//
+// linear = sign(encoded) * (c*|encoded| + f) , 0 <= |encoded| < d
+// = sign(encoded) * ((a*|encoded| + b)^g + e), d <= |encoded|
+//
+// (A simple gamma transfer function sets g to gamma and a to 1.)
+typedef struct TransferFunction {
+ float g, a,b,c,d,e,f;
+} TransferFunction;
+
+static constexpr TransferFunction kSRGB_TransFun =
+ { 2.4f, (float)(1/1.055), (float)(0.055/1.055), (float)(1/12.92), 0.04045f, 0.0f, 0.0f };
+
+static constexpr TransferFunction kLinear_TransFun =
+ { 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
+
inline Color operator+=(Color& lhs, const Color& rhs) {
lhs.r += rhs.r;
lhs.g += rhs.g;
@@ -312,7 +329,7 @@
float hlgOetfLUT(float e);
Color hlgOetfLUT(Color e);
-constexpr size_t kHlgOETFPrecision = 10;
+constexpr size_t kHlgOETFPrecision = 16;
constexpr size_t kHlgOETFNumEntries = 1 << kHlgOETFPrecision;
/*
@@ -325,7 +342,7 @@
float hlgInvOetfLUT(float e_gamma);
Color hlgInvOetfLUT(Color e_gamma);
-constexpr size_t kHlgInvOETFPrecision = 10;
+constexpr size_t kHlgInvOETFPrecision = 12;
constexpr size_t kHlgInvOETFNumEntries = 1 << kHlgInvOETFPrecision;
/*
@@ -338,7 +355,7 @@
float pqOetfLUT(float e);
Color pqOetfLUT(Color e);
-constexpr size_t kPqOETFPrecision = 10;
+constexpr size_t kPqOETFPrecision = 16;
constexpr size_t kPqOETFNumEntries = 1 << kPqOETFPrecision;
/*
@@ -351,7 +368,7 @@
float pqInvOetfLUT(float e_gamma);
Color pqInvOetfLUT(Color e_gamma);
-constexpr size_t kPqInvOETFPrecision = 10;
+constexpr size_t kPqInvOETFPrecision = 12;
constexpr size_t kPqInvOETFNumEntries = 1 << kPqInvOETFPrecision;
diff --git a/libs/ultrahdr/include/ultrahdr/icc.h b/libs/ultrahdr/include/ultrahdr/icc.h
index 7f047f8..971b267 100644
--- a/libs/ultrahdr/include/ultrahdr/icc.h
+++ b/libs/ultrahdr/include/ultrahdr/icc.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_ULTRAHDR_ICC_H
#define ANDROID_ULTRAHDR_ICC_H
+#include <ultrahdr/gainmapmath.h>
#include <ultrahdr/jpegr.h>
#include <ultrahdr/jpegrutils.h>
#include <utils/RefBase.h>
@@ -222,7 +223,7 @@
const ultrahdr_color_gamut gamut);
static sp<DataStruct> write_xyz_tag(float x, float y, float z);
static sp<DataStruct> write_trc_tag(const int table_entries, const void* table_16);
- static sp<DataStruct> write_trc_tag_for_linear();
+ static sp<DataStruct> write_trc_tag(const TransferFunction& fn);
static float compute_tone_map_gain(const ultrahdr_transfer_function tf, float L);
static sp<DataStruct> write_cicp_tag(uint32_t color_primaries,
uint32_t transfer_characteristics);
diff --git a/libs/ultrahdr/include/ultrahdr/jpegr.h b/libs/ultrahdr/include/ultrahdr/jpegr.h
index a35fd30..f80496a 100644
--- a/libs/ultrahdr/include/ultrahdr/jpegr.h
+++ b/libs/ultrahdr/include/ultrahdr/jpegr.h
@@ -348,16 +348,6 @@
status_t extractPrimaryImageAndGainMap(jr_compressed_ptr compressed_jpegr_image,
jr_compressed_ptr primary_image,
jr_compressed_ptr gain_map);
- /*
- * This method is called in the decoding pipeline. It will read XMP metadata to find the start
- * position of the compressed gain map, and will extract the compressed gain map.
- *
- * @param compressed_jpegr_image compressed JPEGR image
- * @param dest destination of compressed gain map
- * @return NO_ERROR if calculation succeeds, error code if error occurs.
- */
- status_t extractGainMap(jr_compressed_ptr compressed_jpegr_image,
- jr_compressed_ptr dest);
/*
* This method is called in the encoding pipeline. It will take the standard 8-bit JPEG image,
diff --git a/libs/ultrahdr/include/ultrahdr/jpegrerrorcode.h b/libs/ultrahdr/include/ultrahdr/jpegrerrorcode.h
index 0641232..5420e1c 100644
--- a/libs/ultrahdr/include/ultrahdr/jpegrerrorcode.h
+++ b/libs/ultrahdr/include/ultrahdr/jpegrerrorcode.h
@@ -44,6 +44,7 @@
ERROR_JPEGR_INVALID_TRANS_FUNC = JPEGR_IO_ERROR_BASE - 6,
ERROR_JPEGR_INVALID_METADATA = JPEGR_IO_ERROR_BASE - 7,
ERROR_JPEGR_UNSUPPORTED_METADATA = JPEGR_IO_ERROR_BASE - 8,
+ ERROR_JPEGR_GAIN_MAP_IMAGE_NOT_FOUND = JPEGR_IO_ERROR_BASE - 9,
JPEGR_RUNTIME_ERROR_BASE = -20000,
ERROR_JPEGR_ENCODE_ERROR = JPEGR_RUNTIME_ERROR_BASE - 1,
diff --git a/libs/ultrahdr/jpegr.cpp b/libs/ultrahdr/jpegr.cpp
index 9c57f34..5a601bd 100644
--- a/libs/ultrahdr/jpegr.cpp
+++ b/libs/ultrahdr/jpegr.cpp
@@ -539,9 +539,12 @@
return ERROR_JPEGR_INVALID_NULL_PTR;
}
- jpegr_compressed_struct primary_image, gain_map;
- JPEGR_CHECK(extractPrimaryImageAndGainMap(compressed_jpegr_image,
- &primary_image, &gain_map));
+ jpegr_compressed_struct primary_image, gainmap_image;
+ status_t status =
+ extractPrimaryImageAndGainMap(compressed_jpegr_image, &primary_image, &gainmap_image);
+ if (status != NO_ERROR && status != ERROR_JPEGR_GAIN_MAP_IMAGE_NOT_FOUND) {
+ return status;
+ }
JpegDecoderHelper jpeg_decoder;
if (!jpeg_decoder.getCompressedImageParameters(primary_image.data, primary_image.length,
@@ -550,7 +553,7 @@
return ERROR_JPEGR_DECODE_ERROR;
}
- return NO_ERROR;
+ return status;
}
/* Decode API */
@@ -586,90 +589,34 @@
return ERROR_JPEGR_INVALID_INPUT_TYPE;
}
- if (output_format == ULTRAHDR_OUTPUT_SDR) {
- JpegDecoderHelper jpeg_decoder;
- if (!jpeg_decoder.decompressImage(compressed_jpegr_image->data, compressed_jpegr_image->length,
- true)) {
- return ERROR_JPEGR_DECODE_ERROR;
+ jpegr_compressed_struct primary_image, gainmap_image;
+ status_t status =
+ extractPrimaryImageAndGainMap(compressed_jpegr_image, &primary_image, &gainmap_image);
+ if (status != NO_ERROR) {
+ if (output_format != ULTRAHDR_OUTPUT_SDR || status != ERROR_JPEGR_GAIN_MAP_IMAGE_NOT_FOUND) {
+ ALOGE("received invalid compressed jpegr image");
+ return status;
}
- jpegr_uncompressed_struct uncompressed_rgba_image;
- uncompressed_rgba_image.data = jpeg_decoder.getDecompressedImagePtr();
- uncompressed_rgba_image.width = jpeg_decoder.getDecompressedImageWidth();
- uncompressed_rgba_image.height = jpeg_decoder.getDecompressedImageHeight();
- memcpy(dest->data, uncompressed_rgba_image.data,
- uncompressed_rgba_image.width * uncompressed_rgba_image.height * 4);
- dest->width = uncompressed_rgba_image.width;
- dest->height = uncompressed_rgba_image.height;
-
- if (gain_map == nullptr && exif == nullptr) {
- return NO_ERROR;
- }
-
- if (exif != nullptr) {
- if (exif->data == nullptr) {
- return ERROR_JPEGR_INVALID_NULL_PTR;
- }
- if (exif->length < jpeg_decoder.getEXIFSize()) {
- return ERROR_JPEGR_BUFFER_TOO_SMALL;
- }
- memcpy(exif->data, jpeg_decoder.getEXIFPtr(), jpeg_decoder.getEXIFSize());
- exif->length = jpeg_decoder.getEXIFSize();
- }
- if (gain_map == nullptr) {
- return NO_ERROR;
- }
- }
-
- jpegr_compressed_struct compressed_map;
- JPEGR_CHECK(extractGainMap(compressed_jpegr_image, &compressed_map));
-
- JpegDecoderHelper gain_map_decoder;
- if (!gain_map_decoder.decompressImage(compressed_map.data, compressed_map.length)) {
- return ERROR_JPEGR_DECODE_ERROR;
- }
- if ((gain_map_decoder.getDecompressedImageWidth() *
- gain_map_decoder.getDecompressedImageHeight()) >
- gain_map_decoder.getDecompressedImageSize()) {
- return ERROR_JPEGR_CALCULATION_ERROR;
- }
-
- if (gain_map != nullptr) {
- gain_map->width = gain_map_decoder.getDecompressedImageWidth();
- gain_map->height = gain_map_decoder.getDecompressedImageHeight();
- int size = gain_map->width * gain_map->height;
- gain_map->data = malloc(size);
- memcpy(gain_map->data, gain_map_decoder.getDecompressedImagePtr(), size);
- }
-
- ultrahdr_metadata_struct uhdr_metadata;
- if (!getMetadataFromXMP(static_cast<uint8_t*>(gain_map_decoder.getXMPPtr()),
- gain_map_decoder.getXMPSize(), &uhdr_metadata)) {
- return ERROR_JPEGR_INVALID_METADATA;
- }
-
- if (metadata != nullptr) {
- metadata->version = uhdr_metadata.version;
- metadata->minContentBoost = uhdr_metadata.minContentBoost;
- metadata->maxContentBoost = uhdr_metadata.maxContentBoost;
- metadata->gamma = uhdr_metadata.gamma;
- metadata->offsetSdr = uhdr_metadata.offsetSdr;
- metadata->offsetHdr = uhdr_metadata.offsetHdr;
- metadata->hdrCapacityMin = uhdr_metadata.hdrCapacityMin;
- metadata->hdrCapacityMax = uhdr_metadata.hdrCapacityMax;
- }
-
- if (output_format == ULTRAHDR_OUTPUT_SDR) {
- return NO_ERROR;
}
JpegDecoderHelper jpeg_decoder;
- if (!jpeg_decoder.decompressImage(compressed_jpegr_image->data, compressed_jpegr_image->length)) {
+ if (!jpeg_decoder.decompressImage(primary_image.data, primary_image.length,
+ (output_format == ULTRAHDR_OUTPUT_SDR))) {
return ERROR_JPEGR_DECODE_ERROR;
}
- if ((jpeg_decoder.getDecompressedImageWidth() *
- jpeg_decoder.getDecompressedImageHeight() * 3 / 2) >
- jpeg_decoder.getDecompressedImageSize()) {
- return ERROR_JPEGR_CALCULATION_ERROR;
+
+ if (output_format == ULTRAHDR_OUTPUT_SDR) {
+ if ((jpeg_decoder.getDecompressedImageWidth() *
+ jpeg_decoder.getDecompressedImageHeight() * 4) >
+ jpeg_decoder.getDecompressedImageSize()) {
+ return ERROR_JPEGR_CALCULATION_ERROR;
+ }
+ } else {
+ if ((jpeg_decoder.getDecompressedImageWidth() *
+ jpeg_decoder.getDecompressedImageHeight() * 3 / 2) >
+ jpeg_decoder.getDecompressedImageSize()) {
+ return ERROR_JPEGR_CALCULATION_ERROR;
+ }
}
if (exif != nullptr) {
@@ -683,11 +630,53 @@
exif->length = jpeg_decoder.getEXIFSize();
}
+ if (output_format == ULTRAHDR_OUTPUT_SDR) {
+ dest->width = jpeg_decoder.getDecompressedImageWidth();
+ dest->height = jpeg_decoder.getDecompressedImageHeight();
+ memcpy(dest->data, jpeg_decoder.getDecompressedImagePtr(), dest->width * dest->height * 4);
+ return NO_ERROR;
+ }
+
+ JpegDecoderHelper gain_map_decoder;
+ if (!gain_map_decoder.decompressImage(gainmap_image.data, gainmap_image.length)) {
+ return ERROR_JPEGR_DECODE_ERROR;
+ }
+ if ((gain_map_decoder.getDecompressedImageWidth() *
+ gain_map_decoder.getDecompressedImageHeight()) >
+ gain_map_decoder.getDecompressedImageSize()) {
+ return ERROR_JPEGR_CALCULATION_ERROR;
+ }
+
jpegr_uncompressed_struct map;
map.data = gain_map_decoder.getDecompressedImagePtr();
map.width = gain_map_decoder.getDecompressedImageWidth();
map.height = gain_map_decoder.getDecompressedImageHeight();
+ if (gain_map != nullptr) {
+ gain_map->width = map.width;
+ gain_map->height = map.height;
+ int size = gain_map->width * gain_map->height;
+ gain_map->data = malloc(size);
+ memcpy(gain_map->data, map.data, size);
+ }
+
+ ultrahdr_metadata_struct uhdr_metadata;
+ if (!getMetadataFromXMP(static_cast<uint8_t*>(gain_map_decoder.getXMPPtr()),
+ gain_map_decoder.getXMPSize(), &uhdr_metadata)) {
+ return ERROR_JPEGR_INVALID_METADATA;
+ }
+
+ if (metadata != nullptr) {
+ metadata->version = uhdr_metadata.version;
+ metadata->minContentBoost = uhdr_metadata.minContentBoost;
+ metadata->maxContentBoost = uhdr_metadata.maxContentBoost;
+ metadata->gamma = uhdr_metadata.gamma;
+ metadata->offsetSdr = uhdr_metadata.offsetSdr;
+ metadata->offsetHdr = uhdr_metadata.offsetHdr;
+ metadata->hdrCapacityMin = uhdr_metadata.hdrCapacityMin;
+ metadata->hdrCapacityMax = uhdr_metadata.hdrCapacityMax;
+ }
+
jpegr_uncompressed_struct uncompressed_yuv_420_image;
uncompressed_yuv_420_image.data = jpeg_decoder.getDecompressedImagePtr();
uncompressed_yuv_420_image.width = jpeg_decoder.getDecompressedImageWidth();
@@ -1070,7 +1059,7 @@
}
case ULTRAHDR_OUTPUT_HDR_PQ:
{
-#if USE_HLG_OETF_LUT
+#if USE_PQ_OETF_LUT
ColorTransformFn hdrOetf = pqOetfLUT;
#else
ColorTransformFn hdrOetf = pqOetf;
@@ -1131,12 +1120,8 @@
const auto& jpeg_info = jpeg_info_builder.GetInfo();
const auto& image_ranges = jpeg_info.GetImageRanges();
- if (image_ranges.empty()) {
- return ERROR_JPEGR_INVALID_INPUT_TYPE;
- }
- if (image_ranges.size() != 2) {
- // Must be 2 JPEG Images
+ if (image_ranges.empty()) {
return ERROR_JPEGR_INVALID_INPUT_TYPE;
}
@@ -1146,23 +1131,23 @@
primary_image->length = image_ranges[0].GetLength();
}
+ if (image_ranges.size() == 1) {
+ return ERROR_JPEGR_GAIN_MAP_IMAGE_NOT_FOUND;
+ }
+
if (gain_map != nullptr) {
gain_map->data = static_cast<uint8_t*>(compressed_jpegr_image->data) +
image_ranges[1].GetBegin();
gain_map->length = image_ranges[1].GetLength();
}
- return NO_ERROR;
-}
-
-
-status_t JpegR::extractGainMap(jr_compressed_ptr compressed_jpegr_image,
- jr_compressed_ptr dest) {
- if (compressed_jpegr_image == nullptr || dest == nullptr) {
- return ERROR_JPEGR_INVALID_NULL_PTR;
+ // TODO: choose primary image and gain map image carefully
+ if (image_ranges.size() > 2) {
+ ALOGW("Number of jpeg images present %d, primary, gain map images may not be correctly chosen",
+ (int)image_ranges.size());
}
- return extractPrimaryImageAndGainMap(compressed_jpegr_image, nullptr, dest);
+ return NO_ERROR;
}
// JPEG/R structure:
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index b007fd3..8f62629 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -185,13 +185,6 @@
header_libs: [
"libinputflinger_headers",
],
- target: {
- host: {
- static_libs: [
- "libui-types",
- ],
- },
- },
}
cc_library_shared {
diff --git a/services/inputflinger/InputDeviceMetricsCollector.cpp b/services/inputflinger/InputDeviceMetricsCollector.cpp
index 999e175..89e37db 100644
--- a/services/inputflinger/InputDeviceMetricsCollector.cpp
+++ b/services/inputflinger/InputDeviceMetricsCollector.cpp
@@ -31,7 +31,7 @@
namespace {
-constexpr nanoseconds DEFAULT_USAGE_SESSION_TIMEOUT = std::chrono::minutes(2);
+constexpr nanoseconds DEFAULT_USAGE_SESSION_TIMEOUT = std::chrono::seconds(5);
/**
* Log debug messages about metrics events logged to statsd.
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index 37b3187..1a9f47d 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -34,7 +34,7 @@
namespace android {
static const bool ENABLE_INPUT_DEVICE_USAGE_METRICS =
- sysprop::InputProperties::enable_input_device_usage_metrics().value_or(true);
+ sysprop::InputProperties::enable_input_device_usage_metrics().value_or(false);
using gui::FocusRequest;
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index fffb640..29c4e46 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -654,7 +654,6 @@
TouchedWindow touchedWindow;
touchedWindow.windowHandle = oldWindow;
touchedWindow.targetFlags = InputTarget::Flags::DISPATCH_AS_HOVER_EXIT;
- touchedWindow.pointerIds.set(pointerId);
out.push_back(touchedWindow);
}
}
@@ -673,7 +672,7 @@
}
touchedWindow.targetFlags = InputTarget::Flags::DISPATCH_AS_IS;
}
- touchedWindow.pointerIds.set(pointerId);
+ touchedWindow.addHoveringPointer(entry.deviceId, pointerId);
if (canReceiveForegroundTouches(*newWindow->getInfo())) {
touchedWindow.targetFlags |= InputTarget::Flags::FOREGROUND;
}
@@ -2195,8 +2194,8 @@
/**
* In general, touch should be always split between windows. Some exceptions:
* 1. Don't split touch is if we have an active pointer down, and a new pointer is going down that's
- * from the same device, *and* the window that's receiving the current pointer does not support
- * split touch.
+ * from the same device, *and* the window that's receiving the current pointer does not support
+ * split touch.
* 2. Don't split mouse events
*/
bool InputDispatcher::shouldSplitTouch(const TouchState& touchState,
@@ -2219,9 +2218,7 @@
continue;
}
- // Eventually, touchedWindow will contain the deviceId of each pointer that's currently
- // being sent there. For now, use deviceId from touch state.
- if (entry.deviceId == touchState.deviceId && touchedWindow.pointerIds.any()) {
+ if (touchedWindow.hasTouchingPointers(entry.deviceId)) {
return false;
}
}
@@ -2254,8 +2251,14 @@
}
bool isSplit = shouldSplitTouch(tempTouchState, entry);
- const bool switchedDevice = (oldState != nullptr) &&
- (oldState->deviceId != entry.deviceId || oldState->source != entry.source);
+ bool switchedDevice = false;
+ if (oldState != nullptr) {
+ std::set<int32_t> oldActiveDevices = oldState->getActiveDeviceIds();
+ const bool anotherDeviceIsActive =
+ oldActiveDevices.count(entry.deviceId) == 0 && !oldActiveDevices.empty();
+ switchedDevice |= anotherDeviceIsActive;
+ switchedDevice |= oldState->source != entry.source;
+ }
const bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE ||
maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER ||
@@ -2274,7 +2277,7 @@
// from another device. However, if the new event is a down event, let's cancel the current
// touch and let the new one take over.
if (switchedDevice && wasDown && !isDown) {
- LOG(INFO) << "Dropping event because a pointer for device " << oldState->deviceId
+ LOG(INFO) << "Dropping event because a pointer for another device "
<< " is already down in display " << displayId << ": " << entry.getDescription();
// TODO(b/211379801): test multiple simultaneous input streams.
outInjectionResult = InputEventInjectionResult::FAILED;
@@ -2284,7 +2287,6 @@
if (newGesture) {
// If a new gesture is starting, clear the touch state completely.
tempTouchState.reset();
- tempTouchState.deviceId = entry.deviceId;
tempTouchState.source = entry.source;
isSplit = false;
} else if (switchedDevice && maskedAction == AMOTION_EVENT_ACTION_MOVE) {
@@ -2404,7 +2406,7 @@
// still add a window to the touch state. We should avoid doing that, but some of the
// later checks ("at least one foreground window") rely on this in order to dispatch
// the event properly, so that needs to be updated, possibly by looking at InputTargets.
- tempTouchState.addOrUpdateWindow(windowHandle, targetFlags, pointerIds,
+ tempTouchState.addOrUpdateWindow(windowHandle, targetFlags, entry.deviceId, pointerIds,
isDownOrPointerDown
? std::make_optional(entry.eventTime)
: std::nullopt);
@@ -2428,8 +2430,8 @@
if (isSplit) {
wallpaperFlags |= InputTarget::Flags::SPLIT;
}
- tempTouchState.addOrUpdateWindow(wallpaper, wallpaperFlags, pointerIds,
- entry.eventTime);
+ tempTouchState.addOrUpdateWindow(wallpaper, wallpaperFlags, entry.deviceId,
+ pointerIds, entry.eventTime);
}
}
}
@@ -2440,12 +2442,12 @@
// which is a specific behaviour that we want.
const int32_t pointerId = entry.pointerProperties[pointerIndex].id;
for (TouchedWindow& touchedWindow : tempTouchState.windows) {
- if (touchedWindow.pointerIds.test(pointerId) &&
- touchedWindow.pilferedPointerIds.count() > 0) {
+ if (touchedWindow.hasTouchingPointer(entry.deviceId, pointerId) &&
+ touchedWindow.hasPilferingPointers(entry.deviceId)) {
// This window is already pilfering some pointers, and this new pointer is also
// going to it. Therefore, take over this pointer and don't give it to anyone
// else.
- touchedWindow.pilferedPointerIds.set(pointerId);
+ touchedWindow.addPilferingPointer(entry.deviceId, pointerId);
}
}
@@ -2517,7 +2519,7 @@
tempTouchState.getTouchedWindow(oldTouchedWindowHandle);
addWindowTargetLocked(oldTouchedWindowHandle,
InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT, pointerIds,
- touchedWindow.firstDownTimeInTarget, targets);
+ touchedWindow.getDownTimeInTarget(entry.deviceId), targets);
// Make a slippery entrance into the new window.
if (newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
@@ -2538,13 +2540,14 @@
targetFlags |= InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
}
- tempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds,
- entry.eventTime);
+ tempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags,
+ entry.deviceId, pointerIds, entry.eventTime);
// Check if the wallpaper window should deliver the corresponding event.
slipWallpaperTouch(targetFlags, oldTouchedWindowHandle, newTouchedWindowHandle,
- tempTouchState, pointerId, targets);
- tempTouchState.removeTouchedPointerFromWindow(pointerId, oldTouchedWindowHandle);
+ tempTouchState, entry.deviceId, pointerId, targets);
+ tempTouchState.removeTouchingPointerFromWindow(entry.deviceId, pointerId,
+ oldTouchedWindowHandle);
}
}
@@ -2558,7 +2561,8 @@
if (mDragState && mDragState->dragWindow == touchedWindow.windowHandle) {
continue;
}
- touchedWindow.pointerIds.set(entry.pointerProperties[pointerIndex].id);
+ touchedWindow.addTouchingPointer(entry.deviceId,
+ entry.pointerProperties[pointerIndex].id);
}
}
}
@@ -2570,7 +2574,7 @@
for (const TouchedWindow& touchedWindow : hoveringWindows) {
std::optional<InputTarget> target =
createInputTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
- touchedWindow.firstDownTimeInTarget);
+ touchedWindow.getDownTimeInTarget(entry.deviceId));
if (!target) {
continue;
}
@@ -2627,15 +2631,16 @@
// Output targets from the touch state.
for (const TouchedWindow& touchedWindow : tempTouchState.windows) {
- if (touchedWindow.pointerIds.none() && !touchedWindow.hasHoveringPointers(entry.deviceId)) {
+ if (!touchedWindow.hasTouchingPointers(entry.deviceId) &&
+ !touchedWindow.hasHoveringPointers(entry.deviceId)) {
// Windows with hovering pointers are getting persisted inside TouchState.
// Do not send this event to those windows.
continue;
}
addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
- touchedWindow.pointerIds, touchedWindow.firstDownTimeInTarget,
- targets);
+ touchedWindow.getTouchingPointers(entry.deviceId),
+ touchedWindow.getDownTimeInTarget(entry.deviceId), targets);
}
// During targeted injection, only allow owned targets to receive events
@@ -2689,12 +2694,11 @@
}
if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER ||
maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
- tempTouchState.deviceId = entry.deviceId;
tempTouchState.source = entry.source;
}
} else if (maskedAction == AMOTION_EVENT_ACTION_UP) {
// Pointer went up.
- tempTouchState.removeTouchedPointer(entry.pointerProperties[0].id);
+ tempTouchState.removeTouchingPointer(entry.deviceId, entry.pointerProperties[0].id);
} else if (maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
// All pointers up or canceled.
tempTouchState.reset();
@@ -2711,8 +2715,8 @@
for (size_t i = 0; i < tempTouchState.windows.size();) {
TouchedWindow& touchedWindow = tempTouchState.windows[i];
- touchedWindow.pointerIds.reset(pointerId);
- if (touchedWindow.pointerIds.none()) {
+ touchedWindow.removeTouchingPointer(entry.deviceId, pointerId);
+ if (!touchedWindow.hasTouchingPointers(entry.deviceId)) {
tempTouchState.windows.erase(tempTouchState.windows.begin() + i);
continue;
}
@@ -4389,7 +4393,7 @@
const auto touchStateIt = mTouchStatesByDisplay.find(args.displayId);
if (touchStateIt != mTouchStatesByDisplay.end()) {
const TouchState& touchState = touchStateIt->second;
- if (touchState.deviceId == args.deviceId && touchState.isDown()) {
+ if (touchState.hasTouchingPointers(args.deviceId)) {
policyFlags |= POLICY_FLAG_PASS_TO_USER;
}
}
@@ -5427,14 +5431,22 @@
// Find the target touch state and touched window by fromToken.
auto [state, touchedWindow, displayId] = findTouchStateWindowAndDisplayLocked(fromToken);
+
if (state == nullptr || touchedWindow == nullptr) {
- ALOGD("Focus transfer failed because from window is not being touched.");
+ ALOGD("Touch transfer failed because from window is not being touched.");
return false;
}
+ std::set<int32_t> deviceIds = touchedWindow->getTouchingDeviceIds();
+ if (deviceIds.size() != 1) {
+ LOG(DEBUG) << "Can't transfer touch. Currently touching devices: " << dumpSet(deviceIds)
+ << " for window: " << touchedWindow->dump();
+ return false;
+ }
+ const int32_t deviceId = *deviceIds.begin();
sp<WindowInfoHandle> toWindowHandle = getWindowHandleLocked(toToken, displayId);
if (toWindowHandle == nullptr) {
- ALOGW("Cannot transfer focus because to window not found.");
+ ALOGW("Cannot transfer touch because to window not found.");
return false;
}
@@ -5446,7 +5458,7 @@
// Erase old window.
ftl::Flags<InputTarget::Flags> oldTargetFlags = touchedWindow->targetFlags;
- std::bitset<MAX_POINTER_ID + 1> pointerIds = touchedWindow->pointerIds;
+ std::bitset<MAX_POINTER_ID + 1> pointerIds = touchedWindow->getTouchingPointers(deviceId);
sp<WindowInfoHandle> fromWindowHandle = touchedWindow->windowHandle;
state->removeWindowByToken(fromToken);
@@ -5457,7 +5469,8 @@
if (canReceiveForegroundTouches(*toWindowHandle->getInfo())) {
newTargetFlags |= InputTarget::Flags::FOREGROUND;
}
- state->addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds, downTimeInTarget);
+ state->addOrUpdateWindow(toWindowHandle, newTargetFlags, deviceId, pointerIds,
+ downTimeInTarget);
// Store the dragging window.
if (isDragDrop) {
@@ -5476,16 +5489,15 @@
std::shared_ptr<Connection> toConnection = getConnectionLocked(toToken);
if (fromConnection != nullptr && toConnection != nullptr) {
fromConnection->inputState.mergePointerStateTo(toConnection->inputState);
- CancelationOptions
- options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
- "transferring touch focus from this window to another window");
+ CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
+ "transferring touch from this window to another window");
synthesizeCancelationEventsForConnectionLocked(fromConnection, options);
synthesizePointerDownEventsForConnectionLocked(downTimeInTarget, toConnection,
newTargetFlags);
// Check if the wallpaper window should deliver the corresponding event.
transferWallpaperTouch(oldTargetFlags, newTargetFlags, fromWindowHandle, toWindowHandle,
- *state, pointerIds);
+ *state, deviceId, pointerIds);
}
} // release lock
@@ -5969,20 +5981,28 @@
}
auto [statePtr, windowPtr, displayId] = findTouchStateWindowAndDisplayLocked(token);
- if (statePtr == nullptr || windowPtr == nullptr || windowPtr->pointerIds.none()) {
+ if (statePtr == nullptr || windowPtr == nullptr) {
ALOGW("Attempted to pilfer points from a channel without any on-going pointer streams."
" Ignoring.");
return BAD_VALUE;
}
+ std::set<int32_t> deviceIds = windowPtr->getTouchingDeviceIds();
+ if (deviceIds.size() != 1) {
+ LOG(WARNING) << "Can't pilfer. Currently touching devices: " << dumpSet(deviceIds)
+ << " in window: " << windowPtr->dump();
+ return BAD_VALUE;
+ }
+ const int32_t deviceId = *deviceIds.begin();
TouchState& state = *statePtr;
TouchedWindow& window = *windowPtr;
// Send cancel events to all the input channels we're stealing from.
CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
"input channel stole pointer stream");
- options.deviceId = state.deviceId;
+ options.deviceId = deviceId;
options.displayId = displayId;
- options.pointerIds = window.pointerIds;
+ std::bitset<MAX_POINTER_ID + 1> pointerIds = window.getTouchingPointers(deviceId);
+ options.pointerIds = pointerIds;
std::string canceledWindows;
for (const TouchedWindow& w : state.windows) {
const std::shared_ptr<InputChannel> channel =
@@ -5999,9 +6019,9 @@
// Prevent the gesture from being sent to any other windows.
// This only blocks relevant pointers to be sent to other windows
- window.pilferedPointerIds |= window.pointerIds;
+ window.addPilferingPointers(deviceId, pointerIds);
- state.cancelPointersForWindowsExcept(window.pointerIds, token);
+ state.cancelPointersForWindowsExcept(deviceId, pointerIds, token);
return OK;
}
@@ -6781,7 +6801,7 @@
void InputDispatcher::slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
const sp<WindowInfoHandle>& oldWindowHandle,
const sp<WindowInfoHandle>& newWindowHandle,
- TouchState& state, int32_t pointerId,
+ TouchState& state, int32_t deviceId, int32_t pointerId,
std::vector<InputTarget>& targets) const {
std::bitset<MAX_POINTER_ID + 1> pointerIds;
pointerIds.set(pointerId);
@@ -6803,8 +6823,8 @@
addWindowTargetLocked(oldWallpaper,
oldTouchedWindow.targetFlags |
InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT,
- pointerIds, oldTouchedWindow.firstDownTimeInTarget, targets);
- state.removeTouchedPointerFromWindow(pointerId, oldWallpaper);
+ pointerIds, oldTouchedWindow.getDownTimeInTarget(deviceId), targets);
+ state.removeTouchingPointerFromWindow(deviceId, pointerId, oldWallpaper);
}
if (newWallpaper != nullptr) {
@@ -6812,7 +6832,7 @@
InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER |
InputTarget::Flags::WINDOW_IS_OBSCURED |
InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED,
- pointerIds);
+ deviceId, pointerIds);
}
}
@@ -6820,7 +6840,7 @@
ftl::Flags<InputTarget::Flags> newTargetFlags,
const sp<WindowInfoHandle> fromWindowHandle,
const sp<WindowInfoHandle> toWindowHandle,
- TouchState& state,
+ TouchState& state, int32_t deviceId,
std::bitset<MAX_POINTER_ID + 1> pointerIds) {
const bool oldHasWallpaper = oldTargetFlags.test(InputTarget::Flags::FOREGROUND) &&
fromWindowHandle->getInfo()->inputConfig.test(
@@ -6850,7 +6870,8 @@
oldTargetFlags & (InputTarget::Flags::SPLIT | InputTarget::Flags::DISPATCH_AS_IS);
wallpaperFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED |
InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
- state.addOrUpdateWindow(newWallpaper, wallpaperFlags, pointerIds, downTimeInTarget);
+ state.addOrUpdateWindow(newWallpaper, wallpaperFlags, deviceId, pointerIds,
+ downTimeInTarget);
std::shared_ptr<Connection> wallpaperConnection =
getConnectionLocked(newWallpaper->getToken());
if (wallpaperConnection != nullptr) {
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 78d268d..9cd1666 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -711,14 +711,14 @@
void slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
const sp<android::gui::WindowInfoHandle>& oldWindowHandle,
const sp<android::gui::WindowInfoHandle>& newWindowHandle,
- TouchState& state, int32_t pointerId,
+ TouchState& state, int32_t deviceId, int32_t pointerId,
std::vector<InputTarget>& targets) const REQUIRES(mLock);
void transferWallpaperTouch(ftl::Flags<InputTarget::Flags> oldTargetFlags,
ftl::Flags<InputTarget::Flags> newTargetFlags,
const sp<android::gui::WindowInfoHandle> fromWindowHandle,
const sp<android::gui::WindowInfoHandle> toWindowHandle,
- TouchState& state, std::bitset<MAX_POINTER_ID + 1> pointerIds)
- REQUIRES(mLock);
+ TouchState& state, int32_t deviceId,
+ std::bitset<MAX_POINTER_ID + 1> pointerIds) REQUIRES(mLock);
sp<android::gui::WindowInfoHandle> findWallpaperWindowBelow(
const sp<android::gui::WindowInfoHandle>& windowHandle) const REQUIRES(mLock);
diff --git a/services/inputflinger/dispatcher/TouchState.cpp b/services/inputflinger/dispatcher/TouchState.cpp
index 0a61d48..dcbb366 100644
--- a/services/inputflinger/dispatcher/TouchState.cpp
+++ b/services/inputflinger/dispatcher/TouchState.cpp
@@ -31,18 +31,34 @@
*this = TouchState();
}
-void TouchState::removeTouchedPointer(int32_t pointerId) {
+std::set<int32_t> TouchState::getActiveDeviceIds() const {
+ std::set<int32_t> out;
+ for (const TouchedWindow& w : windows) {
+ std::set<int32_t> deviceIds = w.getActiveDeviceIds();
+ out.insert(deviceIds.begin(), deviceIds.end());
+ }
+ return out;
+}
+
+bool TouchState::hasTouchingPointers(int32_t deviceId) const {
+ return std::any_of(windows.begin(), windows.end(), [&](const TouchedWindow& window) {
+ return window.hasTouchingPointers(deviceId);
+ });
+}
+
+void TouchState::removeTouchingPointer(int32_t removedDeviceId, int32_t pointerId) {
for (TouchedWindow& touchedWindow : windows) {
- touchedWindow.removeTouchingPointer(pointerId);
+ touchedWindow.removeTouchingPointer(removedDeviceId, pointerId);
}
clearWindowsWithoutPointers();
}
-void TouchState::removeTouchedPointerFromWindow(
- int32_t pointerId, const sp<android::gui::WindowInfoHandle>& windowHandle) {
+void TouchState::removeTouchingPointerFromWindow(
+ int32_t removedDeviceId, int32_t pointerId,
+ const sp<android::gui::WindowInfoHandle>& windowHandle) {
for (TouchedWindow& touchedWindow : windows) {
if (touchedWindow.windowHandle == windowHandle) {
- touchedWindow.removeTouchingPointer(pointerId);
+ touchedWindow.removeTouchingPointer(removedDeviceId, pointerId);
clearWindowsWithoutPointers();
return;
}
@@ -58,13 +74,14 @@
void TouchState::clearWindowsWithoutPointers() {
std::erase_if(windows, [](const TouchedWindow& w) {
- return w.pointerIds.none() && !w.hasHoveringPointers();
+ return !w.hasTouchingPointers() && !w.hasHoveringPointers();
});
}
void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle,
ftl::Flags<InputTarget::Flags> targetFlags,
- std::bitset<MAX_POINTER_ID + 1> pointerIds,
+ int32_t addedDeviceId,
+ std::bitset<MAX_POINTER_ID + 1> touchingPointerIds,
std::optional<nsecs_t> firstDownTimeInTarget) {
for (TouchedWindow& touchedWindow : windows) {
// We do not compare windows by token here because two windows that share the same token
@@ -75,11 +92,11 @@
touchedWindow.targetFlags.clear(InputTarget::Flags::DISPATCH_AS_IS);
}
// For cases like hover enter/exit or DISPATCH_AS_OUTSIDE a touch window might not have
- // downTime set initially. Need to update existing window when an pointer is down for
- // the window.
- touchedWindow.pointerIds |= pointerIds;
- if (!touchedWindow.firstDownTimeInTarget.has_value()) {
- touchedWindow.firstDownTimeInTarget = firstDownTimeInTarget;
+ // downTime set initially. Need to update existing window when a pointer is down for the
+ // window.
+ touchedWindow.addTouchingPointers(addedDeviceId, touchingPointerIds);
+ if (firstDownTimeInTarget) {
+ touchedWindow.trySetDownTimeInTarget(addedDeviceId, *firstDownTimeInTarget);
}
return;
}
@@ -87,8 +104,10 @@
TouchedWindow touchedWindow;
touchedWindow.windowHandle = windowHandle;
touchedWindow.targetFlags = targetFlags;
- touchedWindow.pointerIds = pointerIds;
- touchedWindow.firstDownTimeInTarget = firstDownTimeInTarget;
+ touchedWindow.addTouchingPointers(addedDeviceId, touchingPointerIds);
+ if (firstDownTimeInTarget) {
+ touchedWindow.trySetDownTimeInTarget(addedDeviceId, *firstDownTimeInTarget);
+ }
windows.push_back(touchedWindow);
}
@@ -130,12 +149,12 @@
}
}
-void TouchState::cancelPointersForWindowsExcept(std::bitset<MAX_POINTER_ID + 1> pointerIds,
+void TouchState::cancelPointersForWindowsExcept(int32_t touchedDeviceId,
+ std::bitset<MAX_POINTER_ID + 1> pointerIds,
const sp<IBinder>& token) {
- if (pointerIds.none()) return;
- std::for_each(windows.begin(), windows.end(), [&pointerIds, &token](TouchedWindow& w) {
+ std::for_each(windows.begin(), windows.end(), [&](TouchedWindow& w) {
if (w.windowHandle->getToken() != token) {
- w.pointerIds &= ~pointerIds;
+ w.removeTouchingPointers(touchedDeviceId, pointerIds);
}
});
clearWindowsWithoutPointers();
@@ -149,24 +168,29 @@
*/
void TouchState::cancelPointersForNonPilferingWindows() {
// First, find all pointers that are being pilfered, across all windows
- std::bitset<MAX_POINTER_ID + 1> allPilferedPointerIds;
- std::for_each(windows.begin(), windows.end(), [&allPilferedPointerIds](const TouchedWindow& w) {
- allPilferedPointerIds |= w.pilferedPointerIds;
- });
+ std::map<int32_t /*deviceId*/, std::bitset<MAX_POINTER_ID + 1>> allPilferedPointerIdsByDevice;
+ for (const TouchedWindow& w : windows) {
+ for (const auto& [iterDeviceId, pilferedPointerIds] : w.getPilferingPointers()) {
+ allPilferedPointerIdsByDevice[iterDeviceId] |= pilferedPointerIds;
+ }
+ };
// Optimization: most of the time, pilfering does not occur
- if (allPilferedPointerIds.none()) return;
+ if (allPilferedPointerIdsByDevice.empty()) return;
// Now, remove all pointers from every window that's being pilfered by other windows.
// For example, if window A is pilfering pointer 1 (only), and window B is pilfering pointer 2
// (only), the remove pointer 2 from window A and pointer 1 from window B. Usually, the set of
// pilfered pointers will be disjoint across all windows, but there's no reason to cause that
// limitation here.
- std::for_each(windows.begin(), windows.end(), [&allPilferedPointerIds](TouchedWindow& w) {
- std::bitset<MAX_POINTER_ID + 1> pilferedByOtherWindows =
- w.pilferedPointerIds ^ allPilferedPointerIds;
- w.pointerIds &= ~pilferedByOtherWindows;
- });
+ for (const auto& [iterDeviceId, allPilferedPointerIds] : allPilferedPointerIdsByDevice) {
+ std::for_each(windows.begin(), windows.end(), [&](TouchedWindow& w) {
+ std::bitset<MAX_POINTER_ID + 1> pilferedByOtherWindows =
+ w.getPilferingPointers(iterDeviceId) ^ allPilferedPointerIds;
+ // Remove all pointers pilfered by other windows
+ w.removeTouchingPointers(iterDeviceId, pilferedByOtherWindows);
+ });
+ }
clearWindowsWithoutPointers();
}
@@ -216,7 +240,7 @@
bool TouchState::isDown() const {
return std::any_of(windows.begin(), windows.end(),
- [](const TouchedWindow& window) { return window.pointerIds.any(); });
+ [](const TouchedWindow& window) { return window.hasTouchingPointers(); });
}
bool TouchState::hasHoveringPointers() const {
@@ -245,19 +269,15 @@
void TouchState::removeAllPointersForDevice(int32_t removedDeviceId) {
for (TouchedWindow& window : windows) {
window.removeAllHoveringPointersForDevice(removedDeviceId);
+ window.removeAllTouchingPointersForDevice(removedDeviceId);
}
- if (deviceId == removedDeviceId) {
- for (TouchedWindow& window : windows) {
- window.removeAllTouchingPointers();
- }
- }
+
clearWindowsWithoutPointers();
}
std::string TouchState::dump() const {
std::string out;
- out += StringPrintf("deviceId=%d, source=%s\n", deviceId,
- inputEventSourceToString(source).c_str());
+ out += StringPrintf("source=%s\n", inputEventSourceToString(source).c_str());
if (!windows.empty()) {
out += " Windows:\n";
for (size_t i = 0; i < windows.size(); i++) {
diff --git a/services/inputflinger/dispatcher/TouchState.h b/services/inputflinger/dispatcher/TouchState.h
index 15b840f..1bda0fb 100644
--- a/services/inputflinger/dispatcher/TouchState.h
+++ b/services/inputflinger/dispatcher/TouchState.h
@@ -29,8 +29,6 @@
namespace inputdispatcher {
struct TouchState {
- // id of the device that is currently down, others are rejected
- int32_t deviceId = -1;
// source of the device that is current down, others are rejected
uint32_t source = 0;
@@ -43,24 +41,28 @@
void reset();
void clearWindowsWithoutPointers();
- void removeTouchedPointer(int32_t pointerId);
- void removeTouchedPointerFromWindow(int32_t pointerId,
- const sp<android::gui::WindowInfoHandle>& windowHandle);
+ std::set<int32_t> getActiveDeviceIds() const;
+
+ bool hasTouchingPointers(int32_t device) const;
+ void removeTouchingPointer(int32_t deviceId, int32_t pointerId);
+ void removeTouchingPointerFromWindow(int32_t deviceId, int32_t pointerId,
+ const sp<android::gui::WindowInfoHandle>& windowHandle);
void addOrUpdateWindow(const sp<android::gui::WindowInfoHandle>& windowHandle,
- ftl::Flags<InputTarget::Flags> targetFlags,
- std::bitset<MAX_POINTER_ID + 1> pointerIds,
+ ftl::Flags<InputTarget::Flags> targetFlags, int32_t deviceId,
+ std::bitset<MAX_POINTER_ID + 1> touchingPointerIds,
std::optional<nsecs_t> firstDownTimeInTarget = std::nullopt);
void addHoveringPointerToWindow(const sp<android::gui::WindowInfoHandle>& windowHandle,
int32_t deviceId, int32_t hoveringPointerId);
void removeHoveringPointer(int32_t deviceId, int32_t hoveringPointerId);
void clearHoveringPointers();
- void removeAllPointersForDevice(int32_t removedDeviceId);
+ void removeAllPointersForDevice(int32_t deviceId);
void removeWindowByToken(const sp<IBinder>& token);
void filterNonAsIsTouchWindows();
// Cancel pointers for current set of windows except the window with particular binder token.
- void cancelPointersForWindowsExcept(std::bitset<MAX_POINTER_ID + 1> pointerIds,
+ void cancelPointersForWindowsExcept(int32_t deviceId,
+ std::bitset<MAX_POINTER_ID + 1> pointerIds,
const sp<IBinder>& token);
// Cancel pointers for current set of non-pilfering windows i.e. windows with isPilferingWindow
// set to false.
diff --git a/services/inputflinger/dispatcher/TouchedWindow.cpp b/services/inputflinger/dispatcher/TouchedWindow.cpp
index d55d657..ae16520 100644
--- a/services/inputflinger/dispatcher/TouchedWindow.cpp
+++ b/services/inputflinger/dispatcher/TouchedWindow.cpp
@@ -16,6 +16,7 @@
#include "TouchedWindow.h"
+#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <input/PrintTools.h>
@@ -26,67 +27,236 @@
namespace inputdispatcher {
bool TouchedWindow::hasHoveringPointers() const {
- return !mHoveringPointerIdsByDevice.empty();
+ for (const auto& [_, state] : mDeviceStates) {
+ if (state.hoveringPointerIds.any()) {
+ return true;
+ }
+ }
+ return false;
}
bool TouchedWindow::hasHoveringPointers(int32_t deviceId) const {
- return mHoveringPointerIdsByDevice.find(deviceId) != mHoveringPointerIdsByDevice.end();
+ const auto stateIt = mDeviceStates.find(deviceId);
+ if (stateIt == mDeviceStates.end()) {
+ return false;
+ }
+ const DeviceState& state = stateIt->second;
+
+ return state.hoveringPointerIds.any();
}
void TouchedWindow::clearHoveringPointers() {
- mHoveringPointerIdsByDevice.clear();
+ for (auto& [_, state] : mDeviceStates) {
+ state.hoveringPointerIds.reset();
+ }
+
+ std::erase_if(mDeviceStates, [](const auto& pair) { return !pair.second.hasPointers(); });
}
bool TouchedWindow::hasHoveringPointer(int32_t deviceId, int32_t pointerId) const {
- auto it = mHoveringPointerIdsByDevice.find(deviceId);
- if (it == mHoveringPointerIdsByDevice.end()) {
+ const auto stateIt = mDeviceStates.find(deviceId);
+ if (stateIt == mDeviceStates.end()) {
return false;
}
- return it->second.test(pointerId);
+ const DeviceState& state = stateIt->second;
+
+ return state.hoveringPointerIds.test(pointerId);
}
void TouchedWindow::addHoveringPointer(int32_t deviceId, int32_t pointerId) {
- const auto [it, _] = mHoveringPointerIdsByDevice.insert({deviceId, {}});
- it->second.set(pointerId);
+ mDeviceStates[deviceId].hoveringPointerIds.set(pointerId);
}
-void TouchedWindow::removeTouchingPointer(int32_t pointerId) {
- pointerIds.reset(pointerId);
- pilferedPointerIds.reset(pointerId);
- if (pointerIds.none()) {
- firstDownTimeInTarget.reset();
+void TouchedWindow::addTouchingPointer(int32_t deviceId, int32_t pointerId) {
+ mDeviceStates[deviceId].touchingPointerIds.set(pointerId);
+}
+
+void TouchedWindow::addTouchingPointers(int32_t deviceId,
+ std::bitset<MAX_POINTER_ID + 1> pointers) {
+ mDeviceStates[deviceId].touchingPointerIds |= pointers;
+}
+
+bool TouchedWindow::hasTouchingPointers() const {
+ for (const auto& [_, state] : mDeviceStates) {
+ if (state.touchingPointerIds.any()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool TouchedWindow::hasTouchingPointers(int32_t deviceId) const {
+ return getTouchingPointers(deviceId).any();
+}
+
+bool TouchedWindow::hasTouchingPointer(int32_t deviceId, int32_t pointerId) const {
+ return getTouchingPointers(deviceId).test(pointerId);
+}
+
+std::bitset<MAX_POINTER_ID + 1> TouchedWindow::getTouchingPointers(int32_t deviceId) const {
+ const auto stateIt = mDeviceStates.find(deviceId);
+ if (stateIt == mDeviceStates.end()) {
+ return {};
+ }
+ const DeviceState& state = stateIt->second;
+
+ return state.touchingPointerIds;
+}
+
+void TouchedWindow::removeTouchingPointer(int32_t deviceId, int32_t pointerId) {
+ std::bitset<MAX_POINTER_ID + 1> pointerIds;
+ pointerIds.set(pointerId, true);
+
+ removeTouchingPointers(deviceId, pointerIds);
+}
+
+void TouchedWindow::removeTouchingPointers(int32_t deviceId,
+ std::bitset<MAX_POINTER_ID + 1> pointers) {
+ const auto stateIt = mDeviceStates.find(deviceId);
+ if (stateIt == mDeviceStates.end()) {
+ return;
+ }
+ DeviceState& state = stateIt->second;
+
+ state.touchingPointerIds &= ~pointers;
+ state.pilferingPointerIds &= ~pointers;
+
+ if (!state.hasPointers()) {
+ mDeviceStates.erase(stateIt);
}
}
-void TouchedWindow::removeAllTouchingPointers() {
- pointerIds.reset();
+std::set<int32_t> TouchedWindow::getTouchingDeviceIds() const {
+ std::set<int32_t> deviceIds;
+ for (const auto& [deviceId, _] : mDeviceStates) {
+ deviceIds.insert(deviceId);
+ }
+ return deviceIds;
+}
+
+std::set<int32_t> TouchedWindow::getActiveDeviceIds() const {
+ std::set<int32_t> out;
+ for (const auto& [deviceId, _] : mDeviceStates) {
+ out.emplace(deviceId);
+ }
+ return out;
+}
+
+bool TouchedWindow::hasPilferingPointers(int32_t deviceId) const {
+ const auto stateIt = mDeviceStates.find(deviceId);
+ if (stateIt == mDeviceStates.end()) {
+ return false;
+ }
+ const DeviceState& state = stateIt->second;
+
+ return state.pilferingPointerIds.any();
+}
+
+void TouchedWindow::addPilferingPointers(int32_t deviceId,
+ std::bitset<MAX_POINTER_ID + 1> pointerIds) {
+ mDeviceStates[deviceId].pilferingPointerIds |= pointerIds;
+}
+
+void TouchedWindow::addPilferingPointer(int32_t deviceId, int32_t pointerId) {
+ mDeviceStates[deviceId].pilferingPointerIds.set(pointerId);
+}
+
+std::bitset<MAX_POINTER_ID + 1> TouchedWindow::getPilferingPointers(int32_t deviceId) const {
+ const auto stateIt = mDeviceStates.find(deviceId);
+ if (stateIt == mDeviceStates.end()) {
+ return {};
+ }
+ const DeviceState& state = stateIt->second;
+
+ return state.pilferingPointerIds;
+}
+
+std::map<int32_t, std::bitset<MAX_POINTER_ID + 1>> TouchedWindow::getPilferingPointers() const {
+ std::map<int32_t, std::bitset<MAX_POINTER_ID + 1>> out;
+ for (const auto& [deviceId, state] : mDeviceStates) {
+ out.emplace(deviceId, state.pilferingPointerIds);
+ }
+ return out;
+}
+
+std::optional<nsecs_t> TouchedWindow::getDownTimeInTarget(int32_t deviceId) const {
+ const auto stateIt = mDeviceStates.find(deviceId);
+ if (stateIt == mDeviceStates.end()) {
+ return {};
+ }
+ const DeviceState& state = stateIt->second;
+ return state.downTimeInTarget;
+}
+
+void TouchedWindow::trySetDownTimeInTarget(int32_t deviceId, nsecs_t downTime) {
+ auto [stateIt, _] = mDeviceStates.try_emplace(deviceId);
+ DeviceState& state = stateIt->second;
+
+ if (!state.downTimeInTarget) {
+ state.downTimeInTarget = downTime;
+ }
+}
+
+void TouchedWindow::removeAllTouchingPointersForDevice(int32_t deviceId) {
+ const auto stateIt = mDeviceStates.find(deviceId);
+ if (stateIt == mDeviceStates.end()) {
+ return;
+ }
+ DeviceState& state = stateIt->second;
+
+ state.touchingPointerIds.reset();
+ state.pilferingPointerIds.reset();
+ state.downTimeInTarget.reset();
+
+ if (!state.hasPointers()) {
+ mDeviceStates.erase(stateIt);
+ }
}
void TouchedWindow::removeHoveringPointer(int32_t deviceId, int32_t pointerId) {
- const auto it = mHoveringPointerIdsByDevice.find(deviceId);
- if (it == mHoveringPointerIdsByDevice.end()) {
+ const auto stateIt = mDeviceStates.find(deviceId);
+ if (stateIt == mDeviceStates.end()) {
return;
}
- it->second.set(pointerId, false);
+ DeviceState& state = stateIt->second;
- if (it->second.none()) {
- mHoveringPointerIdsByDevice.erase(deviceId);
+ state.hoveringPointerIds.set(pointerId, false);
+
+ if (!state.hasPointers()) {
+ mDeviceStates.erase(stateIt);
}
}
void TouchedWindow::removeAllHoveringPointersForDevice(int32_t deviceId) {
- mHoveringPointerIdsByDevice.erase(deviceId);
+ const auto stateIt = mDeviceStates.find(deviceId);
+ if (stateIt == mDeviceStates.end()) {
+ return;
+ }
+ DeviceState& state = stateIt->second;
+
+ state.hoveringPointerIds.reset();
+
+ if (!state.hasPointers()) {
+ mDeviceStates.erase(stateIt);
+ }
+}
+
+std::string TouchedWindow::deviceStateToString(const TouchedWindow::DeviceState& state) {
+ return StringPrintf("[touchingPointerIds=%s, "
+ "downTimeInTarget=%s, hoveringPointerIds=%s, pilferingPointerIds=%s]",
+ bitsetToString(state.touchingPointerIds).c_str(),
+ toString(state.downTimeInTarget).c_str(),
+ bitsetToString(state.hoveringPointerIds).c_str(),
+ bitsetToString(state.pilferingPointerIds).c_str());
}
std::string TouchedWindow::dump() const {
std::string out;
- std::string hoveringPointers =
- dumpMap(mHoveringPointerIdsByDevice, constToString, bitsetToString);
- out += StringPrintf("name='%s', pointerIds=%s, targetFlags=%s, firstDownTimeInTarget=%s, "
- "mHoveringPointerIdsByDevice=%s, pilferedPointerIds=%s\n",
- windowHandle->getName().c_str(), bitsetToString(pointerIds).c_str(),
- targetFlags.string().c_str(), toString(firstDownTimeInTarget).c_str(),
- hoveringPointers.c_str(), bitsetToString(pilferedPointerIds).c_str());
+ std::string deviceStates =
+ dumpMap(mDeviceStates, constToString, TouchedWindow::deviceStateToString);
+ out += StringPrintf("name='%s', targetFlags=%s, mDeviceStates=%s\n",
+ windowHandle->getName().c_str(), targetFlags.string().c_str(),
+ deviceStates.c_str());
return out;
}
diff --git a/services/inputflinger/dispatcher/TouchedWindow.h b/services/inputflinger/dispatcher/TouchedWindow.h
index 43e7169..81393fc 100644
--- a/services/inputflinger/dispatcher/TouchedWindow.h
+++ b/services/inputflinger/dispatcher/TouchedWindow.h
@@ -20,6 +20,7 @@
#include <input/Input.h>
#include <utils/BitSet.h>
#include <bitset>
+#include <set>
#include "InputTarget.h"
namespace android {
@@ -30,28 +31,66 @@
struct TouchedWindow {
sp<gui::WindowInfoHandle> windowHandle;
ftl::Flags<InputTarget::Flags> targetFlags;
- std::bitset<MAX_POINTER_ID + 1> pointerIds;
- // The pointer ids of the pointers that this window is currently pilfering
- std::bitset<MAX_POINTER_ID + 1> pilferedPointerIds;
- // Time at which the first action down occurred on this window.
- // NOTE: This is not initialized in case of HOVER entry/exit and DISPATCH_AS_OUTSIDE scenario.
- std::optional<nsecs_t> firstDownTimeInTarget;
+ // Hovering
bool hasHoveringPointers() const;
bool hasHoveringPointers(int32_t deviceId) const;
-
bool hasHoveringPointer(int32_t deviceId, int32_t pointerId) const;
void addHoveringPointer(int32_t deviceId, int32_t pointerId);
void removeHoveringPointer(int32_t deviceId, int32_t pointerId);
- void removeTouchingPointer(int32_t pointerId);
- void removeAllTouchingPointers();
+ // Touching
+ bool hasTouchingPointer(int32_t deviceId, int32_t pointerId) const;
+ bool hasTouchingPointers() const;
+ bool hasTouchingPointers(int32_t deviceId) const;
+ std::bitset<MAX_POINTER_ID + 1> getTouchingPointers(int32_t deviceId) const;
+ void addTouchingPointer(int32_t deviceId, int32_t pointerId);
+ void addTouchingPointers(int32_t deviceId, std::bitset<MAX_POINTER_ID + 1> pointers);
+ void removeTouchingPointer(int32_t deviceId, int32_t pointerId);
+ void removeTouchingPointers(int32_t deviceId, std::bitset<MAX_POINTER_ID + 1> pointers);
+ /**
+ * Get the currently active touching device id. If there isn't exactly 1 touching device, return
+ * nullopt.
+ */
+ std::set<int32_t> getTouchingDeviceIds() const;
+ /**
+ * The ids of devices that are currently touching or hovering.
+ */
+ std::set<int32_t> getActiveDeviceIds() const;
+
+ // Pilfering pointers
+ bool hasPilferingPointers(int32_t deviceId) const;
+ void addPilferingPointers(int32_t deviceId, std::bitset<MAX_POINTER_ID + 1> pointerIds);
+ void addPilferingPointer(int32_t deviceId, int32_t pointerId);
+ std::bitset<MAX_POINTER_ID + 1> getPilferingPointers(int32_t deviceId) const;
+ std::map<int32_t, std::bitset<MAX_POINTER_ID + 1>> getPilferingPointers() const;
+
+ // Down time
+ std::optional<nsecs_t> getDownTimeInTarget(int32_t deviceId) const;
+ void trySetDownTimeInTarget(int32_t deviceId, nsecs_t downTime);
+
+ void removeAllTouchingPointersForDevice(int32_t deviceId);
void removeAllHoveringPointersForDevice(int32_t deviceId);
void clearHoveringPointers();
std::string dump() const;
private:
- std::map<int32_t /*deviceId*/, std::bitset<MAX_POINTER_ID + 1>> mHoveringPointerIdsByDevice;
+ struct DeviceState {
+ std::bitset<MAX_POINTER_ID + 1> touchingPointerIds;
+ // The pointer ids of the pointers that this window is currently pilfering, by device
+ std::bitset<MAX_POINTER_ID + 1> pilferingPointerIds;
+ // Time at which the first action down occurred on this window, for each device
+ // NOTE: This is not initialized in case of HOVER entry/exit and DISPATCH_AS_OUTSIDE
+ // scenario.
+ std::optional<nsecs_t> downTimeInTarget;
+ std::bitset<MAX_POINTER_ID + 1> hoveringPointerIds;
+
+ bool hasPointers() const { return touchingPointerIds.any() || hoveringPointerIds.any(); };
+ };
+
+ std::map<int32_t /*deviceId*/, DeviceState> mDeviceStates;
+
+ static std::string deviceStateToString(const TouchedWindow::DeviceState& state);
};
} // namespace inputdispatcher
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index bf07f72..89c80bc 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -195,7 +195,6 @@
"ScreenCaptureOutput.cpp",
"StartPropertySetThread.cpp",
"SurfaceFlinger.cpp",
- "SurfaceFlingerConfig.cpp",
"SurfaceFlingerDefaultFactory.cpp",
"Tracing/LayerTracing.cpp",
"Tracing/TransactionTracing.cpp",
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 2789fa6..f6ca9e2 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -78,19 +78,18 @@
.setDisplayHeight(ANativeWindow_getHeight(args.nativeWindow.get()))
.setNativeWindow(std::move(args.nativeWindow))
.setDisplaySurface(std::move(args.displaySurface))
- .setMaxTextureCacheSize(static_cast<size_t>(
- mFlinger->getConfig().maxFrameBufferAcquiredBuffers))
+ .setMaxTextureCacheSize(
+ static_cast<size_t>(SurfaceFlinger::maxFrameBufferAcquiredBuffers))
.build());
- if (!mFlinger->getConfig().disableClientCompositionCache &&
- mFlinger->getConfig().maxFrameBufferAcquiredBuffers > 0) {
+ if (!mFlinger->mDisableClientCompositionCache &&
+ SurfaceFlinger::maxFrameBufferAcquiredBuffers > 0) {
mCompositionDisplay->createClientCompositionCache(
- static_cast<uint32_t>(mFlinger->getConfig().maxFrameBufferAcquiredBuffers));
+ static_cast<uint32_t>(SurfaceFlinger::maxFrameBufferAcquiredBuffers));
}
- mCompositionDisplay->setPredictCompositionStrategy(
- mFlinger->getConfig().predictCompositionStrategy);
- mCompositionDisplay->setTreat170mAsSrgb(mFlinger->getConfig().treat170mAsSrgb);
+ mCompositionDisplay->setPredictCompositionStrategy(mFlinger->mPredictCompositionStrategy);
+ mCompositionDisplay->setTreat170mAsSrgb(mFlinger->mTreat170mAsSrgb);
mCompositionDisplay->createDisplayColorProfile(
compositionengine::DisplayColorProfileCreationArgsBuilder()
.setHasWideColorGamut(args.hasWideColorGamut)
@@ -412,22 +411,23 @@
capabilities.getDesiredMinLuminance());
}
-void DisplayDevice::enableRefreshRateOverlay(bool enable, bool setByHwc) {
+void DisplayDevice::enableRefreshRateOverlay(bool enable, bool setByHwc, bool showSpinner,
+ bool showRenderRate, bool showInMiddle) {
if (!enable) {
mRefreshRateOverlay.reset();
return;
}
ftl::Flags<RefreshRateOverlay::Features> features;
- if (mFlinger->getConfig().refreshRateOverlay.showSpinner) {
+ if (showSpinner) {
features |= RefreshRateOverlay::Features::Spinner;
}
- if (mFlinger->getConfig().refreshRateOverlay.showRenderRate) {
+ if (showRenderRate) {
features |= RefreshRateOverlay::Features::RenderRate;
}
- if (mFlinger->getConfig().refreshRateOverlay.showInMiddle) {
+ if (showInMiddle) {
features |= RefreshRateOverlay::Features::ShowInMiddle;
}
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index d2a9fb6..dc5f8a8 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -236,7 +236,8 @@
}
// Enables an overlay to be displayed with the current refresh rate
- void enableRefreshRateOverlay(bool enable, bool setByHwc) REQUIRES(kMainThreadContext);
+ void enableRefreshRateOverlay(bool enable, bool setByHwc, bool showSpinner, bool showRenderRate,
+ bool showInMiddle) REQUIRES(kMainThreadContext);
void updateRefreshRateOverlayRate(Fps displayFps, Fps renderFps, bool setByHwc = false);
bool isRefreshRateOverlayEnabled() const { return mRefreshRateOverlay != nullptr; }
bool onKernelTimerChanged(std::optional<DisplayModeId>, bool timerExpired);
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 14fff77..ce602a8 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -50,8 +50,7 @@
FramebufferSurface::FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId,
const sp<IGraphicBufferConsumer>& consumer,
- const ui::Size& size, const ui::Size& maxSize,
- int maxAcquiredBufferCount)
+ const ui::Size& size, const ui::Size& maxSize)
: ConsumerBase(consumer),
mDisplayId(displayId),
mMaxSize(maxSize),
@@ -71,7 +70,8 @@
GRALLOC_USAGE_HW_COMPOSER);
const auto limitedSize = limitSize(size);
mConsumer->setDefaultBufferSize(limitedSize.width, limitedSize.height);
- mConsumer->setMaxAcquiredBufferCount(maxAcquiredBufferCount);
+ mConsumer->setMaxAcquiredBufferCount(
+ SurfaceFlinger::maxFrameBufferAcquiredBuffers - 1);
for (size_t i = 0; i < sizeof(mHwcBufferIds) / sizeof(mHwcBufferIds[0]); ++i) {
mHwcBufferIds[i] = UINT64_MAX;
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 5a1d14f..0b863da 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -42,7 +42,7 @@
public:
FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId,
const sp<IGraphicBufferConsumer>& consumer, const ui::Size& size,
- const ui::Size& maxSize, int maxAcquiredBufferCount);
+ const ui::Size& maxSize);
virtual status_t beginFrame(bool mustRecompose);
virtual status_t prepareFrame(CompositionType compositionType);
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index d759c12..d62075e 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -50,7 +50,7 @@
const sp<IGraphicBufferProducer>& sink,
const sp<IGraphicBufferProducer>& bqProducer,
const sp<IGraphicBufferConsumer>& bqConsumer,
- const std::string& name, bool useHwcForRgbToYuv)
+ const std::string& name)
: ConsumerBase(bqConsumer),
mHwc(hwc),
mDisplayId(displayId),
@@ -69,7 +69,7 @@
mOutputFence(Fence::NO_FENCE),
mFbProducerSlot(BufferQueue::INVALID_BUFFER_SLOT),
mOutputProducerSlot(BufferQueue::INVALID_BUFFER_SLOT),
- mForceHwcCopy(useHwcForRgbToYuv) {
+ mForceHwcCopy(SurfaceFlinger::useHwcForRgbToYuv) {
mSource[SOURCE_SINK] = sink;
mSource[SOURCE_SCRATCH] = bqProducer;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 8a56d5f..be06e2b 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -77,8 +77,7 @@
public:
VirtualDisplaySurface(HWComposer&, VirtualDisplayId, const sp<IGraphicBufferProducer>& sink,
const sp<IGraphicBufferProducer>& bqProducer,
- const sp<IGraphicBufferConsumer>& bqConsumer, const std::string& name,
- bool useHwcForRgbToYuv);
+ const sp<IGraphicBufferConsumer>& bqConsumer, const std::string& name);
//
// DisplaySurface interface
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 8e1b8f2..5a010e8 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2562,7 +2562,7 @@
compositionengine::OutputLayer* Layer::findOutputLayerForDisplay(
const DisplayDevice* display) const {
if (!display) return nullptr;
- if (!mFlinger->getConfig().layerLifecycleManagerEnabled) {
+ if (!mFlinger->mLayerLifecycleManagerEnabled) {
return display->getCompositionDisplay()->getOutputLayerForLayer(
getCompositionEngineLayerFE());
}
@@ -2907,7 +2907,7 @@
void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) {
for (const auto& handle : mDrawingState.callbackHandles) {
- if (mFlinger->getConfig().layerLifecycleManagerEnabled) {
+ if (mFlinger->mLayerLifecycleManagerEnabled) {
handle->transformHint = mTransformHint;
} else {
handle->transformHint = mSkipReportingTransformHint
@@ -3162,7 +3162,7 @@
mFlinger->mTimeStats->setPostTime(layerId, mDrawingState.frameNumber, getName().c_str(),
mOwnerUid, postTime, getGameMode());
- if (mFlinger->getConfig().legacyFrontEndEnabled) {
+ if (mFlinger->mLegacyFrontEndEnabled) {
recordLayerHistoryBufferUpdate(getLayerProps());
}
diff --git a/services/surfaceflinger/LayerRenderArea.cpp b/services/surfaceflinger/LayerRenderArea.cpp
index 9c1944b..51d4ff8 100644
--- a/services/surfaceflinger/LayerRenderArea.cpp
+++ b/services/surfaceflinger/LayerRenderArea.cpp
@@ -78,7 +78,7 @@
mTransform = mLayerTransform.inverse();
}
- if (mFlinger.getConfig().layerLifecycleManagerEnabled) {
+ if (mFlinger.mLayerLifecycleManagerEnabled) {
drawLayers();
return;
}
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 03f3b40..8f658d5 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -322,7 +322,7 @@
};
std::function<std::vector<std::pair<Layer*, sp<LayerFE>>>()> getLayerSnapshots;
- if (mFlinger.getConfig().layerLifecycleManagerEnabled) {
+ if (mFlinger.mLayerLifecycleManagerEnabled) {
auto filterFn = [&](const frontend::LayerSnapshot& snapshot,
bool& outStopTraversal) -> bool {
const Rect bounds =
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 60c0904..ba13293 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -214,6 +214,16 @@
// TODO(b/141333600): Consolidate with DisplayMode::Builder::getDefaultDensity.
constexpr float FALLBACK_DENSITY = ACONFIGURATION_DENSITY_TV;
+float getDensityFromProperty(const char* property, bool required) {
+ char value[PROPERTY_VALUE_MAX];
+ const float density = property_get(property, value, nullptr) > 0 ? std::atof(value) : 0.f;
+ if (!density && required) {
+ ALOGE("%s must be defined as a build property", property);
+ return FALLBACK_DENSITY;
+ }
+ return density;
+}
+
// Currently we only support V0_SRGB and DISPLAY_P3 as composition preference.
bool validateCompositionDataspace(Dataspace dataspace) {
return dataspace == Dataspace::V0_SRGB || dataspace == Dataspace::DISPLAY_P3;
@@ -312,6 +322,18 @@
static const int MAX_TRACING_MEMORY = 1024 * 1024 * 1024; // 1GB
// ---------------------------------------------------------------------------
+int64_t SurfaceFlinger::dispSyncPresentTimeOffset;
+bool SurfaceFlinger::useHwcForRgbToYuv;
+bool SurfaceFlinger::hasSyncFramework;
+int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers;
+int64_t SurfaceFlinger::minAcquiredBuffers = 1;
+uint32_t SurfaceFlinger::maxGraphicsWidth;
+uint32_t SurfaceFlinger::maxGraphicsHeight;
+bool SurfaceFlinger::useContextPriority;
+Dataspace SurfaceFlinger::defaultCompositionDataspace = Dataspace::V0_SRGB;
+ui::PixelFormat SurfaceFlinger::defaultCompositionPixelFormat = ui::PixelFormat::RGBA_8888;
+Dataspace SurfaceFlinger::wideColorGamutCompositionDataspace = Dataspace::V0_SRGB;
+ui::PixelFormat SurfaceFlinger::wideColorGamutCompositionPixelFormat = ui::PixelFormat::RGBA_8888;
LatchUnsignaledConfig SurfaceFlinger::enableLatchUnsignaledConfig;
std::string decodeDisplayColorSetting(DisplayColorSetting displayColorSetting) {
@@ -338,35 +360,136 @@
ui::Transform::RotationFlags SurfaceFlinger::sActiveDisplayRotationFlags = ui::Transform::ROT_0;
-SurfaceFlinger::SurfaceFlinger(surfaceflinger::Config& config)
- : mConfig(&config),
- mDebugFlashDelay(base::GetUintProperty("debug.sf.showupdates"s, 0u)),
+SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag)
+ : mFactory(factory),
+ mPid(getpid()),
mTimeStats(std::make_shared<impl::TimeStats>()),
- mFrameTracer(mConfig->factory->createFrameTracer()),
- mFrameTimeline(mConfig->factory->createFrameTimeline(mTimeStats, mConfig->pid)),
- mCompositionEngine(mConfig->factory->createCompositionEngine()),
+ mFrameTracer(mFactory.createFrameTracer()),
+ mFrameTimeline(mFactory.createFrameTimeline(mTimeStats, mPid)),
+ mCompositionEngine(mFactory.createCompositionEngine()),
+ mHwcServiceName(base::GetProperty("debug.sf.hwc_service_name"s, "default"s)),
mTunnelModeEnabledReporter(sp<TunnelModeEnabledReporter>::make()),
+ mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)),
+ mInternalDisplayDensity(
+ getDensityFromProperty("ro.sf.lcd_density", !mEmulatedDisplayDensity)),
mPowerAdvisor(std::make_unique<Hwc2::impl::PowerAdvisor>(*this)),
mWindowInfosListenerInvoker(sp<WindowInfosListenerInvoker>::make()) {
- ATRACE_CALL();
- ALOGI("SurfaceFlinger is starting.");
- ALOGI("Using HWComposer service: %s", mConfig->hwcServiceName.c_str());
- ALOGI_IF(mConfig->backpressureGpuComposition, "Enabling backpressure for GPU composition");
- ALOGI_IF(!mConfig->supportsBlur, "Disabling blur effects, they are not supported.");
- ALOGI_IF(mConfig->trebleTestingOverride, "Enabling Treble testing override");
+ ALOGI("Using HWComposer service: %s", mHwcServiceName.c_str());
+}
- if (mConfig->trebleTestingOverride) {
+SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipInitialization) {
+ ATRACE_CALL();
+ ALOGI("SurfaceFlinger is starting");
+
+ hasSyncFramework = running_without_sync_framework(true);
+
+ dispSyncPresentTimeOffset = present_time_offset_from_vsync_ns(0);
+
+ useHwcForRgbToYuv = force_hwc_copy_for_virtual_displays(false);
+
+ maxFrameBufferAcquiredBuffers = max_frame_buffer_acquired_buffers(2);
+ minAcquiredBuffers =
+ SurfaceFlingerProperties::min_acquired_buffers().value_or(minAcquiredBuffers);
+
+ maxGraphicsWidth = std::max(max_graphics_width(0), 0);
+ maxGraphicsHeight = std::max(max_graphics_height(0), 0);
+
+ mSupportsWideColor = has_wide_color_display(false);
+ mDefaultCompositionDataspace =
+ static_cast<ui::Dataspace>(default_composition_dataspace(Dataspace::V0_SRGB));
+ mWideColorGamutCompositionDataspace = static_cast<ui::Dataspace>(wcg_composition_dataspace(
+ mSupportsWideColor ? Dataspace::DISPLAY_P3 : Dataspace::V0_SRGB));
+ defaultCompositionDataspace = mDefaultCompositionDataspace;
+ wideColorGamutCompositionDataspace = mWideColorGamutCompositionDataspace;
+ defaultCompositionPixelFormat = static_cast<ui::PixelFormat>(
+ default_composition_pixel_format(ui::PixelFormat::RGBA_8888));
+ wideColorGamutCompositionPixelFormat =
+ static_cast<ui::PixelFormat>(wcg_composition_pixel_format(ui::PixelFormat::RGBA_8888));
+
+ mColorSpaceAgnosticDataspace =
+ static_cast<ui::Dataspace>(color_space_agnostic_dataspace(Dataspace::UNKNOWN));
+
+ mLayerCachingEnabled = [] {
+ const bool enable =
+ android::sysprop::SurfaceFlingerProperties::enable_layer_caching().value_or(false);
+ return base::GetBoolProperty(std::string("debug.sf.enable_layer_caching"), enable);
+ }();
+
+ useContextPriority = use_context_priority(true);
+
+ mInternalDisplayPrimaries = sysprop::getDisplayNativePrimaries();
+
+ // debugging stuff...
+ char value[PROPERTY_VALUE_MAX];
+
+ property_get("ro.build.type", value, "user");
+ mIsUserBuild = strcmp(value, "user") == 0;
+
+ mDebugFlashDelay = base::GetUintProperty("debug.sf.showupdates"s, 0u);
+
+ mBackpressureGpuComposition = base::GetBoolProperty("debug.sf.enable_gl_backpressure"s, true);
+ ALOGI_IF(mBackpressureGpuComposition, "Enabling backpressure for GPU composition");
+
+ property_get("ro.surface_flinger.supports_background_blur", value, "0");
+ bool supportsBlurs = atoi(value);
+ mSupportsBlur = supportsBlurs;
+ ALOGI_IF(!mSupportsBlur, "Disabling blur effects, they are not supported.");
+
+ const size_t defaultListSize = MAX_LAYERS;
+ auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize));
+ mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize;
+ mGraphicBufferProducerListSizeLogThreshold =
+ std::max(static_cast<int>(0.95 *
+ static_cast<double>(mMaxGraphicBufferProducerListSize)),
+ 1);
+
+ property_get("debug.sf.luma_sampling", value, "1");
+ mLumaSampling = atoi(value);
+
+ property_get("debug.sf.disable_client_composition_cache", value, "0");
+ mDisableClientCompositionCache = atoi(value);
+
+ property_get("debug.sf.predict_hwc_composition_strategy", value, "1");
+ mPredictCompositionStrategy = atoi(value);
+
+ property_get("debug.sf.treat_170m_as_sRGB", value, "0");
+ mTreat170mAsSrgb = atoi(value);
+
+ mIgnoreHwcPhysicalDisplayOrientation =
+ base::GetBoolProperty("debug.sf.ignore_hwc_physical_display_orientation"s, false);
+
+ // We should be reading 'persist.sys.sf.color_saturation' here
+ // but since /data may be encrypted, we need to wait until after vold
+ // comes online to attempt to read the property. The property is
+ // instead read after the boot animation
+
+ if (base::GetBoolProperty("debug.sf.treble_testing_override"s, false)) {
// Without the override SurfaceFlinger cannot connect to HIDL
// services that are not listed in the manifests. Considered
// deriving the setting from the set service name, but it
// would be brittle if the name that's not 'default' is used
// for production purposes later on.
+ ALOGI("Enabling Treble testing override");
android::hardware::details::setTrebleTestingOverride(true);
}
- if (!mConfig->isUserBuild && mConfig->enableTransactionTracing) {
+ // TODO (b/270966065) Update the HWC based refresh rate overlay to support spinner
+ mRefreshRateOverlaySpinner = property_get_bool("debug.sf.show_refresh_rate_overlay_spinner", 0);
+ mRefreshRateOverlayRenderRate =
+ property_get_bool("debug.sf.show_refresh_rate_overlay_render_rate", 0);
+ mRefreshRateOverlayShowInMiddle =
+ property_get_bool("debug.sf.show_refresh_rate_overlay_in_middle", 0);
+
+ if (!mIsUserBuild && base::GetBoolProperty("debug.sf.enable_transaction_tracing"s, true)) {
mTransactionTracing.emplace();
}
+
+ mIgnoreHdrCameraLayers = ignore_hdr_camera_layers(false);
+
+ mLayerLifecycleManagerEnabled =
+ base::GetBoolProperty("persist.debug.sf.enable_layer_lifecycle_manager"s, false);
+ mLegacyFrontEndEnabled = !mLayerLifecycleManagerEnabled ||
+ base::GetBoolProperty("persist.debug.sf.enable_legacy_frontend"s, false);
}
LatchUnsignaledConfig SurfaceFlinger::getLatchUnsignaledConfig() {
@@ -693,18 +816,17 @@
// Get a RenderEngine for the given display / config (can't fail)
// TODO(b/77156734): We need to stop casting and use HAL types when possible.
// Sending maxFrameBufferAcquiredBuffers as the cache size is tightly tuned to single-display.
- auto builder =
- renderengine::RenderEngineCreationArgs::Builder()
- .setPixelFormat(static_cast<int32_t>(mConfig->defaultCompositionPixelFormat))
- .setImageCacheSize(mConfig->maxFrameBufferAcquiredBuffers)
- .setUseColorManagerment(useColorManagement)
- .setEnableProtectedContext(enable_protected_contents(false))
- .setPrecacheToneMapperShaderOnly(false)
- .setSupportsBackgroundBlur(mConfig->supportsBlur)
- .setContextPriority(
- mConfig->useContextPriority
- ? renderengine::RenderEngine::ContextPriority::REALTIME
- : renderengine::RenderEngine::ContextPriority::MEDIUM);
+ auto builder = renderengine::RenderEngineCreationArgs::Builder()
+ .setPixelFormat(static_cast<int32_t>(defaultCompositionPixelFormat))
+ .setImageCacheSize(maxFrameBufferAcquiredBuffers)
+ .setUseColorManagerment(useColorManagement)
+ .setEnableProtectedContext(enable_protected_contents(false))
+ .setPrecacheToneMapperShaderOnly(false)
+ .setSupportsBackgroundBlur(mSupportsBlur)
+ .setContextPriority(
+ useContextPriority
+ ? renderengine::RenderEngine::ContextPriority::REALTIME
+ : renderengine::RenderEngine::ContextPriority::MEDIUM);
if (auto type = chooseRenderEngineTypeViaSysProp()) {
builder.setRenderEngineType(type.value());
}
@@ -719,7 +841,7 @@
}
mCompositionEngine->setTimeStats(mTimeStats);
- mCompositionEngine->setHwComposer(getFactory().createHWComposer(mConfig->hwcServiceName));
+ mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName));
mCompositionEngine->getHwComposer().setCallback(*this);
ClientCache::getInstance().setRenderEngine(&getRenderEngine());
@@ -909,11 +1031,11 @@
info->connectionType = snapshot.connectionType();
info->deviceProductInfo = snapshot.deviceProductInfo();
- if (mConfig->emulatedDisplayDensity) {
- info->density = mConfig->emulatedDisplayDensity;
+ if (mEmulatedDisplayDensity) {
+ info->density = mEmulatedDisplayDensity;
} else {
info->density = info->connectionType == ui::DisplayConnectionType::Internal
- ? mConfig->internalDisplayDensity
+ ? mInternalDisplayDensity
: FALLBACK_DENSITY;
}
info->density /= ACONFIGURATION_DENSITY_MEDIUM;
@@ -976,7 +1098,7 @@
info->supportedDisplayModes.push_back(outMode);
}
- info->supportedColorModes = snapshot.filterColorModes(mConfig->supportsWideColor);
+ info->supportedColorModes = snapshot.filterColorModes(mSupportsWideColor);
const PhysicalDisplayId displayId = snapshot.displayId();
@@ -1374,7 +1496,7 @@
}
// TODO(b/229846990): For now, assume that all internal displays have the same primaries.
- primaries = mConfig->internalDisplayPrimaries;
+ primaries = mInternalDisplayPrimaries;
return NO_ERROR;
}
@@ -1398,7 +1520,7 @@
const auto& [display, snapshotRef] = *displayOpt;
const auto& snapshot = snapshotRef.get();
- const auto modes = snapshot.filterColorModes(mConfig->supportsWideColor);
+ const auto modes = snapshot.filterColorModes(mSupportsWideColor);
const bool exists = std::find(modes.begin(), modes.end(), mode) != modes.end();
if (mode < ui::ColorMode::NATIVE || !exists) {
@@ -1704,7 +1826,7 @@
}
*outIsWideColorDisplay =
- display->isPrimary() ? mConfig->supportsWideColor : display->hasWideColorGamut();
+ display->isPrimary() ? mSupportsWideColor : display->hasWideColorGamut();
return NO_ERROR;
}
@@ -1725,12 +1847,10 @@
Dataspace* outDataspace, ui::PixelFormat* outPixelFormat,
Dataspace* outWideColorGamutDataspace,
ui::PixelFormat* outWideColorGamutPixelFormat) const {
- *outDataspace =
- mOverrideDefaultCompositionDataspace.value_or(mConfig->defaultCompositionDataspace);
- *outPixelFormat = mConfig->defaultCompositionPixelFormat;
- *outWideColorGamutDataspace = mOverrideWideColorGamutCompositionDataspace.value_or(
- mConfig->wideColorGamutCompositionDataspace);
- *outWideColorGamutPixelFormat = mConfig->wideColorGamutCompositionPixelFormat;
+ *outDataspace = mDefaultCompositionDataspace;
+ *outPixelFormat = defaultCompositionPixelFormat;
+ *outWideColorGamutDataspace = mWideColorGamutCompositionDataspace;
+ *outWideColorGamutPixelFormat = wideColorGamutCompositionPixelFormat;
return NO_ERROR;
}
@@ -2193,7 +2313,7 @@
.displays = mFrontEndDisplayInfos,
.displayChanges = mFrontEndDisplayInfosChanged,
.globalShadowSettings = mDrawingState.globalShadowSettings,
- .supportsBlur = mConfig->supportsBlur,
+ .supportsBlur = mSupportsBlur,
.forceFullDamage = mForceFullDamage,
.supportedLayerGenericMetadata =
getHwComposer().getSupportedLayerGenericMetadata(),
@@ -2213,7 +2333,7 @@
mustComposite |= mLayerLifecycleManager.getGlobalChanges().get() != 0;
bool newDataLatched = false;
- if (!mConfig->legacyFrontEndEnabled) {
+ if (!mLegacyFrontEndEnabled) {
ATRACE_NAME("DisplayCallbackAndStatsUpdates");
applyTransactions(update.transactions, vsyncId);
const nsecs_t latchTime = systemTime();
@@ -2307,7 +2427,7 @@
}
if (pacesetterFrameTarget.isFramePending()) {
- if (mConfig->backpressureGpuComposition || pacesetterFrameTarget.didMissHwcFrame()) {
+ if (mBackpressureGpuComposition || pacesetterFrameTarget.didMissHwcFrame()) {
scheduleCommit(FrameHint::kNone);
return false;
}
@@ -2338,7 +2458,7 @@
mPowerAdvisor->updateTargetWorkDuration(idealVsyncPeriod);
}
- if (mConfig->refreshRateOverlay.showSpinner) {
+ if (mRefreshRateOverlaySpinner) {
Mutex::Autolock lock(mStateLock);
if (const auto display = getDefaultDisplayDeviceLocked()) {
display->animateRefreshRateOverlay();
@@ -2354,12 +2474,12 @@
const bool flushTransactions = clearTransactionFlags(eTransactionFlushNeeded);
bool transactionsAreEmpty;
- if (mConfig->legacyFrontEndEnabled) {
+ if (mLegacyFrontEndEnabled) {
mustComposite |=
updateLayerSnapshotsLegacy(vsyncId, pacesetterFrameTarget.frameBeginTime().ns(),
flushTransactions, transactionsAreEmpty);
}
- if (mConfig->layerLifecycleManagerEnabled) {
+ if (mLayerLifecycleManagerEnabled) {
mustComposite |=
updateLayerSnapshots(vsyncId, pacesetterFrameTarget.frameBeginTime().ns(),
flushTransactions, transactionsAreEmpty);
@@ -2465,7 +2585,7 @@
refreshArgs.outputColorSetting = useColorManagement
? mDisplayColorSetting
: compositionengine::OutputColorSetting::kUnmanaged;
- refreshArgs.colorSpaceAgnosticDataspace = mConfig->colorSpaceAgnosticDataspace;
+ refreshArgs.colorSpaceAgnosticDataspace = mColorSpaceAgnosticDataspace;
refreshArgs.forceOutputColorMode = mForceColorMode;
refreshArgs.updatingOutputGeometryThisFrame = mVisibleRegionsDirty;
@@ -2619,7 +2739,7 @@
// Even though the camera layer may be using an HDR transfer function or otherwise be "HDR"
// the device may need to avoid boosting the brightness as a result of these layers to
// reduce power consumption during camera recording
- if (mConfig->ignoreHdrCameraLayers) {
+ if (mIgnoreHdrCameraLayers) {
if (snapshot.externalTexture &&
(snapshot.externalTexture->getUsage() & GRALLOC_USAGE_HW_CAMERA_WRITE) != 0) {
return false;
@@ -2650,7 +2770,7 @@
if (!id) {
return ui::ROTATION_0;
}
- if (!mConfig->ignoreHwcPhysicalDisplayOrientation &&
+ if (!mIgnoreHwcPhysicalDisplayOrientation &&
getHwComposer().getComposer()->isSupported(
Hwc2::Composer::OptionalFeature::PhysicalDisplayOrientation)) {
switch (getHwComposer().getPhysicalDisplayOrientation(*id)) {
@@ -2817,7 +2937,7 @@
}
};
- if (mConfig->layerLifecycleManagerEnabled) {
+ if (mLayerLifecycleManagerEnabled) {
mLayerSnapshotBuilder.forEachVisibleSnapshot(
[&, compositionDisplay = compositionDisplay](
std::unique_ptr<frontend::LayerSnapshot>& snapshot) {
@@ -2869,7 +2989,7 @@
const bool isDisplayConnected =
defaultDisplay && getHwComposer().isConnected(defaultDisplay->getPhysicalId());
- if (!mConfig->hasSyncFramework) {
+ if (!hasSyncFramework) {
if (isDisplayConnected && defaultDisplay->isPoweredOn()) {
mScheduler->enableHardwareVsync(defaultDisplay->getPhysicalId());
}
@@ -2910,7 +3030,7 @@
if (!layer->hasTrustedPresentationListener()) {
return;
}
- const frontend::LayerSnapshot* snapshot = mConfig->layerLifecycleManagerEnabled
+ const frontend::LayerSnapshot* snapshot = mLayerLifecycleManagerEnabled
? mLayerSnapshotBuilder.getSnapshot(layer->sequence)
: layer->getLayerSnapshot();
std::optional<const DisplayDevice*> displayOpt = std::nullopt;
@@ -3305,7 +3425,7 @@
builder.setPowerAdvisor(mPowerAdvisor.get());
builder.setName(state.displayName);
auto compositionDisplay = getCompositionEngine().createDisplay(builder.build());
- compositionDisplay->setLayerCachingEnabled(mConfig->layerCachingEnabled);
+ compositionDisplay->setLayerCachingEnabled(mLayerCachingEnabled);
sp<compositionengine::DisplaySurface> displaySurface;
sp<IGraphicBufferProducer> producer;
@@ -3317,8 +3437,7 @@
const auto displayId = VirtualDisplayId::tryCast(compositionDisplay->getId());
LOG_FATAL_IF(!displayId);
auto surface = sp<VirtualDisplaySurface>::make(getHwComposer(), *displayId, state.surface,
- bqProducer, bqConsumer, state.displayName,
- mConfig->useHwcForRgbToYuv);
+ bqProducer, bqConsumer, state.displayName);
displaySurface = surface;
producer = std::move(surface);
} else {
@@ -3328,11 +3447,10 @@
state.surface.get());
const auto displayId = PhysicalDisplayId::tryCast(compositionDisplay->getId());
LOG_FATAL_IF(!displayId);
- displaySurface = sp<FramebufferSurface>::make(getHwComposer(), *displayId, bqConsumer,
- state.physical->activeMode->getResolution(),
- ui::Size(mConfig->maxGraphicsWidth,
- mConfig->maxGraphicsHeight),
- mConfig->maxFrameBufferAcquiredBuffers);
+ displaySurface =
+ sp<FramebufferSurface>::make(getHwComposer(), *displayId, bqConsumer,
+ state.physical->activeMode->getResolution(),
+ ui::Size(maxGraphicsWidth, maxGraphicsHeight));
producer = bqProducer;
}
@@ -3513,7 +3631,7 @@
// Commit display transactions.
const bool displayTransactionNeeded = transactionFlags & eDisplayTransactionNeeded;
mFrontEndDisplayInfosChanged = displayTransactionNeeded;
- if (displayTransactionNeeded && !mConfig->layerLifecycleManagerEnabled) {
+ if (displayTransactionNeeded && !mLayerLifecycleManagerEnabled) {
processDisplayChangesLocked();
mFrontEndDisplayInfos.clear();
for (const auto& [_, display] : mDisplays) {
@@ -3713,7 +3831,7 @@
outWindowInfos.reserve(sNumWindowInfos);
sNumWindowInfos = 0;
- if (mConfig->layerLifecycleManagerEnabled) {
+ if (mLayerLifecycleManagerEnabled) {
mLayerSnapshotBuilder.forEachInputSnapshot(
[&outWindowInfos](const frontend::LayerSnapshot& snapshot) {
outWindowInfos.push_back(snapshot.inputInfo);
@@ -3837,7 +3955,7 @@
if (display->refreshRateSelector().kernelIdleTimerController()) {
features |= Feature::kKernelIdleTimer;
}
- if (mConfig->backpressureGpuComposition) {
+ if (mBackpressureGpuComposition) {
features |= Feature::kBackpressureGpuComposition;
}
@@ -4383,7 +4501,7 @@
void SurfaceFlinger::addTransactionReadyFilters() {
mTransactionHandler.addTransactionReadyFilter(
std::bind(&SurfaceFlinger::transactionReadyTimelineCheck, this, std::placeholders::_1));
- if (mConfig->layerLifecycleManagerEnabled) {
+ if (mLayerLifecycleManagerEnabled) {
mTransactionHandler.addTransactionReadyFilter(
std::bind(&SurfaceFlinger::transactionReadyBufferCheck, this,
std::placeholders::_1));
@@ -4614,7 +4732,7 @@
const std::vector<ListenerCallbacks>& listenerCallbacks,
int originPid, int originUid, uint64_t transactionId) {
uint32_t transactionFlags = 0;
- if (!mConfig->layerLifecycleManagerEnabled) {
+ if (!mLayerLifecycleManagerEnabled) {
for (DisplayState& display : displays) {
transactionFlags |= setDisplayStateLocked(display);
}
@@ -4629,12 +4747,12 @@
uint32_t clientStateFlags = 0;
for (auto& resolvedState : states) {
- if (mConfig->legacyFrontEndEnabled) {
+ if (mLegacyFrontEndEnabled) {
clientStateFlags |=
setClientStateLocked(frameTimelineInfo, resolvedState, desiredPresentTime,
isAutoTimestamp, postTime, transactionId);
- } else /* mConfig->layerLifecycleManagerEnabled */ {
+ } else /*mLayerLifecycleManagerEnabled*/ {
clientStateFlags |= updateLayerCallbacksAndStats(frameTimelineInfo, resolvedState,
desiredPresentTime, isAutoTimestamp,
postTime, transactionId);
@@ -4708,7 +4826,7 @@
}
mFrontEndDisplayInfosChanged = mTransactionFlags & eDisplayTransactionNeeded;
- if (mFrontEndDisplayInfosChanged && !mConfig->legacyFrontEndEnabled) {
+ if (mFrontEndDisplayInfosChanged && !mLegacyFrontEndEnabled) {
processDisplayChangesLocked();
mFrontEndDisplayInfos.clear();
for (const auto& [_, display] : mDisplays) {
@@ -4911,7 +5029,7 @@
if (layer->setCornerRadius(s.cornerRadius))
flags |= eTraversalNeeded;
}
- if (what & layer_state_t::eBackgroundBlurRadiusChanged && mConfig->supportsBlur) {
+ if (what & layer_state_t::eBackgroundBlurRadiusChanged && mSupportsBlur) {
if (layer->setBackgroundBlurRadius(s.backgroundBlurRadius)) flags |= eTraversalNeeded;
}
if (what & layer_state_t::eBlurRegionsChanged) {
@@ -5315,7 +5433,7 @@
return result;
}
- if (mConfig->legacyFrontEndEnabled) {
+ if (mLegacyFrontEndEnabled) {
std::scoped_lock<std::mutex> lock(mMirrorDisplayLock);
mMirrorDisplays.emplace_back(layerStack, outResult.handle, args.client);
}
@@ -5422,10 +5540,9 @@
const nsecs_t now = systemTime();
state.desiredPresentTime = now;
state.postTime = now;
- state.originPid = mConfig->pid;
+ state.originPid = mPid;
state.originUid = static_cast<int>(getuid());
- const uint64_t transactionId =
- (static_cast<uint64_t>(mConfig->pid) << 32) | mUniqueTransactionId++;
+ const uint64_t transactionId = (static_cast<uint64_t>(mPid) << 32) | mUniqueTransactionId++;
state.id = transactionId;
// reset screen orientation and use primary layer stack
@@ -5445,7 +5562,7 @@
std::vector<TransactionState> transactions;
transactions.emplace_back(state);
- if (mConfig->legacyFrontEndEnabled) {
+ if (mLegacyFrontEndEnabled) {
applyTransactions(transactions, VsyncId{0});
} else {
applyAndCommitDisplayTransactionStates(transactions);
@@ -5741,13 +5858,13 @@
void SurfaceFlinger::appendSfConfigString(std::string& result) const {
result.append(" [sf");
- StringAppendF(&result, " PRESENT_TIME_OFFSET=%" PRId64, mConfig->dispSyncPresentTimeOffset);
- StringAppendF(&result, " FORCE_HWC_FOR_RBG_TO_YUV=%d", mConfig->useHwcForRgbToYuv);
+ StringAppendF(&result, " PRESENT_TIME_OFFSET=%" PRId64, dispSyncPresentTimeOffset);
+ StringAppendF(&result, " FORCE_HWC_FOR_RBG_TO_YUV=%d", useHwcForRgbToYuv);
StringAppendF(&result, " MAX_VIRT_DISPLAY_DIM=%zu",
getHwComposer().getMaxVirtualDisplayDimension());
- StringAppendF(&result, " RUNNING_WITHOUT_SYNC_FRAMEWORK=%d", !mConfig->hasSyncFramework);
+ StringAppendF(&result, " RUNNING_WITHOUT_SYNC_FRAMEWORK=%d", !hasSyncFramework);
StringAppendF(&result, " NUM_FRAMEBUFFER_SURFACE_BUFFERS=%" PRId64,
- mConfig->maxFrameBufferAcquiredBuffers);
+ maxFrameBufferAcquiredBuffers);
result.append("]");
}
@@ -5767,7 +5884,7 @@
StringAppendF(&result,
" present offset: %9" PRId64 " ns\t VSYNC period: %9" PRId64
" ns\n\n",
- mConfig->dispSyncPresentTimeOffset, getVsyncPeriodFromHWC());
+ dispSyncPresentTimeOffset, getVsyncPeriodFromHWC());
}
void SurfaceFlinger::dumpEvents(std::string& result) const {
@@ -5866,7 +5983,7 @@
}
void SurfaceFlinger::dumpWideColorInfo(std::string& result) const {
- StringAppendF(&result, "Device supports wide color: %d\n", mConfig->supportsWideColor);
+ StringAppendF(&result, "Device supports wide color: %d\n", mSupportsWideColor);
StringAppendF(&result, "Device uses color management: %d\n", useColorManagement);
StringAppendF(&result, "DisplayColorSetting: %s\n",
decodeDisplayColorSetting(mDisplayColorSetting).c_str());
@@ -5900,7 +6017,7 @@
}
}
- if (mConfig->legacyFrontEndEnabled) {
+ if (mLegacyFrontEndEnabled) {
LayersProto layersProto;
for (const sp<Layer>& layer : mDrawingState.layersSortedByZ) {
if (stackIdsToSkip.find(layer->getLayerStack().id) != stackIdsToSkip.end()) {
@@ -6557,7 +6674,7 @@
if (!validateCompositionDataspace(dataspace)) {
return BAD_VALUE;
}
- mOverrideDefaultCompositionDataspace = dataspace;
+ mDefaultCompositionDataspace = dataspace;
}
n = data.readInt32();
if (n) {
@@ -6565,12 +6682,12 @@
if (!validateCompositionDataspace(dataspace)) {
return BAD_VALUE;
}
- mOverrideWideColorGamutCompositionDataspace = dataspace;
+ mWideColorGamutCompositionDataspace = dataspace;
}
} else {
- // Reset data space overrides.
- mOverrideDefaultCompositionDataspace.reset();
- mOverrideWideColorGamutCompositionDataspace.reset();
+ // restore composition data space.
+ mDefaultCompositionDataspace = defaultCompositionDataspace;
+ mWideColorGamutCompositionDataspace = wideColorGamutCompositionDataspace;
}
return NO_ERROR;
}
@@ -6709,10 +6826,10 @@
}
{
Mutex::Autolock lock(mStateLock);
- mConfig->layerCachingEnabled = n != 0;
+ mLayerCachingEnabled = n != 0;
for (const auto& [_, display] : mDisplays) {
if (!inputId || *inputId == display->getPhysicalId()) {
- display->enableLayerCaching(mConfig->layerCachingEnabled);
+ display->enableLayerCaching(mLayerCachingEnabled);
}
}
}
@@ -7037,7 +7154,7 @@
});
GetLayerSnapshotsFunction getLayerSnapshots;
- if (mConfig->layerLifecycleManagerEnabled) {
+ if (mLayerLifecycleManagerEnabled) {
getLayerSnapshots =
getLayerSnapshotsForScreenshots(layerStack, args.uid, std::move(excludeLayerIds));
} else {
@@ -7080,7 +7197,7 @@
});
GetLayerSnapshotsFunction getLayerSnapshots;
- if (mConfig->layerLifecycleManagerEnabled) {
+ if (mLayerLifecycleManagerEnabled) {
getLayerSnapshots = getLayerSnapshotsForScreenshots(layerStack, CaptureArgs::UNSET_UID,
/*snapshotFilterFn=*/nullptr);
} else {
@@ -7176,7 +7293,7 @@
RenderAreaFuture renderAreaFuture = ftl::defer([=]() -> std::unique_ptr<RenderArea> {
ui::Transform layerTransform;
Rect layerBufferSize;
- if (mConfig->layerLifecycleManagerEnabled) {
+ if (mLayerLifecycleManagerEnabled) {
frontend::LayerSnapshot* snapshot =
mLayerSnapshotBuilder.getSnapshot(parent->getSequence());
if (!snapshot) {
@@ -7196,7 +7313,7 @@
args.hintForSeamlessTransition);
});
GetLayerSnapshotsFunction getLayerSnapshots;
- if (mConfig->layerLifecycleManagerEnabled) {
+ if (mLayerLifecycleManagerEnabled) {
std::optional<FloatRect> parentCrop = std::nullopt;
if (args.childrenOnly) {
parentCrop = crop.isEmpty() ? FloatRect(0, 0, reqSize.width, reqSize.height)
@@ -7449,7 +7566,7 @@
layerStack, regionSampling, renderArea = std::move(renderArea),
renderIntent]() -> FenceResult {
std::unique_ptr<compositionengine::CompositionEngine> compositionEngine =
- mConfig->factory->createCompositionEngine();
+ mFactory.createCompositionEngine();
compositionEngine->setRenderEngine(mRenderEngine.get());
compositionengine::Output::ColorProfile colorProfile{.dataspace = dataspace,
@@ -7519,7 +7636,7 @@
}
void SurfaceFlinger::traverseLegacyLayers(const LayerVector::Visitor& visitor) const {
- if (mConfig->layerLifecycleManagerEnabled) {
+ if (mLayerLifecycleManagerEnabled) {
for (auto& layer : mLegacyLayers) {
visitor(layer.second.get());
}
@@ -7841,7 +7958,9 @@
}
if (const auto device = getDisplayDeviceLocked(id)) {
- device->enableRefreshRateOverlay(enable, setByHwc);
+ device->enableRefreshRateOverlay(enable, setByHwc, mRefreshRateOverlaySpinner,
+ mRefreshRateOverlayRenderRate,
+ mRefreshRateOverlayShowInMiddle);
}
}
}
@@ -7852,12 +7971,12 @@
}
int SurfaceFlinger::calculateMaxAcquiredBufferCount(Fps refreshRate,
- std::chrono::nanoseconds presentLatency) const {
+ std::chrono::nanoseconds presentLatency) {
auto pipelineDepth = presentLatency.count() / refreshRate.getPeriodNsecs();
if (presentLatency.count() % refreshRate.getPeriodNsecs()) {
pipelineDepth++;
}
- return std::max(mConfig->minAcquiredBuffers, static_cast<int64_t>(pipelineDepth - 1));
+ return std::max(minAcquiredBuffers, static_cast<int64_t>(pipelineDepth - 1));
}
status_t SurfaceFlinger::getMaxAcquiredBufferCount(int* buffers) const {
@@ -7939,7 +8058,7 @@
}
void SurfaceFlinger::sample() {
- if (!mConfig->lumaSampling || !mRegionSamplingThread) {
+ if (!mLumaSampling || !mRegionSamplingThread) {
return;
}
@@ -8131,7 +8250,7 @@
void SurfaceFlinger::moveSnapshotsFromCompositionArgs(
compositionengine::CompositionRefreshArgs& refreshArgs,
const std::vector<std::pair<Layer*, LayerFE*>>& layers) {
- if (mConfig->layerLifecycleManagerEnabled) {
+ if (mLayerLifecycleManagerEnabled) {
std::vector<std::unique_ptr<frontend::LayerSnapshot>>& snapshots =
mLayerSnapshotBuilder.getSnapshots();
for (auto [_, layerFE] : layers) {
@@ -8139,7 +8258,7 @@
snapshots[i] = std::move(layerFE->mSnapshot);
}
}
- if (mConfig->legacyFrontEndEnabled && !mConfig->layerLifecycleManagerEnabled) {
+ if (mLegacyFrontEndEnabled && !mLayerLifecycleManagerEnabled) {
for (auto [layer, layerFE] : layers) {
layer->updateLayerSnapshot(std::move(layerFE->mSnapshot));
}
@@ -8149,7 +8268,7 @@
std::vector<std::pair<Layer*, LayerFE*>> SurfaceFlinger::moveSnapshotsToCompositionArgs(
compositionengine::CompositionRefreshArgs& refreshArgs, bool cursorOnly) {
std::vector<std::pair<Layer*, LayerFE*>> layers;
- if (mConfig->layerLifecycleManagerEnabled) {
+ if (mLayerLifecycleManagerEnabled) {
nsecs_t currentTime = systemTime();
mLayerSnapshotBuilder.forEachVisibleSnapshot(
[&](std::unique_ptr<frontend::LayerSnapshot>& snapshot) {
@@ -8175,7 +8294,7 @@
layers.emplace_back(legacyLayer.get(), layerFE.get());
});
}
- if (mConfig->legacyFrontEndEnabled && !mConfig->layerLifecycleManagerEnabled) {
+ if (mLegacyFrontEndEnabled && !mLayerLifecycleManagerEnabled) {
auto moveSnapshots = [&layers, &refreshArgs, cursorOnly](Layer* layer) {
if (const auto& layerFE = layer->getCompositionEngineLayerFE()) {
if (cursorOnly &&
@@ -8267,7 +8386,7 @@
.displays = mFrontEndDisplayInfos,
.displayChanges = true,
.globalShadowSettings = mDrawingState.globalShadowSettings,
- .supportsBlur = mConfig->supportsBlur,
+ .supportsBlur = mSupportsBlur,
.forceFullDamage = mForceFullDamage,
.excludeLayerIds = std::move(excludeLayerIds),
.supportedLayerGenericMetadata =
@@ -8301,7 +8420,7 @@
.displays = mFrontEndDisplayInfos,
.displayChanges = true,
.globalShadowSettings = mDrawingState.globalShadowSettings,
- .supportsBlur = mConfig->supportsBlur,
+ .supportsBlur = mSupportsBlur,
.forceFullDamage = mForceFullDamage,
.parentCrop = parentCrop,
.excludeLayerIds = std::move(excludeLayerIds),
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 55e1b75..5c57abd 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -63,7 +63,6 @@
#include <scheduler/interface/ICompositor.h>
#include <ui/FenceResult.h>
-#include "Client.h"
#include "Display/PhysicalDisplay.h"
#include "DisplayDevice.h"
#include "DisplayHardware/HWC2.h"
@@ -82,7 +81,6 @@
#include "Scheduler/RefreshRateSelector.h"
#include "Scheduler/RefreshRateStats.h"
#include "Scheduler/Scheduler.h"
-#include "SurfaceFlingerConfig.h"
#include "SurfaceFlingerFactory.h"
#include "ThreadContext.h"
#include "Tracing/LayerTracing.h"
@@ -109,6 +107,7 @@
#include <aidl/android/hardware/graphics/common/DisplayDecorationSupport.h>
#include <aidl/android/hardware/graphics/composer3/RefreshRateChangedDebugData.h>
+#include "Client.h"
using namespace android::surfaceflinger;
@@ -198,7 +197,10 @@
private scheduler::ISchedulerCallback,
private compositionengine::ICEPowerCallback {
public:
- explicit SurfaceFlinger(surfaceflinger::Config&) ANDROID_API;
+ struct SkipInitializationTag {};
+
+ SurfaceFlinger(surfaceflinger::Factory&, SkipInitializationTag) ANDROID_API;
+ explicit SurfaceFlinger(surfaceflinger::Factory&) ANDROID_API;
// set main thread scheduling policy
static status_t setSchedFifo(bool enabled) ANDROID_API;
@@ -208,9 +210,51 @@
static char const* getServiceName() ANDROID_API { return "SurfaceFlinger"; }
+ // If fences from sync Framework are supported.
+ static bool hasSyncFramework;
+
+ // The offset in nanoseconds to use when VsyncController timestamps present fence
+ // signaling time.
+ static int64_t dispSyncPresentTimeOffset;
+
+ // Some hardware can do RGB->YUV conversion more efficiently in hardware
+ // controlled by HWC than in hardware controlled by the video encoder.
+ // This instruct VirtualDisplaySurface to use HWC for such conversion on
+ // GL composition.
+ static bool useHwcForRgbToYuv;
+
+ // Controls the number of buffers SurfaceFlinger will allocate for use in
+ // FramebufferSurface
+ static int64_t maxFrameBufferAcquiredBuffers;
+
+ // Controls the minimum acquired buffers SurfaceFlinger will suggest via
+ // ISurfaceComposer.getMaxAcquiredBufferCount().
+ static int64_t minAcquiredBuffers;
+
+ // Controls the maximum width and height in pixels that the graphics pipeline can support for
+ // GPU fallback composition. For example, 8k devices with 4k GPUs, or 4k devices with 2k GPUs.
+ static uint32_t maxGraphicsWidth;
+ static uint32_t maxGraphicsHeight;
+
// Indicate if device wants color management on its display.
static const constexpr bool useColorManagement = true;
+ static bool useContextPriority;
+
+ // The data space and pixel format that SurfaceFlinger expects hardware composer
+ // to composite efficiently. Meaning under most scenarios, hardware composer
+ // will accept layers with the data space and pixel format.
+ static ui::Dataspace defaultCompositionDataspace;
+ static ui::PixelFormat defaultCompositionPixelFormat;
+
+ // The data space and pixel format that SurfaceFlinger expects hardware composer
+ // to composite efficiently for wide color gamut surfaces. Meaning under most scenarios,
+ // hardware composer will accept layers with the data space and pixel format.
+ static ui::Dataspace wideColorGamutCompositionDataspace;
+ static ui::PixelFormat wideColorGamutCompositionPixelFormat;
+
+ static constexpr SkipInitializationTag SkipInitialization;
+
static LatchUnsignaledConfig enableLatchUnsignaledConfig;
// must be called before clients can connect
@@ -231,8 +275,7 @@
// Schedule sampling independently from commit or composite.
void scheduleSample();
- const surfaceflinger::Config& getConfig() { return *mConfig; }
- surfaceflinger::Factory& getFactory() { return *mConfig->factory; }
+ surfaceflinger::Factory& getFactory() { return mFactory; }
// The CompositionEngine encapsulates all composition related interfaces and actions.
compositionengine::CompositionEngine& getCompositionEngine() const;
@@ -264,6 +307,10 @@
return mTransactionCallbackInvoker;
}
+ // If set, disables reusing client composition buffers. This can be set by
+ // debug.sf.disable_client_composition_cache
+ bool mDisableClientCompositionCache = false;
+
// Disables expensive rendering for all displays
// This is scheduled on the main thread
void disableExpensiveRendering();
@@ -274,6 +321,17 @@
// run parallel to the hwc validateDisplay call and re-run if the predition is incorrect.
bool mPredictCompositionStrategy = false;
+ // If true, then any layer with a SMPTE 170M transfer function is decoded using the sRGB
+ // transfer instead. This is mainly to preserve legacy behavior, where implementations treated
+ // SMPTE 170M as sRGB prior to color management being implemented, and now implementations rely
+ // on this behavior to increase contrast for some media sources.
+ bool mTreat170mAsSrgb = false;
+
+ // Allows to ignore physical orientation provided through hwc API in favour of
+ // 'ro.surface_flinger.primary_display_orientation'.
+ // TODO(b/246793311): Clean up a temporary property
+ bool mIgnoreHwcPhysicalDisplayOrientation = false;
+
void forceFutureUpdate(int delayInMs);
const DisplayDevice* getDisplayFromLayerStack(ui::LayerStack)
REQUIRES(mStateLock, kMainThreadContext);
@@ -608,6 +666,12 @@
// Keeps track of whether the kernel idle timer is currently enabled, so we don't have to
// make calls to sys prop each time.
bool mKernelIdleTimerEnabled = false;
+ // Show spinner with refresh rate overlay
+ bool mRefreshRateOverlaySpinner = false;
+ // Show render rate with refresh rate overlay
+ bool mRefreshRateOverlayRenderRate = false;
+ // Show render rate overlay offseted to the middle of the screen (e.g. for circular displays)
+ bool mRefreshRateOverlayShowInMiddle = false;
void setDesiredActiveMode(display::DisplayModeRequest&&, bool force = false)
REQUIRES(mStateLock);
@@ -1042,8 +1106,8 @@
*/
const std::unordered_map<std::string, uint32_t>& getGenericLayerMetadataKeyMap() const;
- int calculateMaxAcquiredBufferCount(Fps refreshRate,
- std::chrono::nanoseconds presentLatency) const;
+ static int calculateMaxAcquiredBufferCount(Fps refreshRate,
+ std::chrono::nanoseconds presentLatency);
int getMaxAcquiredBufferCountForRefreshRate(Fps refreshRate) const;
bool isHdrLayer(const frontend::LayerSnapshot& snapshot) const;
@@ -1053,7 +1117,8 @@
void traverseLegacyLayers(const LayerVector::Visitor& visitor) const;
sp<StartPropertySetThread> mStartPropertySetThread;
- surfaceflinger::Config* const mConfig = nullptr;
+ surfaceflinger::Factory& mFactory;
+ pid_t mPid;
std::future<void> mRenderEnginePrimeCacheFuture;
// mStateLock has conventions related to the current thread, because only
@@ -1080,6 +1145,12 @@
float mGlobalSaturationFactor = 1.0f;
mat4 mClientColorMatrix;
+ size_t mMaxGraphicBufferProducerListSize = MAX_LAYERS;
+ // If there are more GraphicBufferProducers tracked by SurfaceFlinger than
+ // this threshold, then begin logging.
+ size_t mGraphicBufferProducerListSizeLogThreshold =
+ static_cast<size_t>(0.95 * static_cast<double>(MAX_LAYERS));
+
// protected by mStateLock (but we could use another lock)
bool mLayersRemoved = false;
bool mLayersAdded = false;
@@ -1089,6 +1160,7 @@
// constant members (no synchronization needed for access)
const nsecs_t mBootTime = systemTime();
+ bool mIsUserBuild = true;
// Can only accessed from the main thread, these members
// don't need synchronization
@@ -1100,6 +1172,7 @@
// Used to ensure we omit a callback when HDR layer info listener is newly added but the
// scene hasn't changed
bool mAddingHDRLayerInfoListener = false;
+ bool mIgnoreHdrCameraLayers = false;
// Set during transaction application stage to track if the input info or children
// for a layer has changed.
@@ -1158,6 +1231,9 @@
std::atomic<nsecs_t> mDebugInTransaction = 0;
std::atomic_bool mForceFullDamage = false;
+ bool mLayerCachingEnabled = false;
+ bool mBackpressureGpuComposition = false;
+
LayerTracing mLayerTracing;
bool mLayerTracingEnabled = false;
@@ -1170,6 +1246,9 @@
VsyncId mLastCommittedVsyncId;
+ // If blurs should be enabled on this device.
+ bool mSupportsBlur = false;
+
TransactionCallbackInvoker mTransactionCallbackInvoker;
// We maintain a pool of pre-generated texture names to hand out to avoid
@@ -1201,9 +1280,13 @@
// This property can be used to force SurfaceFlinger to always pick a certain color mode.
ui::ColorMode mForceColorMode = ui::ColorMode::NATIVE;
- std::optional<ui::Dataspace> mOverrideDefaultCompositionDataspace;
- std::optional<ui::Dataspace> mOverrideWideColorGamutCompositionDataspace;
+ // Whether to enable wide color gamut (e.g. Display P3) for internal displays that support it.
+ // If false, wide color modes are filtered out for all internal displays.
+ bool mSupportsWideColor = false;
+ ui::Dataspace mDefaultCompositionDataspace;
+ ui::Dataspace mWideColorGamutCompositionDataspace;
+ ui::Dataspace mColorSpaceAgnosticDataspace;
float mDimmingRatio = -1.f;
std::unique_ptr<renderengine::RenderEngine> mRenderEngine;
@@ -1217,6 +1300,8 @@
// any mutex.
size_t mMaxRenderTargetSize{1};
+ const std::string mHwcServiceName;
+
/*
* Scheduler
*/
@@ -1233,9 +1318,14 @@
// below flags are set by main thread only
bool mSetActiveModePending = false;
+ bool mLumaSampling = true;
sp<RegionSamplingThread> mRegionSamplingThread;
sp<FpsReporter> mFpsReporter;
sp<TunnelModeEnabledReporter> mTunnelModeEnabledReporter;
+ ui::DisplayPrimaries mInternalDisplayPrimaries;
+
+ const float mEmulatedDisplayDensity;
+ const float mInternalDisplayDensity;
// Should only be accessed by the main thread.
sp<os::IInputFlinger> mInputFlinger;
@@ -1312,6 +1402,9 @@
bool mPowerHintSessionEnabled;
+ bool mLayerLifecycleManagerEnabled = false;
+ bool mLegacyFrontEndEnabled = true;
+
frontend::LayerLifecycleManager mLayerLifecycleManager;
frontend::LayerHierarchyBuilder mLayerHierarchyBuilder{{}};
frontend::LayerSnapshotBuilder mLayerSnapshotBuilder;
diff --git a/services/surfaceflinger/SurfaceFlingerConfig.cpp b/services/surfaceflinger/SurfaceFlingerConfig.cpp
deleted file mode 100644
index 0b25a44..0000000
--- a/services/surfaceflinger/SurfaceFlingerConfig.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright 2023 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 <cstdlib>
-
-#include <SurfaceFlingerProperties.h>
-#include <SurfaceFlingerProperties.sysprop.h>
-#include <android-base/properties.h>
-#include <android/configuration.h>
-
-#include "SurfaceFlingerConfig.h"
-
-namespace android::surfaceflinger {
-
-using namespace std::string_literals;
-
-namespace {
-
-// TODO(b/141333600): Consolidate with DisplayMode::Builder::getDefaultDensity.
-constexpr float FALLBACK_DENSITY = ACONFIGURATION_DENSITY_TV;
-
-float getDensityFromProperty(const std::string& key, bool required) {
- std::string value = base::GetProperty(key, ""s);
- const float density = static_cast<float>(std::atof(value.c_str()));
- if (density == 0.f && required) {
- ALOGE("%s must be defined as a build property", key.c_str());
- return FALLBACK_DENSITY;
- }
- return density;
-}
-
-} // namespace
-
-Config::Config() = default;
-
-Config Config::makeDefault(Factory* factory) {
- Config cfg{};
-
- // Note: The values set here will affect tests.
- // To keep tests hermetic, do not set values here based on runtime values.
-
- cfg.factory = factory;
- cfg.hwcServiceName = "default"s;
- cfg.pid = getpid(); // Exception to the hermetic rules. Allow the pid to be cached.
-
- return cfg;
-}
-
-Config Config::makeProduction(Factory* factory) {
- Config cfg = makeDefault(factory);
-
- cfg.hwcServiceName = base::GetProperty("debug.sf.hwc_service_name"s, "default"s);
-
- cfg.emulatedDisplayDensity = getDensityFromProperty("qemu.sf.lcd_density"s, false),
- cfg.internalDisplayDensity =
- getDensityFromProperty("ro.sf.lcd_density"s, cfg.emulatedDisplayDensity == 0.f),
-
- cfg.hasSyncFramework = sysprop::running_without_sync_framework(cfg.hasSyncFramework);
- cfg.dispSyncPresentTimeOffset =
- sysprop::present_time_offset_from_vsync_ns(cfg.dispSyncPresentTimeOffset);
- cfg.useHwcForRgbToYuv = sysprop::force_hwc_copy_for_virtual_displays(cfg.useHwcForRgbToYuv);
- cfg.maxFrameBufferAcquiredBuffers =
- sysprop::max_frame_buffer_acquired_buffers(cfg.maxFrameBufferAcquiredBuffers);
- cfg.minAcquiredBuffers = sysprop::SurfaceFlingerProperties::min_acquired_buffers().value_or(
- cfg.minAcquiredBuffers);
-
- cfg.maxGraphicsWidth = std::max(static_cast<uint32_t>(sysprop::max_graphics_width(
- static_cast<int32_t>(cfg.maxGraphicsWidth))),
- 0u);
- cfg.maxGraphicsHeight = std::max(static_cast<uint32_t>(sysprop::max_graphics_height(
- static_cast<int32_t>(cfg.maxGraphicsHeight))),
- 0u);
-
- cfg.supportsWideColor = sysprop::has_wide_color_display(cfg.supportsWideColor);
-
- cfg.defaultCompositionDataspace = static_cast<ui::Dataspace>(
- sysprop::default_composition_dataspace(cfg.defaultCompositionDataspace));
- cfg.defaultCompositionPixelFormat = static_cast<ui::PixelFormat>(
- sysprop::default_composition_pixel_format(cfg.defaultCompositionPixelFormat));
-
- cfg.wideColorGamutCompositionDataspace =
- static_cast<ui::Dataspace>(sysprop::wcg_composition_dataspace(
- cfg.supportsWideColor ? ui::Dataspace::DISPLAY_P3 : ui::Dataspace::V0_SRGB));
- cfg.wideColorGamutCompositionPixelFormat = static_cast<ui::PixelFormat>(
- sysprop::wcg_composition_pixel_format(cfg.wideColorGamutCompositionPixelFormat));
-
- cfg.colorSpaceAgnosticDataspace = static_cast<ui::Dataspace>(
- sysprop::color_space_agnostic_dataspace(cfg.colorSpaceAgnosticDataspace));
-
- cfg.internalDisplayPrimaries = sysprop::getDisplayNativePrimaries();
-
- cfg.layerCachingEnabled =
- base::GetBoolProperty("debug.sf.enable_layer_caching"s,
- android::sysprop::SurfaceFlingerProperties::enable_layer_caching()
- .value_or(cfg.layerCachingEnabled));
- cfg.useContextPriority = sysprop::use_context_priority(cfg.useContextPriority);
-
- cfg.isUserBuild = "user"s == base::GetProperty("ro.build.type"s, "user"s);
-
- cfg.backpressureGpuComposition = base::GetBoolProperty("debug.sf.enable_gl_backpressure"s,
- cfg.backpressureGpuComposition);
- cfg.supportsBlur =
- base::GetBoolProperty("ro.surface_flinger.supports_background_blur"s, cfg.supportsBlur);
-
- cfg.lumaSampling = base::GetBoolProperty("debug.sf.luma_sampling"s, cfg.lumaSampling);
-
- cfg.disableClientCompositionCache =
- base::GetBoolProperty("debug.sf.disable_client_composition_cache"s,
- cfg.disableClientCompositionCache);
-
- cfg.predictCompositionStrategy =
- base::GetBoolProperty("debug.sf.predict_hwc_composition_strategy"s,
- cfg.predictCompositionStrategy);
-
- cfg.treat170mAsSrgb =
- base::GetBoolProperty("debug.sf.treat_170m_as_sRGB"s, cfg.treat170mAsSrgb);
-
- cfg.ignoreHwcPhysicalDisplayOrientation =
- base::GetBoolProperty("debug.sf.ignore_hwc_physical_display_orientation"s,
- cfg.ignoreHwcPhysicalDisplayOrientation);
-
- cfg.trebleTestingOverride =
- base::GetBoolProperty("debug.sf.treble_testing_override"s, cfg.trebleTestingOverride);
-
- // TODO (b/270966065) Update the HWC based refresh rate overlay to support spinner
- cfg.refreshRateOverlay.showSpinner =
- base::GetBoolProperty("debug.sf.show_refresh_rate_overlay_spinner"s,
- cfg.refreshRateOverlay.showSpinner);
- cfg.refreshRateOverlay.showRenderRate =
- base::GetBoolProperty("debug.sf.show_refresh_rate_overlay_render_rate"s,
- cfg.refreshRateOverlay.showRenderRate);
- cfg.refreshRateOverlay.showInMiddle =
- base::GetBoolProperty("debug.sf.show_refresh_rate_overlay_in_middle"s,
- cfg.refreshRateOverlay.showInMiddle);
-
- cfg.ignoreHdrCameraLayers = sysprop::ignore_hdr_camera_layers(cfg.ignoreHdrCameraLayers);
-
- cfg.enableTransactionTracing = base::GetBoolProperty("debug.sf.enable_transaction_tracing"s,
- cfg.enableTransactionTracing);
- cfg.layerLifecycleManagerEnabled =
- base::GetBoolProperty("persist.debug.sf.enable_layer_lifecycle_manager"s,
- cfg.layerLifecycleManagerEnabled);
- cfg.legacyFrontEndEnabled = !cfg.layerLifecycleManagerEnabled ||
- base::GetBoolProperty("persist.debug.sf.enable_legacy_frontend"s, false);
-
- return cfg;
-}
-
-} // namespace android::surfaceflinger
\ No newline at end of file
diff --git a/services/surfaceflinger/SurfaceFlingerConfig.h b/services/surfaceflinger/SurfaceFlingerConfig.h
deleted file mode 100644
index 7c3348e..0000000
--- a/services/surfaceflinger/SurfaceFlingerConfig.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <cstdlib>
-
-#include <ui/ConfigStoreTypes.h>
-#include <ui/GraphicTypes.h>
-
-namespace android::surfaceflinger {
-
-class Factory;
-
-struct Config final {
- Factory* factory = nullptr;
-
- std::string hwcServiceName;
- pid_t pid;
-
- float emulatedDisplayDensity = 0;
- float internalDisplayDensity = 0;
-
- // If fences from sync Framework are supported.
- bool hasSyncFramework = true;
-
- // The offset in nanoseconds to use when VsyncController timestamps present
- // fence signaling time.
- int64_t dispSyncPresentTimeOffset = 0;
-
- // Some hardware can do RGB->YUV conversion more efficiently in hardware
- // controlled by HWC than in hardware controlled by the video encoder. This
- // instruct VirtualDisplaySurface to use HWC for such conversion on GL
- // composition.
- bool useHwcForRgbToYuv = false;
-
- // Controls the number of buffers SurfaceFlinger will allocate for use in
- // FramebufferSurface
- int64_t maxFrameBufferAcquiredBuffers = 2;
-
- // Controls the minimum acquired buffers SurfaceFlinger will suggest via
- // ISurfaceComposer.getMaxAcquiredBufferCount().
- int64_t minAcquiredBuffers = 1;
-
- // Controls the maximum width and height in pixels that the graphics
- // pipeline can support for GPU fallback composition. For example, 8k
- // devices with 4k GPUs, or 4k devices with 2k GPUs.
- uint32_t maxGraphicsWidth = 0;
- uint32_t maxGraphicsHeight = 0;
-
- // Whether to enable wide color gamut (e.g. Display P3) for internal
- // displays that support it. If false, wide color modes are filtered out
- // for all internal displays.
- bool mSupportsWideColor = false;
- bool supportsWideColor = false;
-
- // The data space and pixel format that SurfaceFlinger expects hardware
- // composer to composite efficiently. Meaning under most scenarios,
- // hardware composer will accept layers with the data space and pixel
- // format.
- ui::Dataspace defaultCompositionDataspace = ui::Dataspace::V0_SRGB;
- ui::PixelFormat defaultCompositionPixelFormat = ui::PixelFormat::RGBA_8888;
-
- // The data space and pixel format that SurfaceFlinger expects hardware
- // composer to composite efficiently for wide color gamut surfaces. Meaning
- // under most scenarios, hardware composer will accept layers with the data
- // space and pixel format.
- ui::Dataspace wideColorGamutCompositionDataspace = ui::Dataspace::V0_SRGB;
- ui::PixelFormat wideColorGamutCompositionPixelFormat = ui::PixelFormat::RGBA_8888;
-
- ui::Dataspace colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
-
- ui::DisplayPrimaries internalDisplayPrimaries{};
-
- bool layerCachingEnabled = false;
- bool useContextPriority = true;
- bool isUserBuild = true;
- bool backpressureGpuComposition = true;
-
- // If blurs should be enabled on this device.
- bool supportsBlur = false;
- bool lumaSampling = true;
-
- // If set, disables reusing client composition buffers. This can be set by
- // debug.sf.disable_client_composition_cache
- bool disableClientCompositionCache = false;
-
- // If set, composition engine tries to predict the composition strategy
- // provided by HWC based on the previous frame. If the strategy can be
- // predicted, gpu composition will run parallel to the hwc validateDisplay
- // call and re-run if the predition is incorrect.
- bool predictCompositionStrategy = true;
-
- // If true, then any layer with a SMPTE 170M transfer function is decoded
- // using the sRGB transfer instead. This is mainly to preserve legacy
- // behavior, where implementations treated SMPTE 170M as sRGB prior to
- // color management being implemented, and now implementations rely on this
- // behavior to increase contrast for some media sources.
- bool treat170mAsSrgb = false;
-
- // Allows to ignore physical orientation provided through hwc API in favour
- // of 'ro.surface_flinger.primary_display_orientation'.
- // TODO(b/246793311): Clean up a temporary property
- bool ignoreHwcPhysicalDisplayOrientation = false;
-
- bool trebleTestingOverride = false;
-
- struct {
- // Show spinner with refresh rate overlay
- bool showSpinner = false;
-
- // Show render rate with refresh rate overlay
- bool showRenderRate = false;
-
- // Show render rate overlay offseted to the middle of the screen (e.g.
- // for circular displays)
- bool showInMiddle = false;
- } refreshRateOverlay;
-
- bool ignoreHdrCameraLayers = false;
- bool enableTransactionTracing = true;
- bool layerLifecycleManagerEnabled = false;
- bool legacyFrontEndEnabled = true;
-
- static Config makeDefault(Factory* factory);
- static Config makeProduction(Factory* factory);
-
-private:
- Config();
-};
-
-} // namespace android::surfaceflinger
diff --git a/services/surfaceflinger/SurfaceFlingerFactory.cpp b/services/surfaceflinger/SurfaceFlingerFactory.cpp
index ac351cb..7bd6cf6 100644
--- a/services/surfaceflinger/SurfaceFlingerFactory.cpp
+++ b/services/surfaceflinger/SurfaceFlingerFactory.cpp
@@ -14,17 +14,22 @@
* limitations under the License.
*/
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+
#include "SurfaceFlinger.h"
-#include "SurfaceFlingerConfig.h"
#include "SurfaceFlingerDefaultFactory.h"
namespace android::surfaceflinger {
sp<SurfaceFlinger> createSurfaceFlinger() {
static DefaultFactory factory;
- static Config config = Config::makeProduction(&factory);
- return sp<SurfaceFlinger>::make(config);
+ return sp<SurfaceFlinger>::make(factory);
}
} // namespace android::surfaceflinger
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_displayhardware_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_displayhardware_fuzzer.cpp
index d296c47..9fac14e 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_displayhardware_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_displayhardware_fuzzer.cpp
@@ -481,8 +481,7 @@
sp<FramebufferSurface> surface =
sp<FramebufferSurface>::make(mHwc, mPhysicalDisplayId, bqConsumer,
- getFuzzedSize() /*size*/, getFuzzedSize() /*maxSize*/,
- mFdp.PickValueInArray(kMaxFrameBufferAcquiredBuffers));
+ getFuzzedSize() /*size*/, getFuzzedSize() /*maxSize*/);
surface->beginFrame(mFdp.ConsumeBool());
surface->prepareFrame(mFdp.PickValueInArray(kCompositionTypes));
@@ -516,8 +515,7 @@
auto surface =
sp<VirtualDisplaySurface>::make(mHwc, VirtualDisplayId, sink, bqProducer, bqConsumer,
- mFdp.ConsumeRandomLengthString().c_str() /*name*/,
- mFdp.ConsumeBool() /* useHwcForRgbToYuv */);
+ mFdp.ConsumeRandomLengthString().c_str() /*name*/);
surface->beginFrame(mFdp.ConsumeBool());
surface->prepareFrame(mFdp.PickValueInArray(kCompositionTypes));
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
index df342dc..80943b5 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
@@ -124,20 +124,19 @@
mFlinger->setSchedFifo(mFdp.ConsumeBool());
mFlinger->setSchedAttr(mFdp.ConsumeBool());
mFlinger->getServiceName();
+ mFlinger->hasSyncFramework = mFdp.ConsumeBool();
+ mFlinger->dispSyncPresentTimeOffset = mFdp.ConsumeIntegral<int64_t>();
+ mFlinger->useHwcForRgbToYuv = mFdp.ConsumeBool();
+ mFlinger->maxFrameBufferAcquiredBuffers = mFdp.ConsumeIntegral<int64_t>();
+ mFlinger->maxGraphicsWidth = mFdp.ConsumeIntegral<uint32_t>();
+ mFlinger->maxGraphicsHeight = mFdp.ConsumeIntegral<uint32_t>();
+ mTestableFlinger.mutableSupportsWideColor() = mFdp.ConsumeBool();
+ mFlinger->useContextPriority = mFdp.ConsumeBool();
- auto& config = mTestableFlinger.mutableConfig();
- config.hasSyncFramework = mFdp.ConsumeBool();
- config.dispSyncPresentTimeOffset = mFdp.ConsumeIntegral<int64_t>();
- config.useHwcForRgbToYuv = mFdp.ConsumeBool();
- config.maxFrameBufferAcquiredBuffers = mFdp.ConsumeIntegral<int64_t>();
- config.maxGraphicsWidth = mFdp.ConsumeIntegral<uint32_t>();
- config.maxGraphicsHeight = mFdp.ConsumeIntegral<uint32_t>();
- config.supportsWideColor = mFdp.ConsumeBool();
- config.useContextPriority = mFdp.ConsumeBool();
- config.defaultCompositionDataspace = mFdp.PickValueInArray(kDataspaces);
- config.defaultCompositionPixelFormat = mFdp.PickValueInArray(kPixelFormats);
- config.wideColorGamutCompositionDataspace = mFdp.PickValueInArray(kDataspaces);
- config.wideColorGamutCompositionPixelFormat = mFdp.PickValueInArray(kPixelFormats);
+ mFlinger->defaultCompositionDataspace = mFdp.PickValueInArray(kDataspaces);
+ mFlinger->defaultCompositionPixelFormat = mFdp.PickValueInArray(kPixelFormats);
+ mFlinger->wideColorGamutCompositionDataspace = mFdp.PickValueInArray(kDataspaces);
+ mFlinger->wideColorGamutCompositionPixelFormat = mFdp.PickValueInArray(kPixelFormats);
mFlinger->enableLatchUnsignaledConfig = mFdp.PickValueInArray(kLatchUnsignaledConfig);
@@ -156,7 +155,7 @@
}
void SurfaceFlingerFuzzer::setInternalDisplayPrimaries() {
- auto& primaries = mTestableFlinger.mutableConfig().internalDisplayPrimaries;
+ ui::DisplayPrimaries primaries;
primaries.red.X = mFdp.ConsumeFloatingPoint<float>();
primaries.red.Y = mFdp.ConsumeFloatingPoint<float>();
primaries.red.Z = mFdp.ConsumeFloatingPoint<float>();
@@ -169,6 +168,7 @@
primaries.white.X = mFdp.ConsumeFloatingPoint<float>();
primaries.white.Y = mFdp.ConsumeFloatingPoint<float>();
primaries.white.Z = mFdp.ConsumeFloatingPoint<float>();
+ mTestableFlinger.setInternalDisplayPrimaries(primaries);
}
void SurfaceFlingerFuzzer::setTransactionState() {
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
index 97cb5d3..0c9a16b 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
@@ -46,7 +46,6 @@
#include "Scheduler/VsyncModulator.h"
#include "StartPropertySetThread.h"
#include "SurfaceFlinger.h"
-#include "SurfaceFlingerConfig.h"
#include "SurfaceFlingerDefaultFactory.h"
#include "ThreadContext.h"
#include "TimeStats/TimeStats.h"
@@ -151,8 +150,6 @@
ui::PixelFormat::YCBCR_P010,
ui::PixelFormat::HSV_888};
-static constexpr int kMaxFrameBufferAcquiredBuffers[] = {2, 3, 4};
-
inline VsyncId getFuzzedVsyncId(FuzzedDataProvider& fdp) {
return VsyncId{fdp.ConsumeIntegral<int64_t>()};
}
@@ -407,8 +404,6 @@
SurfaceFlinger *flinger() { return mFlinger.get(); }
scheduler::TestableScheduler *scheduler() { return mScheduler; }
- auto& mutableConfig() { return mConfig; }
-
void initializeDisplays() {
FTL_FAKE_GUARD(kMainThreadContext, mFlinger->initializeDisplays());
}
@@ -700,6 +695,10 @@
mFactory.mCreateNativeWindowSurface = f;
}
+ void setInternalDisplayPrimaries(const ui::DisplayPrimaries &primaries) {
+ memcpy(&mFlinger->mInternalDisplayPrimaries, &primaries, sizeof(ui::DisplayPrimaries));
+ }
+
static auto &mutableLayerDrawingState(const sp<Layer> &layer) { return layer->mDrawingState; }
auto &mutableStateLock() { return mFlinger->mStateLock; }
@@ -765,12 +764,13 @@
auto calculateMaxAcquiredBufferCount(Fps refreshRate,
std::chrono::nanoseconds presentLatency) const {
- return mFlinger->calculateMaxAcquiredBufferCount(refreshRate, presentLatency);
+ return SurfaceFlinger::calculateMaxAcquiredBufferCount(refreshRate, presentLatency);
}
/* Read-write access to private data to set up preconditions and assert
* post-conditions.
*/
+ auto& mutableSupportsWideColor() { return mFlinger->mSupportsWideColor; }
auto& mutableCurrentState() { return mFlinger->mCurrentState; }
auto& mutableDisplays() { return mFlinger->mDisplays; }
auto& mutableDrawingState() { return mFlinger->mDrawingState; }
@@ -794,8 +794,8 @@
void triggerOnFrameRateOverridesChanged() override {}
surfaceflinger::test::Factory mFactory;
- surfaceflinger::Config mConfig = surfaceflinger::Config::makeDefault(&mFactory);
- sp<SurfaceFlinger> mFlinger = sp<SurfaceFlinger>::make(mConfig);
+ sp<SurfaceFlinger> mFlinger =
+ sp<SurfaceFlinger>::make(mFactory, SurfaceFlinger::SkipInitialization);
scheduler::TestableScheduler *mScheduler = nullptr;
std::shared_ptr<scheduler::RefreshRateSelector> mRefreshRateSelector;
};
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_service_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_service_fuzzer.cpp
index c16a005..849a896 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_service_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_service_fuzzer.cpp
@@ -17,15 +17,13 @@
#include <fuzzbinder/libbinder_driver.h>
#include "SurfaceFlinger.h"
-#include "SurfaceFlingerConfig.h"
#include "SurfaceFlingerDefaultFactory.h"
using namespace android;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
DefaultFactory factory;
- surfaceflinger::Config config = surfaceflinger::Config::makeDefault(&factory);
- sp<SurfaceFlinger> flinger = sp<SurfaceFlinger>::make(config);
+ sp<SurfaceFlinger> flinger = sp<SurfaceFlinger>::make(factory);
flinger->init();
sp<SurfaceComposerAIDL> composerAIDL = sp<SurfaceComposerAIDL>::make(flinger);
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 7124f87..e32cf88 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -34,7 +34,7 @@
::testing::UnitTest::GetInstance()->current_test_info();
ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
- mFlinger.mutableConfig().supportsWideColor = false;
+ mFlinger.mutableSupportsWideColor() = false;
mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged;
mFlinger.setCreateBufferQueueFunction([](auto, auto, auto) {
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
index 5599a7a..ee12276 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
@@ -684,7 +684,7 @@
static constexpr bool WIDE_COLOR_SUPPORTED = false;
static void injectConfigChange(DisplayTransactionTest* test) {
- test->mFlinger.mutableConfig().supportsWideColor = true;
+ test->mFlinger.mutableSupportsWideColor() = true;
}
static void setupComposerCallExpectations(DisplayTransactionTest* test) {
@@ -699,7 +699,7 @@
static constexpr bool WIDE_COLOR_SUPPORTED = false;
static void injectConfigChange(DisplayTransactionTest* test) {
- test->mFlinger.mutableConfig().supportsWideColor = false;
+ test->mFlinger.mutableSupportsWideColor() = false;
test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged;
}
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 6c14f6e..fab3c0e 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -250,8 +250,10 @@
EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms));
- mFlinger.mutableConfig().minAcquiredBuffers = 2;
+ const auto savedMinAcquiredBuffers = mFlinger.mutableMinAcquiredBuffers();
+ mFlinger.mutableMinAcquiredBuffers() = 2;
EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms));
+ mFlinger.mutableMinAcquiredBuffers() = savedMinAcquiredBuffers;
}
MATCHER(Is120Hz, "") {
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayNativePrimariesTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayNativePrimariesTest.cpp
index fe38384..5951c98 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayNativePrimariesTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayNativePrimariesTest.cpp
@@ -84,7 +84,9 @@
injector.inject();
auto internalDisplayToken = injector.token();
- populateDummyDisplayNativePrimaries(mFlinger.mutableConfig().internalDisplayPrimaries);
+ ui::DisplayPrimaries expectedPrimaries;
+ populateDummyDisplayNativePrimaries(expectedPrimaries);
+ mFlinger.setInternalDisplayPrimaries(expectedPrimaries);
ui::DisplayPrimaries primaries;
EXPECT_EQ(NO_ERROR, mFlinger.getDisplayNativePrimaries(internalDisplayToken, primaries));
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
index 61891c1..c0796df 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
@@ -36,7 +36,7 @@
static constexpr bool WIDE_COLOR_SUPPORTED = true;
static void injectConfigChange(DisplayTransactionTest* test) {
- test->mFlinger.mutableConfig().supportsWideColor = true;
+ test->mFlinger.mutableSupportsWideColor() = true;
test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged;
}
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 099abf5..156c40a 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -45,8 +45,6 @@
#include "Scheduler/RefreshRateSelector.h"
#include "StartPropertySetThread.h"
#include "SurfaceFlinger.h"
-#include "SurfaceFlingerConfig.h"
-#include "SurfaceFlingerDefaultFactory.h"
#include "TestableScheduler.h"
#include "mock/DisplayHardware/MockComposer.h"
#include "mock/DisplayHardware/MockDisplayMode.h"
@@ -170,15 +168,13 @@
TestableSurfaceFlinger(sp<SurfaceFlinger> flinger = nullptr) : mFlinger(flinger) {
if (!mFlinger) {
- mFlinger = sp<SurfaceFlinger>::make(mConfig);
+ mFlinger = sp<SurfaceFlinger>::make(mFactory, SurfaceFlinger::SkipInitialization);
}
}
SurfaceFlinger* flinger() { return mFlinger.get(); }
scheduler::TestableScheduler* scheduler() { return mScheduler; }
- auto& mutableConfig() { return mConfig; }
-
// Extend this as needed for accessing SurfaceFlinger private (and public)
// functions.
@@ -316,6 +312,10 @@
mFactory.mCreateNativeWindowSurface = f;
}
+ void setInternalDisplayPrimaries(const ui::DisplayPrimaries& primaries) {
+ memcpy(&mFlinger->mInternalDisplayPrimaries, &primaries, sizeof(ui::DisplayPrimaries));
+ }
+
static auto& mutableLayerDrawingState(const sp<Layer>& layer) { return layer->mDrawingState; }
auto& mutableStateLock() { return mFlinger->mStateLock; }
@@ -513,7 +513,7 @@
auto calculateMaxAcquiredBufferCount(Fps refreshRate,
std::chrono::nanoseconds presentLatency) const {
- return mFlinger->calculateMaxAcquiredBufferCount(refreshRate, presentLatency);
+ return SurfaceFlinger::calculateMaxAcquiredBufferCount(refreshRate, presentLatency);
}
auto setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
@@ -596,6 +596,8 @@
const auto& hwcPhysicalDisplayIdMap() const { return getHwComposer().mPhysicalDisplayIdMap; }
const auto& hwcDisplayData() const { return getHwComposer().mDisplayData; }
+ auto& mutableSupportsWideColor() { return mFlinger->mSupportsWideColor; }
+
auto& mutableCurrentState() { return mFlinger->mCurrentState; }
auto& mutableDisplayColorSetting() { return mFlinger->mDisplayColorSetting; }
auto& mutableDisplays() { return mFlinger->mDisplays; }
@@ -620,6 +622,8 @@
return SurfaceFlinger::sActiveDisplayRotationFlags;
}
+ auto& mutableMinAcquiredBuffers() { return SurfaceFlinger::minAcquiredBuffers; }
+
auto fromHandle(const sp<IBinder>& handle) { return LayerHandle::getLayer(handle); }
~TestableSurfaceFlinger() {
@@ -1004,7 +1008,6 @@
static constexpr VsyncId kVsyncId{123};
surfaceflinger::test::Factory mFactory;
- surfaceflinger::Config mConfig = surfaceflinger::Config::makeDefault(&mFactory);
sp<SurfaceFlinger> mFlinger;
scheduler::mock::SchedulerCallback mSchedulerCallback;
scheduler::mock::NoOpSchedulerCallback mNoOpSchedulerCallback;