Merge "libbinder: Add support for Trusty kernel"
diff --git a/cmds/atrace/README.md b/cmds/atrace/README.md
new file mode 100644
index 0000000..faa43b2
--- /dev/null
+++ b/cmds/atrace/README.md
@@ -0,0 +1,48 @@
+# Atrace categories
+
+The atrace command (and the perfetto configuration) allow listing **categories**
+to select subsets of events to be traced.
+
+Each category can include some userspace events and some ftrace events.
+
+## Vendor categories
+
+It's possible to extend exiting categories (or to define new categories) from
+the /vendor partition in order to add hardware specific ftrace events.
+
+Since android 14, if the file `/vendor/etc/atrace/atrace_categories.txt`, atrace
+and perfetto will consider the categories and ftrace events listed there.
+
+The file contains a list of categories, and for each category (on the following
+lines, indented with one or more spaces of time), a list of ftrace events that
+should be enabled when the category is enabled.
+
+Each ftrace event should be a subdirectory in `/sys/kernel/tracing/events/` and
+should be of the form `group/event`. Listing a whole group is not supported,
+each event needs to be listed explicitly.
+
+It is not an error if an ftrace event is listed in the file, but not present on
+the tracing file system.
+
+Example:
+
+```
+gfx
+ mali/gpu_power_state
+ mali/mali_pm_status
+thermal_tj
+ thermal_exynos/thermal_cpu_pressure
+ thermal_exynos/thermal_exynos_arm_update
+```
+
+The file lists two categories (`gfx` and `thermal_tj`). When the `gfx` category
+is enabled, atrace (or perfetto) will enable
+`/sys/kernel/tracing/events/mali/gpu_power_state` and
+`/sys/kernel/tracing/events/mali/mali_pm_status`. When the `thermal_tj` category
+is enabled, atrace (or perfetto) will enable
+`/sys/kernel/tracing/events/thermal_exynos/thermal_cpu_pressure` and
+`/sys/kernel/tracing/events/thermal_exynos/thermal_exynos_arm_update`.
+
+Since android 14, if the file `/vendor/etc/atrace/atrace_categories.txt` exists
+on the file system, perfetto and atrace do not query the android.hardware.atrace
+HAL (which is deprecated).
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 46859a2..8105626 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -49,6 +49,7 @@
#include <android-base/file.h>
#include <android-base/macros.h>
#include <android-base/properties.h>
+#include <android-base/strings.h>
#include <android-base/stringprintf.h>
using namespace android;
@@ -73,7 +74,9 @@
const char* k_pdxServiceCategory = "pdx";
const char* k_coreServicesProp = "ro.atrace.core.services";
-typedef enum { OPT, REQ } requiredness ;
+const char* kVendorCategoriesPath = "/vendor/etc/atrace/atrace_categories.txt";
+
+typedef enum { OPT, REQ } requiredness;
struct TracingCategory {
// The name identifying the category.
@@ -255,7 +258,20 @@
} },
};
-struct TracingVendorCategory {
+// A category in the vendor categories file.
+struct TracingVendorFileCategory {
+ // The name identifying the category.
+ std::string name;
+
+ // If the category is enabled through command.
+ bool enabled = false;
+
+ // Paths to the ftrace enable files (relative to g_traceFolder).
+ std::vector<std::string> ftrace_enable_paths;
+};
+
+// A category in the vendor HIDL HAL.
+struct TracingVendorHalCategory {
// The name identifying the category.
std::string name;
@@ -265,11 +281,8 @@
// If the category is enabled through command.
bool enabled;
- TracingVendorCategory(string &&name, string &&description, bool enabled)
- : name(std::move(name))
- , description(std::move(description))
- , enabled(enabled)
- {}
+ TracingVendorHalCategory(string&& name, string&& description, bool enabled)
+ : name(std::move(name)), description(std::move(description)), enabled(enabled) {}
};
/* Command line options */
@@ -289,8 +302,9 @@
static bool g_traceAborted = false;
static bool g_categoryEnables[arraysize(k_categories)] = {};
static std::string g_traceFolder;
+static std::vector<TracingVendorFileCategory> g_vendorFileCategories;
static sp<IAtraceDevice> g_atraceHal;
-static std::vector<TracingVendorCategory> g_vendorCategories;
+static std::vector<TracingVendorHalCategory> g_vendorHalCategories;
/* Sys file paths */
static const char* k_traceClockPath =
@@ -647,6 +661,13 @@
}
}
}
+ for (const TracingVendorFileCategory& c : g_vendorFileCategories) {
+ for (const std::string& path : c.ftrace_enable_paths) {
+ if (fileIsWritable(path.c_str())) {
+ ok &= setKernelOptionEnable(path.c_str(), false);
+ }
+ }
+ }
return ok;
}
@@ -726,7 +747,13 @@
static bool setCategoryEnable(const char* name)
{
bool vendor_found = false;
- for (auto &c : g_vendorCategories) {
+ for (auto& c : g_vendorFileCategories) {
+ if (strcmp(name, c.name.c_str()) == 0) {
+ c.enabled = true;
+ vendor_found = true;
+ }
+ }
+ for (auto& c : g_vendorHalCategories) {
if (strcmp(name, c.name.c_str()) == 0) {
c.enabled = true;
vendor_found = true;
@@ -872,6 +899,16 @@
}
}
+ for (const TracingVendorFileCategory& c : g_vendorFileCategories) {
+ if (c.enabled) {
+ for (const std::string& path : c.ftrace_enable_paths) {
+ if (fileIsWritable(path.c_str())) {
+ ok &= setKernelOptionEnable(path.c_str(), true);
+ }
+ }
+ }
+ }
+
return ok;
}
@@ -1057,7 +1094,10 @@
printf(" %10s - %s\n", c.name, c.longname);
}
}
- for (const auto &c : g_vendorCategories) {
+ for (const auto& c : g_vendorFileCategories) {
+ printf(" %10s - (VENDOR)\n", c.name.c_str());
+ }
+ for (const auto& c : g_vendorHalCategories) {
printf(" %10s - %s (HAL)\n", c.name.c_str(), c.description.c_str());
}
}
@@ -1116,8 +1156,38 @@
return true;
}
-void initVendorCategories()
-{
+void initVendorCategoriesFromFile() {
+ std::ifstream is(kVendorCategoriesPath);
+ for (std::string line; std::getline(is, line);) {
+ if (line.empty()) {
+ continue;
+ }
+ if (android::base::StartsWith(line, ' ') || android::base::StartsWith(line, '\t')) {
+ if (g_vendorFileCategories.empty()) {
+ fprintf(stderr, "Malformed vendor categories file\n");
+ exit(1);
+ return;
+ }
+ std::string_view path = std::string_view(line).substr(1);
+ while (android::base::StartsWith(path, ' ') || android::base::StartsWith(path, '\t')) {
+ path.remove_prefix(1);
+ }
+ if (path.empty()) {
+ continue;
+ }
+ std::string enable_path = "events/";
+ enable_path += path;
+ enable_path += "/enable";
+ g_vendorFileCategories.back().ftrace_enable_paths.push_back(std::move(enable_path));
+ } else {
+ TracingVendorFileCategory cat;
+ cat.name = line;
+ g_vendorFileCategories.push_back(std::move(cat));
+ }
+ }
+}
+
+void initVendorCategoriesFromHal() {
g_atraceHal = IAtraceDevice::getService();
if (g_atraceHal == nullptr) {
@@ -1125,27 +1195,34 @@
return;
}
- Return<void> ret = g_atraceHal->listCategories(
- [](const auto& list) {
- g_vendorCategories.reserve(list.size());
- for (const auto& category : list) {
- g_vendorCategories.emplace_back(category.name, category.description, false);
- }
- });
+ Return<void> ret = g_atraceHal->listCategories([](const auto& list) {
+ g_vendorHalCategories.reserve(list.size());
+ for (const auto& category : list) {
+ g_vendorHalCategories.emplace_back(category.name, category.description, false);
+ }
+ });
if (!ret.isOk()) {
fprintf(stderr, "calling atrace HAL failed: %s\n", ret.description().c_str());
}
}
-static bool setUpVendorTracing()
-{
+void initVendorCategories() {
+ // If kVendorCategoriesPath exists on the filesystem, do not use the HAL.
+ if (access(kVendorCategoriesPath, F_OK) != -1) {
+ initVendorCategoriesFromFile();
+ } else {
+ initVendorCategoriesFromHal();
+ }
+}
+
+static bool setUpVendorTracingWithHal() {
if (g_atraceHal == nullptr) {
// No atrace HAL
return true;
}
std::vector<hidl_string> categories;
- for (const auto &c : g_vendorCategories) {
+ for (const auto& c : g_vendorHalCategories) {
if (c.enabled) {
categories.emplace_back(c.name);
}
@@ -1166,15 +1243,14 @@
return true;
}
-static bool cleanUpVendorTracing()
-{
+static bool cleanUpVendorTracingWithHal() {
if (g_atraceHal == nullptr) {
// No atrace HAL
return true;
}
- if (!g_vendorCategories.size()) {
- // No vendor categories
+ if (!g_vendorHalCategories.size()) {
+ // No vendor HAL categories
return true;
}
@@ -1328,7 +1404,7 @@
if (ok && traceStart && !onlyUserspace) {
ok &= setUpKernelTracing();
- ok &= setUpVendorTracing();
+ ok &= setUpVendorTracingWithHal();
ok &= startTrace();
}
@@ -1399,7 +1475,7 @@
if (traceStop) {
cleanUpUserspaceTracing();
if (!onlyUserspace) {
- cleanUpVendorTracing();
+ cleanUpVendorTracingWithHal();
cleanUpKernelTracing();
}
}
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index ee081c4..44ff62b 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -1475,7 +1475,7 @@
#ifdef BINDER_WITH_KERNEL_IPC
flat_binder_object obj;
obj.hdr.type = BINDER_TYPE_FD;
- obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
+ obj.flags = 0;
obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
obj.handle = fd;
obj.cookie = takeOwnership ? 1 : 0;
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 28d1f16..d0de7b9 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -75,12 +75,48 @@
AIBinder::AIBinder(const AIBinder_Class* clazz) : mClazz(clazz) {}
AIBinder::~AIBinder() {}
-std::optional<bool> AIBinder::associateClassInternal(const AIBinder_Class* clazz,
- const String16& newDescriptor, bool set) {
+// b/175635923 libcxx causes "implicit-conversion" with a string with invalid char
+static std::string SanitizeString(const String16& str) {
+ std::string sanitized{String8(str)};
+ for (auto& c : sanitized) {
+ if (!isprint(c)) {
+ c = '?';
+ }
+ }
+ return sanitized;
+}
+
+bool AIBinder::associateClass(const AIBinder_Class* clazz) {
+ if (clazz == nullptr) return false;
+
+ // If mClazz is non-null, this must have been called and cached
+ // already. So, we can safely call this first. Due to the implementation
+ // of getInterfaceDescriptor (at time of writing), two simultaneous calls
+ // may lead to extra binder transactions, but this is expected to be
+ // exceedingly rare. Once we have a binder, when we get it again later,
+ // we won't make another binder transaction here.
+ const String16& descriptor = getBinder()->getInterfaceDescriptor();
+ const String16& newDescriptor = clazz->getInterfaceDescriptor();
+
std::lock_guard<std::mutex> lock(mClazzMutex);
if (mClazz == clazz) return true;
- if (mClazz != nullptr) {
+ // If this is an ABpBinder, the first class object becomes the canonical one. The implication
+ // of this is that no API can require a proxy information to get information on how to behave.
+ // from the class itself - which should only store the interface descriptor. The functionality
+ // should be implemented by adding AIBinder_* APIs to set values on binders themselves, by
+ // setting things on AIBinder_Class which get transferred along with the binder, so that they
+ // can be read along with the BpBinder, or by modifying APIs directly (e.g. an option in
+ // onTransact).
+ //
+ // While this check is required to support linkernamespaces, one downside of it is that
+ // you may parcel code to communicate between things in the same process. However, comms
+ // between linkernamespaces like this already happen for cross-language calls like Java<->C++
+ // or Rust<->Java, and there are good stability guarantees here. This interacts with
+ // binder Stability checks exactly like any other in-process call. The stability is known
+ // to the IBinder object, so that it doesn't matter if a class object comes from
+ // a different stability level.
+ if (mClazz != nullptr && !asABpBinder()) {
const String16& currentDescriptor = mClazz->getInterfaceDescriptor();
if (newDescriptor == currentDescriptor) {
LOG(ERROR) << __func__ << ": Class descriptors '" << currentDescriptor
@@ -97,37 +133,10 @@
return false;
}
- if (set) {
- // if this is a local object, it's not one known to libbinder_ndk
- mClazz = clazz;
- return true;
- }
-
- return {};
-}
-
-// b/175635923 libcxx causes "implicit-conversion" with a string with invalid char
-static std::string SanitizeString(const String16& str) {
- std::string sanitized{String8(str)};
- for (auto& c : sanitized) {
- if (!isprint(c)) {
- c = '?';
- }
- }
- return sanitized;
-}
-
-bool AIBinder::associateClass(const AIBinder_Class* clazz) {
- if (clazz == nullptr) return false;
-
- const String16& newDescriptor = clazz->getInterfaceDescriptor();
-
- auto result = associateClassInternal(clazz, newDescriptor, false);
- if (result.has_value()) return *result;
-
- CHECK(asABpBinder() != nullptr); // ABBinder always has a descriptor
-
- const String16& descriptor = getBinder()->getInterfaceDescriptor();
+ // This will always be an O(n) comparison, but it's expected to be extremely rare.
+ // since it's an error condition. Do the comparison after we take the lock and
+ // check the pointer equality fast path. By always taking the lock, it's also
+ // more flake-proof. However, the check is not dependent on the lock.
if (descriptor != newDescriptor) {
if (getBinder()->isBinderAlive()) {
LOG(ERROR) << __func__ << ": Expecting binder to have class '" << newDescriptor
@@ -141,7 +150,14 @@
return false;
}
- return associateClassInternal(clazz, newDescriptor, true).value();
+ // A local binder being set for the first time OR
+ // ignoring a proxy binder which is set multiple time, by considering the first
+ // associated class as the canonical one.
+ if (mClazz == nullptr) {
+ mClazz = clazz;
+ }
+
+ return true;
}
ABBinder::ABBinder(const AIBinder_Class* clazz, void* userData)
@@ -325,6 +341,10 @@
return lhs->binder < rhs->binder;
}
+// WARNING: When multiple classes exist with the same interface descriptor in different
+// linkernamespaces, the first one to be associated with mClazz becomes the canonical one
+// and the only requirement on this is that the interface descriptors match. If this
+// is an ABpBinder, no other state can be referenced from mClazz.
AIBinder_Class::AIBinder_Class(const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate,
AIBinder_Class_onDestroy onDestroy,
AIBinder_Class_onTransact onTransact)
@@ -632,6 +652,10 @@
(*in)->get()->markForBinder(binder->getBinder());
status_t status = android::OK;
+
+ // note - this is the only read of a value in clazz, and it comes with a warning
+ // on the API itself. Do not copy this design. Instead, attach data in a new
+ // version of the prepareTransaction function.
if (clazz->writeHeader) {
status = (*in)->get()->writeInterfaceToken(clazz->getInterfaceDescriptor());
}
diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h
index d7098e8..67bb092 100644
--- a/libs/binder/ndk/ibinder_internal.h
+++ b/libs/binder/ndk/ibinder_internal.h
@@ -53,12 +53,14 @@
}
private:
- std::optional<bool> associateClassInternal(const AIBinder_Class* clazz,
- const ::android::String16& newDescriptor, bool set);
-
// AIBinder instance is instance of this class for a local object. In order to transact on a
// remote object, this also must be set for simplicity (although right now, only the
// interfaceDescriptor from it is used).
+ //
+ // WARNING: When multiple classes exist with the same interface descriptor in different
+ // linkernamespaces, the first one to be associated with mClazz becomes the canonical one
+ // and the only requirement on this is that the interface descriptors match. If this
+ // is an ABpBinder, no other state can be referenced from mClazz.
const AIBinder_Class* mClazz;
std::mutex mClazzMutex;
};
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index 1af2119..05677a8 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -229,6 +229,11 @@
*
* Available since API level 33.
*
+ * WARNING: this API interacts badly with linkernamespaces. For correct behavior, you must
+ * use it on all instances of a class in the same process which share the same interface
+ * descriptor. In general, it is recommended you do not use this API, because it is disabling
+ * type safety.
+ *
* \param clazz class to disable interface header on.
*/
void AIBinder_Class_disableInterfaceTokenHeader(AIBinder_Class* clazz) __INTRODUCED_IN(33);
diff --git a/libs/binder/ndk/tests/iface.cpp b/libs/binder/ndk/tests/iface.cpp
index 2afe5d2..76acff5 100644
--- a/libs/binder/ndk/tests/iface.cpp
+++ b/libs/binder/ndk/tests/iface.cpp
@@ -72,6 +72,11 @@
AIBinder_Class* IFoo::kClass = AIBinder_Class_define(kIFooDescriptor, IFoo_Class_onCreate,
IFoo_Class_onDestroy, IFoo_Class_onTransact);
+// Defines the same class. Ordinarly, you would never want to do this, but it's done here
+// to simulate what would happen when multiple linker namespaces interact.
+AIBinder_Class* IFoo::kClassDupe = AIBinder_Class_define(
+ kIFooDescriptor, IFoo_Class_onCreate, IFoo_Class_onDestroy, IFoo_Class_onTransact);
+
class BpFoo : public IFoo {
public:
explicit BpFoo(AIBinder* binder) : mBinder(binder) {}
diff --git a/libs/binder/ndk/tests/include/iface/iface.h b/libs/binder/ndk/tests/include/iface/iface.h
index 7408d0c..0a562f0 100644
--- a/libs/binder/ndk/tests/include/iface/iface.h
+++ b/libs/binder/ndk/tests/include/iface/iface.h
@@ -30,8 +30,13 @@
static const char* kIFooDescriptor;
static AIBinder_Class* kClass;
+ static AIBinder_Class* kClassDupe;
// binder representing this interface with one reference count
+ // NOTE - this will create a new binder if it already exists. If you use
+ // getService for instance, you must pull outBinder. Don't use this without
+ // verifying isRemote or pointer equality. This is not a very good testing API - don't
+ // copy it - consider the AIDL-generated APIs instead.
AIBinder* getBinder();
// Takes ownership of IFoo
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index 9d5ef68..5b2532a 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -55,6 +55,18 @@
constexpr unsigned int kShutdownWaitTime = 10;
constexpr uint64_t kContextTestValue = 0xb4e42fb4d9a1d715;
+class MyTestFoo : public IFoo {
+ binder_status_t doubleNumber(int32_t in, int32_t* out) override {
+ *out = 2 * in;
+ LOG(INFO) << "doubleNumber (" << in << ") => " << *out;
+ return STATUS_OK;
+ }
+ binder_status_t die() override {
+ ADD_FAILURE() << "die called on local instance";
+ return STATUS_OK;
+ }
+};
+
class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest {
ndk::ScopedAStatus repeatInt(int32_t in, int32_t* out) {
*out = in;
@@ -296,11 +308,10 @@
}
TEST(NdkBinder, UnimplementedDump) {
- sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName);
+ ndk::SpAIBinder binder;
+ sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName, binder.getR());
ASSERT_NE(foo, nullptr);
- AIBinder* binder = foo->getBinder();
- EXPECT_EQ(OK, AIBinder_dump(binder, STDOUT_FILENO, nullptr, 0));
- AIBinder_decStrong(binder);
+ EXPECT_EQ(OK, AIBinder_dump(binder.get(), STDOUT_FILENO, nullptr, 0));
}
TEST(NdkBinder, UnimplementedShell) {
@@ -324,6 +335,24 @@
EXPECT_EQ(2, out);
}
+TEST(NdkBinder, ReassociateBpBinderWithSameDescriptor) {
+ ndk::SpAIBinder binder;
+ sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName, binder.getR());
+
+ EXPECT_TRUE(AIBinder_isRemote(binder.get()));
+
+ EXPECT_TRUE(AIBinder_associateClass(binder.get(), IFoo::kClassDupe));
+}
+
+TEST(NdkBinder, CantHaveTwoLocalBinderClassesWithSameDescriptor) {
+ sp<IFoo> foo = sp<MyTestFoo>::make();
+ ndk::SpAIBinder binder(foo->getBinder());
+
+ EXPECT_FALSE(AIBinder_isRemote(binder.get()));
+
+ EXPECT_FALSE(AIBinder_associateClass(binder.get(), IFoo::kClassDupe));
+}
+
TEST(NdkBinder, GetTestServiceStressTest) {
// libbinder has some complicated logic to make sure only one instance of
// ABpBinder is associated with each binder.
@@ -545,18 +574,6 @@
AIBinder_decStrong(binder);
}
-class MyTestFoo : public IFoo {
- binder_status_t doubleNumber(int32_t in, int32_t* out) override {
- *out = 2 * in;
- LOG(INFO) << "doubleNumber (" << in << ") => " << *out;
- return STATUS_OK;
- }
- binder_status_t die() override {
- ADD_FAILURE() << "die called on local instance";
- return STATUS_OK;
- }
-};
-
TEST(NdkBinder, SetInheritRt) {
// functional test in binderLibTest
sp<IFoo> foo = sp<MyTestFoo>::make();
@@ -597,7 +614,8 @@
sp<IFoo> foo = new MyTestFoo;
EXPECT_EQ(EX_NONE, foo->addService(kInstanceName));
- sp<IFoo> getFoo = IFoo::getService(kInstanceName);
+ ndk::SpAIBinder binder;
+ sp<IFoo> getFoo = IFoo::getService(kInstanceName, binder.getR());
EXPECT_EQ(foo.get(), getFoo.get());
int32_t out;
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index 435095a..b2e069c 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -617,15 +617,27 @@
static_assert(static_cast<int>(aidl::android::hardware::graphics::common::PixelFormat::R_8) ==
AHARDWAREBUFFER_FORMAT_R8_UNORM,
"HAL and AHardwareBuffer pixel format don't match");
+ static_assert(static_cast<int>(aidl::android::hardware::graphics::common::PixelFormat::R_16_UINT) ==
+ AHARDWAREBUFFER_FORMAT_R16_UINT,
+ "HAL and AHardwareBuffer pixel format don't match");
+ static_assert(static_cast<int>(aidl::android::hardware::graphics::common::PixelFormat::RG_1616_UINT) ==
+ AHARDWAREBUFFER_FORMAT_R16G16_UINT,
+ "HAL and AHardwareBuffer pixel format don't match");
+ static_assert(static_cast<int>(aidl::android::hardware::graphics::common::PixelFormat::RGBA_10101010) ==
+ AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM,
+ "HAL and AHardwareBuffer pixel format don't match");
switch (format) {
case AHARDWAREBUFFER_FORMAT_R8_UNORM:
+ case AHARDWAREBUFFER_FORMAT_R16_UINT:
+ case AHARDWAREBUFFER_FORMAT_R16G16_UINT:
case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
+ case AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM:
case AHARDWAREBUFFER_FORMAT_BLOB:
case AHARDWAREBUFFER_FORMAT_D16_UNORM:
case AHARDWAREBUFFER_FORMAT_D24_UNORM:
@@ -677,6 +689,7 @@
return 1;
case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
case AHARDWAREBUFFER_FORMAT_D16_UNORM:
+ case AHARDWAREBUFFER_FORMAT_R16_UINT:
return 2;
case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
case AHARDWAREBUFFER_FORMAT_D24_UNORM:
@@ -686,8 +699,10 @@
case AHARDWAREBUFFER_FORMAT_D32_FLOAT:
case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
case AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT:
+ case AHARDWAREBUFFER_FORMAT_R16G16_UINT:
return 4;
case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
+ case AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM:
return 8;
default:
return 0;
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index c35507b..b2e8bea 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -173,6 +173,27 @@
* OpenGL ES: GR_GL_R8
*/
AHARDWAREBUFFER_FORMAT_R8_UNORM = 0x38,
+
+ /**
+ * Corresponding formats:
+ * Vulkan: VK_FORMAT_R16_UINT
+ * OpenGL ES: GR_GL_R16UI
+ */
+ AHARDWAREBUFFER_FORMAT_R16_UINT = 0x39,
+
+ /**
+ * Corresponding formats:
+ * Vulkan: VK_FORMAT_R16G16_UINT
+ * OpenGL ES: GR_GL_RG16UI
+ */
+ AHARDWAREBUFFER_FORMAT_R16G16_UINT = 0x3a,
+
+ /**
+ * Corresponding formats:
+ * Vulkan: VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16
+ * OpenGL ES: N/A
+ */
+ AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM = 0x3b,
};
/**
diff --git a/libs/ui/include/ui/PixelFormat.h b/libs/ui/include/ui/PixelFormat.h
index f422ce4..cf5c2e8 100644
--- a/libs/ui/include/ui/PixelFormat.h
+++ b/libs/ui/include/ui/PixelFormat.h
@@ -53,16 +53,19 @@
// real pixel formats supported for rendering -----------------------------
- PIXEL_FORMAT_RGBA_8888 = HAL_PIXEL_FORMAT_RGBA_8888, // 4x8-bit RGBA
- PIXEL_FORMAT_RGBX_8888 = HAL_PIXEL_FORMAT_RGBX_8888, // 4x8-bit RGB0
- PIXEL_FORMAT_RGB_888 = HAL_PIXEL_FORMAT_RGB_888, // 3x8-bit RGB
- PIXEL_FORMAT_RGB_565 = HAL_PIXEL_FORMAT_RGB_565, // 16-bit RGB
- PIXEL_FORMAT_BGRA_8888 = HAL_PIXEL_FORMAT_BGRA_8888, // 4x8-bit BGRA
- PIXEL_FORMAT_RGBA_5551 = 6, // 16-bit ARGB
- PIXEL_FORMAT_RGBA_4444 = 7, // 16-bit ARGB
- PIXEL_FORMAT_RGBA_FP16 = HAL_PIXEL_FORMAT_RGBA_FP16, // 64-bit RGBA
- PIXEL_FORMAT_RGBA_1010102 = HAL_PIXEL_FORMAT_RGBA_1010102, // 32-bit RGBA
- PIXEL_FORMAT_R_8 = 0x38,
+ PIXEL_FORMAT_RGBA_8888 = HAL_PIXEL_FORMAT_RGBA_8888, // 4x8-bit RGBA
+ PIXEL_FORMAT_RGBX_8888 = HAL_PIXEL_FORMAT_RGBX_8888, // 4x8-bit RGB0
+ PIXEL_FORMAT_RGB_888 = HAL_PIXEL_FORMAT_RGB_888, // 3x8-bit RGB
+ PIXEL_FORMAT_RGB_565 = HAL_PIXEL_FORMAT_RGB_565, // 16-bit RGB
+ PIXEL_FORMAT_BGRA_8888 = HAL_PIXEL_FORMAT_BGRA_8888, // 4x8-bit BGRA
+ PIXEL_FORMAT_RGBA_5551 = 6, // 16-bit ARGB
+ PIXEL_FORMAT_RGBA_4444 = 7, // 16-bit ARGB
+ PIXEL_FORMAT_RGBA_FP16 = HAL_PIXEL_FORMAT_RGBA_FP16, // 64-bit RGBA
+ PIXEL_FORMAT_RGBA_1010102 = HAL_PIXEL_FORMAT_RGBA_1010102, // 32-bit RGBA
+ PIXEL_FORMAT_R_8 = 0x38,
+ PIXEL_FORMAT_R_16_UINT = 0x39,
+ PIXEL_FORMAT_RG_1616_UINT = 0x3a,
+ PIXEL_FORMAT_RGBA_10101010 = 0x3b,
};
typedef int32_t PixelFormat;
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 2e22c36..e9935e5 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -508,6 +508,10 @@
case VK_FORMAT_R8_UNORM:
native_format = android::PIXEL_FORMAT_R_8;
break;
+ // TODO: Do we need to query for VK_EXT_rgba10x6_formats here?
+ case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16:
+ native_format = android::PIXEL_FORMAT_RGBA_10101010;
+ break;
default:
ALOGV("unsupported swapchain format %d", format);
break;
@@ -754,7 +758,6 @@
const InstanceData& instance_data = GetData(pdev);
- bool wide_color_support = false;
uint64_t consumer_usage = 0;
bool colorspace_ext =
instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
@@ -765,27 +768,15 @@
if (!surfaceless_enabled) {
return VK_ERROR_SURFACE_LOST_KHR;
}
- // Support for VK_GOOGLE_surfaceless_query. The EGL loader
- // unconditionally supports wide color formats, even if they will cause
- // a SurfaceFlinger fallback. Based on that, wide_color_support will be
- // set to true in this case.
- wide_color_support = true;
+ // Support for VK_GOOGLE_surfaceless_query.
// TODO(b/203826952): research proper value; temporarily use the
// values seen on Pixel
consumer_usage = AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY;
} else {
Surface& surface = *SurfaceFromHandle(surface_handle);
- int err = native_window_get_wide_color_support(surface.window.get(),
- &wide_color_support);
- if (err) {
- return VK_ERROR_SURFACE_LOST_KHR;
- }
- ALOGV("wide_color_support is: %d", wide_color_support);
-
consumer_usage = surface.consumer_usage;
}
- wide_color_support = wide_color_support && colorspace_ext;
AHardwareBuffer_Desc desc = {};
desc.width = 1;
@@ -807,9 +798,6 @@
VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_PASS_THROUGH_EXT});
all_formats.emplace_back(VkSurfaceFormatKHR{
VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_BT709_LINEAR_EXT});
- }
-
- if (wide_color_support) {
all_formats.emplace_back(VkSurfaceFormatKHR{
VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT});
all_formats.emplace_back(VkSurfaceFormatKHR{
@@ -839,8 +827,6 @@
all_formats.emplace_back(
VkSurfaceFormatKHR{VK_FORMAT_R16G16B16A16_SFLOAT,
VK_COLOR_SPACE_PASS_THROUGH_EXT});
- }
- if (wide_color_support) {
all_formats.emplace_back(
VkSurfaceFormatKHR{VK_FORMAT_R16G16B16A16_SFLOAT,
VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT});
@@ -859,8 +845,6 @@
all_formats.emplace_back(
VkSurfaceFormatKHR{VK_FORMAT_A2B10G10R10_UNORM_PACK32,
VK_COLOR_SPACE_PASS_THROUGH_EXT});
- }
- if (wide_color_support) {
all_formats.emplace_back(
VkSurfaceFormatKHR{VK_FORMAT_A2B10G10R10_UNORM_PACK32,
VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT});
@@ -875,6 +859,22 @@
}
}
+ // TODO query VK_EXT_rgba10x6_formats support
+ desc.format = AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM;
+ if (AHardwareBuffer_isSupported(&desc)) {
+ all_formats.emplace_back(
+ VkSurfaceFormatKHR{VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
+ VK_COLOR_SPACE_SRGB_NONLINEAR_KHR});
+ if (colorspace_ext) {
+ all_formats.emplace_back(
+ VkSurfaceFormatKHR{VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
+ VK_COLOR_SPACE_PASS_THROUGH_EXT});
+ all_formats.emplace_back(
+ VkSurfaceFormatKHR{VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
+ VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT});
+ }
+ }
+
// NOTE: Any new formats that are added must be coordinated across different
// Android users. This includes the ANGLE team (a layered implementation of
// OpenGL-ES).
diff --git a/vulkan/vkjson/vkjson.cc b/vulkan/vkjson/vkjson.cc
index da6b00a..0284192 100644
--- a/vulkan/vkjson/vkjson.cc
+++ b/vulkan/vkjson/vkjson.cc
@@ -731,7 +731,7 @@
visitor->Visit("vulkanMemoryModelAvailabilityVisibilityChains", &features->vulkanMemoryModelAvailabilityVisibilityChains) &&
visitor->Visit("shaderOutputViewportIndex", &features->shaderOutputViewportIndex) &&
visitor->Visit("shaderOutputLayer", &features->shaderOutputLayer) &&
- visitor->Visit("shaderOutputLayer", &features->shaderOutputLayer);
+ visitor->Visit("subgroupBroadcastDynamicId", &features->subgroupBroadcastDynamicId);
}
template <typename Visitor>