Merge "Add CtsSurfaceControlTestsStaging to SF presubmit" into main
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index ac101ec..334bae4 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -34,7 +34,6 @@
"unique_file.cpp",
"utils.cpp",
"utils_default.cpp",
- "view_compiler.cpp",
":installd_aidl",
],
shared_libs: [
@@ -254,7 +253,6 @@
"unique_file.cpp",
"utils.cpp",
"utils_default.cpp",
- "view_compiler.cpp",
],
static_libs: [
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 073d0c4..d7c9b40 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -69,7 +69,6 @@
#include "installd_deps.h"
#include "otapreopt_utils.h"
#include "utils.h"
-#include "view_compiler.h"
#include "CacheTracker.h"
#include "CrateManager.h"
@@ -3258,17 +3257,6 @@
return ok();
}
-binder::Status InstalldNativeService::compileLayouts(const std::string& apkPath,
- const std::string& packageName,
- const std ::string& outDexFile, int uid,
- bool* _aidl_return) {
- const char* apk_path = apkPath.c_str();
- const char* package_name = packageName.c_str();
- const char* out_dex_file = outDexFile.c_str();
- *_aidl_return = android::installd::view_compiler(apk_path, package_name, out_dex_file, uid);
- return *_aidl_return ? ok() : error("viewcompiler failed");
-}
-
binder::Status InstalldNativeService::linkNativeLibraryDirectory(
const std::optional<std::string>& uuid, const std::string& packageName,
const std::string& nativeLibPath32, int32_t userId) {
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 1ec092d..1b56144 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -146,9 +146,6 @@
binder::Status controlDexOptBlocking(bool block);
- binder::Status compileLayouts(const std::string& apkPath, const std::string& packageName,
- const std::string& outDexFile, int uid, bool* _aidl_return);
-
binder::Status rmdex(const std::string& codePath, const std::string& instructionSet);
binder::Status mergeProfiles(int32_t uid, const std::string& packageName,
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 8893e38..f5a7709 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -70,8 +70,6 @@
// Blocks (when block is true) or unblock (when block is false) dexopt.
// Blocking also invloves cancelling the currently running dexopt.
void controlDexOptBlocking(boolean block);
- boolean compileLayouts(@utf8InCpp String apkPath, @utf8InCpp String packageName,
- @utf8InCpp String outDexFile, int uid);
void rmdex(@utf8InCpp String codePath, @utf8InCpp String instructionSet);
diff --git a/cmds/installd/view_compiler.cpp b/cmds/installd/view_compiler.cpp
deleted file mode 100644
index 8c000a1..0000000
--- a/cmds/installd/view_compiler.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "view_compiler.h"
-
-#include <string>
-
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include "utils.h"
-
-#include "android-base/logging.h"
-#include "android-base/stringprintf.h"
-#include "android-base/unique_fd.h"
-
-namespace android {
-namespace installd {
-
-namespace {
-
-using ::android::base::unique_fd;
-
-constexpr int kTimeoutMs = 300000;
-
-} // namespace
-
-bool view_compiler(const char* apk_path, const char* package_name, const char* out_dex_file,
- int uid) {
- CHECK(apk_path != nullptr);
- CHECK(package_name != nullptr);
- CHECK(out_dex_file != nullptr);
-
- // viewcompiler won't have permission to open anything, so we have to open the files first
- // and pass file descriptors.
-
- // Open input file
- unique_fd infd{open(apk_path, O_RDONLY)}; // NOLINT(android-cloexec-open)
- if (infd.get() < 0) {
- PLOG(ERROR) << "Could not open input file: " << apk_path;
- return false;
- }
-
- // Set up output file. viewcompiler can't open outputs by fd, but it can write to stdout, so
- // we close stdout and open it towards the right output.
- unique_fd outfd{open(out_dex_file, O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, 0644)};
- if (outfd.get() < 0) {
- PLOG(ERROR) << "Could not open output file: " << out_dex_file;
- return false;
- }
- if (fchmod(outfd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) != 0) {
- PLOG(ERROR) << "Could not change output file permissions";
- return false;
- }
- if (dup2(outfd, STDOUT_FILENO) < 0) {
- PLOG(ERROR) << "Could not duplicate output file descriptor";
- return false;
- }
-
- // Prepare command line arguments for viewcompiler
- std::string args[] = {"/system/bin/viewcompiler",
- "--apk",
- "--infd",
- android::base::StringPrintf("%d", infd.get()),
- "--dex",
- "--package",
- package_name};
- char* const argv[] = {const_cast<char*>(args[0].c_str()), const_cast<char*>(args[1].c_str()),
- const_cast<char*>(args[2].c_str()), const_cast<char*>(args[3].c_str()),
- const_cast<char*>(args[4].c_str()), const_cast<char*>(args[5].c_str()),
- const_cast<char*>(args[6].c_str()), nullptr};
-
- pid_t pid = fork();
- if (pid == 0) {
- // Now that we've opened the files we need, drop privileges.
- drop_capabilities(uid);
- execv("/system/bin/viewcompiler", argv);
- _exit(1);
- }
-
- int return_code = wait_child_with_timeout(pid, kTimeoutMs);
- if (!WIFEXITED(return_code)) {
- LOG(WARNING) << "viewcompiler failed for " << package_name << ":" << apk_path;
- if (WTERMSIG(return_code) == SIGKILL) {
- // If the subprocess is killed while it's writing to the file, the file is likely
- // corrupted, so we should remove it.
- remove_file_at_fd(outfd.get());
- }
- return false;
- }
- return WEXITSTATUS(return_code) == 0;
-}
-
-} // namespace installd
-} // namespace android
diff --git a/cmds/installd/view_compiler.h b/cmds/installd/view_compiler.h
deleted file mode 100644
index aa141ca..0000000
--- a/cmds/installd/view_compiler.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef VIEW_COMPILER_H_
-#define VIEW_COMPILER_H_
-
-namespace android {
-namespace installd {
-
-bool view_compiler(const char* apk_path, const char* package_name, const char* out_dex_file,
- int uid);
-
-} // namespace installd
-} // namespace android
-
-#endif // VIEW_COMPILER_H_
diff --git a/libs/binder/ndk/stability.cpp b/libs/binder/ndk/stability.cpp
index 7eafb9c..73eb863 100644
--- a/libs/binder/ndk/stability.cpp
+++ b/libs/binder/ndk/stability.cpp
@@ -27,6 +27,10 @@
#error libbinder_ndk should only be built in a system context
#endif
+#ifdef __ANDROID_VENDOR__
+#error libbinder_ndk should only be built in a system context
+#endif
+
#ifdef __ANDROID_NDK__
#error libbinder_ndk should only be built in a system context
#endif
diff --git a/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h b/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
index 47607a0..9ebaf16 100644
--- a/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
+++ b/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
@@ -104,7 +104,7 @@
GL_UPDATED = 2,
VULKAN = 3,
VULKAN_UPDATED = 4,
- ANGLE = 5,
+ ANGLE = 5, // cover both system ANGLE and ANGLE APK
};
enum Stats {
diff --git a/libs/nativewindow/include/android/native_window_aidl.h b/libs/nativewindow/include/android/native_window_aidl.h
index a252245..0d5727d 100644
--- a/libs/nativewindow/include/android/native_window_aidl.h
+++ b/libs/nativewindow/include/android/native_window_aidl.h
@@ -34,6 +34,12 @@
#include <android/native_window.h>
#include <sys/cdefs.h>
+// Only required by the AIDL glue helper
+#ifdef __cplusplus
+#include <sstream>
+#include <string>
+#endif // __cplusplus
+
__BEGIN_DECLS
/**
@@ -80,7 +86,7 @@
* Takes ownership of the ANativeWindow* given to it in reset() and will automatically
* destroy it in the destructor, similar to a smart pointer container
*/
-class NativeWindow {
+class NativeWindow final {
public:
NativeWindow() noexcept {}
explicit NativeWindow(ANativeWindow* _Nullable window) {
@@ -123,15 +129,29 @@
}
mWindow = window;
}
- inline ANativeWindow* _Nullable operator-> () const { return mWindow; }
+
inline ANativeWindow* _Nullable get() const { return mWindow; }
- inline explicit operator bool () const { return mWindow != nullptr; }
NativeWindow& operator=(NativeWindow&& other) noexcept {
mWindow = other.release(); // steal ownership from r-value
return *this;
}
+ inline ANativeWindow* _Nullable operator->() const { return mWindow; }
+ inline explicit operator bool() const { return mWindow != nullptr; }
+ inline bool operator==(const NativeWindow& rhs) const { return mWindow == rhs.mWindow; }
+ inline bool operator!=(const NativeWindow& rhs) const { return !(*this == rhs); }
+ inline bool operator<(const NativeWindow& rhs) const { return mWindow < rhs.mWindow; }
+ inline bool operator>(const NativeWindow& rhs) const { return rhs < *this; }
+ inline bool operator>=(const NativeWindow& rhs) const { return !(*this < rhs); }
+ inline bool operator<=(const NativeWindow& rhs) const { return !(*this > rhs); }
+
+ std::string toString() const {
+ std::ostringstream ss;
+ ss << "NativeWindow: " << mWindow;
+ return ss.str();
+ }
+
/**
* Stops managing any contained ANativeWindow*, returning it to the caller. Ownership
* is released.
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 04e2fff..7b2f39c 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -567,6 +567,7 @@
return nullptr;
}
+ // use ANGLE APK driver
android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::ANGLE);
driver_t* hnd = nullptr;
@@ -635,7 +636,13 @@
Loader::driver_t* Loader::attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix,
const bool exact) {
ATRACE_CALL();
- android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::GL);
+ if (strcmp(suffix, "angle") == 0) {
+ // use system ANGLE driver
+ android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::ANGLE);
+ } else {
+ android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::GL);
+ }
+
driver_t* hnd = nullptr;
void* dso = load_system_driver("GLES", suffix, exact);
if (dso) {
diff --git a/services/gpuservice/gpustats/GpuStats.cpp b/services/gpuservice/gpustats/GpuStats.cpp
index f06a045..d447d1e 100644
--- a/services/gpuservice/gpustats/GpuStats.cpp
+++ b/services/gpuservice/gpustats/GpuStats.cpp
@@ -163,11 +163,11 @@
addLoadingTime(driver, driverLoadingTime, &appInfo);
appInfo.appPackageName = appPackageName;
appInfo.driverVersionCode = driverVersionCode;
- appInfo.angleInUse = driverPackageName == "angle";
+ appInfo.angleInUse = driver == GpuStatsInfo::Driver::ANGLE;
appInfo.lastAccessTime = std::chrono::system_clock::now();
mAppStats.insert({appStatsKey, appInfo});
} else {
- mAppStats[appStatsKey].angleInUse = driverPackageName == "angle";
+ mAppStats[appStatsKey].angleInUse = driver == GpuStatsInfo::Driver::ANGLE;
addLoadingTime(driver, driverLoadingTime, &mAppStats[appStatsKey]);
mAppStats[appStatsKey].lastAccessTime = std::chrono::system_clock::now();
}
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 069d89b..ff82914 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -21,6 +21,7 @@
#include "LayerHistory.h"
#include <android-base/stringprintf.h>
+#include <com_android_graphics_surfaceflinger_flags.h>
#include <cutils/properties.h>
#include <gui/TraceUtils.h>
#include <utils/Log.h>
@@ -39,8 +40,14 @@
namespace {
+using namespace com::android::graphics::surfaceflinger;
+
bool isLayerActive(const LayerInfo& info, nsecs_t threshold) {
- // Layers with an explicit frame rate or frame rate category are always kept active,
+ if (flags::misc1() && !info.isVisible()) {
+ return false;
+ }
+
+ // Layers with an explicit frame rate or frame rate category are kept active,
// but ignore NoVote.
if (info.getSetFrameRateVote().isValid() && !info.getSetFrameRateVote().isNoVote()) {
return true;
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp
index 36f2475..54e9022 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp
@@ -304,19 +304,22 @@
if (mLayerVote.type != LayerHistory::LayerVoteType::Heuristic) {
if (mLayerVote.category != FrameRateCategory::Default) {
- ATRACE_FORMAT_INSTANT("ExplicitCategory (%s)",
+ const auto voteType = mLayerVote.type == LayerHistory::LayerVoteType::NoVote
+ ? LayerHistory::LayerVoteType::NoVote
+ : LayerHistory::LayerVoteType::ExplicitCategory;
+ ATRACE_FORMAT_INSTANT("Vote %s (category=%s)", ftl::enum_string(voteType).c_str(),
ftl::enum_string(mLayerVote.category).c_str());
- ALOGV("%s uses frame rate category: %d", mName.c_str(),
- static_cast<int>(mLayerVote.category));
- votes.push_back({LayerHistory::LayerVoteType::ExplicitCategory, Fps(),
- Seamlessness::Default, mLayerVote.category,
+ ALOGV("%s voted %s with category: %s", mName.c_str(),
+ ftl::enum_string(voteType).c_str(),
+ ftl::enum_string(mLayerVote.category).c_str());
+ votes.push_back({voteType, Fps(), Seamlessness::Default, mLayerVote.category,
mLayerVote.categorySmoothSwitchOnly});
}
if (mLayerVote.fps.isValid() ||
mLayerVote.type != LayerHistory::LayerVoteType::ExplicitDefault) {
ATRACE_FORMAT_INSTANT("Vote %s", ftl::enum_string(mLayerVote.type).c_str());
- ALOGV("%s voted %d ", mName.c_str(), static_cast<int>(mLayerVote.type));
+ ALOGV("%s voted %d", mName.c_str(), static_cast<int>(mLayerVote.type));
votes.push_back(mLayerVote);
}
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
index 1d23fb5..eb69d0b 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
@@ -401,7 +401,6 @@
float RefreshRateSelector::calculateLayerScoreLocked(const LayerRequirement& layer, Fps refreshRate,
bool isSeamlessSwitch) const {
- ATRACE_CALL();
// Slightly prefer seamless switches.
constexpr float kSeamedSwitchPenalty = 0.95f;
const float seamlessness = isSeamlessSwitch ? 1.0f : kSeamedSwitchPenalty;
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp
index 631adf1..2f6058f 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp
@@ -18,12 +18,14 @@
#define LOG_TAG "LayerHistoryIntegrationTest"
#include <Layer.h>
+#include <com_android_graphics_surfaceflinger_flags.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <log/log.h>
#include <renderengine/mock/FakeExternalTexture.h>
+#include "FlagUtils.h"
#include "FpsOps.h"
#include "LayerHierarchyTest.h"
#include "Scheduler/LayerHistory.h"
@@ -36,6 +38,7 @@
namespace android::scheduler {
using android::mock::createDisplayMode;
+using namespace com::android::graphics::surfaceflinger;
class LayerHistoryIntegrationTest : public surfaceflinger::frontend::LayerSnapshotTestBase {
protected:
@@ -492,7 +495,9 @@
EXPECT_EQ(1, frequentLayerCount(time));
}
-TEST_F(LayerHistoryIntegrationTest, invisibleExplicitLayer) {
+TEST_F(LayerHistoryIntegrationTest, invisibleExplicitLayerIsActive) {
+ SET_FLAG_FOR_TEST(flags::misc1, false);
+
auto explicitVisiblelayer = createLegacyAndFrontedEndLayer(1);
auto explicitInvisiblelayer = createLegacyAndFrontedEndLayer(2);
hideLayer(2);
@@ -515,6 +520,31 @@
EXPECT_EQ(2, frequentLayerCount(time));
}
+TEST_F(LayerHistoryIntegrationTest, invisibleExplicitLayerIsNotActive) {
+ SET_FLAG_FOR_TEST(flags::misc1, true);
+
+ auto explicitVisiblelayer = createLegacyAndFrontedEndLayer(1);
+ auto explicitInvisiblelayer = createLegacyAndFrontedEndLayer(2);
+ hideLayer(2);
+ setFrameRate(1, 60.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
+ ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
+ setFrameRate(2, 90.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
+ ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
+ nsecs_t time = systemTime();
+
+ // Post a buffer to the layers to make them active
+ setBufferWithPresentTime(explicitVisiblelayer, time);
+ setBufferWithPresentTime(explicitInvisiblelayer, time);
+
+ EXPECT_EQ(2u, layerCount());
+ ASSERT_EQ(1u, summarizeLayerHistory(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple,
+ summarizeLayerHistory(time)[0].vote);
+ EXPECT_EQ(60_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate);
+ EXPECT_EQ(1u, activeLayerCount());
+ EXPECT_EQ(1, frequentLayerCount(time));
+}
+
TEST_F(LayerHistoryIntegrationTest, infrequentAnimatingLayer) {
auto layer = createLegacyAndFrontedEndLayer(1);
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
index 33c1d86..e8831ab 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
@@ -22,10 +22,12 @@
#define LOG_TAG "LayerHistoryTest"
#include <Layer.h>
+#include <com_android_graphics_surfaceflinger_flags.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <log/log.h>
+#include "FlagUtils.h"
#include "FpsOps.h"
#include "Scheduler/LayerHistory.h"
#include "Scheduler/LayerInfo.h"
@@ -149,6 +151,8 @@
namespace {
+using namespace com::android::graphics::surfaceflinger;
+
TEST_F(LayerHistoryTest, singleLayerNoVoteDefaultCompatibility) {
const auto layer = createLayer();
EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
@@ -555,6 +559,33 @@
EXPECT_EQ(FrameRateCategory::High, summarizeLayerHistory(time)[0].frameRateCategory);
}
+TEST_F(LayerHistoryTest, oneLayerExplicitVoteWithCategoryNotVisibleDoesNotVote) {
+ SET_FLAG_FOR_TEST(flags::misc1, true);
+
+ auto layer = createLayer();
+ EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false));
+ EXPECT_CALL(*layer, getFrameRateForLayerTree())
+ .WillRepeatedly(
+ Return(Layer::FrameRate(12.34_Hz, Layer::FrameRateCompatibility::Default,
+ Seamlessness::OnlySeamless, FrameRateCategory::High)));
+
+ EXPECT_EQ(1, layerCount());
+ EXPECT_EQ(0, activeLayerCount());
+
+ nsecs_t time = systemTime();
+ for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
+ history().record(layer->getSequence(), layer->getLayerProps(), time, time,
+ LayerHistory::LayerUpdateType::Buffer);
+ time += HI_FPS_PERIOD;
+ }
+
+ // Layer is not visible, so the layer is moved to inactive, infrequent, and it will not have
+ // votes to consider for refresh rate selection.
+ ASSERT_EQ(0, summarizeLayerHistory(time).size());
+ EXPECT_EQ(0, activeLayerCount());
+ EXPECT_EQ(0, frequentLayerCount(time));
+}
+
TEST_F(LayerHistoryTest, multipleLayers) {
auto layer1 = createLayer("A");
auto layer2 = createLayer("B");
@@ -780,6 +811,8 @@
}
TEST_F(LayerHistoryTest, invisibleExplicitLayer) {
+ SET_FLAG_FOR_TEST(flags::misc1, false);
+
auto explicitVisiblelayer = createLayer();
auto explicitInvisiblelayer = createLayer();
@@ -810,6 +843,39 @@
EXPECT_EQ(2, frequentLayerCount(time));
}
+TEST_F(LayerHistoryTest, invisibleExplicitLayerDoesNotVote) {
+ SET_FLAG_FOR_TEST(flags::misc1, true);
+
+ auto explicitVisiblelayer = createLayer();
+ auto explicitInvisiblelayer = createLayer();
+
+ EXPECT_CALL(*explicitVisiblelayer, isVisible()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*explicitVisiblelayer, getFrameRateForLayerTree())
+ .WillRepeatedly(Return(
+ Layer::FrameRate(60_Hz, Layer::FrameRateCompatibility::ExactOrMultiple)));
+
+ EXPECT_CALL(*explicitInvisiblelayer, isVisible()).WillRepeatedly(Return(false));
+ EXPECT_CALL(*explicitInvisiblelayer, getFrameRateForLayerTree())
+ .WillRepeatedly(Return(
+ Layer::FrameRate(90_Hz, Layer::FrameRateCompatibility::ExactOrMultiple)));
+
+ nsecs_t time = systemTime();
+
+ // Post a buffer to the layers to make them active
+ history().record(explicitVisiblelayer->getSequence(), explicitVisiblelayer->getLayerProps(),
+ time, time, LayerHistory::LayerUpdateType::Buffer);
+ history().record(explicitInvisiblelayer->getSequence(), explicitInvisiblelayer->getLayerProps(),
+ time, time, LayerHistory::LayerUpdateType::Buffer);
+
+ EXPECT_EQ(2, layerCount());
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple,
+ summarizeLayerHistory(time)[0].vote);
+ EXPECT_EQ(60_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate);
+ EXPECT_EQ(1, activeLayerCount());
+ EXPECT_EQ(1, frequentLayerCount(time));
+}
+
TEST_F(LayerHistoryTest, infrequentAnimatingLayer) {
auto layer = createLayer();
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 8f1982d..03af56c 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -271,7 +271,7 @@
resetScheduler(mScheduler);
}
- void setupMockScheduler(test::MockSchedulerOptions options = {}) {
+ void setupMockScheduler(surfaceflinger::test::MockSchedulerOptions options = {}) {
using testing::_;
using testing::Return;