Merge "Use unique_ptr for CommandEntry"
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 587d25f..5186ad3 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -171,6 +171,7 @@
{ OPT, "events/clk/clk_disable/enable" },
{ OPT, "events/clk/clk_enable/enable" },
{ OPT, "events/power/cpu_frequency_limits/enable" },
+ { OPT, "events/power/suspend_resume/enable" },
} },
{ "membus", "Memory Bus Utilization", 0, {
{ REQ, "events/memory_bus/enable" },
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index f1426b6..6e460a0 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -49,6 +49,8 @@
chmod 0666 /sys/kernel/tracing/events/power/cpu_frequency_limits/enable
chmod 0666 /sys/kernel/debug/tracing/events/power/gpu_frequency/enable
chmod 0666 /sys/kernel/tracing/events/power/gpu_frequency/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/power/suspend_resume/enable
+ chmod 0666 /sys/kernel/tracing/events/power/suspend_resume/enable
chmod 0666 /sys/kernel/debug/tracing/events/cpufreq_interactive/enable
chmod 0666 /sys/kernel/tracing/events/cpufreq_interactive/enable
chmod 0666 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin/enable
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 3a0aa95..7443cb3 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -44,10 +44,12 @@
#include <unistd.h>
#include <chrono>
+#include <cmath>
#include <fstream>
#include <functional>
#include <future>
#include <memory>
+#include <numeric>
#include <regex>
#include <set>
#include <string>
@@ -1232,6 +1234,45 @@
}
}
+static void DumpExternalFragmentationInfo() {
+ struct stat st;
+ if (stat("/proc/buddyinfo", &st) != 0) {
+ MYLOGE("Unable to dump external fragmentation info\n");
+ return;
+ }
+
+ printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
+ std::ifstream ifs("/proc/buddyinfo");
+ auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
+ for (std::string line; std::getline(ifs, line);) {
+ std::smatch match_results;
+ if (std::regex_match(line, match_results, unusable_index_regex)) {
+ std::stringstream free_pages(std::string{match_results[3]});
+ std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
+ std::istream_iterator<int>());
+
+ int total_free_pages = 0;
+ for (size_t i = 0; i < free_pages_per_order.size(); i++) {
+ total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
+ }
+
+ printf("Node %s, zone %8s", match_results[1].str().c_str(),
+ match_results[2].str().c_str());
+
+ int usable_free_pages = total_free_pages;
+ for (size_t i = 0; i < free_pages_per_order.size(); i++) {
+ auto unusable_index = (total_free_pages - usable_free_pages) /
+ static_cast<double>(total_free_pages);
+ printf(" %5.3f", unusable_index);
+ usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
+ }
+
+ printf("\n");
+ }
+ }
+ printf("\n");
+}
+
// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
// via the consent they are shown. Ignores other errors that occur while running various
// commands. The consent checking is currently done around long running tasks, which happen to
@@ -1258,7 +1299,7 @@
DumpFile("ZONEINFO", "/proc/zoneinfo");
DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
DumpFile("BUDDYINFO", "/proc/buddyinfo");
- DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
+ DumpExternalFragmentationInfo();
DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index 73780ec..0212bc5 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -275,7 +275,7 @@
writer.StartEntry("primary.prof", ZipWriter::kCompress);
writer.FinishEntry();
writer.Finish();
- close(fd);
+ fclose(file);
}
// Create the app user data.
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index 5f7dc25..f35f360 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -98,18 +98,12 @@
return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
}
+ // implicitly unlinked when the binder is removed
if (OK != binder->linkToDeath(this)) {
LOG(ERROR) << "Could not linkToDeath when adding " << name;
return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
}
- auto it = mNameToService.find(name);
- if (it != mNameToService.end()) {
- if (OK != it->second.binder->unlinkToDeath(this)) {
- LOG(WARNING) << "Could not unlinkToDeath when adding " << name;
- }
- }
-
mNameToService[name] = Service {
.binder = binder,
.allowIsolated = allowIsolated,
diff --git a/data/etc/car_core_hardware.xml b/data/etc/car_core_hardware.xml
index ad7791e..50f117d 100644
--- a/data/etc/car_core_hardware.xml
+++ b/data/etc/car_core_hardware.xml
@@ -40,7 +40,6 @@
<feature name="android.software.voice_recognizers" notLowRam="true" />
<feature name="android.software.backup" />
<feature name="android.software.home_screen" />
- <feature name="android.software.print" />
<feature name="android.software.companion_device_setup" />
<feature name="android.software.autofill" />
<feature name="android.software.cant_save_state" />
diff --git a/include/android/bitmap.h b/include/android/bitmap.h
index 2def64d..6fba0ac 100644
--- a/include/android/bitmap.h
+++ b/include/android/bitmap.h
@@ -60,6 +60,8 @@
ANDROID_BITMAP_FORMAT_RGBA_4444 = 7,
/** Alpha: 8 bits. */
ANDROID_BITMAP_FORMAT_A_8 = 8,
+ /** Each component is stored as a half float. **/
+ ANDROID_BITMAP_FORMAT_RGBA_F16 = 9,
};
/** Bitmap info, see AndroidBitmap_getInfo(). */
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 1537e69..dec75f5 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -38,7 +38,7 @@
virtual status_t transact( uint32_t code,
const Parcel& data,
Parcel* reply,
- uint32_t flags = 0);
+ uint32_t flags = 0) final;
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index e71541b..28599f4 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -45,7 +45,7 @@
virtual status_t transact( uint32_t code,
const Parcel& data,
Parcel* reply,
- uint32_t flags = 0);
+ uint32_t flags = 0) final;
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 6da3086..734a928 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-cc_library {
+cc_library_shared {
name: "libbinder_ndk",
export_include_dirs: [
"include_ndk",
- "include_apex",
+ "include_platform",
],
cflags: [
@@ -33,6 +33,7 @@
"ibinder_jni.cpp",
"parcel.cpp",
"process.cpp",
+ "stability.cpp",
"status.cpp",
"service_manager.cpp",
],
@@ -54,7 +55,7 @@
version_script: "libbinder_ndk.map.txt",
stubs: {
symbol_file: "libbinder_ndk.map.txt",
- versions: ["29"],
+ versions: ["29", "30"],
},
}
@@ -79,6 +80,6 @@
symbol_file: "libbinder_ndk.map.txt",
export_include_dirs: [
"include_ndk",
- "include_apex",
+ "include_platform",
],
}
diff --git a/libs/binder/ndk/include_apex/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
similarity index 100%
rename from libs/binder/ndk/include_apex/android/binder_manager.h
rename to libs/binder/ndk/include_platform/android/binder_manager.h
diff --git a/libs/binder/ndk/include_apex/android/binder_process.h b/libs/binder/ndk/include_platform/android/binder_process.h
similarity index 100%
rename from libs/binder/ndk/include_apex/android/binder_process.h
rename to libs/binder/ndk/include_platform/android/binder_process.h
diff --git a/libs/binder/ndk/include_platform/android/binder_stability.h b/libs/binder/ndk/include_platform/android/binder_stability.h
new file mode 100644
index 0000000..e6aeb04
--- /dev/null
+++ b/libs/binder/ndk/include_platform/android/binder_stability.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/binder_ibinder.h>
+
+__BEGIN_DECLS
+
+#ifdef __ANDROID_VNDK__
+
+/**
+ * This interface has the stability of the vendor image.
+ */
+void AIBinder_markVendorStability(AIBinder* binder);
+
+static inline void AIBinder_markCompilationUnitStability(AIBinder* binder) {
+ AIBinder_markVendorStability(binder);
+}
+
+#else // ndef defined __ANDROID_VNDK__
+
+/**
+ * This interface has the stability of the system image.
+ */
+void AIBinder_markSystemStability(AIBinder* binder);
+
+static inline void AIBinder_markCompilationUnitStability(AIBinder* binder) {
+ AIBinder_markSystemStability(binder);
+}
+
+#endif // ifdef __ANDROID_VNDK__
+
+/**
+ * This interface has system<->vendor stability
+ */
+void AIBinder_markVintfStability(AIBinder* binder);
+
+__END_DECLS
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 4f685d1..feedde6 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -98,3 +98,12 @@
local:
*;
};
+
+LIBBINDER_NDK30 { # introduced=30
+ global:
+ AIBinder_markSystemStability; # apex
+ AIBinder_markVendorStability; # vndk
+ AIBinder_markVintfStability; # apex vndk
+ local:
+ *;
+};
diff --git a/libs/binder/ndk/stability.cpp b/libs/binder/ndk/stability.cpp
new file mode 100644
index 0000000..a5b3ece
--- /dev/null
+++ b/libs/binder/ndk/stability.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/binder_stability.h>
+
+#include <binder/Stability.h>
+#include "ibinder_internal.h"
+
+#include <log/log.h>
+
+using ::android::internal::Stability;
+
+#ifdef __ANDROID_VNDK__
+#error libbinder_ndk should only be built in a system context
+#endif
+
+#ifdef __ANDROID_NDK__
+#error libbinder_ndk should only be built in a system context
+#endif
+
+// explicit extern because symbol is only declared in header when __ANDROID_VNDK__
+extern "C" void AIBinder_markVendorStability(AIBinder* binder) {
+ Stability::markVndk(binder->getBinder().get());
+}
+
+void AIBinder_markSystemStability(AIBinder* binder) {
+ Stability::markCompilationUnit(binder->getBinder().get());
+}
+
+void AIBinder_markVintfStability(AIBinder* binder) {
+ Stability::markVintf(binder->getBinder().get());
+}
diff --git a/libs/binder/ndk/test/Android.bp b/libs/binder/ndk/test/Android.bp
index 8cd4e03..bb1fe2f 100644
--- a/libs/binder/ndk/test/Android.bp
+++ b/libs/binder/ndk/test/Android.bp
@@ -44,10 +44,10 @@
"libandroid_runtime_lazy",
"libbase",
"libbinder",
+ "libbinder_ndk",
"libutils",
],
static_libs: [
- "libbinder_ndk",
"test_libbinder_ndk_library",
],
}
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 724cb15..bc457ce 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -138,18 +138,30 @@
test_suites: ["device-tests"],
}
+aidl_interface {
+ name: "binderStabilityTestIface",
+ srcs: [
+ "IBinderStabilityTest.aidl",
+ ],
+}
+
cc_test {
name: "binderStabilityTest",
defaults: ["binder_test_defaults"],
srcs: [
"binderStabilityTest.cpp",
- "IBinderStabilityTest.aidl",
- "IBinderStabilityTestSub.aidl",
],
shared_libs: [
+ "libbinder_ndk",
"libbinder",
+ "liblog",
"libutils",
],
+ static_libs: [
+ "binderStabilityTestIface-cpp",
+ "binderStabilityTestIface-ndk_platform",
+ ],
+
test_suites: ["device-tests"],
}
diff --git a/libs/binder/tests/IBinderStabilityTest.aidl b/libs/binder/tests/IBinderStabilityTest.aidl
index 9559196..36e1c2c 100644
--- a/libs/binder/tests/IBinderStabilityTest.aidl
+++ b/libs/binder/tests/IBinderStabilityTest.aidl
@@ -14,34 +14,32 @@
* limitations under the License.
*/
-import IBinderStabilityTestSub;
-
// DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
// THIS IS ONLY FOR TESTING!
interface IBinderStabilityTest {
// DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
// THIS IS ONLY FOR TESTING!
- void sendBinder(IBinderStabilityTestSub binder);
+ void sendBinder(IBinder binder);
// DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
// THIS IS ONLY FOR TESTING!
- void sendAndCallBinder(IBinderStabilityTestSub binder);
+ void sendAndCallBinder(IBinder binder);
// DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
// THIS IS ONLY FOR TESTING!
- IBinderStabilityTestSub returnNoStabilityBinder();
+ IBinder returnNoStabilityBinder();
// DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
// THIS IS ONLY FOR TESTING!
- IBinderStabilityTestSub returnLocalStabilityBinder();
+ IBinder returnLocalStabilityBinder();
// DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
// THIS IS ONLY FOR TESTING!
- IBinderStabilityTestSub returnVintfStabilityBinder();
+ IBinder returnVintfStabilityBinder();
// DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
// THIS IS ONLY FOR TESTING!
- IBinderStabilityTestSub returnVendorStabilityBinder();
+ IBinder returnVendorStabilityBinder();
}
// DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
// THIS IS ONLY FOR TESTING!
diff --git a/libs/binder/tests/IBinderStabilityTestSub.aidl b/libs/binder/tests/IBinderStabilityTestSub.aidl
deleted file mode 100644
index a81ebf9..0000000
--- a/libs/binder/tests/IBinderStabilityTestSub.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-interface IBinderStabilityTestSub {
- void userDefinedTransaction();
-}
diff --git a/libs/binder/tests/binderStabilityTest.cpp b/libs/binder/tests/binderStabilityTest.cpp
index 52595e0..0336b9e 100644
--- a/libs/binder/tests/binderStabilityTest.cpp
+++ b/libs/binder/tests/binderStabilityTest.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include <android/binder_manager.h>
+#include <android/binder_stability.h>
#include <binder/Binder.h>
#include <binder/IBinder.h>
#include <binder/IPCThreadState.h>
@@ -24,143 +26,225 @@
#include <sys/prctl.h>
-#include "BnBinderStabilityTestSub.h"
+#include "aidl/BnBinderStabilityTest.h"
#include "BnBinderStabilityTest.h"
-#include "BpBinderStabilityTest.h"
using namespace android;
+using namespace ndk;
using android::binder::Status;
+using android::internal::Stability; // for testing only!
-const String16 kNoStabilityServer = String16("binder_stability_test_service_low");
-const String16 kCompilationUnitServer = String16("binder_stability_test_service_compl");
-const String16 kVintfServer = String16("binder_stability_test_service_vintf");
+const String16 kSystemStabilityServer = String16("binder_stability_test_service_system");
-class BadStabilityTestSub : public BnBinderStabilityTestSub {
- Status userDefinedTransaction() {
- return Status::ok();
+// This is handwritten so that we can test different stability levels w/o having the AIDL
+// compiler assign them. Hand-writing binder interfaces is considered a bad practice
+// sanity reasons. YOU SHOULD DEFINE AN AIDL INTERFACE INSTEAD!
+class BadStableBinder : public BBinder {
+public:
+ static constexpr uint32_t USER_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION;
+ static String16 kDescriptor;
+
+ bool gotUserTransaction = false;
+
+ static status_t doUserTransaction(const sp<IBinder>& binder) {
+ Parcel data, reply;
+ data.writeInterfaceToken(kDescriptor);
+ return binder->transact(USER_TRANSACTION, data, &reply, 0/*flags*/);
+ }
+
+ status_t onTransact(uint32_t code,
+ const Parcel& data, Parcel* reply, uint32_t flags) override {
+ if (code == USER_TRANSACTION) {
+ // not interested in this kind of stability. Make sure
+ // we have a test failure
+ LOG_ALWAYS_FATAL_IF(!data.enforceInterface(kDescriptor));
+
+ gotUserTransaction = true;
+
+ ALOGE("binder stability: Got user transaction");
+ return OK;
+ }
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+
+ static sp<BadStableBinder> undef() {
+ sp<BadStableBinder> iface = new BadStableBinder();
+ return iface;
+ }
+
+ static sp<BadStableBinder> system() {
+ sp<BadStableBinder> iface = new BadStableBinder();
+ Stability::markCompilationUnit(iface.get()); // <- for test only
+ return iface;
+ }
+
+ static sp<BadStableBinder> vintf() {
+ sp<BadStableBinder> iface = new BadStableBinder();
+ Stability::markVintf(iface.get()); // <- for test only
+ return iface;
+ }
+
+ static sp<BadStableBinder> vendor() {
+ sp<BadStableBinder> iface = new BadStableBinder();
+ Stability::markVndk(iface.get()); // <- for test only
+ return iface;
}
};
-
-sp<IBinderStabilityTestSub> getCompilationUnitStability() {
- sp<BnBinderStabilityTestSub> iface = new BadStabilityTestSub();
- // NO! NO! NO! NO! DO NOT EVERY DO SOMETHING LIKE THIS?
- // WHAT ARE YOU CRAZY? IT'S VERY DANGEROUS
- internal::Stability::markCompilationUnit(iface.get()); // <- BAD, NO! DO NOT COPY
- return iface;
-}
-
-sp<IBinderStabilityTestSub> getVintfStability() {
- sp<BnBinderStabilityTestSub> iface = new BadStabilityTestSub();
- // NO! NO! NO! NO! DO NOT EVERY DO SOMETHING LIKE THIS?
- // WHAT ARE YOU CRAZY? IT'S VERY DANGEROUS
- internal::Stability::markVintf(iface.get()); // <- BAD, NO! DO NOT COPY
- return iface;
-}
-
-sp<IBinderStabilityTestSub> getVendorStability() {
- sp<BnBinderStabilityTestSub> iface = new BadStabilityTestSub();
- // NO! NO! NO! NO! DO NOT EVERY DO SOMETHING LIKE THIS?
- // WHAT ARE YOU CRAZY? IT'S VERY DANGEROUS
- internal::Stability::markVndk(iface.get()); // <- BAD, NO! DO NOT COPY
- return iface;
-}
+String16 BadStableBinder::kDescriptor = String16("BadStableBinder.test");
// NO! NO! NO! Do not even think of doing something like this!
// This is for testing! If a class like this was actually used in production,
// it would ruin everything!
-class BadStabilityTester : public BnBinderStabilityTest {
+class MyBinderStabilityTest : public BnBinderStabilityTest {
public:
- Status sendBinder(const sp<IBinderStabilityTestSub>& /*binder*/) override {
+ Status sendBinder(const sp<IBinder>& /*binder*/) override {
return Status::ok();
}
- Status sendAndCallBinder(const sp<IBinderStabilityTestSub>& binder) override {
- return binder->userDefinedTransaction();
+ Status sendAndCallBinder(const sp<IBinder>& binder) override {
+ Stability::debugLogStability("sendAndCallBinder got binder", binder);
+ return Status::fromExceptionCode(BadStableBinder::doUserTransaction(binder));
}
- Status returnNoStabilityBinder(sp<IBinderStabilityTestSub>* _aidl_return) override {
- *_aidl_return = new BadStabilityTestSub();
+ Status returnNoStabilityBinder(sp<IBinder>* _aidl_return) override {
+ *_aidl_return = BadStableBinder::undef();
return Status::ok();
}
- Status returnLocalStabilityBinder(sp<IBinderStabilityTestSub>* _aidl_return) override {
- *_aidl_return = getCompilationUnitStability();
+ Status returnLocalStabilityBinder(sp<IBinder>* _aidl_return) override {
+ *_aidl_return = BadStableBinder::system();
return Status::ok();
}
- Status returnVintfStabilityBinder(sp<IBinderStabilityTestSub>* _aidl_return) override {
- *_aidl_return = getVintfStability();
+ Status returnVintfStabilityBinder(sp<IBinder>* _aidl_return) override {
+ *_aidl_return = BadStableBinder::vintf();
return Status::ok();
}
- Status returnVendorStabilityBinder(sp<IBinderStabilityTestSub>* _aidl_return) override {
- *_aidl_return = getVendorStability();
+ Status returnVendorStabilityBinder(sp<IBinder>* _aidl_return) override {
+ *_aidl_return = BadStableBinder::vendor();
return Status::ok();
}
};
-void checkSystemStabilityBinder(const sp<IBinderStabilityTest>& complServer) {
- EXPECT_TRUE(complServer->sendBinder(new BadStabilityTestSub()).isOk());
- EXPECT_TRUE(complServer->sendBinder(getCompilationUnitStability()).isOk());
- EXPECT_TRUE(complServer->sendBinder(getVintfStability()).isOk());
- EXPECT_TRUE(complServer->sendBinder(getVendorStability()).isOk());
+TEST(BinderStability, CantCallVendorBinderInSystemContext) {
+ sp<IBinder> serverBinder = android::defaultServiceManager()->getService(kSystemStabilityServer);
+ auto server = interface_cast<IBinderStabilityTest>(serverBinder);
- EXPECT_TRUE(complServer->sendAndCallBinder(new BadStabilityTestSub()).isOk());
- EXPECT_TRUE(complServer->sendAndCallBinder(getCompilationUnitStability()).isOk());
- EXPECT_TRUE(complServer->sendAndCallBinder(getVintfStability()).isOk());
+ ASSERT_NE(nullptr, server.get());
+ ASSERT_NE(nullptr, IInterface::asBinder(server)->remoteBinder());
- // !!! user-defined transaction may not be stable for remote server !!!
- EXPECT_FALSE(complServer->sendAndCallBinder(getVendorStability()).isOk());
+ EXPECT_TRUE(server->sendBinder(BadStableBinder::undef()).isOk());
+ EXPECT_TRUE(server->sendBinder(BadStableBinder::system()).isOk());
+ EXPECT_TRUE(server->sendBinder(BadStableBinder::vintf()).isOk());
+ EXPECT_TRUE(server->sendBinder(BadStableBinder::vendor()).isOk());
- sp<IBinderStabilityTestSub> out;
- EXPECT_TRUE(complServer->returnNoStabilityBinder(&out).isOk());
+ {
+ sp<BadStableBinder> binder = BadStableBinder::undef();
+ EXPECT_TRUE(server->sendAndCallBinder(binder).isOk());
+ EXPECT_TRUE(binder->gotUserTransaction);
+ }
+ {
+ sp<BadStableBinder> binder = BadStableBinder::system();
+ EXPECT_TRUE(server->sendAndCallBinder(binder).isOk());
+ EXPECT_TRUE(binder->gotUserTransaction);
+ }
+ {
+ sp<BadStableBinder> binder = BadStableBinder::vintf();
+ EXPECT_TRUE(server->sendAndCallBinder(binder).isOk());
+ EXPECT_TRUE(binder->gotUserTransaction);
+ }
+ {
+ // !!! user-defined transaction may not be stable for remote server !!!
+ // !!! so, it does not work !!!
+ sp<BadStableBinder> binder = BadStableBinder::vendor();
+ EXPECT_EQ(BAD_TYPE, server->sendAndCallBinder(binder).exceptionCode());
+ EXPECT_FALSE(binder->gotUserTransaction);
+ }
+
+ sp<IBinder> out;
+ EXPECT_TRUE(server->returnNoStabilityBinder(&out).isOk());
ASSERT_NE(nullptr, out.get());
- EXPECT_EQ(OK, IInterface::asBinder(out)->pingBinder());
- EXPECT_TRUE(out->userDefinedTransaction().isOk());
+ EXPECT_EQ(OK, out->pingBinder());
+ EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out));
- EXPECT_TRUE(complServer->returnLocalStabilityBinder(&out).isOk());
+ EXPECT_TRUE(server->returnLocalStabilityBinder(&out).isOk());
ASSERT_NE(nullptr, out.get());
- EXPECT_EQ(OK, IInterface::asBinder(out)->pingBinder());
- EXPECT_TRUE(out->userDefinedTransaction().isOk());
+ EXPECT_EQ(OK, out->pingBinder());
+ EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out));
- EXPECT_TRUE(complServer->returnVintfStabilityBinder(&out).isOk());
+ EXPECT_TRUE(server->returnVintfStabilityBinder(&out).isOk());
ASSERT_NE(nullptr, out.get());
- EXPECT_EQ(OK, IInterface::asBinder(out)->pingBinder());
- EXPECT_TRUE(out->userDefinedTransaction().isOk());
+ EXPECT_EQ(OK, out->pingBinder());
+ EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out));
- EXPECT_TRUE(complServer->returnVendorStabilityBinder(&out).isOk());
+ EXPECT_TRUE(server->returnVendorStabilityBinder(&out).isOk());
ASSERT_NE(nullptr, out.get());
// !!! libbinder-defined transaction works !!!
- EXPECT_EQ(OK, IInterface::asBinder(out)->pingBinder());
+ EXPECT_EQ(OK, out->pingBinder());
// !!! user-defined transaction may not be stable !!!
- EXPECT_FALSE(out->userDefinedTransaction().isOk());
+ // !!! so, it does not work !!!
+ EXPECT_EQ(BAD_TYPE, BadStableBinder::doUserTransaction(out));
}
-TEST(BinderStability, RemoteNoStabilityServer) {
- sp<IBinder> remoteBinder = android::defaultServiceManager()->getService(kNoStabilityServer);
- auto remoteServer = interface_cast<IBinderStabilityTest>(remoteBinder);
+// This is handwritten so that we can test different stability levels w/o having the AIDL
+// compiler assign them. Hand-writing binder interfaces is considered a bad practice
+// sanity reasons. YOU SHOULD DEFINE AN AIDL INTERFACE INSTEAD!
- ASSERT_NE(nullptr, remoteServer.get());
- ASSERT_NE(nullptr, IInterface::asBinder(remoteServer)->remoteBinder());
+struct NdkBinderStable_DataClass {
+ bool gotUserTransaction = false;
+};
+void* NdkBadStableBinder_Class_onCreate(void* args) {
+ LOG_ALWAYS_FATAL_IF(args != nullptr, "Takes no args");
+ return static_cast<void*>(new NdkBinderStable_DataClass);
+}
+void NdkBadStableBinder_Class_onDestroy(void* userData) {
+ delete static_cast<NdkBinderStable_DataClass*>(userData);
+}
+NdkBinderStable_DataClass* NdkBadStableBinder_getUserData(AIBinder* binder) {
+ LOG_ALWAYS_FATAL_IF(binder == nullptr);
+ void* userData = AIBinder_getUserData(binder);
+ LOG_ALWAYS_FATAL_IF(userData == nullptr, "null data - binder is remote?");
- checkSystemStabilityBinder(remoteServer);
+ return static_cast<NdkBinderStable_DataClass*>(userData);
+}
+binder_status_t NdkBadStableBinder_Class_onTransact(
+ AIBinder* binder, transaction_code_t code, const AParcel* /*in*/, AParcel* /*out*/) {
+
+ if (code == BadStableBinder::USER_TRANSACTION) {
+ ALOGE("ndk binder stability: Got user transaction");
+ NdkBadStableBinder_getUserData(binder)->gotUserTransaction = true;
+ return STATUS_OK;
+ }
+
+ return STATUS_UNKNOWN_TRANSACTION;
}
-TEST(BinderStability, RemoteLowStabilityServer) {
- sp<IBinder> remoteBinder = android::defaultServiceManager()->getService(kCompilationUnitServer);
- auto remoteServer = interface_cast<IBinderStabilityTest>(remoteBinder);
+static AIBinder_Class* kNdkBadStableBinder =
+ AIBinder_Class_define(String8(BadStableBinder::kDescriptor).c_str(),
+ NdkBadStableBinder_Class_onCreate,
+ NdkBadStableBinder_Class_onDestroy,
+ NdkBadStableBinder_Class_onTransact);
+
+// for testing only to get around __ANDROID_VNDK__ guard.
+extern "C" void AIBinder_markVendorStability(AIBinder* binder); // <- BAD DO NOT COPY
+
+TEST(BinderStability, NdkCantCallVendorBinderInSystemContext) {
+ SpAIBinder binder = SpAIBinder(AServiceManager_getService(
+ String8(kSystemStabilityServer).c_str()));
+
+ std::shared_ptr<aidl::IBinderStabilityTest> remoteServer =
+ aidl::IBinderStabilityTest::fromBinder(binder);
ASSERT_NE(nullptr, remoteServer.get());
- ASSERT_NE(nullptr, IInterface::asBinder(remoteServer)->remoteBinder());
- checkSystemStabilityBinder(remoteServer);
-}
+ SpAIBinder comp = SpAIBinder(AIBinder_new(kNdkBadStableBinder, nullptr /*args*/));
+ EXPECT_TRUE(remoteServer->sendBinder(comp).isOk());
+ EXPECT_TRUE(remoteServer->sendAndCallBinder(comp).isOk());
+ EXPECT_TRUE(NdkBadStableBinder_getUserData(comp.get())->gotUserTransaction);
-TEST(BinderStability, RemoteVintfServer) {
- sp<IBinder> remoteBinder = android::defaultServiceManager()->getService(kVintfServer);
- auto remoteServer = interface_cast<IBinderStabilityTest>(remoteBinder);
-
- ASSERT_NE(nullptr, remoteServer.get());
- ASSERT_NE(nullptr, IInterface::asBinder(remoteServer)->remoteBinder());
-
- checkSystemStabilityBinder(remoteServer);
+ SpAIBinder vendor = SpAIBinder(AIBinder_new(kNdkBadStableBinder, nullptr /*args*/));
+ AIBinder_markVendorStability(vendor.get());
+ EXPECT_TRUE(remoteServer->sendBinder(vendor).isOk());
+ EXPECT_FALSE(remoteServer->sendAndCallBinder(vendor).isOk());
+ EXPECT_FALSE(NdkBadStableBinder_getUserData(vendor.get())->gotUserTransaction);
}
class MarksStabilityInConstructor : public BBinder {
@@ -168,7 +252,7 @@
static bool gDestructed;
MarksStabilityInConstructor() {
- internal::Stability::markCompilationUnit(this);
+ Stability::markCompilationUnit(this);
}
~MarksStabilityInConstructor() {
gDestructed = true;
@@ -191,6 +275,14 @@
ASSERT_TRUE(MarksStabilityInConstructor::gDestructed);
}
+TEST(BinderStability, RemarkDies) {
+ ASSERT_DEATH({
+ sp<IBinder> binder = new BBinder();
+ Stability::markCompilationUnit(binder.get()); // <-- only called for tests
+ Stability::markVndk(binder.get()); // <-- only called for tests
+ }, "Should only mark known object.");
+}
+
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
@@ -198,16 +290,8 @@
// child process
prctl(PR_SET_PDEATHSIG, SIGHUP);
- sp<IBinder> noStability = new BadStabilityTester;
- android::defaultServiceManager()->addService(kNoStabilityServer, noStability);
-
- sp<IBinder> compil = new BadStabilityTester;
- internal::Stability::markCompilationUnit(compil.get());
- android::defaultServiceManager()->addService(kCompilationUnitServer, compil);
-
- sp<IBinder> vintf = new BadStabilityTester;
- internal::Stability::markVintf(vintf.get());
- android::defaultServiceManager()->addService(kVintfServer, vintf);
+ sp<IBinder> server = new MyBinderStabilityTest;
+ android::defaultServiceManager()->addService(kSystemStabilityServer, server);
IPCThreadState::self()->joinThreadPool(true);
exit(1); // should not reach
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index ff1ba0a..386f731 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -410,6 +410,19 @@
bgSurface->expectTap(1, 1);
}
+TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets_overflow) {
+ std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);
+ // In case we pass the very big inset without any checking.
+ fgSurface->mInputInfo.surfaceInset = INT32_MAX;
+ fgSurface->showAt(100, 100);
+
+ fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); });
+
+ // expect no crash for overflow, and inset size to be clamped to surface size
+ injectTap(202, 202);
+ fgSurface->expectTap(1, 1);
+}
+
// Ensure we ignore transparent region when getting screen bounds when positioning input frame.
TEST_F(InputSurfacesTest, input_ignores_transparent_region) {
std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index c11b88e..14ed73d 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -299,14 +299,10 @@
}
void SensorService::setSensorAccess(uid_t uid, bool hasAccess) {
- SortedVector< sp<SensorEventConnection> > activeConnections;
- populateActiveConnections(&activeConnections);
- {
- Mutex::Autolock _l(mLock);
- for (size_t i = 0 ; i < activeConnections.size(); i++) {
- if (activeConnections[i] != nullptr && activeConnections[i]->getUid() == uid) {
- activeConnections[i]->setSensorAccess(hasAccess);
- }
+ ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
+ for (const sp<SensorEventConnection>& conn : connLock.getActiveConnections()) {
+ if (conn->getUid() == uid) {
+ conn->setSensorAccess(hasAccess);
}
}
}
@@ -360,7 +356,7 @@
if (args.size() > 2) {
return INVALID_OPERATION;
}
- Mutex::Autolock _l(mLock);
+ ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
SensorDevice& dev(SensorDevice::getInstance());
if (args.size() == 2 && args[0] == String16("restrict")) {
// If already in restricted mode. Ignore.
@@ -374,7 +370,7 @@
mCurrentOperatingMode = RESTRICTED;
// temporarily stop all sensor direct report and disable sensors
- disableAllSensorsLocked();
+ disableAllSensorsLocked(&connLock);
mWhiteListedPackage.setTo(String8(args[1]));
return status_t(NO_ERROR);
} else if (args.size() == 1 && args[0] == String16("enable")) {
@@ -382,7 +378,7 @@
if (mCurrentOperatingMode == RESTRICTED) {
mCurrentOperatingMode = NORMAL;
// enable sensors and recover all sensor direct report
- enableAllSensorsLocked();
+ enableAllSensorsLocked(&connLock);
}
if (mCurrentOperatingMode == DATA_INJECTION) {
resetToNormalModeLocked();
@@ -473,22 +469,18 @@
result.appendFormat("Sensor Privacy: %s\n",
mSensorPrivacyPolicy->isSensorPrivacyEnabled() ? "enabled" : "disabled");
- result.appendFormat("%zd active connections\n", mActiveConnections.size());
- for (size_t i=0 ; i < mActiveConnections.size() ; i++) {
- sp<SensorEventConnection> connection(mActiveConnections[i].promote());
- if (connection != nullptr) {
- result.appendFormat("Connection Number: %zu \n", i);
- connection->dump(result);
- }
+ const auto& activeConnections = connLock.getActiveConnections();
+ result.appendFormat("%zd active connections\n", activeConnections.size());
+ for (size_t i=0 ; i < activeConnections.size() ; i++) {
+ result.appendFormat("Connection Number: %zu \n", i);
+ activeConnections[i]->dump(result);
}
- result.appendFormat("%zd direct connections\n", mDirectConnections.size());
- for (size_t i = 0 ; i < mDirectConnections.size() ; i++) {
- sp<SensorDirectConnection> connection(mDirectConnections[i].promote());
- if (connection != nullptr) {
- result.appendFormat("Direct connection %zu:\n", i);
- connection->dump(result);
- }
+ const auto& directConnections = connLock.getDirectConnections();
+ result.appendFormat("%zd direct connections\n", directConnections.size());
+ for (size_t i = 0 ; i < directConnections.size() ; i++) {
+ result.appendFormat("Direct connection %zu:\n", i);
+ directConnections[i]->dump(result);
}
result.appendFormat("Previous Registrations:\n");
@@ -515,17 +507,14 @@
}
void SensorService::disableAllSensors() {
- Mutex::Autolock _l(mLock);
- disableAllSensorsLocked();
+ ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
+ disableAllSensorsLocked(&connLock);
}
-void SensorService::disableAllSensorsLocked() {
+void SensorService::disableAllSensorsLocked(ConnectionSafeAutolock* connLock) {
SensorDevice& dev(SensorDevice::getInstance());
- for (auto &i : mDirectConnections) {
- sp<SensorDirectConnection> connection(i.promote());
- if (connection != nullptr) {
- connection->stopAll(true /* backupRecord */);
- }
+ for (const sp<SensorDirectConnection>& connection : connLock->getDirectConnections()) {
+ connection->stopAll(true /* backupRecord */);
}
dev.disableAllSensors();
// Clear all pending flush connections for all active sensors. If one of the active
@@ -537,11 +526,11 @@
}
void SensorService::enableAllSensors() {
- Mutex::Autolock _l(mLock);
- enableAllSensorsLocked();
+ ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
+ enableAllSensorsLocked(&connLock);
}
-void SensorService::enableAllSensorsLocked() {
+void SensorService::enableAllSensorsLocked(ConnectionSafeAutolock* connLock) {
// sensors should only be enabled if the operating state is not restricted and sensor
// privacy is not enabled.
if (mCurrentOperatingMode == RESTRICTED || mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
@@ -552,14 +541,12 @@
}
SensorDevice& dev(SensorDevice::getInstance());
dev.enableAllSensors();
- for (auto &i : mDirectConnections) {
- sp<SensorDirectConnection> connection(i.promote());
- if (connection != nullptr) {
- connection->recoverAll();
- }
+ for (const sp<SensorDirectConnection>& connection : connLock->getDirectConnections()) {
+ connection->recoverAll();
}
}
+
// NOTE: This is a remote API - make sure all args are validated
status_t SensorService::shellCommand(int in, int out, int err, Vector<String16>& args) {
if (!checkCallingPermission(sManageSensorsPermission, nullptr, nullptr)) {
@@ -734,17 +721,8 @@
for (int i = 0; i < count; i++) {
mSensorEventBuffer[i].flags = 0;
}
+ ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
- // Make a copy of the connection vector as some connections may be removed during the course
- // of this loop (especially when one-shot sensor events are present in the sensor_event
- // buffer). Promote all connections to StrongPointers before the lock is acquired. If the
- // destructor of the sp gets called when the lock is acquired, it may result in a deadlock
- // as ~SensorEventConnection() needs to acquire mLock again for cleanup. So copy all the
- // strongPointers to a vector before the lock is acquired.
- SortedVector< sp<SensorEventConnection> > activeConnections;
- populateActiveConnections(&activeConnections);
-
- Mutex::Autolock _l(mLock);
// Poll has returned. Hold a wakelock if one of the events is from a wake up sensor. The
// rest of this loop is under a critical section protected by mLock. Acquiring a wakeLock,
// sending events to clients (incrementing SensorEventConnection::mWakeLockRefCount) should
@@ -818,6 +796,10 @@
}
}
+ // Cache the list of active connections, since we use it in multiple places below but won't
+ // modify it here
+ const std::vector<sp<SensorEventConnection>> activeConnections = connLock.getActiveConnections();
+
for (int i = 0; i < count; ++i) {
// Map flush_complete_events in the buffer to SensorEventConnections which called flush
// on the hardware sensor. mapFlushEventsToConnections[i] will be the
@@ -869,11 +851,8 @@
ALOGE("Dynamic sensor release error.");
}
- size_t numConnections = activeConnections.size();
- for (size_t i=0 ; i < numConnections; ++i) {
- if (activeConnections[i] != nullptr) {
- activeConnections[i]->removeSensor(handle);
- }
+ for (const sp<SensorEventConnection>& connection : activeConnections) {
+ connection->removeSensor(handle);
}
}
}
@@ -882,18 +861,14 @@
// Send our events to clients. Check the state of wake lock for each client and release the
// lock if none of the clients need it.
bool needsWakeLock = false;
- size_t numConnections = activeConnections.size();
- for (size_t i=0 ; i < numConnections; ++i) {
- if (activeConnections[i] != nullptr) {
- activeConnections[i]->sendEvents(mSensorEventBuffer, count, mSensorEventScratch,
- mMapFlushEventsToConnections);
- needsWakeLock |= activeConnections[i]->needsWakeLock();
- // If the connection has one-shot sensors, it may be cleaned up after first trigger.
- // Early check for one-shot sensors.
- if (activeConnections[i]->hasOneShotSensors()) {
- cleanupAutoDisabledSensorLocked(activeConnections[i], mSensorEventBuffer,
- count);
- }
+ for (const sp<SensorEventConnection>& connection : activeConnections) {
+ connection->sendEvents(mSensorEventBuffer, count, mSensorEventScratch,
+ mMapFlushEventsToConnections);
+ needsWakeLock |= connection->needsWakeLock();
+ // If the connection has one-shot sensors, it may be cleaned up after first trigger.
+ // Early check for one-shot sensors.
+ if (connection->hasOneShotSensors()) {
+ cleanupAutoDisabledSensorLocked(connection, mSensorEventBuffer, count);
}
}
@@ -912,17 +887,11 @@
}
void SensorService::resetAllWakeLockRefCounts() {
- SortedVector< sp<SensorEventConnection> > activeConnections;
- populateActiveConnections(&activeConnections);
- {
- Mutex::Autolock _l(mLock);
- for (size_t i=0 ; i < activeConnections.size(); ++i) {
- if (activeConnections[i] != nullptr) {
- activeConnections[i]->resetWakeLockRefCount();
- }
- }
- setWakeLockAcquiredLocked(false);
+ ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
+ for (const sp<SensorEventConnection>& connection : connLock.getActiveConnections()) {
+ connection->resetWakeLockRefCount();
}
+ setWakeLockAcquiredLocked(false);
}
void SensorService::setWakeLockAcquiredLocked(bool acquire) {
@@ -1144,9 +1113,7 @@
sp<SensorEventConnection> result(new SensorEventConnection(this, uid, connPackageName,
requestedMode == DATA_INJECTION, connOpPackageName, hasSensorAccess));
if (requestedMode == DATA_INJECTION) {
- if (mActiveConnections.indexOf(result) < 0) {
- mActiveConnections.add(result);
- }
+ mConnectionHolder.addEventConnectionIfNotPresent(result);
// Add the associated file descriptor to the Looper for polling whenever there is data to
// be injected.
result->updateLooperRegistration(mLooper);
@@ -1162,7 +1129,7 @@
sp<ISensorEventConnection> SensorService::createSensorDirectConnection(
const String16& opPackageName, uint32_t size, int32_t type, int32_t format,
const native_handle *resource) {
- Mutex::Autolock _l(mLock);
+ ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
// No new direct connections are allowed when sensor privacy is enabled
if (mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
@@ -1190,9 +1157,8 @@
}
// check for duplication
- for (auto &i : mDirectConnections) {
- sp<SensorDirectConnection> connection(i.promote());
- if (connection != nullptr && connection->isEquivalent(&mem)) {
+ for (const sp<SensorDirectConnection>& connection : connLock.getDirectConnections()) {
+ if (connection->isEquivalent(&mem)) {
ALOGE("Duplicate create channel request for the same share memory");
return nullptr;
}
@@ -1229,7 +1195,7 @@
return nullptr;
}
- SensorDirectConnection* conn = nullptr;
+ sp<SensorDirectConnection> conn;
SensorDevice& dev(SensorDevice::getInstance());
int channelHandle = dev.registerDirectChannel(&mem);
@@ -1246,7 +1212,7 @@
} else {
// add to list of direct connections
// sensor service should never hold pointer or sp of SensorDirectConnection object.
- mDirectConnections.add(wp<SensorDirectConnection>(conn));
+ mConnectionHolder.addDirectConnection(conn);
}
return conn;
}
@@ -1358,7 +1324,7 @@
}
void SensorService::cleanupConnection(SensorEventConnection* c) {
- Mutex::Autolock _l(mLock);
+ ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
const wp<SensorEventConnection> connection(c);
size_t size = mActiveSensors.size();
ALOGD_IF(DEBUG_CONNECTIONS, "%zu active sensors", size);
@@ -1391,10 +1357,10 @@
}
}
c->updateLooperRegistration(mLooper);
- mActiveConnections.remove(connection);
+ mConnectionHolder.removeEventConnection(connection);
BatteryService::cleanup(c->getUid());
if (c->needsWakeLock()) {
- checkWakeLockStateLocked();
+ checkWakeLockStateLocked(&connLock);
}
{
@@ -1414,7 +1380,7 @@
SensorDevice& dev(SensorDevice::getInstance());
dev.unregisterDirectChannel(c->getHalChannelHandle());
- mDirectConnections.remove(c);
+ mConnectionHolder.removeDirectConnection(c);
}
sp<SensorInterface> SensorService::getSensorInterfaceFromHandle(int handle) const {
@@ -1433,7 +1399,7 @@
return BAD_VALUE;
}
- Mutex::Autolock _l(mLock);
+ ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
if (mCurrentOperatingMode != NORMAL
&& !isWhiteListedPackage(connection->getPackageName())) {
return INVALID_OPERATION;
@@ -1484,7 +1450,7 @@
}
connection->sendEvents(&event, 1, nullptr);
if (!connection->needsWakeLock() && mWakeLockAcquired) {
- checkWakeLockStateLocked();
+ checkWakeLockStateLocked(&connLock);
}
}
}
@@ -1497,9 +1463,7 @@
BatteryService::enableSensor(connection->getUid(), handle);
// the sensor was added (which means it wasn't already there)
// so, see if this connection becomes active
- if (mActiveConnections.indexOf(connection) < 0) {
- mActiveConnections.add(connection);
- }
+ mConnectionHolder.addEventConnectionIfNotPresent(connection);
} else {
ALOGW("sensor %08x already enabled in connection %p (ignoring)",
handle, connection.get());
@@ -1603,7 +1567,7 @@
}
if (connection->hasAnySensor() == false) {
connection->updateLooperRegistration(mLooper);
- mActiveConnections.remove(connection);
+ mConnectionHolder.removeEventConnection(connection);
}
// see if this sensor becomes inactive
if (rec->removeConnection(connection)) {
@@ -1762,22 +1726,19 @@
}
void SensorService::checkWakeLockState() {
- Mutex::Autolock _l(mLock);
- checkWakeLockStateLocked();
+ ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
+ checkWakeLockStateLocked(&connLock);
}
-void SensorService::checkWakeLockStateLocked() {
+void SensorService::checkWakeLockStateLocked(ConnectionSafeAutolock* connLock) {
if (!mWakeLockAcquired) {
return;
}
bool releaseLock = true;
- for (size_t i=0 ; i<mActiveConnections.size() ; i++) {
- sp<SensorEventConnection> connection(mActiveConnections[i].promote());
- if (connection != nullptr) {
- if (connection->needsWakeLock()) {
- releaseLock = false;
- break;
- }
+ for (const sp<SensorEventConnection>& connection : connLock->getActiveConnections()) {
+ if (connection->needsWakeLock()) {
+ releaseLock = false;
+ break;
}
}
if (releaseLock) {
@@ -1793,17 +1754,6 @@
}
}
-void SensorService::populateActiveConnections(
- SortedVector< sp<SensorEventConnection> >* activeConnections) {
- Mutex::Autolock _l(mLock);
- for (size_t i=0 ; i < mActiveConnections.size(); ++i) {
- sp<SensorEventConnection> connection(mActiveConnections[i].promote());
- if (connection != nullptr) {
- activeConnections->add(connection);
- }
- }
-}
-
bool SensorService::isWhiteListedPackage(const String8& packageName) {
return (packageName.contains(mWhiteListedPackage.string()));
}
@@ -1938,4 +1888,62 @@
}
return binder::Status::ok();
}
-}; // namespace android
+
+SensorService::ConnectionSafeAutolock::ConnectionSafeAutolock(
+ SensorService::SensorConnectionHolder& holder, Mutex& mutex)
+ : mConnectionHolder(holder), mAutolock(mutex) {}
+
+template<typename ConnectionType>
+const std::vector<sp<ConnectionType>>& SensorService::ConnectionSafeAutolock::getConnectionsHelper(
+ const SortedVector<wp<ConnectionType>>& connectionList,
+ std::vector<std::vector<sp<ConnectionType>>>* referenceHolder) {
+ referenceHolder->emplace_back();
+ std::vector<sp<ConnectionType>>& connections = referenceHolder->back();
+ for (const wp<ConnectionType>& weakConnection : connectionList){
+ sp<ConnectionType> connection = weakConnection.promote();
+ if (connection != nullptr) {
+ connections.push_back(std::move(connection));
+ }
+ }
+ return connections;
+}
+
+const std::vector<sp<SensorService::SensorEventConnection>>&
+ SensorService::ConnectionSafeAutolock::getActiveConnections() {
+ return getConnectionsHelper(mConnectionHolder.mActiveConnections,
+ &mReferencedActiveConnections);
+}
+
+const std::vector<sp<SensorService::SensorDirectConnection>>&
+ SensorService::ConnectionSafeAutolock::getDirectConnections() {
+ return getConnectionsHelper(mConnectionHolder.mDirectConnections,
+ &mReferencedDirectConnections);
+}
+
+void SensorService::SensorConnectionHolder::addEventConnectionIfNotPresent(
+ const sp<SensorService::SensorEventConnection>& connection) {
+ if (mActiveConnections.indexOf(connection) < 0) {
+ mActiveConnections.add(connection);
+ }
+}
+
+void SensorService::SensorConnectionHolder::removeEventConnection(
+ const wp<SensorService::SensorEventConnection>& connection) {
+ mActiveConnections.remove(connection);
+}
+
+void SensorService::SensorConnectionHolder::addDirectConnection(
+ const sp<SensorService::SensorDirectConnection>& connection) {
+ mDirectConnections.add(connection);
+}
+
+void SensorService::SensorConnectionHolder::removeDirectConnection(
+ const wp<SensorService::SensorDirectConnection>& connection) {
+ mDirectConnections.remove(connection);
+}
+
+SensorService::ConnectionSafeAutolock SensorService::SensorConnectionHolder::lock(Mutex& mutex) {
+ return ConnectionSafeAutolock(*this, mutex);
+}
+
+} // namespace android
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index e6ec96d..060b5eb 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -20,6 +20,7 @@
#include "SensorList.h"
#include "RecentEventLogger.h"
+#include <android-base/macros.h>
#include <binder/AppOpsManager.h>
#include <binder/BinderService.h>
#include <binder/IUidObserver.h>
@@ -42,6 +43,7 @@
#include <sys/types.h>
#include <unordered_map>
#include <unordered_set>
+#include <vector>
#if __clang__
// Clang warns about SensorEventConnection::dump hiding BBinder::dump. The cause isn't fixable
@@ -95,10 +97,67 @@
friend class BinderService<SensorService>;
// nested class/struct for internal use
- class SensorRecord;
+ class ConnectionSafeAutolock;
+ class SensorConnectionHolder;
class SensorEventAckReceiver;
+ class SensorRecord;
class SensorRegistrationInfo;
+ // Promoting a SensorEventConnection or SensorDirectConnection from wp to sp must be done with
+ // mLock held, but destroying that sp must be done unlocked to avoid a race condition that
+ // causes a deadlock (remote dies while we hold a local sp, then our decStrong() call invokes
+ // the dtor -> cleanupConnection() tries to re-lock the mutex). This class ensures safe usage
+ // by wrapping a Mutex::Autolock on SensorService's mLock, plus vectors that hold promoted sp<>
+ // references until the lock is released, when they are safely destroyed.
+ // All read accesses to the connection lists in mConnectionHolder must be done via this class.
+ class ConnectionSafeAutolock final {
+ public:
+ // Returns a list of non-null promoted connection references
+ const std::vector<sp<SensorEventConnection>>& getActiveConnections();
+ const std::vector<sp<SensorDirectConnection>>& getDirectConnections();
+
+ private:
+ // Constructed via SensorConnectionHolder::lock()
+ friend class SensorConnectionHolder;
+ explicit ConnectionSafeAutolock(SensorConnectionHolder& holder, Mutex& mutex);
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ConnectionSafeAutolock);
+
+ // NOTE: Order of these members is important, as the destructor for non-static members
+ // get invoked in the reverse order of their declaration. Here we are relying on the
+ // Autolock to be destroyed *before* the vectors, so the sp<> objects are destroyed without
+ // the lock held, which avoids the deadlock.
+ SensorConnectionHolder& mConnectionHolder;
+ std::vector<std::vector<sp<SensorEventConnection>>> mReferencedActiveConnections;
+ std::vector<std::vector<sp<SensorDirectConnection>>> mReferencedDirectConnections;
+ Mutex::Autolock mAutolock;
+
+ template<typename ConnectionType>
+ const std::vector<sp<ConnectionType>>& getConnectionsHelper(
+ const SortedVector<wp<ConnectionType>>& connectionList,
+ std::vector<std::vector<sp<ConnectionType>>>* referenceHolder);
+ };
+
+ // Encapsulates the collection of active SensorEventConection and SensorDirectConnection
+ // references. Write access is done through this class with mLock held, but all read access
+ // must be routed through ConnectionSafeAutolock.
+ class SensorConnectionHolder {
+ public:
+ void addEventConnectionIfNotPresent(const sp<SensorEventConnection>& connection);
+ void removeEventConnection(const wp<SensorEventConnection>& connection);
+
+ void addDirectConnection(const sp<SensorDirectConnection>& connection);
+ void removeDirectConnection(const wp<SensorDirectConnection>& connection);
+
+ // Pass in the mutex that protects this connection holder; acquires the lock and returns an
+ // object that can be used to safely read the lists of connections
+ ConnectionSafeAutolock lock(Mutex& mutex);
+
+ private:
+ friend class ConnectionSafeAutolock;
+ SortedVector< wp<SensorEventConnection> > mActiveConnections;
+ SortedVector< wp<SensorDirectConnection> > mDirectConnections;
+ };
+
// If accessing a sensor we need to make sure the UID has access to it. If
// the app UID is idle then it cannot access sensors and gets no trigger
// events, no on-change events, flush event behavior does not change, and
@@ -250,7 +309,7 @@
// method checks whether all the events from these wake up sensors have been delivered to the
// corresponding applications, if yes the wakelock is released.
void checkWakeLockState();
- void checkWakeLockStateLocked();
+ void checkWakeLockStateLocked(ConnectionSafeAutolock* connLock);
bool isWakeLockAcquired();
bool isWakeUpSensorEvent(const sensors_event_t& event) const;
@@ -268,10 +327,6 @@
// Send events from the event cache for this particular connection.
void sendEventsFromCache(const sp<SensorEventConnection>& connection);
- // Promote all weak referecences in mActiveConnections vector to strong references and add them
- // to the output vector.
- void populateActiveConnections( SortedVector< sp<SensorEventConnection> >* activeConnections);
-
// If SensorService is operating in RESTRICTED mode, only select whitelisted packages are
// allowed to register for or call flush on sensors. Typically only cts test packages are
// allowed.
@@ -306,10 +361,10 @@
// temporarily stops all active direct connections and disables all sensors
void disableAllSensors();
- void disableAllSensorsLocked();
+ void disableAllSensorsLocked(ConnectionSafeAutolock* connLock);
// restarts the previously stopped direct connections and enables all sensors
void enableAllSensors();
- void enableAllSensorsLocked();
+ void enableAllSensorsLocked(ConnectionSafeAutolock* connLock);
static uint8_t sHmacGlobalKey[128];
static bool sHmacGlobalKeyIsValid;
@@ -327,12 +382,13 @@
mutable Mutex mLock;
DefaultKeyedVector<int, SensorRecord*> mActiveSensors;
std::unordered_set<int> mActiveVirtualSensors;
- SortedVector< wp<SensorEventConnection> > mActiveConnections;
+ SensorConnectionHolder mConnectionHolder;
bool mWakeLockAcquired;
sensors_event_t *mSensorEventBuffer, *mSensorEventScratch;
+ // WARNING: these SensorEventConnection instances must not be promoted to sp, except via
+ // modification to add support for them in ConnectionSafeAutolock
wp<const SensorEventConnection> * mMapFlushEventsToConnections;
std::unordered_map<int, SensorServiceUtil::RecentEventLogger*> mRecentEvent;
- SortedVector< wp<SensorDirectConnection> > mDirectConnections;
Mode mCurrentOperatingMode;
// This packagaName is set when SensorService is in RESTRICTED or DATA_INJECTION mode. Only
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 965d8f4..afb9cec 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -138,7 +138,6 @@
"Layer.cpp",
"LayerProtoHelper.cpp",
"LayerRejecter.cpp",
- "LayerStats.cpp",
"LayerVector.cpp",
"MonitoredProducer.cpp",
"NativeWindowSurface.cpp",
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 87bec11..13c748f 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -167,7 +167,7 @@
}
return std::nullopt;
}
- bool blackOutLayer = (isProtected() && !targetSettings.supportProtectedContent) ||
+ bool blackOutLayer = (isProtected() && !targetSettings.supportsProtectedContent) ||
(isSecure() && !targetSettings.isSecure);
const State& s(getDrawingState());
auto& layer = *result;
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index c86acf0..7a0f82b 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -48,7 +48,7 @@
class BufferLayer : public Layer {
public:
explicit BufferLayer(const LayerCreationArgs& args);
- ~BufferLayer() override;
+ virtual ~BufferLayer() override;
// -----------------------------------------------------------------------
// Overriden from Layer
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 0f26211..611decf 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -51,6 +51,16 @@
mCurrentState.dataspace = ui::Dataspace::V0_SRGB;
}
+BufferStateLayer::~BufferStateLayer() {
+ if (mActiveBuffer != nullptr) {
+ // Ensure that mActiveBuffer is uncached from RenderEngine here, as
+ // RenderEngine may have been using the buffer as an external texture
+ // after the client uncached the buffer.
+ auto& engine(mFlinger->getRenderEngine());
+ engine.unbindExternalTextureBuffer(mActiveBuffer->getId());
+ }
+}
+
// -----------------------------------------------------------------------
// Interface implementation for Layer
// -----------------------------------------------------------------------
@@ -604,10 +614,6 @@
}
}
-void BufferStateLayer::bufferErased(const client_cache_t& clientCacheId) {
- mFlinger->getRenderEngine().unbindExternalTextureBuffer(clientCacheId.id);
-}
-
void BufferStateLayer::HwcSlotGenerator::bufferErased(const client_cache_t& clientCacheId) {
std::lock_guard lock(mMutex);
if (!clientCacheId.isValid()) {
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 5e5b9b0..6db91ef 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -35,6 +35,8 @@
public:
explicit BufferStateLayer(const LayerCreationArgs&);
+ ~BufferStateLayer() override;
+
// -----------------------------------------------------------------------
// Interface implementation for Layer
// -----------------------------------------------------------------------
@@ -102,9 +104,6 @@
bool fenceHasSignaled() const override;
bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override;
- // Inherit from ClientCache::ErasedRecipient
- void bufferErased(const client_cache_t& clientCacheId) override;
-
private:
nsecs_t getDesiredPresentTime() override;
std::shared_ptr<FenceTime> getCurrentFenceTime() const override;
diff --git a/services/surfaceflinger/ClientCache.cpp b/services/surfaceflinger/ClientCache.cpp
index 77f2f57..16fe27c 100644
--- a/services/surfaceflinger/ClientCache.cpp
+++ b/services/surfaceflinger/ClientCache.cpp
@@ -55,16 +55,16 @@
return true;
}
-void ClientCache::add(const client_cache_t& cacheId, const sp<GraphicBuffer>& buffer) {
+bool ClientCache::add(const client_cache_t& cacheId, const sp<GraphicBuffer>& buffer) {
auto& [processToken, id] = cacheId;
if (processToken == nullptr) {
ALOGE("failed to cache buffer: invalid process token");
- return;
+ return false;
}
if (!buffer) {
ALOGE("failed to cache buffer: invalid buffer");
- return;
+ return false;
}
std::lock_guard lock(mMutex);
@@ -77,13 +77,13 @@
token = processToken.promote();
if (!token) {
ALOGE("failed to cache buffer: invalid token");
- return;
+ return false;
}
status_t err = token->linkToDeath(mDeathRecipient);
if (err != NO_ERROR) {
ALOGE("failed to cache buffer: could not link to death");
- return;
+ return false;
}
auto [itr, success] =
mBuffers.emplace(processToken, std::unordered_map<uint64_t, ClientCacheBuffer>());
@@ -95,10 +95,11 @@
if (processBuffers.size() > BUFFER_CACHE_MAX_SIZE) {
ALOGE("failed to cache buffer: cache is full");
- return;
+ return false;
}
processBuffers[id].buffer = buffer;
+ return true;
}
void ClientCache::erase(const client_cache_t& cacheId) {
@@ -139,16 +140,17 @@
return buf->buffer;
}
-void ClientCache::registerErasedRecipient(const client_cache_t& cacheId,
+bool ClientCache::registerErasedRecipient(const client_cache_t& cacheId,
const wp<ErasedRecipient>& recipient) {
std::lock_guard lock(mMutex);
ClientCacheBuffer* buf = nullptr;
if (!getBuffer(cacheId, &buf)) {
ALOGE("failed to register erased recipient, could not retrieve buffer");
- return;
+ return false;
}
buf->recipients.insert(recipient);
+ return true;
}
void ClientCache::unregisterErasedRecipient(const client_cache_t& cacheId,
diff --git a/services/surfaceflinger/ClientCache.h b/services/surfaceflinger/ClientCache.h
index 9f057c4..aa6c80d 100644
--- a/services/surfaceflinger/ClientCache.h
+++ b/services/surfaceflinger/ClientCache.h
@@ -36,7 +36,7 @@
public:
ClientCache();
- void add(const client_cache_t& cacheId, const sp<GraphicBuffer>& buffer);
+ bool add(const client_cache_t& cacheId, const sp<GraphicBuffer>& buffer);
void erase(const client_cache_t& cacheId);
sp<GraphicBuffer> get(const client_cache_t& cacheId);
@@ -48,7 +48,7 @@
virtual void bufferErased(const client_cache_t& clientCacheId) = 0;
};
- void registerErasedRecipient(const client_cache_t& cacheId,
+ bool registerErasedRecipient(const client_cache_t& cacheId,
const wp<ErasedRecipient>& recipient);
void unregisterErasedRecipient(const client_cache_t& cacheId,
const wp<ErasedRecipient>& recipient);
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index 6f076ad..ae6bdbc 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -94,6 +94,7 @@
"tests/LayerTest.cpp",
"tests/MockHWC2.cpp",
"tests/MockHWComposer.cpp",
+ "tests/MockPowerAdvisor.cpp",
"tests/OutputTest.cpp",
"tests/OutputLayerTest.cpp",
"tests/RenderSurfaceTest.cpp",
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
index 0b6b4e4..0778936 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
@@ -20,6 +20,7 @@
#include <optional>
#include "DisplayHardware/DisplayIdentification.h"
+#include "DisplayHardware/PowerAdvisor.h"
namespace android::compositionengine {
@@ -37,6 +38,10 @@
// Identifies the display to the HWC, if composition is supported by it
std::optional<DisplayId> displayId;
+
+ // Optional pointer to the power advisor interface, if one is needed for
+ // this display.
+ Hwc2::PowerAdvisor* powerAdvisor = nullptr;
};
/**
@@ -68,6 +73,10 @@
mArgs.displayId = displayId;
return *this;
}
+ DisplayCreationArgsBuilder& setPowerAdvisor(Hwc2::PowerAdvisor* powerAdvisor) {
+ mArgs.powerAdvisor = powerAdvisor;
+ return *this;
+ }
private:
DisplayCreationArgs mArgs;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
index 94fab1f..2a901ae 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
@@ -59,7 +59,7 @@
const bool isSecure;
// If set to true, the target buffer has protected content support.
- const bool supportProtectedContent;
+ const bool supportsProtectedContent;
// Modified by each call to prepareClientComposition to indicate the
// region of the target buffer that should be cleared.
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
index d96d58c..d5763d5 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
@@ -116,6 +116,12 @@
// The color transform
mat4 colorTransform;
bool colorTransformIsIdentity{true};
+
+ // True if the layer is completely opaque
+ bool isOpaque{true};
+
+ // True if the layer has protected content
+ bool hasProtectedContent{false};
};
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index 4dfcfa4..f73304d 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -22,6 +22,7 @@
#include <unordered_map>
#include <math/mat4.h>
+#include <renderengine/LayerSettings.h>
#include <ui/Fence.h>
#include <ui/GraphicTypes.h>
#include <ui/Region.h>
@@ -156,6 +157,12 @@
// Prepares a frame for display
virtual void prepareFrame() = 0;
+ // Performs client composition as needed for layers on the output. The
+ // output fence is set to a fence to signal when client composition is
+ // finished.
+ // Returns false if client composition cannot be performed.
+ virtual bool composeSurfaces(const Region& debugFence, base::unique_fd* outReadyFence) = 0;
+
// Posts the new frame, and sets release fences.
virtual void postFramebuffer() = 0;
@@ -163,7 +170,14 @@
virtual void setDisplayColorProfile(std::unique_ptr<DisplayColorProfile>) = 0;
virtual void setRenderSurface(std::unique_ptr<RenderSurface>) = 0;
virtual void chooseCompositionStrategy() = 0;
+ virtual bool getSkipColorTransform() const = 0;
virtual FrameFences presentAndGetFrameFences() = 0;
+ virtual std::vector<renderengine::LayerSettings> generateClientCompositionRequests(
+ bool supportsProtectedContent, Region& clearRegion) = 0;
+ virtual void appendRegionFlashRequests(
+ const Region& flashRegion,
+ std::vector<renderengine::LayerSettings>& clientCompositionLayers) = 0;
+ virtual void setExpensiveRenderingExpected(bool enabled) = 0;
};
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
index d7f00a9..5f62b32 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
@@ -93,6 +93,9 @@
// Applies a HWC device layer request
virtual void applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest request) = 0;
+ // Returns true if the composition settings scale pixels
+ virtual bool needsFiltering() const = 0;
+
// Debugging
virtual void dump(std::string& result) const = 0;
};
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
index 795061a..36e4aac 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
@@ -23,6 +23,7 @@
#include "DisplayHardware/DisplayIdentification.h"
#include "DisplayHardware/HWComposer.h"
+#include "DisplayHardware/PowerAdvisor.h"
namespace android::compositionengine {
@@ -42,7 +43,9 @@
void setColorTransform(const mat4&) override;
void setColorMode(ui::ColorMode, ui::Dataspace, ui::RenderIntent, ui::Dataspace) override;
void chooseCompositionStrategy() override;
+ bool getSkipColorTransform() const override;
compositionengine::Output::FrameFences presentAndGetFrameFences() override;
+ void setExpensiveRenderingExpected(bool) override;
// compositionengine::Display overrides
const std::optional<DisplayId>& getId() const override;
@@ -65,9 +68,11 @@
private:
const bool mIsVirtual;
std::optional<DisplayId> mId;
+ Hwc2::PowerAdvisor* const mPowerAdvisor{nullptr};
};
std::shared_ptr<Display> createDisplay(const compositionengine::CompositionEngine&,
compositionengine::DisplayCreationArgs&&);
+
} // namespace impl
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index 5f4a764..3972f2b 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -77,6 +77,7 @@
void beginFrame() override;
void prepareFrame() override;
+ bool composeSurfaces(const Region&, base::unique_fd*) override;
void postFramebuffer() override;
// Testing
@@ -86,7 +87,13 @@
protected:
const CompositionEngine& getCompositionEngine() const;
void chooseCompositionStrategy() override;
+ bool getSkipColorTransform() const override;
compositionengine::Output::FrameFences presentAndGetFrameFences() override;
+ std::vector<renderengine::LayerSettings> generateClientCompositionRequests(
+ bool supportsProtectedContent, Region& clearRegion) override;
+ void appendRegionFlashRequests(const Region&,
+ std::vector<renderengine::LayerSettings>&) override;
+ void setExpensiveRenderingExpected(bool enabled) override;
void dumpBase(std::string&) const;
private:
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
index d8ad02a..4c3f935 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
@@ -55,6 +55,7 @@
void applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition) override;
void prepareForDeviceLayerRequests() override;
void applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest request) override;
+ bool needsFiltering() const override;
void dump(std::string& result) const override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
index d494413..c944bec 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
@@ -77,8 +77,17 @@
MOCK_METHOD0(prepareFrame, void());
MOCK_METHOD0(chooseCompositionStrategy, void());
+ MOCK_METHOD2(composeSurfaces, bool(const Region&, base::unique_fd*));
+ MOCK_CONST_METHOD0(getSkipColorTransform, bool());
+
MOCK_METHOD0(postFramebuffer, void());
MOCK_METHOD0(presentAndGetFrameFences, compositionengine::Output::FrameFences());
+
+ MOCK_METHOD2(generateClientCompositionRequests,
+ std::vector<renderengine::LayerSettings>(bool, Region&));
+ MOCK_METHOD2(appendRegionFlashRequests,
+ void(const Region&, std::vector<renderengine::LayerSettings>&));
+ MOCK_METHOD1(setExpensiveRenderingExpected, void(bool));
};
} // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
index 195648f..d8d637d 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
@@ -46,6 +46,7 @@
MOCK_METHOD1(applyDeviceCompositionTypeChange, void(Hwc2::IComposerClient::Composition));
MOCK_METHOD0(prepareForDeviceLayerRequests, void());
MOCK_METHOD1(applyDeviceLayerRequest, void(Hwc2::IComposerClient::LayerRequest request));
+ MOCK_CONST_METHOD0(needsFiltering, bool());
MOCK_CONST_METHOD1(dump, void(std::string&));
};
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index 6831901..6cd392e 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -26,6 +26,7 @@
#include <utils/Trace.h>
#include "DisplayHardware/HWComposer.h"
+#include "DisplayHardware/PowerAdvisor.h"
namespace android::compositionengine::impl {
@@ -38,7 +39,8 @@
Display::Display(const CompositionEngine& compositionEngine, DisplayCreationArgs&& args)
: compositionengine::impl::Output(compositionEngine),
mIsVirtual(args.isVirtual),
- mId(args.displayId) {
+ mId(args.displayId),
+ mPowerAdvisor(args.powerAdvisor) {
editState().isSecure = args.isSecure;
}
@@ -160,6 +162,15 @@
state.usesDeviceComposition = !allLayersRequireClientComposition();
}
+bool Display::getSkipColorTransform() const {
+ if (!mId) {
+ return false;
+ }
+
+ auto& hwc = getCompositionEngine().getHwComposer();
+ return hwc.hasDisplayCapability(*mId, HWC2::DisplayCapability::SkipClientColorTransform);
+}
+
bool Display::anyLayersRequireClientComposition() const {
const auto& layers = getOutputLayersOrderedByZ();
return std::any_of(layers.cbegin(), layers.cend(),
@@ -240,4 +251,12 @@
return result;
}
+void Display::setExpensiveRenderingExpected(bool enabled) {
+ Output::setExpensiveRenderingExpected(enabled);
+
+ if (mPowerAdvisor && mId) {
+ mPowerAdvisor->setExpensiveRenderingExpected(*mId, enabled);
+ }
+}
+
} // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp
index 37d6eaa..0dc4bf1 100644
--- a/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp
@@ -71,6 +71,8 @@
dumpVal(out, "color", state.color);
out.append("\n ");
+ dumpVal(out, "isOpaque", state.isOpaque);
+ dumpVal(out, "hasProtectedContent", state.hasProtectedContent);
dumpVal(out, "isColorspaceAgnostic", state.isColorspaceAgnostic);
dumpVal(out, "dataspace", toString(state.dataspace), state.dataspace);
dumpVal(out, "hdr metadata types", state.hdrMetadata.validTypes);
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index b411e0a..fb576e0 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -17,13 +17,20 @@
#include <android-base/stringprintf.h>
#include <compositionengine/CompositionEngine.h>
#include <compositionengine/DisplayColorProfile.h>
+#include <compositionengine/Layer.h>
#include <compositionengine/LayerFE.h>
#include <compositionengine/RenderSurface.h>
+#include <compositionengine/impl/LayerCompositionState.h>
#include <compositionengine/impl/Output.h>
#include <compositionengine/impl/OutputLayer.h>
+#include <renderengine/DisplaySettings.h>
+#include <renderengine/RenderEngine.h>
#include <ui/DebugUtils.h>
+#include <ui/HdrCapabilities.h>
#include <utils/Trace.h>
+#include "TracedOrdinal.h"
+
namespace android::compositionengine {
Output::~Output() = default;
@@ -73,10 +80,10 @@
dirtyEntireOutput();
}
-// TODO(lpique): Rename setSize() once more is moved.
+// TODO(b/121291683): Rename setSize() once more is moved.
void Output::setBounds(const ui::Size& size) {
mRenderSurface->setDisplaySize(size);
- // TODO(lpique): Rename mState.size once more is moved.
+ // TODO(b/121291683): Rename mState.size once more is moved.
mState.bounds = Rect(mRenderSurface->getSize());
dirtyEntireOutput();
@@ -292,6 +299,179 @@
mRenderSurface->prepareFrame(mState.usesClientComposition, mState.usesDeviceComposition);
}
+bool Output::composeSurfaces(const Region& debugRegion, base::unique_fd* readyFence) {
+ ATRACE_CALL();
+ ALOGV(__FUNCTION__);
+
+ const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition",
+ mState.usesClientComposition};
+ if (!hasClientComposition) {
+ return true;
+ }
+
+ ALOGV("hasClientComposition");
+
+ auto& renderEngine = mCompositionEngine.getRenderEngine();
+ const bool supportsProtectedContent = renderEngine.supportsProtectedContent();
+
+ renderengine::DisplaySettings clientCompositionDisplay;
+ clientCompositionDisplay.physicalDisplay = mState.frame;
+ clientCompositionDisplay.clip = mState.scissor;
+ clientCompositionDisplay.globalTransform = mState.transform.asMatrix4();
+ clientCompositionDisplay.orientation = mState.orientation;
+ clientCompositionDisplay.outputDataspace =
+ mDisplayColorProfile->hasWideColorGamut() ? mState.dataspace : ui::Dataspace::UNKNOWN;
+ clientCompositionDisplay.maxLuminance =
+ mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
+
+ // Compute the global color transform matrix.
+ if (!mState.usesDeviceComposition && !getSkipColorTransform()) {
+ clientCompositionDisplay.colorTransform = mState.colorTransformMat;
+ }
+
+ // Note: Updated by generateClientCompositionRequests
+ clientCompositionDisplay.clearRegion = Region::INVALID_REGION;
+
+ // Generate the client composition requests for the layers on this output.
+ std::vector<renderengine::LayerSettings> clientCompositionLayers =
+ generateClientCompositionRequests(supportsProtectedContent,
+ clientCompositionDisplay.clearRegion);
+ appendRegionFlashRequests(debugRegion, clientCompositionLayers);
+
+ // If we the display is secure, protected content support is enabled, and at
+ // least one layer has protected content, we need to use a secure back
+ // buffer.
+ if (mState.isSecure && supportsProtectedContent) {
+ bool needsProtected =
+ std::any_of(mOutputLayersOrderedByZ.begin(), mOutputLayersOrderedByZ.end(),
+ [](auto& layer) {
+ return layer->getLayer().getState().frontEnd.hasProtectedContent;
+ });
+ if (needsProtected != renderEngine.isProtected()) {
+ renderEngine.useProtectedContext(needsProtected);
+ }
+ if (needsProtected != mRenderSurface->isProtected() &&
+ needsProtected == renderEngine.isProtected()) {
+ mRenderSurface->setProtected(needsProtected);
+ }
+ }
+
+ base::unique_fd fd;
+ sp<GraphicBuffer> buf = mRenderSurface->dequeueBuffer(&fd);
+ if (buf == nullptr) {
+ ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
+ "client composition for this frame",
+ mName.c_str());
+ return false;
+ }
+
+ // We boost GPU frequency here because there will be color spaces conversion
+ // and it's expensive. We boost the GPU frequency so that GPU composition can
+ // finish in time. We must reset GPU frequency afterwards, because high frequency
+ // consumes extra battery.
+ const bool expensiveRenderingExpected =
+ clientCompositionDisplay.outputDataspace == ui::Dataspace::DISPLAY_P3;
+ if (expensiveRenderingExpected) {
+ setExpensiveRenderingExpected(true);
+ }
+
+ renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayers,
+ buf->getNativeBuffer(), /*useFramebufferCache=*/true, std::move(fd),
+ readyFence);
+
+ if (expensiveRenderingExpected) {
+ setExpensiveRenderingExpected(false);
+ }
+
+ return true;
+}
+
+std::vector<renderengine::LayerSettings> Output::generateClientCompositionRequests(
+ bool supportsProtectedContent, Region& clearRegion) {
+ std::vector<renderengine::LayerSettings> clientCompositionLayers;
+ ALOGV("Rendering client layers");
+
+ const Region viewportRegion(mState.viewport);
+ const bool useIdentityTransform = false;
+ bool firstLayer = true;
+ // Used when a layer clears part of the buffer.
+ Region dummyRegion;
+
+ for (auto& layer : mOutputLayersOrderedByZ) {
+ const auto& layerState = layer->getState();
+ const auto& layerFEState = layer->getLayer().getState().frontEnd;
+ auto& layerFE = layer->getLayerFE();
+
+ const Region clip(viewportRegion.intersect(layer->getState().visibleRegion));
+ ALOGV("Layer: %s", layerFE.getDebugName());
+ if (clip.isEmpty()) {
+ ALOGV(" Skipping for empty clip");
+ firstLayer = false;
+ continue;
+ }
+
+ bool clientComposition = layer->requiresClientComposition();
+
+ // We clear the client target for non-client composed layers if
+ // requested by the HWC. We skip this if the layer is not an opaque
+ // rectangle, as by definition the layer must blend with whatever is
+ // underneath. We also skip the first layer as the buffer target is
+ // guaranteed to start out cleared.
+ bool clearClientComposition =
+ layerState.clearClientTarget && layerFEState.isOpaque && !firstLayer;
+
+ ALOGV(" Composition type: client %d clear %d", clientComposition, clearClientComposition);
+
+ if (clientComposition || clearClientComposition) {
+ compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{
+ clip,
+ useIdentityTransform,
+ layer->needsFiltering() || mState.needsFiltering,
+ mState.isSecure,
+ supportsProtectedContent,
+ clientComposition ? clearRegion : dummyRegion,
+ };
+ if (auto result = layerFE.prepareClientComposition(targetSettings)) {
+ if (clearClientComposition) {
+ auto& layerSettings = *result;
+ layerSettings.source.buffer.buffer = nullptr;
+ layerSettings.source.solidColor = half3(0.0, 0.0, 0.0);
+ layerSettings.alpha = half(0.0);
+ layerSettings.disableBlending = true;
+ }
+
+ clientCompositionLayers.push_back(*result);
+ }
+ }
+
+ firstLayer = false;
+ }
+
+ return clientCompositionLayers;
+}
+
+void Output::appendRegionFlashRequests(
+ const Region& flashRegion,
+ std::vector<renderengine::LayerSettings>& clientCompositionLayers) {
+ if (flashRegion.isEmpty()) {
+ return;
+ }
+
+ renderengine::LayerSettings layerSettings;
+ layerSettings.source.buffer.buffer = nullptr;
+ layerSettings.source.solidColor = half3(1.0, 0.0, 1.0);
+ layerSettings.alpha = half(1.0);
+
+ for (const auto& rect : flashRegion) {
+ layerSettings.geometry.boundaries = rect.toFloatRect();
+ clientCompositionLayers.push_back(layerSettings);
+ }
+}
+
+void Output::setExpensiveRenderingExpected(bool) {
+ // The base class does nothing with this call.
+}
+
void Output::postFramebuffer() {
ATRACE_CALL();
ALOGV(__FUNCTION__);
@@ -300,10 +480,10 @@
return;
}
- mRenderSurface->onPresentDisplayCompleted();
-
auto frame = presentAndGetFrameFences();
+ mRenderSurface->onPresentDisplayCompleted();
+
for (auto& layer : getOutputLayersOrderedByZ()) {
// The layer buffer from the previous frame (if any) is released
// by HWC only when the release fence from this frame (if any) is
@@ -353,6 +533,10 @@
mState.usesDeviceComposition = false;
}
+bool Output::getSkipColorTransform() const {
+ return true;
+}
+
compositionengine::Output::FrameFences Output::presentAndGetFrameFences() {
compositionengine::Output::FrameFences result;
if (mState.usesClientComposition) {
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index 6e744b9..e721cf5 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -614,6 +614,13 @@
}
}
+bool OutputLayer::needsFiltering() const {
+ const auto& displayFrame = mState.displayFrame;
+ const auto& sourceCrop = mState.sourceCrop;
+ return sourceCrop.getHeight() != displayFrame.getHeight() ||
+ sourceCrop.getWidth() != displayFrame.getWidth();
+}
+
void OutputLayer::dump(std::string& out) const {
using android::base::StringAppendF;
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index e3be0d7..743da82 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -30,6 +30,7 @@
#include "MockHWC2.h"
#include "MockHWComposer.h"
+#include "MockPowerAdvisor.h"
namespace android::compositionengine {
namespace {
@@ -59,6 +60,7 @@
}
StrictMock<android::mock::HWComposer> mHwComposer;
+ StrictMock<Hwc2::mock::PowerAdvisor> mPowerAdvisor;
StrictMock<mock::CompositionEngine> mCompositionEngine;
sp<mock::NativeWindow> mNativeWindow = new StrictMock<mock::NativeWindow>();
StrictMock<HWC2::mock::Layer> mHWC2Layer1;
@@ -68,7 +70,10 @@
mock::OutputLayer* mLayer2 = new StrictMock<mock::OutputLayer>();
mock::OutputLayer* mLayer3 = new StrictMock<mock::OutputLayer>();
impl::Display mDisplay{mCompositionEngine,
- DisplayCreationArgsBuilder().setDisplayId(DEFAULT_DISPLAY_ID).build()};
+ DisplayCreationArgsBuilder()
+ .setDisplayId(DEFAULT_DISPLAY_ID)
+ .setPowerAdvisor(&mPowerAdvisor)
+ .build()};
};
/*
@@ -344,6 +349,24 @@
}
/*
+ * Display::getSkipColorTransform()
+ */
+
+TEST_F(DisplayTest, getSkipColorTransformDoesNothingIfNonHwcDisplay) {
+ auto nonHwcDisplay{
+ impl::createDisplay(mCompositionEngine, DisplayCreationArgsBuilder().build())};
+ EXPECT_FALSE(nonHwcDisplay->getSkipColorTransform());
+}
+
+TEST_F(DisplayTest, getSkipColorTransformChecksHwcCapability) {
+ EXPECT_CALL(mHwComposer,
+ hasDisplayCapability(std::make_optional(DEFAULT_DISPLAY_ID),
+ HWC2::DisplayCapability::SkipClientColorTransform))
+ .WillOnce(Return(true));
+ EXPECT_TRUE(mDisplay.getSkipColorTransform());
+}
+
+/*
* Display::anyLayersRequireClientComposition()
*/
@@ -502,5 +525,17 @@
EXPECT_EQ(layer2Fence, result.layerFences[&mHWC2Layer2]);
}
+/*
+ * Display::setExpensiveRenderingExpected()
+ */
+
+TEST_F(DisplayTest, setExpensiveRenderingExpectedForwardsToPowerAdvisor) {
+ EXPECT_CALL(mPowerAdvisor, setExpensiveRenderingExpected(DEFAULT_DISPLAY_ID, true)).Times(1);
+ mDisplay.setExpensiveRenderingExpected(true);
+
+ EXPECT_CALL(mPowerAdvisor, setExpensiveRenderingExpected(DEFAULT_DISPLAY_ID, false)).Times(1);
+ mDisplay.setExpensiveRenderingExpected(false);
+}
+
} // namespace
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.cpp b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.cpp
new file mode 100644
index 0000000..85b9403
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MockPowerAdvisor.h"
+
+namespace android {
+namespace Hwc2 {
+
+// This will go away once PowerAdvisor is moved into the "backend" library
+PowerAdvisor::~PowerAdvisor() = default;
+
+namespace mock {
+
+// The Google Mock documentation recommends explicit non-header instantiations
+// for better compile time performance.
+PowerAdvisor::PowerAdvisor() = default;
+PowerAdvisor::~PowerAdvisor() = default;
+
+} // namespace mock
+} // namespace Hwc2
+} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
new file mode 100644
index 0000000..c5a73f2
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <gmock/gmock.h>
+
+#include "DisplayHardware/PowerAdvisor.h"
+
+namespace android {
+namespace Hwc2 {
+namespace mock {
+
+class PowerAdvisor : public android::Hwc2::PowerAdvisor {
+public:
+ PowerAdvisor();
+ ~PowerAdvisor() override;
+
+ MOCK_METHOD2(setExpensiveRenderingExpected, void(DisplayId displayId, bool expected));
+};
+
+} // namespace mock
+} // namespace Hwc2
+} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index a5428ad..c83cae6 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -875,5 +875,23 @@
EXPECT_FALSE(mOutputLayer.getState().clearClientTarget);
}
+/*
+ * OutputLayer::needsFiltering()
+ */
+
+TEST_F(OutputLayerTest, needsFilteringReturnsFalseIfDisplaySizeSameAsSourceSize) {
+ mOutputLayer.editState().displayFrame = Rect(100, 100, 200, 200);
+ mOutputLayer.editState().sourceCrop = FloatRect{0.f, 0.f, 100.f, 100.f};
+
+ EXPECT_FALSE(mOutputLayer.needsFiltering());
+}
+
+TEST_F(OutputLayerTest, needsFilteringReturnsTrueIfDisplaySizeDifferentFromSourceSize) {
+ mOutputLayer.editState().displayFrame = Rect(100, 100, 200, 200);
+ mOutputLayer.editState().sourceCrop = FloatRect{0.f, 0.f, 100.1f, 100.1f};
+
+ EXPECT_TRUE(mOutputLayer.needsFiltering());
+}
+
} // namespace
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index d136562..b6d79d4 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -60,7 +60,7 @@
mDisplayInstallOrientation(args.displayInstallOrientation),
mCompositionDisplay{mFlinger->getCompositionEngine().createDisplay(
compositionengine::DisplayCreationArgs{args.isSecure, args.isVirtual,
- args.displayId})},
+ args.displayId, args.powerAdvisor})},
mIsVirtual(args.isVirtual),
mOrientation(),
mActiveConfig(0),
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 8bc19d4..4321e3d 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -40,6 +40,7 @@
#include <utils/Timers.h>
#include "DisplayHardware/DisplayIdentification.h"
+#include "DisplayHardware/PowerAdvisor.h"
#include "RenderArea.h"
namespace android {
@@ -241,6 +242,7 @@
std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>> hwcColorModes;
int initialPowerMode{HWC_POWER_MODE_NORMAL};
bool isPrimary{false};
+ Hwc2::PowerAdvisor* powerAdvisor{nullptr};
};
class DisplayRenderArea : public RenderArea {
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index a2eeea5..b612476 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -440,6 +440,7 @@
}
void Layer::latchPerFrameState(compositionengine::LayerFECompositionState& compositionState) const {
+ const auto& drawingState{getDrawingState()};
compositionState.forceClientComposition = false;
// TODO(lpique): b/121291683 Remove this one we are sure we don't need the
@@ -451,9 +452,14 @@
compositionState.colorTransform = getColorTransform();
compositionState.colorTransformIsIdentity = !hasColorTransform();
compositionState.surfaceDamage = surfaceDamageRegion;
+ compositionState.hasProtectedContent = isProtected();
+
+ const bool usesRoundedCorners = getRoundedCornerState().radius != 0.f;
+ compositionState.isOpaque =
+ isOpaque(drawingState) && !usesRoundedCorners && getAlpha() == 1.0_hf;
// Force client composition for special cases known only to the front-end.
- if (isHdrY410() || getRoundedCornerState().radius > 0.0f) {
+ if (isHdrY410() || usesRoundedCorners) {
compositionState.forceClientComposition = true;
}
}
@@ -1932,46 +1938,10 @@
}
}
-void Layer::writeToProtoCompositionState(LayerProto* layerInfo,
- const sp<DisplayDevice>& displayDevice,
- uint32_t traceFlags) const {
- auto outputLayer = findOutputLayerForDisplay(displayDevice);
- if (!outputLayer) {
- return;
- }
-
- writeToProtoDrawingState(layerInfo, traceFlags);
- writeToProtoCommonState(layerInfo, LayerVector::StateSet::Drawing, traceFlags);
-
- const auto& compositionState = outputLayer->getState();
-
- const Rect& frame = compositionState.displayFrame;
- LayerProtoHelper::writeToProto(frame, [&]() { return layerInfo->mutable_hwc_frame(); });
-
- const FloatRect& crop = compositionState.sourceCrop;
- LayerProtoHelper::writeToProto(crop, [&]() { return layerInfo->mutable_hwc_crop(); });
-
- const int32_t transform =
- getCompositionLayer() ? static_cast<int32_t>(compositionState.bufferTransform) : 0;
- layerInfo->set_hwc_transform(transform);
-
- const int32_t compositionType =
- static_cast<int32_t>(compositionState.hwc ? (*compositionState.hwc).hwcCompositionType
- : Hwc2::IComposerClient::Composition::CLIENT);
- layerInfo->set_hwc_composition_type(compositionType);
-}
-
bool Layer::isRemovedFromCurrentState() const {
return mRemovedFromCurrentState;
}
-// Debug helper for b/137560795
-#define INT32_MIGHT_OVERFLOW(n) (((n) >= INT32_MAX / 2) || ((n) <= INT32_MIN / 2))
-
-#define RECT_BOUNDS_INVALID(rect) \
- (INT32_MIGHT_OVERFLOW((rect).left) || INT32_MIGHT_OVERFLOW((rect).right) || \
- INT32_MIGHT_OVERFLOW((rect).bottom) || INT32_MIGHT_OVERFLOW((rect).top))
-
InputWindowInfo Layer::fillInputInfo() {
InputWindowInfo info = mDrawingState.inputInfo;
@@ -1982,14 +1952,14 @@
ui::Transform t = getTransform();
const float xScale = t.sx();
const float yScale = t.sy();
- float xSurfaceInset = info.surfaceInset;
- float ySurfaceInset = info.surfaceInset;
+ int32_t xSurfaceInset = info.surfaceInset;
+ int32_t ySurfaceInset = info.surfaceInset;
if (xScale != 1.0f || yScale != 1.0f) {
- info.windowXScale *= 1.0f / xScale;
- info.windowYScale *= 1.0f / yScale;
+ info.windowXScale *= (xScale != 0.0f) ? 1.0f / xScale : 0.0f;
+ info.windowYScale *= (yScale != 0.0f) ? 1.0f / yScale : 0.0f;
info.touchableRegion.scaleSelf(xScale, yScale);
- xSurfaceInset *= xScale;
- ySurfaceInset *= yScale;
+ xSurfaceInset = std::round(xSurfaceInset * xScale);
+ ySurfaceInset = std::round(ySurfaceInset * yScale);
}
// Transform layer size to screen space and inset it by surface insets.
@@ -2002,25 +1972,10 @@
}
layerBounds = t.transform(layerBounds);
- // debug check for b/137560795
- {
- if (RECT_BOUNDS_INVALID(layerBounds)) {
- ALOGE("layer %s bounds are invalid (%" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32
- ")",
- mName.c_str(), layerBounds.left, layerBounds.top, layerBounds.right,
- layerBounds.bottom);
- std::string out;
- getTransform().dump(out, "Transform");
- ALOGE("%s", out.c_str());
- layerBounds.left = layerBounds.top = layerBounds.right = layerBounds.bottom = 0;
- }
+ // clamp inset to layer bounds
+ xSurfaceInset = (xSurfaceInset >= 0) ? std::min(xSurfaceInset, layerBounds.getWidth() / 2) : 0;
+ ySurfaceInset = (ySurfaceInset >= 0) ? std::min(ySurfaceInset, layerBounds.getHeight() / 2) : 0;
- if (INT32_MIGHT_OVERFLOW(xSurfaceInset) || INT32_MIGHT_OVERFLOW(ySurfaceInset)) {
- ALOGE("layer %s surface inset are invalid (%" PRIi32 ", %" PRIi32 ")", mName.c_str(),
- int32_t(xSurfaceInset), int32_t(ySurfaceInset));
- xSurfaceInset = ySurfaceInset = 0;
- }
- }
layerBounds.inset(xSurfaceInset, ySurfaceInset, xSurfaceInset, ySurfaceInset);
// Input coordinate should match the layer bounds.
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 953f25d..87a5896 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -93,7 +93,7 @@
LayerMetadata metadata;
};
-class Layer : public virtual compositionengine::LayerFE, public ClientCache::ErasedRecipient {
+class Layer : public virtual compositionengine::LayerFE {
static std::atomic<int32_t> sSequence;
public:
@@ -440,11 +440,6 @@
// thread.
void writeToProtoDrawingState(LayerProto* layerInfo,
uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
- // Write states that are modified by the main thread. This includes drawing
- // state as well as buffer data and composition data for layers on the specified
- // display. This should be called in the main or tracing thread.
- void writeToProtoCompositionState(LayerProto* layerInfo, const sp<DisplayDevice>& displayDevice,
- uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
// Write drawing or current state. If writing current state, the caller should hold the
// external mStateLock. If writing drawing state, this function should be called on the
// main or tracing thread.
@@ -676,9 +671,6 @@
compositionengine::OutputLayer* findOutputLayerForDisplay(
const sp<const DisplayDevice>& display) const;
- // Inherit from ClientCache::ErasedRecipient
- void bufferErased(const client_cache_t& /*clientCacheId*/) override {}
-
protected:
// constant
sp<SurfaceFlinger> mFlinger;
diff --git a/services/surfaceflinger/LayerStats.cpp b/services/surfaceflinger/LayerStats.cpp
deleted file mode 100644
index a2d1feb..0000000
--- a/services/surfaceflinger/LayerStats.cpp
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright 2018 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 "LayerStats"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-
-#include "LayerStats.h"
-#include "DisplayHardware/HWComposer.h"
-#include "ui/DebugUtils.h"
-
-#include <android-base/stringprintf.h>
-#include <log/log.h>
-#include <utils/Trace.h>
-
-namespace android {
-
-using base::StringAppendF;
-using base::StringPrintf;
-
-void LayerStats::enable() {
- ATRACE_CALL();
- std::lock_guard<std::mutex> lock(mMutex);
- if (mEnabled) return;
- mLayerShapeStatsMap.clear();
- mEnabled = true;
- ALOGD("Logging enabled");
-}
-
-void LayerStats::disable() {
- ATRACE_CALL();
- std::lock_guard<std::mutex> lock(mMutex);
- if (!mEnabled) return;
- mEnabled = false;
- ALOGD("Logging disabled");
-}
-
-void LayerStats::clear() {
- ATRACE_CALL();
- std::lock_guard<std::mutex> lock(mMutex);
- mLayerShapeStatsMap.clear();
- ALOGD("Cleared current layer stats");
-}
-
-bool LayerStats::isEnabled() {
- return mEnabled;
-}
-
-void LayerStats::traverseLayerTreeStatsLocked(
- const std::vector<LayerProtoParser::Layer*>& layerTree,
- const LayerProtoParser::LayerGlobal& layerGlobal,
- std::vector<std::string>* const outLayerShapeVec) {
- for (const auto& layer : layerTree) {
- if (!layer) continue;
- traverseLayerTreeStatsLocked(layer->children, layerGlobal, outLayerShapeVec);
- std::string key = "";
- StringAppendF(&key, ",%s", layer->type.c_str());
- StringAppendF(&key, ",%s", layerCompositionType(layer->hwcCompositionType));
- StringAppendF(&key, ",%d", layer->isProtected);
- StringAppendF(&key, ",%s", layerTransform(layer->hwcTransform));
- StringAppendF(&key, ",%s", layerPixelFormat(layer->activeBuffer.format).c_str());
- StringAppendF(&key, ",%s", layer->dataspace.c_str());
- StringAppendF(&key, ",%s",
- destinationLocation(layer->hwcFrame.left, layerGlobal.resolution[0], true));
- StringAppendF(&key, ",%s",
- destinationLocation(layer->hwcFrame.top, layerGlobal.resolution[1], false));
- StringAppendF(&key, ",%s",
- destinationSize(layer->hwcFrame.right - layer->hwcFrame.left,
- layerGlobal.resolution[0], true));
- StringAppendF(&key, ",%s",
- destinationSize(layer->hwcFrame.bottom - layer->hwcFrame.top,
- layerGlobal.resolution[1], false));
- StringAppendF(&key, ",%s", scaleRatioWH(layer).c_str());
- StringAppendF(&key, ",%s", alpha(static_cast<float>(layer->color.a)));
-
- outLayerShapeVec->push_back(key);
- ALOGV("%s", key.c_str());
- }
-}
-
-void LayerStats::logLayerStats(const LayersProto& layersProto) {
- ATRACE_CALL();
- ALOGV("Logging");
- auto layerGlobal = LayerProtoParser::generateLayerGlobalInfo(layersProto);
- auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
- std::vector<std::string> layerShapeVec;
-
- std::lock_guard<std::mutex> lock(mMutex);
- traverseLayerTreeStatsLocked(layerTree.topLevelLayers, layerGlobal, &layerShapeVec);
-
- std::string layerShapeKey =
- StringPrintf("%d,%s,%s,%s", static_cast<int32_t>(layerShapeVec.size()),
- layerGlobal.colorMode.c_str(), layerGlobal.colorTransform.c_str(),
- layerTransform(layerGlobal.globalTransform));
- ALOGV("%s", layerShapeKey.c_str());
-
- std::sort(layerShapeVec.begin(), layerShapeVec.end(), std::greater<std::string>());
- for (auto const& s : layerShapeVec) {
- layerShapeKey += s;
- }
-
- mLayerShapeStatsMap[layerShapeKey]++;
-}
-
-void LayerStats::dump(std::string& result) {
- ATRACE_CALL();
- ALOGD("Dumping");
- std::lock_guard<std::mutex> lock(mMutex);
- result.append("Frequency,LayerCount,ColorMode,ColorTransform,Orientation\n");
- result.append("LayerType,CompositionType,IsProtected,Transform,PixelFormat,Dataspace,");
- result.append("DstX,DstY,DstWidth,DstHeight,WScale,HScale,Alpha\n");
- for (auto& u : mLayerShapeStatsMap) {
- StringAppendF(&result, "%u,%s\n", u.second, u.first.c_str());
- }
-}
-
-const char* LayerStats::destinationLocation(int32_t location, int32_t range, bool isHorizontal) {
- static const char* locationArray[8] = {"0", "1/8", "1/4", "3/8", "1/2", "5/8", "3/4", "7/8"};
- int32_t ratio = location * 8 / range;
- if (ratio < 0) return "N/A";
- if (isHorizontal) {
- // X location is divided into 4 buckets {"0", "1/4", "1/2", "3/4"}
- if (ratio > 6) return "3/4";
- // use index 0, 2, 4, 6
- return locationArray[ratio & ~1];
- }
- if (ratio > 7) return "7/8";
- return locationArray[ratio];
-}
-
-const char* LayerStats::destinationSize(int32_t size, int32_t range, bool isWidth) {
- static const char* sizeArray[8] = {"1/8", "1/4", "3/8", "1/2", "5/8", "3/4", "7/8", "1"};
- int32_t ratio = size * 8 / range;
- if (ratio < 0) return "N/A";
- if (isWidth) {
- // width is divided into 4 buckets {"1/4", "1/2", "3/4", "1"}
- if (ratio > 6) return "1";
- // use index 1, 3, 5, 7
- return sizeArray[ratio | 1];
- }
- if (ratio > 7) return "1";
- return sizeArray[ratio];
-}
-
-const char* LayerStats::layerTransform(int32_t transform) {
- return getTransformName(static_cast<hwc_transform_t>(transform));
-}
-
-const char* LayerStats::layerCompositionType(int32_t compositionType) {
- return getCompositionName(static_cast<hwc2_composition_t>(compositionType));
-}
-
-std::string LayerStats::layerPixelFormat(int32_t pixelFormat) {
- return decodePixelFormat(pixelFormat);
-}
-
-std::string LayerStats::scaleRatioWH(const LayerProtoParser::Layer* layer) {
- if (!layer->type.compare("ColorLayer")) return "N/A,N/A";
- std::string ret = "";
- if (isRotated(layer->hwcTransform)) {
- ret += scaleRatio(layer->hwcFrame.right - layer->hwcFrame.left,
- static_cast<int32_t>(layer->hwcCrop.bottom - layer->hwcCrop.top));
- ret += ",";
- ret += scaleRatio(layer->hwcFrame.bottom - layer->hwcFrame.top,
- static_cast<int32_t>(layer->hwcCrop.right - layer->hwcCrop.left));
- } else {
- ret += scaleRatio(layer->hwcFrame.right - layer->hwcFrame.left,
- static_cast<int32_t>(layer->hwcCrop.right - layer->hwcCrop.left));
- ret += ",";
- ret += scaleRatio(layer->hwcFrame.bottom - layer->hwcFrame.top,
- static_cast<int32_t>(layer->hwcCrop.bottom - layer->hwcCrop.top));
- }
- return ret;
-}
-
-const char* LayerStats::scaleRatio(int32_t destinationScale, int32_t sourceScale) {
- // Make scale buckets from <1/64 to >= 16, to avoid floating point
- // calculation, x64 on destinationScale first
- int32_t scale = destinationScale * 64 / sourceScale;
- if (!scale) return "<1/64";
- if (scale < 2) return "1/64";
- if (scale < 4) return "1/32";
- if (scale < 8) return "1/16";
- if (scale < 16) return "1/8";
- if (scale < 32) return "1/4";
- if (scale < 64) return "1/2";
- if (scale < 128) return "1";
- if (scale < 256) return "2";
- if (scale < 512) return "4";
- if (scale < 1024) return "8";
- return ">=16";
-}
-
-const char* LayerStats::alpha(float a) {
- if (a == 1.0f) return "1.0";
- if (a > 0.9f) return "0.99";
- if (a > 0.8f) return "0.9";
- if (a > 0.7f) return "0.8";
- if (a > 0.6f) return "0.7";
- if (a > 0.5f) return "0.6";
- if (a > 0.4f) return "0.5";
- if (a > 0.3f) return "0.4";
- if (a > 0.2f) return "0.3";
- if (a > 0.1f) return "0.2";
- if (a > 0.0f) return "0.1";
- return "0.0";
-}
-
-bool LayerStats::isRotated(int32_t transform) {
- return transform & HWC_TRANSFORM_ROT_90;
-}
-
-bool LayerStats::isVFlipped(int32_t transform) {
- return transform & HWC_TRANSFORM_FLIP_V;
-}
-
-bool LayerStats::isHFlipped(int32_t transform) {
- return transform & HWC_TRANSFORM_FLIP_H;
-}
-
-} // namespace android
diff --git a/services/surfaceflinger/LayerStats.h b/services/surfaceflinger/LayerStats.h
deleted file mode 100644
index 62b2688..0000000
--- a/services/surfaceflinger/LayerStats.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2018 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 <layerproto/LayerProtoHeader.h>
-#include <layerproto/LayerProtoParser.h>
-#include <mutex>
-#include <unordered_map>
-
-using namespace android::surfaceflinger;
-
-namespace android {
-
-class LayerStats {
-public:
- void enable();
- void disable();
- void clear();
- bool isEnabled();
- void logLayerStats(const LayersProto& layersProto);
- void dump(std::string& result);
-
-private:
- // Traverse layer tree to get all visible layers' stats
- void traverseLayerTreeStatsLocked(
- const std::vector<LayerProtoParser::Layer*>& layerTree,
- const LayerProtoParser::LayerGlobal& layerGlobal,
- std::vector<std::string>* const outLayerShapeVec);
- // Convert layer's top-left position into 8x8 percentage of the display
- static const char* destinationLocation(int32_t location, int32_t range, bool isHorizontal);
- // Convert layer's size into 8x8 percentage of the display
- static const char* destinationSize(int32_t size, int32_t range, bool isWidth);
- // Return the name of the transform
- static const char* layerTransform(int32_t transform);
- // Return the name of the composition type
- static const char* layerCompositionType(int32_t compositionType);
- // Return the name of the pixel format
- static std::string layerPixelFormat(int32_t pixelFormat);
- // Calculate scale ratios of layer's width/height with rotation information
- static std::string scaleRatioWH(const LayerProtoParser::Layer* layer);
- // Calculate scale ratio from source to destination and convert to string
- static const char* scaleRatio(int32_t destinationScale, int32_t sourceScale);
- // Bucket the alpha into designed buckets
- static const char* alpha(float a);
- // Return whether the original buffer is rotated in final composition
- static bool isRotated(int32_t transform);
- // Return whether the original buffer is V-flipped in final composition
- static bool isVFlipped(int32_t transform);
- // Return whether the original buffer is H-flipped in final composition
- static bool isHFlipped(int32_t transform);
-
- bool mEnabled = false;
- // Protect mLayersStatsMap
- std::mutex mMutex;
- // Hashmap for tracking the frame(layer shape) stats
- // KEY is a concatenation of all layers' properties within a frame
- // VALUE is the number of times this particular set has been scanned out
- std::unordered_map<std::string, uint32_t> mLayerShapeStatsMap;
-};
-
-} // namespace android
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp
index e782dd5..723d71f 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp
@@ -49,7 +49,7 @@
mLastPresentTime = lastPresentTime;
// Ignore time diff that are too high - those are stale values
if (timeDiff > OBSOLETE_TIME_EPSILON_NS.count()) return;
- const nsecs_t refreshDuration = (timeDiff > 0) ? timeDiff : mMinRefreshDuration;
+ const nsecs_t refreshDuration = std::max(timeDiff, mMinRefreshDuration);
const int fps = 1e9f / refreshDuration;
mRefreshRateHistory.insertRefreshRate(fps);
}
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 952643c..3883427 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -118,6 +118,14 @@
}
}
+Scheduler::Scheduler(std::unique_ptr<DispSync> primaryDispSync,
+ std::unique_ptr<EventControlThread> eventControlThread,
+ const scheduler::RefreshRateConfigs& configs)
+ : mHasSyncFramework(false),
+ mPrimaryDispSync(std::move(primaryDispSync)),
+ mEventControlThread(std::move(eventControlThread)),
+ mRefreshRateConfigs(configs) {}
+
Scheduler::~Scheduler() {
// Ensure the OneShotTimer threads are joined before we start destroying state.
mDisplayPowerTimer.reset();
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 0d9d7aa..5905ff6 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -204,6 +204,10 @@
enum class TimerState { Reset, Expired };
enum class TouchState { Inactive, Active };
+ // Used by tests to inject mocks.
+ Scheduler(std::unique_ptr<DispSync>, std::unique_ptr<EventControlThread>,
+ const scheduler::RefreshRateConfigs&);
+
// Creates a connection on the given EventThread and forwards the given callbacks.
sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&,
ISurfaceComposer::ConfigChanged);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 488b9ef..04e7bf5 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1798,8 +1798,6 @@
doComposition(displayDevice, repaintEverything);
}
- logLayerStats();
-
postFrame();
postComposition();
@@ -1904,6 +1902,10 @@
auto display = displayDevice->getCompositionDisplay();
for (auto& layer : display->getOutputLayersOrderedByZ()) {
+ if (mDebugDisableHWC || mDebugRegion) {
+ layer->editState().forceClientComposition = true;
+ }
+
// Update the composition state of the output layer, as needed
// recomputing it from the state given by the front-end layer.
layer->updateCompositionState(updatingGeometryThisFrame);
@@ -1943,7 +1945,7 @@
if (!dirtyRegion.isEmpty()) {
base::unique_fd readyFence;
// redraw the whole screen
- doComposeSurfaces(displayDevice, dirtyRegion, &readyFence);
+ display->composeSurfaces(dirtyRegion, &readyFence);
display->getRenderSurface()->queueBuffer(std::move(readyFence));
}
@@ -1958,20 +1960,6 @@
displayDevice->getCompositionDisplay()->prepareFrame();
}
-void SurfaceFlinger::logLayerStats() {
- ATRACE_CALL();
- if (CC_UNLIKELY(mLayerStats.isEnabled())) {
- for (const auto& [token, display] : mDisplays) {
- if (display->isPrimary()) {
- mLayerStats.logLayerStats(dumpVisibleLayersProtoInfo(display));
- return;
- }
- }
-
- ALOGE("logLayerStats: no primary display");
- }
-}
-
void SurfaceFlinger::updateCompositorTiming(const DisplayStatInfo& stats, nsecs_t compositeTime,
std::shared_ptr<FenceTime>& presentFenceTime) {
// Update queue of past composite+present times and determine the
@@ -2488,6 +2476,7 @@
creationArgs.displaySurface = dispSurface;
creationArgs.hasWideColorGamut = false;
creationArgs.supportedPerFrameMetadata = 0;
+ creationArgs.powerAdvisor = displayId ? &mPowerAdvisor : nullptr;
const bool isInternalDisplay = displayId && displayId == getInternalDisplayIdLocked();
creationArgs.isPrimary = isInternalDisplay;
@@ -3228,201 +3217,12 @@
ALOGV("doDisplayComposition");
base::unique_fd readyFence;
- if (!doComposeSurfaces(displayDevice, Region::INVALID_REGION, &readyFence)) return;
+ if (!display->composeSurfaces(Region::INVALID_REGION, &readyFence)) return;
// swap buffers (presentation)
display->getRenderSurface()->queueBuffer(std::move(readyFence));
}
-bool SurfaceFlinger::doComposeSurfaces(const sp<DisplayDevice>& displayDevice,
- const Region& debugRegion, base::unique_fd* readyFence) {
- ATRACE_CALL();
- ALOGV("doComposeSurfaces");
-
- auto display = displayDevice->getCompositionDisplay();
- const auto& displayState = display->getState();
- const auto displayId = display->getId();
- auto& renderEngine = getRenderEngine();
- const bool supportProtectedContent = renderEngine.supportsProtectedContent();
-
- const Region bounds(displayState.bounds);
- const DisplayRenderArea renderArea(displayDevice);
- const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition",
- displayState.usesClientComposition};
- bool applyColorMatrix = false;
-
- renderengine::DisplaySettings clientCompositionDisplay;
- std::vector<renderengine::LayerSettings> clientCompositionLayers;
- sp<GraphicBuffer> buf;
- base::unique_fd fd;
-
- if (hasClientComposition) {
- ALOGV("hasClientComposition");
-
- if (displayDevice->isPrimary() && supportProtectedContent) {
- bool needsProtected = false;
- for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
- // If the layer is a protected layer, mark protected context is needed.
- if (layer->isProtected()) {
- needsProtected = true;
- break;
- }
- }
- if (needsProtected != renderEngine.isProtected()) {
- renderEngine.useProtectedContext(needsProtected);
- }
- if (needsProtected != display->getRenderSurface()->isProtected() &&
- needsProtected == renderEngine.isProtected()) {
- display->getRenderSurface()->setProtected(needsProtected);
- }
- }
-
- buf = display->getRenderSurface()->dequeueBuffer(&fd);
-
- if (buf == nullptr) {
- ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
- "client composition for this frame",
- displayDevice->getDisplayName().c_str());
- return false;
- }
-
- clientCompositionDisplay.physicalDisplay = displayState.scissor;
- clientCompositionDisplay.clip = displayState.scissor;
- const ui::Transform& displayTransform = displayState.transform;
- clientCompositionDisplay.globalTransform = displayTransform.asMatrix4();
- clientCompositionDisplay.orientation = displayState.orientation;
-
- const auto* profile = display->getDisplayColorProfile();
- Dataspace outputDataspace = Dataspace::UNKNOWN;
- if (profile->hasWideColorGamut()) {
- outputDataspace = displayState.dataspace;
- }
- clientCompositionDisplay.outputDataspace = outputDataspace;
- clientCompositionDisplay.maxLuminance =
- profile->getHdrCapabilities().getDesiredMaxLuminance();
-
- const bool hasDeviceComposition = displayState.usesDeviceComposition;
- const bool skipClientColorTransform =
- getHwComposer()
- .hasDisplayCapability(displayId,
- HWC2::DisplayCapability::SkipClientColorTransform);
-
- // Compute the global color transform matrix.
- applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform;
- if (applyColorMatrix) {
- clientCompositionDisplay.colorTransform = displayState.colorTransformMat;
- }
- }
-
- /*
- * and then, render the layers targeted at the framebuffer
- */
-
- ALOGV("Rendering client layers");
- const bool useIdentityTransform = false;
- bool firstLayer = true;
- Region clearRegion = Region::INVALID_REGION;
- for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
- const Region viewportRegion(displayState.viewport);
- const Region clip(viewportRegion.intersect(layer->visibleRegion));
- ALOGV("Layer: %s", layer->getName().string());
- ALOGV(" Composition type: %s", toString(layer->getCompositionType(displayDevice)).c_str());
- if (!clip.isEmpty()) {
- switch (layer->getCompositionType(displayDevice)) {
- case Hwc2::IComposerClient::Composition::CURSOR:
- case Hwc2::IComposerClient::Composition::DEVICE:
- case Hwc2::IComposerClient::Composition::SIDEBAND:
- case Hwc2::IComposerClient::Composition::SOLID_COLOR: {
- LOG_ALWAYS_FATAL_IF(!displayId);
- const Layer::State& state(layer->getDrawingState());
- if (layer->getClearClientTarget(displayDevice) && !firstLayer &&
- layer->isOpaque(state) && (layer->getAlpha() == 1.0f) &&
- layer->getRoundedCornerState().radius == 0.0f && hasClientComposition) {
- // never clear the very first layer since we're
- // guaranteed the FB is already cleared
- Region dummyRegion;
- compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{
- clip,
- useIdentityTransform,
- layer->needsFiltering(renderArea.getDisplayDevice()) ||
- renderArea.needsFiltering(),
- renderArea.isSecure(),
- supportProtectedContent,
- dummyRegion,
- };
- auto result = layer->prepareClientComposition(targetSettings);
-
- if (result) {
- auto& layerSettings = *result;
- layerSettings.source.buffer.buffer = nullptr;
- layerSettings.source.solidColor = half3(0.0, 0.0, 0.0);
- layerSettings.alpha = half(0.0);
- layerSettings.disableBlending = true;
- clientCompositionLayers.push_back(layerSettings);
- }
- }
- break;
- }
- case Hwc2::IComposerClient::Composition::CLIENT: {
- compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{
- clip,
- useIdentityTransform,
- layer->needsFiltering(renderArea.getDisplayDevice()) ||
- renderArea.needsFiltering(),
- renderArea.isSecure(),
- supportProtectedContent,
- clearRegion,
- };
- auto result = layer->prepareClientComposition(targetSettings);
- if (result) {
- clientCompositionLayers.push_back(*result);
- }
- break;
- }
- default:
- break;
- }
- } else {
- ALOGV(" Skipping for empty clip");
- }
- firstLayer = false;
- }
-
- // Perform some cleanup steps if we used client composition.
- if (hasClientComposition) {
- clientCompositionDisplay.clearRegion = clearRegion;
-
- // We boost GPU frequency here because there will be color spaces conversion
- // and it's expensive. We boost the GPU frequency so that GPU composition can
- // finish in time. We must reset GPU frequency afterwards, because high frequency
- // consumes extra battery.
- const bool expensiveRenderingExpected =
- clientCompositionDisplay.outputDataspace == Dataspace::DISPLAY_P3;
- if (expensiveRenderingExpected && displayId) {
- mPowerAdvisor.setExpensiveRenderingExpected(*displayId, true);
- }
- if (!debugRegion.isEmpty()) {
- Region::const_iterator it = debugRegion.begin();
- Region::const_iterator end = debugRegion.end();
- while (it != end) {
- const Rect& rect = *it++;
- renderengine::LayerSettings layerSettings;
- layerSettings.source.buffer.buffer = nullptr;
- layerSettings.source.solidColor = half3(1.0, 0.0, 1.0);
- layerSettings.geometry.boundaries = rect.toFloatRect();
- layerSettings.alpha = half(1.0);
- clientCompositionLayers.push_back(layerSettings);
- }
- }
- renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayers,
- buf->getNativeBuffer(), /*useFramebufferCache=*/true, std::move(fd),
- readyFence);
- } else if (displayId) {
- mPowerAdvisor.setExpensiveRenderingExpected(*displayId, false);
- }
- return true;
-}
-
status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc,
const sp<IBinder>& parentHandle,
@@ -3441,7 +3241,7 @@
}
if (mNumLayers >= MAX_LAYERS) {
- ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers,
+ ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers.load(),
MAX_LAYERS);
return NO_MEMORY;
}
@@ -3465,7 +3265,7 @@
mMaxGraphicBufferProducerListSize,
"Suspected IGBP leak: %zu IGBPs (%zu max), %zu Layers",
mGraphicBufferProducerList.size(),
- mMaxGraphicBufferProducerListSize, mNumLayers);
+ mMaxGraphicBufferProducerListSize, mNumLayers.load());
}
mLayersAdded = true;
}
@@ -3677,6 +3477,7 @@
if (uncacheBuffer.isValid()) {
ClientCache::getInstance().erase(uncacheBuffer);
+ getRenderEngine().unbindExternalTextureBuffer(uncacheBuffer.id);
}
// If a synchronous transaction is explicitly requested without any changes, force a transaction
@@ -4039,12 +3840,18 @@
bool bufferChanged = what & layer_state_t::eBufferChanged;
bool cacheIdChanged = what & layer_state_t::eCachedBufferChanged;
sp<GraphicBuffer> buffer;
- if (bufferChanged && cacheIdChanged) {
- ClientCache::getInstance().add(s.cachedBuffer, s.buffer);
- ClientCache::getInstance().registerErasedRecipient(s.cachedBuffer,
- wp<ClientCache::ErasedRecipient>(layer));
- getRenderEngine().cacheExternalTextureBuffer(s.buffer);
+ if (bufferChanged && cacheIdChanged && s.buffer != nullptr) {
buffer = s.buffer;
+ bool success = ClientCache::getInstance().add(s.cachedBuffer, s.buffer);
+ if (success) {
+ getRenderEngine().cacheExternalTextureBuffer(s.buffer);
+ success = ClientCache::getInstance()
+ .registerErasedRecipient(s.cachedBuffer,
+ wp<ClientCache::ErasedRecipient>(this));
+ if (!success) {
+ getRenderEngine().unbindExternalTextureBuffer(s.buffer->getId());
+ }
+ }
} else if (cacheIdChanged) {
buffer = ClientCache::getInstance().get(s.cachedBuffer);
} else if (bufferChanged) {
@@ -4465,14 +4272,10 @@
using namespace std::string_literals;
static const std::unordered_map<std::string, Dumper> dumpers = {
- {"--clear-layer-stats"s, dumper([this](std::string&) { mLayerStats.clear(); })},
- {"--disable-layer-stats"s, dumper([this](std::string&) { mLayerStats.disable(); })},
{"--display-id"s, dumper(&SurfaceFlinger::dumpDisplayIdentificationData)},
{"--dispsync"s, dumper([this](std::string& s) {
mScheduler->dumpPrimaryDispSync(s);
})},
- {"--dump-layer-stats"s, dumper([this](std::string& s) { mLayerStats.dump(s); })},
- {"--enable-layer-stats"s, dumper([this](std::string&) { mLayerStats.enable(); })},
{"--frame-events"s, dumper(&SurfaceFlinger::dumpFrameEventsLocked)},
{"--latency"s, argsDumper(&SurfaceFlinger::dumpStatsLocked)},
{"--latency-clear"s, argsDumper(&SurfaceFlinger::clearStatsLocked)},
@@ -4485,7 +4288,8 @@
const auto flag = args.empty() ? ""s : std::string(String8(args[0]));
- if (const auto it = dumpers.find(flag); it != dumpers.end()) {
+ const auto it = dumpers.find(flag);
+ if (it != dumpers.end()) {
(it->second)(args, asProto, result);
} else if (!asProto) {
dumpAllLocked(args, result);
@@ -4495,13 +4299,15 @@
mStateLock.unlock();
}
- LayersProto layersProto = dumpProtoFromMainThread();
- if (asProto) {
- result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize());
- } else {
- auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
- result.append(LayerProtoParser::layerTreeToString(layerTree));
- result.append("\n");
+ if (it == dumpers.end()) {
+ const LayersProto layersProto = dumpProtoFromMainThread();
+ if (asProto) {
+ result.append(layersProto.SerializeAsString());
+ } else {
+ const auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
+ result.append(LayerProtoParser::layerTreeToString(layerTree));
+ result.append("\n");
+ }
}
}
write(fd, result.c_str(), result.size());
@@ -4760,33 +4566,6 @@
return layersProto;
}
-LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(
- const sp<DisplayDevice>& displayDevice) const {
- LayersProto layersProto;
-
- SizeProto* resolution = layersProto.mutable_resolution();
- resolution->set_w(displayDevice->getWidth());
- resolution->set_h(displayDevice->getHeight());
-
- auto display = displayDevice->getCompositionDisplay();
- const auto& displayState = display->getState();
-
- layersProto.set_color_mode(decodeColorMode(displayState.colorMode));
- layersProto.set_color_transform(decodeColorTransform(displayState.colorTransform));
- layersProto.set_global_transform(displayState.orientation);
-
- const auto displayId = displayDevice->getId();
- LOG_ALWAYS_FATAL_IF(!displayId);
- mDrawingState.traverseInZOrder([&](Layer* layer) {
- if (!layer->visibleRegion.isEmpty() && !display->getOutputLayersOrderedByZ().empty()) {
- LayerProto* layerProto = layersProto.add_layers();
- layer->writeToProtoCompositionState(layerProto, displayDevice);
- }
- });
-
- return layersProto;
-}
-
void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) const {
const bool colorize = !args.empty() && args[0] == String16("--color");
Colorizer colorizer(colorize);
@@ -4839,7 +4618,7 @@
* Dump the visible layer list
*/
colorizer.bold(result);
- StringAppendF(&result, "Visible layers (count = %zu)\n", mNumLayers);
+ StringAppendF(&result, "Visible layers (count = %zu)\n", mNumLayers.load());
StringAppendF(&result, "GraphicBufferProducers: %zu, max %zu\n",
mGraphicBufferProducerList.size(), mMaxGraphicBufferProducerListSize);
colorizer.reset(result);
@@ -5645,10 +5424,13 @@
drawLayers();
} else {
Rect bounds = getBounds();
- screenshotParentLayer = mFlinger->getFactory().createContainerLayer(
- LayerCreationArgs(mFlinger, nullptr, String8("Screenshot Parent"),
- bounds.getWidth(), bounds.getHeight(), 0,
- LayerMetadata()));
+ // 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(
+ LayerCreationArgs(mFlinger, nullptr, String8("Screenshot Parent"),
+ bounds.getWidth(), bounds.getHeight(), 0,
+ LayerMetadata()));
ReparentForDrawing reparent(mLayer, screenshotParentLayer, sourceCrop);
drawLayers();
@@ -5659,9 +5441,6 @@
const sp<Layer> mLayer;
const Rect mCrop;
- // 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;
ui::Transform mTransform;
bool mNeedsFiltering;
@@ -6096,6 +5875,10 @@
return nullptr;
}
+void SurfaceFlinger::bufferErased(const client_cache_t& clientCacheId) {
+ getRenderEngine().unbindExternalTextureBuffer(clientCacheId.id);
+}
+
} // namespace android
#if defined(__gl_h_)
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 3974a8c..e199ad5 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -52,7 +52,6 @@
#include "DisplayHardware/PowerAdvisor.h"
#include "Effects/Daltonizer.h"
#include "FrameTracker.h"
-#include "LayerStats.h"
#include "LayerVector.h"
#include "Scheduler/RefreshRateConfigs.h"
#include "Scheduler/RefreshRateStats.h"
@@ -172,9 +171,9 @@
class SurfaceFlinger : public BnSurfaceComposer,
public PriorityDumper,
+ public ClientCache::ErasedRecipient,
private IBinder::DeathRecipient,
- private HWC2::ComposerCallback
-{
+ private HWC2::ComposerCallback {
public:
SurfaceFlingerBE& getBE() { return mBE; }
const SurfaceFlingerBE& getBE() const { return mBE; }
@@ -322,6 +321,9 @@
sp<Layer> fromHandle(const sp<IBinder>& handle) REQUIRES(mStateLock);
+ // Inherit from ClientCache::ErasedRecipient
+ void bufferErased(const client_cache_t& clientCacheId) override;
+
private:
friend class BufferLayer;
friend class BufferQueueLayer;
@@ -762,15 +764,8 @@
void calculateWorkingSet();
void doComposition(const sp<DisplayDevice>& display, bool repainEverything);
void doDebugFlashRegions(const sp<DisplayDevice>& display, bool repaintEverything);
- void logLayerStats();
void doDisplayComposition(const sp<DisplayDevice>& display, const Region& dirtyRegion);
- // This fails if using GL and the surface has been destroyed. readyFence
- // will be populated if using GL and native fence sync is supported, to
- // signal when drawing has completed.
- bool doComposeSurfaces(const sp<DisplayDevice>& display, const Region& debugRegionm,
- base::unique_fd* readyFence);
-
void postFrame();
/* ------------------------------------------------------------------------
@@ -884,7 +879,6 @@
LayersProto dumpProtoFromMainThread(uint32_t traceFlags = SurfaceTracing::TRACE_ALL)
EXCLUDES(mStateLock);
void withTracingLock(std::function<void()> operation) REQUIRES(mStateLock);
- LayersProto dumpVisibleLayersProtoInfo(const sp<DisplayDevice>& display) const;
bool isLayerTripleBufferingDisabled() const {
return this->mLayerTripleBufferingDisabled;
@@ -1001,7 +995,6 @@
SurfaceTracing mTracing{*this};
bool mTracingEnabled = false;
bool mTracingEnabledChanged GUARDED_BY(mStateLock) = false;
- LayerStats mLayerStats;
const std::shared_ptr<TimeStats> mTimeStats;
bool mUseHwcVirtualDisplays = false;
std::atomic<uint32_t> mFrameMissedCount = 0;
@@ -1072,7 +1065,7 @@
// Static screen stats
bool mHasPoweredOff = false;
- size_t mNumLayers = 0;
+ std::atomic<size_t> mNumLayers = 0;
// Verify that transaction is being called by an approved process:
// either AID_GRAPHICS or AID_SYSTEM.
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index c97a19b..93fe7d0 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -173,8 +173,8 @@
ALOGV("[%d]-[%" PRIu64 "]-presentFenceTime[%" PRId64 "]", layerID,
timeRecords[0].frameTime.frameNumber, timeRecords[0].frameTime.presentTime);
- const std::string& layerName = layerRecord.layerName;
if (prevTimeRecord.ready) {
+ const std::string& layerName = layerRecord.layerName;
if (!mTimeStats.stats.count(layerName)) {
mTimeStats.stats[layerName].layerName = layerName;
mTimeStats.stats[layerName].packageName = getPackageName(layerName);
@@ -220,18 +220,6 @@
timeRecords[0].frameTime.frameNumber, presentToPresentMs);
timeStatsLayer.deltas["present2present"].insert(presentToPresentMs);
}
-
- // Output additional trace points to track frame time.
- ATRACE_INT64(("TimeStats-Post - " + layerName).c_str(), timeRecords[0].frameTime.postTime);
- ATRACE_INT64(("TimeStats-Acquire - " + layerName).c_str(),
- timeRecords[0].frameTime.acquireTime);
- ATRACE_INT64(("TimeStats-Latch - " + layerName).c_str(),
- timeRecords[0].frameTime.latchTime);
- ATRACE_INT64(("TimeStats-Desired - " + layerName).c_str(),
- timeRecords[0].frameTime.desiredTime);
- ATRACE_INT64(("TimeStats-Present - " + layerName).c_str(),
- timeRecords[0].frameTime.presentTime);
-
prevTimeRecord = timeRecords[0];
timeRecords.pop_front();
layerRecord.waitData--;
@@ -613,7 +601,7 @@
if (asProto) {
ALOGD("Dumping TimeStats as proto");
SFTimeStatsGlobalProto timeStatsProto = mTimeStats.toProto(maxLayers);
- result.append(timeStatsProto.SerializeAsString().c_str(), timeStatsProto.ByteSize());
+ result.append(timeStatsProto.SerializeAsString());
} else {
ALOGD("Dumping TimeStats as text");
result.append(mTimeStats.toString(maxLayers));
diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
index d3381e5..ef488bd 100644
--- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp
+++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
@@ -37,16 +37,6 @@
return lhs->id < rhs->id;
}
-const LayerProtoParser::LayerGlobal LayerProtoParser::generateLayerGlobalInfo(
- const LayersProto& layersProto) {
- LayerGlobal layerGlobal;
- layerGlobal.resolution = {layersProto.resolution().w(), layersProto.resolution().h()};
- layerGlobal.colorMode = layersProto.color_mode();
- layerGlobal.colorTransform = layersProto.color_transform();
- layerGlobal.globalTransform = layersProto.global_transform();
- return layerGlobal;
-}
-
LayerProtoParser::LayerTree LayerProtoParser::generateLayerTree(const LayersProto& layersProto) {
LayerTree layerTree;
layerTree.allLayers = generateLayerList(layersProto);
@@ -114,10 +104,6 @@
layer.bufferTransform = generateTransform(layerProto.buffer_transform());
layer.queuedFrames = layerProto.queued_frames();
layer.refreshPending = layerProto.refresh_pending();
- layer.hwcFrame = generateRect(layerProto.hwc_frame());
- layer.hwcCrop = generateFloatRect(layerProto.hwc_crop());
- layer.hwcTransform = layerProto.hwc_transform();
- layer.hwcCompositionType = layerProto.hwc_composition_type();
layer.isProtected = layerProto.is_protected();
layer.cornerRadius = layerProto.corner_radius();
for (const auto& entry : layerProto.metadata()) {
diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
index d1b2b1f..54e02ca 100644
--- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
+++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
@@ -108,10 +108,6 @@
Transform bufferTransform;
int32_t queuedFrames;
bool refreshPending;
- LayerProtoParser::Rect hwcFrame;
- LayerProtoParser::FloatRect hwcCrop;
- int32_t hwcTransform;
- int32_t hwcCompositionType;
bool isProtected;
float cornerRadius;
LayerMetadata metadata;
@@ -119,14 +115,6 @@
std::string to_string() const;
};
- class LayerGlobal {
- public:
- int2 resolution;
- std::string colorMode;
- std::string colorTransform;
- int32_t globalTransform;
- };
-
class LayerTree {
public:
// all layers in LayersProto and in the original order
@@ -136,7 +124,6 @@
std::vector<Layer*> topLevelLayers;
};
- static const LayerGlobal generateLayerGlobalInfo(const LayersProto& layersProto);
static LayerTree generateLayerTree(const LayersProto& layersProto);
static std::string layerTreeToString(const LayerTree& layerTree);
diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
index b097505..c7fbff3 100644
--- a/services/surfaceflinger/layerproto/layers.proto
+++ b/services/surfaceflinger/layerproto/layers.proto
@@ -7,10 +7,6 @@
// Contains a list of all layers.
message LayersProto {
repeated LayerProto layers = 1;
- SizeProto resolution = 2;
- string color_mode = 3;
- string color_transform = 4;
- int32 global_transform = 5;
}
// Information about each layer.
diff --git a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
new file mode 100644
index 0000000..b66e56e
--- /dev/null
+++ b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
@@ -0,0 +1,138 @@
+props {
+ module: "android.sysprop.SurfaceFlingerProperties"
+ prop {
+ api_name: "color_space_agnostic_dataspace"
+ type: Long
+ prop_name: "ro.surface_flinger.color_space_agnostic_dataspace"
+ }
+ prop {
+ api_name: "default_composition_dataspace"
+ type: Long
+ prop_name: "ro.surface_flinger.default_composition_dataspace"
+ }
+ prop {
+ api_name: "default_composition_pixel_format"
+ type: Integer
+ prop_name: "ro.surface_flinger.default_composition_pixel_format"
+ }
+ prop {
+ api_name: "display_primary_blue"
+ type: DoubleList
+ prop_name: "ro.surface_flinger.display_primary_blue"
+ }
+ prop {
+ api_name: "display_primary_green"
+ type: DoubleList
+ prop_name: "ro.surface_flinger.display_primary_green"
+ }
+ prop {
+ api_name: "display_primary_red"
+ type: DoubleList
+ prop_name: "ro.surface_flinger.display_primary_red"
+ }
+ prop {
+ api_name: "display_primary_white"
+ type: DoubleList
+ prop_name: "ro.surface_flinger.display_primary_white"
+ }
+ prop {
+ api_name: "enable_protected_contents"
+ prop_name: "ro.surface_flinger.protected_contents"
+ }
+ prop {
+ api_name: "force_hwc_copy_for_virtual_displays"
+ prop_name: "ro.surface_flinger.force_hwc_copy_for_virtual_displays"
+ }
+ prop {
+ api_name: "has_HDR_display"
+ prop_name: "ro.surface_flinger.has_HDR_display"
+ }
+ prop {
+ api_name: "has_wide_color_display"
+ prop_name: "ro.surface_flinger.has_wide_color_display"
+ }
+ prop {
+ api_name: "max_frame_buffer_acquired_buffers"
+ type: Long
+ prop_name: "ro.surface_flinger.max_frame_buffer_acquired_buffers"
+ }
+ prop {
+ api_name: "max_virtual_display_dimension"
+ type: Long
+ prop_name: "ro.surface_flinger.max_virtual_display_dimension"
+ }
+ prop {
+ api_name: "present_time_offset_from_vsync_ns"
+ type: Long
+ prop_name: "ro.surface_flinger.present_time_offset_from_vsync_ns"
+ }
+ prop {
+ api_name: "primary_display_orientation"
+ type: Enum
+ prop_name: "ro.surface_flinger.primary_display_orientation"
+ enum_values: "ORIENTATION_0|ORIENTATION_90|ORIENTATION_180|ORIENTATION_270"
+ }
+ prop {
+ api_name: "running_without_sync_framework"
+ prop_name: "ro.surface_flinger.running_without_sync_framework"
+ }
+ prop {
+ api_name: "set_display_power_timer_ms"
+ type: Integer
+ prop_name: "ro.surface_flinger.set_display_power_timer_ms"
+ }
+ prop {
+ api_name: "set_idle_timer_ms"
+ type: Integer
+ prop_name: "ro.surface_flinger.set_idle_timer_ms"
+ }
+ prop {
+ api_name: "set_touch_timer_ms"
+ type: Integer
+ prop_name: "ro.surface_flinger.set_touch_timer_ms"
+ }
+ prop {
+ api_name: "start_graphics_allocator_service"
+ prop_name: "ro.surface_flinger.start_graphics_allocator_service"
+ }
+ prop {
+ api_name: "support_kernel_idle_timer"
+ prop_name: "ro.surface_flinger.support_kernel_idle_timer"
+ }
+ prop {
+ api_name: "use_color_management"
+ prop_name: "ro.surface_flinger.use_color_management"
+ }
+ prop {
+ api_name: "use_context_priority"
+ prop_name: "ro.surface_flinger.use_context_priority"
+ }
+ prop {
+ api_name: "use_smart_90_for_video"
+ prop_name: "ro.surface_flinger.use_smart_90_for_video"
+ }
+ prop {
+ api_name: "use_vr_flinger"
+ prop_name: "ro.surface_flinger.use_vr_flinger"
+ }
+ prop {
+ api_name: "vsync_event_phase_offset_ns"
+ type: Long
+ prop_name: "ro.surface_flinger.vsync_event_phase_offset_ns"
+ }
+ prop {
+ api_name: "vsync_sf_event_phase_offset_ns"
+ type: Long
+ prop_name: "ro.surface_flinger.vsync_sf_event_phase_offset_ns"
+ }
+ prop {
+ api_name: "wcg_composition_dataspace"
+ type: Long
+ prop_name: "ro.surface_flinger.wcg_composition_dataspace"
+ }
+ prop {
+ api_name: "wcg_composition_pixel_format"
+ type: Integer
+ prop_name: "ro.surface_flinger.wcg_composition_pixel_format"
+ }
+}
diff --git a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-latest.txt b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-latest.txt
new file mode 100644
index 0000000..b66e56e
--- /dev/null
+++ b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-latest.txt
@@ -0,0 +1,138 @@
+props {
+ module: "android.sysprop.SurfaceFlingerProperties"
+ prop {
+ api_name: "color_space_agnostic_dataspace"
+ type: Long
+ prop_name: "ro.surface_flinger.color_space_agnostic_dataspace"
+ }
+ prop {
+ api_name: "default_composition_dataspace"
+ type: Long
+ prop_name: "ro.surface_flinger.default_composition_dataspace"
+ }
+ prop {
+ api_name: "default_composition_pixel_format"
+ type: Integer
+ prop_name: "ro.surface_flinger.default_composition_pixel_format"
+ }
+ prop {
+ api_name: "display_primary_blue"
+ type: DoubleList
+ prop_name: "ro.surface_flinger.display_primary_blue"
+ }
+ prop {
+ api_name: "display_primary_green"
+ type: DoubleList
+ prop_name: "ro.surface_flinger.display_primary_green"
+ }
+ prop {
+ api_name: "display_primary_red"
+ type: DoubleList
+ prop_name: "ro.surface_flinger.display_primary_red"
+ }
+ prop {
+ api_name: "display_primary_white"
+ type: DoubleList
+ prop_name: "ro.surface_flinger.display_primary_white"
+ }
+ prop {
+ api_name: "enable_protected_contents"
+ prop_name: "ro.surface_flinger.protected_contents"
+ }
+ prop {
+ api_name: "force_hwc_copy_for_virtual_displays"
+ prop_name: "ro.surface_flinger.force_hwc_copy_for_virtual_displays"
+ }
+ prop {
+ api_name: "has_HDR_display"
+ prop_name: "ro.surface_flinger.has_HDR_display"
+ }
+ prop {
+ api_name: "has_wide_color_display"
+ prop_name: "ro.surface_flinger.has_wide_color_display"
+ }
+ prop {
+ api_name: "max_frame_buffer_acquired_buffers"
+ type: Long
+ prop_name: "ro.surface_flinger.max_frame_buffer_acquired_buffers"
+ }
+ prop {
+ api_name: "max_virtual_display_dimension"
+ type: Long
+ prop_name: "ro.surface_flinger.max_virtual_display_dimension"
+ }
+ prop {
+ api_name: "present_time_offset_from_vsync_ns"
+ type: Long
+ prop_name: "ro.surface_flinger.present_time_offset_from_vsync_ns"
+ }
+ prop {
+ api_name: "primary_display_orientation"
+ type: Enum
+ prop_name: "ro.surface_flinger.primary_display_orientation"
+ enum_values: "ORIENTATION_0|ORIENTATION_90|ORIENTATION_180|ORIENTATION_270"
+ }
+ prop {
+ api_name: "running_without_sync_framework"
+ prop_name: "ro.surface_flinger.running_without_sync_framework"
+ }
+ prop {
+ api_name: "set_display_power_timer_ms"
+ type: Integer
+ prop_name: "ro.surface_flinger.set_display_power_timer_ms"
+ }
+ prop {
+ api_name: "set_idle_timer_ms"
+ type: Integer
+ prop_name: "ro.surface_flinger.set_idle_timer_ms"
+ }
+ prop {
+ api_name: "set_touch_timer_ms"
+ type: Integer
+ prop_name: "ro.surface_flinger.set_touch_timer_ms"
+ }
+ prop {
+ api_name: "start_graphics_allocator_service"
+ prop_name: "ro.surface_flinger.start_graphics_allocator_service"
+ }
+ prop {
+ api_name: "support_kernel_idle_timer"
+ prop_name: "ro.surface_flinger.support_kernel_idle_timer"
+ }
+ prop {
+ api_name: "use_color_management"
+ prop_name: "ro.surface_flinger.use_color_management"
+ }
+ prop {
+ api_name: "use_context_priority"
+ prop_name: "ro.surface_flinger.use_context_priority"
+ }
+ prop {
+ api_name: "use_smart_90_for_video"
+ prop_name: "ro.surface_flinger.use_smart_90_for_video"
+ }
+ prop {
+ api_name: "use_vr_flinger"
+ prop_name: "ro.surface_flinger.use_vr_flinger"
+ }
+ prop {
+ api_name: "vsync_event_phase_offset_ns"
+ type: Long
+ prop_name: "ro.surface_flinger.vsync_event_phase_offset_ns"
+ }
+ prop {
+ api_name: "vsync_sf_event_phase_offset_ns"
+ type: Long
+ prop_name: "ro.surface_flinger.vsync_sf_event_phase_offset_ns"
+ }
+ prop {
+ api_name: "wcg_composition_dataspace"
+ type: Long
+ prop_name: "ro.surface_flinger.wcg_composition_dataspace"
+ }
+ prop {
+ api_name: "wcg_composition_pixel_format"
+ type: Integer
+ prop_name: "ro.surface_flinger.wcg_composition_pixel_format"
+ }
+}
diff --git a/services/surfaceflinger/sysprop/api/current.txt b/services/surfaceflinger/sysprop/api/current.txt
deleted file mode 100644
index d802177..0000000
--- a/services/surfaceflinger/sysprop/api/current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/services/surfaceflinger/sysprop/api/removed.txt b/services/surfaceflinger/sysprop/api/removed.txt
deleted file mode 100644
index d802177..0000000
--- a/services/surfaceflinger/sysprop/api/removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/services/surfaceflinger/sysprop/api/system-current.txt b/services/surfaceflinger/sysprop/api/system-current.txt
deleted file mode 100644
index 79854b3..0000000
--- a/services/surfaceflinger/sysprop/api/system-current.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-// Signature format: 2.0
-package android.sysprop {
-
- public final class SurfaceFlingerProperties {
- method public static java.util.Optional<java.lang.Long> color_space_agnostic_dataspace();
- method public static java.util.Optional<java.lang.Long> default_composition_dataspace();
- method public static java.util.Optional<java.lang.Integer> default_composition_pixel_format();
- method public static java.util.List<java.lang.Double> display_primary_blue();
- method public static java.util.List<java.lang.Double> display_primary_green();
- method public static java.util.List<java.lang.Double> display_primary_red();
- method public static java.util.List<java.lang.Double> display_primary_white();
- method public static java.util.Optional<java.lang.Boolean> enable_protected_contents();
- method public static java.util.Optional<java.lang.Boolean> force_hwc_copy_for_virtual_displays();
- method public static java.util.Optional<java.lang.Boolean> has_HDR_display();
- method public static java.util.Optional<java.lang.Boolean> has_wide_color_display();
- method public static java.util.Optional<java.lang.Long> max_frame_buffer_acquired_buffers();
- method public static java.util.Optional<java.lang.Long> max_virtual_display_dimension();
- method public static java.util.Optional<java.lang.Long> present_time_offset_from_vsync_ns();
- method public static java.util.Optional<android.sysprop.SurfaceFlingerProperties.primary_display_orientation_values> primary_display_orientation();
- method public static java.util.Optional<java.lang.Boolean> running_without_sync_framework();
- method public static java.util.Optional<java.lang.Integer> set_display_power_timer_ms();
- method public static java.util.Optional<java.lang.Integer> set_idle_timer_ms();
- method public static java.util.Optional<java.lang.Integer> set_touch_timer_ms();
- method public static java.util.Optional<java.lang.Boolean> start_graphics_allocator_service();
- method public static java.util.Optional<java.lang.Boolean> support_kernel_idle_timer();
- method public static java.util.Optional<java.lang.Boolean> use_color_management();
- method public static java.util.Optional<java.lang.Boolean> use_context_priority();
- method public static java.util.Optional<java.lang.Boolean> use_smart_90_for_video();
- method public static java.util.Optional<java.lang.Boolean> use_vr_flinger();
- method public static java.util.Optional<java.lang.Long> vsync_event_phase_offset_ns();
- method public static java.util.Optional<java.lang.Long> vsync_sf_event_phase_offset_ns();
- method public static java.util.Optional<java.lang.Long> wcg_composition_dataspace();
- method public static java.util.Optional<java.lang.Integer> wcg_composition_pixel_format();
- }
-
- public enum SurfaceFlingerProperties.primary_display_orientation_values {
- method public String getPropValue();
- enum_constant public static final android.sysprop.SurfaceFlingerProperties.primary_display_orientation_values ORIENTATION_0;
- enum_constant public static final android.sysprop.SurfaceFlingerProperties.primary_display_orientation_values ORIENTATION_180;
- enum_constant public static final android.sysprop.SurfaceFlingerProperties.primary_display_orientation_values ORIENTATION_270;
- enum_constant public static final android.sysprop.SurfaceFlingerProperties.primary_display_orientation_values ORIENTATION_90;
- }
-
-}
-
diff --git a/services/surfaceflinger/sysprop/api/system-removed.txt b/services/surfaceflinger/sysprop/api/system-removed.txt
deleted file mode 100644
index d802177..0000000
--- a/services/surfaceflinger/sysprop/api/system-removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/services/surfaceflinger/sysprop/api/test-current.txt b/services/surfaceflinger/sysprop/api/test-current.txt
deleted file mode 100644
index d802177..0000000
--- a/services/surfaceflinger/sysprop/api/test-current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/services/surfaceflinger/sysprop/api/test-removed.txt b/services/surfaceflinger/sysprop/api/test-removed.txt
deleted file mode 100644
index d802177..0000000
--- a/services/surfaceflinger/sysprop/api/test-removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 47243a9..82dd3c7 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -34,7 +34,6 @@
#include "ColorLayer.h"
#include "Layer.h"
-#include "TestableScheduler.h"
#include "TestableSurfaceFlinger.h"
#include "mock/DisplayHardware/MockComposer.h"
#include "mock/MockDispSync.h"
@@ -95,10 +94,6 @@
mFlinger.mutableEventQueue().reset(mMessageQueue);
setupScheduler();
- EXPECT_CALL(*mPrimaryDispSync, computeNextRefresh(0)).WillRepeatedly(Return(0));
- EXPECT_CALL(*mPrimaryDispSync, getPeriod())
- .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
- EXPECT_CALL(*mPrimaryDispSync, expectedPresentTime()).WillRepeatedly(Return(0));
EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
.WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_DISPLAY_WIDTH), Return(0)));
EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
@@ -125,15 +120,22 @@
}
void setupScheduler() {
- mScheduler = new TestableScheduler(mFlinger.mutableRefreshRateConfigs());
- mScheduler->mutableEventControlThread().reset(mEventControlThread);
- mScheduler->mutablePrimaryDispSync().reset(mPrimaryDispSync);
- EXPECT_CALL(*mEventThread.get(), registerDisplayEventConnection(_));
- sp<Scheduler::ConnectionHandle> connectionHandle =
- mScheduler->addConnection(std::move(mEventThread));
- mFlinger.mutableSfConnectionHandle() = std::move(connectionHandle);
+ auto eventThread = std::make_unique<mock::EventThread>();
+ auto sfEventThread = std::make_unique<mock::EventThread>();
- mFlinger.mutableScheduler().reset(mScheduler);
+ EXPECT_CALL(*eventThread, registerDisplayEventConnection(_));
+ EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_));
+
+ auto primaryDispSync = std::make_unique<mock::DispSync>();
+
+ EXPECT_CALL(*primaryDispSync, computeNextRefresh(0)).WillRepeatedly(Return(0));
+ EXPECT_CALL(*primaryDispSync, getPeriod())
+ .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+ EXPECT_CALL(*primaryDispSync, expectedPresentTime()).WillRepeatedly(Return(0));
+
+ mFlinger.setupScheduler(std::move(primaryDispSync),
+ std::make_unique<mock::EventControlThread>(),
+ std::move(eventThread), std::move(sfEventThread));
}
void setupForceGeometryDirty() {
@@ -157,7 +159,6 @@
std::unordered_set<HWC2::Capability> mDefaultCapabilities = {HWC2::Capability::SidebandStream};
- TestableScheduler* mScheduler;
TestableSurfaceFlinger mFlinger;
sp<DisplayDevice> mDisplay;
sp<DisplayDevice> mExternalDisplay;
@@ -168,13 +169,9 @@
sp<GraphicBuffer> mBuffer = new GraphicBuffer();
ANativeWindowBuffer* mNativeWindowBuffer = mBuffer->getNativeBuffer();
- std::unique_ptr<mock::EventThread> mEventThread = std::make_unique<mock::EventThread>();
- mock::EventControlThread* mEventControlThread = new mock::EventControlThread();
-
Hwc2::mock::Composer* mComposer = nullptr;
renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
mock::MessageQueue* mMessageQueue = new mock::MessageQueue();
- mock::DispSync* mPrimaryDispSync = new mock::DispSync();
sp<Fence> mClientTargetAcquireFence = Fence::NO_FENCE;
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 5f58e7d..8f6f3ec 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -95,11 +95,10 @@
DisplayTransactionTest();
~DisplayTransactionTest() override;
- void setupScheduler();
-
// --------------------------------------------------------------------
// Mock/Fake injection
+ void injectMockScheduler();
void injectMockComposer(int virtualDisplayCount);
void injectFakeBufferQueueFactory();
void injectFakeNativeWindowSurfaceFactory();
@@ -119,11 +118,7 @@
// --------------------------------------------------------------------
// Test instances
- TestableScheduler* mScheduler;
TestableSurfaceFlinger mFlinger;
- mock::EventThread* mEventThread = new mock::EventThread();
- mock::EventThread* mSFEventThread = new mock::EventThread();
- mock::EventControlThread* mEventControlThread = new mock::EventControlThread();
sp<mock::NativeWindow> mNativeWindow = new mock::NativeWindow();
sp<GraphicBuffer> mBuffer = new GraphicBuffer();
@@ -134,7 +129,11 @@
Hwc2::mock::Composer* mComposer = nullptr;
mock::MessageQueue* mMessageQueue = new mock::MessageQueue();
mock::SurfaceInterceptor* mSurfaceInterceptor = new mock::SurfaceInterceptor();
- mock::DispSync* mPrimaryDispSync = new mock::DispSync();
+
+ mock::DispSync* mPrimaryDispSync = new mock::DispSync;
+ mock::EventControlThread* mEventControlThread = new mock::EventControlThread;
+ mock::EventThread* mEventThread = new mock::EventThread;
+ mock::EventThread* mSFEventThread = new mock::EventThread;
// These mocks are created only when expected to be created via a factory.
sp<mock::GraphicBufferConsumer> mConsumer;
@@ -164,7 +163,7 @@
return nullptr;
});
- setupScheduler();
+ injectMockScheduler();
mFlinger.mutableEventQueue().reset(mMessageQueue);
mFlinger.setupRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine));
mFlinger.mutableInterceptor().reset(mSurfaceInterceptor);
@@ -178,20 +177,14 @@
ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
}
-void DisplayTransactionTest::setupScheduler() {
- mScheduler = new TestableScheduler(mFlinger.mutableRefreshRateConfigs());
- mScheduler->mutableEventControlThread().reset(mEventControlThread);
- mScheduler->mutablePrimaryDispSync().reset(mPrimaryDispSync);
+void DisplayTransactionTest::injectMockScheduler() {
EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_));
EXPECT_CALL(*mSFEventThread, registerDisplayEventConnection(_));
- sp<Scheduler::ConnectionHandle> sfConnectionHandle =
- mScheduler->addConnection(std::unique_ptr<EventThread>(mSFEventThread));
- mFlinger.mutableSfConnectionHandle() = std::move(sfConnectionHandle);
- sp<Scheduler::ConnectionHandle> appConnectionHandle =
- mScheduler->addConnection(std::unique_ptr<EventThread>(mEventThread));
- mFlinger.mutableAppConnectionHandle() = std::move(appConnectionHandle);
- mFlinger.mutableScheduler().reset(mScheduler);
+ mFlinger.setupScheduler(std::unique_ptr<DispSync>(mPrimaryDispSync),
+ std::unique_ptr<EventControlThread>(mEventControlThread),
+ std::unique_ptr<EventThread>(mEventThread),
+ std::unique_ptr<EventThread>(mSFEventThread));
}
void DisplayTransactionTest::injectMockComposer(int virtualDisplayCount) {
@@ -1131,8 +1124,8 @@
// Preconditions
// vsync is enabled and available
- mScheduler->mutablePrimaryHWVsyncEnabled() = true;
- mScheduler->mutableHWVsyncAvailable() = true;
+ mFlinger.scheduler()->mutablePrimaryHWVsyncEnabled() = true;
+ mFlinger.scheduler()->mutableHWVsyncAvailable() = true;
// A display exists
auto existing = Case::Display::makeFakeExistingDisplayInjector(this);
@@ -1156,8 +1149,8 @@
// Postconditions
// vsyncs should be off and not available.
- EXPECT_FALSE(mScheduler->mutablePrimaryHWVsyncEnabled());
- EXPECT_FALSE(mScheduler->mutableHWVsyncAvailable());
+ EXPECT_FALSE(mFlinger.scheduler()->mutablePrimaryHWVsyncEnabled());
+ EXPECT_FALSE(mFlinger.scheduler()->mutableHWVsyncAvailable());
// The display should have been removed from the display map.
EXPECT_FALSE(hasDisplayDevice(existing.token()));
@@ -3008,7 +3001,7 @@
}
static void setInitialPrimaryHWVsyncEnabled(DisplayTransactionTest* test, bool enabled) {
- test->mScheduler->mutablePrimaryHWVsyncEnabled() = enabled;
+ test->mFlinger.scheduler()->mutablePrimaryHWVsyncEnabled() = enabled;
}
static void setupRepaintEverythingCallExpectations(DisplayTransactionTest* test) {
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index cb6980e..5157cc4 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -20,15 +20,16 @@
#include <gui/ISurfaceComposer.h>
#include "Scheduler/EventThread.h"
-#include "Scheduler/RefreshRateConfigs.h"
#include "Scheduler/Scheduler.h"
namespace android {
class TestableScheduler : public Scheduler {
public:
- TestableScheduler(const scheduler::RefreshRateConfigs& refreshRateConfig)
- : Scheduler([](bool) {}, refreshRateConfig) {}
+ TestableScheduler(std::unique_ptr<DispSync> primaryDispSync,
+ std::unique_ptr<EventControlThread> eventControlThread,
+ const scheduler::RefreshRateConfigs& configs)
+ : Scheduler(std::move(primaryDispSync), std::move(eventControlThread), configs) {}
// Creates EventThreadConnection with the given eventThread. Creates Scheduler::Connection
// and adds it to the list of connectins. Returns the ConnectionHandle for the
@@ -62,7 +63,7 @@
mutableEventControlThread().reset();
mutablePrimaryDispSync().reset();
mConnections.clear();
- };
+ }
};
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 64d34ee..97fafcb 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -36,7 +36,7 @@
#include "SurfaceFlinger.h"
#include "SurfaceFlingerFactory.h"
#include "SurfaceInterceptor.h"
-
+#include "TestableScheduler.h"
#include "TimeStats/TimeStats.h"
namespace android {
@@ -176,6 +176,8 @@
class TestableSurfaceFlinger {
public:
+ TestableScheduler* scheduler() { return mScheduler; }
+
// Extend this as needed for accessing SurfaceFlinger private (and public)
// functions.
@@ -188,6 +190,23 @@
std::make_unique<impl::HWComposer>(std::move(composer)));
}
+ void setupScheduler(std::unique_ptr<DispSync> primaryDispSync,
+ std::unique_ptr<EventControlThread> eventControlThread,
+ std::unique_ptr<EventThread> appEventThread,
+ std::unique_ptr<EventThread> sfEventThread) {
+ mScheduler =
+ new TestableScheduler(std::move(primaryDispSync), std::move(eventControlThread),
+ mFlinger->mRefreshRateConfigs);
+
+ mFlinger->mAppConnectionHandle = mScheduler->addConnection(std::move(appEventThread));
+ mFlinger->mSfConnectionHandle = mScheduler->addConnection(std::move(sfEventThread));
+
+ mFlinger->mScheduler.reset(mScheduler);
+ mFlinger->mVSyncModulator.emplace(*mScheduler, mFlinger->mAppConnectionHandle,
+ mFlinger->mSfConnectionHandle,
+ mFlinger->mPhaseOffsets->getCurrentOffsets());
+ }
+
using CreateBufferQueueFunction = surfaceflinger::test::Factory::CreateBufferQueueFunction;
void setCreateBufferQueueFunction(CreateBufferQueueFunction f) {
mFactory.mCreateBufferQueue = f;
@@ -338,10 +357,6 @@
auto& mutableHwcPhysicalDisplayIdMap() { return getHwComposer().mPhysicalDisplayIdMap; }
auto& mutableInternalHwcDisplayId() { return getHwComposer().mInternalHwcDisplayId; }
auto& mutableExternalHwcDisplayId() { return getHwComposer().mExternalHwcDisplayId; }
- auto& mutableScheduler() { return mFlinger->mScheduler; }
- auto& mutableAppConnectionHandle() { return mFlinger->mAppConnectionHandle; }
- auto& mutableSfConnectionHandle() { return mFlinger->mSfConnectionHandle; }
- auto& mutableRefreshRateConfigs() { return mFlinger->mRefreshRateConfigs; }
~TestableSurfaceFlinger() {
// All these pointer and container clears help ensure that GMock does
@@ -353,7 +368,6 @@
mutableDrawingState().displays.clear();
mutableEventQueue().reset();
mutableInterceptor().reset();
- mutableScheduler().reset();
mFlinger->mCompositionEngine->setHwComposer(std::unique_ptr<HWComposer>());
mFlinger->mCompositionEngine->setRenderEngine(
std::unique_ptr<renderengine::RenderEngine>());
@@ -573,6 +587,7 @@
surfaceflinger::test::Factory mFactory;
sp<SurfaceFlinger> mFlinger = new SurfaceFlinger(mFactory, SurfaceFlinger::SkipInitialization);
+ TestableScheduler* mScheduler = nullptr;
// We need to keep a reference to these so they are properly destroyed.
std::vector<std::unique_ptr<HWC2Display>> mFakeHwcDisplays;
diff --git a/vulkan/Android.bp b/vulkan/Android.bp
index 7747734..4934970 100644
--- a/vulkan/Android.bp
+++ b/vulkan/Android.bp
@@ -31,6 +31,5 @@
subdirs = [
"nulldrv",
"libvulkan",
- "tools",
"vkjson",
]
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index 368130d..4608be2 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -1172,11 +1172,16 @@
std::call_once(once_flag, []() {
if (driver::OpenHAL()) {
- DiscoverLayers();
initialized = true;
}
});
+ {
+ static std::mutex layer_lock;
+ std::lock_guard<std::mutex> lock(layer_lock);
+ DiscoverLayers();
+ }
+
return initialized;
}
diff --git a/vulkan/tools/Android.bp b/vulkan/tools/Android.bp
deleted file mode 100644
index 2514094..0000000
--- a/vulkan/tools/Android.bp
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2015 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_binary {
- name: "vkinfo",
-
- clang: true,
- cflags: [
- "-fvisibility=hidden",
- "-fstrict-aliasing",
-
- "-DLOG_TAG=\"vkinfo\"",
-
- "-Weverything",
- "-Werror",
- "-Wno-padded",
- "-Wno-undef",
- "-Wno-switch-enum",
- ],
- cppflags: [
- "-Wno-c++98-compat-pedantic",
- "-Wno-c99-extensions",
- "-Wno-old-style-cast",
- ],
-
- srcs: ["vkinfo.cpp"],
-
- shared_libs: [
- "libvulkan",
- "liblog",
- ],
-}
diff --git a/vulkan/tools/vkinfo.cpp b/vulkan/tools/vkinfo.cpp
deleted file mode 100644
index 89bc926..0000000
--- a/vulkan/tools/vkinfo.cpp
+++ /dev/null
@@ -1,634 +0,0 @@
-/*
- * Copyright 2015 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 <inttypes.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <algorithm>
-#include <array>
-#include <sstream>
-#include <vector>
-
-#include <vulkan/vulkan.h>
-
-namespace {
-
-struct Options {
- bool layer_description;
- bool layer_extensions;
- bool unsupported_features;
- bool validate;
-};
-
-struct GpuInfo {
- VkPhysicalDeviceProperties properties;
- VkPhysicalDeviceMemoryProperties memory;
- VkPhysicalDeviceFeatures features;
- std::vector<VkQueueFamilyProperties> queue_families;
- std::vector<VkExtensionProperties> extensions;
- std::vector<VkLayerProperties> layers;
- std::vector<std::vector<VkExtensionProperties>> layer_extensions;
-};
-struct VulkanInfo {
- std::vector<VkExtensionProperties> extensions;
- std::vector<VkLayerProperties> layers;
- std::vector<std::vector<VkExtensionProperties>> layer_extensions;
- std::vector<GpuInfo> gpus;
-};
-
-// ----------------------------------------------------------------------------
-
-[[noreturn]] void die(const char* proc, VkResult result) {
- const char* result_str;
- switch (result) {
- // clang-format off
- case VK_SUCCESS: result_str = "VK_SUCCESS"; break;
- case VK_NOT_READY: result_str = "VK_NOT_READY"; break;
- case VK_TIMEOUT: result_str = "VK_TIMEOUT"; break;
- case VK_EVENT_SET: result_str = "VK_EVENT_SET"; break;
- case VK_EVENT_RESET: result_str = "VK_EVENT_RESET"; break;
- case VK_INCOMPLETE: result_str = "VK_INCOMPLETE"; break;
- case VK_ERROR_OUT_OF_HOST_MEMORY: result_str = "VK_ERROR_OUT_OF_HOST_MEMORY"; break;
- case VK_ERROR_OUT_OF_DEVICE_MEMORY: result_str = "VK_ERROR_OUT_OF_DEVICE_MEMORY"; break;
- case VK_ERROR_INITIALIZATION_FAILED: result_str = "VK_ERROR_INITIALIZATION_FAILED"; break;
- case VK_ERROR_DEVICE_LOST: result_str = "VK_ERROR_DEVICE_LOST"; break;
- case VK_ERROR_MEMORY_MAP_FAILED: result_str = "VK_ERROR_MEMORY_MAP_FAILED"; break;
- case VK_ERROR_LAYER_NOT_PRESENT: result_str = "VK_ERROR_LAYER_NOT_PRESENT"; break;
- case VK_ERROR_EXTENSION_NOT_PRESENT: result_str = "VK_ERROR_EXTENSION_NOT_PRESENT"; break;
- case VK_ERROR_INCOMPATIBLE_DRIVER: result_str = "VK_ERROR_INCOMPATIBLE_DRIVER"; break;
- default: result_str = "<unknown VkResult>"; break;
- // clang-format on
- }
- fprintf(stderr, "%s failed: %s (%d)\n", proc, result_str, result);
- exit(1);
-}
-
-bool HasExtension(const std::vector<VkExtensionProperties>& extensions,
- const char* name) {
- return std::find_if(extensions.cbegin(), extensions.cend(),
- [=](const VkExtensionProperties& prop) {
- return strcmp(prop.extensionName, name) == 0;
- }) != extensions.end();
-}
-
-void EnumerateInstanceExtensions(
- const char* layer_name,
- std::vector<VkExtensionProperties>* extensions) {
- VkResult result;
- uint32_t count;
- result =
- vkEnumerateInstanceExtensionProperties(layer_name, &count, nullptr);
- if (result != VK_SUCCESS)
- die("vkEnumerateInstanceExtensionProperties (count)", result);
- do {
- extensions->resize(count);
- result = vkEnumerateInstanceExtensionProperties(layer_name, &count,
- extensions->data());
- } while (result == VK_INCOMPLETE);
- if (result != VK_SUCCESS)
- die("vkEnumerateInstanceExtensionProperties (data)", result);
-}
-
-void EnumerateDeviceExtensions(VkPhysicalDevice gpu,
- const char* layer_name,
- std::vector<VkExtensionProperties>* extensions) {
- VkResult result;
- uint32_t count;
- result =
- vkEnumerateDeviceExtensionProperties(gpu, layer_name, &count, nullptr);
- if (result != VK_SUCCESS)
- die("vkEnumerateDeviceExtensionProperties (count)", result);
- do {
- extensions->resize(count);
- result = vkEnumerateDeviceExtensionProperties(gpu, layer_name, &count,
- extensions->data());
- } while (result == VK_INCOMPLETE);
- if (result != VK_SUCCESS)
- die("vkEnumerateDeviceExtensionProperties (data)", result);
-}
-
-void GatherGpuInfo(VkPhysicalDevice gpu,
- const Options &options,
- GpuInfo& info) {
- VkResult result;
- uint32_t count;
-
- vkGetPhysicalDeviceProperties(gpu, &info.properties);
- vkGetPhysicalDeviceMemoryProperties(gpu, &info.memory);
- vkGetPhysicalDeviceFeatures(gpu, &info.features);
-
- vkGetPhysicalDeviceQueueFamilyProperties(gpu, &count, nullptr);
- info.queue_families.resize(count);
- vkGetPhysicalDeviceQueueFamilyProperties(gpu, &count,
- info.queue_families.data());
-
- result = vkEnumerateDeviceLayerProperties(gpu, &count, nullptr);
- if (result != VK_SUCCESS)
- die("vkEnumerateDeviceLayerProperties (count)", result);
- do {
- info.layers.resize(count);
- result =
- vkEnumerateDeviceLayerProperties(gpu, &count, info.layers.data());
- } while (result == VK_INCOMPLETE);
- if (result != VK_SUCCESS)
- die("vkEnumerateDeviceLayerProperties (data)", result);
- info.layer_extensions.resize(info.layers.size());
-
- EnumerateDeviceExtensions(gpu, nullptr, &info.extensions);
- for (size_t i = 0; i < info.layers.size(); i++) {
- EnumerateDeviceExtensions(gpu, info.layers[i].layerName,
- &info.layer_extensions[i]);
- }
-
- const std::array<const char*, 1> kDesiredExtensions = {
- {VK_KHR_SWAPCHAIN_EXTENSION_NAME},
- };
- const char* extensions[kDesiredExtensions.size()];
- uint32_t num_extensions = 0;
- for (const auto& desired_ext : kDesiredExtensions) {
- bool available = HasExtension(info.extensions, desired_ext);
- if (options.validate) {
- for (size_t i = 0; !available && i < info.layer_extensions.size();
- i++)
- available = HasExtension(info.layer_extensions[i], desired_ext);
- }
- if (available)
- extensions[num_extensions++] = desired_ext;
- }
-
- VkDevice device;
- float queue_priorities[] = {0.0};
- const VkDeviceQueueCreateInfo queue_create_info = {
- .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
- .queueFamilyIndex = 0,
- .queueCount = 1,
- .pQueuePriorities = queue_priorities
- };
- // clang-format off
- const char *kValidationLayers[] = {
- "VK_LAYER_GOOGLE_threading",
- "VK_LAYER_LUNARG_parameter_validation",
- "VK_LAYER_LUNARG_device_limits",
- "VK_LAYER_LUNARG_object_tracker",
- "VK_LAYER_LUNARG_image",
- "VK_LAYER_LUNARG_core_validation",
- "VK_LAYER_LUNARG_swapchain",
- "VK_LAYER_GOOGLE_unique_objects"
- };
- // clang-format on
- uint32_t num_layers = sizeof(kValidationLayers) / sizeof(char*);
- const VkDeviceCreateInfo create_info = {
- .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
- .queueCreateInfoCount = 1,
- .pQueueCreateInfos = &queue_create_info,
- .enabledExtensionCount = num_extensions,
- .ppEnabledExtensionNames = extensions,
- .enabledLayerCount = (options.validate) ? num_layers : 0,
- .ppEnabledLayerNames = kValidationLayers,
- .pEnabledFeatures = &info.features,
- };
- result = vkCreateDevice(gpu, &create_info, nullptr, &device);
- if (result != VK_SUCCESS)
- die("vkCreateDevice", result);
- vkDestroyDevice(device, nullptr);
-}
-
-void GatherInfo(VulkanInfo* info, const Options& options) {
- VkResult result;
- uint32_t count;
-
- result = vkEnumerateInstanceLayerProperties(&count, nullptr);
- if (result != VK_SUCCESS)
- die("vkEnumerateInstanceLayerProperties (count)", result);
- do {
- info->layers.resize(count);
- result =
- vkEnumerateInstanceLayerProperties(&count, info->layers.data());
- } while (result == VK_INCOMPLETE);
- if (result != VK_SUCCESS)
- die("vkEnumerateInstanceLayerProperties (data)", result);
- info->layer_extensions.resize(info->layers.size());
-
- EnumerateInstanceExtensions(nullptr, &info->extensions);
- for (size_t i = 0; i < info->layers.size(); i++) {
- EnumerateInstanceExtensions(info->layers[i].layerName,
- &info->layer_extensions[i]);
- }
-
- const char* kDesiredExtensions[] = {
- VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
- };
- const char*
- extensions[sizeof(kDesiredExtensions) / sizeof(kDesiredExtensions[0])];
- uint32_t num_extensions = 0;
- for (const auto& desired_ext : kDesiredExtensions) {
- bool available = HasExtension(info->extensions, desired_ext);
- if (options.validate) {
- for (size_t i = 0; !available && i < info->layer_extensions.size();
- i++)
- available =
- HasExtension(info->layer_extensions[i], desired_ext);
- }
- if (available)
- extensions[num_extensions++] = desired_ext;
- }
-
- // clang-format off
- const char *kValidationLayers[] = {
- "VK_LAYER_GOOGLE_threading",
- "VK_LAYER_LUNARG_parameter_validation",
- "VK_LAYER_LUNARG_device_limits",
- "VK_LAYER_LUNARG_object_tracker",
- "VK_LAYER_LUNARG_image",
- "VK_LAYER_LUNARG_core_validation",
- "VK_LAYER_LUNARG_swapchain",
- "VK_LAYER_GOOGLE_unique_objects"
- };
- // clang-format on
- uint32_t num_layers = sizeof(kValidationLayers) / sizeof(char*);
-
- const VkApplicationInfo application_info = {
- .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
- .pApplicationName = "vkinfo",
- .applicationVersion = 0,
- .pEngineName = "vkinfo",
- .engineVersion = 0,
- .apiVersion = VK_API_VERSION_1_0,
- };
- const VkInstanceCreateInfo create_info = {
- .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
- .pApplicationInfo = &application_info,
- .enabledExtensionCount = num_extensions,
- .ppEnabledExtensionNames = extensions,
- .enabledLayerCount = (options.validate) ? num_layers : 0,
- .ppEnabledLayerNames = kValidationLayers,
- };
- VkInstance instance;
- result = vkCreateInstance(&create_info, nullptr, &instance);
- if (result != VK_SUCCESS)
- die("vkCreateInstance", result);
-
- uint32_t num_gpus;
- result = vkEnumeratePhysicalDevices(instance, &num_gpus, nullptr);
- if (result != VK_SUCCESS)
- die("vkEnumeratePhysicalDevices (count)", result);
- std::vector<VkPhysicalDevice> gpus(num_gpus, VK_NULL_HANDLE);
- do {
- gpus.resize(num_gpus, VK_NULL_HANDLE);
- result = vkEnumeratePhysicalDevices(instance, &num_gpus, gpus.data());
- } while (result == VK_INCOMPLETE);
- if (result != VK_SUCCESS)
- die("vkEnumeratePhysicalDevices (data)", result);
-
- info->gpus.resize(num_gpus);
- for (size_t i = 0; i < gpus.size(); i++)
- GatherGpuInfo(gpus[i], options, info->gpus.at(i));
-
- vkDestroyInstance(instance, nullptr);
-}
-
-// ----------------------------------------------------------------------------
-
-const size_t kMaxIndent = 8;
-const size_t kIndentSize = 3;
-std::array<char, kMaxIndent * kIndentSize + 1> kIndent;
-const char* Indent(size_t n) {
- static bool initialized = false;
- if (!initialized) {
- kIndent.fill(' ');
- kIndent.back() = '\0';
- initialized = true;
- }
- return kIndent.data() +
- (kIndent.size() - (kIndentSize * std::min(n, kMaxIndent) + 1));
-}
-
-const char* VkPhysicalDeviceTypeStr(VkPhysicalDeviceType type) {
- switch (type) {
- case VK_PHYSICAL_DEVICE_TYPE_OTHER:
- return "OTHER";
- case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
- return "INTEGRATED_GPU";
- case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
- return "DISCRETE_GPU";
- case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
- return "VIRTUAL_GPU";
- case VK_PHYSICAL_DEVICE_TYPE_CPU:
- return "CPU";
- default:
- return "<UNKNOWN>";
- }
-}
-
-void PrintExtensions(const std::vector<VkExtensionProperties>& extensions,
- const Options& /*options*/,
- size_t indent) {
- for (const auto& e : extensions)
- printf("%s%s (v%u)\n", Indent(indent), e.extensionName, e.specVersion);
-}
-
-void PrintLayers(
- const std::vector<VkLayerProperties>& layers,
- const std::vector<std::vector<VkExtensionProperties>> extensions,
- const Options& options,
- size_t indent) {
- for (size_t i = 0; i < layers.size(); i++) {
- printf("%s%s %u.%u.%u/%u\n", Indent(indent), layers[i].layerName,
- VK_VERSION_MAJOR(layers[i].specVersion),
- VK_VERSION_MINOR(layers[i].specVersion),
- VK_VERSION_PATCH(layers[i].specVersion),
- layers[i].implementationVersion);
- if (options.layer_description)
- printf("%s%s\n", Indent(indent + 1), layers[i].description);
- if (options.layer_extensions && !extensions[i].empty()) {
- if (!extensions[i].empty()) {
- printf("%sExtensions [%zu]:\n", Indent(indent + 1),
- extensions[i].size());
- PrintExtensions(extensions[i], options, indent + 2);
- }
- }
- }
-}
-
-void PrintAllFeatures(const char* indent,
- const VkPhysicalDeviceFeatures& features) {
- // clang-format off
- printf("%srobustBufferAccess: %s\n", indent, features.robustBufferAccess ? "YES" : "NO");
- printf("%sfullDrawIndexUint32: %s\n", indent, features.fullDrawIndexUint32 ? "YES" : "NO");
- printf("%simageCubeArray: %s\n", indent, features.imageCubeArray ? "YES" : "NO");
- printf("%sindependentBlend: %s\n", indent, features.independentBlend ? "YES" : "NO");
- printf("%sgeometryShader: %s\n", indent, features.geometryShader ? "YES" : "NO");
- printf("%stessellationShader: %s\n", indent, features.tessellationShader ? "YES" : "NO");
- printf("%ssampleRateShading: %s\n", indent, features.sampleRateShading ? "YES" : "NO");
- printf("%sdualSrcBlend: %s\n", indent, features.dualSrcBlend ? "YES" : "NO");
- printf("%slogicOp: %s\n", indent, features.logicOp ? "YES" : "NO");
- printf("%smultiDrawIndirect: %s\n", indent, features.multiDrawIndirect ? "YES" : "NO");
- printf("%sdrawIndirectFirstInstance: %s\n", indent, features.drawIndirectFirstInstance ? "YES" : "NO");
- printf("%sdepthClamp: %s\n", indent, features.depthClamp ? "YES" : "NO");
- printf("%sdepthBiasClamp: %s\n", indent, features.depthBiasClamp ? "YES" : "NO");
- printf("%sfillModeNonSolid: %s\n", indent, features.fillModeNonSolid ? "YES" : "NO");
- printf("%sdepthBounds: %s\n", indent, features.depthBounds ? "YES" : "NO");
- printf("%swideLines: %s\n", indent, features.wideLines ? "YES" : "NO");
- printf("%slargePoints: %s\n", indent, features.largePoints ? "YES" : "NO");
- printf("%salphaToOne: %s\n", indent, features.alphaToOne ? "YES" : "NO");
- printf("%smultiViewport: %s\n", indent, features.multiViewport ? "YES" : "NO");
- printf("%ssamplerAnisotropy: %s\n", indent, features.samplerAnisotropy ? "YES" : "NO");
- printf("%stextureCompressionETC2: %s\n", indent, features.textureCompressionETC2 ? "YES" : "NO");
- printf("%stextureCompressionASTC_LDR: %s\n", indent, features.textureCompressionASTC_LDR ? "YES" : "NO");
- printf("%stextureCompressionBC: %s\n", indent, features.textureCompressionBC ? "YES" : "NO");
- printf("%socclusionQueryPrecise: %s\n", indent, features.occlusionQueryPrecise ? "YES" : "NO");
- printf("%spipelineStatisticsQuery: %s\n", indent, features.pipelineStatisticsQuery ? "YES" : "NO");
- printf("%svertexPipelineStoresAndAtomics: %s\n", indent, features.vertexPipelineStoresAndAtomics ? "YES" : "NO");
- printf("%sfragmentStoresAndAtomics: %s\n", indent, features.fragmentStoresAndAtomics ? "YES" : "NO");
- printf("%sshaderTessellationAndGeometryPointSize: %s\n", indent, features.shaderTessellationAndGeometryPointSize ? "YES" : "NO");
- printf("%sshaderImageGatherExtended: %s\n", indent, features.shaderImageGatherExtended ? "YES" : "NO");
- printf("%sshaderStorageImageExtendedFormats: %s\n", indent, features.shaderStorageImageExtendedFormats ? "YES" : "NO");
- printf("%sshaderStorageImageMultisample: %s\n", indent, features.shaderStorageImageMultisample ? "YES" : "NO");
- printf("%sshaderStorageImageReadWithoutFormat: %s\n", indent, features.shaderStorageImageReadWithoutFormat ? "YES" : "NO");
- printf("%sshaderStorageImageWriteWithoutFormat: %s\n", indent, features.shaderStorageImageWriteWithoutFormat ? "YES" : "NO");
- printf("%sshaderUniformBufferArrayDynamicIndexing: %s\n", indent, features.shaderUniformBufferArrayDynamicIndexing ? "YES" : "NO");
- printf("%sshaderSampledImageArrayDynamicIndexing: %s\n", indent, features.shaderSampledImageArrayDynamicIndexing ? "YES" : "NO");
- printf("%sshaderStorageBufferArrayDynamicIndexing: %s\n", indent, features.shaderStorageBufferArrayDynamicIndexing ? "YES" : "NO");
- printf("%sshaderStorageImageArrayDynamicIndexing: %s\n", indent, features.shaderStorageImageArrayDynamicIndexing ? "YES" : "NO");
- printf("%sshaderClipDistance: %s\n", indent, features.shaderClipDistance ? "YES" : "NO");
- printf("%sshaderCullDistance: %s\n", indent, features.shaderCullDistance ? "YES" : "NO");
- printf("%sshaderFloat64: %s\n", indent, features.shaderFloat64 ? "YES" : "NO");
- printf("%sshaderInt64: %s\n", indent, features.shaderInt64 ? "YES" : "NO");
- printf("%sshaderInt16: %s\n", indent, features.shaderInt16 ? "YES" : "NO");
- printf("%sshaderResourceResidency: %s\n", indent, features.shaderResourceResidency ? "YES" : "NO");
- printf("%sshaderResourceMinLod: %s\n", indent, features.shaderResourceMinLod ? "YES" : "NO");
- printf("%ssparseBinding: %s\n", indent, features.sparseBinding ? "YES" : "NO");
- printf("%ssparseResidencyBuffer: %s\n", indent, features.sparseResidencyBuffer ? "YES" : "NO");
- printf("%ssparseResidencyImage2D: %s\n", indent, features.sparseResidencyImage2D ? "YES" : "NO");
- printf("%ssparseResidencyImage3D: %s\n", indent, features.sparseResidencyImage3D ? "YES" : "NO");
- printf("%ssparseResidency2Samples: %s\n", indent, features.sparseResidency2Samples ? "YES" : "NO");
- printf("%ssparseResidency4Samples: %s\n", indent, features.sparseResidency4Samples ? "YES" : "NO");
- printf("%ssparseResidency8Samples: %s\n", indent, features.sparseResidency8Samples ? "YES" : "NO");
- printf("%ssparseResidency16Samples: %s\n", indent, features.sparseResidency16Samples ? "YES" : "NO");
- printf("%ssparseResidencyAliased: %s\n", indent, features.sparseResidencyAliased ? "YES" : "NO");
- printf("%svariableMultisampleRate: %s\n", indent, features.variableMultisampleRate ? "YES" : "NO");
- printf("%sinheritedQueries: %s\n", indent, features.inheritedQueries ? "YES" : "NO");
- // clang-format on
-}
-
-void PrintSupportedFeatures(const char* indent,
- const VkPhysicalDeviceFeatures& features) {
- // clang-format off
- if (features.robustBufferAccess) printf("%srobustBufferAccess\n", indent);
- if (features.fullDrawIndexUint32) printf("%sfullDrawIndexUint32\n", indent);
- if (features.imageCubeArray) printf("%simageCubeArray\n", indent);
- if (features.independentBlend) printf("%sindependentBlend\n", indent);
- if (features.geometryShader) printf("%sgeometryShader\n", indent);
- if (features.tessellationShader) printf("%stessellationShader\n", indent);
- if (features.sampleRateShading) printf("%ssampleRateShading\n", indent);
- if (features.dualSrcBlend) printf("%sdualSrcBlend\n", indent);
- if (features.logicOp) printf("%slogicOp\n", indent);
- if (features.multiDrawIndirect) printf("%smultiDrawIndirect\n", indent);
- if (features.drawIndirectFirstInstance) printf("%sdrawIndirectFirstInstance\n", indent);
- if (features.depthClamp) printf("%sdepthClamp\n", indent);
- if (features.depthBiasClamp) printf("%sdepthBiasClamp\n", indent);
- if (features.fillModeNonSolid) printf("%sfillModeNonSolid\n", indent);
- if (features.depthBounds) printf("%sdepthBounds\n", indent);
- if (features.wideLines) printf("%swideLines\n", indent);
- if (features.largePoints) printf("%slargePoints\n", indent);
- if (features.alphaToOne) printf("%salphaToOne\n", indent);
- if (features.multiViewport) printf("%smultiViewport\n", indent);
- if (features.samplerAnisotropy) printf("%ssamplerAnisotropy\n", indent);
- if (features.textureCompressionETC2) printf("%stextureCompressionETC2\n", indent);
- if (features.textureCompressionASTC_LDR) printf("%stextureCompressionASTC_LDR\n", indent);
- if (features.textureCompressionBC) printf("%stextureCompressionBC\n", indent);
- if (features.occlusionQueryPrecise) printf("%socclusionQueryPrecise\n", indent);
- if (features.pipelineStatisticsQuery) printf("%spipelineStatisticsQuery\n", indent);
- if (features.vertexPipelineStoresAndAtomics) printf("%svertexPipelineStoresAndAtomics\n", indent);
- if (features.fragmentStoresAndAtomics) printf("%sfragmentStoresAndAtomics\n", indent);
- if (features.shaderTessellationAndGeometryPointSize) printf("%sshaderTessellationAndGeometryPointSize\n", indent);
- if (features.shaderImageGatherExtended) printf("%sshaderImageGatherExtended\n", indent);
- if (features.shaderStorageImageExtendedFormats) printf("%sshaderStorageImageExtendedFormats\n", indent);
- if (features.shaderStorageImageMultisample) printf("%sshaderStorageImageMultisample\n", indent);
- if (features.shaderStorageImageReadWithoutFormat) printf("%sshaderStorageImageReadWithoutFormat\n", indent);
- if (features.shaderStorageImageWriteWithoutFormat) printf("%sshaderStorageImageWriteWithoutFormat\n", indent);
- if (features.shaderUniformBufferArrayDynamicIndexing) printf("%sshaderUniformBufferArrayDynamicIndexing\n", indent);
- if (features.shaderSampledImageArrayDynamicIndexing) printf("%sshaderSampledImageArrayDynamicIndexing\n", indent);
- if (features.shaderStorageBufferArrayDynamicIndexing) printf("%sshaderStorageBufferArrayDynamicIndexing\n", indent);
- if (features.shaderStorageImageArrayDynamicIndexing) printf("%sshaderStorageImageArrayDynamicIndexing\n", indent);
- if (features.shaderClipDistance) printf("%sshaderClipDistance\n", indent);
- if (features.shaderCullDistance) printf("%sshaderCullDistance\n", indent);
- if (features.shaderFloat64) printf("%sshaderFloat64\n", indent);
- if (features.shaderInt64) printf("%sshaderInt64\n", indent);
- if (features.shaderInt16) printf("%sshaderInt16\n", indent);
- if (features.shaderResourceResidency) printf("%sshaderResourceResidency\n", indent);
- if (features.shaderResourceMinLod) printf("%sshaderResourceMinLod\n", indent);
- if (features.sparseBinding) printf("%ssparseBinding\n", indent);
- if (features.sparseResidencyBuffer) printf("%ssparseResidencyBuffer\n", indent);
- if (features.sparseResidencyImage2D) printf("%ssparseResidencyImage2D\n", indent);
- if (features.sparseResidencyImage3D) printf("%ssparseResidencyImage3D\n", indent);
- if (features.sparseResidency2Samples) printf("%ssparseResidency2Samples\n", indent);
- if (features.sparseResidency4Samples) printf("%ssparseResidency4Samples\n", indent);
- if (features.sparseResidency8Samples) printf("%ssparseResidency8Samples\n", indent);
- if (features.sparseResidency16Samples) printf("%ssparseResidency16Samples\n", indent);
- if (features.sparseResidencyAliased) printf("%ssparseResidencyAliased\n", indent);
- if (features.variableMultisampleRate) printf("%svariableMultisampleRate\n", indent);
- if (features.inheritedQueries) printf("%sinheritedQueries\n", indent);
- // clang-format on
-}
-
-void PrintGpuInfo(const GpuInfo& info, const Options& options, size_t indent) {
- VkResult result;
- std::ostringstream strbuf;
-
- printf("%s\"%s\" (%s) %u.%u.%u/%#x [%04x:%04x]\n", Indent(indent),
- info.properties.deviceName,
- VkPhysicalDeviceTypeStr(info.properties.deviceType),
- VK_VERSION_MAJOR(info.properties.apiVersion),
- VK_VERSION_MINOR(info.properties.apiVersion),
- VK_VERSION_PATCH(info.properties.apiVersion),
- info.properties.driverVersion, info.properties.vendorID,
- info.properties.deviceID);
-
- for (uint32_t heap = 0; heap < info.memory.memoryHeapCount; heap++) {
- if ((info.memory.memoryHeaps[heap].flags &
- VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0)
- strbuf << "DEVICE_LOCAL";
- printf("%sHeap %u: %" PRIu64 " MiB (0x%" PRIx64 " B) %s\n",
- Indent(indent + 1), heap,
- info.memory.memoryHeaps[heap].size / 0x100000,
- info.memory.memoryHeaps[heap].size, strbuf.str().c_str());
- strbuf.str(std::string());
-
- for (uint32_t type = 0; type < info.memory.memoryTypeCount; type++) {
- if (info.memory.memoryTypes[type].heapIndex != heap)
- continue;
- VkMemoryPropertyFlags flags =
- info.memory.memoryTypes[type].propertyFlags;
- if ((flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0)
- strbuf << " DEVICE_LOCAL";
- if ((flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
- strbuf << " HOST_VISIBLE";
- if ((flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0)
- strbuf << " COHERENT";
- if ((flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) != 0)
- strbuf << " CACHED";
- if ((flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) != 0)
- strbuf << " LAZILY_ALLOCATED";
- printf("%sType %u:%s\n", Indent(indent + 2), type,
- strbuf.str().c_str());
- strbuf.str(std::string());
- }
- }
-
- for (uint32_t family = 0; family < info.queue_families.size(); family++) {
- const VkQueueFamilyProperties& qprops = info.queue_families[family];
- VkQueueFlags flags = qprops.queueFlags;
- char flags_str[5];
- flags_str[0] = (flags & VK_QUEUE_GRAPHICS_BIT) ? 'G' : '_';
- flags_str[1] = (flags & VK_QUEUE_COMPUTE_BIT) ? 'C' : '_';
- flags_str[2] = (flags & VK_QUEUE_TRANSFER_BIT) ? 'T' : '_';
- flags_str[3] = (flags & VK_QUEUE_SPARSE_BINDING_BIT) ? 'S' : '_';
- flags_str[4] = '\0';
- printf(
- "%sQueue Family %u: %ux %s\n"
- "%stimestampValidBits: %ub\n"
- "%sminImageTransferGranularity: (%u,%u,%u)\n",
- Indent(indent + 1), family, qprops.queueCount, flags_str,
- Indent(indent + 2), qprops.timestampValidBits, Indent(indent + 2),
- qprops.minImageTransferGranularity.width,
- qprops.minImageTransferGranularity.height,
- qprops.minImageTransferGranularity.depth);
- }
-
- printf("%sFeatures:\n", Indent(indent + 1));
- if (options.unsupported_features) {
- PrintAllFeatures(Indent(indent + 2), info.features);
- } else {
- PrintSupportedFeatures(Indent(indent + 2), info.features);
- }
-
- printf("%sExtensions [%zu]:\n", Indent(indent + 1), info.extensions.size());
- if (!info.extensions.empty())
- PrintExtensions(info.extensions, options, indent + 2);
- printf("%sLayers [%zu]:\n", Indent(indent + 1), info.layers.size());
- if (!info.layers.empty())
- PrintLayers(info.layers, info.layer_extensions, options, indent + 2);
-}
-
-void PrintInfo(const VulkanInfo& info, const Options& options) {
- std::ostringstream strbuf;
- size_t indent = 0;
-
- printf("%sInstance Extensions [%zu]:\n", Indent(indent),
- info.extensions.size());
- PrintExtensions(info.extensions, options, indent + 1);
- printf("%sInstance Layers [%zu]:\n", Indent(indent), info.layers.size());
- if (!info.layers.empty())
- PrintLayers(info.layers, info.layer_extensions, options, indent + 1);
-
- printf("%sPhysicalDevices [%zu]:\n", Indent(indent), info.gpus.size());
- for (const auto& gpu : info.gpus)
- PrintGpuInfo(gpu, options, indent + 1);
-}
-
-const char kUsageString[] =
- "usage: vkinfo [options]\n"
- " -v enable all the following verbose options\n"
- " -layer_description print layer description strings\n"
- " -layer_extensions print extensions supported by each layer\n"
- " -unsupported_features print all physical device features\n"
- " -validate enable validation layers if present\n"
- " -debug_pause pause at start until resumed via debugger\n";
-
-} // namespace
-
-// ----------------------------------------------------------------------------
-
-int main(int argc, char const* argv[]) {
- static volatile bool startup_pause = false;
- Options options = {
- .layer_description = false, .layer_extensions = false,
- .unsupported_features = false,
- .validate = false,
- };
- for (int argi = 1; argi < argc; argi++) {
- if (strcmp(argv[argi], "-h") == 0) {
- fputs(kUsageString, stdout);
- return 0;
- }
- if (strcmp(argv[argi], "-v") == 0) {
- options.layer_description = true;
- options.layer_extensions = true;
- options.unsupported_features = true;
- } else if (strcmp(argv[argi], "-layer_description") == 0) {
- options.layer_description = true;
- } else if (strcmp(argv[argi], "-layer_extensions") == 0) {
- options.layer_extensions = true;
- } else if (strcmp(argv[argi], "-unsupported_features") == 0) {
- options.unsupported_features = true;
- } else if (strcmp(argv[argi], "-validate") == 0) {
- options.validate = true;
- } else if (strcmp(argv[argi], "-debug_pause") == 0) {
- startup_pause = true;
- }
- }
-
- while (startup_pause) {
- sleep(0);
- }
-
- VulkanInfo info;
- GatherInfo(&info, options);
- PrintInfo(info, options);
- return 0;
-}