Merge "Add retries to vibrator HAL controller"
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 8173c89..5db44c7 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -58,6 +58,14 @@
},
{
"name": "libsurfaceflinger_unittest"
+ },
+ {
+ "name": "CtsGraphicsTestCases",
+ "options": [
+ {
+ "include-filter": "android.graphics.cts.VulkanPreTransformTest"
+ }
+ ]
}
]
}
diff --git a/build/phone-hdpi-512-dalvik-heap.mk b/build/phone-hdpi-512-dalvik-heap.mk
index 102c3f1..f9a12ef 100644
--- a/build/phone-hdpi-512-dalvik-heap.mk
+++ b/build/phone-hdpi-512-dalvik-heap.mk
@@ -17,10 +17,10 @@
# Provides overrides to configure the Dalvik heap for a standard high density
# phone with around 512MB total RAM.
-PRODUCT_PROPERTY_OVERRIDES += \
- dalvik.vm.heapstartsize=5m \
- dalvik.vm.heapgrowthlimit=48m \
- dalvik.vm.heapsize=128m \
- dalvik.vm.heaptargetutilization=0.75 \
- dalvik.vm.heapminfree=512k \
- dalvik.vm.heapmaxfree=2m
+PRODUCT_VENDOR_PROPERTIES += \
+ dalvik.vm.heapstartsize?=5m \
+ dalvik.vm.heapgrowthlimit?=48m \
+ dalvik.vm.heapsize?=128m \
+ dalvik.vm.heaptargetutilization?=0.75 \
+ dalvik.vm.heapminfree?=512k \
+ dalvik.vm.heapmaxfree?=2m
diff --git a/build/phone-hdpi-dalvik-heap.mk b/build/phone-hdpi-dalvik-heap.mk
index cc0ac90..71cce74 100644
--- a/build/phone-hdpi-dalvik-heap.mk
+++ b/build/phone-hdpi-dalvik-heap.mk
@@ -16,9 +16,9 @@
# Provides overrides to configure the Dalvik heap for a standard high density phone.
-PRODUCT_PROPERTY_OVERRIDES += \
- dalvik.vm.heapstartsize=5m \
- dalvik.vm.heapsize=32m \
- dalvik.vm.heaptargetutilization=0.75 \
- dalvik.vm.heapminfree=512k \
- dalvik.vm.heapmaxfree=2m
+PRODUCT_VENDOR_PROPERTIES += \
+ dalvik.vm.heapstartsize?=5m \
+ dalvik.vm.heapsize?=32m \
+ dalvik.vm.heaptargetutilization?=0.75 \
+ dalvik.vm.heapminfree?=512k \
+ dalvik.vm.heapmaxfree?=2m
diff --git a/build/phone-xhdpi-1024-dalvik-heap.mk b/build/phone-xhdpi-1024-dalvik-heap.mk
index 221227d..a522a7d 100644
--- a/build/phone-xhdpi-1024-dalvik-heap.mk
+++ b/build/phone-xhdpi-1024-dalvik-heap.mk
@@ -16,10 +16,10 @@
# Provides overrides to configure the Dalvik heap for a xhdpi phone
-PRODUCT_PROPERTY_OVERRIDES += \
- dalvik.vm.heapstartsize=8m \
- dalvik.vm.heapgrowthlimit=96m \
- dalvik.vm.heapsize=256m \
- dalvik.vm.heaptargetutilization=0.75 \
- dalvik.vm.heapminfree=512k \
- dalvik.vm.heapmaxfree=8m
+PRODUCT_VENDOR_PROPERTIES += \
+ dalvik.vm.heapstartsize?=8m \
+ dalvik.vm.heapgrowthlimit?=96m \
+ dalvik.vm.heapsize?=256m \
+ dalvik.vm.heaptargetutilization?=0.75 \
+ dalvik.vm.heapminfree?=512k \
+ dalvik.vm.heapmaxfree?=8m
diff --git a/build/phone-xhdpi-2048-dalvik-heap.mk b/build/phone-xhdpi-2048-dalvik-heap.mk
index 7ccfc13..f38d2f2 100644
--- a/build/phone-xhdpi-2048-dalvik-heap.mk
+++ b/build/phone-xhdpi-2048-dalvik-heap.mk
@@ -17,10 +17,10 @@
# Provides overrides to configure the Dalvik heap for a 2GB phone
# 192m of RAM gives enough space for 5 8 megapixel camera bitmaps in RAM.
-PRODUCT_PROPERTY_OVERRIDES += \
- dalvik.vm.heapstartsize=8m \
- dalvik.vm.heapgrowthlimit=192m \
- dalvik.vm.heapsize=512m \
- dalvik.vm.heaptargetutilization=0.75 \
- dalvik.vm.heapminfree=512k \
- dalvik.vm.heapmaxfree=8m
+PRODUCT_VENDOR_PROPERTIES += \
+ dalvik.vm.heapstartsize?=8m \
+ dalvik.vm.heapgrowthlimit?=192m \
+ dalvik.vm.heapsize?=512m \
+ dalvik.vm.heaptargetutilization?=0.75 \
+ dalvik.vm.heapminfree?=512k \
+ dalvik.vm.heapmaxfree?=8m
diff --git a/build/phone-xhdpi-4096-dalvik-heap.mk b/build/phone-xhdpi-4096-dalvik-heap.mk
index 2b84841..a6ff5a8 100644
--- a/build/phone-xhdpi-4096-dalvik-heap.mk
+++ b/build/phone-xhdpi-4096-dalvik-heap.mk
@@ -16,10 +16,10 @@
# Provides overrides to configure the Dalvik heap for a 4GB phone
-PRODUCT_PROPERTY_OVERRIDES += \
- dalvik.vm.heapstartsize=8m \
- dalvik.vm.heapgrowthlimit=192m \
- dalvik.vm.heapsize=512m \
- dalvik.vm.heaptargetutilization=0.6 \
- dalvik.vm.heapminfree=8m \
- dalvik.vm.heapmaxfree=16m
+PRODUCT_VENDOR_PROPERTIES += \
+ dalvik.vm.heapstartsize?=8m \
+ dalvik.vm.heapgrowthlimit?=192m \
+ dalvik.vm.heapsize?=512m \
+ dalvik.vm.heaptargetutilization?=0.6 \
+ dalvik.vm.heapminfree?=8m \
+ dalvik.vm.heapmaxfree?=16m
diff --git a/build/phone-xhdpi-6144-dalvik-heap.mk b/build/phone-xhdpi-6144-dalvik-heap.mk
index 2bacc4a..f08830b 100644
--- a/build/phone-xhdpi-6144-dalvik-heap.mk
+++ b/build/phone-xhdpi-6144-dalvik-heap.mk
@@ -16,10 +16,10 @@
# Provides overrides to configure the Dalvik heap for a 6GB phone
-PRODUCT_PROPERTY_OVERRIDES += \
- dalvik.vm.heapstartsize=16m \
- dalvik.vm.heapgrowthlimit=256m \
- dalvik.vm.heapsize=512m \
- dalvik.vm.heaptargetutilization=0.5 \
- dalvik.vm.heapminfree=8m \
- dalvik.vm.heapmaxfree=32m
+PRODUCT_VENDOR_PROPERTIES += \
+ dalvik.vm.heapstartsize?=16m \
+ dalvik.vm.heapgrowthlimit?=256m \
+ dalvik.vm.heapsize?=512m \
+ dalvik.vm.heaptargetutilization?=0.5 \
+ dalvik.vm.heapminfree?=8m \
+ dalvik.vm.heapmaxfree?=32m
diff --git a/build/tablet-10in-xhdpi-2048-dalvik-heap.mk b/build/tablet-10in-xhdpi-2048-dalvik-heap.mk
index 1721fcc..48c6ea6 100644
--- a/build/tablet-10in-xhdpi-2048-dalvik-heap.mk
+++ b/build/tablet-10in-xhdpi-2048-dalvik-heap.mk
@@ -16,10 +16,10 @@
# Provides overrides to configure the Dalvik heap for a standard tablet device.
-PRODUCT_PROPERTY_OVERRIDES += \
- dalvik.vm.heapstartsize=16m \
- dalvik.vm.heapgrowthlimit=192m \
- dalvik.vm.heapsize=512m \
- dalvik.vm.heaptargetutilization=0.75 \
- dalvik.vm.heapminfree=512k \
- dalvik.vm.heapmaxfree=8m
+PRODUCT_VENDOR_PROPERTIES += \
+ dalvik.vm.heapstartsize?=16m \
+ dalvik.vm.heapgrowthlimit?=192m \
+ dalvik.vm.heapsize?=512m \
+ dalvik.vm.heaptargetutilization?=0.75 \
+ dalvik.vm.heapminfree?=512k \
+ dalvik.vm.heapmaxfree?=8m
diff --git a/build/tablet-7in-hdpi-1024-dalvik-heap.mk b/build/tablet-7in-hdpi-1024-dalvik-heap.mk
index 7fd34b5..d0027dc 100644
--- a/build/tablet-7in-hdpi-1024-dalvik-heap.mk
+++ b/build/tablet-7in-hdpi-1024-dalvik-heap.mk
@@ -16,10 +16,10 @@
# Provides overrides to configure the Dalvik heap for a standard tablet device.
-PRODUCT_PROPERTY_OVERRIDES += \
- dalvik.vm.heapstartsize=8m \
- dalvik.vm.heapgrowthlimit=80m \
- dalvik.vm.heapsize=384m \
- dalvik.vm.heaptargetutilization=0.75 \
- dalvik.vm.heapminfree=512k \
- dalvik.vm.heapmaxfree=8m
+PRODUCT_VENDOR_PROPERTIES += \
+ dalvik.vm.heapstartsize?=8m \
+ dalvik.vm.heapgrowthlimit?=80m \
+ dalvik.vm.heapsize?=384m \
+ dalvik.vm.heaptargetutilization?=0.75 \
+ dalvik.vm.heapminfree?=512k \
+ dalvik.vm.heapmaxfree?=8m
diff --git a/build/tablet-7in-xhdpi-2048-dalvik-heap.mk b/build/tablet-7in-xhdpi-2048-dalvik-heap.mk
index e0f20c1..7c06b4b 100644
--- a/build/tablet-7in-xhdpi-2048-dalvik-heap.mk
+++ b/build/tablet-7in-xhdpi-2048-dalvik-heap.mk
@@ -16,10 +16,10 @@
# Provides overrides to configure the Dalvik heap for a 320dpi 7" tablet device.
-PRODUCT_PROPERTY_OVERRIDES += \
- dalvik.vm.heapstartsize=16m \
- dalvik.vm.heapgrowthlimit=192m \
- dalvik.vm.heapsize=512m \
- dalvik.vm.heaptargetutilization=0.75 \
- dalvik.vm.heapminfree=512k \
- dalvik.vm.heapmaxfree=8m
+PRODUCT_VENDOR_PROPERTIES += \
+ dalvik.vm.heapstartsize?=16m \
+ dalvik.vm.heapgrowthlimit?=192m \
+ dalvik.vm.heapsize?=512m \
+ dalvik.vm.heaptargetutilization?=0.75 \
+ dalvik.vm.heapminfree?=512k \
+ dalvik.vm.heapmaxfree?=8m
diff --git a/build/tablet-dalvik-heap.mk b/build/tablet-dalvik-heap.mk
index f577fb8..1688665 100644
--- a/build/tablet-dalvik-heap.mk
+++ b/build/tablet-dalvik-heap.mk
@@ -16,10 +16,10 @@
# Provides overrides to configure the Dalvik heap for a standard tablet device.
-PRODUCT_PROPERTY_OVERRIDES += \
- dalvik.vm.heapstartsize=5m \
- dalvik.vm.heapgrowthlimit=48m \
- dalvik.vm.heapsize=256m \
- dalvik.vm.heaptargetutilization=0.75 \
- dalvik.vm.heapminfree=512k \
- dalvik.vm.heapmaxfree=2m
+PRODUCT_VENDOR_PROPERTIES += \
+ dalvik.vm.heapstartsize?=5m \
+ dalvik.vm.heapgrowthlimit?=48m \
+ dalvik.vm.heapsize?=256m \
+ dalvik.vm.heaptargetutilization?=0.75 \
+ dalvik.vm.heapminfree?=512k \
+ dalvik.vm.heapmaxfree?=2m
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index ead491e..4058934 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -152,6 +152,8 @@
"tests/dumpstate_smoke_test.cpp",
],
static_libs: ["libgmock"],
+ test_config: "dumpstate_smoke_test.xml",
+ test_suites: ["device-tests"],
}
diff --git a/cmds/dumpstate/TEST_MAPPING b/cmds/dumpstate/TEST_MAPPING
index 083944f..8b03cfd 100644
--- a/cmds/dumpstate/TEST_MAPPING
+++ b/cmds/dumpstate/TEST_MAPPING
@@ -1,7 +1,21 @@
{
"presubmit": [
+ // TODO(159590499) add BugreportManagerTestCases
+ {
+ "name": "dumpstate_smoke_test"
+ },
{
"name": "dumpstate_test"
}
+ ],
+ "postsubmit": [
+ {
+ "name": "BugreportManagerTestCases"
+ }
+ ],
+ "imports": [
+ {
+ "path": "frameworks/base/packages/Shell"
+ }
]
-}
\ No newline at end of file
+}
diff --git a/cmds/dumpstate/dumpstate_smoke_test.xml b/cmds/dumpstate/dumpstate_smoke_test.xml
new file mode 100644
index 0000000..0aff200
--- /dev/null
+++ b/cmds/dumpstate/dumpstate_smoke_test.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<configuration description="Config for dumpstate_smoke_test">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="dumpstate_smoke_test->/data/local/tmp/dumpstate_smoke_test" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="dumpstate_smoke_test" />
+ <option name="native-test-timeout" value="600000" />
+ </test>
+</configuration>
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
index 6f2d754..bb0e5ad 100644
--- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -209,13 +209,12 @@
static std::shared_ptr<std::vector<SectionInfo>> sections;
static Dumpstate& ds;
static std::chrono::milliseconds duration;
- static void SetUpTestCase() {
+ static void GenerateBugreport() {
// clang-format off
char* argv[] = {
(char*)"dumpstate",
(char*)"-d",
- (char*)"-z",
- (char*)"-B"
+ (char*)"-z"
};
// clang-format on
sp<DumpstateListener> listener(new DumpstateListener(dup(fileno(stdout)), sections));
@@ -236,20 +235,20 @@
std::chrono::milliseconds ZippedBugreportGenerationTest::duration = 0s;
TEST_F(ZippedBugreportGenerationTest, IsGeneratedWithoutErrors) {
+ GenerateBugreport();
EXPECT_EQ(access(getZipFilePath().c_str(), F_OK), 0);
}
-TEST_F(ZippedBugreportGenerationTest, Is3MBto30MBinSize) {
+TEST_F(ZippedBugreportGenerationTest, Is3MBMBinSize) {
struct stat st;
EXPECT_EQ(stat(getZipFilePath().c_str(), &st), 0);
EXPECT_GE(st.st_size, 3000000 /* 3MB */);
- EXPECT_LE(st.st_size, 30000000 /* 30MB */);
}
-TEST_F(ZippedBugreportGenerationTest, TakesBetween30And150Seconds) {
+TEST_F(ZippedBugreportGenerationTest, TakesBetween30And300Seconds) {
EXPECT_GE(duration, 30s) << "Expected completion in more than 30s. Actual time "
<< duration.count() << " s.";
- EXPECT_LE(duration, 150s) << "Expected completion in less than 150s. Actual time "
+ EXPECT_LE(duration, 300s) << "Expected completion in less than 300s. Actual time "
<< duration.count() << " s.";
}
@@ -266,7 +265,8 @@
CloseArchive(handle);
}
- void FileExists(const char* filename, uint32_t minsize, uint32_t maxsize) {
+ void FileExists(const char* filename, uint32_t minsize,
+ uint32_t maxsize = std::numeric_limits<uint32_t>::max()) {
ZipEntry entry;
GetEntry(handle, filename, &entry);
EXPECT_GT(entry.uncompressed_length, minsize);
@@ -285,7 +285,7 @@
main_entry.uncompressed_length);
// contains main entry file
- FileExists(bugreport_txt_name.c_str(), 1000000U, 50000000U);
+ FileExists(bugreport_txt_name.c_str(), 1000000U);
}
TEST_F(ZippedBugReportContentsTest, ContainsVersion) {
@@ -301,8 +301,9 @@
}
TEST_F(ZippedBugReportContentsTest, ContainsBoardSpecificFiles) {
- FileExists("dumpstate_board.bin", 1000000U, 80000000U);
- FileExists("dumpstate_board.txt", 100000U, 1000000U);
+ // TODO(b/160109027): cf_x86_phone-userdebug does not dump them.
+ // FileExists("dumpstate_board.bin", 1000000U, 80000000U);
+ // FileExists("dumpstate_board.txt", 100000U, 1000000U);
}
TEST_F(ZippedBugReportContentsTest, ContainsProtoFile) {
diff --git a/libs/adbd_auth/adbd_auth.cpp b/libs/adbd_auth/adbd_auth.cpp
index 5a0d3f6..dae6eeb 100644
--- a/libs/adbd_auth/adbd_auth.cpp
+++ b/libs/adbd_auth/adbd_auth.cpp
@@ -83,28 +83,28 @@
InitFrameworkHandlers();
epoll_fd_.reset(epoll_create1(EPOLL_CLOEXEC));
if (epoll_fd_ == -1) {
- PLOG(FATAL) << "failed to create epoll fd";
+ PLOG(FATAL) << "adbd_auth: failed to create epoll fd";
}
event_fd_.reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
if (event_fd_ == -1) {
- PLOG(FATAL) << "failed to create eventfd";
+ PLOG(FATAL) << "adbd_auth: failed to create eventfd";
}
sock_fd_.reset(android_get_control_socket("adbd"));
if (sock_fd_ == -1) {
- PLOG(ERROR) << "failed to get adbd authentication socket";
+ PLOG(ERROR) << "adbd_auth: failed to get adbd authentication socket";
} else {
if (fcntl(sock_fd_.get(), F_SETFD, FD_CLOEXEC) != 0) {
- PLOG(FATAL) << "failed to make adbd authentication socket cloexec";
+ PLOG(FATAL) << "adbd_auth: failed to make adbd authentication socket cloexec";
}
if (fcntl(sock_fd_.get(), F_SETFL, O_NONBLOCK) != 0) {
- PLOG(FATAL) << "failed to make adbd authentication socket nonblocking";
+ PLOG(FATAL) << "adbd_auth: failed to make adbd authentication socket nonblocking";
}
if (listen(sock_fd_.get(), 4) != 0) {
- PLOG(FATAL) << "failed to listen on adbd authentication socket";
+ PLOG(FATAL) << "adbd_auth: failed to listen on adbd authentication socket";
}
}
}
@@ -146,7 +146,7 @@
struct epoll_event event;
event.events = EPOLLIN;
if (!output_queue_.empty()) {
- LOG(INFO) << "marking framework writable";
+ LOG(INFO) << "adbd_auth: marking framework writable";
event.events |= EPOLLOUT;
}
event.data.u64 = kEpollConstFramework;
@@ -155,7 +155,7 @@
}
void ReplaceFrameworkFd(unique_fd new_fd) REQUIRES(mutex_) {
- LOG(INFO) << "received new framework fd " << new_fd.get()
+ LOG(INFO) << "adbd_auth: received new framework fd " << new_fd.get()
<< " (current = " << framework_fd_.get() << ")";
// If we already had a framework fd, clean up after ourselves.
@@ -170,7 +170,7 @@
struct epoll_event event;
event.events = EPOLLIN;
if (!output_queue_.empty()) {
- LOG(INFO) << "marking framework writable";
+ LOG(INFO) << "adbd_auth: marking framework writable";
event.events |= EPOLLOUT;
}
event.data.u64 = kEpollConstFramework;
@@ -180,10 +180,10 @@
}
void HandlePacket(std::string_view packet) EXCLUDES(mutex_) {
- LOG(INFO) << "received packet: " << packet;
+ LOG(INFO) << "adbd_auth: received packet: " << packet;
if (packet.size() < 2) {
- LOG(ERROR) << "received packet of invalid length";
+ LOG(ERROR) << "adbd_auth: received packet of invalid length";
std::lock_guard<std::mutex> lock(mutex_);
ReplaceFrameworkFd(unique_fd());
}
@@ -197,7 +197,7 @@
}
}
if (!handled_packet) {
- LOG(ERROR) << "unhandled packet: " << packet;
+ LOG(ERROR) << "adbd_auth: unhandled packet: " << packet;
std::lock_guard<std::mutex> lock(mutex_);
ReplaceFrameworkFd(unique_fd());
}
@@ -206,12 +206,18 @@
void AllowUsbDevice(std::string_view buf) EXCLUDES(mutex_) {
std::lock_guard<std::mutex> lock(mutex_);
CHECK(buf.empty());
- CHECK(dispatched_prompt_.has_value());
- auto& [id, key, arg] = *dispatched_prompt_;
- keys_.emplace(id, std::move(key));
- callbacks_.key_authorized(arg, id);
- dispatched_prompt_ = std::nullopt;
+ if (dispatched_prompt_.has_value()) {
+ // It's possible for the framework to send us a response without our having sent a
+ // request to it: e.g. if adbd restarts while we have a pending request.
+ auto& [id, key, arg] = *dispatched_prompt_;
+ keys_.emplace(id, std::move(key));
+
+ callbacks_.key_authorized(arg, id);
+ dispatched_prompt_ = std::nullopt;
+ } else {
+ LOG(WARNING) << "adbd_auth: received authorization for unknown prompt, ignoring";
+ }
// We need to dispatch pending prompts here upon success as well,
// since we might have multiple queued prompts.
@@ -273,14 +279,14 @@
iovs[2].iov_base = p->public_key.data();
iovs[2].iov_len = p->public_key.size();
} else {
- LOG(FATAL) << "unhandled packet type?";
+ LOG(FATAL) << "adbd_auth: unhandled packet type?";
}
output_queue_.pop_front();
ssize_t rc = writev(framework_fd_.get(), iovs, iovcnt);
if (rc == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
- PLOG(ERROR) << "failed to write to framework fd";
+ PLOG(ERROR) << "adbd_auth: failed to write to framework fd";
ReplaceFrameworkFd(unique_fd());
return false;
}
@@ -290,7 +296,7 @@
void Run() {
if (sock_fd_ == -1) {
- LOG(ERROR) << "adbd authentication socket unavailable, disabling user prompts";
+ LOG(ERROR) << "adbd_auth: socket unavailable, disabling user prompts";
} else {
struct epoll_event event;
event.events = EPOLLIN;
@@ -309,9 +315,9 @@
struct epoll_event events[3];
int rc = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd_.get(), events, 3, -1));
if (rc == -1) {
- PLOG(FATAL) << "epoll_wait failed";
+ PLOG(FATAL) << "adbd_auth: epoll_wait failed";
} else if (rc == 0) {
- LOG(FATAL) << "epoll_wait returned 0";
+ LOG(FATAL) << "adbd_auth: epoll_wait returned 0";
}
bool restart = false;
@@ -326,7 +332,7 @@
unique_fd new_framework_fd(accept4(sock_fd_.get(), nullptr, nullptr,
SOCK_CLOEXEC | SOCK_NONBLOCK));
if (new_framework_fd == -1) {
- PLOG(FATAL) << "failed to accept framework fd";
+ PLOG(FATAL) << "adbd_auth: failed to accept framework fd";
}
LOG(INFO) << "adbd_auth: received a new framework connection";
@@ -344,7 +350,8 @@
uint64_t dummy;
int rc = TEMP_FAILURE_RETRY(read(event_fd_.get(), &dummy, sizeof(dummy)));
if (rc != 8) {
- PLOG(FATAL) << "failed to read from eventfd (rc = " << rc << ")";
+ PLOG(FATAL)
+ << "adbd_auth: failed to read from eventfd (rc = " << rc << ")";
}
std::lock_guard<std::mutex> lock(mutex_);
@@ -357,9 +364,9 @@
if (event.events & EPOLLIN) {
int rc = TEMP_FAILURE_RETRY(read(framework_fd_.get(), buf, sizeof(buf)));
if (rc == -1) {
- LOG(FATAL) << "failed to read from framework fd";
+ LOG(FATAL) << "adbd_auth: failed to read from framework fd";
} else if (rc == 0) {
- LOG(INFO) << "hit EOF on framework fd";
+ LOG(INFO) << "adbd_auth: hit EOF on framework fd";
std::lock_guard<std::mutex> lock(mutex_);
ReplaceFrameworkFd(unique_fd());
} else {
@@ -386,10 +393,10 @@
void IteratePublicKeys(bool (*callback)(void*, const char*, size_t), void* opaque) {
for (const auto& path : key_paths) {
if (access(path, R_OK) == 0) {
- LOG(INFO) << "Loading keys from " << path;
+ LOG(INFO) << "adbd_auth: loading keys from " << path;
std::string content;
if (!android::base::ReadFileToString(path, &content)) {
- PLOG(ERROR) << "Couldn't read " << path;
+ PLOG(ERROR) << "adbd_auth: couldn't read " << path;
continue;
}
for (const auto& line : android::base::Split(content, "\n")) {
@@ -405,6 +412,7 @@
uint64_t id = NextId();
std::lock_guard<std::mutex> lock(mutex_);
+ LOG(INFO) << "adbd_auth: sending prompt with id " << id;
pending_prompts_.emplace_back(id, public_key, arg);
DispatchPendingPrompt();
return id;
@@ -423,7 +431,7 @@
std::lock_guard<std::mutex> lock(mutex_);
auto it = keys_.find(id);
if (it == keys_.end()) {
- LOG(DEBUG) << "couldn't find public key to notify disconnection, skipping";
+ LOG(DEBUG) << "adbd_auth: couldn't find public key to notify disconnection, skipping";
return;
}
output_queue_.emplace_back(AdbdAuthPacketDisconnected{.public_key = std::move(it->second)});
@@ -446,7 +454,8 @@
std::lock_guard<std::mutex> lock(mutex_);
auto it = keys_.find(id);
if (it == keys_.end()) {
- LOG(DEBUG) << "couldn't find public key to notify disconnection of tls device, skipping";
+ LOG(DEBUG) << "adbd_auth: couldn't find public key to notify disconnection of tls "
+ "device, skipping";
return;
}
output_queue_.emplace_back(AdbdPacketTlsDeviceDisconnected{
@@ -461,9 +470,9 @@
uint64_t value = 1;
ssize_t rc = write(event_fd_.get(), &value, sizeof(value));
if (rc == -1) {
- PLOG(FATAL) << "write to eventfd failed";
+ PLOG(FATAL) << "adbd_auth: write to eventfd failed";
} else if (rc != sizeof(value)) {
- LOG(FATAL) << "write to eventfd returned short (" << rc << ")";
+ LOG(FATAL) << "adbd_auth: write to eventfd returned short (" << rc << ")";
}
}
@@ -516,8 +525,9 @@
if (callbacks->version == 1) {
return new AdbdAuthContext(reinterpret_cast<AdbdAuthCallbacksV1*>(callbacks));
} else {
- LOG(ERROR) << "received unknown AdbdAuthCallbacks version " << callbacks->version;
- return nullptr;
+ LOG(ERROR) << "adbd_auth: received unknown AdbdAuthCallbacks version "
+ << callbacks->version;
+ return nullptr;
}
}
@@ -545,7 +555,12 @@
void adbd_auth_prompt_user(AdbdAuthContext* ctx, const char* public_key, size_t len,
void* opaque) {
- ctx->PromptUser(std::string_view(public_key, len), opaque);
+ adbd_auth_prompt_user_with_id(ctx, public_key, len, opaque);
+}
+
+uint64_t adbd_auth_prompt_user_with_id(AdbdAuthContext* ctx, const char* public_key, size_t len,
+ void* opaque) {
+ return ctx->PromptUser(std::string_view(public_key, len), opaque);
}
uint64_t adbd_auth_tls_device_connected(AdbdAuthContext* ctx,
diff --git a/libs/adbd_auth/include/adbd_auth.h b/libs/adbd_auth/include/adbd_auth.h
index 6ee3166..8f834df 100644
--- a/libs/adbd_auth/include/adbd_auth.h
+++ b/libs/adbd_auth/include/adbd_auth.h
@@ -122,9 +122,23 @@
* @param len the length of the public_key argument
* @param arg an opaque userdata argument
*/
-void adbd_auth_prompt_user(AdbdAuthContext* ctx,
- const char* public_key,
- size_t len, void* opaque) __INTRODUCED_IN(30);
+void adbd_auth_prompt_user(AdbdAuthContext* ctx, const char* public_key, size_t len, void* opaque)
+ __INTRODUCED_IN(30);
+
+/**
+ * Prompt the user to authorize a public key.
+ *
+ * When this happens, a callback will be run on the auth thread with the result.
+ *
+ * @param ctx the AdbdAuthContext
+ * @param public_key the RSA public key to prompt user with
+ * @param len the length of the public_key argument
+ * @param arg an opaque userdata argument
+ * @return a unique id which will be returned via callback
+ */
+__attribute__((weak)) uint64_t adbd_auth_prompt_user_with_id(AdbdAuthContext* ctx,
+ const char* public_key, size_t len,
+ void* opaque) __INTRODUCED_IN(30);
/**
* Let system_server know that a TLS device has connected.
diff --git a/libs/adbd_auth/libadbd_auth.map.txt b/libs/adbd_auth/libadbd_auth.map.txt
index 5857ecb..7584ca3 100644
--- a/libs/adbd_auth/libadbd_auth.map.txt
+++ b/libs/adbd_auth/libadbd_auth.map.txt
@@ -7,6 +7,7 @@
adbd_auth_notify_auth; # apex introduced=30
adbd_auth_notify_disconnect; # apex introduced=30
adbd_auth_prompt_user; # apex introduced=30
+ adbd_auth_prompt_user_with_id; # apex introduced=30
adbd_auth_tls_device_connected; # apex introduced=30
adbd_auth_tls_device_disconnected; # apex introduced=30
adbd_auth_get_max_version; # apex introduced=30
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index db4aba8..b24a577 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -17,6 +17,8 @@
export_include_dirs: ["include"],
vendor_available: true,
host_supported: true,
+ // TODO(b/153609531): remove when no longer needed.
+ native_bridge_supported: true,
header_libs: [
"libbase_headers",
@@ -62,6 +64,8 @@
},
double_loadable: true,
host_supported: true,
+ // TODO(b/153609531): remove when no longer needed.
+ native_bridge_supported: true,
// TODO(b/31559095): get headers from bionic on host
include_dirs: [
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 166c1d8..5ea56de 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -2667,7 +2667,7 @@
releaseObjects();
- if (data) {
+ if (data || desired == 0) {
LOG_ALLOC("Parcel %p: restart from %zu to %zu capacity", this, mDataCapacity, desired);
pthread_mutex_lock(&gParcelGlobalAllocSizeLock);
gParcelGlobalAllocSize += desired;
diff --git a/libs/binder/ndk/include_platform/android/binder_parcel_platform.h b/libs/binder/ndk/include_platform/android/binder_parcel_platform.h
index ac46cb8..114a781 100644
--- a/libs/binder/ndk/include_platform/android/binder_parcel_platform.h
+++ b/libs/binder/ndk/include_platform/android/binder_parcel_platform.h
@@ -20,6 +20,10 @@
__BEGIN_DECLS
+#if defined(__ANDROID_APEX__) || defined(__ANDROID_VNDK__)
+#error this is only for platform code
+#endif
+
/**
* Gets whether or not FDs are allowed by this AParcel
*
@@ -29,4 +33,4 @@
*/
bool AParcel_getAllowFds(const AParcel*);
-__END_DECLS
\ No newline at end of file
+__END_DECLS
diff --git a/libs/gui/OWNERS b/libs/gui/OWNERS
index cbb4b97..ecccf29 100644
--- a/libs/gui/OWNERS
+++ b/libs/gui/OWNERS
@@ -13,3 +13,13 @@
vishnun@google.com
per-file EndToEndNativeInputTest.cpp = svv@google.com
+
+# BufferQueue is feature-frozen
+per-file BufferQueue* = set noparent
+per-file BufferQueue* = jreck@google.com, sumir@google.com, alecmouri@google.com
+per-file IGraphicBuffer* = set noparent
+per-file IGraphicBuffer* = jreck@google.com, sumir@google.com, alecmouri@google.com
+per-file include/gui/BufferQueue* = set noparent
+per-file include/gui/BufferQueue* = jreck@google.com, sumir@google.com, alecmouri@google.com
+per-file include/gui/IGraphicBuffer* = set noparent
+per-file include/gui/IGraphicBuffer* = jreck@google.com, sumir@google.com, alecmouri@google.com
\ No newline at end of file
diff --git a/libs/gui/bufferqueue/OWNERS b/libs/gui/bufferqueue/OWNERS
index cbe9317..615dd79 100644
--- a/libs/gui/bufferqueue/OWNERS
+++ b/libs/gui/bufferqueue/OWNERS
@@ -1,5 +1,4 @@
-chz@google.com
-lajos@google.com
-pawin@google.com
-taklee@google.com
-wonsik@google.com
+# BufferQueue is feature-frozen
+jreck@google.com
+sumir@google.com
+alecmouri@google.com
\ No newline at end of file
diff --git a/libs/vr/libpdx/fuzz/Android.bp b/libs/vr/libpdx/fuzz/Android.bp
index 3490775..8ab09f3 100644
--- a/libs/vr/libpdx/fuzz/Android.bp
+++ b/libs/vr/libpdx/fuzz/Android.bp
@@ -15,9 +15,6 @@
shared_libs: [
"libutils",
"liblog",
+ "libcutils",
],
- fuzz_config: {
- fuzz_on_haiku_host: false,
- fuzz_on_haiku_device: false,
- },
}
diff --git a/services/gpuservice/Android.bp b/services/gpuservice/Android.bp
index 04fe1e6..1bcaab4 100644
--- a/services/gpuservice/Android.bp
+++ b/services/gpuservice/Android.bp
@@ -22,6 +22,7 @@
"libcutils",
"libgfxstats",
"libgpumem",
+ "libgpumemtracer",
"libgraphicsenv",
"liblog",
"libutils",
diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp
index bad5637..18c819f 100644
--- a/services/gpuservice/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -27,10 +27,13 @@
#include <gpumem/GpuMem.h>
#include <gpustats/GpuStats.h>
#include <private/android_filesystem_config.h>
+#include <tracing/GpuMemTracer.h>
#include <utils/String8.h>
#include <utils/Trace.h>
#include <vkjson.h>
+#include <thread>
+
namespace android {
using base::StringAppendF;
@@ -46,8 +49,14 @@
const char* const GpuService::SERVICE_NAME = "gpu";
GpuService::GpuService()
- : mGpuMem(std::make_unique<GpuMem>()), mGpuStats(std::make_unique<GpuStats>()) {
- mGpuMem->initialize();
+ : mGpuMem(std::make_shared<GpuMem>()),
+ mGpuStats(std::make_unique<GpuStats>()),
+ mGpuMemTracer(std::make_unique<GpuMemTracer>()) {
+ std::thread asyncInitThread([this]() {
+ mGpuMem->initialize();
+ mGpuMemTracer->initialize(mGpuMem);
+ });
+ asyncInitThread.detach();
};
void GpuService::setGpuStats(const std::string& driverPackageName,
diff --git a/services/gpuservice/GpuService.h b/services/gpuservice/GpuService.h
index 9a0460d..43faa3e 100644
--- a/services/gpuservice/GpuService.h
+++ b/services/gpuservice/GpuService.h
@@ -30,6 +30,7 @@
class GpuMem;
class GpuStats;
+class GpuMemTracer;
class GpuService : public BnGpuService, public PriorityDumper {
public:
@@ -75,8 +76,9 @@
/*
* Attributes
*/
- std::unique_ptr<GpuMem> mGpuMem;
+ std::shared_ptr<GpuMem> mGpuMem;
std::unique_ptr<GpuStats> mGpuStats;
+ std::unique_ptr<GpuMemTracer> mGpuMemTracer;
std::string developerDriverPath;
};
diff --git a/services/gpuservice/gpumem/GpuMem.cpp b/services/gpuservice/gpumem/GpuMem.cpp
index 1d4b524..9b4053b 100644
--- a/services/gpuservice/gpumem/GpuMem.cpp
+++ b/services/gpuservice/gpumem/GpuMem.cpp
@@ -24,6 +24,7 @@
#include <libbpf.h>
#include <libbpf_android.h>
#include <log/log.h>
+#include <unistd.h>
#include <utils/Trace.h>
#include <unordered_map>
@@ -47,11 +48,17 @@
return;
}
+ // TODO(http://b/159963505): Figure out a nicer way to wait until GPU driver loaded.
// Attach the program to the tracepoint, and the tracepoint is automatically enabled here.
- if (bpf_attach_tracepoint(fd, kGpuMemTraceGroup, kGpuMemTotalTracepoint) < 0) {
- ALOGE("Failed to attach bpf program to %s/%s tracepoint", kGpuMemTraceGroup,
- kGpuMemTotalTracepoint);
- return;
+ int count = 0;
+ while (bpf_attach_tracepoint(fd, kGpuMemTraceGroup, kGpuMemTotalTracepoint) < 0) {
+ if (++count > kGpuWaitTimeout) {
+ ALOGE("Failed to attach bpf program to %s/%s tracepoint", kGpuMemTraceGroup,
+ kGpuMemTotalTracepoint);
+ return;
+ }
+ // Retry until GPU driver loaded or timeout.
+ sleep(1);
}
// Use the read-only wrapper BpfMapRO to properly retrieve the read-only map.
@@ -61,6 +68,8 @@
return;
}
setGpuMemTotalMap(map);
+
+ mInitialized.store(true);
}
void GpuMem::setGpuMemTotalMap(bpf::BpfMap<uint64_t, uint64_t>& map) {
@@ -71,7 +80,7 @@
void GpuMem::dump(const Vector<String16>& /* args */, std::string* result) {
ATRACE_CALL();
- if (!mGpuMemTotalMap.isValid()) {
+ if (!mInitialized.load() || !mGpuMemTotalMap.isValid()) {
result->append("Failed to initialize GPU memory eBPF\n");
return;
}
diff --git a/services/gpuservice/gpumem/include/gpumem/GpuMem.h b/services/gpuservice/gpumem/include/gpumem/GpuMem.h
index 6d0322a..49a9f95 100644
--- a/services/gpuservice/gpumem/include/gpumem/GpuMem.h
+++ b/services/gpuservice/gpumem/include/gpumem/GpuMem.h
@@ -31,6 +31,29 @@
void initialize();
// dumpsys interface
void dump(const Vector<String16>& args, std::string* result);
+ bool isInitialized() { return mInitialized.load(); }
+
+ // Traverse the map and send each value read back to the callback function.
+ // Used for tracing.
+ template <typename lambda>
+ void traceGpuMemTotals(lambda tracerCallback) {
+ auto res = mGpuMemTotalMap.getFirstKey();
+ if (!res.ok()) return;
+ uint64_t key = res.value();
+ while (true) {
+ uint32_t gpu_id = key >> 32;
+ uint32_t pid = key;
+
+ res = mGpuMemTotalMap.readValue(key);
+ if (!res.ok()) break;
+ uint64_t size = res.value();
+
+ tracerCallback(gpu_id, pid, size);
+ res = mGpuMemTotalMap.getNextKey(key);
+ if (!res.ok()) break;
+ key = res.value();
+ }
+ }
private:
// Friend class for testing.
@@ -39,6 +62,8 @@
// set gpu memory total map
void setGpuMemTotalMap(bpf::BpfMap<uint64_t, uint64_t>& map);
+ // indicate whether ebpf has been initialized
+ std::atomic<bool> mInitialized = false;
// bpf map for GPU memory total data
android::bpf::BpfMap<uint64_t, uint64_t> mGpuMemTotalMap;
@@ -51,6 +76,8 @@
"/sys/fs/bpf/prog_gpu_mem_tracepoint_gpu_mem_gpu_mem_total";
// pinned gpu memory total bpf map path in bpf sysfs
static constexpr char kGpuMemTotalMapPath[] = "/sys/fs/bpf/map_gpu_mem_gpu_mem_total_map";
+ // 30 seconds timeout for trying to attach bpf program to tracepoint
+ static constexpr int kGpuWaitTimeout = 30;
};
} // namespace android
diff --git a/services/gpuservice/tests/unittests/GpuMemTest.cpp b/services/gpuservice/tests/unittests/GpuMemTest.cpp
index 6ba304c..abaf30a 100644
--- a/services/gpuservice/tests/unittests/GpuMemTest.cpp
+++ b/services/gpuservice/tests/unittests/GpuMemTest.cpp
@@ -62,6 +62,7 @@
mGpuMem = std::make_unique<GpuMem>();
mTestableGpuMem = TestableGpuMem(mGpuMem.get());
+ mTestableGpuMem.setInitialized();
errno = 0;
mTestMap = bpf::BpfMap<uint64_t, uint64_t>(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE,
BPF_F_NO_PREALLOC);
diff --git a/services/gpuservice/tests/unittests/TestableGpuMem.h b/services/gpuservice/tests/unittests/TestableGpuMem.h
index 0e4b01c..6c8becb 100644
--- a/services/gpuservice/tests/unittests/TestableGpuMem.h
+++ b/services/gpuservice/tests/unittests/TestableGpuMem.h
@@ -26,6 +26,8 @@
TestableGpuMem() = default;
explicit TestableGpuMem(GpuMem *gpuMem) : mGpuMem(gpuMem) {}
+ void setInitialized() { mGpuMem->mInitialized.store(true); }
+
void setGpuMemTotalMap(bpf::BpfMap<uint64_t, uint64_t>& map) {
mGpuMem->setGpuMemTotalMap(map);
}
diff --git a/services/gpuservice/tracing/Android.bp b/services/gpuservice/tracing/Android.bp
new file mode 100644
index 0000000..919fed3
--- /dev/null
+++ b/services/gpuservice/tracing/Android.bp
@@ -0,0 +1,41 @@
+// Copyright 2020 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.
+
+cc_library_shared {
+ name: "libgpumemtracer",
+ srcs: [
+ "GpuMemTracer.cpp",
+ ],
+ shared_libs: [
+ "libgpumem",
+ "libbase",
+ "liblog",
+ "libutils",
+ ],
+ static_libs: [
+ "libperfetto_client_experimental",
+ ],
+ export_include_dirs: ["include"],
+ export_static_lib_headers: [
+ "libperfetto_client_experimental",
+ ],
+ cppflags: [
+ "-Wall",
+ "-Werror",
+ "-Wformat",
+ "-Wthread-safety",
+ "-Wunused",
+ "-Wunreachable-code",
+ ],
+}
diff --git a/services/gpuservice/tracing/GpuMemTracer.cpp b/services/gpuservice/tracing/GpuMemTracer.cpp
new file mode 100644
index 0000000..c9bfa57
--- /dev/null
+++ b/services/gpuservice/tracing/GpuMemTracer.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "GpuMemTracer"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "tracing/GpuMemTracer.h"
+
+#include <gpumem/GpuMem.h>
+#include <perfetto/trace/android/gpu_mem_event.pbzero.h>
+#include <unistd.h>
+#include <utils/Timers.h>
+
+#include <algorithm>
+#include <thread>
+
+PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::GpuMemTracer::GpuMemDataSource);
+
+namespace android {
+
+std::mutex GpuMemTracer::sTraceMutex;
+std::condition_variable GpuMemTracer::sCondition;
+bool GpuMemTracer::sTraceStarted;
+
+void GpuMemTracer::initialize(std::shared_ptr<GpuMem> gpuMem) {
+ if (!gpuMem->isInitialized()) {
+ ALOGE("Cannot initialize GpuMemTracer before GpuMem");
+ return;
+ }
+ mGpuMem = gpuMem;
+ perfetto::TracingInitArgs args;
+ args.backends = perfetto::kSystemBackend;
+ // TODO(b/160016498): Find a better way to wait for traced
+ // Sleep for 30 seconds to make sure the data source is registered only
+ // after traced starts.
+ sleep(30);
+ perfetto::Tracing::Initialize(args);
+ registerDataSource();
+ std::thread tracerThread(&GpuMemTracer::threadLoop, this);
+ pthread_setname_np(tracerThread.native_handle(), "GpuMemTracerThread");
+ tracerThread.detach();
+}
+
+void GpuMemTracer::registerDataSource() {
+ perfetto::DataSourceDescriptor dsd;
+ dsd.set_name(kGpuMemDataSource);
+ GpuMemDataSource::Register(dsd);
+}
+
+void GpuMemTracer::threadLoop() {
+ while (true) {
+ {
+ std::unique_lock<std::mutex> lock(GpuMemTracer::sTraceMutex);
+ while (!sTraceStarted) {
+ sCondition.wait(lock);
+ }
+ }
+ traceInitialCounters();
+ {
+ std::lock_guard<std::mutex> lock(GpuMemTracer::sTraceMutex);
+ sTraceStarted = false;
+ }
+ }
+}
+
+void GpuMemTracer::traceInitialCounters() {
+ if (!mGpuMem->isInitialized()) {
+ // This should never happen.
+ ALOGE("Cannot trace without GpuMem initialization");
+ return;
+ }
+ mGpuMem->traceGpuMemTotals([](uint32_t gpuId, uint32_t pid, uint64_t size) {
+ GpuMemDataSource::Trace([&](GpuMemDataSource::TraceContext ctx) {
+ auto packet = ctx.NewTracePacket();
+ packet->set_timestamp(systemTime());
+ auto* event = packet->set_gpu_mem_total_event();
+ event->set_gpu_id(gpuId);
+ event->set_pid(pid);
+ event->set_size(size);
+ });
+ });
+ // Flush the TraceContext. The last packet in the above loop will go
+ // missing without this flush.
+ GpuMemDataSource::Trace([](GpuMemDataSource::TraceContext ctx) { ctx.Flush(); });
+}
+
+} // namespace android
diff --git a/services/gpuservice/tracing/include/tracing/GpuMemTracer.h b/services/gpuservice/tracing/include/tracing/GpuMemTracer.h
new file mode 100644
index 0000000..40deb4c
--- /dev/null
+++ b/services/gpuservice/tracing/include/tracing/GpuMemTracer.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2020 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 <perfetto/tracing.h>
+
+#include <mutex>
+
+namespace android {
+
+class GpuMem;
+
+class GpuMemTracer {
+public:
+ class GpuMemDataSource : public perfetto::DataSource<GpuMemDataSource> {
+ virtual void OnSetup(const SetupArgs&) override{};
+ virtual void OnStart(const StartArgs&) override {
+ std::unique_lock<std::mutex> lock(GpuMemTracer::sTraceMutex);
+ sTraceStarted = true;
+ sCondition.notify_all();
+ }
+ virtual void OnStop(const StopArgs&) override{};
+ };
+
+ ~GpuMemTracer() = default;
+
+ // Sets up the perfetto tracing backend and data source.
+ void initialize(std::shared_ptr<GpuMem>);
+ // Registers the data source with the perfetto backend. Called as part of initialize()
+ // and should not be called manually outside of tests. Public to allow for substituting a
+ // perfetto::kInProcessBackend in tests.
+ void registerDataSource();
+
+ static constexpr char kGpuMemDataSource[] = "android.gpu.memory";
+ static std::condition_variable sCondition;
+ static std::mutex sTraceMutex;
+ static bool sTraceStarted;
+
+private:
+ void traceInitialCounters();
+ void threadLoop();
+
+ std::shared_ptr<GpuMem> mGpuMem;
+};
+
+} // namespace android
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 91803c8..49f9c54 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -3568,6 +3568,10 @@
sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(
const sp<IBinder>& windowHandleToken) const {
+ if (windowHandleToken == nullptr) {
+ return nullptr;
+ }
+
for (auto& it : mWindowHandlesByDisplay) {
const std::vector<sp<InputWindowHandle>> windowHandles = it.second;
for (const sp<InputWindowHandle>& windowHandle : windowHandles) {
@@ -3583,7 +3587,8 @@
for (auto& it : mWindowHandlesByDisplay) {
const std::vector<sp<InputWindowHandle>> windowHandles = it.second;
for (const sp<InputWindowHandle>& handle : windowHandles) {
- if (handle->getToken() == windowHandle->getToken()) {
+ if (handle->getId() == windowHandle->getId() &&
+ handle->getToken() == windowHandle->getToken()) {
if (windowHandle->getInfo()->displayId != it.first) {
ALOGE("Found window %s in display %" PRId32
", but it should belong to display %" PRId32,
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index f8d5351..0fa8787 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -335,7 +335,8 @@
virtual void getReaderConfiguration(InputReaderConfiguration* outConfig) = 0;
/* Gets a pointer controller associated with the specified cursor device (ie. a mouse). */
- virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) = 0;
+ virtual std::shared_ptr<PointerControllerInterface> obtainPointerController(
+ int32_t deviceId) = 0;
/* Notifies the input reader policy that some input devices have changed
* and provides information about all current input devices.
diff --git a/services/inputflinger/include/PointerControllerInterface.h b/services/inputflinger/include/PointerControllerInterface.h
index 194c665..bffff88 100644
--- a/services/inputflinger/include/PointerControllerInterface.h
+++ b/services/inputflinger/include/PointerControllerInterface.h
@@ -33,7 +33,7 @@
* The pointer controller is responsible for providing synchronization and for tracking
* display orientation changes if needed.
*/
-class PointerControllerInterface : public virtual RefBase {
+class PointerControllerInterface {
protected:
PointerControllerInterface() { }
virtual ~PointerControllerInterface() { }
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 657a134..d3441ac 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -390,8 +390,9 @@
}
}
-sp<PointerControllerInterface> InputReader::getPointerControllerLocked(int32_t deviceId) {
- sp<PointerControllerInterface> controller = mPointerController.promote();
+std::shared_ptr<PointerControllerInterface> InputReader::getPointerControllerLocked(
+ int32_t deviceId) {
+ std::shared_ptr<PointerControllerInterface> controller = mPointerController.lock();
if (controller == nullptr) {
controller = mPolicy->obtainPointerController(deviceId);
mPointerController = controller;
@@ -401,7 +402,7 @@
}
void InputReader::updatePointerDisplayLocked() {
- sp<PointerControllerInterface> controller = mPointerController.promote();
+ std::shared_ptr<PointerControllerInterface> controller = mPointerController.lock();
if (controller == nullptr) {
return;
}
@@ -424,7 +425,7 @@
}
void InputReader::fadePointerLocked() {
- sp<PointerControllerInterface> controller = mPointerController.promote();
+ std::shared_ptr<PointerControllerInterface> controller = mPointerController.lock();
if (controller != nullptr) {
controller->fade(PointerControllerInterface::TRANSITION_GRADUAL);
}
@@ -725,7 +726,8 @@
mReader->fadePointerLocked();
}
-sp<PointerControllerInterface> InputReader::ContextImpl::getPointerController(int32_t deviceId) {
+std::shared_ptr<PointerControllerInterface> InputReader::ContextImpl::getPointerController(
+ int32_t deviceId) {
// lock is already held by the input loop
return mReader->getPointerControllerLocked(deviceId);
}
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 693ec30..108b9c2 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -17,19 +17,20 @@
#ifndef _UI_INPUTREADER_INPUT_READER_H
#define _UI_INPUTREADER_INPUT_READER_H
+#include <PointerControllerInterface.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+
+#include <memory>
+#include <unordered_map>
+#include <vector>
+
#include "EventHub.h"
#include "InputListener.h"
#include "InputReaderBase.h"
#include "InputReaderContext.h"
#include "InputThread.h"
-#include <PointerControllerInterface.h>
-#include <utils/Condition.h>
-#include <utils/Mutex.h>
-
-#include <unordered_map>
-#include <vector>
-
namespace android {
class InputDevice;
@@ -104,7 +105,8 @@
virtual void disableVirtualKeysUntil(nsecs_t time) override;
virtual bool shouldDropVirtualKey(nsecs_t now, int32_t keyCode, int32_t scanCode) override;
virtual void fadePointer() override;
- virtual sp<PointerControllerInterface> getPointerController(int32_t deviceId) override;
+ virtual std::shared_ptr<PointerControllerInterface> getPointerController(
+ int32_t deviceId) override;
virtual void requestTimeoutAtTime(nsecs_t when) override;
virtual int32_t bumpGeneration() override;
virtual void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) override;
@@ -160,8 +162,8 @@
void dispatchExternalStylusState(const StylusState& state);
// The PointerController that is shared among all the input devices that need it.
- wp<PointerControllerInterface> mPointerController;
- sp<PointerControllerInterface> getPointerControllerLocked(int32_t deviceId);
+ std::weak_ptr<PointerControllerInterface> mPointerController;
+ std::shared_ptr<PointerControllerInterface> getPointerControllerLocked(int32_t deviceId);
void updatePointerDisplayLocked();
void fadePointerLocked();
diff --git a/services/inputflinger/reader/include/InputReaderContext.h b/services/inputflinger/reader/include/InputReaderContext.h
index 85701e4..ffb8d8c 100644
--- a/services/inputflinger/reader/include/InputReaderContext.h
+++ b/services/inputflinger/reader/include/InputReaderContext.h
@@ -46,7 +46,7 @@
virtual bool shouldDropVirtualKey(nsecs_t now, int32_t keyCode, int32_t scanCode) = 0;
virtual void fadePointer() = 0;
- virtual sp<PointerControllerInterface> getPointerController(int32_t deviceId) = 0;
+ virtual std::shared_ptr<PointerControllerInterface> getPointerController(int32_t deviceId) = 0;
virtual void requestTimeoutAtTime(nsecs_t when) = 0;
virtual int32_t bumpGeneration() = 0;
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.h b/services/inputflinger/reader/mapper/CursorInputMapper.h
index f65ac39..05bbb26 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.h
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.h
@@ -106,7 +106,7 @@
int32_t mOrientation;
- sp<PointerControllerInterface> mPointerController;
+ std::shared_ptr<PointerControllerInterface> mPointerController;
int32_t mButtonState;
nsecs_t mDownTime;
diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
index 030a846..b2e10d6 100644
--- a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
@@ -123,42 +123,15 @@
if (rawAxisInfo.valid) {
// Map axis.
AxisInfo axisInfo;
- bool explicitlyMapped = !getDeviceContext().mapAxis(abs, &axisInfo);
+ const bool explicitlyMapped = !getDeviceContext().mapAxis(abs, &axisInfo);
+
if (!explicitlyMapped) {
// Axis is not explicitly mapped, will choose a generic axis later.
axisInfo.mode = AxisInfo::MODE_NORMAL;
axisInfo.axis = -1;
}
- // Apply flat override.
- int32_t rawFlat =
- axisInfo.flatOverride < 0 ? rawAxisInfo.flat : axisInfo.flatOverride;
-
- // Calculate scaling factors and limits.
- Axis axis;
- if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
- float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
- float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
- axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, scale, 0.0f, highScale,
- 0.0f, 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
- rawAxisInfo.resolution * scale);
- } else if (isCenteredAxis(axisInfo.axis)) {
- float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
- float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
- axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, scale, offset, scale,
- offset, -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
- rawAxisInfo.resolution * scale);
- } else {
- float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
- axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, scale, 0.0f, scale,
- 0.0f, 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
- rawAxisInfo.resolution * scale);
- }
-
- // To eliminate noise while the joystick is at rest, filter out small variations
- // in axis values up front.
- axis.filter = axis.fuzz ? axis.fuzz : axis.flat * 0.25f;
-
+ Axis axis = createAxis(axisInfo, rawAxisInfo, explicitlyMapped);
mAxes.add(abs, axis);
}
}
@@ -198,6 +171,40 @@
}
}
+JoystickInputMapper::Axis JoystickInputMapper::createAxis(const AxisInfo& axisInfo,
+ const RawAbsoluteAxisInfo& rawAxisInfo,
+ bool explicitlyMapped) {
+ // Apply flat override.
+ int32_t rawFlat = axisInfo.flatOverride < 0 ? rawAxisInfo.flat : axisInfo.flatOverride;
+
+ // Calculate scaling factors and limits.
+ Axis axis;
+ if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
+ float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
+ float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
+ axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, scale, 0.0f, highScale, 0.0f, 0.0f,
+ 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
+ rawAxisInfo.resolution * scale);
+ } else if (isCenteredAxis(axisInfo.axis)) {
+ float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
+ float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
+ axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, scale, offset, scale, offset,
+ -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
+ rawAxisInfo.resolution * scale);
+ } else {
+ float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
+ axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, scale, 0.0f, scale, 0.0f, 0.0f,
+ 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
+ rawAxisInfo.resolution * scale);
+ }
+
+ // To eliminate noise while the joystick is at rest, filter out small variations
+ // in axis values up front.
+ axis.filter = axis.fuzz ? axis.fuzz : axis.flat * 0.25f;
+
+ return axis;
+}
+
bool JoystickInputMapper::haveAxis(int32_t axisId) {
size_t numAxes = mAxes.size();
for (size_t i = 0; i < numAxes; i++) {
diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.h b/services/inputflinger/reader/mapper/JoystickInputMapper.h
index 823a096..29d5652 100644
--- a/services/inputflinger/reader/mapper/JoystickInputMapper.h
+++ b/services/inputflinger/reader/mapper/JoystickInputMapper.h
@@ -86,6 +86,9 @@
}
};
+ static Axis createAxis(const AxisInfo& AxisInfo, const RawAbsoluteAxisInfo& rawAxisInfo,
+ bool explicitlyMapped);
+
// Axes indexed by raw ABS_* axis index.
KeyedVector<int32_t, Axis> mAxes;
diff --git a/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h b/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
index 2a3e263..a86443d 100644
--- a/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
+++ b/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
@@ -17,12 +17,13 @@
#ifndef _UI_INPUTREADER_TOUCH_CURSOR_INPUT_MAPPER_COMMON_H
#define _UI_INPUTREADER_TOUCH_CURSOR_INPUT_MAPPER_COMMON_H
+#include <input/DisplayViewport.h>
+#include <stdint.h>
+
#include "EventHub.h"
#include "InputListener.h"
#include "InputReaderContext.h"
-#include <stdint.h>
-
namespace android {
// --- Static Definitions ---
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 99a572a..10b6a18 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -765,7 +765,7 @@
mPointerController = getContext()->getPointerController(getDeviceId());
}
} else {
- mPointerController.clear();
+ mPointerController.reset();
}
if (viewportChanged || deviceModeChanged) {
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index 58bfc5c..7f811a0 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -376,7 +376,7 @@
nsecs_t mDownTime;
// The pointer controller, or null if the device is not a pointer.
- sp<PointerControllerInterface> mPointerController;
+ std::shared_ptr<PointerControllerInterface> mPointerController;
std::vector<VirtualKey> mVirtualKeys;
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 1a133dc..ea4d885 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -2368,7 +2368,7 @@
mWindow =
new FakeWindowHandle(mApplication, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
mWindow->setFrame(Rect(0, 0, 30, 30));
- mWindow->setDispatchingTimeout(10ms);
+ mWindow->setDispatchingTimeout(30ms);
mWindow->setFocus(true);
// Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
// window.
@@ -2760,7 +2760,7 @@
mFocusedWindow =
new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT);
- mFocusedWindow->setDispatchingTimeout(10ms);
+ mFocusedWindow->setDispatchingTimeout(30ms);
mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
InputWindowInfo::FLAG_SPLIT_TOUCH);
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index c457a15..18bd3d0 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -27,12 +27,13 @@
#include <TestInputListener.h>
#include <TouchInputMapper.h>
#include <UinputDevice.h>
-
#include <android-base/thread_annotations.h>
#include <gtest/gtest.h>
#include <inttypes.h>
#include <math.h>
+#include <memory>
+
namespace android {
using std::chrono_literals::operator""ms;
@@ -76,15 +77,14 @@
int32_t mButtonState;
int32_t mDisplayId;
-protected:
- virtual ~FakePointerController() { }
-
public:
FakePointerController() :
mHaveBounds(false), mMinX(0), mMinY(0), mMaxX(0), mMaxY(0), mX(0), mY(0),
mButtonState(0), mDisplayId(ADISPLAY_ID_DEFAULT) {
}
+ virtual ~FakePointerController() {}
+
void setBounds(float minX, float minY, float maxX, float maxY) {
mHaveBounds = true;
mMinX = minX;
@@ -176,7 +176,7 @@
std::condition_variable mDevicesChangedCondition;
InputReaderConfiguration mConfig;
- KeyedVector<int32_t, sp<FakePointerController> > mPointerControllers;
+ std::unordered_map<int32_t, std::shared_ptr<FakePointerController>> mPointerControllers;
std::vector<InputDeviceInfo> mInputDevices GUARDED_BY(mLock);
bool mInputDevicesChanged GUARDED_BY(mLock){false};
std::vector<DisplayViewport> mViewports;
@@ -256,8 +256,8 @@
void removeDisabledDevice(int32_t deviceId) { mConfig.disabledDevices.erase(deviceId); }
- void setPointerController(int32_t deviceId, const sp<FakePointerController>& controller) {
- mPointerControllers.add(deviceId, controller);
+ void setPointerController(int32_t deviceId, std::shared_ptr<FakePointerController> controller) {
+ mPointerControllers.insert_or_assign(deviceId, std::move(controller));
}
const InputReaderConfiguration* getReaderConfiguration() const {
@@ -318,8 +318,8 @@
*outConfig = mConfig;
}
- virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) {
- return mPointerControllers.valueFor(deviceId);
+ virtual std::shared_ptr<PointerControllerInterface> obtainPointerController(int32_t deviceId) {
+ return mPointerControllers[deviceId];
}
virtual void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) {
@@ -847,7 +847,7 @@
bool mUpdateGlobalMetaStateWasCalled;
int32_t mGeneration;
int32_t mNextId;
- wp<PointerControllerInterface> mPointerController;
+ std::weak_ptr<PointerControllerInterface> mPointerController;
public:
FakeInputReaderContext(std::shared_ptr<EventHubInterface> eventHub,
@@ -876,7 +876,7 @@
}
void updatePointerDisplay() {
- sp<PointerControllerInterface> controller = mPointerController.promote();
+ std::shared_ptr<PointerControllerInterface> controller = mPointerController.lock();
if (controller != nullptr) {
InputReaderConfiguration config;
mPolicy->getReaderConfiguration(&config);
@@ -913,8 +913,8 @@
virtual bool shouldDropVirtualKey(nsecs_t, int32_t, int32_t) { return false; }
- virtual sp<PointerControllerInterface> getPointerController(int32_t deviceId) {
- sp<PointerControllerInterface> controller = mPointerController.promote();
+ virtual std::shared_ptr<PointerControllerInterface> getPointerController(int32_t deviceId) {
+ std::shared_ptr<PointerControllerInterface> controller = mPointerController.lock();
if (controller == nullptr) {
controller = mPolicy->obtainPointerController(deviceId);
mPointerController = controller;
@@ -2348,9 +2348,9 @@
ASSERT_NEAR(distance, coords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE), EPSILON);
}
- static void assertPosition(const sp<FakePointerController>& controller, float x, float y) {
+ static void assertPosition(const FakePointerController& controller, float x, float y) {
float actualX, actualY;
- controller->getPosition(&actualX, &actualY);
+ controller.getPosition(&actualX, &actualY);
ASSERT_NEAR(x, actualX, 1);
ASSERT_NEAR(y, actualY, 1);
}
@@ -3021,12 +3021,12 @@
protected:
static const int32_t TRACKBALL_MOVEMENT_THRESHOLD;
- sp<FakePointerController> mFakePointerController;
+ std::shared_ptr<FakePointerController> mFakePointerController;
virtual void SetUp() override {
InputMapperTest::SetUp();
- mFakePointerController = new FakePointerController();
+ mFakePointerController = std::make_shared<FakePointerController>();
mFakePolicy->setPointerController(mDevice->getId(), mFakePointerController);
}
@@ -3682,7 +3682,7 @@
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
110.0f, 220.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
- ASSERT_NO_FATAL_FAILURE(assertPosition(mFakePointerController, 110.0f, 220.0f));
+ ASSERT_NO_FATAL_FAILURE(assertPosition(*mFakePointerController, 110.0f, 220.0f));
}
TEST_F(CursorInputMapperTest, Process_PointerCapture) {
@@ -3710,7 +3710,7 @@
ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
10.0f, 20.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
- ASSERT_NO_FATAL_FAILURE(assertPosition(mFakePointerController, 100.0f, 200.0f));
+ ASSERT_NO_FATAL_FAILURE(assertPosition(*mFakePointerController, 100.0f, 200.0f));
// Button press.
process(mapper, ARBITRARY_TIME, EV_KEY, BTN_MOUSE, 1);
@@ -3749,7 +3749,7 @@
ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
30.0f, 40.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
- ASSERT_NO_FATAL_FAILURE(assertPosition(mFakePointerController, 100.0f, 200.0f));
+ ASSERT_NO_FATAL_FAILURE(assertPosition(*mFakePointerController, 100.0f, 200.0f));
// Disable pointer capture and check that the device generation got bumped
// and events are generated the usual way.
@@ -3770,7 +3770,7 @@
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
110.0f, 220.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
- ASSERT_NO_FATAL_FAILURE(assertPosition(mFakePointerController, 110.0f, 220.0f));
+ ASSERT_NO_FATAL_FAILURE(assertPosition(*mFakePointerController, 110.0f, 220.0f));
}
TEST_F(CursorInputMapperTest, Process_ShouldHandleDisplayId) {
@@ -3798,7 +3798,7 @@
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
110.0f, 220.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
- ASSERT_NO_FATAL_FAILURE(assertPosition(mFakePointerController, 110.0f, 220.0f));
+ ASSERT_NO_FATAL_FAILURE(assertPosition(*mFakePointerController, 110.0f, 220.0f));
ASSERT_EQ(SECOND_DISPLAY_ID, args.displayId);
}
@@ -6806,7 +6806,8 @@
TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShouldHandleDisplayId) {
// Setup for second display.
- sp<FakePointerController> fakePointerController = new FakePointerController();
+ std::shared_ptr<FakePointerController> fakePointerController =
+ std::make_shared<FakePointerController>();
fakePointerController->setBounds(0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1);
fakePointerController->setPosition(100, 200);
fakePointerController->setButtonState(0);
@@ -6866,7 +6867,8 @@
device2->reset(ARBITRARY_TIME);
// Setup PointerController.
- sp<FakePointerController> fakePointerController = new FakePointerController();
+ std::shared_ptr<FakePointerController> fakePointerController =
+ std::make_shared<FakePointerController>();
mFakePolicy->setPointerController(mDevice->getId(), fakePointerController);
mFakePolicy->setPointerController(SECOND_DEVICE_ID, fakePointerController);
diff --git a/services/powermanager/PowerHalWrapper.cpp b/services/powermanager/PowerHalWrapper.cpp
index 5f4bfed..95f8623 100644
--- a/services/powermanager/PowerHalWrapper.cpp
+++ b/services/powermanager/PowerHalWrapper.cpp
@@ -117,8 +117,7 @@
bool isSupported = false;
auto isSupportedRet = mHandle->isBoostSupported(boost, &isSupported);
if (!isSupportedRet.isOk()) {
- ALOGV("Skipped setBoost %s because Power HAL is not available to check "
- "support",
+ ALOGV("Skipped setBoost %s because Power HAL is not available to check support",
toString(boost).c_str());
return HalResult::FAILED;
}
@@ -149,8 +148,7 @@
bool isSupported = false;
auto isSupportedRet = mHandle->isModeSupported(mode, &isSupported);
if (!isSupportedRet.isOk()) {
- ALOGV("Skipped setMode %s because Power HAL is not available to check "
- "support",
+ ALOGV("Skipped setMode %s because Power HAL is not available to check support",
toString(mode).c_str());
return HalResult::FAILED;
}
diff --git a/services/powermanager/benchmarks/Android.bp b/services/powermanager/benchmarks/Android.bp
new file mode 100644
index 0000000..5975269
--- /dev/null
+++ b/services/powermanager/benchmarks/Android.bp
@@ -0,0 +1,39 @@
+// Copyright (C) 2020 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.
+
+cc_benchmark {
+ name: "libpowermanager_benchmarks",
+ srcs: [
+ "main.cpp",
+ "PowerHalAidlBenchmarks.cpp",
+ "PowerHalControllerBenchmarks.cpp",
+ "PowerHalHidlBenchmarks.cpp",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "libhidlbase",
+ "liblog",
+ "libpowermanager",
+ "libutils",
+ "android.hardware.power@1.0",
+ "android.hardware.power@1.1",
+ "android.hardware.power-cpp",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+}
diff --git a/services/powermanager/benchmarks/AndroidTest.xml b/services/powermanager/benchmarks/AndroidTest.xml
new file mode 100644
index 0000000..40f4872
--- /dev/null
+++ b/services/powermanager/benchmarks/AndroidTest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+<configuration description="Config for libpowermanager benchmarks">
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="libpowermanager_benchmarks->/data/benchmarktest/benchmark" />
+ </target_preparer>
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-metric-instrumentation" />
+ <test class="com.android.tradefed.testtype.GoogleBenchmarkTest" >
+ <option name="native-benchmark-device-path" value="/data/benchmarktest" />
+ <option name="benchmark-module-name" value="benchmark" />
+ </test>
+</configuration>
diff --git a/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp b/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp
new file mode 100644
index 0000000..a6dad51
--- /dev/null
+++ b/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#define LOG_TAG "PowerHalAidlBenchmarks"
+
+#include <android/hardware/power/Boost.h>
+#include <android/hardware/power/IPower.h>
+#include <android/hardware/power/Mode.h>
+
+#include <benchmark/benchmark.h>
+
+#include <binder/IServiceManager.h>
+
+using android::hardware::power::Boost;
+using android::hardware::power::IPower;
+using android::hardware::power::Mode;
+
+using namespace android;
+
+template <class R, class... Args0, class... Args1>
+static void runBenchmark(benchmark::State& state, R (IPower::*fn)(Args0...), Args1&&... args1) {
+ sp<IPower> hal = waitForVintfService<IPower>();
+
+ if (hal == nullptr) {
+ ALOGI("Power HAL AIDL not available, skipping test...");
+ return;
+ }
+
+ while (state.KeepRunning()) {
+ (*hal.*fn)(std::forward<Args1>(args1)...);
+ }
+}
+
+static void BM_PowerHalAidlBenchmarks_isBoostSupported(benchmark::State& state) {
+ bool isSupported;
+ runBenchmark(state, &IPower::isBoostSupported, Boost::INTERACTION, &isSupported);
+}
+
+static void BM_PowerHalAidlBenchmarks_isModeSupported(benchmark::State& state) {
+ bool isSupported;
+ runBenchmark(state, &IPower::isModeSupported, Mode::INTERACTIVE, &isSupported);
+}
+
+static void BM_PowerHalAidlBenchmarks_setBoost(benchmark::State& state) {
+ runBenchmark(state, &IPower::setBoost, Boost::INTERACTION, 0);
+}
+
+static void BM_PowerHalAidlBenchmarks_setMode(benchmark::State& state) {
+ runBenchmark(state, &IPower::setMode, Mode::INTERACTIVE, false);
+}
+
+BENCHMARK(BM_PowerHalAidlBenchmarks_isBoostSupported);
+BENCHMARK(BM_PowerHalAidlBenchmarks_isModeSupported);
+BENCHMARK(BM_PowerHalAidlBenchmarks_setBoost);
+BENCHMARK(BM_PowerHalAidlBenchmarks_setMode);
diff --git a/services/powermanager/benchmarks/PowerHalControllerBenchmarks.cpp b/services/powermanager/benchmarks/PowerHalControllerBenchmarks.cpp
new file mode 100644
index 0000000..a3a1f4e
--- /dev/null
+++ b/services/powermanager/benchmarks/PowerHalControllerBenchmarks.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#define LOG_TAG "PowerHalControllerBenchmarks"
+
+#include <android/hardware/power/Boost.h>
+#include <android/hardware/power/Mode.h>
+
+#include <benchmark/benchmark.h>
+
+#include <powermanager/PowerHalController.h>
+
+using android::hardware::power::Boost;
+using android::hardware::power::Mode;
+using android::power::PowerHalController;
+
+using namespace android;
+
+static void BM_PowerHalControllerBenchmarks_init(benchmark::State& state) {
+ while (state.KeepRunning()) {
+ PowerHalController controller;
+ controller.init();
+ }
+}
+
+static void BM_PowerHalControllerBenchmarks_initCached(benchmark::State& state) {
+ PowerHalController controller;
+ // First connection out of test.
+ controller.init();
+
+ while (state.KeepRunning()) {
+ controller.init();
+ }
+}
+
+static void BM_PowerHalControllerBenchmarks_setBoost(benchmark::State& state) {
+ while (state.KeepRunning()) {
+ PowerHalController controller;
+ controller.setBoost(Boost::INTERACTION, 0);
+ }
+}
+
+static void BM_PowerHalControllerBenchmarks_setBoostCached(benchmark::State& state) {
+ PowerHalController controller;
+ // First call out of test, to cache supported boost.
+ controller.setBoost(Boost::INTERACTION, 0);
+
+ while (state.KeepRunning()) {
+ controller.setBoost(Boost::INTERACTION, 0);
+ }
+}
+
+static void BM_PowerHalControllerBenchmarks_setMode(benchmark::State& state) {
+ while (state.KeepRunning()) {
+ PowerHalController controller;
+ controller.setMode(Mode::INTERACTIVE, false);
+ }
+}
+
+static void BM_PowerHalControllerBenchmarks_setModeCached(benchmark::State& state) {
+ PowerHalController controller;
+ // First call out of test, to cache supported mode.
+ controller.setMode(Mode::INTERACTIVE, false);
+
+ while (state.KeepRunning()) {
+ controller.setMode(Mode::INTERACTIVE, false);
+ }
+}
+
+BENCHMARK(BM_PowerHalControllerBenchmarks_init);
+BENCHMARK(BM_PowerHalControllerBenchmarks_initCached);
+BENCHMARK(BM_PowerHalControllerBenchmarks_setBoost);
+BENCHMARK(BM_PowerHalControllerBenchmarks_setBoostCached);
+BENCHMARK(BM_PowerHalControllerBenchmarks_setMode);
+BENCHMARK(BM_PowerHalControllerBenchmarks_setModeCached);
diff --git a/services/powermanager/benchmarks/PowerHalHidlBenchmarks.cpp b/services/powermanager/benchmarks/PowerHalHidlBenchmarks.cpp
new file mode 100644
index 0000000..5542ac4
--- /dev/null
+++ b/services/powermanager/benchmarks/PowerHalHidlBenchmarks.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#define LOG_TAG "PowerHalHidlBenchmarks"
+
+#include <android/hardware/power/1.1/IPower.h>
+#include <android/hardware/power/Boost.h>
+#include <android/hardware/power/IPower.h>
+#include <android/hardware/power/Mode.h>
+
+#include <benchmark/benchmark.h>
+
+#include <hardware/power.h>
+#include <hardware_legacy/power.h>
+
+using android::hardware::power::Boost;
+using android::hardware::power::Mode;
+using android::hardware::power::V1_0::Feature;
+using android::hardware::power::V1_0::PowerHint;
+using IPower1_0 = android::hardware::power::V1_0::IPower;
+using IPower1_1 = android::hardware::power::V1_1::IPower;
+
+using namespace android;
+
+template <class R, class I, class... Args0, class... Args1>
+static void runBenchmark(benchmark::State& state, R (I::*fn)(Args0...), Args1&&... args1) {
+ sp<I> hal = I::getService();
+
+ if (hal == nullptr) {
+ ALOGI("Power HAL HIDL not available, skipping test...");
+ return;
+ }
+
+ while (state.KeepRunning()) {
+ (*hal.*fn)(std::forward<Args1>(args1)...);
+ }
+}
+
+static void BM_PowerHalHidlBenchmarks_setFeature(benchmark::State& state) {
+ runBenchmark(state, &IPower1_0::setFeature, Feature::POWER_FEATURE_DOUBLE_TAP_TO_WAKE, false);
+}
+
+static void BM_PowerHalHidlBenchmarks_setInteractive(benchmark::State& state) {
+ runBenchmark(state, &IPower1_0::setInteractive, false);
+}
+
+static void BM_PowerHalHidlBenchmarks_powerHint(benchmark::State& state) {
+ runBenchmark(state, &IPower1_0::powerHint, PowerHint::INTERACTION, 0);
+}
+
+static void BM_PowerHalHidlBenchmarks_powerHintAsync(benchmark::State& state) {
+ runBenchmark(state, &IPower1_1::powerHintAsync, PowerHint::INTERACTION, 0);
+}
+
+BENCHMARK(BM_PowerHalHidlBenchmarks_setFeature);
+BENCHMARK(BM_PowerHalHidlBenchmarks_setInteractive);
+BENCHMARK(BM_PowerHalHidlBenchmarks_powerHint);
+BENCHMARK(BM_PowerHalHidlBenchmarks_powerHintAsync);
diff --git a/services/powermanager/benchmarks/main.cpp b/services/powermanager/benchmarks/main.cpp
new file mode 100644
index 0000000..15c57bf
--- /dev/null
+++ b/services/powermanager/benchmarks/main.cpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2020 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 <benchmark/benchmark.h>
+
+BENCHMARK_MAIN();
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index a790d0b..804a3c3 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -145,6 +145,7 @@
"DisplayHardware/HWComposer.cpp",
"DisplayHardware/PowerAdvisor.cpp",
"DisplayHardware/VirtualDisplaySurface.cpp",
+ "DisplayRenderArea.cpp",
"Effects/Daltonizer.cpp",
"EventLog/EventLog.cpp",
"FrameTracer/FrameTracer.cpp",
@@ -152,6 +153,7 @@
"Layer.cpp",
"LayerProtoHelper.cpp",
"LayerRejecter.cpp",
+ "LayerRenderArea.cpp",
"LayerVector.cpp",
"MonitoredProducer.cpp",
"NativeWindowSurface.cpp",
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 07be791..5f95182 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -208,8 +208,12 @@
}
bool BufferQueueLayer::latchSidebandStream(bool& recomputeVisibleRegions) {
+ // We need to update the sideband stream if the layer has both a buffer and a sideband stream.
+ const bool updateSidebandStream = hasFrameUpdate() && mSidebandStream.get();
+
bool sidebandStreamChanged = true;
- if (mSidebandStreamChanged.compare_exchange_strong(sidebandStreamChanged, false)) {
+ if (mSidebandStreamChanged.compare_exchange_strong(sidebandStreamChanged, false) ||
+ updateSidebandStream) {
// mSidebandStreamChanged was changed to false
mSidebandStream = mConsumer->getSidebandStream();
auto* layerCompositionState = editCompositionState();
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 81b3ccf..576488c 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -40,7 +40,6 @@
#include "DisplayHardware/DisplayIdentification.h"
#include "DisplayHardware/Hal.h"
#include "DisplayHardware/PowerAdvisor.h"
-#include "RenderArea.h"
#include "Scheduler/HwcStrongTypes.h"
namespace android {
@@ -246,123 +245,4 @@
bool isPrimary{false};
};
-class DisplayRenderArea : public RenderArea {
-public:
- static std::unique_ptr<RenderArea> create(wp<const DisplayDevice> displayWeak,
- const Rect& sourceCrop, ui::Size reqSize,
- ui::Dataspace reqDataSpace, RotationFlags rotation,
- bool allowSecureLayers = true) {
- if (auto display = displayWeak.promote()) {
- // Using new to access a private constructor.
- return std::unique_ptr<DisplayRenderArea>(
- new DisplayRenderArea(std::move(display), sourceCrop, reqSize, reqDataSpace,
- rotation, allowSecureLayers));
- }
- return nullptr;
- }
-
- const ui::Transform& getTransform() const override { return mTransform; }
- Rect getBounds() const override { return mDisplay->getBounds(); }
- int getHeight() const override { return mDisplay->getHeight(); }
- int getWidth() const override { return mDisplay->getWidth(); }
- bool isSecure() const override { return mAllowSecureLayers && mDisplay->isSecure(); }
- sp<const DisplayDevice> getDisplayDevice() const override { return mDisplay; }
-
- bool needsFiltering() const override {
- // check if the projection from the logical render area
- // to the physical render area requires filtering
- const Rect& sourceCrop = getSourceCrop();
- int width = sourceCrop.width();
- int height = sourceCrop.height();
- if (getRotationFlags() & ui::Transform::ROT_90) {
- std::swap(width, height);
- }
- return width != getReqWidth() || height != getReqHeight();
- }
-
- Rect getSourceCrop() const override {
- // use the projected display viewport by default.
- if (mSourceCrop.isEmpty()) {
- return mDisplay->getSourceClip();
- }
-
- // If there is a source crop provided then it is assumed that the device
- // was in portrait orientation. This may not logically be true, so
- // correct for the orientation error by undoing the rotation
-
- ui::Rotation logicalOrientation = mDisplay->getOrientation();
- if (logicalOrientation == ui::Rotation::Rotation90) {
- logicalOrientation = ui::Rotation::Rotation270;
- } else if (logicalOrientation == ui::Rotation::Rotation270) {
- logicalOrientation = ui::Rotation::Rotation90;
- }
-
- const auto flags = ui::Transform::toRotationFlags(logicalOrientation);
- int width = mDisplay->getSourceClip().getWidth();
- int height = mDisplay->getSourceClip().getHeight();
- ui::Transform rotation;
- rotation.set(flags, width, height);
- return rotation.transform(mSourceCrop);
- }
-
-private:
- DisplayRenderArea(sp<const DisplayDevice> display, const Rect& sourceCrop, ui::Size reqSize,
- ui::Dataspace reqDataSpace, RotationFlags rotation, bool allowSecureLayers)
- : RenderArea(reqSize, CaptureFill::OPAQUE, reqDataSpace, display->getViewport(),
- applyDeviceOrientation(rotation, display)),
- mDisplay(std::move(display)),
- mSourceCrop(sourceCrop),
- mAllowSecureLayers(allowSecureLayers) {}
-
- static RotationFlags applyDeviceOrientation(RotationFlags orientationFlag,
- const sp<const DisplayDevice>& device) {
- uint32_t inverseRotate90 = 0;
- uint32_t inverseReflect = 0;
-
- // Reverse the logical orientation.
- ui::Rotation logicalOrientation = device->getOrientation();
- if (logicalOrientation == ui::Rotation::Rotation90) {
- logicalOrientation = ui::Rotation::Rotation270;
- } else if (logicalOrientation == ui::Rotation::Rotation270) {
- logicalOrientation = ui::Rotation::Rotation90;
- }
-
- const ui::Rotation orientation = device->getPhysicalOrientation() + logicalOrientation;
-
- switch (orientation) {
- case ui::ROTATION_0:
- return orientationFlag;
-
- case ui::ROTATION_90:
- inverseRotate90 = ui::Transform::ROT_90;
- inverseReflect = ui::Transform::ROT_180;
- break;
-
- case ui::ROTATION_180:
- inverseReflect = ui::Transform::ROT_180;
- break;
-
- case ui::ROTATION_270:
- inverseRotate90 = ui::Transform::ROT_90;
- break;
- }
-
- const uint32_t rotate90 = orientationFlag & ui::Transform::ROT_90;
- uint32_t reflect = orientationFlag & ui::Transform::ROT_180;
-
- // Apply reflection for double rotation.
- if (rotate90 & inverseRotate90) {
- reflect = ~reflect & ui::Transform::ROT_180;
- }
-
- return static_cast<RotationFlags>((rotate90 ^ inverseRotate90) |
- (reflect ^ inverseReflect));
- }
-
- const sp<const DisplayDevice> mDisplay;
- const Rect mSourceCrop;
- const bool mAllowSecureLayers;
- const ui::Transform mTransform = ui::Transform();
-};
-
} // namespace android
diff --git a/services/surfaceflinger/DisplayRenderArea.cpp b/services/surfaceflinger/DisplayRenderArea.cpp
new file mode 100644
index 0000000..7cd283d
--- /dev/null
+++ b/services/surfaceflinger/DisplayRenderArea.cpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2020 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 "DisplayRenderArea.h"
+#include "DisplayDevice.h"
+
+namespace android {
+namespace {
+
+RenderArea::RotationFlags applyDeviceOrientation(RenderArea::RotationFlags rotation,
+ const DisplayDevice& display) {
+ uint32_t inverseRotate90 = 0;
+ uint32_t inverseReflect = 0;
+
+ // Reverse the logical orientation.
+ ui::Rotation logicalOrientation = display.getOrientation();
+ if (logicalOrientation == ui::Rotation::Rotation90) {
+ logicalOrientation = ui::Rotation::Rotation270;
+ } else if (logicalOrientation == ui::Rotation::Rotation270) {
+ logicalOrientation = ui::Rotation::Rotation90;
+ }
+
+ const ui::Rotation orientation = display.getPhysicalOrientation() + logicalOrientation;
+
+ switch (orientation) {
+ case ui::ROTATION_0:
+ return rotation;
+
+ case ui::ROTATION_90:
+ inverseRotate90 = ui::Transform::ROT_90;
+ inverseReflect = ui::Transform::ROT_180;
+ break;
+
+ case ui::ROTATION_180:
+ inverseReflect = ui::Transform::ROT_180;
+ break;
+
+ case ui::ROTATION_270:
+ inverseRotate90 = ui::Transform::ROT_90;
+ break;
+ }
+
+ const uint32_t rotate90 = rotation & ui::Transform::ROT_90;
+ uint32_t reflect = rotation & ui::Transform::ROT_180;
+
+ // Apply reflection for double rotation.
+ if (rotate90 & inverseRotate90) {
+ reflect = ~reflect & ui::Transform::ROT_180;
+ }
+
+ return static_cast<RenderArea::RotationFlags>((rotate90 ^ inverseRotate90) |
+ (reflect ^ inverseReflect));
+}
+
+} // namespace
+
+std::unique_ptr<RenderArea> DisplayRenderArea::create(wp<const DisplayDevice> displayWeak,
+ const Rect& sourceCrop, ui::Size reqSize,
+ ui::Dataspace reqDataSpace,
+ RotationFlags rotation,
+ bool allowSecureLayers) {
+ if (auto display = displayWeak.promote()) {
+ // Using new to access a private constructor.
+ return std::unique_ptr<DisplayRenderArea>(
+ new DisplayRenderArea(std::move(display), sourceCrop, reqSize, reqDataSpace,
+ rotation, allowSecureLayers));
+ }
+ return nullptr;
+}
+
+DisplayRenderArea::DisplayRenderArea(sp<const DisplayDevice> display, const Rect& sourceCrop,
+ ui::Size reqSize, ui::Dataspace reqDataSpace,
+ RotationFlags rotation, bool allowSecureLayers)
+ : RenderArea(reqSize, CaptureFill::OPAQUE, reqDataSpace, display->getViewport(),
+ applyDeviceOrientation(rotation, *display)),
+ mDisplay(std::move(display)),
+ mSourceCrop(sourceCrop),
+ mAllowSecureLayers(allowSecureLayers) {}
+
+const ui::Transform& DisplayRenderArea::getTransform() const {
+ return mTransform;
+}
+
+Rect DisplayRenderArea::getBounds() const {
+ return mDisplay->getBounds();
+}
+
+int DisplayRenderArea::getHeight() const {
+ return mDisplay->getHeight();
+}
+
+int DisplayRenderArea::getWidth() const {
+ return mDisplay->getWidth();
+}
+
+bool DisplayRenderArea::isSecure() const {
+ return mAllowSecureLayers && mDisplay->isSecure();
+}
+
+sp<const DisplayDevice> DisplayRenderArea::getDisplayDevice() const {
+ return mDisplay;
+}
+
+bool DisplayRenderArea::needsFiltering() const {
+ // check if the projection from the logical render area
+ // to the physical render area requires filtering
+ const Rect& sourceCrop = getSourceCrop();
+ int width = sourceCrop.width();
+ int height = sourceCrop.height();
+ if (getRotationFlags() & ui::Transform::ROT_90) {
+ std::swap(width, height);
+ }
+ return width != getReqWidth() || height != getReqHeight();
+}
+
+Rect DisplayRenderArea::getSourceCrop() const {
+ // use the projected display viewport by default.
+ if (mSourceCrop.isEmpty()) {
+ return mDisplay->getSourceClip();
+ }
+
+ // If there is a source crop provided then it is assumed that the device
+ // was in portrait orientation. This may not logically be true, so
+ // correct for the orientation error by undoing the rotation
+
+ ui::Rotation logicalOrientation = mDisplay->getOrientation();
+ if (logicalOrientation == ui::Rotation::Rotation90) {
+ logicalOrientation = ui::Rotation::Rotation270;
+ } else if (logicalOrientation == ui::Rotation::Rotation270) {
+ logicalOrientation = ui::Rotation::Rotation90;
+ }
+
+ const auto flags = ui::Transform::toRotationFlags(logicalOrientation);
+ int width = mDisplay->getSourceClip().getWidth();
+ int height = mDisplay->getSourceClip().getHeight();
+ ui::Transform rotation;
+ rotation.set(flags, width, height);
+ return rotation.transform(mSourceCrop);
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/DisplayRenderArea.h b/services/surfaceflinger/DisplayRenderArea.h
new file mode 100644
index 0000000..340efb5
--- /dev/null
+++ b/services/surfaceflinger/DisplayRenderArea.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2020 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 <ui/GraphicTypes.h>
+#include <ui/Transform.h>
+
+#include "RenderArea.h"
+
+namespace android {
+
+class DisplayDevice;
+
+class DisplayRenderArea : public RenderArea {
+public:
+ static std::unique_ptr<RenderArea> create(wp<const DisplayDevice>, const Rect& sourceCrop,
+ ui::Size reqSize, ui::Dataspace,
+ RotationFlags rotation,
+ bool allowSecureLayers = true);
+
+ const ui::Transform& getTransform() const override;
+ Rect getBounds() const override;
+ int getHeight() const override;
+ int getWidth() const override;
+ bool isSecure() const override;
+ sp<const DisplayDevice> getDisplayDevice() const override;
+ bool needsFiltering() const override;
+ Rect getSourceCrop() const override;
+
+private:
+ DisplayRenderArea(sp<const DisplayDevice>, const Rect& sourceCrop, ui::Size reqSize,
+ ui::Dataspace, RotationFlags rotation, bool allowSecureLayers = true);
+
+ const sp<const DisplayDevice> mDisplay;
+ const Rect mSourceCrop;
+ const bool mAllowSecureLayers;
+ const ui::Transform mTransform;
+};
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index f36b67d..a34af17 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1325,6 +1325,10 @@
return Layer::PRIORITY_UNSET;
}
+bool Layer::isLayerFocusedBasedOnPriority(int32_t priority) {
+ return priority == PRIORITY_FOCUSED_WITH_MODE || priority == PRIORITY_FOCUSED_WITHOUT_MODE;
+};
+
uint32_t Layer::getLayerStack() const {
auto p = mDrawingParent.promote();
if (p == nullptr) {
@@ -1558,7 +1562,7 @@
result.append("-------------------------------");
result.append("-------------------------------");
result.append("-------------------------------");
- result.append("---------\n");
+ result.append("-------------------\n");
result.append(" Layer name\n");
result.append(" Z | ");
result.append(" Window Type | ");
@@ -1566,12 +1570,12 @@
result.append(" Transform | ");
result.append(" Disp Frame (LTRB) | ");
result.append(" Source Crop (LTRB) | ");
- result.append(" Frame Rate (Explicit)\n");
+ result.append(" Frame Rate (Explicit) [Focused]\n");
result.append("-------------------------------");
result.append("-------------------------------");
result.append("-------------------------------");
result.append("-------------------------------");
- result.append("---------\n");
+ result.append("-------------------\n");
}
std::string Layer::frameRateCompatibilityString(Layer::FrameRateCompatibility compatibility) {
@@ -1622,17 +1626,20 @@
crop.bottom);
if (layerState.frameRate.rate != 0 ||
layerState.frameRate.type != FrameRateCompatibility::Default) {
- StringAppendF(&result, "% 6.2ffps %15s\n", layerState.frameRate.rate,
+ StringAppendF(&result, "% 6.2ffps %15s", layerState.frameRate.rate,
frameRateCompatibilityString(layerState.frameRate.type).c_str());
} else {
- StringAppendF(&result, "\n");
+ StringAppendF(&result, " ");
}
+ const auto focused = isLayerFocusedBasedOnPriority(getFrameRateSelectionPriority());
+ StringAppendF(&result, " [%s]\n", focused ? "*" : " ");
+
result.append("- - - - - - - - - - - - - - - - ");
result.append("- - - - - - - - - - - - - - - - ");
result.append("- - - - - - - - - - - - - - - - ");
result.append("- - - - - - - - - - - - - - - - ");
- result.append("- - -\n");
+ result.append("- - - - - - - -\n");
}
void Layer::dumpFrameStats(std::string& result) const {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 068424b..2c90c92 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -94,7 +94,16 @@
class Layer : public virtual RefBase, compositionengine::LayerFE {
static std::atomic<int32_t> sSequence;
+ // The following constants represent priority of the window. SF uses this information when
+ // deciding which window has a priority when deciding about the refresh rate of the screen.
+ // Priority 0 is considered the highest priority. -1 means that the priority is unset.
static constexpr int32_t PRIORITY_UNSET = -1;
+ // Windows that are in focus and voted for the preferred mode ID
+ static constexpr int32_t PRIORITY_FOCUSED_WITH_MODE = 0;
+ // // Windows that are in focus, but have not requested a specific mode ID.
+ static constexpr int32_t PRIORITY_FOCUSED_WITHOUT_MODE = 1;
+ // Windows that are not in focus, but voted for a specific mode ID.
+ static constexpr int32_t PRIORITY_NOT_FOCUSED_WITH_MODE = 2;
public:
mutable bool contentDirty{false};
@@ -400,6 +409,7 @@
// If the variable is not set on the layer, it traverses up the tree to inherit the frame
// rate priority from its parent.
virtual int32_t getFrameRateSelectionPriority() const;
+ static bool isLayerFocusedBasedOnPriority(int32_t priority);
virtual ui::Dataspace getDataSpace() const { return ui::Dataspace::UNKNOWN; }
diff --git a/services/surfaceflinger/LayerRenderArea.cpp b/services/surfaceflinger/LayerRenderArea.cpp
new file mode 100644
index 0000000..c4f8666
--- /dev/null
+++ b/services/surfaceflinger/LayerRenderArea.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2020 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 <ui/GraphicTypes.h>
+#include <ui/Transform.h>
+
+#include "ContainerLayer.h"
+#include "DisplayDevice.h"
+#include "Layer.h"
+#include "LayerRenderArea.h"
+#include "SurfaceFlinger.h"
+
+namespace android {
+namespace {
+
+struct ReparentForDrawing {
+ const sp<Layer>& oldParent;
+
+ ReparentForDrawing(const sp<Layer>& oldParent, const sp<Layer>& newParent,
+ const Rect& drawingBounds)
+ : oldParent(oldParent) {
+ // Compute and cache the bounds for the new parent layer.
+ newParent->computeBounds(drawingBounds.toFloatRect(), ui::Transform(),
+ 0.f /* shadowRadius */);
+ oldParent->setChildrenDrawingParent(newParent);
+ }
+ ~ReparentForDrawing() { oldParent->setChildrenDrawingParent(oldParent); }
+};
+
+} // namespace
+
+LayerRenderArea::LayerRenderArea(SurfaceFlinger& flinger, sp<Layer> layer, const Rect& crop,
+ ui::Size reqSize, ui::Dataspace reqDataSpace, bool childrenOnly,
+ const Rect& displayViewport)
+ : RenderArea(reqSize, CaptureFill::CLEAR, reqDataSpace, displayViewport),
+ mLayer(std::move(layer)),
+ mCrop(crop),
+ mFlinger(flinger),
+ mChildrenOnly(childrenOnly) {}
+
+const ui::Transform& LayerRenderArea::getTransform() const {
+ return mTransform;
+}
+
+Rect LayerRenderArea::getBounds() const {
+ return mLayer->getBufferSize(mLayer->getDrawingState());
+}
+
+int LayerRenderArea::getHeight() const {
+ return mLayer->getBufferSize(mLayer->getDrawingState()).getHeight();
+}
+
+int LayerRenderArea::getWidth() const {
+ return mLayer->getBufferSize(mLayer->getDrawingState()).getWidth();
+}
+
+bool LayerRenderArea::isSecure() const {
+ return false;
+}
+
+bool LayerRenderArea::needsFiltering() const {
+ return mNeedsFiltering;
+}
+
+sp<const DisplayDevice> LayerRenderArea::getDisplayDevice() const {
+ return nullptr;
+}
+
+Rect LayerRenderArea::getSourceCrop() const {
+ if (mCrop.isEmpty()) {
+ return getBounds();
+ } else {
+ return mCrop;
+ }
+}
+
+void LayerRenderArea::render(std::function<void()> drawLayers) {
+ using namespace std::string_literals;
+
+ const Rect sourceCrop = getSourceCrop();
+ // no need to check rotation because there is none
+ mNeedsFiltering = sourceCrop.width() != getReqWidth() || sourceCrop.height() != getReqHeight();
+
+ if (!mChildrenOnly) {
+ mTransform = mLayer->getTransform().inverse();
+ drawLayers();
+ } else {
+ uint32_t w = static_cast<uint32_t>(getWidth());
+ uint32_t h = static_cast<uint32_t>(getHeight());
+ // In the "childrenOnly" case we reparent the children to a screenshot
+ // layer which has no properties set and which does not draw.
+ sp<ContainerLayer> screenshotParentLayer = mFlinger.getFactory().createContainerLayer(
+ {&mFlinger, nullptr, "Screenshot Parent"s, w, h, 0, LayerMetadata()});
+
+ ReparentForDrawing reparent(mLayer, screenshotParentLayer, sourceCrop);
+ drawLayers();
+ }
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/LayerRenderArea.h b/services/surfaceflinger/LayerRenderArea.h
new file mode 100644
index 0000000..81690b9
--- /dev/null
+++ b/services/surfaceflinger/LayerRenderArea.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2020 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 <string>
+
+#include <ui/GraphicTypes.h>
+#include <ui/Transform.h>
+#include <utils/StrongPointer.h>
+
+#include "RenderArea.h"
+
+namespace android {
+
+class DisplayDevice;
+class Layer;
+class SurfaceFlinger;
+
+class LayerRenderArea : public RenderArea {
+public:
+ LayerRenderArea(SurfaceFlinger& flinger, sp<Layer> layer, const Rect& crop, ui::Size reqSize,
+ ui::Dataspace reqDataSpace, bool childrenOnly, const Rect& displayViewport);
+
+ const ui::Transform& getTransform() const override;
+ Rect getBounds() const override;
+ int getHeight() const override;
+ int getWidth() const override;
+ bool isSecure() const override;
+ bool needsFiltering() const override;
+ sp<const DisplayDevice> getDisplayDevice() const override;
+ Rect getSourceCrop() const override;
+
+ void render(std::function<void()> drawLayers) override;
+
+private:
+ const sp<Layer> mLayer;
+ const Rect mCrop;
+
+ ui::Transform mTransform;
+ bool mNeedsFiltering = false;
+
+ SurfaceFlinger& mFlinger;
+ const bool mChildrenOnly;
+};
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 398fd40..899d1fa 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -35,6 +35,7 @@
#include <string>
#include "DisplayDevice.h"
+#include "DisplayRenderArea.h"
#include "Layer.h"
#include "Promise.h"
#include "Scheduler/DispSync.h"
@@ -383,8 +384,9 @@
const Rect sampledBounds = sampleRegion.bounds();
SurfaceFlinger::RenderAreaFuture renderAreaFuture = promise::defer([=] {
- return DisplayRenderArea::create(displayWeak, sampledBounds, sampledBounds.getSize(),
- ui::Dataspace::V0_SRGB, orientation);
+ return DisplayRenderArea::create(displayWeak, screencapRegion.bounds(),
+ sampledBounds.getSize(), ui::Dataspace::V0_SRGB,
+ orientation);
});
std::unordered_set<sp<IRegionSamplingListener>, SpHash<IRegionSamplingListener>> listeners;
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 2925109..ecf2597 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -109,6 +109,8 @@
auto layer = weakLayer.promote();
// Only use the layer if the reference still exists.
if (layer || CC_UNLIKELY(mTraceEnabled)) {
+ const auto layerFocused =
+ Layer::isLayerFocusedBasedOnPriority(layer->getFrameRateSelectionPriority());
// Check if frame rate was set on layer.
const auto frameRate = layer->getFrameRateForLayerTree();
if (frameRate.rate > 0.f) {
@@ -122,11 +124,12 @@
return LayerVoteType::NoVote;
}
}();
- summary.push_back({layer->getName(), voteType, frameRate.rate, /* weight */ 1.0f});
+ summary.push_back({layer->getName(), voteType, frameRate.rate, /* weight */ 1.0f,
+ layerFocused});
} else if (recent) {
summary.push_back({layer->getName(), LayerVoteType::Heuristic,
info->getRefreshRate(now),
- /* weight */ 1.0f});
+ /* weight */ 1.0f, layerFocused});
}
if (CC_UNLIKELY(mTraceEnabled)) {
diff --git a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
index ee612b0..aa04bd7 100644
--- a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
@@ -125,9 +125,10 @@
continue;
}
- // TODO(b/144307188): This needs to be plugged into layer summary as
- // an additional parameter.
- ALOGV("Layer has priority: %d", strong->getFrameRateSelectionPriority());
+ const auto frameRateSelectionPriority = strong->getFrameRateSelectionPriority();
+ const auto layerFocused = Layer::isLayerFocusedBasedOnPriority(frameRateSelectionPriority);
+ ALOGV("%s has priority: %d %s focused", strong->getName().c_str(),
+ frameRateSelectionPriority, layerFocused ? "" : "not");
const auto [type, refreshRate] = info->getRefreshRate(now);
// Skip NoVote layer as those don't have any requirements
@@ -143,7 +144,7 @@
const float layerArea = transformed.getWidth() * transformed.getHeight();
float weight = mDisplayArea ? layerArea / mDisplayArea : 0.0f;
- summary.push_back({strong->getName(), type, refreshRate, weight});
+ summary.push_back({strong->getName(), type, refreshRate, weight, layerFocused});
if (CC_UNLIKELY(mTraceEnabled)) {
trace(layer, *info, type, static_cast<int>(std::round(refreshRate)));
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index a6036c6..053d0a7 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -212,10 +212,11 @@
bool inPrimaryRange =
scores[i].first->inPolicy(policy->primaryRange.min, policy->primaryRange.max);
if ((primaryRangeIsSingleRate || !inPrimaryRange) &&
- layer.vote != LayerVoteType::ExplicitDefault &&
- layer.vote != LayerVoteType::ExplicitExactOrMultiple) {
- // Only layers with explicit frame rate settings are allowed to score refresh rates
- // outside the primary range.
+ !(layer.focused &&
+ (layer.vote == LayerVoteType::ExplicitDefault ||
+ layer.vote == LayerVoteType::ExplicitExactOrMultiple))) {
+ // Only focused layers with explicit frame rate settings are allowed to score
+ // refresh rates outside the primary range.
continue;
}
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 8a51b85..27bf0ec 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -195,15 +195,22 @@
// Captures the layer requirements for a refresh rate. This will be used to determine the
// display refresh rate.
struct LayerRequirement {
- std::string name; // Layer's name. Used for debugging purposes.
- LayerVoteType vote; // Layer vote type.
- float desiredRefreshRate; // Layer's desired refresh rate, if applicable.
- float weight; // Layer's weight in the range of [0, 1]. The higher the weight the more
- // impact this layer would have on choosing the refresh rate.
+ // Layer's name. Used for debugging purposes.
+ std::string name;
+ // Layer vote type.
+ LayerVoteType vote = LayerVoteType::NoVote;
+ // Layer's desired refresh rate, if applicable.
+ float desiredRefreshRate = 0.0f;
+ // Layer's weight in the range of [0, 1]. The higher the weight the more impact this layer
+ // would have on choosing the refresh rate.
+ float weight = 0.0f;
+ // Whether layer is in focus or not based on WindowManager's state
+ bool focused = false;
bool operator==(const LayerRequirement& other) const {
return name == other.name && vote == other.vote &&
- desiredRefreshRate == other.desiredRefreshRate && weight == other.weight;
+ desiredRefreshRate == other.desiredRefreshRate && weight == other.weight &&
+ focused == other.focused;
}
bool operator!=(const LayerRequirement& other) const { return !(*this == other); }
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
index a3cb772..ab5773d 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -77,7 +77,14 @@
std::lock_guard<std::mutex> lk(mMutex);
if (!validate(timestamp)) {
- ALOGV("timestamp was too far off the last known timestamp");
+ // VSR could elect to ignore the incongruent timestamp or resetModel(). If ts is ignored,
+ // don't insert this ts into mTimestamps ringbuffer.
+ if (!mTimestamps.empty()) {
+ mKnownTimestamp =
+ std::max(timestamp, *std::max_element(mTimestamps.begin(), mTimestamps.end()));
+ } else {
+ mKnownTimestamp = timestamp;
+ }
return false;
}
@@ -236,7 +243,13 @@
void VSyncPredictor::clearTimestamps() {
if (!mTimestamps.empty()) {
- mKnownTimestamp = *std::max_element(mTimestamps.begin(), mTimestamps.end());
+ auto const maxRb = *std::max_element(mTimestamps.begin(), mTimestamps.end());
+ if (mKnownTimestamp) {
+ mKnownTimestamp = std::max(*mKnownTimestamp, maxRb);
+ } else {
+ mKnownTimestamp = maxRb;
+ }
+
mTimestamps.clear();
mLastTimestampIndex = 0;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e68c484..db6f1ad 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -102,10 +102,12 @@
#include "DisplayHardware/FramebufferSurface.h"
#include "DisplayHardware/HWComposer.h"
#include "DisplayHardware/VirtualDisplaySurface.h"
+#include "DisplayRenderArea.h"
#include "EffectLayer.h"
#include "Effects/Daltonizer.h"
#include "FrameTracer/FrameTracer.h"
#include "Layer.h"
+#include "LayerRenderArea.h"
#include "LayerVector.h"
#include "MonitoredProducer.h"
#include "NativeWindowSurface.h"
@@ -2003,7 +2005,8 @@
bool runHandleTransaction =
(transactionFlags && (transactionFlags != eTransactionFlushNeeded)) ||
- flushedATransaction;
+ flushedATransaction ||
+ mForceTraversal;
if (runHandleTransaction) {
handleTransaction(eTransactionMask);
@@ -5559,86 +5562,6 @@
float frameScale, bool childrenOnly) {
ATRACE_CALL();
- class LayerRenderArea : public RenderArea {
- public:
- LayerRenderArea(SurfaceFlinger* flinger, const sp<Layer>& layer, const Rect crop,
- ui::Size reqSize, Dataspace reqDataSpace, bool childrenOnly,
- const Rect& displayViewport)
- : RenderArea(reqSize, CaptureFill::CLEAR, reqDataSpace, displayViewport),
- mLayer(layer),
- mCrop(crop),
- mNeedsFiltering(false),
- mFlinger(flinger),
- mChildrenOnly(childrenOnly) {}
- const ui::Transform& getTransform() const override { return mTransform; }
- Rect getBounds() const override { return mLayer->getBufferSize(mLayer->getDrawingState()); }
- int getHeight() const override {
- return mLayer->getBufferSize(mLayer->getDrawingState()).getHeight();
- }
- int getWidth() const override {
- return mLayer->getBufferSize(mLayer->getDrawingState()).getWidth();
- }
- bool isSecure() const override { return false; }
- bool needsFiltering() const override { return mNeedsFiltering; }
- sp<const DisplayDevice> getDisplayDevice() const override { return nullptr; }
- Rect getSourceCrop() const override {
- if (mCrop.isEmpty()) {
- return getBounds();
- } else {
- return mCrop;
- }
- }
- class ReparentForDrawing {
- public:
- const sp<Layer>& oldParent;
- const sp<Layer>& newParent;
-
- ReparentForDrawing(const sp<Layer>& oldParent, const sp<Layer>& newParent,
- const Rect& drawingBounds)
- : oldParent(oldParent), newParent(newParent) {
- // Compute and cache the bounds for the new parent layer.
- newParent->computeBounds(drawingBounds.toFloatRect(), ui::Transform(),
- 0.f /* shadowRadius */);
- oldParent->setChildrenDrawingParent(newParent);
- }
- ~ReparentForDrawing() { oldParent->setChildrenDrawingParent(oldParent); }
- };
-
- void render(std::function<void()> drawLayers) override {
- const Rect sourceCrop = getSourceCrop();
- // no need to check rotation because there is none
- mNeedsFiltering = sourceCrop.width() != getReqWidth() ||
- sourceCrop.height() != getReqHeight();
-
- if (!mChildrenOnly) {
- mTransform = mLayer->getTransform().inverse();
- drawLayers();
- } else {
- uint32_t w = static_cast<uint32_t>(getWidth());
- uint32_t h = static_cast<uint32_t>(getHeight());
- // In the "childrenOnly" case we reparent the children to a screenshot
- // layer which has no properties set and which does not draw.
- sp<ContainerLayer> screenshotParentLayer =
- mFlinger->getFactory().createContainerLayer({mFlinger, nullptr,
- "Screenshot Parent"s, w, h, 0,
- LayerMetadata()});
-
- ReparentForDrawing reparent(mLayer, screenshotParentLayer, sourceCrop);
- drawLayers();
- }
- }
-
- private:
- const sp<Layer> mLayer;
- const Rect mCrop;
-
- ui::Transform mTransform;
- bool mNeedsFiltering;
-
- SurfaceFlinger* mFlinger;
- const bool mChildrenOnly;
- };
-
ui::Size reqSize;
sp<Layer> parent;
Rect crop(sourceCrop);
@@ -5705,7 +5628,7 @@
}
RenderAreaFuture renderAreaFuture = promise::defer([=]() -> std::unique_ptr<RenderArea> {
- return std::make_unique<LayerRenderArea>(this, parent, crop, reqSize, reqDataspace,
+ return std::make_unique<LayerRenderArea>(*this, parent, crop, reqSize, reqDataspace,
childrenOnly, displayViewport);
});
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 6a3937f..e9a2905 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -95,6 +95,7 @@
class MessageBase;
class RefreshRateOverlay;
class RegionSamplingThread;
+class RenderArea;
class TimeStats;
class FrameTracer;
diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
index cfc301b..7b1f0fb 100644
--- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
+++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
@@ -328,7 +328,7 @@
prop {
api_name: "refresh_rate_switching"
type: Boolean
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.refresh_rate_switching"
deprecated: true
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 456891e..9355e61 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -35,6 +35,7 @@
#include <utils/String8.h>
#include "BufferQueueLayer.h"
+#include "DisplayRenderArea.h"
#include "EffectLayer.h"
#include "Layer.h"
#include "TestableSurfaceFlinger.h"
@@ -248,8 +249,9 @@
int fd = -1;
status_t result =
- mFlinger.captureScreenImplLocked(*renderArea, traverseLayers, mCaptureScreenBuffer.get(),
- useIdentityTransform, forSystem, &fd, regionSampling);
+ mFlinger.captureScreenImplLocked(*renderArea, traverseLayers,
+ mCaptureScreenBuffer.get(), useIdentityTransform,
+ forSystem, &fd, regionSampling);
if (fd >= 0) {
close(fd);
}
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index fed591c..03d4460 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -292,7 +292,8 @@
/*currentConfigId=*/HWC_CONFIG_ID_60);
const auto makeLayerRequirements = [](float refreshRate) -> std::vector<LayerRequirement> {
- return {{"testLayer", LayerVoteType::Heuristic, refreshRate, 1.0f}};
+ return {{"testLayer", LayerVoteType::Heuristic, refreshRate, /*weight*/ 1.0f,
+ /*focused*/ false}};
};
EXPECT_EQ(mExpected90Config,
@@ -1132,6 +1133,7 @@
lr.vote = LayerVoteType::ExplicitExactOrMultiple;
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz ExplicitExactOrMultiple";
+ lr.focused = true;
EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = true},
&consideredSignals));
@@ -1140,6 +1142,7 @@
lr.vote = LayerVoteType::ExplicitDefault;
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz ExplicitDefault";
+ lr.focused = true;
EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = true},
&consideredSignals));
@@ -1162,18 +1165,20 @@
lr.vote = LayerVoteType::ExplicitExactOrMultiple;
lr.desiredRefreshRate = 90.0f;
lr.name = "90Hz ExplicitExactOrMultiple";
+ lr.focused = true;
EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = true}));
lr.vote = LayerVoteType::ExplicitDefault;
lr.desiredRefreshRate = 90.0f;
lr.name = "90Hz ExplicitDefault";
+ lr.focused = true;
EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = true}));
}
TEST_F(RefreshRateConfigsTest,
- getBestRefreshRate_withDisplayManagerRequestingSingleRate_onlySwitchesRatesForExplicitLayers) {
+ getBestRefreshRate_withDisplayManagerRequestingSingleRate_onlySwitchesRatesForExplicitFocusedLayers) {
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m60_90Device,
/*currentConfigId=*/HWC_CONFIG_ID_90);
@@ -1194,30 +1199,55 @@
lr.vote = LayerVoteType::ExplicitExactOrMultiple;
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz ExplicitExactOrMultiple";
+ lr.focused = false;
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ lr.focused = true;
EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.vote = LayerVoteType::ExplicitDefault;
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz ExplicitDefault";
+ lr.focused = false;
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ lr.focused = true;
EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.vote = LayerVoteType::Heuristic;
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz Heuristic";
+ lr.focused = false;
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ lr.focused = true;
EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.vote = LayerVoteType::Max;
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz Max";
+ lr.focused = false;
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ lr.focused = true;
EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.vote = LayerVoteType::Min;
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz Min";
+ lr.focused = false;
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ lr.focused = true;
EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
}
@@ -1256,10 +1286,11 @@
// Return the config ID from calling getBestRefreshRate() for a single layer with the
// given voteType and fps.
- auto getFrameRate = [&](LayerVoteType voteType, float fps,
- bool touchActive = false) -> HwcConfigIndexType {
+ auto getFrameRate = [&](LayerVoteType voteType, float fps, bool touchActive = false,
+ bool focused = true) -> HwcConfigIndexType {
layers[0].vote = voteType;
layers[0].desiredRefreshRate = fps;
+ layers[0].focused = focused;
return refreshRateConfigs->getBestRefreshRate(layers, {.touch = touchActive, .idle = false})
.getConfigId();
};
@@ -1277,6 +1308,14 @@
EXPECT_EQ(HWC_CONFIG_ID_90, getFrameRate(LayerVoteType::ExplicitDefault, 90.f));
EXPECT_EQ(HWC_CONFIG_ID_90, getFrameRate(LayerVoteType::ExplicitExactOrMultiple, 90.f));
+ // Layers not focused are not allowed to override primary config
+ EXPECT_EQ(HWC_CONFIG_ID_60,
+ getFrameRate(LayerVoteType::ExplicitDefault, 90.f, /*touch=*/false,
+ /*focused=*/false));
+ EXPECT_EQ(HWC_CONFIG_ID_60,
+ getFrameRate(LayerVoteType::ExplicitExactOrMultiple, 90.f, /*touch=*/false,
+ /*focused=*/false));
+
// Touch boost should be restricted to the primary range.
EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Max, 90.f, /*touch=*/true));
// When we're higher than the primary range max due to a layer frame rate setting, touch boost
diff --git a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
index bf2a889..fc39235 100644
--- a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
@@ -124,6 +124,38 @@
EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + changedPeriod));
}
+// b/159882858
+TEST_F(VSyncPredictorTest, updatesTimebaseForSyntheticAfterIdleTime) {
+ for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
+ EXPECT_TRUE(tracker.addVsyncTimestamp(mNow += mPeriod));
+ }
+
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + mPeriod));
+
+ auto const halfPeriod = mPeriod >> 2;
+ nsecs_t relativelyLongGapWithDrift = mPeriod * 100 + halfPeriod;
+
+ EXPECT_FALSE(tracker.addVsyncTimestamp(mNow += relativelyLongGapWithDrift));
+
+ tracker.resetModel();
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + mPeriod));
+}
+
+TEST_F(VSyncPredictorTest, uponBadVsyncWillSwitchToSyntheticWhileRecalibrating) {
+ auto const slightlyMorePeriod = mPeriod + 10;
+ for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
+ EXPECT_TRUE(tracker.addVsyncTimestamp(mNow += slightlyMorePeriod));
+ }
+
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + slightlyMorePeriod));
+
+ auto const halfPeriod = mPeriod >> 2;
+ EXPECT_FALSE(tracker.addVsyncTimestamp(mNow += halfPeriod));
+
+ tracker.resetModel();
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + mPeriod));
+}
+
TEST_F(VSyncPredictorTest, adaptsToFenceTimelines_60hzHighVariance) {
// these are precomputed simulated 16.6s vsyncs with uniform distribution +/- 1.6ms error
std::vector<nsecs_t> const simulatedVsyncs{