Merge "Add detailed Skia traces sysprop to RenderEngine." into sc-dev
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 204953c..cc0434d 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -292,8 +292,8 @@
}
}
-static unique_fd create_profile(uid_t uid, const std::string& profile, int32_t flags) {
- unique_fd fd(TEMP_FAILURE_RETRY(open(profile.c_str(), flags, 0600)));
+static unique_fd create_profile(uid_t uid, const std::string& profile, int32_t flags, mode_t mode) {
+ unique_fd fd(TEMP_FAILURE_RETRY(open(profile.c_str(), flags, mode)));
if (fd.get() < 0) {
if (errno != EEXIST) {
PLOG(ERROR) << "Failed to create profile " << profile;
@@ -310,7 +310,7 @@
return fd;
}
-static unique_fd open_profile(uid_t uid, const std::string& profile, int32_t flags) {
+static unique_fd open_profile(uid_t uid, const std::string& profile, int32_t flags, mode_t mode) {
// Do not follow symlinks when opening a profile:
// - primary profiles should not contain symlinks in their paths
// - secondary dex paths should have been already resolved and validated
@@ -320,7 +320,7 @@
// Reference profiles and snapshots are created on the fly; so they might not exist beforehand.
unique_fd fd;
if ((flags & O_CREAT) != 0) {
- fd = create_profile(uid, profile, flags);
+ fd = create_profile(uid, profile, flags, mode);
} else {
fd.reset(TEMP_FAILURE_RETRY(open(profile.c_str(), flags)));
}
@@ -336,6 +336,16 @@
PLOG(ERROR) << "Failed to open profile " << profile;
}
return invalid_unique_fd();
+ } else {
+ // If we just create the file we need to set its mode because on Android
+ // open has a mask that only allows owner access.
+ if ((flags & O_CREAT) != 0) {
+ if (fchmod(fd.get(), mode) != 0) {
+ PLOG(ERROR) << "Could not set mode " << std::hex << mode << std::dec
+ << " on profile" << profile;
+ // Not a terminal failure.
+ }
+ }
}
return fd;
@@ -345,20 +355,29 @@
const std::string& location, bool is_secondary_dex) {
std::string profile = create_current_profile_path(user, package_name, location,
is_secondary_dex);
- return open_profile(uid, profile, O_RDONLY);
+ return open_profile(uid, profile, O_RDONLY, /*mode=*/ 0);
}
static unique_fd open_reference_profile(uid_t uid, const std::string& package_name,
const std::string& location, bool read_write, bool is_secondary_dex) {
std::string profile = create_reference_profile_path(package_name, location, is_secondary_dex);
- return open_profile(uid, profile, read_write ? (O_CREAT | O_RDWR) : O_RDONLY);
+ return open_profile(
+ uid,
+ profile,
+ read_write ? (O_CREAT | O_RDWR) : O_RDONLY,
+ S_IRUSR | S_IWUSR | S_IRGRP); // so that ART can also read it when apps run.
}
static UniqueFile open_reference_profile_as_unique_file(uid_t uid, const std::string& package_name,
const std::string& location, bool read_write, bool is_secondary_dex) {
std::string profile_path = create_reference_profile_path(package_name, location,
is_secondary_dex);
- unique_fd ufd = open_profile(uid, profile_path, read_write ? (O_CREAT | O_RDWR) : O_RDONLY);
+ unique_fd ufd = open_profile(
+ uid,
+ profile_path,
+ read_write ? (O_CREAT | O_RDWR) : O_RDONLY,
+ S_IRUSR | S_IWUSR | S_IRGRP); // so that ART can also read it when apps run.
+
return UniqueFile(ufd.release(), profile_path, [](const std::string& path) {
clear_profile(path);
});
@@ -367,7 +386,7 @@
static unique_fd open_spnashot_profile(uid_t uid, const std::string& package_name,
const std::string& location) {
std::string profile = create_snapshot_profile_path(package_name, location);
- return open_profile(uid, profile, O_CREAT | O_RDWR | O_TRUNC);
+ return open_profile(uid, profile, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
}
static void open_profile_files(uid_t uid, const std::string& package_name,
@@ -2484,7 +2503,7 @@
for (size_t i = 0; i < profiles.size(); ) {
std::vector<unique_fd> profiles_fd;
for (size_t k = 0; k < kAggregationBatchSize && i < profiles.size(); k++, i++) {
- unique_fd fd = open_profile(AID_SYSTEM, profiles[i], O_RDONLY);
+ unique_fd fd = open_profile(AID_SYSTEM, profiles[i], O_RDONLY, /*mode=*/ 0);
if (fd.get() >= 0) {
profiles_fd.push_back(std::move(fd));
}
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index e272025..216347e 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -919,7 +919,7 @@
return;
}
- // Check that the snapshot was created witht he expected acess flags.
+ // Check that the snapshot was created with the expected access flags.
CheckFileAccess(snap_profile_, kSystemUid, kSystemGid, 0600 | S_IFREG);
// The snapshot should be equivalent to the merge of profiles.
@@ -962,8 +962,8 @@
return;
}
- // Check that the snapshot was created witht he expected acess flags.
- CheckFileAccess(ref_profile_, kTestAppUid, kTestAppUid, 0600 | S_IFREG);
+ // Check that the snapshot was created with the expected access flags.
+ CheckFileAccess(ref_profile_, kTestAppUid, kTestAppUid, 0640 | S_IFREG);
// The snapshot should be equivalent to the merge of profiles.
std::string ref_profile_content = ref_profile_ + ".expected";
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 3c58238..18eb7b5 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -515,9 +515,10 @@
return mDrawingBuffer.get();
}
-void GLESRenderEngine::primeCache() {
+std::future<void> GLESRenderEngine::primeCache() {
ProgramCache::getInstance().primeCache(mInProtectedContext ? mProtectedEGLContext : mEGLContext,
mUseColorManagement, mPrecacheToneMapperShaderOnly);
+ return {};
}
base::unique_fd GLESRenderEngine::flush() {
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index e7ed9c0..1ff3674 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -57,7 +57,7 @@
EGLSurface protectedStub);
~GLESRenderEngine() override EXCLUDES(mRenderingMutex);
- void primeCache() override;
+ std::future<void> primeCache() override;
void genTextures(size_t count, uint32_t* names) override;
void deleteTextures(size_t count, uint32_t const* names) override;
bool isProtected() const override { return mInProtectedContext; }
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index f805be5..1da9adc 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -29,6 +29,7 @@
#include <ui/GraphicTypes.h>
#include <ui/Transform.h>
+#include <future>
#include <memory>
/**
@@ -105,7 +106,7 @@
// This interface, while still in use until a suitable replacement is built,
// should be considered deprecated, minus some methods which still may be
// used to support legacy behavior.
- virtual void primeCache() = 0;
+ virtual std::future<void> primeCache() = 0;
// dump the extension strings. always call the base class.
virtual void dump(std::string& result) = 0;
diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h
index 27dbd1e..baa1305 100644
--- a/libs/renderengine/include/renderengine/mock/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h
@@ -35,7 +35,7 @@
RenderEngine();
~RenderEngine() override;
- MOCK_METHOD0(primeCache, void());
+ MOCK_METHOD0(primeCache, std::future<void>());
MOCK_METHOD1(dump, void(std::string&));
MOCK_METHOD2(genTextures, void(size_t, uint32_t*));
MOCK_METHOD2(deleteTextures, void(size_t, uint32_t const*));
diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp
index 8a41395..b3975b0 100644
--- a/libs/renderengine/skia/Cache.cpp
+++ b/libs/renderengine/skia/Cache.cpp
@@ -292,7 +292,11 @@
drawSolidLayers(renderengine, display, dstTexture);
drawShadowLayers(renderengine, display, srcTexture);
- drawBlurLayers(renderengine, display, dstTexture);
+
+ if (renderengine->supportsBackgroundBlur()) {
+ drawBlurLayers(renderengine, display, dstTexture);
+ }
+
// The majority of shaders are related to sampling images.
drawImageLayers(renderengine, display, dstTexture, srcTexture);
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 2d80c46..f0986a3 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -36,6 +36,7 @@
#include <SkSurface.h>
#include <android-base/stringprintf.h>
#include <gl/GrGLInterface.h>
+#include <gui/TraceUtils.h>
#include <sync/sync.h>
#include <ui/BlurRegion.h>
#include <ui/DebugUtils.h>
@@ -234,8 +235,9 @@
return engine;
}
-void SkiaGLRenderEngine::primeCache() {
+std::future<void> SkiaGLRenderEngine::primeCache() {
Cache::primeShaderCache(this);
+ return {};
}
EGLConfig SkiaGLRenderEngine::chooseEglConfig(EGLDisplay display, int format, bool logConfig) {
@@ -315,6 +317,7 @@
GrContextOptions options;
options.fDisableDriverCorrectnessWorkarounds = true;
options.fDisableDistanceFieldPaths = true;
+ options.fReducedShaderVariations = true;
options.fPersistentCache = &mSkSLCacheMonitor;
mGrContext = GrDirectContext::MakeGL(glInterface, options);
if (useProtectedContext(true)) {
@@ -506,17 +509,18 @@
return;
}
// We currently don't attempt to map a buffer if the buffer contains protected content
- // or we are using a protected context because GPU resources for protected buffers is
- // much more limited.
+ // because GPU resources for protected buffers is much more limited.
const bool isProtectedBuffer = buffer->getUsage() & GRALLOC_USAGE_PROTECTED;
- if (isProtectedBuffer || mInProtectedContext) {
+ if (isProtectedBuffer) {
return;
}
ATRACE_CALL();
- // If we were to support caching protected buffers then we will need to switch the currently
- // bound context if we are not already using the protected context (and subsequently switch
- // back after the buffer is cached).
+ // If we were to support caching protected buffers then we will need to switch the
+ // currently bound context if we are not already using the protected context (and subsequently
+ // switch back after the buffer is cached). However, for non-protected content we can bind
+ // the texture in either GL context because they are initialized with the same share_context
+ // which allows the texture state to be shared between them.
auto grContext = getActiveGrContext();
auto& cache = mTextureCache;
@@ -550,7 +554,6 @@
if (iter->second == 0) {
mTextureCache.erase(buffer->getId());
- mProtectedTextureCache.erase(buffer->getId());
mGraphicBufferExternalRefs.erase(buffer->getId());
}
}
@@ -702,7 +705,7 @@
validateOutputBufferUsage(buffer->getBuffer());
auto grContext = getActiveGrContext();
- auto& cache = mInProtectedContext ? mProtectedTextureCache : mTextureCache;
+ auto& cache = mTextureCache;
std::shared_ptr<AutoBackendTexture::LocalRef> surfaceTextureRef;
if (const auto& it = cache.find(buffer->getBuffer()->getId()); it != cache.end()) {
@@ -792,7 +795,7 @@
}
for (const auto& layer : layers) {
- ATRACE_NAME("DrawLayer");
+ ATRACE_FORMAT("DrawLayer: %s", layer->name.c_str());
if (kPrintLayerSettings) {
std::stringstream ls;
@@ -1445,12 +1448,6 @@
StringAppendF(&result, "Skia's Protected Wrapped Objects:\n");
gpuProtectedReporter.logOutput(result, true);
- StringAppendF(&result, "RenderEngine protected AHB/BackendTexture cache size: %zu\n",
- mProtectedTextureCache.size());
- StringAppendF(&result, "Dumping buffer ids...\n");
- for (const auto& [id, unused] : mProtectedTextureCache) {
- StringAppendF(&result, "- 0x%" PRIx64 "\n", id);
- }
StringAppendF(&result, "\n");
StringAppendF(&result, "RenderEngine runtime effects: %zu\n", mRuntimeEffects.size());
for (const auto& [linearEffect, unused] : mRuntimeEffects) {
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h
index 97d3b72..b972c73 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.h
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.h
@@ -53,7 +53,7 @@
EGLSurface protectedPlaceholder);
~SkiaGLRenderEngine() override EXCLUDES(mRenderingMutex);
- void primeCache() override;
+ std::future<void> primeCache() override;
status_t drawLayers(const DisplaySettings& display,
const std::vector<const LayerSettings*>& layers,
const std::shared_ptr<ExternalTexture>& buffer,
@@ -126,11 +126,9 @@
// Number of external holders of ExternalTexture references, per GraphicBuffer ID.
std::unordered_map<GraphicBufferId, int32_t> mGraphicBufferExternalRefs
GUARDED_BY(mRenderingMutex);
- // Cache of GL textures that we'll store per GraphicBuffer ID, sliced by GPU context.
+ // Cache of GL textures that we'll store per GraphicBuffer ID, shared between GPU contexts.
std::unordered_map<GraphicBufferId, std::shared_ptr<AutoBackendTexture::LocalRef>> mTextureCache
GUARDED_BY(mRenderingMutex);
- std::unordered_map<GraphicBufferId, std::shared_ptr<AutoBackendTexture::LocalRef>>
- mProtectedTextureCache GUARDED_BY(mRenderingMutex);
std::unordered_map<LinearEffect, sk_sp<SkRuntimeEffect>, LinearEffectHasher> mRuntimeEffects;
StretchShaderFactory mStretchShaderFactory;
diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h
index 7bb6d6d..f098a86 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.h
+++ b/libs/renderengine/skia/SkiaRenderEngine.h
@@ -39,7 +39,7 @@
SkiaRenderEngine(RenderEngineType type);
~SkiaRenderEngine() override {}
- virtual void primeCache() override{};
+ virtual std::future<void> primeCache() override { return {}; };
virtual void genTextures(size_t /*count*/, uint32_t* /*names*/) override{};
virtual void deleteTextures(size_t /*count*/, uint32_t const* /*names*/) override{};
virtual bool isProtected() const override { return false; } // mInProtectedContext; }
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp
index 9009ce4..74c5f47 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.cpp
+++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp
@@ -48,44 +48,70 @@
}
RenderEngineThreaded::~RenderEngineThreaded() {
- {
- std::lock_guard lock(mThreadMutex);
- mRunning = false;
- mCondition.notify_one();
- }
+ mRunning = false;
+ mCondition.notify_one();
if (mThread.joinable()) {
mThread.join();
}
}
+status_t RenderEngineThreaded::setSchedFifo(bool enabled) {
+ static constexpr int kFifoPriority = 2;
+ static constexpr int kOtherPriority = 0;
+
+ struct sched_param param = {0};
+ int sched_policy;
+ if (enabled) {
+ sched_policy = SCHED_FIFO;
+ param.sched_priority = kFifoPriority;
+ } else {
+ sched_policy = SCHED_OTHER;
+ param.sched_priority = kOtherPriority;
+ }
+
+ if (sched_setscheduler(0, sched_policy, ¶m) != 0) {
+ return -errno;
+ }
+ return NO_ERROR;
+}
+
// NO_THREAD_SAFETY_ANALYSIS is because std::unique_lock presently lacks thread safety annotations.
void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) NO_THREAD_SAFETY_ANALYSIS {
ATRACE_CALL();
- struct sched_param param = {0};
- param.sched_priority = 2;
- if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0) {
- ALOGE("Couldn't set SCHED_FIFO");
+ if (setSchedFifo(true) != NO_ERROR) {
+ ALOGW("Couldn't set SCHED_FIFO");
}
mRenderEngine = factory();
- std::unique_lock<std::mutex> lock(mThreadMutex);
pthread_setname_np(pthread_self(), mThreadName);
{
- std::unique_lock<std::mutex> lock(mInitializedMutex);
+ std::scoped_lock lock(mInitializedMutex);
mIsInitialized = true;
}
mInitializedCondition.notify_all();
while (mRunning) {
- if (!mFunctionCalls.empty()) {
- auto task = mFunctionCalls.front();
- mFunctionCalls.pop();
- task(*mRenderEngine);
+ const auto getNextTask = [this]() -> std::optional<Work> {
+ std::scoped_lock lock(mThreadMutex);
+ if (!mFunctionCalls.empty()) {
+ Work task = mFunctionCalls.front();
+ mFunctionCalls.pop();
+ return std::make_optional<Work>(task);
+ }
+ return std::nullopt;
+ };
+
+ const auto task = getNextTask();
+
+ if (task) {
+ (*task)(*mRenderEngine);
}
+
+ std::unique_lock<std::mutex> lock(mThreadMutex);
mCondition.wait(lock, [this]() REQUIRES(mThreadMutex) {
return !mRunning || !mFunctionCalls.empty();
});
@@ -100,18 +126,31 @@
mInitializedCondition.wait(lock, [=] { return mIsInitialized; });
}
-void RenderEngineThreaded::primeCache() {
+std::future<void> RenderEngineThreaded::primeCache() {
+ const auto resultPromise = std::make_shared<std::promise<void>>();
+ std::future<void> resultFuture = resultPromise->get_future();
ATRACE_CALL();
// This function is designed so it can run asynchronously, so we do not need to wait
// for the futures.
{
std::lock_guard lock(mThreadMutex);
- mFunctionCalls.push([](renderengine::RenderEngine& instance) {
+ mFunctionCalls.push([resultPromise](renderengine::RenderEngine& instance) {
ATRACE_NAME("REThreaded::primeCache");
+ if (setSchedFifo(false) != NO_ERROR) {
+ ALOGW("Couldn't set SCHED_OTHER for primeCache");
+ }
+
instance.primeCache();
+ resultPromise->set_value();
+
+ if (setSchedFifo(true) != NO_ERROR) {
+ ALOGW("Couldn't set SCHED_FIFO for primeCache");
+ }
});
}
mCondition.notify_one();
+
+ return resultFuture;
}
void RenderEngineThreaded::dump(std::string& result) {
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h
index eb6098e..c81f137 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.h
+++ b/libs/renderengine/threaded/RenderEngineThreaded.h
@@ -42,7 +42,7 @@
RenderEngineThreaded(CreateInstanceFactory factory, RenderEngineType type);
~RenderEngineThreaded() override;
- void primeCache() override;
+ std::future<void> primeCache() override;
void dump(std::string& result) override;
@@ -74,6 +74,7 @@
private:
void threadMain(CreateInstanceFactory factory);
void waitUntilInitialized() const;
+ static status_t setSchedFifo(bool enabled);
/* ------------------------------------------------------------------------
* Threading
@@ -82,9 +83,10 @@
// Protects the creation and destruction of mThread.
mutable std::mutex mThreadMutex;
std::thread mThread GUARDED_BY(mThreadMutex);
- bool mRunning GUARDED_BY(mThreadMutex) = true;
- mutable std::queue<std::function<void(renderengine::RenderEngine& instance)>> mFunctionCalls
- GUARDED_BY(mThreadMutex);
+ std::atomic<bool> mRunning = true;
+
+ using Work = std::function<void(renderengine::RenderEngine&)>;
+ mutable std::queue<Work> mFunctionCalls GUARDED_BY(mThreadMutex);
mutable std::condition_variable mCondition;
// Used to allow select thread safe methods to be accessed without requiring the
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 9df020d..a1c800e 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -2172,6 +2172,13 @@
return true;
}
+/**
+ * Checks if a sensor should be capped according to HIGH_SAMPLING_RATE_SENSORS
+ * permission.
+ *
+ * This needs to be kept in sync with the list defined on the Java side
+ * in frameworks/base/core/java/android/hardware/SystemSensorManager.java
+ */
bool SensorService::isSensorInCappedSet(int sensorType) {
return (sensorType == SENSOR_TYPE_ACCELEROMETER
|| sensorType == SENSOR_TYPE_ACCELEROMETER_UNCALIBRATED
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
index 2ffd472..244f8ab 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
@@ -73,10 +73,11 @@
void writeOutputIndependentGeometryStateToHWC(HWC2::Layer*, const LayerFECompositionState&,
bool skipLayer);
void writeOutputDependentPerFrameStateToHWC(HWC2::Layer*);
- void writeOutputIndependentPerFrameStateToHWC(HWC2::Layer*, const LayerFECompositionState&);
+ void writeOutputIndependentPerFrameStateToHWC(HWC2::Layer*, const LayerFECompositionState&,
+ bool skipLayer);
void writeSolidColorStateToHWC(HWC2::Layer*, const LayerFECompositionState&);
void writeSidebandStateToHWC(HWC2::Layer*, const LayerFECompositionState&);
- void writeBufferStateToHWC(HWC2::Layer*, const LayerFECompositionState&);
+ void writeBufferStateToHWC(HWC2::Layer*, const LayerFECompositionState&, bool skipLayer);
void writeCompositionTypeToHWC(HWC2::Layer*, Hwc2::IComposerClient::Composition,
bool isPeekingThrough, bool skipLayer);
void detectDisallowedCompositionTypeChange(Hwc2::IComposerClient::Composition from,
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index cd14327..e4e46a7 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -349,7 +349,7 @@
}
writeOutputDependentPerFrameStateToHWC(hwcLayer.get());
- writeOutputIndependentPerFrameStateToHWC(hwcLayer.get(), *outputIndependentState);
+ writeOutputIndependentPerFrameStateToHWC(hwcLayer.get(), *outputIndependentState, skipLayer);
writeCompositionTypeToHWC(hwcLayer.get(), requestedCompositionType, isPeekingThrough,
skipLayer);
@@ -471,7 +471,8 @@
}
void OutputLayer::writeOutputIndependentPerFrameStateToHWC(
- HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState) {
+ HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState,
+ bool skipLayer) {
switch (auto error = hwcLayer->setColorTransform(outputIndependentState.colorTransform)) {
case hal::Error::NONE:
break;
@@ -504,7 +505,7 @@
break;
case hal::Composition::CURSOR:
case hal::Composition::DEVICE:
- writeBufferStateToHWC(hwcLayer, outputIndependentState);
+ writeBufferStateToHWC(hwcLayer, outputIndependentState, skipLayer);
break;
case hal::Composition::INVALID:
case hal::Composition::CLIENT:
@@ -541,7 +542,8 @@
}
void OutputLayer::writeBufferStateToHWC(HWC2::Layer* hwcLayer,
- const LayerFECompositionState& outputIndependentState) {
+ const LayerFECompositionState& outputIndependentState,
+ bool skipLayer) {
auto supportedPerFrameMetadata =
getOutput().getDisplayColorProfile()->getSupportedPerFrameMetadata();
if (auto error = hwcLayer->setPerFrameMetadata(supportedPerFrameMetadata,
@@ -554,7 +556,7 @@
sp<GraphicBuffer> buffer = outputIndependentState.buffer;
sp<Fence> acquireFence = outputIndependentState.acquireFence;
int slot = outputIndependentState.bufferSlot;
- if (getState().overrideInfo.buffer != nullptr) {
+ if (getState().overrideInfo.buffer != nullptr && !skipLayer) {
buffer = getState().overrideInfo.buffer->getBuffer();
acquireFence = getState().overrideInfo.acquireFence;
slot = HwcBufferCache::FLATTENER_CACHING_SLOT;
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
index 69e8c7d..68b6231 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
@@ -294,6 +294,12 @@
return false;
}
+ // Do not use a hole punch with an HDR layer; this should be done in client
+ // composition to properly mix HDR with SDR.
+ if (hasHdrLayers()) {
+ return false;
+ }
+
const auto& layerFE = mLayers[0].getState()->getOutputLayer()->getLayerFE();
if (layerFE.getCompositionState()->forceClientComposition) {
return false;
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index 5bd1216..e9ecf3e 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -699,6 +699,7 @@
Hwc2::IComposerClient::BlendMode::PREMULTIPLIED;
static constexpr float kAlpha = 51.f;
static constexpr float kOverrideAlpha = 1.f;
+ static constexpr float kSkipAlpha = 0.f;
static constexpr ui::Dataspace kDataspace = static_cast<ui::Dataspace>(71);
static constexpr ui::Dataspace kOverrideDataspace = static_cast<ui::Dataspace>(72);
static constexpr int kSupportedPerFrameMetadata = 101;
@@ -1055,6 +1056,22 @@
/*zIsOverridden*/ false, /*isPeekingThrough*/ false);
}
+TEST_F(OutputLayerWriteStateToHWCTest, overriddenSkipLayerDoesNotSendBuffer) {
+ mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
+ includeOverrideInfo();
+
+ expectGeometryCommonCalls(kOverrideDisplayFrame, kOverrideSourceCrop, kOverrideBufferTransform,
+ kOverrideBlendMode, kSkipAlpha);
+ expectPerFrameCommonCalls(SimulateUnsupported::None, kOverrideDataspace, kOverrideVisibleRegion,
+ kOverrideSurfaceDamage);
+ expectSetHdrMetadataAndBufferCalls();
+ expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+ EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));
+
+ mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ true, 0,
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+}
+
TEST_F(OutputLayerWriteStateToHWCTest, includesOverrideInfoIfPresent) {
mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
includeOverrideInfo();
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
index b15e4f3..4a76a95 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
@@ -429,6 +429,20 @@
EXPECT_FALSE(cachedSet.requiresHolePunch());
}
+TEST_F(CachedSetTest, holePunch_requiresNonHdr) {
+ mTestLayers[0]->outputLayerCompositionState.dataspace = ui::Dataspace::BT2020_PQ;
+ mTestLayers[0]->layerState->update(&mTestLayers[0]->outputLayer);
+
+ CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
+ mTestLayers[0]->layerFECompositionState.buffer = sp<GraphicBuffer>::make();
+ sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE;
+
+ CachedSet cachedSet(layer);
+ EXPECT_CALL(*layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
+
+ EXPECT_FALSE(cachedSet.requiresHolePunch());
+}
+
TEST_F(CachedSetTest, requiresHolePunch) {
CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
mTestLayers[0]->layerFECompositionState.buffer = sp<GraphicBuffer>::make();
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a4b6fef..9cccd69 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -680,6 +680,10 @@
if (mStartPropertySetThread->join() != NO_ERROR) {
ALOGE("Join StartPropertySetThread failed!");
}
+
+ if (mRenderEnginePrimeCacheFuture.valid()) {
+ mRenderEnginePrimeCacheFuture.get();
+ }
const nsecs_t now = systemTime();
const nsecs_t duration = now - mBootTime;
ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
@@ -807,7 +811,15 @@
char primeShaderCache[PROPERTY_VALUE_MAX];
property_get("service.sf.prime_shader_cache", primeShaderCache, "1");
if (atoi(primeShaderCache)) {
- getRenderEngine().primeCache();
+ if (setSchedFifo(false) != NO_ERROR) {
+ ALOGW("Can't set SCHED_OTHER for primeCache");
+ }
+
+ mRenderEnginePrimeCacheFuture = getRenderEngine().primeCache();
+
+ if (setSchedFifo(true) != NO_ERROR) {
+ ALOGW("Can't set SCHED_OTHER for primeCache");
+ }
}
getRenderEngine().onPrimaryDisplaySizeChanged(display->getSize());
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 519a5ab..a3fa8d6 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -1183,6 +1183,8 @@
sp<StartPropertySetThread> mStartPropertySetThread;
surfaceflinger::Factory& mFactory;
+ std::future<void> mRenderEnginePrimeCacheFuture;
+
// access must be protected by mStateLock
mutable Mutex mStateLock;
State mCurrentState{LayerVector::StateSet::Current};
diff --git a/services/vibratorservice/VibratorHalWrapper.cpp b/services/vibratorservice/VibratorHalWrapper.cpp
index 1010aa5..f15a963 100644
--- a/services/vibratorservice/VibratorHalWrapper.cpp
+++ b/services/vibratorservice/VibratorHalWrapper.cpp
@@ -95,7 +95,10 @@
}
HalResult<void> HalResult<void>::fromStatus(binder::Status status) {
- if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION) {
+ if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION ||
+ status.transactionError() == android::UNKNOWN_TRANSACTION) {
+ // UNKNOWN_TRANSACTION means the HAL implementation is an older version, so this is
+ // the same as the operation being unsupported by this HAL. Should not retry.
return HalResult<void>::unsupported();
}
if (status.isOk()) {
diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
index 8720d9d..87bc34e 100644
--- a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
+++ b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
@@ -42,7 +42,10 @@
static HalResult<T> unsupported() { return HalResult("", /* unsupported= */ true); }
static HalResult<T> fromStatus(binder::Status status, T data) {
- if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION) {
+ if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION ||
+ status.transactionError() == android::UNKNOWN_TRANSACTION) {
+ // UNKNOWN_TRANSACTION means the HAL implementation is an older version, so this is
+ // the same as the operation being unsupported by this HAL. Should not retry.
return HalResult<T>::unsupported();
}
if (status.isOk()) {
diff --git a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
index af0cdb8..7813303 100644
--- a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
+++ b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
@@ -189,8 +189,7 @@
.WillRepeatedly(vibrator::TriggerSchedulerCallback());
EXPECT_CALL(*mMockHal.get(), on(Eq(11), _))
.Times(Exactly(1))
- .WillRepeatedly(Return(
- Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION)));
+ .WillRepeatedly(Return(Status::fromStatusT(UNKNOWN_TRANSACTION)));
EXPECT_CALL(*mMockHal.get(), on(Eq(12), _))
.Times(Exactly(1))
.WillRepeatedly(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)));
@@ -228,8 +227,7 @@
EXPECT_CALL(*mMockHal.get(), setAmplitude(Eq(0.1f))).Times(Exactly(1));
EXPECT_CALL(*mMockHal.get(), setAmplitude(Eq(0.2f)))
.Times(Exactly(1))
- .WillRepeatedly(Return(
- Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION)));
+ .WillRepeatedly(Return(Status::fromStatusT(UNKNOWN_TRANSACTION)));
EXPECT_CALL(*mMockHal.get(), setAmplitude(Eq(0.5f)))
.Times(Exactly(1))
.WillRepeatedly(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)));
@@ -265,8 +263,7 @@
EXPECT_CALL(*mMockHal.get(),
alwaysOnEnable(Eq(2), Eq(Effect::TICK), Eq(EffectStrength::MEDIUM)))
.Times(Exactly(1))
- .WillRepeatedly(Return(
- Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION)));
+ .WillRepeatedly(Return(Status::fromStatusT(UNKNOWN_TRANSACTION)));
EXPECT_CALL(*mMockHal.get(),
alwaysOnEnable(Eq(3), Eq(Effect::POP), Eq(EffectStrength::STRONG)))
.Times(Exactly(1))
@@ -397,8 +394,7 @@
Return(Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION)));
EXPECT_CALL(*mMockHal.get(), getSupportedPrimitives(_))
.Times(Exactly(1))
- .WillRepeatedly(
- Return(Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION)));
+ .WillRepeatedly(Return(Status::fromStatusT(UNKNOWN_TRANSACTION)));
EXPECT_CALL(*mMockHal.get(), getFrequencyMinimum(_))
.Times(Exactly(1))
.WillRepeatedly(DoAll(SetArgPointee<0>(F_MIN), Return(Status())));
@@ -411,8 +407,7 @@
Return(Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION)));
EXPECT_CALL(*mMockHal.get(), getBandwidthAmplitudeMap(_))
.Times(Exactly(1))
- .WillRepeatedly(
- Return(Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION)));
+ .WillRepeatedly(Return(Status::fromStatusT(UNKNOWN_TRANSACTION)));
EXPECT_CALL(*mMockHal.get(), getSupportedBraking(_))
.Times(Exactly(1))
.WillRepeatedly(
@@ -451,8 +446,7 @@
DoAll(SetArgPointee<3>(1000), TriggerCallbackInArg2(), Return(Status())));
EXPECT_CALL(*mMockHal.get(), perform(Eq(Effect::POP), Eq(EffectStrength::MEDIUM), _, _))
.Times(Exactly(1))
- .WillRepeatedly(Return(
- Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION)));
+ .WillRepeatedly(Return(Status::fromStatusT(UNKNOWN_TRANSACTION)));
EXPECT_CALL(*mMockHal.get(), perform(Eq(Effect::THUD), Eq(EffectStrength::STRONG), _, _))
.Times(Exactly(1))
.WillRepeatedly(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)));
@@ -549,8 +543,7 @@
.WillRepeatedly(DoAll(TriggerCallbackInArg1(), Return(Status())));
EXPECT_CALL(*mMockHal.get(), compose(Eq(singleEffect), _))
.Times(Exactly(1))
- .WillRepeatedly(Return(
- Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION)));
+ .WillRepeatedly(Return(Status::fromStatusT(UNKNOWN_TRANSACTION)));
EXPECT_CALL(*mMockHal.get(), compose(Eq(multipleEffects), _))
.Times(Exactly(1))
.WillRepeatedly(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)));
diff --git a/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp b/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp
index 548d028..1593cb1 100644
--- a/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp
+++ b/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp
@@ -308,8 +308,7 @@
Return(Status())));
EXPECT_CALL(*mMockHal.get(), triggerSynced(_))
.Times(Exactly(3))
- .WillOnce(Return(
- Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION)))
+ .WillOnce(Return(Status::fromStatusT(UNKNOWN_TRANSACTION)))
.WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
.WillRepeatedly(DoAll(TriggerCallback(), Return(Status())));
}
@@ -345,8 +344,7 @@
TEST_F(VibratorManagerHalWrapperAidlTest, TestCancelSynced) {
EXPECT_CALL(*mMockHal.get(), cancelSynced())
.Times(Exactly(3))
- .WillOnce(
- Return(Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION)))
+ .WillOnce(Return(Status::fromStatusT(UNKNOWN_TRANSACTION)))
.WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
.WillRepeatedly(Return(Status()));