Merge pi-platform-release to stage-aosp-master - DO NOT MERGE
Change-Id: I0ba6bf8ab80babed9d86ef028fa2610733b6a4d2
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
new file mode 100644
index 0000000..2d780f5
--- /dev/null
+++ b/PREUPLOAD.cfg
@@ -0,0 +1,7 @@
+[Hook Scripts]
+owners_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "OWNERS$"
+installd_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "^cmds/installd/"
+dumpstate_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "^cmds/dumpstate/"
+dumpsys_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "^cmds/dumpsys/"
+# bugreports matches both cmds/bugreport and cmds/bugreportz
+bugreports_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "^cmds/bugreport"
diff --git a/cmds/atrace/Android.bp b/cmds/atrace/Android.bp
index bb84a18..cc2a6f7 100644
--- a/cmds/atrace/Android.bp
+++ b/cmds/atrace/Android.bp
@@ -19,6 +19,7 @@
"libz",
"libbase",
"libpdx_default_transport",
+ "android.hardware.atrace@1.0",
],
init_rc: ["atrace.rc"],
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index fe9dd56..19c2830 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -37,6 +37,7 @@
#include <binder/IServiceManager.h>
#include <binder/Parcel.h>
+#include <android/hardware/atrace/1.0/IAtraceDevice.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
#include <hidl/ServiceManagement.h>
@@ -52,6 +53,12 @@
using namespace android;
using pdx::default_transport::ServiceUtility;
+using hardware::hidl_vec;
+using hardware::hidl_string;
+using hardware::Return;
+using hardware::atrace::V1_0::IAtraceDevice;
+using hardware::atrace::V1_0::Status;
+using hardware::atrace::V1_0::toString;
using std::string;
@@ -92,10 +99,7 @@
/* Tracing categories */
static const TracingCategory k_categories[] = {
- { "gfx", "Graphics", ATRACE_TAG_GRAPHICS, {
- { OPT, "events/mdss/enable" },
- { OPT, "events/sde/enable" },
- } },
+ { "gfx", "Graphics", ATRACE_TAG_GRAPHICS, { } },
{ "input", "Input", ATRACE_TAG_INPUT, { } },
{ "view", "View System", ATRACE_TAG_VIEW, { } },
{ "webview", "WebView", ATRACE_TAG_WEBVIEW, { } },
@@ -118,6 +122,7 @@
{ "adb", "ADB", ATRACE_TAG_ADB, { } },
{ "vibrator", "Vibrator", ATRACE_TAG_VIBRATOR, { } },
{ "aidl", "AIDL calls", ATRACE_TAG_AIDL, { } },
+ { "nnapi", "NNAPI", ATRACE_TAG_NNAPI, { } },
{ k_coreServiceCategory, "Core services", 0, { } },
{ k_pdxServiceCategory, "PDX services", 0, { } },
{ "sched", "CPU Scheduling", 0, {
@@ -200,7 +205,7 @@
{ REQ, "events/vmscan/mm_vmscan_direct_reclaim_end/enable" },
{ REQ, "events/vmscan/mm_vmscan_kswapd_wake/enable" },
{ REQ, "events/vmscan/mm_vmscan_kswapd_sleep/enable" },
- { REQ, "events/lowmemorykiller/enable" },
+ { OPT, "events/lowmemorykiller/enable" },
} },
{ "regulators", "Voltage and Current Regulators", 0, {
{ REQ, "events/regulator/enable" },
@@ -208,6 +213,7 @@
{ "binder_driver", "Binder Kernel driver", 0, {
{ REQ, "events/binder/binder_transaction/enable" },
{ REQ, "events/binder/binder_transaction_received/enable" },
+ { REQ, "events/binder/binder_transaction_alloc_buf/enable" },
{ OPT, "events/binder/binder_set_priority/enable" },
} },
{ "binder_lock", "Binder global lock trace", 0, {
@@ -218,6 +224,28 @@
{ "pagecache", "Page cache", 0, {
{ REQ, "events/filemap/enable" },
} },
+ { "memory", "Memory", 0, {
+ { OPT, "events/kmem/rss_stat/enable" },
+ { OPT, "events/kmem/ion_heap_grow/enable" },
+ { OPT, "events/kmem/ion_heap_shrink/enable" },
+ } },
+};
+
+struct TracingVendorCategory {
+ // The name identifying the category.
+ std::string name;
+
+ // A longer description of the category.
+ std::string description;
+
+ // 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)
+ {}
};
/* Command line options */
@@ -227,8 +255,8 @@
static bool g_compress = false;
static bool g_nohup = false;
static int g_initialSleepSecs = 0;
-static const char* g_categoriesFile = NULL;
-static const char* g_kernelTraceFuncs = NULL;
+static const char* g_categoriesFile = nullptr;
+static const char* g_kernelTraceFuncs = nullptr;
static const char* g_debugAppCmdLine = "";
static const char* g_outputFile = nullptr;
@@ -237,6 +265,8 @@
static bool g_traceAborted = false;
static bool g_categoryEnables[arraysize(k_categories)] = {};
static std::string g_traceFolder;
+static sp<IAtraceDevice> g_atraceHal;
+static std::vector<TracingVendorCategory> g_vendorCategories;
/* Sys file paths */
static const char* k_traceClockPath =
@@ -260,6 +290,9 @@
static const char* k_printTgidPath =
"options/print-tgid";
+static const char* k_recordTgidPath =
+ "options/record-tgid";
+
static const char* k_funcgraphAbsTimePath =
"options/funcgraph-abstime";
@@ -401,7 +434,7 @@
for (int i = 0; i < MAX_SYS_FILES; i++) {
const char* path = category.sysfiles[i].path;
bool req = category.sysfiles[i].required == REQ;
- if (path != NULL) {
+ if (path != nullptr) {
if (req) {
if (!fileIsWritable(path)) {
return false;
@@ -426,7 +459,7 @@
for (int i = 0; i < MAX_SYS_FILES; i++) {
const char* path = category.sysfiles[i].path;
bool req = category.sysfiles[i].required == REQ;
- if (path != NULL) {
+ if (path != nullptr) {
if (req) {
if (!fileExists(path)) {
return false;
@@ -522,9 +555,15 @@
static bool setPrintTgidEnableIfPresent(bool enable)
{
+ // Pre-4.13 this was options/print-tgid as an android-specific option.
+ // In 4.13+ this is an upstream option called options/record-tgid
+ // Both options produce the same ftrace format change
if (fileExists(k_printTgidPath)) {
return setKernelOptionEnable(k_printTgidPath, enable);
}
+ if (fileExists(k_recordTgidPath)) {
+ return setKernelOptionEnable(k_recordTgidPath, enable);
+ }
return true;
}
@@ -536,10 +575,10 @@
Vector<String16> services = sm->listServices();
for (size_t i = 0; i < services.size(); i++) {
sp<IBinder> obj = sm->checkService(services[i]);
- if (obj != NULL) {
+ if (obj != nullptr) {
Parcel data;
if (obj->transact(IBinder::SYSPROPS_TRANSACTION, data,
- NULL, 0) != OK) {
+ nullptr, 0) != OK) {
if (false) {
// XXX: For some reason this fails on tablets trying to
// poke the "phone" service. It's not clear whether some
@@ -629,9 +668,9 @@
{
int i = 0;
char* start = cmdline;
- while (start != NULL) {
+ while (start != nullptr) {
char* end = strchr(start, ',');
- if (end != NULL) {
+ if (end != nullptr) {
*end = '\0';
end++;
}
@@ -661,7 +700,7 @@
const TracingCategory &c = k_categories[i];
for (int j = 0; j < MAX_SYS_FILES; j++) {
const char* path = c.sysfiles[j].path;
- if (path != NULL && fileIsWritable(path)) {
+ if (path != nullptr && fileIsWritable(path)) {
ok &= setKernelOptionEnable(path, false);
}
}
@@ -697,7 +736,7 @@
ok = false;
}
}
- func = strtok(NULL, ",");
+ func = strtok(nullptr, ",");
}
free(myFuncs);
return ok;
@@ -708,7 +747,7 @@
{
bool ok = true;
- if (funcs == NULL || funcs[0] == '\0') {
+ if (funcs == nullptr || funcs[0] == '\0') {
// Disable kernel function tracing.
if (fileIsWritable(k_currentTracerPath)) {
ok &= writeStr(k_currentTracerPath, "nop");
@@ -730,7 +769,7 @@
char* func = strtok(myFuncs, ",");
while (func) {
ok &= appendStr(k_ftraceFilterPath, func);
- func = strtok(NULL, ",");
+ func = strtok(nullptr, ",");
}
free(myFuncs);
@@ -743,13 +782,20 @@
return ok;
}
-static bool setCategoryEnable(const char* name, bool enable)
+static bool setCategoryEnable(const char* name)
{
+ bool vendor_found = false;
+ for (auto &c : g_vendorCategories) {
+ if (strcmp(name, c.name.c_str()) == 0) {
+ c.enabled = true;
+ vendor_found = true;
+ }
+ }
for (size_t i = 0; i < arraysize(k_categories); i++) {
const TracingCategory& c = k_categories[i];
if (strcmp(name, c.name) == 0) {
if (isCategorySupported(c)) {
- g_categoryEnables[i] = enable;
+ g_categoryEnables[i] = true;
return true;
} else {
if (isCategorySupportedForRoot(c)) {
@@ -763,6 +809,9 @@
}
}
}
+ if (vendor_found) {
+ return true;
+ }
fprintf(stderr, "error: unknown tracing category \"%s\"\n", name);
return false;
}
@@ -772,7 +821,7 @@
if (!categories_file) {
return true;
}
- Tokenizer* tokenizer = NULL;
+ Tokenizer* tokenizer = nullptr;
if (Tokenizer::open(String8(categories_file), &tokenizer) != NO_ERROR) {
return false;
}
@@ -783,7 +832,7 @@
tokenizer->skipDelimiters(" ");
continue;
}
- ok &= setCategoryEnable(token.string(), true);
+ ok &= setCategoryEnable(token.string());
}
delete tokenizer;
return ok;
@@ -874,7 +923,7 @@
for (int j = 0; j < MAX_SYS_FILES; j++) {
const char* path = c.sysfiles[j].path;
bool required = c.sysfiles[j].required == REQ;
- if (path != NULL) {
+ if (path != nullptr) {
if (fileIsWritable(path)) {
ok &= setKernelOptionEnable(path, true);
} else if (required) {
@@ -899,7 +948,7 @@
setTraceOverwriteEnable(true);
setTraceBufferSizeKB(1);
setPrintTgidEnableIfPresent(false);
- setKernelTraceFuncs(NULL);
+ setKernelTraceFuncs(nullptr);
setUserInitiatedTraceProperty(false);
}
@@ -1057,10 +1106,10 @@
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = handleSignal;
- sigaction(SIGHUP, &sa, NULL);
- sigaction(SIGINT, &sa, NULL);
- sigaction(SIGQUIT, &sa, NULL);
- sigaction(SIGTERM, &sa, NULL);
+ sigaction(SIGHUP, &sa, nullptr);
+ sigaction(SIGINT, &sa, nullptr);
+ sigaction(SIGQUIT, &sa, nullptr);
+ sigaction(SIGTERM, &sa, nullptr);
}
static void listSupportedCategories()
@@ -1071,6 +1120,9 @@
printf(" %10s - %s\n", c.name, c.longname);
}
}
+ for (const auto &c : g_vendorCategories) {
+ printf(" %10s - %s (HAL)\n", c.name.c_str(), c.description.c_str());
+ }
}
// Print the command usage help to stderr.
@@ -1127,6 +1179,79 @@
return true;
}
+void initVendorCategories()
+{
+ g_atraceHal = IAtraceDevice::getService();
+
+ if (g_atraceHal == nullptr) {
+ // No atrace HAL
+ 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);
+ }
+ });
+ if (!ret.isOk()) {
+ fprintf(stderr, "calling atrace HAL failed: %s\n", ret.description().c_str());
+ }
+}
+
+static bool setUpVendorTracing()
+{
+ if (g_atraceHal == nullptr) {
+ // No atrace HAL
+ return true;
+ }
+
+ std::vector<hidl_string> categories;
+ for (const auto &c : g_vendorCategories) {
+ if (c.enabled) {
+ categories.emplace_back(c.name);
+ }
+ }
+
+ if (!categories.size()) {
+ return true;
+ }
+
+ auto ret = g_atraceHal->enableCategories(categories);
+ if (!ret.isOk()) {
+ fprintf(stderr, "calling atrace HAL failed: %s\n", ret.description().c_str());
+ return false;
+ } else if (ret != Status::SUCCESS) {
+ fprintf(stderr, "calling atrace HAL failed: %s\n", toString(ret).c_str());
+ return false;
+ }
+ return true;
+}
+
+static bool cleanUpVendorTracing()
+{
+ if (g_atraceHal == nullptr) {
+ // No atrace HAL
+ return true;
+ }
+
+ if (!g_vendorCategories.size()) {
+ // No vendor categories
+ return true;
+ }
+
+ auto ret = g_atraceHal->disableAllCategories();
+ if (!ret.isOk()) {
+ fprintf(stderr, "calling atrace HAL failed: %s\n", ret.description().c_str());
+ return false;
+ } else if (ret != Status::SUCCESS) {
+ fprintf(stderr, "calling atrace HAL failed: %s\n", toString(ret).c_str());
+ return false;
+ }
+ return true;
+}
+
int main(int argc, char **argv)
{
bool async = false;
@@ -1146,17 +1271,19 @@
exit(-1);
}
+ initVendorCategories();
+
for (;;) {
int ret;
int option_index = 0;
static struct option long_options[] = {
- {"async_start", no_argument, 0, 0 },
- {"async_stop", no_argument, 0, 0 },
- {"async_dump", no_argument, 0, 0 },
- {"only_userspace", no_argument, 0, 0 },
- {"list_categories", no_argument, 0, 0 },
- {"stream", no_argument, 0, 0 },
- { 0, 0, 0, 0 }
+ {"async_start", no_argument, nullptr, 0 },
+ {"async_stop", no_argument, nullptr, 0 },
+ {"async_dump", no_argument, nullptr, 0 },
+ {"only_userspace", no_argument, nullptr, 0 },
+ {"list_categories", no_argument, nullptr, 0 },
+ {"stream", no_argument, nullptr, 0 },
+ {nullptr, 0, nullptr, 0 }
};
ret = getopt_long(argc, argv, "a:b:cf:k:ns:t:zo:",
@@ -1164,7 +1291,7 @@
if (ret < 0) {
for (int i = optind; i < argc; i++) {
- if (!setCategoryEnable(argv[i], true)) {
+ if (!setCategoryEnable(argv[i])) {
fprintf(stderr, "error enabling tracing category \"%s\"\n", argv[i]);
exit(1);
}
@@ -1267,6 +1394,7 @@
if (ok && traceStart && !onlyUserspace) {
ok &= setUpKernelTracing();
+ ok &= setUpVendorTracing();
ok &= startTrace();
}
@@ -1285,9 +1413,7 @@
if (!onlyUserspace)
ok = clearTrace();
- if (!onlyUserspace)
- writeClockSyncMarker();
-
+ writeClockSyncMarker();
if (ok && !async && !traceStream) {
// Sleep to allow the trace to be captured.
struct timespec timeLeft;
@@ -1337,6 +1463,7 @@
// Reset the trace buffer size to 1.
if (traceStop) {
+ cleanUpVendorTracing();
cleanUpUserspaceTracing();
if (!onlyUserspace)
cleanUpKernelTracing();
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index d3d0711..d950b7c 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -19,6 +19,8 @@
chmod 0666 /sys/kernel/tracing/options/overwrite
chmod 0666 /sys/kernel/debug/tracing/options/print-tgid
chmod 0666 /sys/kernel/tracing/options/print-tgid
+ chmod 0666 /sys/kernel/debug/tracing/options/record-tgid
+ chmod 0666 /sys/kernel/tracing/options/record-tgid
chmod 0666 /sys/kernel/debug/tracing/saved_cmdlines_size
chmod 0666 /sys/kernel/tracing/saved_cmdlines_size
chmod 0666 /sys/kernel/debug/tracing/events/sched/sched_switch/enable
@@ -57,6 +59,8 @@
chmod 0666 /sys/kernel/tracing/events/binder/binder_transaction/enable
chmod 0666 /sys/kernel/debug/tracing/events/binder/binder_transaction_received/enable
chmod 0666 /sys/kernel/tracing/events/binder/binder_transaction_received/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/binder/binder_transaction_alloc_buf/enable
+ chmod 0666 /sys/kernel/tracing/events/binder/binder_transaction_alloc_buf/enable
chmod 0666 /sys/kernel/debug/tracing/events/binder/binder_lock/enable
chmod 0666 /sys/kernel/tracing/events/binder/binder_lock/enable
chmod 0666 /sys/kernel/debug/tracing/events/binder/binder_locked/enable
@@ -90,6 +94,10 @@
# disk
+ chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_get_data_block/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_get_data_block/enable
+ chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_iget/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_iget/enable
chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_enter/enable
chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_enter/enable
chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_exit/enable
@@ -102,6 +110,12 @@
chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_begin/enable
chmod 0666 /sys/kernel/tracing/events/ext4/ext4_da_write_end/enable
chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_end/enable
+ chmod 0666 /sys/kernel/tracing/events/ext4/ext4_es_lookup_extent_enter/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_es_lookup_extent_enter/enable
+ chmod 0666 /sys/kernel/tracing/events/ext4/ext4_es_lookup_extent_exit/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_es_lookup_extent_exit/enable
+ chmod 0666 /sys/kernel/tracing/events/ext4/ext4_load_inode/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_load_inode/enable
chmod 0666 /sys/kernel/tracing/events/ext4/ext4_sync_file_enter/enable
chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/enable
chmod 0666 /sys/kernel/tracing/events/ext4/ext4_sync_file_exit/enable
@@ -111,12 +125,6 @@
chmod 0666 /sys/kernel/tracing/events/block/block_rq_complete/enable
chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_complete/enable
- # graphics
- chmod 0666 /sys/kernel/tracing/events/sde/enable
- chmod 0666 /sys/kernel/debug/tracing/events/sde/enable
- chmod 0666 /sys/kernel/tracing/events/mdss/enable
- chmod 0666 /sys/kernel/debug/tracing/events/mdss/enable
-
# Tracing disabled by default
write /sys/kernel/debug/tracing/tracing_on 0
write /sys/kernel/tracing/tracing_on 0
@@ -125,6 +133,42 @@
chmod 0666 /sys/kernel/debug/tracing/trace
chmod 0666 /sys/kernel/tracing/trace
+# Read and truncate the per-CPU kernel trace.
+# Cannot use wildcards in .rc files. Update this if there is a phone with
+# more CPUs.
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu0/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu0/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu1/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu1/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu2/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu2/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu3/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu3/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu4/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu4/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu5/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu5/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu6/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu6/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu6/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu7/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu8/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu8/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu9/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu9/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu10/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu10/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu11/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu11/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu12/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu12/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu13/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu13/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu14/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu14/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu15/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu15/trace
+
on property:persist.debug.atrace.boottrace=1
start boottrace
diff --git a/cmds/bugreport/OWNERS b/cmds/bugreport/OWNERS
new file mode 100644
index 0000000..1ba7cff
--- /dev/null
+++ b/cmds/bugreport/OWNERS
@@ -0,0 +1,6 @@
+set noparent
+
+felipeal@google.com
+nandana@google.com
+jsharkey@android.com
+enh@google.com
diff --git a/cmds/bugreportz/OWNERS b/cmds/bugreportz/OWNERS
new file mode 100644
index 0000000..1ba7cff
--- /dev/null
+++ b/cmds/bugreportz/OWNERS
@@ -0,0 +1,6 @@
+set noparent
+
+felipeal@google.com
+nandana@google.com
+jsharkey@android.com
+enh@google.com
diff --git a/cmds/cmd/cmd.cpp b/cmds/cmd/cmd.cpp
index 48d5d4a..4238531 100644
--- a/cmds/cmd/cmd.cpp
+++ b/cmds/cmd/cmd.cpp
@@ -167,13 +167,6 @@
{
signal(SIGPIPE, SIG_IGN);
sp<ProcessState> proc = ProcessState::self();
- // setThreadPoolMaxThreadCount(0) actually tells the kernel it's
- // not allowed to spawn any additional threads, but we still spawn
- // a binder thread from userspace when we call startThreadPool().
- // This is safe because we only have 2 callbacks, neither of which
- // block.
- // See b/36066697 for rationale
- proc->setThreadPoolMaxThreadCount(0);
proc->startThreadPool();
#if DEBUG
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index b04543b..9aa1075 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -57,10 +57,21 @@
export_aidl_headers: true,
},
srcs: [
- "binder/android/os/IDumpstate.aidl",
+ "binder/android/os/DumpstateOptions.cpp",
+ ":dumpstate_aidl",
+ ],
+ export_include_dirs: ["binder"],
+}
+
+filegroup {
+ name: "dumpstate_aidl",
+ srcs: [
"binder/android/os/IDumpstateListener.aidl",
"binder/android/os/IDumpstateToken.aidl",
+ //"binder/android/os/DumpstateOptions.aidl",
+ "binder/android/os/IDumpstate.aidl",
],
+ path: "binder",
}
cc_defaults {
@@ -100,6 +111,31 @@
"dumpstate.cpp",
"main.cpp",
],
+ required: [
+ "atrace",
+ "df",
+ "getprop",
+ "ip",
+ "iptables",
+ "ip6tables",
+ "kill",
+ "librank",
+ "logcat",
+ "lsmod",
+ "lsof",
+ "netstat",
+ "parse_radio_log",
+ "printenv",
+ "procrank",
+ "screencap",
+ "showmap",
+ "ss",
+ "storaged",
+ "top",
+ "uptime",
+ "vdc",
+ "vril-dump",
+ ],
init_rc: ["dumpstate.rc"],
}
@@ -107,6 +143,7 @@
name: "dumpstate_test",
defaults: ["dumpstate_defaults"],
srcs: [
+ "dumpstate.cpp",
"tests/dumpstate_test.cpp",
],
static_libs: ["libgmock"],
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index 49a78e7..260ea4b 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -77,6 +77,13 @@
return binder::Status::ok();
}
+binder::Status DumpstateService::startBugreport(int, const sp<IDumpstateListener>&,
+ const DumpstateOptions&, int32_t* returned_id) {
+ // TODO: fork to handle the bugreport request and return the process id or a request id here.
+ *returned_id = -1;
+ return binder::Status::ok();
+}
+
status_t DumpstateService::dump(int fd, const Vector<String16>&) {
dprintf(fd, "id: %d\n", ds_.id_);
dprintf(fd, "pid: %d\n", ds_.pid_);
diff --git a/cmds/dumpstate/DumpstateService.h b/cmds/dumpstate/DumpstateService.h
index 7bca24a..131aff3 100644
--- a/cmds/dumpstate/DumpstateService.h
+++ b/cmds/dumpstate/DumpstateService.h
@@ -41,6 +41,9 @@
bool getSectionDetails,
sp<IDumpstateToken>* returned_token) override;
+ binder::Status startBugreport(int fd, const sp<IDumpstateListener>& listener,
+ const DumpstateOptions& options, int32_t* returned_id) override;
+
private:
Dumpstate& ds_;
std::mutex lock_;
diff --git a/cmds/dumpstate/DumpstateUtil.cpp b/cmds/dumpstate/DumpstateUtil.cpp
index 85eb464..600a500 100644
--- a/cmds/dumpstate/DumpstateUtil.cpp
+++ b/cmds/dumpstate/DumpstateUtil.cpp
@@ -56,11 +56,11 @@
timespec ts;
ts.tv_sec = MSEC_TO_SEC(timeout_ms);
ts.tv_nsec = (timeout_ms % 1000) * 1000000;
- int ret = TEMP_FAILURE_RETRY(sigtimedwait(&child_mask, NULL, &ts));
+ int ret = TEMP_FAILURE_RETRY(sigtimedwait(&child_mask, nullptr, &ts));
int saved_errno = errno;
// Set the signals back the way they were.
- if (sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) {
+ if (sigprocmask(SIG_SETMASK, &old_mask, nullptr) == -1) {
printf("*** sigprocmask failed: %s\n", strerror(errno));
if (ret == 0) {
return false;
@@ -310,7 +310,7 @@
struct sigaction sigact;
memset(&sigact, 0, sizeof(sigact));
sigact.sa_handler = SIG_IGN;
- sigaction(SIGPIPE, &sigact, NULL);
+ sigaction(SIGPIPE, &sigact, nullptr);
execvp(path, (char**)args.data());
// execvp's result will be handled after waitpid_with_timeout() below, but
diff --git a/cmds/dumpstate/OWNERS b/cmds/dumpstate/OWNERS
new file mode 100644
index 0000000..1ba7cff
--- /dev/null
+++ b/cmds/dumpstate/OWNERS
@@ -0,0 +1,6 @@
+set noparent
+
+felipeal@google.com
+nandana@google.com
+jsharkey@android.com
+enh@google.com
diff --git a/cmds/dumpstate/binder/android/os/DumpstateOptions.aidl b/cmds/dumpstate/binder/android/os/DumpstateOptions.aidl
new file mode 100644
index 0000000..c1a7f15
--- /dev/null
+++ b/cmds/dumpstate/binder/android/os/DumpstateOptions.aidl
@@ -0,0 +1,23 @@
+/**
+ * Copyright (c) 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.
+ */
+
+package android.os;
+
+/**
+ * Specifies arguments for IDumpstate.
+ * {@hide}
+ */
+parcelable DumpstateOptions cpp_header "android/os/DumpstateOptions.h";
diff --git a/cmds/dumpstate/binder/android/os/DumpstateOptions.cpp b/cmds/dumpstate/binder/android/os/DumpstateOptions.cpp
new file mode 100644
index 0000000..5654190
--- /dev/null
+++ b/cmds/dumpstate/binder/android/os/DumpstateOptions.cpp
@@ -0,0 +1,46 @@
+/**
+ * Copyright (c) 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.
+ */
+
+#include <android/os/DumpstateOptions.h>
+
+#include <binder/IBinder.h>
+#include <binder/Parcel.h>
+
+namespace android {
+namespace os {
+
+status_t DumpstateOptions::readFromParcel(const ::android::Parcel* parcel) {
+ if (status_t err = parcel->readBool(&get_section_details)) {
+ return err;
+ }
+ if (status_t err = parcel->readUtf8FromUtf16(&name)) {
+ return err;
+ }
+ return android::OK;
+}
+
+status_t DumpstateOptions::writeToParcel(::android::Parcel* parcel) const {
+ if (status_t err = parcel->writeBool(get_section_details)) {
+ return err;
+ }
+ if (status_t err = parcel->writeUtf8AsUtf16(name)) {
+ return err;
+ }
+ return android::OK;
+}
+
+} // namespace os
+} // namespace android
diff --git a/cmds/dumpstate/binder/android/os/DumpstateOptions.h b/cmds/dumpstate/binder/android/os/DumpstateOptions.h
new file mode 100644
index 0000000..a748e3c
--- /dev/null
+++ b/cmds/dumpstate/binder/android/os/DumpstateOptions.h
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 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.
+ */
+
+#ifndef ANDROID_OS_DUMPSTATE_OPTIONS_H_
+#define ANDROID_OS_DUMPSTATE_OPTIONS_H_
+
+#include <binder/Parcelable.h>
+
+namespace android {
+namespace os {
+
+struct DumpstateOptions : public android::Parcelable {
+ // If true the caller can get callbacks with per-section progress details.
+ bool get_section_details = false;
+
+ // Name of the caller.
+ std::string name;
+
+ status_t writeToParcel(android::Parcel* parcel) const override;
+ status_t readFromParcel(const android::Parcel* parcel) override;
+};
+
+} // namespace os
+} // namespace android
+
+#endif // ANDROID_OS_DUMPSTATE_OPTIONS_H_
diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
index 9b11b96..68a4f21 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
@@ -18,6 +18,7 @@
import android.os.IDumpstateListener;
import android.os.IDumpstateToken;
+import android.os.DumpstateOptions;
/**
* Binder interface for the currently running dumpstate process.
@@ -25,6 +26,8 @@
*/
interface IDumpstate {
+
+ // TODO: remove method once startBugReport is used by Shell.
/*
* Sets the listener for this dumpstate progress.
*
@@ -35,4 +38,11 @@
*/
IDumpstateToken setListener(@utf8InCpp String name, IDumpstateListener listener,
boolean getSectionDetails);
+
+ /*
+ * Starts a bugreport in a child process.
+ *
+ * Returns an identifier of the bugreport process running in the background.
+ */
+ int startBugreport(int fd, IDumpstateListener listener, in DumpstateOptions options);
}
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 9d897f5..17bb7c3 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -90,7 +90,7 @@
/* read before root is shed */
static char cmdline_buf[16384] = "(unknown)";
-static const char *dump_traces_path = NULL;
+static const char *dump_traces_path = nullptr;
// TODO: variables and functions below should be part of dumpstate object
@@ -101,7 +101,6 @@
#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
#define BLK_DEV_SYS_DIR "/sys/block"
-#define RAFT_DIR "/data/misc/raft"
#define RECOVERY_DIR "/cache/recovery"
#define RECOVERY_DATA_DIR "/data/misc/recovery"
#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
@@ -295,7 +294,7 @@
char path[PATH_MAX];
d = opendir(driverpath);
- if (d == NULL) {
+ if (d == nullptr) {
return;
}
@@ -333,7 +332,7 @@
}
// find anrd's pid if it is running.
- pid = GetPidByName("/system/xbin/anrd");
+ pid = GetPidByName("/system/bin/anrd");
if (pid > 0) {
if (stat(trace_path, &st) == 0) {
@@ -455,40 +454,6 @@
}
}
-static void dump_raft() {
- if (PropertiesHelper::IsUserBuild()) {
- return;
- }
-
- std::string raft_path = ds.GetPath("-raft_log.txt");
- if (raft_path.empty()) {
- MYLOGD("raft_path is empty\n");
- return;
- }
-
- struct stat s;
- if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
- MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
- return;
- }
-
- CommandOptions options = CommandOptions::WithTimeout(600).Build();
- if (!ds.IsZipping()) {
- // Write compressed and encoded raft logs to stdout if it's not a zipped bugreport.
- RunCommand("RAFT LOGS", {"logcompressor", "-r", RAFT_DIR}, options);
- return;
- }
-
- RunCommand("RAFT LOGS", {"logcompressor", "-n", "-r", RAFT_DIR, "-o", raft_path}, options);
- if (!ds.AddZipEntry("raft_log.txt", raft_path)) {
- MYLOGE("Unable to add raft log %s to zip file\n", raft_path.c_str());
- } else {
- if (remove(raft_path.c_str())) {
- MYLOGE("Error removing raft file %s: %s\n", raft_path.c_str(), strerror(errno));
- }
- }
-}
-
static bool skip_not_stat(const char *path) {
static const char stat[] = "/stat";
size_t len = strlen(path);
@@ -587,9 +552,9 @@
static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
unsigned long long fields[__STAT_NUMBER_FIELD];
bool z;
- char *cp, *buffer = NULL;
+ char *cp, *buffer = nullptr;
size_t i = 0;
- FILE *fp = fdopen(fd, "rb");
+ FILE *fp = fdopen(dup(fd), "rb");
getline(&buffer, &i, fp);
fclose(fp);
if (!buffer) {
@@ -926,53 +891,6 @@
RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
}
-static void AddGlobalAnrTraceFile(const bool add_to_zip, const std::string& anr_traces_file,
- const std::string& anr_traces_dir) {
- std::string dump_traces_dir;
-
- if (dump_traces_path != nullptr) {
- if (add_to_zip) {
- dump_traces_dir = dirname(dump_traces_path);
- MYLOGD("Adding ANR traces (directory %s) to the zip file\n", dump_traces_dir.c_str());
- ds.AddDir(dump_traces_dir, true);
- } else {
- MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
- dump_traces_path);
- ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
- }
- }
-
-
- // Make sure directory is not added twice.
- // TODO: this is an overzealous check because it's relying on dump_traces_path - which is
- // generated by dump_traces() - and anr_traces_path - which is retrieved from a system
- // property - but in reality they're the same path (although the former could be nullptr).
- // Anyways, once dump_traces() is refactored as a private Dumpstate function, this logic should
- // be revisited.
- bool already_dumped = anr_traces_dir == dump_traces_dir;
-
- MYLOGD("AddGlobalAnrTraceFile(): dump_traces_dir=%s, anr_traces_dir=%s, already_dumped=%d\n",
- dump_traces_dir.c_str(), anr_traces_dir.c_str(), already_dumped);
-
- android::base::unique_fd fd(TEMP_FAILURE_RETRY(
- open(anr_traces_file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
- if (fd.get() < 0) {
- printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_file.c_str(), strerror(errno));
- } else {
- if (add_to_zip) {
- if (!already_dumped) {
- MYLOGD("Adding dalvik ANR traces (directory %s) to the zip file\n",
- anr_traces_dir.c_str());
- ds.AddDir(anr_traces_dir, true);
- }
- } else {
- MYLOGD("Dumping last ANR traces (%s) to the main bugreport entry\n",
- anr_traces_file.c_str());
- dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_file.c_str(), fd.get());
- }
- }
-}
-
static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
anr_traces_dir.c_str());
@@ -1015,50 +933,22 @@
static void AddAnrTraceFiles() {
const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
- std::string anr_traces_file;
- std::string anr_traces_dir;
- bool is_global_trace_file = true;
+ std::string anr_traces_dir = "/data/anr";
- // First check whether the stack-trace-dir property is set. When it's set,
- // each ANR trace will be written to a separate file and not to a global
- // stack trace file.
- anr_traces_dir = android::base::GetProperty("dalvik.vm.stack-trace-dir", "");
- if (anr_traces_dir.empty()) {
- anr_traces_file = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
- if (!anr_traces_file.empty()) {
- anr_traces_dir = dirname(anr_traces_file.c_str());
- }
- } else {
- is_global_trace_file = false;
- }
+ AddAnrTraceDir(add_to_zip, anr_traces_dir);
- // We have neither configured a global trace file nor a trace directory,
- // there will be nothing to dump.
- if (anr_traces_file.empty() && anr_traces_dir.empty()) {
- printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
- return;
- }
-
- if (is_global_trace_file) {
- AddGlobalAnrTraceFile(add_to_zip, anr_traces_file, anr_traces_dir);
- } else {
- AddAnrTraceDir(add_to_zip, anr_traces_dir);
- }
-
- /* slow traces for slow operations */
+ // Slow traces for slow operations.
struct stat st;
- if (!anr_traces_dir.empty()) {
- int i = 0;
- while (true) {
- const std::string slow_trace_path =
- anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
- if (stat(slow_trace_path.c_str(), &st)) {
- // No traces file at this index, done with the files.
- break;
- }
- ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
- i++;
+ int i = 0;
+ while (true) {
+ const std::string slow_trace_path =
+ anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
+ if (stat(slow_trace_path.c_str(), &st)) {
+ // No traces file at this index, done with the files.
+ break;
}
+ ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
+ i++;
}
}
@@ -1314,10 +1204,12 @@
RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT);
if (ds.IsZipping()) {
- RunCommand("HARDWARE HALS", {"lshal"}, CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
+ RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z"},
+ CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
DumpHals();
} else {
- RunCommand("HARDWARE HALS", {"lshal", "--debug"}, CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
+ RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z", "--debug"},
+ CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
}
RunCommand("PRINTENV", {"printenv"});
@@ -1363,6 +1255,8 @@
DumpPacketStats();
+ RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
+
DoKmsg();
DumpIpAddrAndRules();
@@ -1443,7 +1337,7 @@
printf("== Running Application Services (platform)\n");
printf("========================================================\n");
- RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform"},
+ RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
DUMPSYS_COMPONENTS_OPTIONS);
printf("========================================================\n");
@@ -1482,6 +1376,54 @@
printf("========================================================\n");
}
+/* Dumps state for the default case. Returns true if everything went fine. */
+static bool DumpstateDefault() {
+ // Dumps systrace right away, otherwise it will be filled with unnecessary events.
+ // First try to dump anrd trace if the daemon is running. Otherwise, dump
+ // the raw trace.
+ if (!dump_anrd_trace()) {
+ dump_systrace();
+ }
+
+ // Invoking the following dumpsys calls before dump_traces() to try and
+ // keep the system stats as close to its initial state as possible.
+ RunDumpsysCritical();
+
+ /* collect stack traces from Dalvik and native processes (needs root) */
+ dump_traces_path = dump_traces();
+
+ /* Run some operations that require root. */
+ ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
+ ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
+
+ ds.AddDir(RECOVERY_DIR, true);
+ ds.AddDir(RECOVERY_DATA_DIR, true);
+ ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
+ ds.AddDir(LOGPERSIST_DATA_DIR, false);
+ if (!PropertiesHelper::IsUserBuild()) {
+ ds.AddDir(PROFILE_DATA_DIR_CUR, true);
+ ds.AddDir(PROFILE_DATA_DIR_REF, true);
+ }
+ add_mountinfo();
+ DumpIpTablesAsRoot();
+
+ // Capture any IPSec policies in play. No keys are exposed here.
+ RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
+
+ // Run ss as root so we can see socket marks.
+ RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
+
+ // Run iotop as root to show top 100 IO threads
+ RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
+
+ if (!DropRootUser()) {
+ return false;
+ }
+
+ dumpstate();
+ return true;
+}
+
// This method collects common dumpsys for telephony and wifi
static void DumpstateRadioCommon() {
DumpIpTablesAsRoot();
@@ -1537,6 +1479,12 @@
DUMPSYS_COMPONENTS_OPTIONS);
printf("========================================================\n");
+ printf("== Checkins\n");
+ printf("========================================================\n");
+
+ RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
+
+ printf("========================================================\n");
printf("== dumpstate: done (id %d)\n", ds.id_);
printf("========================================================\n");
}
@@ -1759,7 +1707,7 @@
| O_CLOEXEC | O_NOFOLLOW)));
if (fd == -1) {
MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
- return NULL;
+ return nullptr;
}
SHA256_CTX ctx;
@@ -1772,7 +1720,7 @@
break;
} else if (bytes_read == -1) {
MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
- return NULL;
+ return nullptr;
}
SHA256_Update(&ctx, buffer.data(), bytes_read);
@@ -1816,24 +1764,290 @@
// clang-format on
}
-/** Main entry point for dumpstate. */
-int run_main(int argc, char* argv[]) {
- int do_add_date = 0;
- int do_zip_file = 0;
- int do_vibrate = 1;
- char* use_outfile = 0;
- int use_socket = 0;
- int use_control_socket = 0;
- int do_fb = 0;
- int do_broadcast = 0;
- int is_remote_mode = 0;
- bool show_header_only = false;
- bool do_start_service = false;
- bool telephony_only = false;
- bool wifi_only = false;
- int dup_stdout_fd;
- int dup_stderr_fd;
+/*
+ * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
+ * if we are writing zip files and adds the version file.
+ */
+static void PrepareToWriteToFile() {
+ const Dumpstate::DumpOptions& options = ds.options_;
+ ds.bugreport_dir_ = dirname(options.use_outfile.c_str());
+ std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
+ std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
+ ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(options.use_outfile.c_str()),
+ device_name.c_str(), build_id.c_str());
+ if (options.do_add_date) {
+ char date[80];
+ strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
+ ds.name_ = date;
+ } else {
+ ds.name_ = "undated";
+ }
+ if (options.telephony_only) {
+ ds.base_name_ += "-telephony";
+ } else if (options.wifi_only) {
+ ds.base_name_ += "-wifi";
+ }
+
+ if (options.do_fb) {
+ ds.screenshot_path_ = ds.GetPath(".png");
+ }
+ ds.tmp_path_ = ds.GetPath(".tmp");
+ ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
+
+ MYLOGD(
+ "Bugreport dir: %s\n"
+ "Base name: %s\n"
+ "Suffix: %s\n"
+ "Log path: %s\n"
+ "Temporary path: %s\n"
+ "Screenshot path: %s\n",
+ ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
+ ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
+
+ if (options.do_zip_file) {
+ ds.path_ = ds.GetPath(".zip");
+ MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
+ create_parent_dirs(ds.path_.c_str());
+ ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
+ if (ds.zip_file == nullptr) {
+ MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
+ } else {
+ ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
+ }
+ ds.AddTextZipEntry("version.txt", ds.version_);
+ }
+}
+
+/*
+ * Finalizes writing to the file by renaming or zipping the tmp file to the final location,
+ * printing zipped file status, etc.
+ */
+static void FinalizeFile() {
+ const Dumpstate::DumpOptions& options = ds.options_;
+ /* check if user changed the suffix using system properties */
+ std::string name =
+ android::base::GetProperty(android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
+ bool change_suffix = false;
+ if (!name.empty()) {
+ /* must whitelist which characters are allowed, otherwise it could cross directories */
+ std::regex valid_regex("^[-_a-zA-Z0-9]+$");
+ if (std::regex_match(name.c_str(), valid_regex)) {
+ change_suffix = true;
+ } else {
+ MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
+ }
+ }
+ if (change_suffix) {
+ MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
+ ds.name_ = name;
+ if (!ds.screenshot_path_.empty()) {
+ std::string new_screenshot_path = ds.GetPath(".png");
+ if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
+ MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
+ new_screenshot_path.c_str(), strerror(errno));
+ } else {
+ ds.screenshot_path_ = new_screenshot_path;
+ }
+ }
+ }
+
+ bool do_text_file = true;
+ if (options.do_zip_file) {
+ if (!ds.FinishZipFile()) {
+ MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
+ do_text_file = true;
+ } else {
+ do_text_file = false;
+ // Since zip file is already created, it needs to be renamed.
+ std::string new_path = ds.GetPath(".zip");
+ if (ds.path_ != new_path) {
+ MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
+ if (rename(ds.path_.c_str(), new_path.c_str())) {
+ MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
+ strerror(errno));
+ } else {
+ ds.path_ = new_path;
+ }
+ }
+ }
+ }
+ if (do_text_file) {
+ ds.path_ = ds.GetPath(".txt");
+ MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(), ds.tmp_path_.c_str());
+ if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
+ MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(), strerror(errno));
+ ds.path_.clear();
+ }
+ }
+ if (options.use_control_socket) {
+ if (do_text_file) {
+ dprintf(ds.control_socket_fd_,
+ "FAIL:could not create zip file, check %s "
+ "for more details\n",
+ ds.log_path_.c_str());
+ } else {
+ dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
+ }
+ }
+}
+
+/* Broadcasts that we are done with the bugreport */
+static void SendBugreportFinishedBroadcast() {
+ const Dumpstate::DumpOptions& options = ds.options_;
+ if (!ds.path_.empty()) {
+ MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
+ // clang-format off
+
+ std::vector<std::string> am_args = {
+ "--receiver-permission", "android.permission.DUMP",
+ "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
+ "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
+ "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
+ "--es", "android.intent.extra.BUGREPORT", ds.path_,
+ "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
+ };
+ // clang-format on
+ if (options.do_fb) {
+ am_args.push_back("--es");
+ am_args.push_back("android.intent.extra.SCREENSHOT");
+ am_args.push_back(ds.screenshot_path_);
+ }
+ if (!ds.notification_title.empty()) {
+ am_args.push_back("--es");
+ am_args.push_back("android.intent.extra.TITLE");
+ am_args.push_back(ds.notification_title);
+ if (!ds.notification_description.empty()) {
+ am_args.push_back("--es");
+ am_args.push_back("android.intent.extra.DESCRIPTION");
+ am_args.push_back(ds.notification_description);
+ }
+ }
+ if (options.is_remote_mode) {
+ am_args.push_back("--es");
+ am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
+ am_args.push_back(SHA256_file_hash(ds.path_));
+ SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
+ } else {
+ SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
+ }
+ } else {
+ MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
+ }
+}
+
+int Dumpstate::ParseCommandlineOptions(int argc, char* argv[]) {
+ int ret = -1; // success
+ int c;
+ while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
+ switch (c) {
+ // clang-format off
+ case 'd': options_.do_add_date = true; break;
+ case 'z': options_.do_zip_file = true; break;
+ case 'o': options_.use_outfile = optarg; break;
+ case 's': options_.use_socket = true; break;
+ case 'S': options_.use_control_socket = true; break;
+ case 'v': options_.show_header_only = true; break;
+ case 'q': options_.do_vibrate = false; break;
+ case 'p': options_.do_fb = true; break;
+ case 'P': update_progress_ = true; break;
+ case 'R': options_.is_remote_mode = true; break;
+ case 'B': options_.do_broadcast = true; break;
+ case 'V': break; // compatibility no-op
+ case 'h':
+ ret = 0;
+ break;
+ default:
+ fprintf(stderr, "Invalid option: %c\n", c);
+ ret = 1;
+ break;
+ // clang-format on
+ }
+ }
+
+ // TODO: use helper function to convert argv into a string
+ for (int i = 0; i < argc; i++) {
+ args_ += argv[i];
+ if (i < argc - 1) {
+ args_ += " ";
+ }
+ }
+
+ // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
+ optind = 1;
+ return ret;
+}
+
+// TODO: Move away from system properties when we have binder.
+void Dumpstate::SetOptionsFromProperties() {
+ extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
+ if (!extra_options_.empty()) {
+ // Framework uses a system property to override some command-line args.
+ // Currently, it contains the type of the requested bugreport.
+ if (extra_options_ == "bugreportplus") {
+ // Currently, the dumpstate binder is only used by Shell to update progress.
+ options_.do_start_service = true;
+ update_progress_ = true;
+ options_.do_fb = false;
+ } else if (extra_options_ == "bugreportremote") {
+ options_.do_vibrate = false;
+ options_.is_remote_mode = true;
+ options_.do_fb = false;
+ } else if (extra_options_ == "bugreportwear") {
+ options_.do_start_service = true;
+ update_progress_ = true;
+ options_.do_zip_file = true;
+ } else if (extra_options_ == "bugreporttelephony") {
+ options_.telephony_only = true;
+ } else if (extra_options_ == "bugreportwifi") {
+ options_.wifi_only = true;
+ options_.do_zip_file = true;
+ } else {
+ MYLOGE("Unknown extra option: %s\n", extra_options_.c_str());
+ }
+ // Reset the property
+ android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
+ }
+
+ notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
+ if (!notification_title.empty()) {
+ // Reset the property
+ android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
+
+ notification_description = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
+ if (!notification_description.empty()) {
+ // Reset the property
+ android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
+ }
+ MYLOGD("notification (title: %s, description: %s)\n", notification_title.c_str(),
+ notification_description.c_str());
+ }
+}
+
+bool Dumpstate::ValidateOptions() {
+ if ((options_.do_zip_file || options_.do_add_date || ds.update_progress_ ||
+ options_.do_broadcast) &&
+ options_.use_outfile.empty()) {
+ return false;
+ }
+
+ if (options_.use_control_socket && !options_.do_zip_file) {
+ return false;
+ }
+
+ if (ds.update_progress_ && !options_.do_broadcast) {
+ return false;
+ }
+
+ if (options_.is_remote_mode && (ds.update_progress_ || !options_.do_broadcast ||
+ !options_.do_zip_file || !options_.do_add_date)) {
+ return false;
+ }
+ return true;
+}
+
+/* Main entry point for dumpstate. */
+int run_main(int argc, char* argv[]) {
/* set as high priority, and protect from OOM killer */
setpriority(PRIO_PROCESS, 0, -20);
@@ -1850,97 +2064,12 @@
}
}
- /* parse arguments */
- int c;
- while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
- switch (c) {
- // clang-format off
- case 'd': do_add_date = 1; break;
- case 'z': do_zip_file = 1; break;
- case 'o': use_outfile = optarg; break;
- case 's': use_socket = 1; break;
- case 'S': use_control_socket = 1; break;
- case 'v': show_header_only = true; break;
- case 'q': do_vibrate = 0; break;
- case 'p': do_fb = 1; break;
- case 'P': ds.update_progress_ = true; break;
- case 'R': is_remote_mode = 1; break;
- case 'B': do_broadcast = 1; break;
- case 'V': break; // compatibility no-op
- case 'h':
- ShowUsageAndExit(0);
- break;
- default:
- fprintf(stderr, "Invalid option: %c\n", c);
- ShowUsageAndExit();
- // clang-format on
- }
+ int status = ds.ParseCommandlineOptions(argc, argv);
+ if (status != -1) {
+ ShowUsageAndExit(status);
}
-
- // TODO: use helper function to convert argv into a string
- for (int i = 0; i < argc; i++) {
- ds.args_ += argv[i];
- if (i < argc - 1) {
- ds.args_ += " ";
- }
- }
-
- ds.extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
- if (!ds.extra_options_.empty()) {
- // Framework uses a system property to override some command-line args.
- // Currently, it contains the type of the requested bugreport.
- if (ds.extra_options_ == "bugreportplus") {
- // Currently, the dumpstate binder is only used by Shell to update progress.
- do_start_service = true;
- ds.update_progress_ = true;
- do_fb = 0;
- } else if (ds.extra_options_ == "bugreportremote") {
- do_vibrate = 0;
- is_remote_mode = 1;
- do_fb = 0;
- } else if (ds.extra_options_ == "bugreportwear") {
- do_start_service = true;
- ds.update_progress_ = true;
- do_zip_file = 1;
- } else if (ds.extra_options_ == "bugreporttelephony") {
- telephony_only = true;
- } else if (ds.extra_options_ == "bugreportwifi") {
- wifi_only = true;
- do_zip_file = 1;
- } else {
- MYLOGE("Unknown extra option: %s\n", ds.extra_options_.c_str());
- }
- // Reset the property
- android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
- }
-
- ds.notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
- if (!ds.notification_title.empty()) {
- // Reset the property
- android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
-
- ds.notification_description = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
- if (!ds.notification_description.empty()) {
- // Reset the property
- android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
- }
- MYLOGD("notification (title: %s, description: %s)\n",
- ds.notification_title.c_str(), ds.notification_description.c_str());
- }
-
- if ((do_zip_file || do_add_date || ds.update_progress_ || do_broadcast) && !use_outfile) {
- ExitOnInvalidArgs();
- }
-
- if (use_control_socket && !do_zip_file) {
- ExitOnInvalidArgs();
- }
-
- if (ds.update_progress_ && !do_broadcast) {
- ExitOnInvalidArgs();
- }
-
- if (is_remote_mode && (ds.update_progress_ || !do_broadcast || !do_zip_file || !do_add_date)) {
+ ds.SetOptionsFromProperties();
+ if (!ds.ValidateOptions()) {
ExitOnInvalidArgs();
}
@@ -1955,18 +2084,20 @@
exit(1);
}
- if (show_header_only) {
+ const Dumpstate::DumpOptions& options = ds.options_;
+ if (options.show_header_only) {
ds.PrintHeader();
exit(0);
}
- /* redirect output if needed */
- bool is_redirecting = !use_socket && use_outfile;
+ // Redirect output if needed
+ bool is_redirecting = !options.use_socket && !options.use_outfile.empty();
// TODO: temporarily set progress until it's part of the Dumpstate constructor
- std::string stats_path =
- is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt", dirname(use_outfile))
- : "";
+ std::string stats_path = is_redirecting
+ ? android::base::StringPrintf("%s/dumpstate-stats.txt",
+ dirname(options.use_outfile.c_str()))
+ : "";
ds.progress_.reset(new Progress(stats_path));
/* gets the sequential id */
@@ -1978,7 +2109,7 @@
register_sig_handler();
- if (do_start_service) {
+ if (options.do_start_service) {
MYLOGI("Starting 'dumpstate' service\n");
android::status_t ret;
if ((ret = android::os::DumpstateService::Start()) != android::OK) {
@@ -1999,70 +2130,22 @@
// If we are going to use a socket, do it as early as possible
// to avoid timeouts from bugreport.
- if (use_socket) {
+ if (options.use_socket) {
redirect_to_socket(stdout, "dumpstate");
}
- if (use_control_socket) {
+ if (options.use_control_socket) {
MYLOGD("Opening control socket\n");
ds.control_socket_fd_ = open_socket("dumpstate");
ds.update_progress_ = 1;
}
if (is_redirecting) {
- ds.bugreport_dir_ = dirname(use_outfile);
- std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
- std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
- ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(use_outfile),
- device_name.c_str(), build_id.c_str());
- if (do_add_date) {
- char date[80];
- strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
- ds.name_ = date;
- } else {
- ds.name_ = "undated";
- }
-
- if (telephony_only) {
- ds.base_name_ += "-telephony";
- } else if (wifi_only) {
- ds.base_name_ += "-wifi";
- }
-
- if (do_fb) {
- ds.screenshot_path_ = ds.GetPath(".png");
- }
- ds.tmp_path_ = ds.GetPath(".tmp");
- ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
-
- MYLOGD(
- "Bugreport dir: %s\n"
- "Base name: %s\n"
- "Suffix: %s\n"
- "Log path: %s\n"
- "Temporary path: %s\n"
- "Screenshot path: %s\n",
- ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(),
- ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
-
- if (do_zip_file) {
- ds.path_ = ds.GetPath(".zip");
- MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
- create_parent_dirs(ds.path_.c_str());
- ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
- if (ds.zip_file == nullptr) {
- MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
- do_zip_file = 0;
- } else {
- ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
- }
- ds.AddTextZipEntry("version.txt", ds.version_);
- }
+ PrepareToWriteToFile();
if (ds.update_progress_) {
- if (do_broadcast) {
+ if (options.do_broadcast) {
// clang-format off
-
std::vector<std::string> am_args = {
"--receiver-permission", "android.permission.DUMP",
"--es", "android.intent.extra.NAME", ds.name_,
@@ -2073,7 +2156,7 @@
// clang-format on
SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
}
- if (use_control_socket) {
+ if (options.use_control_socket) {
dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str());
}
}
@@ -2086,11 +2169,11 @@
fclose(cmdline);
}
- if (do_vibrate) {
+ if (options.do_vibrate) {
Vibrate(150);
}
- if (do_fb && ds.do_early_screenshot_) {
+ if (options.do_fb && ds.do_early_screenshot_) {
if (ds.screenshot_path_.empty()) {
// should not have happened
MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
@@ -2100,13 +2183,15 @@
}
}
- if (do_zip_file) {
+ if (options.do_zip_file && ds.zip_file != nullptr) {
if (chown(ds.path_.c_str(), AID_SHELL, AID_SHELL)) {
MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path_.c_str(),
strerror(errno));
}
}
+ int dup_stdout_fd;
+ int dup_stderr_fd;
if (is_redirecting) {
TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
redirect_to_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
@@ -2133,60 +2218,17 @@
// duration is logged into MYLOG instead.
ds.PrintHeader();
- if (telephony_only) {
+ if (options.telephony_only) {
DumpstateTelephonyOnly();
ds.DumpstateBoard();
- } else if (wifi_only) {
+ } else if (options.wifi_only) {
DumpstateWifiOnly();
} else {
- // Dumps systrace right away, otherwise it will be filled with unnecessary events.
- // First try to dump anrd trace if the daemon is running. Otherwise, dump
- // the raw trace.
- if (!dump_anrd_trace()) {
- dump_systrace();
- }
-
- // Invoking the following dumpsys calls before dump_traces() to try and
- // keep the system stats as close to its initial state as possible.
- RunDumpsysCritical();
-
- // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
- dump_raft();
-
- /* collect stack traces from Dalvik and native processes (needs root) */
- dump_traces_path = dump_traces();
-
- /* Run some operations that require root. */
- ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
- ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
-
- ds.AddDir(RECOVERY_DIR, true);
- ds.AddDir(RECOVERY_DATA_DIR, true);
- ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
- ds.AddDir(LOGPERSIST_DATA_DIR, false);
- if (!PropertiesHelper::IsUserBuild()) {
- ds.AddDir(PROFILE_DATA_DIR_CUR, true);
- ds.AddDir(PROFILE_DATA_DIR_REF, true);
- }
- add_mountinfo();
- DumpIpTablesAsRoot();
-
- // Capture any IPSec policies in play. No keys are exposed here.
- RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"},
- CommandOptions::WithTimeout(10).Build());
-
- // Run ss as root so we can see socket marks.
- RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"},
- CommandOptions::WithTimeout(10).Build());
-
- // Run iotop as root to show top 100 IO threads
- RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
-
- if (!DropRootUser()) {
+ // Dump state for the default case. This also drops root.
+ if (!DumpstateDefault()) {
+ // Something went wrong.
return -1;
}
-
- dumpstate();
}
/* close output if needed */
@@ -2195,79 +2237,12 @@
}
/* rename or zip the (now complete) .tmp file to its final location */
- if (use_outfile) {
-
- /* check if user changed the suffix using system properties */
- std::string name = android::base::GetProperty(
- android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
- bool change_suffix= false;
- if (!name.empty()) {
- /* must whitelist which characters are allowed, otherwise it could cross directories */
- std::regex valid_regex("^[-_a-zA-Z0-9]+$");
- if (std::regex_match(name.c_str(), valid_regex)) {
- change_suffix = true;
- } else {
- MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
- }
- }
- if (change_suffix) {
- MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
- ds.name_ = name;
- if (!ds.screenshot_path_.empty()) {
- std::string new_screenshot_path = ds.GetPath(".png");
- if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
- MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
- new_screenshot_path.c_str(), strerror(errno));
- } else {
- ds.screenshot_path_ = new_screenshot_path;
- }
- }
- }
-
- bool do_text_file = true;
- if (do_zip_file) {
- if (!ds.FinishZipFile()) {
- MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
- do_text_file = true;
- } else {
- do_text_file = false;
- // Since zip file is already created, it needs to be renamed.
- std::string new_path = ds.GetPath(".zip");
- if (ds.path_ != new_path) {
- MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
- if (rename(ds.path_.c_str(), new_path.c_str())) {
- MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
- strerror(errno));
- } else {
- ds.path_ = new_path;
- }
- }
- }
- }
- if (do_text_file) {
- ds.path_ = ds.GetPath(".txt");
- MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(),
- ds.tmp_path_.c_str());
- if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
- MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(),
- strerror(errno));
- ds.path_.clear();
- }
- }
- if (use_control_socket) {
- if (do_text_file) {
- dprintf(ds.control_socket_fd_,
- "FAIL:could not create zip file, check %s "
- "for more details\n",
- ds.log_path_.c_str());
- } else {
- dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
- }
- }
+ if (!options.use_outfile.empty()) {
+ FinalizeFile();
}
/* vibrate a few but shortly times to let user know it's finished */
- if (do_vibrate) {
+ if (options.do_vibrate) {
for (int i = 0; i < 3; i++) {
Vibrate(75);
usleep((75 + 50) * 1000);
@@ -2275,47 +2250,8 @@
}
/* tell activity manager we're done */
- if (do_broadcast) {
- if (!ds.path_.empty()) {
- MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
- // clang-format off
-
- std::vector<std::string> am_args = {
- "--receiver-permission", "android.permission.DUMP",
- "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
- "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
- "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
- "--es", "android.intent.extra.BUGREPORT", ds.path_,
- "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
- };
- // clang-format on
- if (do_fb) {
- am_args.push_back("--es");
- am_args.push_back("android.intent.extra.SCREENSHOT");
- am_args.push_back(ds.screenshot_path_);
- }
- if (!ds.notification_title.empty()) {
- am_args.push_back("--es");
- am_args.push_back("android.intent.extra.TITLE");
- am_args.push_back(ds.notification_title);
- if (!ds.notification_description.empty()) {
- am_args.push_back("--es");
- am_args.push_back("android.intent.extra.DESCRIPTION");
- am_args.push_back(ds.notification_description);
- }
- }
- if (is_remote_mode) {
- am_args.push_back("--es");
- am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
- am_args.push_back(SHA256_file_hash(ds.path_));
- SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED",
- am_args);
- } else {
- SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
- }
- } else {
- MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
- }
+ if (options.do_broadcast) {
+ SendBugreportFinishedBroadcast();
}
MYLOGD("Final progress: %d/%d (estimated %d)\n", ds.progress_->Get(), ds.progress_->GetMax(),
@@ -2327,7 +2263,7 @@
TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
}
- if (use_control_socket && ds.control_socket_fd_ != -1) {
+ if (options.use_control_socket && ds.control_socket_fd_ != -1) {
MYLOGD("Closing control socket\n");
close(ds.control_socket_fd_);
}
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index b220013..389cc2e 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -290,14 +290,51 @@
/* Returns true if the current version supports priority dump feature. */
bool CurrentVersionSupportsPriorityDumps() const;
- // TODO: initialize fields on constructor
+ // TODO: revisit the return values later.
+ /*
+ * Parses commandline arguments and sets runtime options accordingly.
+ *
+ * Returns 0 or positive number if the caller should exit with returned value as
+ * exit code, or returns -1 if caller should proceed with execution.
+ */
+ int ParseCommandlineOptions(int argc, char* argv[]);
+ /* Sets runtime options from the system properties. */
+ void SetOptionsFromProperties();
+
+ /* Returns true if the options set so far are consistent. */
+ bool ValidateOptions();
+
+ // TODO: add update_progress_ & other options from DumpState.
+ /*
+ * Structure to hold options that determine the behavior of dumpstate.
+ */
+ struct DumpOptions {
+ bool do_add_date = false;
+ bool do_zip_file = false;
+ bool do_vibrate = true;
+ bool use_socket = false;
+ bool use_control_socket = false;
+ bool do_fb = false;
+ bool do_broadcast = false;
+ bool is_remote_mode = false;
+ bool show_header_only = false;
+ bool do_start_service = false;
+ bool telephony_only = false;
+ bool wifi_only = false;
+ std::string use_outfile;
+ };
+
+ // TODO: initialize fields on constructor
// dumpstate id - unique after each device reboot.
uint32_t id_;
// dumpstate pid
pid_t pid_;
+ // Runtime options.
+ DumpOptions options_;
+
// Whether progress updates should be published.
bool update_progress_ = false;
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 838b385..c57535a 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -54,6 +54,8 @@
using ::testing::internal::GetCapturedStderr;
using ::testing::internal::GetCapturedStdout;
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
class DumpstateListenerMock : public IDumpstateListener {
public:
MOCK_METHOD1(onProgressUpdated, binder::Status(int32_t progress));
@@ -144,6 +146,7 @@
ds.progress_.reset(new Progress());
ds.update_progress_ = false;
ds.update_progress_threshold_ = 0;
+ ds.options_ = Dumpstate::DumpOptions();
}
// Runs a command and capture `stdout` and `stderr`.
@@ -201,6 +204,157 @@
Dumpstate& ds = Dumpstate::GetInstance();
};
+TEST_F(DumpstateTest, ParseCommandlineOptionsNone) {
+ // clang-format off
+ char* argv[] = {
+ const_cast<char*>("dumpstate")
+ };
+ // clang-format on
+
+ int ret = ds.ParseCommandlineOptions(ARRAY_SIZE(argv), argv);
+ EXPECT_EQ(-1, ret);
+ EXPECT_FALSE(ds.options_.do_add_date);
+ EXPECT_FALSE(ds.options_.do_zip_file);
+ EXPECT_EQ("", ds.options_.use_outfile);
+ EXPECT_FALSE(ds.options_.use_socket);
+ EXPECT_FALSE(ds.options_.use_control_socket);
+ EXPECT_FALSE(ds.options_.show_header_only);
+ EXPECT_TRUE(ds.options_.do_vibrate);
+ EXPECT_FALSE(ds.options_.do_fb);
+ EXPECT_FALSE(ds.update_progress_);
+ EXPECT_FALSE(ds.options_.is_remote_mode);
+ EXPECT_FALSE(ds.options_.do_broadcast);
+}
+
+TEST_F(DumpstateTest, ParseCommandlineOptionsPartial1) {
+ // clang-format off
+ char* argv[] = {
+ const_cast<char*>("dumpstate"),
+ const_cast<char*>("-d"),
+ const_cast<char*>("-z"),
+ const_cast<char*>("-o abc"),
+ const_cast<char*>("-s"),
+ const_cast<char*>("-S"),
+
+ };
+ // clang-format on
+ int ret = ds.ParseCommandlineOptions(ARRAY_SIZE(argv), argv);
+ EXPECT_EQ(-1, ret);
+ EXPECT_TRUE(ds.options_.do_add_date);
+ EXPECT_TRUE(ds.options_.do_zip_file);
+ // TODO: Maybe we should trim the filename
+ EXPECT_EQ(" abc", std::string(ds.options_.use_outfile));
+ EXPECT_TRUE(ds.options_.use_socket);
+ EXPECT_TRUE(ds.options_.use_control_socket);
+
+ // Other options retain default values
+ EXPECT_FALSE(ds.options_.show_header_only);
+ EXPECT_TRUE(ds.options_.do_vibrate);
+ EXPECT_FALSE(ds.options_.do_fb);
+ EXPECT_FALSE(ds.update_progress_);
+ EXPECT_FALSE(ds.options_.is_remote_mode);
+ EXPECT_FALSE(ds.options_.do_broadcast);
+}
+
+TEST_F(DumpstateTest, ParseCommandlineOptionsPartial2) {
+ // clang-format off
+ char* argv[] = {
+ const_cast<char*>("dumpstate"),
+ const_cast<char*>("-v"),
+ const_cast<char*>("-q"),
+ const_cast<char*>("-p"),
+ const_cast<char*>("-P"),
+ const_cast<char*>("-R"),
+ const_cast<char*>("-B"),
+ };
+ // clang-format on
+ int ret = ds.ParseCommandlineOptions(ARRAY_SIZE(argv), argv);
+ EXPECT_EQ(-1, ret);
+ EXPECT_TRUE(ds.options_.show_header_only);
+ EXPECT_FALSE(ds.options_.do_vibrate);
+ EXPECT_TRUE(ds.options_.do_fb);
+ EXPECT_TRUE(ds.update_progress_);
+ EXPECT_TRUE(ds.options_.is_remote_mode);
+ EXPECT_TRUE(ds.options_.do_broadcast);
+
+ // Other options retain default values
+ EXPECT_FALSE(ds.options_.do_add_date);
+ EXPECT_FALSE(ds.options_.do_zip_file);
+ EXPECT_EQ("", ds.options_.use_outfile);
+ EXPECT_FALSE(ds.options_.use_socket);
+ EXPECT_FALSE(ds.options_.use_control_socket);
+}
+
+TEST_F(DumpstateTest, ParseCommandlineOptionsHelp) {
+ // clang-format off
+ char* argv[] = {
+ const_cast<char*>("dumpstate"),
+ const_cast<char*>("-h")
+ };
+ // clang-format on
+ int ret = ds.ParseCommandlineOptions(ARRAY_SIZE(argv), argv);
+
+ // -h is for help. Caller exit with code = 0 after printing usage, so expect return = 0.
+ EXPECT_EQ(0, ret);
+}
+
+TEST_F(DumpstateTest, ParseCommandlineOptionsUnknown) {
+ // clang-format off
+ char* argv[] = {
+ const_cast<char*>("dumpstate"),
+ const_cast<char*>("-u") // unknown flag
+ };
+ // clang-format on
+ int ret = ds.ParseCommandlineOptions(ARRAY_SIZE(argv), argv);
+
+ // -u is unknown. Caller exit with code = 1 to show execution failure, after printing usage,
+ // so expect return = 1.
+ EXPECT_EQ(1, ret);
+}
+
+TEST_F(DumpstateTest, ValidateOptionsNeedOutfile1) {
+ ds.options_.do_zip_file = true;
+ EXPECT_FALSE(ds.ValidateOptions());
+ ds.options_.use_outfile = "a/b/c";
+ EXPECT_TRUE(ds.ValidateOptions());
+}
+
+TEST_F(DumpstateTest, ValidateOptionsNeedOutfile2) {
+ ds.options_.do_broadcast = true;
+ EXPECT_FALSE(ds.ValidateOptions());
+ ds.options_.use_outfile = "a/b/c";
+ EXPECT_TRUE(ds.ValidateOptions());
+}
+
+TEST_F(DumpstateTest, ValidateOptionsNeedZipfile) {
+ ds.options_.use_control_socket = true;
+ EXPECT_FALSE(ds.ValidateOptions());
+
+ ds.options_.do_zip_file = true;
+ ds.options_.use_outfile = "a/b/c"; // do_zip_file needs outfile
+ EXPECT_TRUE(ds.ValidateOptions());
+}
+
+TEST_F(DumpstateTest, ValidateOptionsUpdateProgressNeedsBroadcast) {
+ ds.update_progress_ = true;
+ ds.options_.use_outfile = "a/b/c"; // update_progress_ needs outfile
+ EXPECT_FALSE(ds.ValidateOptions());
+
+ ds.options_.do_broadcast = true;
+ EXPECT_TRUE(ds.ValidateOptions());
+}
+
+TEST_F(DumpstateTest, ValidateOptionsRemoteMode) {
+ ds.options_.is_remote_mode = true;
+ EXPECT_FALSE(ds.ValidateOptions());
+
+ ds.options_.do_broadcast = true;
+ ds.options_.do_zip_file = true;
+ ds.options_.do_add_date = true;
+ ds.options_.use_outfile = "a/b/c"; // do_broadcast needs outfile
+ EXPECT_TRUE(ds.ValidateOptions());
+}
+
TEST_F(DumpstateTest, RunCommandNoArgs) {
EXPECT_EQ(-1, RunCommand("", {}));
}
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 022f4fc..77f09b7 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -525,13 +525,13 @@
if (PropertiesHelper::IsDryRun()) return;
/* Get size of kernel buffer */
- int size = klogctl(KLOG_SIZE_BUFFER, NULL, 0);
+ int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
if (size <= 0) {
printf("Unexpected klogctl return value: %d\n\n", size);
return;
}
char *buf = (char *) malloc(size + 1);
- if (buf == NULL) {
+ if (buf == nullptr) {
printf("memory allocation failed\n\n");
return;
}
@@ -598,7 +598,7 @@
DurationReporter duration_reporter(title);
DIR *dirp;
struct dirent *d;
- char *newpath = NULL;
+ char *newpath = nullptr;
const char *slash = "/";
int retval = 0;
@@ -611,7 +611,7 @@
++slash;
}
dirp = opendir(dir);
- if (dirp == NULL) {
+ if (dirp == nullptr) {
retval = -errno;
MYLOGE("%s: %s\n", dir, strerror(errno));
return retval;
@@ -620,7 +620,7 @@
if (!dump_from_fd) {
dump_from_fd = dump_file_from_fd;
}
- for (; ((d = readdir(dirp))); free(newpath), newpath = NULL) {
+ for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
if ((d->d_name[0] == '.')
&& (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
|| (d->d_name[1] == '\0'))) {
@@ -648,7 +648,7 @@
printf("*** %s: %s\n", newpath, strerror(errno));
continue;
}
- (*dump_from_fd)(NULL, newpath, fd.get());
+ (*dump_from_fd)(nullptr, newpath, fd.get());
}
closedir(dirp);
if (!title.empty()) {
@@ -779,29 +779,11 @@
_redirect_to_file(redirect, path, O_APPEND);
}
-const char* DumpTraces(const std::string& traces_path);
-const char* DumpTracesTombstoned(const std::string& traces_dir);
-
-/* dump Dalvik and native stack traces, return the trace file location (NULL if none) */
-const char *dump_traces() {
+// Dump Dalvik and native stack traces, return the trace file location (nullptr if none).
+const char* dump_traces() {
DurationReporter duration_reporter("DUMP TRACES");
- const std::string traces_dir = android::base::GetProperty("dalvik.vm.stack-trace-dir", "");
- if (!traces_dir.empty()) {
- return DumpTracesTombstoned(traces_dir);
- }
-
- const std::string traces_file = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
- if (!traces_file.empty()) {
- return DumpTraces(traces_file);
- }
-
- return nullptr;
-}
-
-const char* DumpTracesTombstoned(const std::string& traces_dir) {
- const std::string temp_file_pattern = traces_dir + "/dumptrace_XXXXXX";
-
+ const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX";
const size_t buf_size = temp_file_pattern.length() + 1;
std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
@@ -902,156 +884,6 @@
return file_name_buf.release();
}
-const char* DumpTraces(const std::string& traces_path) {
- const char* result = NULL;
- /* move the old traces.txt (if any) out of the way temporarily */
- std::string anrtraces_path = traces_path + ".anr";
- if (rename(traces_path.c_str(), anrtraces_path.c_str()) && errno != ENOENT) {
- MYLOGE("rename(%s, %s): %s\n", traces_path.c_str(), anrtraces_path.c_str(), strerror(errno));
- return nullptr; // Can't rename old traces.txt -- no permission? -- leave it alone instead
- }
-
- /* create a new, empty traces.txt file to receive stack dumps */
- int fd = TEMP_FAILURE_RETRY(
- open(traces_path.c_str(), O_CREAT | O_WRONLY | O_APPEND | O_TRUNC | O_NOFOLLOW | O_CLOEXEC,
- 0666)); /* -rw-rw-rw- */
- if (fd < 0) {
- MYLOGE("%s: %s\n", traces_path.c_str(), strerror(errno));
- return nullptr;
- }
- int chmod_ret = fchmod(fd, 0666);
- if (chmod_ret < 0) {
- MYLOGE("fchmod on %s failed: %s\n", traces_path.c_str(), strerror(errno));
- close(fd);
- return nullptr;
- }
-
- /* Variables below must be initialized before 'goto' statements */
- int dalvik_found = 0;
- int ifd, wfd = -1;
- std::set<int> hal_pids = get_interesting_hal_pids();
-
- /* walk /proc and kill -QUIT all Dalvik processes */
- DIR *proc = opendir("/proc");
- if (proc == NULL) {
- MYLOGE("/proc: %s\n", strerror(errno));
- goto error_close_fd;
- }
-
- /* use inotify to find when processes are done dumping */
- ifd = inotify_init();
- if (ifd < 0) {
- MYLOGE("inotify_init: %s\n", strerror(errno));
- goto error_close_fd;
- }
-
- wfd = inotify_add_watch(ifd, traces_path.c_str(), IN_CLOSE_WRITE);
- if (wfd < 0) {
- MYLOGE("inotify_add_watch(%s): %s\n", traces_path.c_str(), strerror(errno));
- goto error_close_ifd;
- }
-
- struct dirent *d;
- while ((d = readdir(proc))) {
- int pid = atoi(d->d_name);
- if (pid <= 0) continue;
-
- char path[PATH_MAX];
- char data[PATH_MAX];
- snprintf(path, sizeof(path), "/proc/%d/exe", pid);
- ssize_t len = readlink(path, data, sizeof(data) - 1);
- if (len <= 0) {
- continue;
- }
- data[len] = '\0';
-
- if (!strncmp(data, "/system/bin/app_process", strlen("/system/bin/app_process"))) {
- /* skip zygote -- it won't dump its stack anyway */
- snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
- int cfd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC));
- len = read(cfd, data, sizeof(data) - 1);
- close(cfd);
- if (len <= 0) {
- continue;
- }
- data[len] = '\0';
- if (!strncmp(data, "zygote", strlen("zygote"))) {
- continue;
- }
-
- ++dalvik_found;
- uint64_t start = Nanotime();
- if (kill(pid, SIGQUIT)) {
- MYLOGE("kill(%d, SIGQUIT): %s\n", pid, strerror(errno));
- continue;
- }
-
- /* wait for the writable-close notification from inotify */
- struct pollfd pfd = { ifd, POLLIN, 0 };
- int ret = poll(&pfd, 1, TRACE_DUMP_TIMEOUT_MS);
- if (ret < 0) {
- MYLOGE("poll: %s\n", strerror(errno));
- } else if (ret == 0) {
- MYLOGE("warning: timed out dumping pid %d\n", pid);
- } else {
- struct inotify_event ie;
- read(ifd, &ie, sizeof(ie));
- }
-
- if (lseek(fd, 0, SEEK_END) < 0) {
- MYLOGE("lseek: %s\n", strerror(errno));
- } else {
- dprintf(fd, "[dump dalvik stack %d: %.3fs elapsed]\n", pid,
- (float)(Nanotime() - start) / NANOS_PER_SEC);
- }
- } else if (should_dump_native_traces(data) ||
- hal_pids.find(pid) != hal_pids.end()) {
- /* dump native process if appropriate */
- if (lseek(fd, 0, SEEK_END) < 0) {
- MYLOGE("lseek: %s\n", strerror(errno));
- } else {
- static uint16_t timeout_failures = 0;
- uint64_t start = Nanotime();
-
- /* If 3 backtrace dumps fail in a row, consider debuggerd dead. */
- if (timeout_failures == 3) {
- dprintf(fd, "too many stack dump failures, skipping...\n");
- } else if (dump_backtrace_to_file_timeout(
- pid, kDebuggerdNativeBacktrace, 20, fd) == -1) {
- dprintf(fd, "dumping failed, likely due to a timeout\n");
- timeout_failures++;
- } else {
- timeout_failures = 0;
- }
- dprintf(fd, "[dump native stack %d: %.3fs elapsed]\n", pid,
- (float)(Nanotime() - start) / NANOS_PER_SEC);
- }
- }
- }
-
- if (dalvik_found == 0) {
- MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
- }
-
- static std::string dumptraces_path = android::base::StringPrintf(
- "%s/bugreport-%s", dirname(traces_path.c_str()), basename(traces_path.c_str()));
- if (rename(traces_path.c_str(), dumptraces_path.c_str())) {
- MYLOGE("rename(%s, %s): %s\n", traces_path.c_str(), dumptraces_path.c_str(),
- strerror(errno));
- goto error_close_ifd;
- }
- result = dumptraces_path.c_str();
-
- /* replace the saved [ANR] traces.txt file */
- rename(anrtraces_path.c_str(), traces_path.c_str());
-
-error_close_ifd:
- close(ifd);
-error_close_fd:
- close(fd);
- return result;
-}
-
void dump_route_tables() {
DurationReporter duration_reporter("DUMP ROUTE TABLES");
if (PropertiesHelper::IsDryRun()) return;
diff --git a/cmds/dumpsys/OWNERS b/cmds/dumpsys/OWNERS
new file mode 100644
index 0000000..1ba7cff
--- /dev/null
+++ b/cmds/dumpsys/OWNERS
@@ -0,0 +1,6 @@
+set noparent
+
+felipeal@google.com
+nandana@google.com
+jsharkey@android.com
+enh@google.com
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index 5029352..8f60881 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -74,7 +74,7 @@
explicit WriteOnFdAction(const std::string& output) : output_(output) {
}
virtual Result Perform(const ArgumentTuple& args) {
- int fd = ::std::tr1::get<0>(args);
+ int fd = ::testing::get<0>(args);
android::base::WriteStringToFd(output_, fd);
}
diff --git a/cmds/flatland/GLHelper.cpp b/cmds/flatland/GLHelper.cpp
index d5b3372..62d2fa1 100644
--- a/cmds/flatland/GLHelper.cpp
+++ b/cmds/flatland/GLHelper.cpp
@@ -29,7 +29,7 @@
mContext(EGL_NO_CONTEXT),
mDummySurface(EGL_NO_SURFACE),
mConfig(0),
- mShaderPrograms(NULL),
+ mShaderPrograms(nullptr),
mDitherTexture(0) {
}
@@ -101,12 +101,12 @@
}
void GLHelper::tearDown() {
- if (mShaderPrograms != NULL) {
+ if (mShaderPrograms != nullptr) {
delete[] mShaderPrograms;
- mShaderPrograms = NULL;
+ mShaderPrograms = nullptr;
}
- if (mSurfaceComposerClient != NULL) {
+ if (mSurfaceComposerClient != nullptr) {
mSurfaceComposerClient->dispose();
mSurfaceComposerClient.clear();
}
@@ -210,7 +210,7 @@
glc->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
sp<ANativeWindow> anw = new Surface(producer);
- EGLSurface s = eglCreateWindowSurface(mDisplay, mConfig, anw.get(), NULL);
+ EGLSurface s = eglCreateWindowSurface(mDisplay, mConfig, anw.get(), nullptr);
if (s == EGL_NO_SURFACE) {
fprintf(stderr, "eglCreateWindowSurface error: %#x\n", eglGetError());
return false;
@@ -223,7 +223,7 @@
bool GLHelper::computeWindowScale(uint32_t w, uint32_t h, float* scale) {
sp<IBinder> dpy = mSurfaceComposerClient->getBuiltInDisplay(0);
- if (dpy == NULL) {
+ if (dpy == nullptr) {
fprintf(stderr, "SurfaceComposer::getBuiltInDisplay failed.\n");
return false;
}
@@ -247,7 +247,7 @@
bool result;
status_t err;
- if (mSurfaceComposerClient == NULL) {
+ if (mSurfaceComposerClient == nullptr) {
mSurfaceComposerClient = new SurfaceComposerClient;
}
err = mSurfaceComposerClient->initCheck();
@@ -258,7 +258,7 @@
sp<SurfaceControl> sc = mSurfaceComposerClient->createSurface(
String8("Benchmark"), w, h, PIXEL_FORMAT_RGBA_8888, 0);
- if (sc == NULL || !sc->isValid()) {
+ if (sc == nullptr || !sc->isValid()) {
fprintf(stderr, "Failed to create SurfaceControl.\n");
return false;
}
@@ -275,7 +275,7 @@
.apply();
sp<ANativeWindow> anw = sc->getSurface();
- EGLSurface s = eglCreateWindowSurface(mDisplay, mConfig, anw.get(), NULL);
+ EGLSurface s = eglCreateWindowSurface(mDisplay, mConfig, anw.get(), nullptr);
if (s == EGL_NO_SURFACE) {
fprintf(stderr, "eglCreateWindowSurface error: %#x\n", eglGetError());
return false;
@@ -294,7 +294,7 @@
return false;
}
- glShaderSource(shader, 1, &src, NULL);
+ glShaderSource(shader, 1, &src, nullptr);
glCompileShader(shader);
GLint compiled = 0;
@@ -305,7 +305,7 @@
if (infoLen) {
char* buf = new char[infoLen];
if (buf) {
- glGetShaderInfoLog(shader, infoLen, NULL, buf);
+ glGetShaderInfoLog(shader, infoLen, nullptr, buf);
fprintf(stderr, "Shader compile log:\n%s\n", buf);
delete[] buf;
}
@@ -318,21 +318,21 @@
}
static void printShaderSource(const char* const* src) {
- for (size_t i = 0; i < MAX_SHADER_LINES && src[i] != NULL; i++) {
+ for (size_t i = 0; i < MAX_SHADER_LINES && src[i] != nullptr; i++) {
fprintf(stderr, "%3zu: %s\n", i+1, src[i]);
}
}
static const char* makeShaderString(const char* const* src) {
size_t len = 0;
- for (size_t i = 0; i < MAX_SHADER_LINES && src[i] != NULL; i++) {
+ for (size_t i = 0; i < MAX_SHADER_LINES && src[i] != nullptr; i++) {
// The +1 is for the '\n' that will be added.
len += strlen(src[i]) + 1;
}
char* result = new char[len+1];
char* end = result;
- for (size_t i = 0; i < MAX_SHADER_LINES && src[i] != NULL; i++) {
+ for (size_t i = 0; i < MAX_SHADER_LINES && src[i] != nullptr; i++) {
strcpy(end, src[i]);
end += strlen(src[i]);
*end = '\n';
@@ -376,7 +376,7 @@
if (bufLength) {
char* buf = new char[bufLength];
if (buf) {
- glGetProgramInfoLog(program, bufLength, NULL, buf);
+ glGetProgramInfoLog(program, bufLength, nullptr, buf);
fprintf(stderr, "Program link log:\n%s\n", buf);
delete[] buf;
}
diff --git a/cmds/flatland/Main.cpp b/cmds/flatland/Main.cpp
index 3d7cac0..7ceb397 100644
--- a/cmds/flatland/Main.cpp
+++ b/cmds/flatland/Main.cpp
@@ -284,7 +284,7 @@
public:
Layer() :
- mGLHelper(NULL),
+ mGLHelper(nullptr),
mSurface(EGL_NO_SURFACE) {
}
@@ -316,23 +316,23 @@
}
void tearDown() {
- if (mComposer != NULL) {
+ if (mComposer != nullptr) {
mComposer->tearDown();
delete mComposer;
- mComposer = NULL;
+ mComposer = nullptr;
}
- if (mRenderer != NULL) {
+ if (mRenderer != nullptr) {
mRenderer->tearDown();
delete mRenderer;
- mRenderer = NULL;
+ mRenderer = nullptr;
}
if (mSurface != EGL_NO_SURFACE) {
mGLHelper->destroySurface(&mSurface);
mGLConsumer->abandon();
}
- mGLHelper = NULL;
+ mGLHelper = nullptr;
mGLConsumer.clear();
}
@@ -377,7 +377,7 @@
mDesc(desc),
mInstance(instance),
mNumLayers(countLayers(desc)),
- mGLHelper(NULL),
+ mGLHelper(nullptr),
mSurface(EGL_NO_SURFACE),
mWindowSurface(EGL_NO_SURFACE) {
}
@@ -443,7 +443,7 @@
mLayers[i].tearDown();
}
- if (mGLHelper != NULL) {
+ if (mGLHelper != nullptr) {
if (mWindowSurface != EGL_NO_SURFACE) {
mGLHelper->destroySurface(&mWindowSurface);
}
@@ -453,7 +453,7 @@
mSurfaceControl.clear();
mGLHelper->tearDown();
delete mGLHelper;
- mGLHelper = NULL;
+ mGLHelper = nullptr;
}
}
@@ -553,7 +553,7 @@
static size_t countLayers(const BenchmarkDesc& desc) {
size_t i;
for (i = 0; i < MAX_NUM_LAYERS; i++) {
- if (desc.layers[i].rendererFactory == NULL) {
+ if (desc.layers[i].rendererFactory == nullptr) {
break;
}
}
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index 94c3102..9d0d8ba 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -108,10 +108,8 @@
"-Wall",
"-Werror"
],
- clang: true,
- srcs: [
- "otapreopt_parameters.cpp"],
+ srcs: ["otapreopt_parameters.cpp"],
export_include_dirs: ["."],
@@ -123,4 +121,39 @@
],
}
-subdirs = ["tests"]
+//
+// OTA Executable
+//
+
+cc_binary {
+ name: "otapreopt",
+ cflags: [
+ "-Wall",
+ "-Werror"
+ ],
+
+ srcs: [
+ "dexopt.cpp",
+ "globals.cpp",
+ "otapreopt.cpp",
+ "utils.cpp",
+ ],
+
+ header_libs: ["dex2oat_headers"],
+
+ static_libs: [
+ "libartimagevalues",
+ "libdiskusage",
+ "libotapreoptparameters",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libcrypto",
+ "libcutils",
+ "liblog",
+ "liblogwrap",
+ "libselinux",
+ "libutils",
+ ],
+}
diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk
index a4f95da..30de0b3 100644
--- a/cmds/installd/Android.mk
+++ b/cmds/installd/Android.mk
@@ -1,43 +1,5 @@
LOCAL_PATH := $(call my-dir)
-#
-# OTA Executable
-#
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := otapreopt
-LOCAL_CFLAGS := -Wall -Werror
-
-# Base & ASLR boundaries for boot image creation.
-ifndef LIBART_IMG_HOST_MIN_BASE_ADDRESS_DELTA
- LOCAL_LIBART_IMG_HOST_MIN_BASE_ADDRESS_DELTA := -0x1000000
-else
- LOCAL_LIBART_IMG_HOST_MIN_BASE_ADDRESS_DELTA := $(LIBART_IMG_HOST_MIN_BASE_ADDRESS_DELTA)
-endif
-ifndef LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA
- LOCAL_LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA := 0x1000000
-else
- LOCAL_LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA := $(LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA)
-endif
-LOCAL_CFLAGS += -DART_BASE_ADDRESS=$(LIBART_IMG_HOST_BASE_ADDRESS)
-LOCAL_CFLAGS += -DART_BASE_ADDRESS_MIN_DELTA=$(LOCAL_LIBART_IMG_HOST_MIN_BASE_ADDRESS_DELTA)
-LOCAL_CFLAGS += -DART_BASE_ADDRESS_MAX_DELTA=$(LOCAL_LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA)
-
-LOCAL_SRC_FILES := otapreopt.cpp otapreopt_parameters.cpp globals.cpp utils.cpp dexopt.cpp
-LOCAL_HEADER_LIBRARIES := dex2oat_headers
-LOCAL_SHARED_LIBRARIES := \
- libbase \
- libcrypto \
- libcutils \
- liblog \
- liblogwrap \
- libselinux \
- libutils \
-
-LOCAL_STATIC_LIBRARIES := libdiskusage
-LOCAL_CLANG := true
-include $(BUILD_EXECUTABLE)
-
# OTA slot script
include $(CLEAR_VARS)
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 860a68b..e336232 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -775,7 +775,7 @@
PLOG(WARNING) << "Failed to chmod " << p->fts_path;
}
}
- // Intentional fall through to also set GID
+ [[fallthrough]]; // also set GID
case FTS_F:
if (chown(p->fts_path, -1, expected) != 0) {
PLOG(WARNING) << "Failed to chown " << p->fts_path;
@@ -1412,7 +1412,7 @@
&& !strcmp(p->fts_parent->fts_parent->fts_parent->fts_name, "Android")) {
p->fts_number = 1;
}
- // Fall through to count the directory
+ [[fallthrough]]; // to count the directory
case FTS_DEFAULT:
case FTS_F:
case FTS_SL:
@@ -1827,13 +1827,14 @@
}
}
}
- // Fall through to always count against total
+ [[fallthrough]]; // always count against total
case FTS_D:
// Ignore data belonging to specific apps
p->fts_number = p->fts_parent->fts_number;
if (p->fts_level == 1 && !strcmp(p->fts_name, "Android")) {
p->fts_number = 1;
}
+ [[fallthrough]]; // always count against total
case FTS_DEFAULT:
case FTS_SL:
case FTS_SLNONE:
diff --git a/cmds/installd/MatchExtensionGen.h b/cmds/installd/MatchExtensionGen.h
index fded6b7..35c3889 100644
--- a/cmds/installd/MatchExtensionGen.h
+++ b/cmds/installd/MatchExtensionGen.h
@@ -31,6 +31,7 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
case 'p': case 'P':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
@@ -41,10 +42,15 @@
switch (ext[5]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
}
+ break;
}
+ break;
}
+ break;
case 'a': case 'A':
switch (ext[1]) {
case 'a': case 'A':
@@ -53,7 +59,9 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
case 'i': case 'I':
switch (ext[2]) {
case 'f': case 'F':
@@ -63,56 +71,73 @@
switch (ext[4]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
case 'f': case 'F':
switch (ext[4]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
}
+ break;
case 'm': case 'M':
switch (ext[2]) {
case 'r': case 'R':
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
case 'r': case 'R':
switch (ext[2]) {
case 't': case 'T':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
case 'w': case 'W':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 's': case 'S':
switch (ext[2]) {
case 'f': case 'F':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
case 'x': case 'X':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
case 'v': case 'V':
switch (ext[2]) {
case 'i': case 'I':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
case 'w': case 'W':
switch (ext[2]) {
case 'b': case 'B':
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
}
+ break;
case 'b': case 'B':
switch (ext[1]) {
case 'm': case 'M':
@@ -121,8 +146,11 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
case 'c': case 'C':
switch (ext[1]) {
case 'r': case 'R':
@@ -131,8 +159,11 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
case 'd': case 'D':
switch (ext[1]) {
case 'i': case 'I':
@@ -141,23 +172,30 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
case 'l': case 'L':
switch (ext[2]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
case 'n': case 'N':
switch (ext[2]) {
case 'g': case 'G':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'v': case 'V':
switch (ext[2]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
case 'f': case 'F':
switch (ext[1]) {
case 'l': case 'L':
@@ -168,13 +206,18 @@
switch (ext[4]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
case 'i': case 'I':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
}
+ break;
case 'g': case 'G':
switch (ext[1]) {
case 'i': case 'I':
@@ -183,15 +226,20 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 's': case 'S':
switch (ext[2]) {
case 'm': case 'M':
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
}
+ break;
case 'j': case 'J':
switch (ext[1]) {
case 'n': case 'N':
@@ -200,7 +248,9 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'p': case 'P':
switch (ext[2]) {
case 'e': case 'E':
@@ -210,13 +260,18 @@
switch (ext[4]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'g': case 'G':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
case 'l': case 'L':
switch (ext[1]) {
case 's': case 'S':
@@ -225,12 +280,16 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
case 'x': case 'X':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
}
+ break;
case 'm': case 'M':
switch (ext[1]) {
case '3':
@@ -239,36 +298,46 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
case '4':
switch (ext[2]) {
case 'a': case 'A':
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
case 'v': case 'V':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
case 'k': case 'K':
switch (ext[2]) {
case 'a': case 'A':
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
case 'v': case 'V':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
case 'n': case 'N':
switch (ext[2]) {
case 'g': case 'G':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
case 'o': case 'O':
switch (ext[2]) {
case 'v': case 'V':
@@ -280,23 +349,30 @@
switch (ext[5]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
}
+ break;
}
+ break;
case 'p': case 'P':
switch (ext[2]) {
case '2':
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
case '3':
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
case '4':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
case 'e': case 'E':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
@@ -307,8 +383,11 @@
switch (ext[5]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
}
+ break;
case 'g': case 'G':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
@@ -316,16 +395,22 @@
switch (ext[4]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
}
+ break;
case 'x': case 'X':
switch (ext[2]) {
case 'u': case 'U':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
}
+ break;
case 'n': case 'N':
switch (ext[1]) {
case 'e': case 'E':
@@ -334,15 +419,20 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'r': case 'R':
switch (ext[2]) {
case 'w': case 'W':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
case 'o': case 'O':
switch (ext[1]) {
case 'g': case 'G':
@@ -351,19 +441,25 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
case 'g': case 'G':
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
case 'r': case 'R':
switch (ext[2]) {
case 'f': case 'F':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
case 'p': case 'P':
switch (ext[1]) {
case 'b': case 'B':
@@ -372,68 +468,88 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'c': case 'C':
switch (ext[2]) {
case 'x': case 'X':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'e': case 'E':
switch (ext[2]) {
case 'f': case 'F':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'g': case 'G':
switch (ext[2]) {
case 'm': case 'M':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'l': case 'L':
switch (ext[2]) {
case 's': case 'S':
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
case 'n': case 'N':
switch (ext[2]) {
case 'g': case 'G':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
case 'm': case 'M':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'p': case 'P':
switch (ext[2]) {
case 'm': case 'M':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 's': case 'S':
switch (ext[2]) {
case 'd': case 'D':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
case 'q': case 'Q':
switch (ext[1]) {
case 't': case 'T':
switch (ext[2]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
case 'r': case 'R':
switch (ext[1]) {
case 'a': case 'A':
@@ -443,30 +559,39 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
case 's': case 'S':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'g': case 'G':
switch (ext[2]) {
case 'b': case 'B':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'm': case 'M':
switch (ext[2]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
case 'w': case 'W':
switch (ext[2]) {
case '2':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
case 's': case 'S':
switch (ext[1]) {
case 'd': case 'D':
@@ -475,21 +600,27 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
case 'n': case 'N':
switch (ext[2]) {
case 'd': case 'D':
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
case 'r': case 'R':
switch (ext[2]) {
case 'w': case 'W':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'v': case 'V':
switch (ext[2]) {
case 'g': case 'G':
@@ -499,9 +630,13 @@
switch (ext[4]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
}
+ break;
case 't': case 'T':
switch (ext[1]) {
case 'i': case 'I':
@@ -513,13 +648,18 @@
switch (ext[4]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
case 's': case 'S':
switch (ext[2]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
case 'v': case 'V':
switch (ext[1]) {
case 'o': case 'O':
@@ -528,8 +668,11 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
}
+ break;
case 'w': case 'W':
switch (ext[1]) {
case 'a': case 'A':
@@ -538,11 +681,14 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
case 'x': case 'X':
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
}
+ break;
case 'b': case 'B':
switch (ext[2]) {
case 'm': case 'M':
@@ -551,8 +697,11 @@
switch (ext[4]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
case 'e': case 'E':
switch (ext[2]) {
case 'b': case 'B':
@@ -561,12 +710,16 @@
switch (ext[4]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
case 'p': case 'P':
switch (ext[4]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
case 'm': case 'M':
switch (ext[2]) {
case '\0': return AID_MEDIA_VIDEO;
@@ -574,30 +727,39 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_AUDIO;
}
+ break;
case 'v': case 'V':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
case 'x': case 'X':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
case 'r': case 'R':
switch (ext[2]) {
case 'f': case 'F':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
case 'v': case 'V':
switch (ext[2]) {
case 'x': case 'X':
switch (ext[3]) {
case '\0': return AID_MEDIA_VIDEO;
}
+ break;
}
+ break;
}
+ break;
case 'x': case 'X':
switch (ext[1]) {
case 'b': case 'B':
@@ -606,22 +768,29 @@
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'p': case 'P':
switch (ext[2]) {
case 'm': case 'M':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
case 'w': case 'W':
switch (ext[2]) {
case 'd': case 'D':
switch (ext[3]) {
case '\0': return AID_MEDIA_IMAGE;
}
+ break;
}
+ break;
}
+ break;
}
return 0;
diff --git a/cmds/installd/OWNERS b/cmds/installd/OWNERS
new file mode 100644
index 0000000..50440f1
--- /dev/null
+++ b/cmds/installd/OWNERS
@@ -0,0 +1,7 @@
+set noparent
+
+calin@google.com
+agampe@google.com
+jsharkey@android.com
+toddke@google.com
+ngeoffray@google.com
diff --git a/cmds/installd/TEST_MAPPING b/cmds/installd/TEST_MAPPING
new file mode 100644
index 0000000..3de5c79
--- /dev/null
+++ b/cmds/installd/TEST_MAPPING
@@ -0,0 +1,19 @@
+{
+ "presubmit": [
+ {
+ "name": "installd_cache_test"
+ },
+ {
+ "name": "installd_dexopt_test"
+ },
+ {
+ "name": "installd_otapreopt_test"
+ },
+ {
+ "name": "installd_service_test"
+ },
+ {
+ "name": "installd_utils_test"
+ }
+ ]
+}
diff --git a/cmds/installd/art_helper/Android.bp b/cmds/installd/art_helper/Android.bp
new file mode 100644
index 0000000..c47dd72
--- /dev/null
+++ b/cmds/installd/art_helper/Android.bp
@@ -0,0 +1,12 @@
+// Inherit image values.
+art_global_defaults {
+ name: "libartimagevalues_defaults",
+}
+
+cc_library_static {
+ name: "libartimagevalues",
+ defaults: ["libartimagevalues_defaults"],
+ srcs: ["art_image_values.cpp"],
+ export_include_dirs: ["."],
+ cflags: ["-Wconversion"],
+}
diff --git a/cmds/installd/art_helper/art_image_values.cpp b/cmds/installd/art_helper/art_image_values.cpp
new file mode 100644
index 0000000..a139049
--- /dev/null
+++ b/cmds/installd/art_helper/art_image_values.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "art_image_values.h"
+
+namespace android {
+namespace installd {
+namespace art {
+
+uint32_t GetImageBaseAddress() {
+ return ART_BASE_ADDRESS;
+}
+int32_t GetImageMinBaseAddressDelta() {
+ return ART_BASE_ADDRESS_MIN_DELTA;
+}
+int32_t GetImageMaxBaseAddressDelta() {
+ return ART_BASE_ADDRESS_MAX_DELTA;
+}
+
+static_assert(ART_BASE_ADDRESS_MIN_DELTA < ART_BASE_ADDRESS_MAX_DELTA, "Inconsistent setup");
+
+} // namespace art
+} // namespace installd
+} // namespace android
diff --git a/cmds/installd/art_helper/art_image_values.h b/cmds/installd/art_helper/art_image_values.h
new file mode 100644
index 0000000..20c44c9
--- /dev/null
+++ b/cmds/installd/art_helper/art_image_values.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef FRAMEWORKS_NATIVE_CMDS_INSTALLD_ART_HELPER_ART_IMAGE_VALUES_H
+#define FRAMEWORKS_NATIVE_CMDS_INSTALLD_ART_HELPER_ART_IMAGE_VALUES_H
+
+#include <cstdint>
+
+namespace android {
+namespace installd {
+namespace art {
+
+uint32_t GetImageBaseAddress();
+int32_t GetImageMinBaseAddressDelta();
+int32_t GetImageMaxBaseAddressDelta();
+
+} // namespace art
+} // namespace installd
+} // namespace android
+
+#endif // FRAMEWORKS_NATIVE_CMDS_INSTALLD_ART_HELPER_ART_IMAGE_VALUES_H
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 9615a75..03a411d 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#define LOG_TAG "installed"
+#define LOG_TAG "installd"
#include <array>
#include <fcntl.h>
@@ -773,7 +773,8 @@
}
// program name, reference profile fd, the final NULL and the profile fds
- const char* argv[3 + profile_args.size() + apk_args.size() + (copy_and_update ? 1 : 0)];
+ const char* argv[3 + profile_args.size() + apk_args.size()
+ + dex_location_args.size() + (copy_and_update ? 1 : 0)];
int i = 0;
argv[i++] = profman_bin;
argv[i++] = reference_profile_arg.c_str();
@@ -1691,15 +1692,12 @@
*dexopt_needed_out = NO_DEXOPT_NEEDED; return true;
case 1: // dexoptanalyzer: dex2oat_from_scratch
*dexopt_needed_out = DEX2OAT_FROM_SCRATCH; return true;
- case 5: // dexoptanalyzer: dex2oat_for_bootimage_odex
+ case 4: // dexoptanalyzer: dex2oat_for_bootimage_odex
*dexopt_needed_out = -DEX2OAT_FOR_BOOT_IMAGE; return true;
- case 6: // dexoptanalyzer: dex2oat_for_filter_odex
+ case 5: // dexoptanalyzer: dex2oat_for_filter_odex
*dexopt_needed_out = -DEX2OAT_FOR_FILTER; return true;
- case 7: // dexoptanalyzer: dex2oat_for_relocation_odex
- *dexopt_needed_out = -DEX2OAT_FOR_RELOCATION; return true;
case 2: // dexoptanalyzer: dex2oat_for_bootimage_oat
case 3: // dexoptanalyzer: dex2oat_for_filter_oat
- case 4: // dexoptanalyzer: dex2oat_for_relocation_oat
*error_msg = StringPrintf("Dexoptanalyzer return the status of an oat file."
" Expected odex file status for secondary dex %s"
" : dexoptanalyzer result=%d",
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index bb6fab3..0db11e1 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -31,7 +31,6 @@
static constexpr int DEX2OAT_FROM_SCRATCH = 1;
static constexpr int DEX2OAT_FOR_BOOT_IMAGE = 2;
static constexpr int DEX2OAT_FOR_FILTER = 3;
-static constexpr int DEX2OAT_FOR_RELOCATION = 4;
// Clear the reference profile identified by the given profile name.
bool clear_primary_reference_profile(const std::string& pkgname, const std::string& profile_name);
diff --git a/cmds/installd/matchgen.py b/cmds/installd/matchgen.py
index 131487d..42ce82b 100644
--- a/cmds/installd/matchgen.py
+++ b/cmds/installd/matchgen.py
@@ -84,6 +84,8 @@
print "%scase '%s':" % (prefix, k)
dump(target[k], index + 1)
print "%s}" % (prefix)
+ if index > 0:
+ print "%sbreak;" % (prefix)
dump(trie, 0)
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 96d8c47..b2e7047 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -32,6 +32,7 @@
#include <android-base/macros.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
+#include <art_image_values.h>
#include <cutils/fs.h>
#include <cutils/properties.h>
#include <dex2oat_return_codes.h>
@@ -88,6 +89,12 @@
"DEXOPT_MASK unexpected.");
+template<typename T>
+static constexpr bool IsPowerOfTwo(T x) {
+ static_assert(std::is_integral<T>::value, "T must be integral");
+ // TODO: assert unsigned. There is currently many uses with signed values.
+ return (x & (x - 1)) == 0;
+}
template<typename T>
static constexpr T RoundDown(T x, typename std::decay<T>::type n) {
@@ -315,21 +322,8 @@
return false;
}
const char* isa = parameters_.instruction_set;
-
- // Check whether the file exists where expected.
std::string dalvik_cache = GetOTADataDirectory() + "/" + DALVIK_CACHE;
std::string isa_path = dalvik_cache + "/" + isa;
- std::string art_path = isa_path + "/system@framework@boot.art";
- std::string oat_path = isa_path + "/system@framework@boot.oat";
- bool cleared = false;
- if (access(art_path.c_str(), F_OK) == 0 && access(oat_path.c_str(), F_OK) == 0) {
- // Files exist, assume everything is alright if not forced. Otherwise clean up.
- if (!force) {
- return true;
- }
- ClearDirectory(isa_path);
- cleared = true;
- }
// Reset umask in otapreopt, so that we control the the access for the files we create.
umask(0);
@@ -348,18 +342,34 @@
}
}
- // Prepare to create.
+ // Check whether we have files in /data.
+ // TODO: check that the files are correct wrt/ jars.
+ std::string art_path = isa_path + "/system@framework@boot.art";
+ std::string oat_path = isa_path + "/system@framework@boot.oat";
+ bool cleared = false;
+ if (access(art_path.c_str(), F_OK) == 0 && access(oat_path.c_str(), F_OK) == 0) {
+ // Files exist, assume everything is alright if not forced. Otherwise clean up.
+ if (!force) {
+ return true;
+ }
+ ClearDirectory(isa_path);
+ cleared = true;
+ }
+
+ // Check whether we have an image in /system.
+ // TODO: check that the files are correct wrt/ jars.
+ std::string preopted_boot_art_path = StringPrintf("/system/framework/%s/boot.art", isa);
+ if (access(preopted_boot_art_path.c_str(), F_OK) == 0) {
+ // Note: we ignore |force| here.
+ return true;
+ }
+
+
if (!cleared) {
ClearDirectory(isa_path);
}
- std::string preopted_boot_art_path = StringPrintf("/system/framework/%s/boot.art", isa);
- if (access(preopted_boot_art_path.c_str(), F_OK) == 0) {
- return PatchoatBootImage(isa_path, isa);
- } else {
- // No preopted boot image. Try to compile.
- return Dex2oatBootImage(boot_classpath_, art_path, oat_path, isa);
- }
+ return Dex2oatBootImage(boot_classpath_, art_path, oat_path, isa);
}
static bool CreatePath(const std::string& path) {
@@ -424,29 +434,6 @@
CHECK_EQ(0, closedir(c_dir)) << "Unable to close directory.";
}
- bool PatchoatBootImage(const std::string& output_dir, const char* isa) const {
- // This needs to be kept in sync with ART, see art/runtime/gc/space/image_space.cc.
-
- std::vector<std::string> cmd;
- cmd.push_back("/system/bin/patchoat");
-
- cmd.push_back("--input-image-location=/system/framework/boot.art");
- cmd.push_back(StringPrintf("--output-image-directory=%s", output_dir.c_str()));
-
- cmd.push_back(StringPrintf("--instruction-set=%s", isa));
-
- int32_t base_offset = ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA,
- ART_BASE_ADDRESS_MAX_DELTA);
- cmd.push_back(StringPrintf("--base-offset-delta=%d", base_offset));
-
- std::string error_msg;
- bool result = Exec(cmd, &error_msg);
- if (!result) {
- LOG(ERROR) << "Could not generate boot image: " << error_msg;
- }
- return result;
- }
-
bool Dex2oatBootImage(const std::string& boot_cp,
const std::string& art_path,
const std::string& oat_path,
@@ -460,9 +447,9 @@
}
cmd.push_back(StringPrintf("--oat-file=%s", oat_path.c_str()));
- int32_t base_offset = ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA,
- ART_BASE_ADDRESS_MAX_DELTA);
- cmd.push_back(StringPrintf("--base=0x%x", ART_BASE_ADDRESS + base_offset));
+ int32_t base_offset = ChooseRelocationOffsetDelta(art::GetImageMinBaseAddressDelta(),
+ art::GetImageMaxBaseAddressDelta());
+ cmd.push_back(StringPrintf("--base=0x%x", art::GetImageBaseAddress() + base_offset));
cmd.push_back(StringPrintf("--instruction-set=%s", isa));
@@ -604,7 +591,7 @@
// If the dexopt failed, we may have a stale boot image from a previous OTA run.
// Then regenerate and retry.
if (WEXITSTATUS(dexopt_result) ==
- static_cast<int>(art::dex2oat::ReturnCode::kCreateRuntime)) {
+ static_cast<int>(::art::dex2oat::ReturnCode::kCreateRuntime)) {
if (!PrepareBootImage(/* force */ true)) {
LOG(ERROR) << "Forced boot image creating failed. Original error return was "
<< dexopt_result;
diff --git a/cmds/installd/otapreopt_parameters.cpp b/cmds/installd/otapreopt_parameters.cpp
index cf3de01..b1ad8db 100644
--- a/cmds/installd/otapreopt_parameters.cpp
+++ b/cmds/installd/otapreopt_parameters.cpp
@@ -16,6 +16,8 @@
#include "otapreopt_parameters.h"
+#include <cstring>
+
#include <android-base/logging.h>
#include "dexopt.h"
@@ -248,6 +250,8 @@
case 8: num_args_expected = 16; break;
// Version 9 adds a new dexopt flag: DEXOPT_GENERATE_APP_IMAGE
case 9: num_args_expected = 16; break;
+ // Version 10 is a compatibility bump.
+ case 10: num_args_expected = 16; break;
default:
LOG(ERROR) << "Don't know how to read arguments for version " << version;
return false;
@@ -360,6 +364,15 @@
}
}
+ if (version < 10) {
+ // Do not accept '&' as shared libraries from versions prior to 10. These may lead
+ // to runtime crashes. The server side of version 10+ should send the correct
+ // context in almost all cases (e.g., only for actual shared packages).
+ if (shared_libraries != nullptr && std::string("&") == shared_libraries) {
+ return false;
+ }
+ }
+
return true;
}
diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp
index 7438d3d..739f33f 100644
--- a/cmds/installd/tests/Android.bp
+++ b/cmds/installd/tests/Android.bp
@@ -1,6 +1,7 @@
// Build the unit tests for installd
cc_test {
name: "installd_utils_test",
+ test_suites: ["device-tests"],
clang: true,
srcs: ["installd_utils_test.cpp"],
cflags: ["-Wall", "-Werror"],
@@ -18,6 +19,7 @@
cc_test {
name: "installd_cache_test",
+ test_suites: ["device-tests"],
clang: true,
srcs: ["installd_cache_test.cpp"],
cflags: ["-Wall", "-Werror"],
@@ -39,6 +41,7 @@
cc_test {
name: "installd_service_test",
+ test_suites: ["device-tests"],
clang: true,
srcs: ["installd_service_test.cpp"],
cflags: ["-Wall", "-Werror"],
@@ -60,6 +63,7 @@
cc_test {
name: "installd_dexopt_test",
+ test_suites: ["device-tests"],
clang: true,
srcs: ["installd_dexopt_test.cpp"],
cflags: ["-Wall", "-Werror"],
@@ -81,6 +85,7 @@
cc_test {
name: "installd_otapreopt_test",
+ test_suites: ["device-tests"],
clang: true,
srcs: ["installd_otapreopt_test.cpp"],
cflags: ["-Wall", "-Werror"],
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index 279bce8..f216c53 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -84,10 +84,16 @@
system(cmd.c_str());
}
-static void mkdir(const std::string& path, uid_t owner, gid_t group, mode_t mode) {
- ::mkdir(path.c_str(), mode);
- ::chown(path.c_str(), owner, group);
- ::chmod(path.c_str(), mode);
+static int mkdir(const std::string& path, uid_t owner, gid_t group, mode_t mode) {
+ int ret = ::mkdir(path.c_str(), mode);
+ if (ret != 0) {
+ return ret;
+ }
+ ret = ::chown(path.c_str(), owner, group);
+ if (ret != 0) {
+ return ret;
+ }
+ return ::chmod(path.c_str(), mode);
}
static int log_callback(int type, const char *fmt, ...) { // NOLINT
@@ -184,7 +190,7 @@
se_info_ = "default";
app_apk_dir_ = android_app_dir + package_name_;
- create_mock_app();
+ ASSERT_TRUE(create_mock_app());
}
virtual void TearDown() {
@@ -198,33 +204,56 @@
delete service_;
}
- void create_mock_app() {
+ ::testing::AssertionResult create_mock_app() {
// Create the oat dir.
app_oat_dir_ = app_apk_dir_ + "/oat";
- mkdir(app_apk_dir_, kSystemUid, kSystemGid, 0755);
- service_->createOatDir(app_oat_dir_, kRuntimeIsa);
+ if (mkdir(app_apk_dir_, kSystemUid, kSystemGid, 0755) != 0) {
+ return ::testing::AssertionFailure() << "Could not create app dir " << app_apk_dir_
+ << " : " << strerror(errno);
+ }
+ binder::Status status = service_->createOatDir(app_oat_dir_, kRuntimeIsa);
+ if (!status.isOk()) {
+ return ::testing::AssertionFailure() << "Could not create oat dir: "
+ << status.toString8().c_str();
+ }
// Copy the primary apk.
apk_path_ = app_apk_dir_ + "/base.jar";
- ASSERT_TRUE(WriteBase64ToFile(kDexFile, apk_path_, kSystemUid, kSystemGid, 0644));
+ std::string error_msg;
+ if (!WriteBase64ToFile(kDexFile, apk_path_, kSystemUid, kSystemGid, 0644, &error_msg)) {
+ return ::testing::AssertionFailure() << "Could not write base64 file to " << apk_path_
+ << " : " << error_msg;
+ }
// Create the app user data.
- ASSERT_TRUE(service_->createAppData(
- volume_uuid_,
- package_name_,
- kTestUserId,
- kAppDataFlags,
- kTestAppUid,
- se_info_,
- kOSdkVersion,
- &ce_data_inode_).isOk());
+ status = service_->createAppData(
+ volume_uuid_,
+ package_name_,
+ kTestUserId,
+ kAppDataFlags,
+ kTestAppUid,
+ se_info_,
+ kOSdkVersion,
+ &ce_data_inode_);
+ if (!status.isOk()) {
+ return ::testing::AssertionFailure() << "Could not create app data: "
+ << status.toString8().c_str();
+ }
// Create a secondary dex file on CE storage
const char* volume_uuid_cstr = volume_uuid_ == nullptr ? nullptr : volume_uuid_->c_str();
app_private_dir_ce_ = create_data_user_ce_package_path(
volume_uuid_cstr, kTestUserId, package_name_.c_str());
secondary_dex_ce_ = app_private_dir_ce_ + "/secondary_ce.jar";
- ASSERT_TRUE(WriteBase64ToFile(kDexFile, secondary_dex_ce_, kTestAppUid, kTestAppGid, 0600));
+ if (!WriteBase64ToFile(kDexFile,
+ secondary_dex_ce_,
+ kTestAppUid,
+ kTestAppGid,
+ 0600,
+ &error_msg)) {
+ return ::testing::AssertionFailure() << "Could not write base64 file to "
+ << secondary_dex_ce_ << " : " << error_msg;
+ }
std::string app_private_dir_ce_link = create_data_user_ce_package_path_as_user_link(
volume_uuid_cstr, kTestUserId, package_name_.c_str());
secondary_dex_ce_link_ = app_private_dir_ce_link + "/secondary_ce.jar";
@@ -233,10 +262,24 @@
app_private_dir_de_ = create_data_user_de_package_path(
volume_uuid_cstr, kTestUserId, package_name_.c_str());
secondary_dex_de_ = app_private_dir_de_ + "/secondary_de.jar";
- ASSERT_TRUE(WriteBase64ToFile(kDexFile, secondary_dex_de_, kTestAppUid, kTestAppGid, 0600));
+ if (!WriteBase64ToFile(kDexFile,
+ secondary_dex_de_,
+ kTestAppUid,
+ kTestAppGid,
+ 0600,
+ &error_msg)) {
+ return ::testing::AssertionFailure() << "Could not write base64 file to "
+ << secondary_dex_de_ << " : " << error_msg;
+ }
// Fix app data uid.
- ASSERT_TRUE(service_->fixupAppData(volume_uuid_, kTestUserId).isOk());
+ status = service_->fixupAppData(volume_uuid_, kTestUserId);
+ if (!status.isOk()) {
+ return ::testing::AssertionFailure() << "Could not fixup app data: "
+ << status.toString8().c_str();
+ }
+
+ return ::testing::AssertionSuccess();
}
diff --git a/cmds/installd/tests/installd_otapreopt_test.cpp b/cmds/installd/tests/installd_otapreopt_test.cpp
index b518507..66dd51e 100644
--- a/cmds/installd/tests/installd_otapreopt_test.cpp
+++ b/cmds/installd/tests/installd_otapreopt_test.cpp
@@ -114,11 +114,14 @@
case 7: return "7";
case 8: return "8";
case 9: return "9";
+ case 10: return "10";
}
return nullptr;
}
- std::vector<const char*> getArgs(uint32_t version, bool versioned) {
+ std::vector<const char*> getArgs(uint32_t version,
+ bool versioned,
+ const char* shared_libs = "shared.lib") {
std::vector<const char*> args;
args.push_back("otapreopt"); // "otapreopt"
args.push_back("a"); // slot
@@ -135,7 +138,7 @@
args.push_back("0"); // dexopt_flags
args.push_back("speed"); // filter
args.push_back("!"); // volume
- args.push_back("shared.lib"); // libs
+ args.push_back(shared_libs); // libs
if (version > 1) {
args.push_back("!"); // seinfo
@@ -159,9 +162,11 @@
return args;
}
- void VerifyReadArguments(uint32_t version, bool versioned) {
+ void VerifyReadArguments(uint32_t version,
+ bool versioned,
+ const char* shared_libs = "shared.lib") {
OTAPreoptParameters params;
- std::vector<const char*> args = getArgs(version, versioned);
+ std::vector<const char*> args = getArgs(version, versioned, shared_libs);
ASSERT_TRUE(params.ReadArguments(args.size() - 1, args.data()));
verifyPackageParameters(params, version, versioned, args.data());
}
@@ -199,6 +204,18 @@
VerifyReadArguments(7, true);
}
+TEST_F(OTAPreoptTest, ReadArgumentsV9SharedLibsAmpersand) {
+ OTAPreoptParameters params;
+ std::vector<const char*> args = getArgs(9, true, "&");
+ ASSERT_FALSE(params.ReadArguments(args.size() - 1, args.data()));
+}
+
+TEST_F(OTAPreoptTest, ReadArgumentsV10SharedLibsAmpersand) {
+ OTAPreoptParameters params;
+ std::vector<const char*> args = getArgs(10, true, "&");
+ ASSERT_TRUE(params.ReadArguments(args.size() - 1, args.data()));
+}
+
TEST_F(OTAPreoptTest, ReadArgumentsFailToManyArgs) {
OTAPreoptParameters params;
std::vector<const char*> args = getArgs(5, true);
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index bcdd03e..ad7a5ae 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -21,6 +21,7 @@
#include <gtest/gtest.h>
#include "InstalldNativeService.h"
+#include "MatchExtensionGen.h"
#include "globals.h"
#include "utils.h"
@@ -529,5 +530,19 @@
EXPECT_NE(0, validate_apk_path_subdirs("/data/app/com.example/dir/dir/dir//file"));
}
+TEST_F(UtilsTest, MatchExtension_Valid) {
+ EXPECT_EQ(AID_MEDIA_VIDEO, MatchExtension("mpg"));
+ EXPECT_EQ(AID_MEDIA_VIDEO, MatchExtension("mpeg"));
+ EXPECT_EQ(AID_MEDIA_VIDEO, MatchExtension("mPeG"));
+ EXPECT_EQ(AID_MEDIA_VIDEO, MatchExtension("MPEG"));
+}
+
+TEST_F(UtilsTest, MatchExtension_Invalid) {
+ EXPECT_EQ(0, MatchExtension("log"));
+ EXPECT_EQ(0, MatchExtension("3amp"));
+ EXPECT_EQ(0, MatchExtension("fpe"));
+ EXPECT_EQ(0, MatchExtension("docx"));
+}
+
} // namespace installd
} // namespace android
diff --git a/cmds/installd/tests/test_utils.h b/cmds/installd/tests/test_utils.h
index b8785c6..a7ef674 100644
--- a/cmds/installd/tests/test_utils.h
+++ b/cmds/installd/tests/test_utils.h
@@ -3,6 +3,7 @@
#include <sys/capability.h>
#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
#include <selinux/android.h>
uint8_t kBase64Map[256] = {
@@ -74,7 +75,7 @@
}
bool WriteBase64ToFile(const char* base64, const std::string& file,
- uid_t uid, gid_t gid, int mode) {
+ uid_t uid, gid_t gid, int mode, std::string* error_msg) {
CHECK(base64 != nullptr);
size_t length;
std::unique_ptr<uint8_t[]> bytes(DecodeBase64(base64, &length));
@@ -83,8 +84,10 @@
int fd = open(file.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+ using android::base::StringPrintf;
+
if (fd < 0) {
- PLOG(ERROR) << "Could not open file " << file;
+ *error_msg = StringPrintf("Could not open file %s: %s", file.c_str(), strerror(errno));
return false;
}
@@ -92,18 +95,18 @@
while (wrote < length) {
ssize_t cur = write(fd, bytes.get() + wrote, length - wrote);
if (cur == -1) {
- PLOG(ERROR) << "Could not write file " << file;
+ *error_msg = StringPrintf("Could not write file %s: %s", file.c_str(), strerror(errno));
return false;
}
wrote += cur;
}
if (::chown(file.c_str(), uid, gid) != 0) {
- PLOG(ERROR) << "Could not chown file " << file;
+ *error_msg = StringPrintf("Could not chown file %s: %s", file.c_str(), strerror(errno));
return false;
}
if (::chmod(file.c_str(), mode) != 0) {
- PLOG(ERROR) << "Could not chmod file " << file;
+ *error_msg = StringPrintf("Could not chmod file %s: %s", file.c_str(), strerror(errno));
return false;
}
return true;
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 1ff45e4..8672206 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -974,7 +974,7 @@
if (chmod(p->fts_path, target_mode) != 0) {
PLOG(WARNING) << "Failed to chmod " << p->fts_path;
}
- // Intentional fall through to also set GID
+ [[fallthrough]]; // to also set GID
case FTS_F:
if (chown(p->fts_path, -1, gid) != 0) {
PLOG(WARNING) << "Failed to chown " << p->fts_path;
diff --git a/cmds/lshal/DebugCommand.cpp b/cmds/lshal/DebugCommand.cpp
index dd8812d..0952db6 100644
--- a/cmds/lshal/DebugCommand.cpp
+++ b/cmds/lshal/DebugCommand.cpp
@@ -59,8 +59,8 @@
auto pair = splitFirst(mInterfaceName, '/');
- FQName fqName(pair.first);
- if (!fqName.isValid() || fqName.isIdentifier() || !fqName.isFullyQualified()) {
+ FQName fqName;
+ if (!FQName::parse(pair.first, &fqName) || fqName.isIdentifier() || !fqName.isFullyQualified()) {
mLshal.err() << "Invalid fully-qualified name '" << pair.first << "'\n\n";
return USAGE;
}
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index ff22048..a6d7a78 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -18,14 +18,17 @@
#include <getopt.h>
+#include <algorithm>
#include <fstream>
+#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
-#include <sstream>
#include <regex>
+#include <sstream>
#include <android-base/file.h>
+#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
#include <hidl-hash/Hash.h>
@@ -54,6 +57,19 @@
return (p == Partition::SYSTEM) ? vintf::SchemaType::FRAMEWORK : vintf::SchemaType::DEVICE;
}
+Partition toPartition(vintf::SchemaType t) {
+ switch (t) {
+ case vintf::SchemaType::FRAMEWORK: return Partition::SYSTEM;
+ // TODO(b/71555570): Device manifest does not distinguish HALs from vendor or ODM.
+ case vintf::SchemaType::DEVICE: return Partition::VENDOR;
+ }
+ return Partition::UNKNOWN;
+}
+
+std::string getPackageAndVersion(const std::string& fqInstance) {
+ return splitFirst(fqInstance, ':').first;
+}
+
NullableOStream<std::ostream> ListCommand::out() const {
return mLshal.out();
}
@@ -74,6 +90,8 @@
}
const std::string &ListCommand::getCmdline(pid_t pid) {
+ static const std::string kEmptyString{};
+ if (pid == NO_PID) return kEmptyString;
auto pair = mCmdlines.find(pid);
if (pair != mCmdlines.end()) {
return pair->second;
@@ -90,6 +108,7 @@
}
Partition ListCommand::getPartition(pid_t pid) {
+ if (pid == NO_PID) return Partition::UNKNOWN;
auto it = mPartitions.find(pid);
if (it != mPartitions.end()) {
return it->second;
@@ -101,21 +120,19 @@
// Give sensible defaults when nothing can be inferred from runtime.
// process: Partition inferred from executable location or cmdline.
-Partition ListCommand::resolvePartition(Partition process, const FQName& fqName) const {
- if (fqName.inPackage("vendor") ||
- fqName.inPackage("com")) {
+Partition ListCommand::resolvePartition(Partition process, const FqInstance& fqInstance) const {
+ if (fqInstance.inPackage("vendor") || fqInstance.inPackage("com")) {
return Partition::VENDOR;
}
- if (fqName.inPackage("android.frameworks") ||
- fqName.inPackage("android.system") ||
- fqName.inPackage("android.hidl")) {
+ if (fqInstance.inPackage("android.frameworks") || fqInstance.inPackage("android.system") ||
+ fqInstance.inPackage("android.hidl")) {
return Partition::SYSTEM;
}
// Some android.hardware HALs are served from system. Check the value from executable
// location / cmdline first.
- if (fqName.inPackage("android.hardware")) {
+ if (fqInstance.inPackage("android.hardware")) {
if (process != Partition::UNKNOWN) {
return process;
}
@@ -125,6 +142,67 @@
return process;
}
+bool match(const vintf::ManifestInstance& instance, const FqInstance& fqInstance,
+ vintf::TransportArch ta) {
+ // For hwbinder libs, allow missing arch in manifest.
+ // For passthrough libs, allow missing interface/instance in table.
+ return (ta.transport == instance.transport()) &&
+ (ta.transport == vintf::Transport::HWBINDER ||
+ vintf::contains(instance.arch(), ta.arch)) &&
+ (!fqInstance.hasInterface() || fqInstance.getInterface() == instance.interface()) &&
+ (!fqInstance.hasInstance() || fqInstance.getInstance() == instance.instance());
+}
+
+bool match(const vintf::MatrixInstance& instance, const FqInstance& fqInstance,
+ vintf::TransportArch /* ta */) {
+ return (!fqInstance.hasInterface() || fqInstance.getInterface() == instance.interface()) &&
+ (!fqInstance.hasInstance() || instance.matchInstance(fqInstance.getInstance()));
+}
+
+template <typename ObjectType>
+VintfInfo getVintfInfo(const std::shared_ptr<const ObjectType>& object,
+ const FqInstance& fqInstance, vintf::TransportArch ta, VintfInfo value) {
+ bool found = false;
+ (void)object->forEachInstanceOfVersion(fqInstance.getPackage(), fqInstance.getVersion(),
+ [&](const auto& instance) {
+ found = match(instance, fqInstance, ta);
+ return !found; // continue if not found
+ });
+ return found ? value : VINTF_INFO_EMPTY;
+}
+
+std::shared_ptr<const vintf::HalManifest> ListCommand::getDeviceManifest() const {
+ return vintf::VintfObject::GetDeviceHalManifest();
+}
+
+std::shared_ptr<const vintf::CompatibilityMatrix> ListCommand::getDeviceMatrix() const {
+ return vintf::VintfObject::GetDeviceCompatibilityMatrix();
+}
+
+std::shared_ptr<const vintf::HalManifest> ListCommand::getFrameworkManifest() const {
+ return vintf::VintfObject::GetFrameworkHalManifest();
+}
+
+std::shared_ptr<const vintf::CompatibilityMatrix> ListCommand::getFrameworkMatrix() const {
+ return vintf::VintfObject::GetFrameworkCompatibilityMatrix();
+}
+
+VintfInfo ListCommand::getVintfInfo(const std::string& fqInstanceName,
+ vintf::TransportArch ta) const {
+ FqInstance fqInstance;
+ if (!fqInstance.setTo(fqInstanceName) &&
+ // Ignore interface / instance for passthrough libs
+ !fqInstance.setTo(getPackageAndVersion(fqInstanceName))) {
+ err() << "Warning: Cannot parse '" << fqInstanceName << "'; no VINTF info." << std::endl;
+ return VINTF_INFO_EMPTY;
+ }
+
+ return lshal::getVintfInfo(getDeviceManifest(), fqInstance, ta, DEVICE_MANIFEST) |
+ lshal::getVintfInfo(getFrameworkManifest(), fqInstance, ta, FRAMEWORK_MANIFEST) |
+ lshal::getVintfInfo(getDeviceMatrix(), fqInstance, ta, DEVICE_MATRIX) |
+ lshal::getVintfInfo(getFrameworkMatrix(), fqInstance, ta, FRAMEWORK_MATRIX);
+}
+
static bool scanBinderContext(pid_t pid,
const std::string &contextName,
std::function<void(const std::string&)> eachLine) {
@@ -221,16 +299,40 @@
return &pair.first->second;
}
-// Must process hwbinder services first, then passthrough services.
+bool ListCommand::shouldFetchHalType(const HalType &type) const {
+ return (std::find(mFetchTypes.begin(), mFetchTypes.end(), type) != mFetchTypes.end());
+}
+
+Table* ListCommand::tableForType(HalType type) {
+ switch (type) {
+ case HalType::BINDERIZED_SERVICES:
+ return &mServicesTable;
+ case HalType::PASSTHROUGH_CLIENTS:
+ return &mPassthroughRefTable;
+ case HalType::PASSTHROUGH_LIBRARIES:
+ return &mImplementationsTable;
+ case HalType::VINTF_MANIFEST:
+ return &mManifestHalsTable;
+ case HalType::LAZY_HALS:
+ return &mLazyHalsTable;
+ default:
+ LOG(FATAL) << "Unknown HAL type " << static_cast<int64_t>(type);
+ return nullptr;
+ }
+}
+const Table* ListCommand::tableForType(HalType type) const {
+ return const_cast<ListCommand*>(this)->tableForType(type);
+}
+
void ListCommand::forEachTable(const std::function<void(Table &)> &f) {
- f(mServicesTable);
- f(mPassthroughRefTable);
- f(mImplementationsTable);
+ for (const auto& type : mListTypes) {
+ f(*tableForType(type));
+ }
}
void ListCommand::forEachTable(const std::function<void(const Table &)> &f) const {
- f(mServicesTable);
- f(mPassthroughRefTable);
- f(mImplementationsTable);
+ for (const auto& type : mListTypes) {
+ f(*tableForType(type));
+ }
}
void ListCommand::postprocess() {
@@ -246,22 +348,25 @@
}
}
for (TableEntry& entry : table) {
- entry.partition = getPartition(entry.serverPid);
+ if (entry.partition == Partition::UNKNOWN) {
+ entry.partition = getPartition(entry.serverPid);
+ }
+ entry.vintfInfo = getVintfInfo(entry.interfaceName, {entry.transport, entry.arch});
}
});
// use a double for loop here because lshal doesn't care about efficiency.
for (TableEntry &packageEntry : mImplementationsTable) {
std::string packageName = packageEntry.interfaceName;
- FQName fqPackageName{packageName.substr(0, packageName.find("::"))};
- if (!fqPackageName.isValid()) {
+ FQName fqPackageName;
+ if (!FQName::parse(packageName.substr(0, packageName.find("::")), &fqPackageName)) {
continue;
}
for (TableEntry &interfaceEntry : mPassthroughRefTable) {
- if (interfaceEntry.arch != ARCH_UNKNOWN) {
+ if (interfaceEntry.arch != vintf::Arch::ARCH_EMPTY) {
continue;
}
- FQName interfaceName{splitFirst(interfaceEntry.interfaceName, '/').first};
- if (!interfaceName.isValid()) {
+ FQName interfaceName;
+ if (!FQName::parse(splitFirst(interfaceEntry.interfaceName, '/').first, &interfaceName)) {
continue;
}
if (interfaceName.getPackageAndVersion() == fqPackageName) {
@@ -282,158 +387,156 @@
mImplementationsTable.setDescription(
"All available passthrough implementations (all -impl.so files).\n"
"These may return subclasses through their respective HIDL_FETCH_I* functions.");
+ mManifestHalsTable.setDescription(
+ "All HALs that are in VINTF manifest.");
+ mLazyHalsTable.setDescription(
+ "All HALs that are declared in VINTF manifest:\n"
+ " - as hwbinder HALs but are not registered to hwservicemanager, and\n"
+ " - as hwbinder/passthrough HALs with no implementation.");
}
-static inline bool findAndBumpVersion(vintf::ManifestHal* hal, const vintf::Version& version) {
- for (vintf::Version& v : hal->versions) {
- if (v.majorVer == version.majorVer) {
- v.minorVer = std::max(v.minorVer, version.minorVer);
- return true;
- }
+bool ListCommand::addEntryWithInstance(const TableEntry& entry,
+ vintf::HalManifest* manifest) const {
+ FqInstance fqInstance;
+ if (!fqInstance.setTo(entry.interfaceName)) {
+ err() << "Warning: '" << entry.interfaceName << "' is not a valid FqInstance." << std::endl;
+ return false;
}
- return false;
+
+ if (fqInstance.getPackage() == gIBaseFqName.package()) {
+ return true; // always remove IBase from manifest
+ }
+
+ Partition partition = resolvePartition(entry.partition, fqInstance);
+
+ if (partition == Partition::UNKNOWN) {
+ err() << "Warning: Cannot guess the partition of FqInstance " << fqInstance.string()
+ << std::endl;
+ return false;
+ }
+
+ if (partition != mVintfPartition) {
+ return true; // strip out instances that is in a different partition.
+ }
+
+ vintf::Arch arch;
+ if (entry.transport == vintf::Transport::HWBINDER) {
+ arch = vintf::Arch::ARCH_EMPTY; // no need to specify arch in manifest
+ } else if (entry.transport == vintf::Transport::PASSTHROUGH) {
+ if (entry.arch == vintf::Arch::ARCH_EMPTY) {
+ err() << "Warning: '" << entry.interfaceName << "' doesn't have bitness info.";
+ return false;
+ }
+ arch = entry.arch;
+ } else {
+ err() << "Warning: '" << entry.transport << "' is not a valid transport." << std::endl;
+ return false;
+ }
+
+ std::string e;
+ if (!manifest->insertInstance(fqInstance, entry.transport, arch, vintf::HalFormat::HIDL, &e)) {
+ err() << "Warning: Cannot insert '" << fqInstance.string() << ": " << e << std::endl;
+ return false;
+ }
+ return true;
+}
+
+bool ListCommand::addEntryWithoutInstance(const TableEntry& entry,
+ const vintf::HalManifest* manifest) const {
+ const auto& packageAndVersion = splitFirst(getPackageAndVersion(entry.interfaceName), '@');
+ const auto& package = packageAndVersion.first;
+ vintf::Version version;
+ if (!vintf::parse(packageAndVersion.second, &version)) {
+ err() << "Warning: Cannot parse version '" << packageAndVersion.second << "' for entry '"
+ << entry.interfaceName << "'" << std::endl;
+ return false;
+ }
+
+ bool found = false;
+ (void)manifest->forEachInstanceOfVersion(package, version, [&found](const auto&) {
+ found = true;
+ return false; // break
+ });
+ return found;
}
void ListCommand::dumpVintf(const NullableOStream<std::ostream>& out) const {
using vintf::operator|=;
using vintf::operator<<;
+ using namespace std::placeholders;
vintf::HalManifest manifest;
manifest.setType(toSchemaType(mVintfPartition));
- forEachTable([this, &manifest] (const Table &table) {
- for (const TableEntry &entry : table) {
- std::string fqInstanceName = entry.interfaceName;
+ std::vector<std::string> error;
+ for (const TableEntry& entry : mServicesTable)
+ if (!addEntryWithInstance(entry, &manifest)) error.push_back(entry.interfaceName);
+ for (const TableEntry& entry : mPassthroughRefTable)
+ if (!addEntryWithInstance(entry, &manifest)) error.push_back(entry.interfaceName);
+ for (const TableEntry& entry : mManifestHalsTable)
+ if (!addEntryWithInstance(entry, &manifest)) error.push_back(entry.interfaceName);
- if (&table == &mImplementationsTable) {
- // Quick hack to work around *'s
- replaceAll(&fqInstanceName, '*', 'D');
- }
- auto splittedFqInstanceName = splitFirst(fqInstanceName, '/');
- FQName fqName(splittedFqInstanceName.first);
- if (!fqName.isValid()) {
- err() << "Warning: '" << splittedFqInstanceName.first
- << "' is not a valid FQName." << std::endl;
- continue;
- }
+ std::vector<std::string> passthrough;
+ for (const TableEntry& entry : mImplementationsTable)
+ if (!addEntryWithoutInstance(entry, &manifest)) passthrough.push_back(entry.interfaceName);
- if (fqName.package() == gIBaseFqName.package()) {
- continue; // always remove IBase from manifest
- }
-
- Partition partition = resolvePartition(entry.partition, fqName);
-
- if (partition == Partition::UNKNOWN) {
- err() << "Warning: Cannot guess the partition of instance " << fqInstanceName
- << ". It is removed from the generated manifest." << std::endl;
- continue;
- }
-
- if (partition != mVintfPartition) {
- continue; // strip out instances that is in a different partition.
- }
-
- std::string interfaceName =
- &table == &mImplementationsTable ? "" : fqName.name();
- std::string instanceName =
- &table == &mImplementationsTable ? "" : splittedFqInstanceName.second;
-
- vintf::Version version{fqName.getPackageMajorVersion(),
- fqName.getPackageMinorVersion()};
- vintf::Transport transport;
- vintf::Arch arch;
- if (entry.transport == "hwbinder") {
- transport = vintf::Transport::HWBINDER;
- arch = vintf::Arch::ARCH_EMPTY;
- } else if (entry.transport == "passthrough") {
- transport = vintf::Transport::PASSTHROUGH;
- switch (entry.arch) {
- case lshal::ARCH32:
- arch = vintf::Arch::ARCH_32; break;
- case lshal::ARCH64:
- arch = vintf::Arch::ARCH_64; break;
- case lshal::ARCH_BOTH:
- arch = vintf::Arch::ARCH_32_64; break;
- case lshal::ARCH_UNKNOWN: // fallthrough
- default:
- err() << "Warning: '" << fqName.package()
- << "' doesn't have bitness info, assuming 32+64." << std::endl;
- arch = vintf::Arch::ARCH_32_64;
- }
- } else {
- err() << "Warning: '" << entry.transport << "' is not a valid transport." << std::endl;
- continue;
- }
-
- bool done = false;
- for (vintf::ManifestHal *hal : manifest.getHals(fqName.package())) {
- if (hal->transport() != transport) {
- if (transport != vintf::Transport::PASSTHROUGH) {
- err() << "Fatal: should not reach here. Generated result may be wrong for '"
- << hal->name << "'."
- << std::endl;
- }
- done = true;
- break;
- }
- if (findAndBumpVersion(hal, version)) {
- if (&table != &mImplementationsTable) {
- hal->insertLegacyInstance(interfaceName, instanceName);
- }
- hal->transportArch.arch |= arch;
- done = true;
- break;
- }
- }
- if (done) {
- continue; // to next TableEntry
- }
- vintf::ManifestHal manifestHal{
- vintf::HalFormat::HIDL,
- std::string{fqName.package()},
- {version},
- {transport, arch},
- {}};
- if (&table != &mImplementationsTable) {
- manifestHal.insertLegacyInstance(interfaceName, instanceName);
- }
- if (!manifest.add(std::move(manifestHal))) {
- err() << "Warning: cannot add hal '" << fqInstanceName << "'" << std::endl;
- }
- }
- });
out << "<!-- " << std::endl
- << " This is a skeleton " << manifest.type() << " manifest. Notes: " << std::endl
- << INIT_VINTF_NOTES
- << "-->" << std::endl;
- out << vintf::gHalManifestConverter(manifest, vintf::SerializeFlag::HALS_NO_FQNAME);
+ << " This is a skeleton " << manifest.type() << " manifest. Notes: " << std::endl
+ << INIT_VINTF_NOTES;
+ if (!error.empty()) {
+ out << std::endl << " The following HALs are not added; see warnings." << std::endl;
+ for (const auto& e : error) {
+ out << " " << e << std::endl;
+ }
+ }
+ if (!passthrough.empty()) {
+ out << std::endl
+ << " The following HALs are passthrough and no interface or instance " << std::endl
+ << " names can be inferred." << std::endl;
+ for (const auto& e : passthrough) {
+ out << " " << e << std::endl;
+ }
+ }
+ out << "-->" << std::endl;
+ out << vintf::gHalManifestConverter(manifest, vintf::SerializeFlags::HALS_ONLY);
}
std::string ListCommand::INIT_VINTF_NOTES{
- " 1. If a HAL is supported in both hwbinder and passthrough transport, \n"
+ " 1. If a HAL is supported in both hwbinder and passthrough transport,\n"
" only hwbinder is shown.\n"
" 2. It is likely that HALs in passthrough transport does not have\n"
" <interface> declared; users will have to write them by hand.\n"
" 3. A HAL with lower minor version can be overridden by a HAL with\n"
" higher minor version if they have the same name and major version.\n"
+ " 4. This output is intended for launch devices.\n"
+ " Upgrading devices should not use this tool to generate device\n"
+ " manifest and replace the existing manifest directly, but should\n"
+ " edit the existing manifest manually.\n"
+ " Specifically, devices which launched at Android O-MR1 or earlier\n"
+ " should not use the 'fqname' format for required HAL entries and\n"
+ " should instead use the legacy package, name, instance-name format\n"
+ " until they are updated.\n"
};
-static Architecture fromBaseArchitecture(::android::hidl::base::V1_0::DebugInfo::Architecture a) {
+static vintf::Arch fromBaseArchitecture(::android::hidl::base::V1_0::DebugInfo::Architecture a) {
switch (a) {
case ::android::hidl::base::V1_0::DebugInfo::Architecture::IS_64BIT:
- return ARCH64;
+ return vintf::Arch::ARCH_64;
case ::android::hidl::base::V1_0::DebugInfo::Architecture::IS_32BIT:
- return ARCH32;
+ return vintf::Arch::ARCH_32;
case ::android::hidl::base::V1_0::DebugInfo::Architecture::UNKNOWN: // fallthrough
default:
- return ARCH_UNKNOWN;
+ return vintf::Arch::ARCH_EMPTY;
}
}
void ListCommand::dumpTable(const NullableOStream<std::ostream>& out) const {
if (mNeat) {
- MergedTable({&mServicesTable, &mPassthroughRefTable, &mImplementationsTable})
- .createTextTable().dump(out.buf());
+ std::vector<const Table*> tables;
+ forEachTable([&tables](const Table &table) {
+ tables.push_back(&table);
+ });
+ MergedTable(std::move(tables)).createTextTable().dump(out.buf());
return;
}
@@ -481,24 +584,13 @@
return OK;
}
-void ListCommand::putEntry(TableEntrySource source, TableEntry &&entry) {
- Table *table = nullptr;
- switch (source) {
- case HWSERVICEMANAGER_LIST :
- table = &mServicesTable; break;
- case PTSERVICEMANAGER_REG_CLIENT :
- table = &mPassthroughRefTable; break;
- case LIST_DLLIB :
- table = &mImplementationsTable; break;
- default:
- err() << "Error: Unknown source of entry " << source << std::endl;
- }
- if (table) {
- table->add(std::forward<TableEntry>(entry));
- }
+void ListCommand::putEntry(HalType type, TableEntry &&entry) {
+ tableForType(type)->add(std::forward<TableEntry>(entry));
}
Status ListCommand::fetchAllLibraries(const sp<IServiceManager> &manager) {
+ if (!shouldFetchHalType(HalType::PASSTHROUGH_LIBRARIES)) { return OK; }
+
using namespace ::android::hardware;
using namespace ::android::hidl::manager::V1_0;
using namespace ::android::hidl::base::V1_0;
@@ -510,12 +602,12 @@
std::string{info.instanceName.c_str()};
entries.emplace(interfaceName, TableEntry{
.interfaceName = interfaceName,
- .transport = "passthrough",
+ .transport = vintf::Transport::PASSTHROUGH,
.clientPids = info.clientPids,
}).first->second.arch |= fromBaseArchitecture(info.arch);
}
for (auto &&pair : entries) {
- putEntry(LIST_DLLIB, std::move(pair.second));
+ putEntry(HalType::PASSTHROUGH_LIBRARIES, std::move(pair.second));
}
});
if (!ret.isOk()) {
@@ -527,6 +619,8 @@
}
Status ListCommand::fetchPassthrough(const sp<IServiceManager> &manager) {
+ if (!shouldFetchHalType(HalType::PASSTHROUGH_CLIENTS)) { return OK; }
+
using namespace ::android::hardware;
using namespace ::android::hardware::details;
using namespace ::android::hidl::manager::V1_0;
@@ -536,11 +630,11 @@
if (info.clientPids.size() <= 0) {
continue;
}
- putEntry(PTSERVICEMANAGER_REG_CLIENT, {
+ putEntry(HalType::PASSTHROUGH_CLIENTS, {
.interfaceName =
std::string{info.interfaceName.c_str()} + "/" +
std::string{info.instanceName.c_str()},
- .transport = "passthrough",
+ .transport = vintf::Transport::PASSTHROUGH,
.serverPid = info.clientPids.size() == 1 ? info.clientPids[0] : NO_PID,
.clientPids = info.clientPids,
.arch = fromBaseArchitecture(info.arch)
@@ -556,8 +650,11 @@
}
Status ListCommand::fetchBinderized(const sp<IServiceManager> &manager) {
- const std::string mode = "hwbinder";
+ using vintf::operator<<;
+ if (!shouldFetchHalType(HalType::BINDERIZED_SERVICES)) { return OK; }
+
+ const vintf::Transport mode = vintf::Transport::HWBINDER;
hidl_vec<hidl_string> fqInstanceNames;
// copying out for timeoutIPC
auto listRet = timeoutIPC(manager, &IServiceManager::list, [&] (const auto &names) {
@@ -576,12 +673,13 @@
TableEntry& entry = allTableEntries[fqInstanceName];
entry.interfaceName = fqInstanceName;
entry.transport = mode;
+ entry.serviceStatus = ServiceStatus::NON_RESPONSIVE;
status |= fetchBinderizedEntry(manager, &entry);
}
for (auto& pair : allTableEntries) {
- putEntry(HWSERVICEMANAGER_LIST, std::move(pair.second));
+ putEntry(HalType::BINDERIZED_SERVICES, std::move(pair.second));
}
return status;
}
@@ -681,9 +779,100 @@
handleError(TRANSACTION_ERROR, "getHashChain failed: " + hashRet.description());
}
} while (0);
+ if (status == OK) {
+ entry->serviceStatus = ServiceStatus::ALIVE;
+ }
return status;
}
+Status ListCommand::fetchManifestHals() {
+ if (!shouldFetchHalType(HalType::VINTF_MANIFEST)) { return OK; }
+ Status status = OK;
+
+ for (auto manifest : {getDeviceManifest(), getFrameworkManifest()}) {
+ if (manifest == nullptr) {
+ status |= VINTF_ERROR;
+ continue;
+ }
+
+ std::map<std::string, TableEntry> entries;
+
+ manifest->forEachInstance([&] (const vintf::ManifestInstance& manifestInstance) {
+ TableEntry entry{
+ .interfaceName = manifestInstance.getFqInstance().string(),
+ .transport = manifestInstance.transport(),
+ .arch = manifestInstance.arch(),
+ // TODO(b/71555570): Device manifest does not distinguish HALs from vendor or ODM.
+ .partition = toPartition(manifest->type()),
+ .serviceStatus = ServiceStatus::DECLARED};
+ std::string key = entry.interfaceName;
+ entries.emplace(std::move(key), std::move(entry));
+ return true;
+ });
+
+ for (auto&& pair : entries)
+ mManifestHalsTable.add(std::move(pair.second));
+ }
+ return status;
+}
+
+Status ListCommand::fetchLazyHals() {
+ using vintf::operator<<;
+
+ if (!shouldFetchHalType(HalType::LAZY_HALS)) { return OK; }
+ Status status = OK;
+
+ for (const TableEntry& manifestEntry : mManifestHalsTable) {
+ if (manifestEntry.transport == vintf::Transport::HWBINDER) {
+ if (!hasHwbinderEntry(manifestEntry)) {
+ mLazyHalsTable.add(TableEntry(manifestEntry));
+ }
+ continue;
+ }
+ if (manifestEntry.transport == vintf::Transport::PASSTHROUGH) {
+ if (!hasPassthroughEntry(manifestEntry)) {
+ mLazyHalsTable.add(TableEntry(manifestEntry));
+ }
+ continue;
+ }
+ err() << "Warning: unrecognized transport in VINTF manifest: "
+ << manifestEntry.transport;
+ status |= VINTF_ERROR;
+ }
+ return status;
+}
+
+bool ListCommand::hasHwbinderEntry(const TableEntry& entry) const {
+ for (const TableEntry& existing : mServicesTable) {
+ if (existing.interfaceName == entry.interfaceName) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool ListCommand::hasPassthroughEntry(const TableEntry& entry) const {
+ FqInstance entryFqInstance;
+ if (!entryFqInstance.setTo(entry.interfaceName)) {
+ return false; // cannot parse, so add it anyway.
+ }
+ for (const TableEntry& existing : mImplementationsTable) {
+ FqInstance existingFqInstance;
+ if (!existingFqInstance.setTo(getPackageAndVersion(existing.interfaceName))) {
+ continue;
+ }
+
+ // For example, manifest may say graphics.mapper@2.1 but passthroughServiceManager
+ // can only list graphics.mapper@2.0.
+ if (entryFqInstance.getPackage() == existingFqInstance.getPackage() &&
+ vintf::Version{entryFqInstance.getVersion()}
+ .minorAtLeast(vintf::Version{existingFqInstance.getVersion()})) {
+ return true;
+ }
+ }
+ return false;
+}
+
Status ListCommand::fetch() {
Status status = OK;
auto bManager = mLshal.serviceManager();
@@ -703,9 +892,27 @@
} else {
status |= fetchAllLibraries(pManager);
}
+ status |= fetchManifestHals();
+ status |= fetchLazyHals();
return status;
}
+void ListCommand::initFetchTypes() {
+ // TODO: refactor to do polymorphism on each table (so that dependency graph is not hardcoded).
+ static const std::map<HalType, std::set<HalType>> kDependencyGraph{
+ {HalType::LAZY_HALS, {HalType::BINDERIZED_SERVICES,
+ HalType::PASSTHROUGH_LIBRARIES,
+ HalType::VINTF_MANIFEST}},
+ };
+ mFetchTypes.insert(mListTypes.begin(), mListTypes.end());
+ for (HalType listType : mListTypes) {
+ auto it = kDependencyGraph.find(listType);
+ if (it != kDependencyGraph.end()) {
+ mFetchTypes.insert(it->second.begin(), it->second.end());
+ }
+ }
+}
+
void ListCommand::registerAllOptions() {
int v = mOptions.size();
// A list of acceptable command line options
@@ -721,7 +928,7 @@
mOptions.push_back({'l', "released", no_argument, v++, [](ListCommand* thiz, const char*) {
thiz->mSelectedColumns.push_back(TableColumnType::RELEASED);
return OK;
- }, "print the 'is released?' column\n(Y=released, empty=unreleased or unknown)"});
+ }, "print the 'is released?' column\n(Y=released, N=unreleased, ?=unknown)"});
mOptions.push_back({'t', "transport", no_argument, v++, [](ListCommand* thiz, const char*) {
thiz->mSelectedColumns.push_back(TableColumnType::TRANSPORT);
return OK;
@@ -761,6 +968,23 @@
}, "Emit debug info from\nIBase::debug with empty options. Cannot be used with --neat.\n"
"Writes to specified file if 'arg' is provided, otherwise stdout."});
+ mOptions.push_back({'V', "vintf", no_argument, v++, [](ListCommand* thiz, const char*) {
+ thiz->mSelectedColumns.push_back(TableColumnType::VINTF);
+ return OK;
+ }, "print VINTF info. This column contains a comma-separated list of:\n"
+ " - DM: device manifest\n"
+ " - DC: device compatibility matrix\n"
+ " - FM: framework manifest\n"
+ " - FC: framework compatibility matrix"});
+ mOptions.push_back({'S', "service-status", no_argument, v++, [](ListCommand* thiz, const char*) {
+ thiz->mSelectedColumns.push_back(TableColumnType::SERVICE_STATUS);
+ return OK;
+ }, "print service status column. Possible values are:\n"
+ " - alive: alive and running hwbinder service;\n"
+ " - registered;dead: registered to hwservicemanager but is not responsive;\n"
+ " - declared: only declared in VINTF manifest but is not registered to hwservicemanager;\n"
+ " - N/A: no information for passthrough HALs."});
+
// long options without short alternatives
mOptions.push_back({'\0', "init-vintf", no_argument, v++, [](ListCommand* thiz, const char* arg) {
thiz->mVintf = true;
@@ -791,6 +1015,46 @@
thiz->mNeat = true;
return OK;
}, "output is machine parsable (no explanatory text).\nCannot be used with --debug."});
+ mOptions.push_back({'\0', "types", required_argument, v++, [](ListCommand* thiz, const char* arg) {
+ if (!arg) { return USAGE; }
+
+ static const std::map<std::string, HalType> kHalTypeMap {
+ {"binderized", HalType::BINDERIZED_SERVICES},
+ {"b", HalType::BINDERIZED_SERVICES},
+ {"passthrough_clients", HalType::PASSTHROUGH_CLIENTS},
+ {"c", HalType::PASSTHROUGH_CLIENTS},
+ {"passthrough_libs", HalType::PASSTHROUGH_LIBRARIES},
+ {"l", HalType::PASSTHROUGH_LIBRARIES},
+ {"vintf", HalType::VINTF_MANIFEST},
+ {"v", HalType::VINTF_MANIFEST},
+ {"lazy", HalType::LAZY_HALS},
+ {"z", HalType::LAZY_HALS},
+ };
+
+ std::vector<std::string> halTypesArgs = split(std::string(arg), ',');
+ for (const auto& halTypeArg : halTypesArgs) {
+ if (halTypeArg.empty()) continue;
+
+ const auto& halTypeIter = kHalTypeMap.find(halTypeArg);
+ if (halTypeIter == kHalTypeMap.end()) {
+
+ thiz->err() << "Unrecognized HAL type: " << halTypeArg << std::endl;
+ return USAGE;
+ }
+
+ // Append unique (non-repeated) HAL types to the reporting list
+ HalType halType = halTypeIter->second;
+ if (std::find(thiz->mListTypes.begin(), thiz->mListTypes.end(), halType) ==
+ thiz->mListTypes.end()) {
+ thiz->mListTypes.push_back(halType);
+ }
+ }
+
+ if (thiz->mListTypes.empty()) { return USAGE; }
+ return OK;
+ }, "comma-separated list of one or more sections.\nThe output is restricted to the selected "
+ "section(s). Valid options\nare: (b|binderized), (c|passthrough_clients), (l|"
+ "passthrough_libs), and (v|vintf).\nDefault is `bcl`."});
}
// Create 'longopts' argument to getopt_long. Caller is responsible for maintaining
@@ -809,9 +1073,9 @@
i++;
}
// getopt_long last option has all zeros
- ret[i].name = NULL;
+ ret[i].name = nullptr;
ret[i].has_arg = 0;
- ret[i].flag = NULL;
+ ret[i].flag = nullptr;
ret[i].val = 0;
return ret;
@@ -829,6 +1093,7 @@
}
Status ListCommand::parseArgs(const Arg &arg) {
+ mListTypes.clear();
if (mOptions.empty()) {
registerAllOptions();
@@ -901,6 +1166,13 @@
}
}
+ // By default, list all HAL types
+ if (mListTypes.empty()) {
+ mListTypes = {HalType::BINDERIZED_SERVICES, HalType::PASSTHROUGH_CLIENTS,
+ HalType::PASSTHROUGH_LIBRARIES};
+ }
+ initFetchTypes();
+
forEachTable([this] (Table& table) {
table.setSelectedColumns(this->mSelectedColumns);
});
@@ -919,22 +1191,6 @@
return status;
}
-static std::vector<std::string> splitString(const std::string &s, char c) {
- std::vector<std::string> components;
-
- size_t startPos = 0;
- size_t matchPos;
- while ((matchPos = s.find(c, startPos)) != std::string::npos) {
- components.push_back(s.substr(startPos, matchPos - startPos));
- startPos = matchPos + 1;
- }
-
- if (startPos <= s.length()) {
- components.push_back(s.substr(startPos));
- }
- return components;
-}
-
const std::string& ListCommand::RegisteredOption::getHelpMessageForArgument() const {
static const std::string empty{};
static const std::string optional{"[=<arg>]"};
@@ -954,7 +1210,7 @@
err() << "list:" << std::endl
<< " lshal" << std::endl
<< " lshal list" << std::endl
- << " List all hals with default ordering and columns (`lshal list -riepc`)" << std::endl
+ << " List all hals with default ordering and columns (`lshal list -liepc`)" << std::endl
<< " lshal list [-h|--help]" << std::endl
<< " -h, --help: Print help message for list (`lshal help list`)" << std::endl
<< " lshal [list] [OPTIONS...]" << std::endl;
@@ -970,7 +1226,7 @@
if (!e.longOption.empty())
err() << "--" << e.longOption << e.getHelpMessageForArgument();
err() << ": ";
- std::vector<std::string> lines = splitString(e.help, '\n');
+ std::vector<std::string> lines = split(e.help, '\n');
for (const auto& line : lines) {
if (&line != &lines.front())
err() << " ";
diff --git a/cmds/lshal/ListCommand.h b/cmds/lshal/ListCommand.h
index 1e85ea0..3f7321d 100644
--- a/cmds/lshal/ListCommand.h
+++ b/cmds/lshal/ListCommand.h
@@ -26,7 +26,9 @@
#include <android-base/macros.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
-#include <hidl-util/FQName.h>
+#include <hidl-util/FqInstance.h>
+#include <vintf/HalManifest.h>
+#include <vintf/VintfObject.h>
#include "Command.h"
#include "NullableOStream.h"
@@ -45,6 +47,14 @@
uint32_t threadCount; // number of threads total
};
+enum class HalType {
+ BINDERIZED_SERVICES = 0,
+ PASSTHROUGH_CLIENTS,
+ PASSTHROUGH_LIBRARIES,
+ VINTF_MANIFEST,
+ LAZY_HALS,
+};
+
class ListCommand : public Command {
public:
ListCommand(Lshal &lshal) : Command(lshal) {}
@@ -80,13 +90,17 @@
protected:
Status parseArgs(const Arg &arg);
+ // Retrieve first-hand information
Status fetch();
+ // Retrieve derived information base on existing table
virtual void postprocess();
Status dump();
- void putEntry(TableEntrySource source, TableEntry &&entry);
+ void putEntry(HalType type, TableEntry &&entry);
Status fetchPassthrough(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
Status fetchBinderized(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
Status fetchAllLibraries(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
+ Status fetchManifestHals();
+ Status fetchLazyHals();
Status fetchBinderizedEntry(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager,
TableEntry *entry);
@@ -113,19 +127,43 @@
void removeDeadProcesses(Pids *pids);
virtual Partition getPartition(pid_t pid);
- Partition resolvePartition(Partition processPartition, const FQName& fqName) const;
+ Partition resolvePartition(Partition processPartition, const FqInstance &fqInstance) const;
+
+ VintfInfo getVintfInfo(const std::string &fqInstanceName, vintf::TransportArch ta) const;
+ // Allow to mock these functions for testing.
+ virtual std::shared_ptr<const vintf::HalManifest> getDeviceManifest() const;
+ virtual std::shared_ptr<const vintf::CompatibilityMatrix> getDeviceMatrix() const;
+ virtual std::shared_ptr<const vintf::HalManifest> getFrameworkManifest() const;
+ virtual std::shared_ptr<const vintf::CompatibilityMatrix> getFrameworkMatrix() const;
void forEachTable(const std::function<void(Table &)> &f);
void forEachTable(const std::function<void(const Table &)> &f) const;
+ Table* tableForType(HalType type);
+ const Table* tableForType(HalType type) const;
NullableOStream<std::ostream> err() const;
NullableOStream<std::ostream> out() const;
void registerAllOptions();
+ // helper functions to dumpVintf.
+ bool addEntryWithInstance(const TableEntry &entry, vintf::HalManifest *manifest) const;
+ bool addEntryWithoutInstance(const TableEntry &entry, const vintf::HalManifest *manifest) const;
+
+ // Helper function. Whether to fetch entries corresponding to a given HAL type.
+ bool shouldFetchHalType(const HalType &type) const;
+
+ void initFetchTypes();
+
+ // Helper functions ti add HALs that are listed in VINTF manifest to LAZY_HALS table.
+ bool hasHwbinderEntry(const TableEntry& entry) const;
+ bool hasPassthroughEntry(const TableEntry& entry) const;
+
Table mServicesTable{};
Table mPassthroughRefTable{};
Table mImplementationsTable{};
+ Table mManifestHalsTable{};
+ Table mLazyHalsTable{};
std::string mFileOutputPath;
TableEntryCompare mSortColumn = nullptr;
@@ -139,6 +177,11 @@
// If true, explanatory text are not emitted.
bool mNeat = false;
+ // Type(s) of HAL associations to list.
+ std::vector<HalType> mListTypes{};
+ // Type(s) of HAL associations to fetch.
+ std::set<HalType> mFetchTypes{};
+
// If an entry does not exist, need to ask /proc/{pid}/cmdline to get it.
// If an entry exist but is an empty string, process might have died.
// If an entry exist and not empty, it contains the cached content of /proc/{pid}/cmdline.
diff --git a/cmds/lshal/PipeRelay.cpp b/cmds/lshal/PipeRelay.cpp
index fc40749..820679f 100644
--- a/cmds/lshal/PipeRelay.cpp
+++ b/cmds/lshal/PipeRelay.cpp
@@ -16,34 +16,75 @@
#include "PipeRelay.h"
-#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <atomic>
+
+#include <android-base/logging.h>
#include <utils/Thread.h>
namespace android {
namespace lshal {
+static constexpr struct timeval READ_TIMEOUT { .tv_sec = 1, .tv_usec = 0 };
+
struct PipeRelay::RelayThread : public Thread {
explicit RelayThread(int fd, std::ostream &os);
bool threadLoop() override;
+ void setFinished();
private:
int mFd;
std::ostream &mOutStream;
+ // If we were to use requestExit() and exitPending() instead, threadLoop()
+ // may not run at all by the time ~PipeRelay is called (i.e. debug() has
+ // returned from HAL). By using our own flag, we ensure that select() and
+ // read() are executed until data are drained.
+ std::atomic_bool mFinished;
+
DISALLOW_COPY_AND_ASSIGN(RelayThread);
};
////////////////////////////////////////////////////////////////////////////////
PipeRelay::RelayThread::RelayThread(int fd, std::ostream &os)
- : mFd(fd),
- mOutStream(os) {
-}
+ : mFd(fd), mOutStream(os), mFinished(false) {}
bool PipeRelay::RelayThread::threadLoop() {
char buffer[1024];
- ssize_t n = read(mFd, buffer, sizeof(buffer));
+
+ fd_set set;
+ FD_ZERO(&set);
+ FD_SET(mFd, &set);
+
+ struct timeval timeout = READ_TIMEOUT;
+
+ int res = TEMP_FAILURE_RETRY(select(mFd + 1, &set, nullptr, nullptr, &timeout));
+ if (res < 0) {
+ PLOG(INFO) << "select() failed";
+ return false;
+ }
+
+ if (res == 0 || !FD_ISSET(mFd, &set)) {
+ if (mFinished) {
+ LOG(WARNING) << "debug: timeout reading from pipe, output may be truncated.";
+ return false;
+ }
+ // timeout, but debug() has not returned, so wait for HAL to finish.
+ return true;
+ }
+
+ // FD_ISSET(mFd, &set) == true. Data available, start reading
+ ssize_t n = TEMP_FAILURE_RETRY(read(mFd, buffer, sizeof(buffer)));
+
+ if (n < 0) {
+ PLOG(ERROR) << "read() failed";
+ }
if (n <= 0) {
return false;
@@ -54,11 +95,15 @@
return true;
}
+void PipeRelay::RelayThread::setFinished() {
+ mFinished = true;
+}
+
////////////////////////////////////////////////////////////////////////////////
PipeRelay::PipeRelay(std::ostream &os)
: mInitCheck(NO_INIT) {
- int res = socketpair(AF_UNIX, SOCK_STREAM, 0 /* protocol */, mFds);
+ int res = pipe(mFds);
if (res < 0) {
mInitCheck = -errno;
@@ -77,20 +122,14 @@
}
PipeRelay::~PipeRelay() {
- if (mFds[1] >= 0) {
- shutdown(mFds[1], SHUT_WR);
- }
+ CloseFd(&mFds[1]);
- if (mFds[0] >= 0) {
- shutdown(mFds[0], SHUT_RD);
- }
-
- if (mThread != NULL) {
+ if (mThread != nullptr) {
+ mThread->setFinished();
mThread->join();
mThread.clear();
}
- CloseFd(&mFds[1]);
CloseFd(&mFds[0]);
}
diff --git a/cmds/lshal/TableEntry.cpp b/cmds/lshal/TableEntry.cpp
index e8792a4..8e21975 100644
--- a/cmds/lshal/TableEntry.cpp
+++ b/cmds/lshal/TableEntry.cpp
@@ -16,7 +16,11 @@
#define LOG_TAG "lshal"
#include <android-base/logging.h>
+#include <map>
+
+#include <android-base/strings.h>
#include <hidl-hash/Hash.h>
+#include <vintf/parse_string.h>
#include "TableEntry.h"
@@ -26,19 +30,19 @@
namespace android {
namespace lshal {
-static const std::string &getArchString(Architecture arch) {
+static const std::string &getArchString(vintf::Arch arch) {
static const std::string sStr64 = "64";
static const std::string sStr32 = "32";
static const std::string sStrBoth = "32+64";
- static const std::string sStrUnknown = "";
+ static const std::string sStrUnknown = "?";
switch (arch) {
- case ARCH64:
+ case vintf::Arch::ARCH_64:
return sStr64;
- case ARCH32:
+ case vintf::Arch::ARCH_32:
return sStr32;
- case ARCH_BOTH:
+ case vintf::Arch::ARCH_32_64:
return sStrBoth;
- case ARCH_UNKNOWN: // fall through
+ case vintf::Arch::ARCH_EMPTY: // fall through
default:
return sStrUnknown;
}
@@ -57,6 +61,8 @@
case TableColumnType::THREADS: return "Thread Use";
case TableColumnType::RELEASED: return "R";
case TableColumnType::HASH: return "Hash";
+ case TableColumnType::VINTF: return "VINTF";
+ case TableColumnType::SERVICE_STATUS: return "Status";
default:
LOG(FATAL) << __func__ << "Should not reach here. " << static_cast<int>(type);
return "";
@@ -68,7 +74,7 @@
case TableColumnType::INTERFACE_NAME:
return interfaceName;
case TableColumnType::TRANSPORT:
- return transport;
+ return vintf::to_string(transport);
case TableColumnType::SERVER_PID:
return serverPid == NO_PID ? "N/A" : std::to_string(serverPid);
case TableColumnType::SERVER_CMD:
@@ -87,6 +93,10 @@
return isReleased();
case TableColumnType::HASH:
return hash;
+ case TableColumnType::VINTF:
+ return getVintfInfo();
+ case TableColumnType::SERVICE_STATUS:
+ return lshal::to_string(serviceStatus);
default:
LOG(FATAL) << __func__ << "Should not reach here. " << static_cast<int>(type);
return "";
@@ -96,12 +106,44 @@
std::string TableEntry::isReleased() const {
static const std::string unreleased = Hash::hexString(Hash::kEmptyHash);
- if (hash.empty() || hash == unreleased) {
- return " "; // unknown or unreleased
+ if (hash.empty()) {
+ return "?";
+ }
+ if (hash == unreleased) {
+ return "N"; // unknown or unreleased
}
return "Y"; // released
}
+std::string TableEntry::getVintfInfo() const {
+ static const std::map<VintfInfo, std::string> values{
+ {DEVICE_MANIFEST, "DM"},
+ {DEVICE_MATRIX, "DC"},
+ {FRAMEWORK_MANIFEST, "FM"},
+ {FRAMEWORK_MATRIX, "FC"},
+ };
+ std::vector<std::string> ret;
+ for (const auto& pair : values) {
+ if (vintfInfo & pair.first) {
+ ret.push_back(pair.second);
+ }
+ }
+ auto joined = base::Join(ret, ',');
+ return joined.empty() ? "X" : joined;
+}
+
+std::string to_string(ServiceStatus s) {
+ switch (s) {
+ case ServiceStatus::ALIVE: return "alive";
+ case ServiceStatus::NON_RESPONSIVE: return "non-responsive";
+ case ServiceStatus::DECLARED: return "declared";
+ case ServiceStatus::UNKNOWN: return "N/A";
+ }
+
+ LOG(FATAL) << __func__ << "Should not reach here." << static_cast<int>(s);
+ return "";
+}
+
TextTable Table::createTextTable(bool neat,
const std::function<std::string(const std::string&)>& emitDebugInfo) const {
@@ -152,6 +194,7 @@
}
std::string TableEntry::to_string() const {
+ using vintf::operator<<;
std::stringstream ss;
ss << "name=" << interfaceName << ";transport=" << transport << ";thread=" << getThreadUsage()
<< ";server=" << serverPid
diff --git a/cmds/lshal/TableEntry.h b/cmds/lshal/TableEntry.h
index 24ea438..7294b0a 100644
--- a/cmds/lshal/TableEntry.h
+++ b/cmds/lshal/TableEntry.h
@@ -24,6 +24,8 @@
#include <iostream>
#include <procpartition/procpartition.h>
+#include <vintf/Arch.h>
+#include <vintf/Transport.h>
#include "TextTable.h"
@@ -33,21 +35,6 @@
using android::procpartition::Partition;
using Pids = std::vector<int32_t>;
-enum : unsigned int {
- HWSERVICEMANAGER_LIST, // through defaultServiceManager()->list()
- PTSERVICEMANAGER_REG_CLIENT, // through registerPassthroughClient
- LIST_DLLIB, // through listing dynamic libraries
-};
-using TableEntrySource = unsigned int;
-
-enum : unsigned int {
- ARCH_UNKNOWN = 0,
- ARCH32 = 1 << 0,
- ARCH64 = 1 << 1,
- ARCH_BOTH = ARCH32 | ARCH64
-};
-using Architecture = unsigned int;
-
enum class TableColumnType : unsigned int {
INTERFACE_NAME,
TRANSPORT,
@@ -60,16 +47,35 @@
THREADS,
RELEASED,
HASH,
+ VINTF,
+ SERVICE_STATUS,
};
+enum : unsigned int {
+ VINTF_INFO_EMPTY = 0,
+ DEVICE_MANIFEST = 1 << 0,
+ DEVICE_MATRIX = 1 << 1,
+ FRAMEWORK_MANIFEST = 1 << 2,
+ FRAMEWORK_MATRIX = 1 << 3,
+};
+using VintfInfo = unsigned int;
+
enum {
NO_PID = -1,
NO_PTR = 0
};
+enum class ServiceStatus {
+ UNKNOWN, // For passthrough
+ ALIVE,
+ NON_RESPONSIVE, // registered but not respond to calls
+ DECLARED, // in VINTF manifest
+};
+std::string to_string(ServiceStatus s);
+
struct TableEntry {
std::string interfaceName{};
- std::string transport{};
+ vintf::Transport transport{vintf::Transport::EMPTY};
int32_t serverPid{NO_PID};
uint32_t threadUsage{0};
uint32_t threadCount{0};
@@ -77,10 +83,13 @@
uint64_t serverObjectAddress{NO_PTR};
Pids clientPids{};
std::vector<std::string> clientCmdlines{};
- Architecture arch{ARCH_UNKNOWN};
+ vintf::Arch arch{vintf::Arch::ARCH_EMPTY};
// empty: unknown, all zeros: unreleased, otherwise: released
std::string hash{};
Partition partition{Partition::UNKNOWN};
+ VintfInfo vintfInfo{VINTF_INFO_EMPTY};
+ // true iff hwbinder and service started
+ ServiceStatus serviceStatus{ServiceStatus::UNKNOWN};
static bool sortByInterfaceName(const TableEntry &a, const TableEntry &b) {
return a.interfaceName < b.interfaceName;
@@ -99,6 +108,8 @@
std::string isReleased() const;
+ std::string getVintfInfo() const;
+
std::string getField(TableColumnType type) const;
bool operator==(const TableEntry& other) const;
diff --git a/cmds/lshal/Timeout.h b/cmds/lshal/Timeout.h
index c940404..58119a6 100644
--- a/cmds/lshal/Timeout.h
+++ b/cmds/lshal/Timeout.h
@@ -57,7 +57,7 @@
BackgroundTaskState &state = *static_cast<BackgroundTaskState *>(data);
state();
state.notify();
- return NULL;
+ return nullptr;
}
template<class R, class P>
@@ -65,7 +65,7 @@
auto now = std::chrono::system_clock::now();
BackgroundTaskState state{std::forward<decltype(func)>(func)};
pthread_t thread;
- if (pthread_create(&thread, NULL, callAndNotify, &state)) {
+ if (pthread_create(&thread, nullptr, callAndNotify, &state)) {
std::cerr << "FATAL: could not create background thread." << std::endl;
return false;
}
@@ -73,7 +73,7 @@
if (!success) {
pthread_kill(thread, SIGINT);
}
- pthread_join(thread, NULL);
+ pthread_join(thread, nullptr);
return success;
}
diff --git a/cmds/lshal/libprocpartition/procpartition.cpp b/cmds/lshal/libprocpartition/procpartition.cpp
index 8ca458a..9645f3a 100644
--- a/cmds/lshal/libprocpartition/procpartition.cpp
+++ b/cmds/lshal/libprocpartition/procpartition.cpp
@@ -50,7 +50,7 @@
false /* follow symlinks */)) {
return "";
}
- return content;
+ return std::string{content.c_str()};
}
Partition parsePartition(const std::string& s) {
diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp
index 4fa941e..8d7405b 100644
--- a/cmds/lshal/test.cpp
+++ b/cmds/lshal/test.cpp
@@ -44,6 +44,13 @@
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
+using android::vintf::Arch;
+using android::vintf::CompatibilityMatrix;
+using android::vintf::gCompatibilityMatrixConverter;
+using android::vintf::gHalManifestConverter;
+using android::vintf::HalManifest;
+using android::vintf::Transport;
+using android::vintf::VintfObject;
using InstanceDebugInfo = IServiceManager::InstanceDebugInfo;
@@ -207,6 +214,11 @@
MOCK_CONST_METHOD2(getPidInfo, bool(pid_t, PidInfo*));
MOCK_CONST_METHOD1(parseCmdline, std::string(pid_t));
MOCK_METHOD1(getPartition, Partition(pid_t));
+
+ MOCK_CONST_METHOD0(getDeviceManifest, std::shared_ptr<const vintf::HalManifest>());
+ MOCK_CONST_METHOD0(getDeviceMatrix, std::shared_ptr<const vintf::CompatibilityMatrix>());
+ MOCK_CONST_METHOD0(getFrameworkManifest, std::shared_ptr<const vintf::HalManifest>());
+ MOCK_CONST_METHOD0(getFrameworkMatrix, std::shared_ptr<const vintf::CompatibilityMatrix>());
};
class ListParseArgsTest : public ::testing::Test {
@@ -214,12 +226,13 @@
void SetUp() override {
mockLshal = std::make_unique<NiceMock<MockLshal>>();
mockList = std::make_unique<MockListCommand>(mockLshal.get());
+ ON_CALL(*mockLshal, err()).WillByDefault(Return(NullableOStream<std::ostream>(err)));
// ListCommand::parseArgs should parse arguments from the second element
optind = 1;
}
std::unique_ptr<MockLshal> mockLshal;
std::unique_ptr<MockListCommand> mockList;
- std::stringstream output;
+ std::stringstream err;
};
TEST_F(ListParseArgsTest, Args) {
@@ -229,6 +242,7 @@
TableColumnType::SERVER_ADDR, TableColumnType::CLIENT_PIDS}),
table.getSelectedColumns());
});
+ EXPECT_EQ("", err.str());
}
TEST_F(ListParseArgsTest, Cmds) {
@@ -243,12 +257,12 @@
EXPECT_THAT(table.getSelectedColumns(), Contains(TableColumnType::CLIENT_CMDS))
<< "should print client cmds with -m";
});
+ EXPECT_EQ("", err.str());
}
TEST_F(ListParseArgsTest, DebugAndNeat) {
- ON_CALL(*mockLshal, err()).WillByDefault(Return(NullableOStream<std::ostream>(output)));
EXPECT_NE(0u, mockList->parseArgs(createArg({"lshal", "--neat", "-d"})));
- EXPECT_THAT(output.str(), StrNe(""));
+ EXPECT_THAT(err.str(), HasSubstr("--neat should not be used with --debug."));
}
/// Fetch Test
@@ -313,7 +327,7 @@
class ListTest : public ::testing::Test {
public:
- void SetUp() override {
+ virtual void SetUp() override {
initMockServiceManager();
lshal = std::make_unique<Lshal>(out, err, serviceManager, passthruManager);
initMockList();
@@ -335,6 +349,15 @@
});
}));
ON_CALL(*mockList, getPartition(_)).WillByDefault(Return(Partition::VENDOR));
+
+ ON_CALL(*mockList, getDeviceManifest())
+ .WillByDefault(Return(std::make_shared<HalManifest>()));
+ ON_CALL(*mockList, getDeviceMatrix())
+ .WillByDefault(Return(std::make_shared<CompatibilityMatrix>()));
+ ON_CALL(*mockList, getFrameworkManifest())
+ .WillByDefault(Return(std::make_shared<HalManifest>()));
+ ON_CALL(*mockList, getFrameworkMatrix())
+ .WillByDefault(Return(std::make_shared<CompatibilityMatrix>()));
}
void initMockServiceManager() {
@@ -388,92 +411,76 @@
}
TEST_F(ListTest, Fetch) {
- EXPECT_EQ(0u, mockList->fetch());
- std::array<std::string, 6> transports{{"hwbinder", "hwbinder", "passthrough",
- "passthrough", "passthrough", "passthrough"}};
- std::array<Architecture, 6> archs{{ARCH64, ARCH64, ARCH32, ARCH32, ARCH32, ARCH32}};
- int id = 1;
+ optind = 1; // mimic Lshal::parseArg()
+ ASSERT_EQ(0u, mockList->parseArgs(createArg({"lshal"})));
+ ASSERT_EQ(0u, mockList->fetch());
+ vintf::TransportArch hwbinder{Transport::HWBINDER, Arch::ARCH_64};
+ vintf::TransportArch passthrough{Transport::PASSTHROUGH, Arch::ARCH_32};
+ std::array<vintf::TransportArch, 6> transportArchs{{hwbinder, hwbinder, passthrough,
+ passthrough, passthrough, passthrough}};
+ int i = 0;
mockList->forEachTable([&](const Table& table) {
- ASSERT_EQ(2u, table.size());
for (const auto& entry : table) {
- const auto& transport = transports[id - 1];
+ if (i >= transportArchs.size()) {
+ break;
+ }
+
+ int id = i + 1;
+ auto transport = transportArchs.at(i).transport;
TableEntry expected{
.interfaceName = getFqInstanceName(id),
.transport = transport,
- .serverPid = transport == "hwbinder" ? id : NO_PID,
- .threadUsage = transport == "hwbinder" ? getPidInfoFromId(id).threadUsage : 0,
- .threadCount = transport == "hwbinder" ? getPidInfoFromId(id).threadCount : 0,
+ .serverPid = transport == Transport::HWBINDER ? id : NO_PID,
+ .threadUsage =
+ transport == Transport::HWBINDER ? getPidInfoFromId(id).threadUsage : 0,
+ .threadCount =
+ transport == Transport::HWBINDER ? getPidInfoFromId(id).threadCount : 0,
.serverCmdline = {},
- .serverObjectAddress = transport == "hwbinder" ? getPtr(id) : NO_PTR,
+ .serverObjectAddress = transport == Transport::HWBINDER ? getPtr(id) : NO_PTR,
.clientPids = getClients(id),
.clientCmdlines = {},
- .arch = archs[id - 1],
+ .arch = transportArchs.at(i).arch,
};
EXPECT_EQ(expected, entry) << expected.to_string() << " vs. " << entry.to_string();
- ++id;
+ ++i;
}
});
+ EXPECT_EQ(transportArchs.size(), i) << "Not all entries are tested.";
+
}
TEST_F(ListTest, DumpVintf) {
- const std::string expected =
- "<!-- \n"
- " This is a skeleton device manifest. Notes: \n" + ListCommand::INIT_VINTF_NOTES +
- "-->\n"
- "<manifest version=\"1.0\" type=\"device\">\n"
- " <hal format=\"hidl\">\n"
- " <name>a.h.foo1</name>\n"
- " <transport>hwbinder</transport>\n"
- " <version>1.0</version>\n"
- " <interface>\n"
- " <name>IFoo</name>\n"
- " <instance>1</instance>\n"
- " </interface>\n"
- " </hal>\n"
- " <hal format=\"hidl\">\n"
- " <name>a.h.foo2</name>\n"
- " <transport>hwbinder</transport>\n"
- " <version>2.0</version>\n"
- " <interface>\n"
- " <name>IFoo</name>\n"
- " <instance>2</instance>\n"
- " </interface>\n"
- " </hal>\n"
- " <hal format=\"hidl\">\n"
- " <name>a.h.foo3</name>\n"
- " <transport arch=\"32\">passthrough</transport>\n"
- " <version>3.0</version>\n"
- " <interface>\n"
- " <name>IFoo</name>\n"
- " <instance>3</instance>\n"
- " </interface>\n"
- " </hal>\n"
- " <hal format=\"hidl\">\n"
- " <name>a.h.foo4</name>\n"
- " <transport arch=\"32\">passthrough</transport>\n"
- " <version>4.0</version>\n"
- " <interface>\n"
- " <name>IFoo</name>\n"
- " <instance>4</instance>\n"
- " </interface>\n"
- " </hal>\n"
- " <hal format=\"hidl\">\n"
- " <name>a.h.foo5</name>\n"
- " <transport arch=\"32\">passthrough</transport>\n"
- " <version>5.0</version>\n"
- " </hal>\n"
- " <hal format=\"hidl\">\n"
- " <name>a.h.foo6</name>\n"
- " <transport arch=\"32\">passthrough</transport>\n"
- " <version>6.0</version>\n"
- " </hal>\n"
- "</manifest>\n";
+ const std::string expected = "<manifest version=\"1.0\" type=\"device\">\n"
+ " <hal format=\"hidl\">\n"
+ " <name>a.h.foo1</name>\n"
+ " <transport>hwbinder</transport>\n"
+ " <fqname>@1.0::IFoo/1</fqname>\n"
+ " </hal>\n"
+ " <hal format=\"hidl\">\n"
+ " <name>a.h.foo2</name>\n"
+ " <transport>hwbinder</transport>\n"
+ " <fqname>@2.0::IFoo/2</fqname>\n"
+ " </hal>\n"
+ " <hal format=\"hidl\">\n"
+ " <name>a.h.foo3</name>\n"
+ " <transport arch=\"32\">passthrough</transport>\n"
+ " <fqname>@3.0::IFoo/3</fqname>\n"
+ " </hal>\n"
+ " <hal format=\"hidl\">\n"
+ " <name>a.h.foo4</name>\n"
+ " <transport arch=\"32\">passthrough</transport>\n"
+ " <fqname>@4.0::IFoo/4</fqname>\n"
+ " </hal>\n"
+ "</manifest>";
optind = 1; // mimic Lshal::parseArg()
EXPECT_EQ(0u, mockList->main(createArg({"lshal", "--init-vintf"})));
- EXPECT_EQ(expected, out.str());
+ auto output = out.str();
+ EXPECT_THAT(output, HasSubstr(expected));
+ EXPECT_THAT(output, HasSubstr("a.h.foo5@5.0::IFoo/5"));
+ EXPECT_THAT(output, HasSubstr("a.h.foo6@6.0::IFoo/6"));
EXPECT_EQ("", err.str());
vintf::HalManifest m;
@@ -487,18 +494,18 @@
const std::string expected =
"[fake description 0]\n"
"R Interface Thread Use Server Clients\n"
- " a.h.foo1@1.0::IFoo/1 11/21 1 2 4\n"
+ "N a.h.foo1@1.0::IFoo/1 11/21 1 2 4\n"
"Y a.h.foo2@2.0::IFoo/2 12/22 2 3 5\n"
"\n"
"[fake description 1]\n"
"R Interface Thread Use Server Clients\n"
- " a.h.foo3@3.0::IFoo/3 N/A N/A 4 6\n"
- " a.h.foo4@4.0::IFoo/4 N/A N/A 5 7\n"
+ "? a.h.foo3@3.0::IFoo/3 N/A N/A 4 6\n"
+ "? a.h.foo4@4.0::IFoo/4 N/A N/A 5 7\n"
"\n"
"[fake description 2]\n"
"R Interface Thread Use Server Clients\n"
- " a.h.foo5@5.0::IFoo/5 N/A N/A 6 8\n"
- " a.h.foo6@6.0::IFoo/6 N/A N/A 7 9\n"
+ "? a.h.foo5@5.0::IFoo/5 N/A N/A 6 8\n"
+ "? a.h.foo6@6.0::IFoo/6 N/A N/A 7 9\n"
"\n";
optind = 1; // mimic Lshal::parseArg()
@@ -511,18 +518,18 @@
const std::string expected =
"[fake description 0]\n"
"Interface R Hash\n"
- "a.h.foo1@1.0::IFoo/1 0000000000000000000000000000000000000000000000000000000000000000\n"
+ "a.h.foo1@1.0::IFoo/1 N 0000000000000000000000000000000000000000000000000000000000000000\n"
"a.h.foo2@2.0::IFoo/2 Y 0202020202020202020202020202020202020202020202020202020202020202\n"
"\n"
"[fake description 1]\n"
"Interface R Hash\n"
- "a.h.foo3@3.0::IFoo/3 \n"
- "a.h.foo4@4.0::IFoo/4 \n"
+ "a.h.foo3@3.0::IFoo/3 ? \n"
+ "a.h.foo4@4.0::IFoo/4 ? \n"
"\n"
"[fake description 2]\n"
"Interface R Hash\n"
- "a.h.foo5@5.0::IFoo/5 \n"
- "a.h.foo6@6.0::IFoo/6 \n"
+ "a.h.foo5@5.0::IFoo/5 ? \n"
+ "a.h.foo6@6.0::IFoo/6 ? \n"
"\n";
optind = 1; // mimic Lshal::parseArg()
@@ -594,6 +601,225 @@
EXPECT_EQ("", err.str());
}
+TEST_F(ListTest, DumpSingleHalType) {
+ const std::string expected =
+ "[fake description 0]\n"
+ "Interface Transport Arch Thread Use Server PTR Clients\n"
+ "a.h.foo1@1.0::IFoo/1 hwbinder 64 11/21 1 0000000000002711 2 4\n"
+ "a.h.foo2@2.0::IFoo/2 hwbinder 64 12/22 2 0000000000002712 3 5\n"
+ "\n";
+
+ optind = 1; // mimic Lshal::parseArg()
+ EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-itrepac", "--types=binderized"})));
+ EXPECT_EQ(expected, out.str());
+ EXPECT_EQ("", err.str());
+}
+
+TEST_F(ListTest, DumpReorderedHalTypes) {
+ const std::string expected =
+ "[fake description 0]\n"
+ "Interface Transport Arch Thread Use Server PTR Clients\n"
+ "a.h.foo3@3.0::IFoo/3 passthrough 32 N/A N/A N/A 4 6\n"
+ "a.h.foo4@4.0::IFoo/4 passthrough 32 N/A N/A N/A 5 7\n"
+ "\n"
+ "[fake description 1]\n"
+ "Interface Transport Arch Thread Use Server PTR Clients\n"
+ "a.h.foo5@5.0::IFoo/5 passthrough 32 N/A N/A N/A 6 8\n"
+ "a.h.foo6@6.0::IFoo/6 passthrough 32 N/A N/A N/A 7 9\n"
+ "\n"
+ "[fake description 2]\n"
+ "Interface Transport Arch Thread Use Server PTR Clients\n"
+ "a.h.foo1@1.0::IFoo/1 hwbinder 64 11/21 1 0000000000002711 2 4\n"
+ "a.h.foo2@2.0::IFoo/2 hwbinder 64 12/22 2 0000000000002712 3 5\n"
+ "\n";
+
+ optind = 1; // mimic Lshal::parseArg()
+ EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-itrepac", "--types=passthrough_clients",
+ "--types=passthrough_libs", "--types=binderized"})));
+ EXPECT_EQ(expected, out.str());
+ EXPECT_EQ("", err.str());
+}
+
+TEST_F(ListTest, DumpAbbreviatedHalTypes) {
+ const std::string expected =
+ "[fake description 0]\n"
+ "Interface Transport Arch Thread Use Server PTR Clients\n"
+ "a.h.foo3@3.0::IFoo/3 passthrough 32 N/A N/A N/A 4 6\n"
+ "a.h.foo4@4.0::IFoo/4 passthrough 32 N/A N/A N/A 5 7\n"
+ "\n"
+ "[fake description 1]\n"
+ "Interface Transport Arch Thread Use Server PTR Clients\n"
+ "a.h.foo5@5.0::IFoo/5 passthrough 32 N/A N/A N/A 6 8\n"
+ "a.h.foo6@6.0::IFoo/6 passthrough 32 N/A N/A N/A 7 9\n"
+ "\n";
+
+ optind = 1; // mimic Lshal::parseArg()
+ EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-itrepac", "--types=c,l"})));
+ EXPECT_EQ(expected, out.str());
+ EXPECT_EQ("", err.str());
+}
+
+TEST_F(ListTest, DumpEmptyAndDuplicateHalTypes) {
+ const std::string expected =
+ "[fake description 0]\n"
+ "Interface Transport Arch Thread Use Server PTR Clients\n"
+ "a.h.foo3@3.0::IFoo/3 passthrough 32 N/A N/A N/A 4 6\n"
+ "a.h.foo4@4.0::IFoo/4 passthrough 32 N/A N/A N/A 5 7\n"
+ "\n"
+ "[fake description 1]\n"
+ "Interface Transport Arch Thread Use Server PTR Clients\n"
+ "a.h.foo5@5.0::IFoo/5 passthrough 32 N/A N/A N/A 6 8\n"
+ "a.h.foo6@6.0::IFoo/6 passthrough 32 N/A N/A N/A 7 9\n"
+ "\n";
+
+ optind = 1; // mimic Lshal::parseArg()
+ EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-itrepac", "--types=c,l,,,l,l,c,",
+ "--types=passthrough_libs,passthrough_clients"})));
+ EXPECT_EQ(expected, out.str());
+ EXPECT_EQ("", err.str());
+}
+
+TEST_F(ListTest, UnknownHalType) {
+ optind = 1; // mimic Lshal::parseArg()
+ EXPECT_EQ(1u, mockList->main(createArg({"lshal", "-itrepac", "--types=c,a"})));
+ EXPECT_THAT(err.str(), HasSubstr("Unrecognized HAL type: a"));
+}
+
+TEST_F(ListTest, Vintf) {
+ std::string deviceManifestXml =
+ "<manifest version=\"1.0\" type=\"device\">\n"
+ " <hal>\n"
+ " <name>a.h.foo1</name>\n"
+ " <transport>hwbinder</transport>\n"
+ " <fqname>@1.0::IFoo/1</fqname>\n"
+ " </hal>\n"
+ " <hal>\n"
+ " <name>a.h.foo3</name>\n"
+ " <transport arch=\"32+64\">passthrough</transport>\n"
+ " <fqname>@3.0::IFoo/3</fqname>\n"
+ " </hal>\n"
+ "</manifest>\n";
+ std::string frameworkManifestXml =
+ "<manifest version=\"1.0\" type=\"framework\">\n"
+ " <hal>\n"
+ " <name>a.h.foo5</name>\n"
+ " <transport arch=\"32\">passthrough</transport>\n"
+ " <fqname>@5.0::IFoo/5</fqname>\n"
+ " </hal>\n"
+ "</manifest>\n";
+ std::string deviceMatrixXml =
+ "<compatibility-matrix version=\"1.0\" type=\"device\">\n"
+ " <hal>\n"
+ " <name>a.h.foo5</name>\n"
+ " <version>5.0</version>\n"
+ " <interface>\n"
+ " <name>IFoo</name>\n"
+ " <instance>5</instance>\n"
+ " </interface>\n"
+ " </hal>\n"
+ "</compatibility-matrix>\n";
+ std::string frameworkMatrixXml =
+ "<compatibility-matrix version=\"1.0\" type=\"framework\">\n"
+ " <hal>\n"
+ " <name>a.h.foo1</name>\n"
+ " <version>1.0</version>\n"
+ " <interface>\n"
+ " <name>IFoo</name>\n"
+ " <instance>1</instance>\n"
+ " </interface>\n"
+ " </hal>\n"
+ " <hal>\n"
+ " <name>a.h.foo3</name>\n"
+ " <version>3.0</version>\n"
+ " <interface>\n"
+ " <name>IFoo</name>\n"
+ " <instance>3</instance>\n"
+ " </interface>\n"
+ " </hal>\n"
+ "</compatibility-matrix>\n";
+
+ std::string expected = "DM,FC a.h.foo1@1.0::IFoo/1\n"
+ "X a.h.foo2@2.0::IFoo/2\n"
+ "DM,FC a.h.foo3@3.0::IFoo/3\n"
+ "X a.h.foo4@4.0::IFoo/4\n"
+ "DC,FM a.h.foo5@5.0::IFoo/5\n"
+ "X a.h.foo6@6.0::IFoo/6\n";
+
+ auto deviceManifest = std::make_shared<HalManifest>();
+ auto frameworkManifest = std::make_shared<HalManifest>();
+ auto deviceMatrix = std::make_shared<CompatibilityMatrix>();
+ auto frameworkMatrix = std::make_shared<CompatibilityMatrix>();
+
+ ASSERT_TRUE(gHalManifestConverter(deviceManifest.get(), deviceManifestXml));
+ ASSERT_TRUE(gHalManifestConverter(frameworkManifest.get(), frameworkManifestXml));
+ ASSERT_TRUE(gCompatibilityMatrixConverter(deviceMatrix.get(), deviceMatrixXml));
+ ASSERT_TRUE(gCompatibilityMatrixConverter(frameworkMatrix.get(), frameworkMatrixXml));
+
+ ON_CALL(*mockList, getDeviceManifest()).WillByDefault(Return(deviceManifest));
+ ON_CALL(*mockList, getDeviceMatrix()).WillByDefault(Return(deviceMatrix));
+ ON_CALL(*mockList, getFrameworkManifest()).WillByDefault(Return(frameworkManifest));
+ ON_CALL(*mockList, getFrameworkMatrix()).WillByDefault(Return(frameworkMatrix));
+
+ optind = 1; // mimic Lshal::parseArg()
+ EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-Vi", "--neat"})));
+ EXPECT_THAT(out.str(), HasSubstr(expected));
+ EXPECT_EQ("", err.str());
+}
+
+class ListVintfTest : public ListTest {
+public:
+ virtual void SetUp() override {
+ ListTest::SetUp();
+ const std::string mockManifestXml =
+ "<manifest version=\"1.0\" type=\"device\">\n"
+ " <hal format=\"hidl\">\n"
+ " <name>a.h.foo1</name>\n"
+ " <transport>hwbinder</transport>\n"
+ " <fqname>@1.0::IFoo/1</fqname>\n"
+ " </hal>\n"
+ " <hal format=\"hidl\">\n"
+ " <name>a.h.bar1</name>\n"
+ " <transport>hwbinder</transport>\n"
+ " <fqname>@1.0::IBar/1</fqname>\n"
+ " </hal>\n"
+ " <hal format=\"hidl\">\n"
+ " <name>a.h.bar2</name>\n"
+ " <transport arch=\"32+64\">passthrough</transport>\n"
+ " <fqname>@2.0::IBar/2</fqname>\n"
+ " </hal>\n"
+ "</manifest>";
+ auto manifest = std::make_shared<HalManifest>();
+ EXPECT_TRUE(gHalManifestConverter(manifest.get(), mockManifestXml));
+ EXPECT_CALL(*mockList, getDeviceManifest())
+ .Times(AnyNumber())
+ .WillRepeatedly(Return(manifest));
+ }
+};
+
+TEST_F(ListVintfTest, ManifestHals) {
+ optind = 1; // mimic Lshal::parseArg()
+ EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-iStr", "--types=v", "--neat"})));
+ EXPECT_THAT(out.str(), HasSubstr("a.h.bar1@1.0::IBar/1 declared hwbinder ?"));
+ EXPECT_THAT(out.str(), HasSubstr("a.h.bar2@2.0::IBar/2 declared passthrough 32+64"));
+ EXPECT_THAT(out.str(), HasSubstr("a.h.foo1@1.0::IFoo/1 declared hwbinder ?"));
+ EXPECT_EQ("", err.str());
+}
+
+TEST_F(ListVintfTest, Lazy) {
+ optind = 1; // mimic Lshal::parseArg()
+ EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-iStr", "--types=z", "--neat"})));
+ EXPECT_THAT(out.str(), HasSubstr("a.h.bar1@1.0::IBar/1 declared hwbinder ?"));
+ EXPECT_THAT(out.str(), HasSubstr("a.h.bar2@2.0::IBar/2 declared passthrough 32+64"));
+ EXPECT_EQ("", err.str());
+}
+
+TEST_F(ListVintfTest, NoLazy) {
+ optind = 1; // mimic Lshal::parseArg()
+ EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-iStr", "--types=b,c,l", "--neat"})));
+ EXPECT_THAT(out.str(), Not(HasSubstr("IBar")));
+ EXPECT_EQ("", err.str());
+}
+
class HelpTest : public ::testing::Test {
public:
void SetUp() override {
diff --git a/cmds/lshal/utils.h b/cmds/lshal/utils.h
index c09e8b1..240155e 100644
--- a/cmds/lshal/utils.h
+++ b/cmds/lshal/utils.h
@@ -46,6 +46,8 @@
TRANSACTION_ERROR = 1 << 8,
// No transaction error, but return value is unexpected.
BAD_IMPL = 1 << 9,
+ // Cannot fetch VINTF data.
+ VINTF_ERROR = 1 << 10,
};
using Status = unsigned int;
diff --git a/cmds/rawbu/Android.bp b/cmds/rawbu/Android.bp
new file mode 100644
index 0000000..363ffc1
--- /dev/null
+++ b/cmds/rawbu/Android.bp
@@ -0,0 +1,14 @@
+// Copyright 2009 The Android Open Source Project
+
+cc_binary {
+ name: "rawbu",
+
+ srcs: ["backup.cpp"],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+
+ shared_libs: ["libcutils"],
+}
diff --git a/cmds/rawbu/Android.mk b/cmds/rawbu/Android.mk
deleted file mode 100644
index 9322151..0000000
--- a/cmds/rawbu/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2009 The Android Open Source Project
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= backup.cpp
-
-LOCAL_CFLAGS := -Wall -Werror
-
-LOCAL_SHARED_LIBRARIES := libcutils libc
-
-LOCAL_MODULE:= rawbu
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
-LOCAL_MODULE_TAGS := debug
-
-include $(BUILD_EXECUTABLE)
diff --git a/cmds/rawbu/backup.cpp b/cmds/rawbu/backup.cpp
index 0072281..8b20e3e 100644
--- a/cmds/rawbu/backup.cpp
+++ b/cmds/rawbu/backup.cpp
@@ -38,7 +38,7 @@
static struct stat statBuffer;
static char copyBuffer[8192];
-static char *backupFilePath = NULL;
+static char *backupFilePath = nullptr;
static uint32_t inputFileVersion;
@@ -58,7 +58,7 @@
{ "/data/system/batterystats.bin", SPECIAL_NO_TOUCH },
{ "/data/system/location", SPECIAL_NO_TOUCH },
{ "/data/dalvik-cache", SPECIAL_NO_BACKUP },
- { NULL, 0 },
+ { nullptr, 0 },
};
/* This is just copied from the shell's built-in wipe command. */
@@ -71,7 +71,7 @@
dir = opendir(path);
- if (dir == NULL) {
+ if (dir == nullptr) {
fprintf (stderr, "Error opendir'ing %s: %s\n",
path, strerror(errno));
return 0;
@@ -87,7 +87,7 @@
for (;;) {
de = readdir(dir);
- if (de == NULL) {
+ if (de == nullptr) {
break;
}
@@ -115,7 +115,7 @@
}
}
- if (!noBackup && SKIP_PATHS[i].path != NULL) {
+ if (!noBackup && SKIP_PATHS[i].path != nullptr) {
// This is a SPECIAL_NO_TOUCH directory.
continue;
}
@@ -203,7 +203,7 @@
int amt = size > (off_t)sizeof(copyBuffer) ? sizeof(copyBuffer) : (int)size;
int readLen = fread(copyBuffer, 1, amt, src);
if (readLen <= 0) {
- if (srcName != NULL) {
+ if (srcName != nullptr) {
fprintf(stderr, "unable to read source (%d of %ld bytes) file '%s': %s\n",
amt, origSize, srcName, errno != 0 ? strerror(errno) : "unexpected EOF");
} else {
@@ -214,7 +214,7 @@
}
int writeLen = fwrite(copyBuffer, 1, readLen, dest);
if (writeLen != readLen) {
- if (destName != NULL) {
+ if (destName != nullptr) {
fprintf(stderr, "unable to write file (%d of %d bytes) '%s': '%s'\n",
writeLen, readLen, destName, strerror(errno));
} else {
@@ -256,14 +256,14 @@
{
DIR *dir;
struct dirent *de;
- char* fullPath = NULL;
+ char* fullPath = nullptr;
int srcLen = strlen(srcPath);
int result = 1;
int i;
dir = opendir(srcPath);
- if (dir == NULL) {
+ if (dir == nullptr) {
fprintf (stderr, "error opendir'ing '%s': %s\n",
srcPath, strerror(errno));
return 0;
@@ -272,7 +272,7 @@
for (;;) {
de = readdir(dir);
- if (de == NULL) {
+ if (de == nullptr) {
break;
}
@@ -283,7 +283,7 @@
continue;
}
- if (fullPath != NULL) {
+ if (fullPath != nullptr) {
free(fullPath);
}
fullPath = (char*)malloc(srcLen + strlen(de->d_name) + 2);
@@ -298,7 +298,7 @@
break;
}
}
- if (SKIP_PATHS[i].path != NULL) {
+ if (SKIP_PATHS[i].path != nullptr) {
continue;
}
}
@@ -343,14 +343,14 @@
}
FILE* src = fopen(fullPath, "r");
- if (src == NULL) {
+ if (src == nullptr) {
fprintf(stderr, "unable to open source file '%s': %s\n",
fullPath, strerror(errno));
result = 0;
goto done;
}
- int copyres = copy_file(fh, src, size, NULL, fullPath);
+ int copyres = copy_file(fh, src, size, nullptr, fullPath);
fclose(src);
if (!copyres) {
result = 0;
@@ -360,7 +360,7 @@
}
done:
- if (fullPath != NULL) {
+ if (fullPath != nullptr) {
free(fullPath);
}
@@ -374,7 +374,7 @@
int res = -1;
FILE* fh = fopen(destPath, "w");
- if (fh == NULL) {
+ if (fh == nullptr) {
fprintf(stderr, "unable to open destination '%s': %s\n",
destPath, strerror(errno));
return -1;
@@ -504,7 +504,7 @@
int res = -1;
FILE* fh = fopen(srcPath, "r");
- if (fh == NULL) {
+ if (fh == nullptr) {
fprintf(stderr, "Unable to open source '%s': %s\n",
srcPath, strerror(errno));
return -1;
@@ -534,7 +534,7 @@
while (1) {
int type;
- char* path = NULL;
+ char* path = nullptr;
if (read_header(fh, &type, &path, &statBuffer) == 0) {
goto done;
}
@@ -570,14 +570,14 @@
printf("Restoring file %s...\n", path);
FILE* dest = fopen(path, "w");
- if (dest == NULL) {
+ if (dest == nullptr) {
fprintf(stderr, "unable to open destination file '%s': %s\n",
path, strerror(errno));
free(path);
goto done;
}
- int copyres = copy_file(dest, fh, size, path, NULL);
+ int copyres = copy_file(dest, fh, size, path, nullptr);
fclose(dest);
if (!copyres) {
free(path);
diff --git a/cmds/service/service.cpp b/cmds/service/service.cpp
index bc11256..34a3fdc 100644
--- a/cmds/service/service.cpp
+++ b/cmds/service/service.cpp
@@ -30,7 +30,7 @@
void writeString16(Parcel& parcel, const char* string)
{
- if (string != NULL)
+ if (string != nullptr)
{
parcel.writeString16(String16(string));
}
@@ -43,7 +43,7 @@
// get the name of the generic interface we hold a reference to
static String16 get_interface_name(sp<IBinder> service)
{
- if (service != NULL) {
+ if (service != nullptr) {
Parcel data, reply;
status_t err = service->transact(IBinder::INTERFACE_TRANSACTION, data, &reply);
if (err == NO_ERROR) {
@@ -93,7 +93,7 @@
#endif
sp<IServiceManager> sm = defaultServiceManager();
fflush(stdout);
- if (sm == NULL) {
+ if (sm == nullptr) {
aerr << "service: Unable to get default service manager!" << endl;
return 20;
}
@@ -106,7 +106,7 @@
if (optind < argc) {
sp<IBinder> service = sm->checkService(String16(argv[optind]));
aout << "Service " << argv[optind] <<
- (service == NULL ? ": not found" : ": found") << endl;
+ (service == nullptr ? ": not found" : ": found") << endl;
} else {
aerr << "service: No service specified for check" << endl;
wantsUsage = true;
@@ -131,7 +131,7 @@
sp<IBinder> service = sm->checkService(String16(argv[optind++]));
String16 ifName = get_interface_name(service);
int32_t code = atoi(argv[optind++]);
- if (service != NULL && ifName.size() > 0) {
+ if (service != nullptr && ifName.size() > 0) {
Parcel data, reply;
// the interface name is first
@@ -186,28 +186,28 @@
data.writeDouble(atof(argv[optind++]));
} else if (strcmp(argv[optind], "null") == 0) {
optind++;
- data.writeStrongBinder(NULL);
+ data.writeStrongBinder(nullptr);
} else if (strcmp(argv[optind], "intent") == 0) {
- char* action = NULL;
- char* dataArg = NULL;
- char* type = NULL;
+ char* action = nullptr;
+ char* dataArg = nullptr;
+ char* type = nullptr;
int launchFlags = 0;
- char* component = NULL;
+ char* component = nullptr;
int categoryCount = 0;
char* categories[16];
- char* context1 = NULL;
+ char* context1 = nullptr;
optind++;
while (optind < argc)
{
char* key = strtok_r(argv[optind], "=", &context1);
- char* value = strtok_r(NULL, "=", &context1);
+ char* value = strtok_r(nullptr, "=", &context1);
// we have reached the end of the XXX=XXX args.
- if (key == NULL) break;
+ if (key == nullptr) break;
if (strcmp(key, "action") == 0)
{
@@ -231,14 +231,14 @@
}
else if (strcmp(key, "categories") == 0)
{
- char* context2 = NULL;
+ char* context2 = nullptr;
int categoryCount = 0;
categories[categoryCount] = strtok_r(value, ",", &context2);
- while (categories[categoryCount] != NULL)
+ while (categories[categoryCount] != nullptr)
{
categoryCount++;
- categories[categoryCount] = strtok_r(NULL, ",", &context2);
+ categories[categoryCount] = strtok_r(nullptr, ",", &context2);
}
}
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index 6b340a8..d776682 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -403,7 +403,11 @@
cb.func_audit = audit_callback;
selinux_set_callback(SELINUX_CB_AUDIT, cb);
+#ifdef VENDORSERVICEMANAGER
+ cb.func_log = selinux_vendor_log_callback;
+#else
cb.func_log = selinux_log_callback;
+#endif
selinux_set_callback(SELINUX_CB_LOG, cb);
#ifdef VENDORSERVICEMANAGER
diff --git a/cmds/surfacereplayer/replayer/Android.bp b/cmds/surfacereplayer/replayer/Android.bp
index 5caceec..7632311 100644
--- a/cmds/surfacereplayer/replayer/Android.bp
+++ b/cmds/surfacereplayer/replayer/Android.bp
@@ -1,6 +1,5 @@
cc_library_shared {
name: "libsurfacereplayer",
- clang: true,
srcs: [
"BufferQueueScheduler.cpp",
"Event.cpp",
@@ -16,7 +15,6 @@
"-Wno-float-equal",
"-Wno-sign-conversion",
"-Wno-padded",
- "-std=c++14",
],
static_libs: [
"libtrace_proto",
@@ -41,7 +39,6 @@
cc_binary {
name: "surfacereplayer",
- clang: true,
srcs: [
"Main.cpp",
],
@@ -61,6 +58,5 @@
"-Wno-float-conversion",
"-Wno-disabled-macro-expansion",
"-Wno-float-equal",
- "-std=c++14",
],
}
diff --git a/cmds/surfacereplayer/replayer/Main.cpp b/cmds/surfacereplayer/replayer/Main.cpp
index 7090bdb..fbfcacf 100644
--- a/cmds/surfacereplayer/replayer/Main.cpp
+++ b/cmds/surfacereplayer/replayer/Main.cpp
@@ -94,7 +94,7 @@
}
char** input = argv + optind;
- if (input[0] == NULL) {
+ if (input[0] == nullptr) {
std::cerr << "No trace file provided...exiting" << std::endl;
abort();
}
diff --git a/data/etc/android.hardware.usb.accessory.xml b/data/etc/android.hardware.usb.accessory.xml
index 80a0904..29df966 100644
--- a/data/etc/android.hardware.usb.accessory.xml
+++ b/data/etc/android.hardware.usb.accessory.xml
@@ -17,6 +17,4 @@
<!-- This is the standard feature indicating that the device supports USB accessories. -->
<permissions>
<feature name="android.hardware.usb.accessory" />
- <library name="com.android.future.usb.accessory"
- file="/system/framework/com.android.future.usb.accessory.jar" />
</permissions>
diff --git a/headers/media_plugin/media/arcvideobridge/IArcVideoBridge.h b/headers/media_plugin/media/arcvideobridge/IArcVideoBridge.h
deleted file mode 100644
index b32c92e..0000000
--- a/headers/media_plugin/media/arcvideobridge/IArcVideoBridge.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_IARC_VIDEO_BRIDGE_H
-#define ANDROID_IARC_VIDEO_BRIDGE_H
-
-#include <arc/IArcBridgeService.h>
-#include <binder/IInterface.h>
-#include <utils/Errors.h>
-
-namespace android {
-
-class IArcVideoBridge : public IInterface {
-public:
- DECLARE_META_INTERFACE(ArcVideoBridge);
-
- // Returns MojoBootstrapResult for creating mojo ipc channel of
- // VideoAcceleratorFactory.
- virtual ::arc::MojoBootstrapResult bootstrapVideoAcceleratorFactory() = 0;
-
- // Get the version of the remote VideoHost on Chromium side.
- virtual int32_t hostVersion() = 0;
-};
-
-class BnArcVideoBridge : public BnInterface<IArcVideoBridge> {
-public:
- virtual status_t onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif // ANDROID_IARC_VIDEO_BRIDGE_H
diff --git a/include/android/choreographer.h b/include/android/choreographer.h
index 43346fe..d75de1e 100644
--- a/include/android/choreographer.h
+++ b/include/android/choreographer.h
@@ -30,8 +30,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 24
-
struct AChoreographer;
typedef struct AChoreographer AChoreographer;
@@ -45,25 +43,29 @@
*/
typedef void (*AChoreographer_frameCallback)(long frameTimeNanos, void* data);
+#if __ANDROID_API__ >= 24
+
/**
* Get the AChoreographer instance for the current thread. This must be called
* on an ALooper thread.
*/
-AChoreographer* AChoreographer_getInstance();
+AChoreographer* AChoreographer_getInstance() __INTRODUCED_IN(24);
/**
* Post a callback to be run on the next frame. The data pointer provided will
* be passed to the callback function when it's called.
*/
void AChoreographer_postFrameCallback(AChoreographer* choreographer,
- AChoreographer_frameCallback callback, void* data);
+ AChoreographer_frameCallback callback, void* data) __INTRODUCED_IN(24);
+
/**
* Post a callback to be run on the frame following the specified delay. The
* data pointer provided will be passed to the callback function when it's
* called.
*/
void AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer,
- AChoreographer_frameCallback callback, void* data, long delayMillis);
+ AChoreographer_frameCallback callback, void* data,
+ long delayMillis) __INTRODUCED_IN(24);
#endif /* __ANDROID_API__ >= 24 */
diff --git a/include/android/configuration.h b/include/android/configuration.h
index 6287332..ef6c5a2 100644
--- a/include/android/configuration.h
+++ b/include/android/configuration.h
@@ -30,6 +30,10 @@
#include <android/asset_manager.h>
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(__api_level) /* nothing */
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -676,34 +680,34 @@
* Return the current configuration screen width in dp units, or
* ACONFIGURATION_SCREEN_WIDTH_DP_ANY if not set.
*/
-int32_t AConfiguration_getScreenWidthDp(AConfiguration* config);
+int32_t AConfiguration_getScreenWidthDp(AConfiguration* config) __INTRODUCED_IN(13);
/**
* Set the configuration's current screen width in dp units.
*/
-void AConfiguration_setScreenWidthDp(AConfiguration* config, int32_t value);
+void AConfiguration_setScreenWidthDp(AConfiguration* config, int32_t value) __INTRODUCED_IN(13);
/**
* Return the current configuration screen height in dp units, or
* ACONFIGURATION_SCREEN_HEIGHT_DP_ANY if not set.
*/
-int32_t AConfiguration_getScreenHeightDp(AConfiguration* config);
+int32_t AConfiguration_getScreenHeightDp(AConfiguration* config) __INTRODUCED_IN(13);
/**
* Set the configuration's current screen width in dp units.
*/
-void AConfiguration_setScreenHeightDp(AConfiguration* config, int32_t value);
+void AConfiguration_setScreenHeightDp(AConfiguration* config, int32_t value) __INTRODUCED_IN(13);
/**
* Return the configuration's smallest screen width in dp units, or
* ACONFIGURATION_SMALLEST_SCREEN_WIDTH_DP_ANY if not set.
*/
-int32_t AConfiguration_getSmallestScreenWidthDp(AConfiguration* config);
+int32_t AConfiguration_getSmallestScreenWidthDp(AConfiguration* config) __INTRODUCED_IN(13);
/**
* Set the configuration's smallest screen width in dp units.
*/
-void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t value);
+void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t value) __INTRODUCED_IN(13);
#endif /* __ANDROID_API__ >= 13 */
#if __ANDROID_API__ >= 17
@@ -711,12 +715,12 @@
* Return the configuration's layout direction, or
* ACONFIGURATION_LAYOUTDIR_ANY if not set.
*/
-int32_t AConfiguration_getLayoutDirection(AConfiguration* config);
+int32_t AConfiguration_getLayoutDirection(AConfiguration* config) __INTRODUCED_IN(17);
/**
* Set the configuration's layout direction.
*/
-void AConfiguration_setLayoutDirection(AConfiguration* config, int32_t value);
+void AConfiguration_setLayoutDirection(AConfiguration* config, int32_t value) __INTRODUCED_IN(17);
#endif /* __ANDROID_API__ >= 17 */
/**
diff --git a/include/android/input.h b/include/android/input.h
index 0829989..6810901 100644
--- a/include/android/input.h
+++ b/include/android/input.h
@@ -56,6 +56,10 @@
#include <android/keycodes.h>
#include <android/looper.h>
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(__api_level) /* nothing */
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -984,7 +988,7 @@
#if __ANDROID_API__ >= 14
/** Get the button state of all buttons that are pressed. */
-int32_t AMotionEvent_getButtonState(const AInputEvent* motion_event);
+int32_t AMotionEvent_getButtonState(const AInputEvent* motion_event) __INTRODUCED_IN(14);
#endif
/**
@@ -1056,7 +1060,7 @@
* The tool type indicates the type of tool used to make contact such as a
* finger or stylus, if known.
*/
-int32_t AMotionEvent_getToolType(const AInputEvent* motion_event, size_t pointer_index);
+int32_t AMotionEvent_getToolType(const AInputEvent* motion_event, size_t pointer_index) __INTRODUCED_IN(14);
#endif
/**
@@ -1150,7 +1154,7 @@
#if __ANDROID_API__ >= 13
/** Get the value of the request axis for the given pointer index. */
float AMotionEvent_getAxisValue(const AInputEvent* motion_event,
- int32_t axis, size_t pointer_index);
+ int32_t axis, size_t pointer_index) __INTRODUCED_IN(13);
#endif
/**
@@ -1288,7 +1292,7 @@
* that occurred between this event and the previous motion event.
*/
float AMotionEvent_getHistoricalAxisValue(const AInputEvent* motion_event,
- int32_t axis, size_t pointer_index, size_t history_index);
+ int32_t axis, size_t pointer_index, size_t history_index) __INTRODUCED_IN(13);
#endif
diff --git a/include/android/multinetwork.h b/include/android/multinetwork.h
index 97892f8..4d24680 100644
--- a/include/android/multinetwork.h
+++ b/include/android/multinetwork.h
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+/**
+ * @addtogroup Networking
+ * @{
+ */
+
+/**
+ * @file multinetwork.h
+ */
+
#ifndef ANDROID_MULTINETWORK_H
#define ANDROID_MULTINETWORK_H
@@ -51,7 +60,7 @@
* on failure with an appropriate errno value set.
*/
-#if __ANDROID_API__ >= 24
+#if __ANDROID_API__ >= 23
/**
* Set the network to be used by the given socket file descriptor.
@@ -61,7 +70,7 @@
* This is the equivalent of: [android.net.Network#bindSocket()](https://developer.android.com/reference/android/net/Network.html#bindSocket(java.net.Socket))
*
*/
-int android_setsocknetwork(net_handle_t network, int fd);
+int android_setsocknetwork(net_handle_t network, int fd) __INTRODUCED_IN(23);
/**
@@ -78,7 +87,7 @@
* This is the equivalent of: [android.net.ConnectivityManager#setProcessDefaultNetwork()](https://developer.android.com/reference/android/net/ConnectivityManager.html#setProcessDefaultNetwork(android.net.Network))
*
*/
-int android_setprocnetwork(net_handle_t network);
+int android_setprocnetwork(net_handle_t network) __INTRODUCED_IN(23);
/**
@@ -97,10 +106,12 @@
*/
int android_getaddrinfofornetwork(net_handle_t network,
const char *node, const char *service,
- const struct addrinfo *hints, struct addrinfo **res);
+ const struct addrinfo *hints, struct addrinfo **res) __INTRODUCED_IN(23);
-#endif /* __ANDROID_API__ >= 24 */
+#endif /* __ANDROID_API__ >= 23 */
__END_DECLS
#endif // ANDROID_MULTINETWORK_H
+
+/** @} */
diff --git a/include/android/native_window_jni.h b/include/android/native_window_jni.h
index 23b39aa..0c196b9 100644
--- a/include/android/native_window_jni.h
+++ b/include/android/native_window_jni.h
@@ -44,16 +44,6 @@
*/
ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface);
-#if __ANDROID_API__ >= 13
-/**
- * Return the ANativeWindow associated with a Java SurfaceTexture object,
- * for interacting with it through native code. This acquires a reference
- * on the ANativeWindow that is returned; be sure to use ANativeWindow_release()
- * when done with it so that it doesn't leak.
- */
-ANativeWindow* ANativeWindow_fromSurfaceTexture(JNIEnv* env, jobject surfaceTexture);
-#endif
-
#if __ANDROID_API__ >= 26
/**
* Return a Java Surface object derived from the ANativeWindow, for interacting
@@ -62,7 +52,7 @@
* and will automatically release the reference when the Java object gets garbage
* collected.
*/
-jobject ANativeWindow_toSurface(JNIEnv* env, ANativeWindow* window);
+jobject ANativeWindow_toSurface(JNIEnv* env, ANativeWindow* window) __INTRODUCED_IN(26);
#endif
#ifdef __cplusplus
diff --git a/include/android/sensor.h b/include/android/sensor.h
index 191777c..005564d 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -472,13 +472,13 @@
* ASensorManager* sensorManager = ASensorManager_getInstance();
*
*/
-#if __ANDROID_API__ >= __ANDROID_API_O__
+#if __ANDROID_API__ >= 26
__attribute__ ((deprecated)) ASensorManager* ASensorManager_getInstance();
#else
ASensorManager* ASensorManager_getInstance();
#endif
-#if __ANDROID_API__ >= __ANDROID_API_O__
+#if __ANDROID_API__ >= 26
/**
* Get a reference to the sensor manager. ASensorManager is a singleton
* per package as different packages may have access to different sensors.
@@ -488,7 +488,7 @@
* ASensorManager* sensorManager = ASensorManager_getInstanceForPackage("foo.bar.baz");
*
*/
-ASensorManager* ASensorManager_getInstanceForPackage(const char* packageName);
+ASensorManager* ASensorManager_getInstanceForPackage(const char* packageName) __INTRODUCED_IN(26);
#endif
/**
@@ -507,7 +507,7 @@
* Returns the default sensor with the given type and wakeUp properties or NULL if no sensor
* of this type and wakeUp properties exists.
*/
-ASensor const* ASensorManager_getDefaultSensorEx(ASensorManager* manager, int type, bool wakeUp);
+ASensor const* ASensorManager_getDefaultSensorEx(ASensorManager* manager, int type, bool wakeUp) __INTRODUCED_IN(21);
#endif
/**
@@ -525,7 +525,7 @@
*/
int ASensorManager_destroyEventQueue(ASensorManager* manager, ASensorEventQueue* queue);
-#if __ANDROID_API__ >= __ANDROID_API_O__
+#if __ANDROID_API__ >= 26
/**
* Create direct channel based on shared memory
*
@@ -542,7 +542,7 @@
* {@link ASensorManager_destroyDirectChannel} and
* {@link ASensorManager_configureDirectReport}, or value less or equal to 0 for failures.
*/
-int ASensorManager_createSharedMemoryDirectChannel(ASensorManager* manager, int fd, size_t size);
+int ASensorManager_createSharedMemoryDirectChannel(ASensorManager* manager, int fd, size_t size) __INTRODUCED_IN(26);
/**
* Create direct channel based on AHardwareBuffer
@@ -560,7 +560,7 @@
* {@link ASensorManager_configureDirectReport}, or value less or equal to 0 for failures.
*/
int ASensorManager_createHardwareBufferDirectChannel(
- ASensorManager* manager, AHardwareBuffer const * buffer, size_t size);
+ ASensorManager* manager, AHardwareBuffer const * buffer, size_t size) __INTRODUCED_IN(26);
/**
* Destroy a direct channel
@@ -575,7 +575,7 @@
* {@link ASensorManager_createSharedMemoryDirectChannel} or
* {@link ASensorManager_createHardwareBufferDirectChannel}.
*/
-void ASensorManager_destroyDirectChannel(ASensorManager* manager, int channelId);
+void ASensorManager_destroyDirectChannel(ASensorManager* manager, int channelId) __INTRODUCED_IN(26);
/**
* Configure direct report on channel
@@ -612,9 +612,9 @@
*
* \return positive token for success or negative error code.
*/
-int ASensorManager_configureDirectReport(
- ASensorManager* manager, ASensor const* sensor, int channelId, int rate);
-#endif
+int ASensorManager_configureDirectReport(ASensorManager* manager,
+ ASensor const* sensor, int channelId, int rate) __INTRODUCED_IN(26);
+#endif /* __ANDROID_API__ >= 26 */
/*****************************************************************************/
@@ -738,30 +738,30 @@
* Returns the maximum size of batches for this sensor. Batches will often be
* smaller, as the hardware fifo might be used for other sensors.
*/
-int ASensor_getFifoMaxEventCount(ASensor const* sensor);
+int ASensor_getFifoMaxEventCount(ASensor const* sensor) __INTRODUCED_IN(21);
/**
* Returns the hardware batch fifo size reserved to this sensor.
*/
-int ASensor_getFifoReservedEventCount(ASensor const* sensor);
+int ASensor_getFifoReservedEventCount(ASensor const* sensor) __INTRODUCED_IN(21);
/**
* Returns this sensor's string type.
*/
-const char* ASensor_getStringType(ASensor const* sensor);
+const char* ASensor_getStringType(ASensor const* sensor) __INTRODUCED_IN(21);
/**
* Returns the reporting mode for this sensor. One of AREPORTING_MODE_* constants.
*/
-int ASensor_getReportingMode(ASensor const* sensor);
+int ASensor_getReportingMode(ASensor const* sensor) __INTRODUCED_IN(21);
/**
* Returns true if this is a wake up sensor, false otherwise.
*/
-bool ASensor_isWakeUpSensor(ASensor const* sensor);
+bool ASensor_isWakeUpSensor(ASensor const* sensor) __INTRODUCED_IN(21);
#endif /* __ANDROID_API__ >= 21 */
-#if __ANDROID_API__ >= __ANDROID_API_O__
+#if __ANDROID_API__ >= 26
/**
* Test if sensor supports a certain type of direct channel.
*
@@ -771,7 +771,8 @@
* or {@link ASENSOR_DIRECT_CHANNEL_TYPE_HARDWARE_BUFFER}.
* \returns true if sensor supports the specified direct channel type.
*/
-bool ASensor_isDirectChannelTypeSupported(ASensor const* sensor, int channelType);
+bool ASensor_isDirectChannelTypeSupported(ASensor const* sensor, int channelType) __INTRODUCED_IN(26);
+
/**
* Get the highest direct rate level that a sensor support.
*
@@ -781,8 +782,8 @@
* If return value is {@link ASENSOR_DIRECT_RATE_STOP}, it means the sensor
* does not support direct report.
*/
-int ASensor_getHighestDirectReportRateLevel(ASensor const* sensor);
-#endif
+int ASensor_getHighestDirectReportRateLevel(ASensor const* sensor) __INTRODUCED_IN(26);
+#endif /* __ANDROID_API__ >= 26 */
#ifdef __cplusplus
};
diff --git a/include/android/sharedmem.h b/include/android/sharedmem.h
index 46d2f4b..7f5177b 100644
--- a/include/android/sharedmem.h
+++ b/include/android/sharedmem.h
@@ -21,12 +21,14 @@
/**
* @file sharedmem.h
+ * @brief Shared memory buffers that can be shared across process.
*/
#ifndef ANDROID_SHARED_MEMORY_H
#define ANDROID_SHARED_MEMORY_H
#include <stddef.h>
+#include <sys/cdefs.h>
/******************************************************************
*
@@ -44,15 +46,11 @@
* - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
*/
-/**
- * Structures and functions for a shared memory buffer that can be shared across process.
- */
-
#ifdef __cplusplus
extern "C" {
#endif
-#if __ANDROID_API__ >= __ANDROID_API_O__
+#if __ANDROID_API__ >= 26
/**
* Create a shared memory region.
@@ -63,19 +61,23 @@
*
* Use close() to release the shared memory region.
*
+ * Available since API level 26.
+ *
* \param name an optional name.
* \param size size of the shared memory region
* \return file descriptor that denotes the shared memory; error code on failure.
*/
-int ASharedMemory_create(const char *name, size_t size);
+int ASharedMemory_create(const char *name, size_t size) __INTRODUCED_IN(26);
/**
* Get the size of the shared memory region.
*
+ * Available since API level 26.
+ *
* \param fd file descriptor of the shared memory region
* \return size in bytes; 0 if fd is not a valid shared memory file descriptor.
*/
-size_t ASharedMemory_getSize(int fd);
+size_t ASharedMemory_getSize(int fd) __INTRODUCED_IN(26);
/**
* Restrict access of shared memory region.
@@ -92,7 +94,8 @@
* int fd = ASharedMemory_create("memory", 128);
*
* // By default it has PROT_READ | PROT_WRITE | PROT_EXEC.
- * char *buffer = (char *) mmap(NULL, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ * size_t memSize = ASharedMemory_getSize(fd);
+ * char *buffer = (char *) mmap(NULL, memSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
*
* strcpy(buffer, "This is an example."); // trivially initialize content
*
@@ -101,14 +104,16 @@
*
* // share fd with another process here and the other process can only map with PROT_READ.
*
+ * Available since API level 26.
+ *
* \param fd file descriptor of the shared memory region.
* \param prot any bitwise-or'ed combination of PROT_READ, PROT_WRITE, PROT_EXEC denoting
* updated access. Note access can only be removed, but not added back.
* \return 0 for success, error code on failure.
*/
-int ASharedMemory_setProt(int fd, int prot);
+int ASharedMemory_setProt(int fd, int prot) __INTRODUCED_IN(26);
-#endif
+#endif // __ANDROID_API__ >= 26
#ifdef __cplusplus
};
diff --git a/include/android/sharedmem_jni.h b/include/android/sharedmem_jni.h
index 85ac78f..13e56e6 100644
--- a/include/android/sharedmem_jni.h
+++ b/include/android/sharedmem_jni.h
@@ -21,6 +21,7 @@
/**
* @file sharedmem_jni.h
+ * @brief Shared memory buffers that can be shared across process.
*/
#ifndef ANDROID_SHARED_MEMORY_JNI_H
@@ -29,6 +30,7 @@
#include <jni.h>
#include <android/sharedmem.h>
#include <stddef.h>
+#include <sys/cdefs.h>
/******************************************************************
*
@@ -46,15 +48,11 @@
* - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
*/
-/**
- * Structures and functions for a shared memory buffer that can be shared across process.
- */
-
#ifdef __cplusplus
extern "C" {
#endif
-#if __ANDROID_API__ >= __ANDROID_API_O_MR1__
+#if __ANDROID_API__ >= 27
/**
* Returns a dup'd FD from the given Java android.os.SharedMemory object. The returned file
@@ -64,15 +62,17 @@
*
* Use close() to release the shared memory region.
*
+ * Available since API level 27.
+ *
* \param env The JNIEnv* pointer
* \param sharedMemory The Java android.os.SharedMemory object
* \return file descriptor that denotes the shared memory; -1 if the shared memory object is
* already closed, if the JNIEnv or jobject is NULL, or if there are too many open file
* descriptors (errno=EMFILE)
*/
-int ASharedMemory_dupFromJava(JNIEnv* env, jobject sharedMemory);
+int ASharedMemory_dupFromJava(JNIEnv* env, jobject sharedMemory) __INTRODUCED_IN(27);
-#endif
+#endif // __ANDROID_API__ >= 27
#ifdef __cplusplus
};
diff --git a/include/android/surface_texture.h b/include/android/surface_texture.h
index 56b3342..540d23a 100644
--- a/include/android/surface_texture.h
+++ b/include/android/surface_texture.h
@@ -43,6 +43,7 @@
*/
#include <stdint.h>
+#include <sys/cdefs.h>
#include <android/native_window.h>
@@ -58,13 +59,15 @@
*/
typedef struct ASurfaceTexture ASurfaceTexture;
+#if __ANDROID_API__ >= 28
+
/**
* Release the reference to the native ASurfaceTexture acquired with
* ASurfaceTexture_fromSurfaceTexture().
* Failing to do so will result in leaked memory and graphic resources.
* \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
*/
-void ASurfaceTexture_release(ASurfaceTexture* st);
+void ASurfaceTexture_release(ASurfaceTexture* st) __INTRODUCED_IN(28);
/**
* Returns a reference to an ANativeWindow (i.e. the Producer) for this SurfaceTexture.
@@ -73,9 +76,9 @@
* \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
* @return A reference to an ANativeWindow. This reference MUST BE released when no longer needed
* using ANativeWindow_release(). Failing to do so will result in leaked resources. nullptr is
- * returned if \st is null or if it's not an instance of android.graphics.SurfaceTexture
+ * returned if \p st is null or if it's not an instance of android.graphics.SurfaceTexture
*/
-ANativeWindow* ASurfaceTexture_acquireANativeWindow(ASurfaceTexture* st);
+ANativeWindow* ASurfaceTexture_acquireANativeWindow(ASurfaceTexture* st) __INTRODUCED_IN(28);
/**
* Attach the SurfaceTexture to the OpenGL ES context that is current on the calling thread. A
@@ -92,7 +95,7 @@
* must be unusued in the OpenGL ES context that is current on the calling thread.
* \return 0 on success, negative posix error code otherwise (see <errno.h>)
*/
-int ASurfaceTexture_attachToGLContext(ASurfaceTexture* st, uint32_t texName);
+int ASurfaceTexture_attachToGLContext(ASurfaceTexture* st, uint32_t texName) __INTRODUCED_IN(28);
/**
* Detach the SurfaceTexture from the OpenGL ES context that owns the OpenGL ES texture object.
@@ -108,7 +111,7 @@
* \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
* \return 0 on success, negative posix error code otherwise (see <errno.h>)
*/
-int ASurfaceTexture_detachFromGLContext(ASurfaceTexture* st);
+int ASurfaceTexture_detachFromGLContext(ASurfaceTexture* st) __INTRODUCED_IN(28);
/**
* Update the texture image to the most recent frame from the image stream. This may only be
@@ -118,7 +121,7 @@
* \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
* \return 0 on success, negative posix error code otherwise (see <errno.h>)
*/
-int ASurfaceTexture_updateTexImage(ASurfaceTexture* st);
+int ASurfaceTexture_updateTexImage(ASurfaceTexture* st) __INTRODUCED_IN(28);
/**
* Retrieve the 4x4 texture coordinate transform matrix associated with the texture image set by
@@ -136,7 +139,7 @@
* \param mtx the array into which the 4x4 matrix will be stored. The array must have exactly
* 16 elements.
*/
-void ASurfaceTexture_getTransformMatrix(ASurfaceTexture* st, float mtx[16]);
+void ASurfaceTexture_getTransformMatrix(ASurfaceTexture* st, float mtx[16]) __INTRODUCED_IN(28);
/**
* Retrieve the timestamp associated with the texture image set by the most recent call to
@@ -155,7 +158,9 @@
*
* \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
*/
-int64_t ASurfaceTexture_getTimestamp(ASurfaceTexture* st);
+int64_t ASurfaceTexture_getTimestamp(ASurfaceTexture* st) __INTRODUCED_IN(28);
+
+#endif /* __ANDROID_API__ >= 28 */
__END_DECLS
diff --git a/include/android/trace.h b/include/android/trace.h
index d3b1fb6..aa24995 100644
--- a/include/android/trace.h
+++ b/include/android/trace.h
@@ -15,11 +15,18 @@
*/
/**
+ * @addtogroup Tracing
+ * @{
+ */
+
+/**
* @file trace.h
* @brief Writes trace events to the system trace buffer.
*
* These trace events can be collected and visualized using the Systrace tool.
* For information about using the Systrace tool, read <a href="https://developer.android.com/studio/profile/systrace.html">Analyzing UI Performance with Systrace</a>.
+ *
+ * Available since API level 23.
*/
#ifndef ANDROID_NATIVE_TRACE_H
@@ -35,28 +42,34 @@
#if __ANDROID_API__ >= 23
/**
- * Returns true if tracing is enabled. Use this signal to avoid expensive computation only necessary
+ * Returns true if tracing is enabled. Use this to avoid expensive computation only necessary
* when tracing is enabled.
+ *
+ * Available since API level 23.
*/
-bool ATrace_isEnabled();
+bool ATrace_isEnabled() __INTRODUCED_IN(23);
/**
* Writes a tracing message to indicate that the given section of code has begun. This call must be
- * followed by a corresponding call to endSection() on the same thread.
+ * followed by a corresponding call to {@link ATrace_endSection} on the same thread.
*
- * Note: At this time the vertical bar character '|' and newline character '\n' are used internally
- * by the tracing mechanism. If sectionName contains these characters they will be replaced with a
+ * Note: At this time the vertical bar character '|' and newline character '\\n' are used internally
+ * by the tracing mechanism. If \p sectionName contains these characters they will be replaced with a
* space character in the trace.
+ *
+ * Available since API level 23.
*/
-void ATrace_beginSection(const char* sectionName);
+void ATrace_beginSection(const char* sectionName) __INTRODUCED_IN(23);
/**
* Writes a tracing message to indicate that a given section of code has ended. This call must be
- * preceeded by a corresponding call to beginSection(char*) on the same thread. Calling this method
+ * preceeded by a corresponding call to {@link ATrace_beginSection} on the same thread. Calling this method
* will mark the end of the most recently begun section of code, so care must be taken to ensure
- * that beginSection / endSection pairs are properly nested and called from the same thread.
+ * that {@link ATrace_beginSection}/{@link ATrace_endSection} pairs are properly nested and called from the same thread.
+ *
+ * Available since API level 23.
*/
-void ATrace_endSection();
+void ATrace_endSection() __INTRODUCED_IN(23);
#endif /* __ANDROID_API__ >= 23 */
@@ -65,3 +78,5 @@
#endif
#endif // ANDROID_NATIVE_TRACE_H
+
+/** @} */
diff --git a/include/batteryservice b/include/batteryservice
deleted file mode 120000
index 2178c32..0000000
--- a/include/batteryservice
+++ /dev/null
@@ -1 +0,0 @@
-../services/batteryservice/include/batteryservice/
\ No newline at end of file
diff --git a/libs/binder/ActivityManager.cpp b/libs/binder/ActivityManager.cpp
index 2728f35..28d0e4f 100644
--- a/libs/binder/ActivityManager.cpp
+++ b/libs/binder/ActivityManager.cpp
@@ -34,16 +34,16 @@
std::lock_guard<Mutex> scoped_lock(mLock);
int64_t startTime = 0;
sp<IActivityManager> service = mService;
- while (service == NULL || !IInterface::asBinder(service)->isBinderAlive()) {
+ while (service == nullptr || !IInterface::asBinder(service)->isBinderAlive()) {
sp<IBinder> binder = defaultServiceManager()->checkService(String16("activity"));
- if (binder == NULL) {
+ if (binder == nullptr) {
// Wait for the activity service to come back...
if (startTime == 0) {
startTime = uptimeMillis();
ALOGI("Waiting for activity service");
} else if ((uptimeMillis() - startTime) > 1000000) {
ALOGW("Waiting too long for activity service, giving up");
- service = NULL;
+ service = nullptr;
break;
}
usleep(25000);
@@ -58,7 +58,7 @@
int ActivityManager::openContentUri(const String16& stringUri)
{
sp<IActivityManager> service = getService();
- return service != NULL ? service->openContentUri(stringUri) : -1;
+ return service != nullptr ? service->openContentUri(stringUri) : -1;
}
void ActivityManager::registerUidObserver(const sp<IUidObserver>& observer,
@@ -67,7 +67,7 @@
const String16& callingPackage)
{
sp<IActivityManager> service = getService();
- if (service != NULL) {
+ if (service != nullptr) {
service->registerUidObserver(observer, event, cutpoint, callingPackage);
}
}
@@ -75,7 +75,7 @@
void ActivityManager::unregisterUidObserver(const sp<IUidObserver>& observer)
{
sp<IActivityManager> service = getService();
- if (service != NULL) {
+ if (service != nullptr) {
service->unregisterUidObserver(observer);
}
}
@@ -83,7 +83,7 @@
bool ActivityManager::isUidActive(const uid_t uid, const String16& callingPackage)
{
sp<IActivityManager> service = getService();
- if (service != NULL) {
+ if (service != nullptr) {
return service->isUidActive(uid, callingPackage);
}
return false;
@@ -91,7 +91,7 @@
status_t ActivityManager::linkToDeath(const sp<IBinder::DeathRecipient>& recipient) {
sp<IActivityManager> service = getService();
- if (service != NULL) {
+ if (service != nullptr) {
return IInterface::asBinder(service)->linkToDeath(recipient);
}
return INVALID_OPERATION;
@@ -99,7 +99,7 @@
status_t ActivityManager::unlinkToDeath(const sp<IBinder::DeathRecipient>& recipient) {
sp<IActivityManager> service = getService();
- if (service != NULL) {
+ if (service != nullptr) {
return IInterface::asBinder(service)->unlinkToDeath(recipient);
}
return INVALID_OPERATION;
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 7c1eaaf..da10687 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -28,7 +28,7 @@
],
}
-cc_library {
+cc_library_shared {
name: "libbinder",
// for vndbinder
@@ -36,6 +36,7 @@
vndk: {
enabled: true,
},
+ double_loadable: true,
srcs: [
"ActivityManager.cpp",
@@ -62,6 +63,7 @@
"MemoryDealer.cpp",
"MemoryHeapBase.cpp",
"Parcel.cpp",
+ "ParcelFileDescriptor.cpp",
"PermissionCache.cpp",
"PermissionController.cpp",
"PersistableBundle.cpp",
@@ -117,7 +119,7 @@
"liblog",
"libcutils",
"libutils",
- "libutilscallstack",
+ "libbinderthreadstate",
],
header_libs: [
diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp
index 62c8987..a494e22 100644
--- a/libs/binder/AppOpsManager.cpp
+++ b/libs/binder/AppOpsManager.cpp
@@ -42,7 +42,7 @@
static const sp<IBinder>& getToken(const sp<IAppOpsService>& service) {
pthread_mutex_lock(&gTokenMutex);
- if (gToken == NULL || gToken->pingBinder() != NO_ERROR) {
+ if (gToken == nullptr || gToken->pingBinder() != NO_ERROR) {
gToken = service->getToken(new BBinder());
}
pthread_mutex_unlock(&gTokenMutex);
@@ -63,16 +63,16 @@
std::lock_guard<Mutex> scoped_lock(mLock);
int64_t startTime = 0;
sp<IAppOpsService> service = mService;
- while (service == NULL || !IInterface::asBinder(service)->isBinderAlive()) {
+ while (service == nullptr || !IInterface::asBinder(service)->isBinderAlive()) {
sp<IBinder> binder = defaultServiceManager()->checkService(_appops);
- if (binder == NULL) {
+ if (binder == nullptr) {
// Wait for the app ops service to come back...
if (startTime == 0) {
startTime = uptimeMillis();
ALOGI("Waiting for app ops service");
} else if ((uptimeMillis()-startTime) > 10000) {
ALOGW("Waiting too long for app ops service, giving up");
- service = NULL;
+ service = nullptr;
break;
}
sleep(1);
@@ -88,14 +88,14 @@
int32_t AppOpsManager::checkOp(int32_t op, int32_t uid, const String16& callingPackage)
{
sp<IAppOpsService> service = getService();
- return service != NULL
+ return service != nullptr
? service->checkOperation(op, uid, callingPackage)
: APP_OPS_MANAGER_UNAVAILABLE_MODE;
}
int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage) {
sp<IAppOpsService> service = getService();
- return service != NULL
+ return service != nullptr
? service->noteOperation(op, uid, callingPackage)
: APP_OPS_MANAGER_UNAVAILABLE_MODE;
}
@@ -103,14 +103,14 @@
int32_t AppOpsManager::startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
bool startIfModeDefault) {
sp<IAppOpsService> service = getService();
- return service != NULL
+ return service != nullptr
? service->startOperation(getToken(service), op, uid, callingPackage,
startIfModeDefault) : APP_OPS_MANAGER_UNAVAILABLE_MODE;
}
void AppOpsManager::finishOp(int32_t op, int32_t uid, const String16& callingPackage) {
sp<IAppOpsService> service = getService();
- if (service != NULL) {
+ if (service != nullptr) {
service->finishOperation(getToken(service), op, uid, callingPackage);
}
}
@@ -118,21 +118,21 @@
void AppOpsManager::startWatchingMode(int32_t op, const String16& packageName,
const sp<IAppOpsCallback>& callback) {
sp<IAppOpsService> service = getService();
- if (service != NULL) {
+ if (service != nullptr) {
service->startWatchingMode(op, packageName, callback);
}
}
void AppOpsManager::stopWatchingMode(const sp<IAppOpsCallback>& callback) {
sp<IAppOpsService> service = getService();
- if (service != NULL) {
+ if (service != nullptr) {
service->stopWatchingMode(callback);
}
}
int32_t AppOpsManager::permissionToOpCode(const String16& permission) {
sp<IAppOpsService> service = getService();
- if (service != NULL) {
+ if (service != nullptr) {
return service->permissionToOpCode(permission);
}
return -1;
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index a81f44e..1bd7c4f 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -43,17 +43,17 @@
sp<IInterface> IBinder::queryLocalInterface(const String16& /*descriptor*/)
{
- return NULL;
+ return nullptr;
}
BBinder* IBinder::localBinder()
{
- return NULL;
+ return nullptr;
}
BpBinder* IBinder::remoteBinder()
{
- return NULL;
+ return nullptr;
}
bool IBinder::checkSubclass(const void* /*subclassID*/) const
@@ -76,8 +76,8 @@
for (size_t i = 0; i < numArgs; i++) {
send.writeString16(args[i]);
}
- send.writeStrongBinder(callback != NULL ? IInterface::asBinder(callback) : NULL);
- send.writeStrongBinder(resultReceiver != NULL ? IInterface::asBinder(resultReceiver) : NULL);
+ send.writeStrongBinder(callback != nullptr ? IInterface::asBinder(callback) : nullptr);
+ send.writeStrongBinder(resultReceiver != nullptr ? IInterface::asBinder(resultReceiver) : nullptr);
return target->transact(SHELL_COMMAND_TRANSACTION, send, &reply);
}
@@ -130,7 +130,7 @@
break;
}
- if (reply != NULL) {
+ if (reply != nullptr) {
reply->setDataPosition(0);
}
@@ -171,7 +171,7 @@
delete e;
e = expected; // Filled in by CAS
}
- if (e == 0) return; // out of memory
+ if (e == nullptr) return; // out of memory
}
AutoMutex _l(e->mLock);
@@ -181,7 +181,7 @@
void* BBinder::findObject(const void* objectID) const
{
Extras* e = mExtras.load(std::memory_order_acquire);
- if (!e) return NULL;
+ if (!e) return nullptr;
AutoMutex _l(e->mLock);
return e->mObjects.find(objectID);
@@ -246,7 +246,7 @@
(void)out;
(void)err;
- if (resultReceiver != NULL) {
+ if (resultReceiver != nullptr) {
resultReceiver->send(INVALID_OPERATION);
}
@@ -273,7 +273,7 @@
};
BpRefBase::BpRefBase(const sp<IBinder>& o)
- : mRemote(o.get()), mRefs(NULL), mState(0)
+ : mRemote(o.get()), mRefs(nullptr), mState(0)
{
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 449a9e9..7342126 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -80,7 +80,7 @@
void* BpBinder::ObjectManager::find(const void* objectID) const
{
const ssize_t i = mObjects.indexOfKey(objectID);
- if (i < 0) return NULL;
+ if (i < 0) return nullptr;
return mObjects.valueAt(i).object;
}
@@ -95,7 +95,7 @@
ALOGV("Killing %zu objects in manager %p", N, this);
for (size_t i=0; i<N; i++) {
const entry_t& e = mObjects.valueAt(i);
- if (e.func != NULL) {
+ if (e.func != nullptr) {
e.func(mObjects.keyAt(i), e.object, e.cleanupCookie);
}
}
@@ -139,7 +139,7 @@
: mHandle(handle)
, mAlive(1)
, mObitsSent(0)
- , mObituaries(NULL)
+ , mObituaries(nullptr)
, mTrackedUid(trackedUid)
{
ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);
@@ -228,7 +228,7 @@
ob.cookie = cookie;
ob.flags = flags;
- LOG_ALWAYS_FATAL_IF(recipient == NULL,
+ LOG_ALWAYS_FATAL_IF(recipient == nullptr,
"linkToDeath(): recipient must be non-NULL");
{
@@ -268,9 +268,9 @@
for (size_t i=0; i<N; i++) {
const Obituary& obit = mObituaries->itemAt(i);
if ((obit.recipient == recipient
- || (recipient == NULL && obit.cookie == cookie))
+ || (recipient == nullptr && obit.cookie == cookie))
&& obit.flags == flags) {
- if (outRecipient != NULL) {
+ if (outRecipient != nullptr) {
*outRecipient = mObituaries->itemAt(i).recipient;
}
mObituaries->removeAt(i);
@@ -280,7 +280,7 @@
self->clearDeathNotification(mHandle, this);
self->flushCommands();
delete mObituaries;
- mObituaries = NULL;
+ mObituaries = nullptr;
}
return NO_ERROR;
}
@@ -299,12 +299,12 @@
mLock.lock();
Vector<Obituary>* obits = mObituaries;
- if(obits != NULL) {
+ if(obits != nullptr) {
ALOGV("Clearing sent death notification: %p handle %d\n", this, mHandle);
IPCThreadState* self = IPCThreadState::self();
self->clearDeathNotification(mHandle, this);
self->flushCommands();
- mObituaries = NULL;
+ mObituaries = nullptr;
}
mObitsSent = 1;
mLock.unlock();
@@ -312,7 +312,7 @@
ALOGV("Reporting death of proxy %p for %zu recipients\n",
this, obits ? obits->size() : 0U);
- if (obits != NULL) {
+ if (obits != nullptr) {
const size_t N = obits->size();
for (size_t i=0; i<N; i++) {
reportOneDeath(obits->itemAt(i));
@@ -326,7 +326,7 @@
{
sp<DeathRecipient> recipient = obit.recipient.promote();
ALOGV("Reporting death to recipient: %p\n", recipient.get());
- if (recipient == NULL) return;
+ if (recipient == nullptr) return;
recipient->binderDied(this);
}
@@ -386,13 +386,13 @@
mLock.lock();
Vector<Obituary>* obits = mObituaries;
- if(obits != NULL) {
+ if(obits != nullptr) {
if (ipc) ipc->clearDeathNotification(mHandle, this);
- mObituaries = NULL;
+ mObituaries = nullptr;
}
mLock.unlock();
- if (obits != NULL) {
+ if (obits != nullptr) {
// XXX Should we tell any remaining DeathRecipient
// objects that the last strong ref has gone away, so they
// are no longer linked?
diff --git a/libs/binder/BufferedTextOutput.cpp b/libs/binder/BufferedTextOutput.cpp
index 30e70b0..857bbf9 100644
--- a/libs/binder/BufferedTextOutput.cpp
+++ b/libs/binder/BufferedTextOutput.cpp
@@ -25,6 +25,7 @@
#include <private/binder/Static.h>
+#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
@@ -36,7 +37,7 @@
{
explicit BufferState(int32_t _seq)
: seq(_seq)
- , buffer(NULL)
+ , buffer(nullptr)
, bufferPos(0)
, bufferSize(0)
, atFront(true)
@@ -87,7 +88,7 @@
Vector<sp<BufferedTextOutput::BufferState> > states;
};
-static mutex_t gMutex;
+static pthread_mutex_t gMutex = PTHREAD_MUTEX_INITIALIZER;
static thread_store_t tls;
@@ -113,7 +114,7 @@
{
int32_t res = -1;
- mutex_lock(&gMutex);
+ pthread_mutex_lock(&gMutex);
if (gFreeBufferIndex >= 0) {
res = gFreeBufferIndex;
@@ -125,17 +126,17 @@
gTextBuffers.add(-1);
}
- mutex_unlock(&gMutex);
+ pthread_mutex_unlock(&gMutex);
return res;
}
static void freeBufferIndex(int32_t idx)
{
- mutex_lock(&gMutex);
+ pthread_mutex_lock(&gMutex);
gTextBuffers.editItemAt(idx) = gFreeBufferIndex;
gFreeBufferIndex = idx;
- mutex_unlock(&gMutex);
+ pthread_mutex_unlock(&gMutex);
}
// ---------------------------------------------------------------------------
@@ -188,7 +189,7 @@
// them out without going through the buffer.
// Slurp up all of the lines.
- const char* lastLine = txt+1;
+ const char* lastLine = txt;
while (txt < end) {
if (*txt++ == '\n') lastLine = txt;
}
@@ -266,13 +267,13 @@
if ((mFlags&MULTITHREADED) != 0) {
ThreadState* ts = getThreadState();
if (ts) {
- while (ts->states.size() <= (size_t)mIndex) ts->states.add(NULL);
+ while (ts->states.size() <= (size_t)mIndex) ts->states.add(nullptr);
BufferState* bs = ts->states[mIndex].get();
- if (bs != NULL && bs->seq == mSeq) return bs;
+ if (bs != nullptr && bs->seq == mSeq) return bs;
ts->states.editItemAt(mIndex) = new BufferState(mIndex);
bs = ts->states[mIndex].get();
- if (bs != NULL) return bs;
+ if (bs != nullptr) return bs;
}
}
diff --git a/libs/binder/Debug.cpp b/libs/binder/Debug.cpp
index 4ac61a3..f38bbb2 100644
--- a/libs/binder/Debug.cpp
+++ b/libs/binder/Debug.cpp
@@ -165,13 +165,13 @@
else if (bytesPerLine >= 8) alignment = 2;
else alignment = 1;
}
- if (func == NULL) func = defaultPrintFunc;
+ if (func == nullptr) func = defaultPrintFunc;
size_t offset;
unsigned char *pos = (unsigned char *)buf;
- if (pos == NULL) {
+ if (pos == nullptr) {
if (singleLineBytesCutoff < 0) func(cookie, "\n");
func(cookie, "(NULL)");
return;
@@ -297,7 +297,7 @@
ssize_t getBinderKernelReferences(size_t count, uintptr_t* buf) {
sp<ProcessState> proc = ProcessState::selfOrNull();
- if (proc.get() == NULL) {
+ if (proc.get() == nullptr) {
return 0;
}
diff --git a/libs/binder/IAppOpsService.cpp b/libs/binder/IAppOpsService.cpp
index 9c76350..068664b 100644
--- a/libs/binder/IAppOpsService.cpp
+++ b/libs/binder/IAppOpsService.cpp
@@ -109,7 +109,7 @@
data.writeStrongBinder(clientToken);
remote()->transact(GET_TOKEN_TRANSACTION, data, &reply);
// fail on exception
- if (reply.readExceptionCode() != 0) return NULL;
+ if (reply.readExceptionCode() != 0) return nullptr;
return reply.readStrongBinder();
}
diff --git a/libs/binder/IInterface.cpp b/libs/binder/IInterface.cpp
index 2fcd3d9..6b77291 100644
--- a/libs/binder/IInterface.cpp
+++ b/libs/binder/IInterface.cpp
@@ -32,14 +32,14 @@
// static
sp<IBinder> IInterface::asBinder(const IInterface* iface)
{
- if (iface == NULL) return NULL;
+ if (iface == nullptr) return nullptr;
return const_cast<IInterface*>(iface)->onAsBinder();
}
// static
sp<IBinder> IInterface::asBinder(const sp<IInterface>& iface)
{
- if (iface == NULL) return NULL;
+ if (iface == nullptr) return nullptr;
return iface->onAsBinder();
}
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index 5c1a4f4..507ce53 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -31,7 +31,6 @@
#include <binder/Parcel.h>
#include <log/log.h>
-#include <utils/CallStack.h>
#include <utils/KeyedVector.h>
#include <utils/threads.h>
@@ -130,7 +129,7 @@
public:
explicit BpMemory(const sp<IBinder>& impl);
virtual ~BpMemory();
- virtual sp<IMemoryHeap> getMemory(ssize_t* offset=0, size_t* size=0) const;
+ virtual sp<IMemoryHeap> getMemory(ssize_t* offset=nullptr, size_t* size=nullptr) const;
private:
mutable sp<IMemoryHeap> mHeap;
@@ -145,22 +144,22 @@
sp<IMemoryHeap> realHeap = BpMemoryHeap::get_heap(binder);
void* const base = realHeap->base();
if (base == MAP_FAILED)
- return 0;
+ return nullptr;
return static_cast<char*>(base) + offset;
}
void* IMemory::pointer() const {
ssize_t offset;
sp<IMemoryHeap> heap = getMemory(&offset);
- void* const base = heap!=0 ? heap->base() : MAP_FAILED;
+ void* const base = heap!=nullptr ? heap->base() : MAP_FAILED;
if (base == MAP_FAILED)
- return 0;
+ return nullptr;
return static_cast<char*>(base) + offset;
}
size_t IMemory::size() const {
size_t size;
- getMemory(NULL, &size);
+ getMemory(nullptr, &size);
return size;
}
@@ -183,16 +182,16 @@
sp<IMemoryHeap> BpMemory::getMemory(ssize_t* offset, size_t* size) const
{
- if (mHeap == 0) {
+ if (mHeap == nullptr) {
Parcel data, reply;
data.writeInterfaceToken(IMemory::getInterfaceDescriptor());
if (remote()->transact(GET_MEMORY, data, &reply) == NO_ERROR) {
sp<IBinder> heap = reply.readStrongBinder();
ssize_t o = reply.readInt32();
size_t s = reply.readInt32();
- if (heap != 0) {
+ if (heap != nullptr) {
mHeap = interface_cast<IMemoryHeap>(heap);
- if (mHeap != 0) {
+ if (mHeap != nullptr) {
size_t heapSize = mHeap->getSize();
if (s <= heapSize
&& o >= 0
@@ -202,7 +201,7 @@
} else {
// Hm.
android_errorWriteWithInfoLog(0x534e4554,
- "26877992", -1, NULL, 0);
+ "26877992", -1, nullptr, 0);
mOffset = 0;
mSize = 0;
}
@@ -212,7 +211,7 @@
}
if (offset) *offset = mOffset;
if (size) *size = mSize;
- return (mSize > 0) ? mHeap : 0;
+ return (mSize > 0) ? mHeap : nullptr;
}
// ---------------------------------------------------------------------------
@@ -264,7 +263,6 @@
if (VERBOSE) {
ALOGD("UNMAPPING binder=%p, heap=%p, size=%zu, fd=%d",
binder.get(), this, mSize, heapId);
- CallStack stack(LOG_TAG);
}
munmap(mBase, mSize);
@@ -334,7 +332,7 @@
access |= PROT_WRITE;
}
mRealHeap = true;
- mBase = mmap(0, size, access, MAP_SHARED, fd, offset);
+ mBase = mmap(nullptr, size, access, MAP_SHARED, fd, offset);
if (mBase == MAP_FAILED) {
ALOGE("cannot map BpMemoryHeap (binder=%p), size=%zd, fd=%d (%s)",
IInterface::asBinder(this).get(), size, fd, strerror(errno));
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index fd552b4..f052bcb 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "IPCThreadState"
#include <binder/IPCThreadState.h>
+#include <binderthreadstate/IPCThreadStateBase.h>
#include <binder/Binder.h>
#include <binder/BpBinder.h>
@@ -289,7 +290,7 @@
if (gShutdown) {
ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
- return NULL;
+ return nullptr;
}
pthread_mutex_lock(&gTLSMutex);
@@ -299,7 +300,7 @@
pthread_mutex_unlock(&gTLSMutex);
ALOGW("IPCThreadState::self() unable to create TLS key, expect a crash: %s\n",
strerror(key_create_value));
- return NULL;
+ return nullptr;
}
gHaveTLS = true;
}
@@ -314,7 +315,7 @@
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
return st;
}
- return NULL;
+ return nullptr;
}
void IPCThreadState::shutdown()
@@ -326,7 +327,7 @@
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(gTLS);
if (st) {
delete st;
- pthread_setspecific(gTLS, NULL);
+ pthread_setspecific(gTLS, nullptr);
}
pthread_key_delete(gTLS);
gHaveTLS = false;
@@ -608,7 +609,7 @@
LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),
(flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");
- err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
+ err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr);
if (err != NO_ERROR) {
if (reply) reply->setError(err);
@@ -645,7 +646,7 @@
else alog << "(none requested)" << endl;
}
} else {
- err = waitForResponse(NULL, NULL);
+ err = waitForResponse(nullptr, nullptr);
}
return err;
@@ -742,6 +743,7 @@
clearCaller();
mIn.setDataCapacity(256);
mOut.setDataCapacity(256);
+ mIPCThreadStateBase = IPCThreadStateBase::self();
}
IPCThreadState::~IPCThreadState()
@@ -755,7 +757,7 @@
err = writeTransactionData(BC_REPLY, flags, -1, 0, reply, &statusBuffer);
if (err < NO_ERROR) return err;
- return waitForResponse(NULL, NULL);
+ return waitForResponse(nullptr, nullptr);
}
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
@@ -815,14 +817,14 @@
freeBuffer, this);
} else {
err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer);
- freeBuffer(NULL,
+ freeBuffer(nullptr,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), this);
}
} else {
- freeBuffer(NULL,
+ freeBuffer(nullptr,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
@@ -1082,6 +1084,9 @@
"Not enough command data for brTRANSACTION");
if (result != NO_ERROR) break;
+ //Record the fact that we're in a binder call.
+ mIPCThreadStateBase->pushCurrentState(
+ IPCThreadStateBase::CallState::BINDER);
Parcel buffer;
buffer.ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
@@ -1129,6 +1134,7 @@
error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
}
+ mIPCThreadStateBase->popCurrentState();
//ALOGI("<<<< TRANSACT from pid %d restore pid %d uid %d\n",
// mCallingPid, origPid, origUid);
@@ -1192,6 +1198,10 @@
return result;
}
+bool IPCThreadState::isServingCall() const {
+ return mIPCThreadStateBase->getCurrentBinderCallState() == IPCThreadStateBase::CallState::BINDER;
+}
+
void IPCThreadState::threadDestructor(void *st)
{
IPCThreadState* const self = static_cast<IPCThreadState*>(st);
@@ -1217,7 +1227,7 @@
alog << "Writing BC_FREE_BUFFER for " << data << endl;
}
ALOG_ASSERT(data != NULL, "Called with NULL data");
- if (parcel != NULL) parcel->closeFileDescriptors();
+ if (parcel != nullptr) parcel->closeFileDescriptors();
IPCThreadState* state = self();
state->mOut.writeInt32(BC_FREE_BUFFER);
state->mOut.writePointer((uintptr_t)data);
diff --git a/libs/binder/IResultReceiver.cpp b/libs/binder/IResultReceiver.cpp
index 646809e..14b5259 100644
--- a/libs/binder/IResultReceiver.cpp
+++ b/libs/binder/IResultReceiver.cpp
@@ -40,7 +40,7 @@
Parcel data;
data.writeInterfaceToken(IResultReceiver::getInterfaceDescriptor());
data.writeInt32(resultCode);
- remote()->transact(OP_SEND, data, NULL, IBinder::FLAG_ONEWAY);
+ remote()->transact(OP_SEND, data, nullptr, IBinder::FLAG_ONEWAY);
}
};
@@ -56,7 +56,7 @@
CHECK_INTERFACE(IResultReceiver, data, reply);
int32_t resultCode = data.readInt32();
send(resultCode);
- if (reply != NULL) {
+ if (reply != nullptr) {
reply->writeNoException();
}
return NO_ERROR;
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index be3bbf7..4ba6c2a 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -27,7 +27,6 @@
#include <cutils/properties.h>
#include <utils/String8.h>
#include <utils/SystemClock.h>
-#include <utils/CallStack.h>
#include <private/binder/Static.h>
@@ -37,14 +36,14 @@
sp<IServiceManager> defaultServiceManager()
{
- if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
+ if (gDefaultServiceManager != nullptr) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
- while (gDefaultServiceManager == NULL) {
+ while (gDefaultServiceManager == nullptr) {
gDefaultServiceManager = interface_cast<IServiceManager>(
- ProcessState::self()->getContextObject(NULL));
- if (gDefaultServiceManager == NULL)
+ ProcessState::self()->getContextObject(nullptr));
+ if (gDefaultServiceManager == nullptr)
sleep(1);
}
}
@@ -57,7 +56,7 @@
bool checkCallingPermission(const String16& permission)
{
- return checkCallingPermission(permission, NULL, NULL);
+ return checkCallingPermission(permission, nullptr, nullptr);
}
static String16 _permission("permission");
@@ -83,7 +82,7 @@
int64_t startTime = 0;
while (true) {
- if (pc != NULL) {
+ if (pc != nullptr) {
bool res = pc->checkPermission(permission, pid, uid);
if (res) {
if (startTime != 0) {
@@ -104,14 +103,14 @@
// Object is dead!
gDefaultServiceManagerLock.lock();
if (gPermissionController == pc) {
- gPermissionController = NULL;
+ gPermissionController = nullptr;
}
gDefaultServiceManagerLock.unlock();
}
// Need to retrieve the permission controller.
sp<IBinder> binder = defaultServiceManager()->checkService(_permission);
- if (binder == NULL) {
+ if (binder == nullptr) {
// Wait for the permission controller to come back...
if (startTime == 0) {
startTime = uptimeMillis();
@@ -144,35 +143,32 @@
virtual sp<IBinder> getService(const String16& name) const
{
sp<IBinder> svc = checkService(name);
- if (svc != NULL) return svc;
+ if (svc != nullptr) return svc;
const bool isVendorService =
strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder") == 0;
const long timeout = uptimeMillis() + 5000;
- if (!gSystemBootCompleted) {
+ if (!gSystemBootCompleted && !isVendorService) {
+ // Vendor code can't access system properties
char bootCompleted[PROPERTY_VALUE_MAX];
property_get("sys.boot_completed", bootCompleted, "0");
gSystemBootCompleted = strcmp(bootCompleted, "1") == 0 ? true : false;
}
- // retry interval in millisecond.
+ // retry interval in millisecond; note that vendor services stay at 100ms
const long sleepTime = gSystemBootCompleted ? 1000 : 100;
int n = 0;
while (uptimeMillis() < timeout) {
n++;
- if (isVendorService) {
- ALOGI("Waiting for vendor service %s...", String8(name).string());
- CallStack stack(LOG_TAG);
- } else if (n%10 == 0) {
- ALOGI("Waiting for service %s...", String8(name).string());
- }
+ ALOGI("Waiting for service '%s' on '%s'...", String8(name).string(),
+ ProcessState::self()->getDriverName().c_str());
usleep(1000*sleepTime);
sp<IBinder> svc = checkService(name);
- if (svc != NULL) return svc;
+ if (svc != nullptr) return svc;
}
ALOGW("Service %s didn't start. Returning NULL", String8(name).string());
- return NULL;
+ return nullptr;
}
virtual sp<IBinder> checkService( const String16& name) const
diff --git a/libs/binder/IShellCallback.cpp b/libs/binder/IShellCallback.cpp
index 23b83a6..dd4a65e 100644
--- a/libs/binder/IShellCallback.cpp
+++ b/libs/binder/IShellCallback.cpp
@@ -68,7 +68,7 @@
String16 seLinuxContext(data.readString16());
String16 mode(data.readString16());
int fd = openFile(path, seLinuxContext, mode);
- if (reply != NULL) {
+ if (reply != nullptr) {
reply->writeNoException();
if (fd >= 0) {
reply->writeInt32(1);
diff --git a/libs/binder/MemoryDealer.cpp b/libs/binder/MemoryDealer.cpp
index 1cfe02a..eacad3b 100644
--- a/libs/binder/MemoryDealer.cpp
+++ b/libs/binder/MemoryDealer.cpp
@@ -52,8 +52,8 @@
NODE* mLast;
public:
- LinkedList() : mFirst(0), mLast(0) { }
- bool isEmpty() const { return mFirst == 0; }
+ LinkedList() : mFirst(nullptr), mLast(nullptr) { }
+ bool isEmpty() const { return mFirst == nullptr; }
NODE const* head() const { return mFirst; }
NODE* head() { return mFirst; }
NODE const* tail() const { return mLast; }
@@ -62,7 +62,7 @@
void insertAfter(NODE* node, NODE* newNode) {
newNode->prev = node;
newNode->next = node->next;
- if (node->next == 0) mLast = newNode;
+ if (node->next == nullptr) mLast = newNode;
else node->next->prev = newNode;
node->next = newNode;
}
@@ -70,17 +70,17 @@
void insertBefore(NODE* node, NODE* newNode) {
newNode->prev = node->prev;
newNode->next = node;
- if (node->prev == 0) mFirst = newNode;
+ if (node->prev == nullptr) mFirst = newNode;
else node->prev->next = newNode;
node->prev = newNode;
}
void insertHead(NODE* newNode) {
- if (mFirst == 0) {
+ if (mFirst == nullptr) {
mFirst = mLast = newNode;
- newNode->prev = newNode->next = 0;
+ newNode->prev = newNode->next = nullptr;
} else {
- newNode->prev = 0;
+ newNode->prev = nullptr;
newNode->next = mFirst;
mFirst->prev = newNode;
mFirst = newNode;
@@ -99,9 +99,9 @@
}
NODE* remove(NODE* node) {
- if (node->prev == 0) mFirst = node->next;
+ if (node->prev == nullptr) mFirst = node->next;
else node->prev->next = node->next;
- if (node->next == 0) mLast = node->prev;
+ if (node->next == nullptr) mLast = node->prev;
else node->next->prev = node->prev;
return node;
}
@@ -141,7 +141,7 @@
struct chunk_t {
chunk_t(size_t start, size_t size)
- : start(start), size(size), free(1), prev(0), next(0) {
+ : start(start), size(size), free(1), prev(nullptr), next(nullptr) {
}
size_t start;
size_t size : 28;
@@ -329,7 +329,7 @@
return 0;
}
size = (size + kMemoryAlign-1) / kMemoryAlign;
- chunk_t* free_chunk = 0;
+ chunk_t* free_chunk = nullptr;
chunk_t* cur = mList.head();
size_t pagesize = getpagesize();
@@ -418,7 +418,7 @@
}
cur = cur->next;
}
- return 0;
+ return nullptr;
}
void SimpleBestFitAllocator::dump(const char* what) const
diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp
index 03f00be..9850ad9 100644
--- a/libs/binder/MemoryHeapBase.cpp
+++ b/libs/binder/MemoryHeapBase.cpp
@@ -36,17 +36,17 @@
MemoryHeapBase::MemoryHeapBase()
: mFD(-1), mSize(0), mBase(MAP_FAILED),
- mDevice(NULL), mNeedUnmap(false), mOffset(0)
+ mDevice(nullptr), mNeedUnmap(false), mOffset(0)
{
}
MemoryHeapBase::MemoryHeapBase(size_t size, uint32_t flags, char const * name)
: mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
- mDevice(0), mNeedUnmap(false), mOffset(0)
+ mDevice(nullptr), mNeedUnmap(false), mOffset(0)
{
const size_t pagesize = getpagesize();
size = ((size + pagesize-1) & ~(pagesize-1));
- int fd = ashmem_create_region(name == NULL ? "MemoryHeapBase" : name, size);
+ int fd = ashmem_create_region(name == nullptr ? "MemoryHeapBase" : name, size);
ALOGE_IF(fd<0, "error creating ashmem region: %s", strerror(errno));
if (fd >= 0) {
if (mapfd(fd, size) == NO_ERROR) {
@@ -59,7 +59,7 @@
MemoryHeapBase::MemoryHeapBase(const char* device, size_t size, uint32_t flags)
: mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
- mDevice(0), mNeedUnmap(false), mOffset(0)
+ mDevice(nullptr), mNeedUnmap(false), mOffset(0)
{
int open_flags = O_RDWR;
if (flags & NO_CACHING)
@@ -78,7 +78,7 @@
MemoryHeapBase::MemoryHeapBase(int fd, size_t size, uint32_t flags, uint32_t offset)
: mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
- mDevice(0), mNeedUnmap(false), mOffset(0)
+ mDevice(nullptr), mNeedUnmap(false), mOffset(0)
{
const size_t pagesize = getpagesize();
size = ((size + pagesize-1) & ~(pagesize-1));
@@ -109,7 +109,7 @@
}
if ((mFlags & DONT_MAP_LOCALLY) == 0) {
- void* base = (uint8_t*)mmap(0, size,
+ void* base = (uint8_t*)mmap(nullptr, size,
PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
if (base == MAP_FAILED) {
ALOGE("mmap(fd=%d, size=%u) failed (%s)",
@@ -121,7 +121,7 @@
mBase = base;
mNeedUnmap = true;
} else {
- mBase = 0; // not MAP_FAILED
+ mBase = nullptr; // not MAP_FAILED
mNeedUnmap = false;
}
mFD = fd;
@@ -143,7 +143,7 @@
//ALOGD("munmap(fd=%d, base=%p, size=%lu)", fd, mBase, mSize);
munmap(mBase, mSize);
}
- mBase = 0;
+ mBase = nullptr;
mSize = 0;
close(fd);
}
diff --git a/libs/binder/OWNERS b/libs/binder/OWNERS
new file mode 100644
index 0000000..350994a
--- /dev/null
+++ b/libs/binder/OWNERS
@@ -0,0 +1,5 @@
+arve@google.com
+ctate@google.com
+hackbod@google.com
+maco@google.com
+smoreland@google.com
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 2e7edd7..b3ae09b 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -117,7 +117,7 @@
return;
case BINDER_TYPE_HANDLE: {
const sp<IBinder> b = proc->getStrongProxyForHandle(obj.handle);
- if (b != NULL) {
+ if (b != nullptr) {
LOG_REFS("Parcel %p acquiring reference on remote %p", who, b.get());
b->incStrong(who);
}
@@ -125,11 +125,11 @@
}
case BINDER_TYPE_WEAK_HANDLE: {
const wp<IBinder> b = proc->getWeakProxyForHandle(obj.handle);
- if (b != NULL) b.get_refs()->incWeak(who);
+ if (b != nullptr) b.get_refs()->incWeak(who);
return;
}
case BINDER_TYPE_FD: {
- if ((obj.cookie != 0) && (outAshmemSize != NULL) && ashmem_valid(obj.handle)) {
+ if ((obj.cookie != 0) && (outAshmemSize != nullptr) && ashmem_valid(obj.handle)) {
// If we own an ashmem fd, keep track of how much memory it refers to.
int size = ashmem_get_size_region(obj.handle);
if (size > 0) {
@@ -146,7 +146,7 @@
void acquire_object(const sp<ProcessState>& proc,
const flat_binder_object& obj, const void* who)
{
- acquire_object(proc, obj, who, NULL);
+ acquire_object(proc, obj, who, nullptr);
}
static void release_object(const sp<ProcessState>& proc,
@@ -165,7 +165,7 @@
return;
case BINDER_TYPE_HANDLE: {
const sp<IBinder> b = proc->getStrongProxyForHandle(obj.handle);
- if (b != NULL) {
+ if (b != nullptr) {
LOG_REFS("Parcel %p releasing reference on remote %p", who, b.get());
b->decStrong(who);
}
@@ -173,12 +173,12 @@
}
case BINDER_TYPE_WEAK_HANDLE: {
const wp<IBinder> b = proc->getWeakProxyForHandle(obj.handle);
- if (b != NULL) b.get_refs()->decWeak(who);
+ if (b != nullptr) b.get_refs()->decWeak(who);
return;
}
case BINDER_TYPE_FD: {
if (obj.cookie != 0) { // owned
- if ((outAshmemSize != NULL) && ashmem_valid(obj.handle)) {
+ if ((outAshmemSize != nullptr) && ashmem_valid(obj.handle)) {
int size = ashmem_get_size_region(obj.handle);
if (size > 0) {
*outAshmemSize -= size;
@@ -197,7 +197,7 @@
void release_object(const sp<ProcessState>& proc,
const flat_binder_object& obj, const void* who)
{
- release_object(proc, obj, who, NULL);
+ release_object(proc, obj, who, nullptr);
}
inline static status_t finish_flatten_binder(
@@ -219,11 +219,11 @@
obj.flags = 0x13 | FLAT_BINDER_FLAG_ACCEPTS_FDS;
}
- if (binder != NULL) {
+ if (binder != nullptr) {
IBinder *local = binder->localBinder();
if (!local) {
BpBinder *proxy = binder->remoteBinder();
- if (proxy == NULL) {
+ if (proxy == nullptr) {
ALOGE("null proxy");
}
const int32_t handle = proxy ? proxy->handle() : 0;
@@ -251,13 +251,13 @@
flat_binder_object obj;
obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
- if (binder != NULL) {
+ if (binder != nullptr) {
sp<IBinder> real = binder.promote();
- if (real != NULL) {
+ if (real != nullptr) {
IBinder *local = real->localBinder();
if (!local) {
BpBinder *proxy = real->remoteBinder();
- if (proxy == NULL) {
+ if (proxy == nullptr) {
ALOGE("null proxy");
}
const int32_t handle = proxy ? proxy->handle() : 0;
@@ -284,13 +284,13 @@
obj.hdr.type = BINDER_TYPE_BINDER;
obj.binder = 0;
obj.cookie = 0;
- return finish_flatten_binder(NULL, obj, out);
+ return finish_flatten_binder(nullptr, obj, out);
} else {
obj.hdr.type = BINDER_TYPE_BINDER;
obj.binder = 0;
obj.cookie = 0;
- return finish_flatten_binder(NULL, obj, out);
+ return finish_flatten_binder(nullptr, obj, out);
}
}
@@ -310,7 +310,7 @@
switch (flat->hdr.type) {
case BINDER_TYPE_BINDER:
*out = reinterpret_cast<IBinder*>(flat->cookie);
- return finish_unflatten_binder(NULL, *flat, in);
+ return finish_unflatten_binder(nullptr, *flat, in);
case BINDER_TYPE_HANDLE:
*out = proc->getStrongProxyForHandle(flat->handle);
return finish_unflatten_binder(
@@ -329,16 +329,16 @@
switch (flat->hdr.type) {
case BINDER_TYPE_BINDER:
*out = reinterpret_cast<IBinder*>(flat->cookie);
- return finish_unflatten_binder(NULL, *flat, in);
+ return finish_unflatten_binder(nullptr, *flat, in);
case BINDER_TYPE_WEAK_BINDER:
if (flat->binder != 0) {
out->set_object_and_refs(
reinterpret_cast<IBinder*>(flat->cookie),
reinterpret_cast<RefBase::weakref_type*>(flat->binder));
} else {
- *out = NULL;
+ *out = nullptr;
}
- return finish_unflatten_binder(NULL, *flat, in);
+ return finish_unflatten_binder(nullptr, *flat, in);
case BINDER_TYPE_HANDLE:
case BINDER_TYPE_WEAK_HANDLE:
*out = proc->getWeakProxyForHandle(flat->handle);
@@ -526,7 +526,7 @@
if (newSize*sizeof(binder_size_t) < mObjectsSize) return NO_MEMORY; // overflow
binder_size_t *objects =
(binder_size_t*)realloc(mObjects, newSize*sizeof(binder_size_t));
- if (objects == (binder_size_t*)0) {
+ if (objects == (binder_size_t*)nullptr) {
return NO_MEMORY;
}
mObjects = objects;
@@ -614,7 +614,7 @@
IPCThreadState* threadState) const
{
int32_t strictPolicy = readInt32();
- if (threadState == NULL) {
+ if (threadState == nullptr) {
threadState = IPCThreadState::self();
}
if ((threadState->getLastTransactionBinderFlags() &
@@ -722,14 +722,14 @@
if (len > INT32_MAX) {
// don't accept size_t values which may have come from an
// inadvertent conversion from a negative int.
- return NULL;
+ return nullptr;
}
const size_t padded = pad_size(len);
// sanity check for integer overflow
if (mDataPos+padded < mDataPos) {
- return NULL;
+ return nullptr;
}
if ((mDataPos+padded) <= mDataCapacity) {
@@ -760,7 +760,7 @@
status_t err = growData(padded);
if (err == NO_ERROR) goto restart_write;
- return NULL;
+ return nullptr;
}
status_t Parcel::writeUtf8AsUtf16(const std::string& str) {
@@ -1063,7 +1063,7 @@
status_t Parcel::writeString16(const char16_t* str, size_t len)
{
- if (str == NULL) return writeInt32(-1);
+ if (str == nullptr) return writeInt32(-1);
status_t err = writeInt32(len);
if (err == NO_ERROR) {
@@ -1180,6 +1180,19 @@
return writeFileDescriptor(fd, takeOwnership);
}
+status_t Parcel::writeDupParcelFileDescriptor(int fd)
+{
+ int dupFd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
+ if (dupFd < 0) {
+ return -errno;
+ }
+ status_t err = writeParcelFileDescriptor(dupFd, true /*takeOwnership*/);
+ if (err != OK) {
+ close(dupFd);
+ }
+ return err;
+}
+
status_t Parcel::writeUniqueFileDescriptor(const base::unique_fd& fd) {
return writeDupFileDescriptor(fd.get());
}
@@ -1221,7 +1234,7 @@
if (result < 0) {
status = result;
} else {
- void* ptr = ::mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ void* ptr = ::mmap(nullptr, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (ptr == MAP_FAILED) {
status = -errno;
} else {
@@ -1278,10 +1291,10 @@
// payload
void* const buf = this->writeInplace(len);
- if (buf == NULL)
+ if (buf == nullptr)
return BAD_VALUE;
- int* fds = NULL;
+ int* fds = nullptr;
if (fd_count) {
fds = new (std::nothrow) int[fd_count];
if (fds == nullptr) {
@@ -1337,7 +1350,7 @@
size_t newSize = ((mObjectsSize+2)*3)/2;
if (newSize*sizeof(binder_size_t) < mObjectsSize) return NO_MEMORY; // overflow
binder_size_t* objects = (binder_size_t*)realloc(mObjects, newSize*sizeof(binder_size_t));
- if (objects == NULL) return NO_MEMORY;
+ if (objects == nullptr) return NO_MEMORY;
mObjects = objects;
mObjectsCapacity = newSize;
}
@@ -1383,7 +1396,7 @@
status_t Parcel::writeNullableMap(const std::unique_ptr<binder::Map>& map)
{
- if (map == NULL) {
+ if (map == nullptr) {
return writeInt32(-1);
}
@@ -1555,7 +1568,7 @@
if (len > INT32_MAX) {
// don't accept size_t values which may have come from an
// inadvertent conversion from a negative int.
- return NULL;
+ return nullptr;
}
if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize
@@ -1566,7 +1579,7 @@
// Still increment the data position by the expected length
mDataPos += pad_size(len);
ALOGV("readInplace Setting data pos of %p to %zu", this, mDataPos);
- return NULL;
+ return nullptr;
}
}
@@ -1575,7 +1588,7 @@
ALOGV("readInplace Setting data pos of %p to %zu", this, mDataPos);
return data;
}
- return NULL;
+ return nullptr;
}
template<class T>
@@ -2025,7 +2038,7 @@
return str;
}
}
- return NULL;
+ return nullptr;
}
String8 Parcel::readString8() const
@@ -2056,7 +2069,7 @@
return OK;
}
const char* str = (const char*)readInplace(size + 1);
- if (str == NULL) {
+ if (str == nullptr) {
return BAD_VALUE;
}
pArg->setTo(str, size);
@@ -2115,12 +2128,12 @@
if (size >= 0 && size < INT32_MAX) {
*outLen = size;
const char16_t* str = (const char16_t*)readInplace((size+1)*sizeof(char16_t));
- if (str != NULL) {
+ if (str != nullptr) {
return str;
}
}
*outLen = 0;
- return NULL;
+ return nullptr;
}
status_t Parcel::readStrongBinder(sp<IBinder>* val) const
@@ -2182,13 +2195,13 @@
int numFds, numInts;
status_t err;
err = readInt32(&numFds);
- if (err != NO_ERROR) return 0;
+ if (err != NO_ERROR) return nullptr;
err = readInt32(&numInts);
- if (err != NO_ERROR) return 0;
+ if (err != NO_ERROR) return nullptr;
native_handle* h = native_handle_create(numFds, numInts);
if (!h) {
- return 0;
+ return nullptr;
}
for (int i=0 ; err==NO_ERROR && i<numFds ; i++) {
@@ -2198,14 +2211,14 @@
close(h->data[j]);
}
native_handle_delete(h);
- return 0;
+ return nullptr;
}
}
err = read(h->data + numFds, sizeof(int)*numInts);
if (err != NO_ERROR) {
native_handle_close(h);
native_handle_delete(h);
- h = 0;
+ h = nullptr;
}
return h;
}
@@ -2249,6 +2262,22 @@
return OK;
}
+status_t Parcel::readUniqueParcelFileDescriptor(base::unique_fd* val) const
+{
+ int got = readParcelFileDescriptor();
+
+ if (got == BAD_TYPE) {
+ return BAD_TYPE;
+ }
+
+ val->reset(fcntl(got, F_DUPFD_CLOEXEC, 0));
+
+ if (val->get() < 0) {
+ return BAD_VALUE;
+ }
+
+ return OK;
+}
status_t Parcel::readUniqueFileDescriptorVector(std::unique_ptr<std::vector<base::unique_fd>>* val) const {
return readNullableTypedVector(val, &Parcel::readUniqueFileDescriptor);
@@ -2278,7 +2307,7 @@
int fd = readFileDescriptor();
if (fd == int(BAD_TYPE)) return BAD_VALUE;
- void* ptr = ::mmap(NULL, len, isMutable ? PROT_READ | PROT_WRITE : PROT_READ,
+ void* ptr = ::mmap(nullptr, len, isMutable ? PROT_READ | PROT_WRITE : PROT_READ,
MAP_SHARED, fd, 0);
if (ptr == MAP_FAILED) return NO_MEMORY;
@@ -2300,10 +2329,10 @@
// payload
void const* const buf = this->readInplace(pad_size(len));
- if (buf == NULL)
+ if (buf == nullptr)
return BAD_VALUE;
- int* fds = NULL;
+ int* fds = nullptr;
if (fd_count) {
fds = new (std::nothrow) int[fd_count];
if (fds == nullptr) {
@@ -2394,7 +2423,7 @@
ALOGW("Attempt to read object from Parcel %p at offset %zu that is not in the object list",
this, DPOS);
}
- return NULL;
+ return nullptr;
}
void Parcel::closeFileDescriptors()
@@ -2604,7 +2633,7 @@
ALOGV("restartWrite Setting data pos of %p to %zu", this, mDataPos);
free(mObjects);
- mObjects = NULL;
+ mObjects = nullptr;
mObjectsSize = mObjectsCapacity = 0;
mNextObjectHint = 0;
mObjectsSorted = false;
@@ -2652,7 +2681,7 @@
mError = NO_MEMORY;
return NO_MEMORY;
}
- binder_size_t* objects = NULL;
+ binder_size_t* objects = nullptr;
if (objectsSize) {
objects = (binder_size_t*)calloc(objectsSize, sizeof(binder_size_t));
@@ -2679,7 +2708,7 @@
}
//ALOGI("Freeing data ref of %p (pid=%d)", this, getpid());
mOwner(this, mData, mDataSize, mObjects, mObjectsSize, mOwnerCookie);
- mOwner = NULL;
+ mOwner = nullptr;
LOG_ALLOC("Parcel %p: taking ownership of %zu capacity", this, desired);
pthread_mutex_lock(&gParcelGlobalAllocSizeLock);
@@ -2754,7 +2783,7 @@
return NO_MEMORY;
}
- if(!(mDataCapacity == 0 && mObjects == NULL
+ if(!(mDataCapacity == 0 && mObjects == nullptr
&& mObjectsCapacity == 0)) {
ALOGE("continueWrite: %zu/%p/%zu/%zu", mDataCapacity, mObjects, mObjectsCapacity, desired);
}
@@ -2779,13 +2808,13 @@
{
LOG_ALLOC("Parcel %p: initState", this);
mError = NO_ERROR;
- mData = 0;
+ mData = nullptr;
mDataSize = 0;
mDataCapacity = 0;
mDataPos = 0;
ALOGV("initState Setting data size of %p to %zu", this, mDataSize);
ALOGV("initState Setting data pos of %p to %zu", this, mDataPos);
- mObjects = NULL;
+ mObjects = nullptr;
mObjectsSize = 0;
mObjectsCapacity = 0;
mNextObjectHint = 0;
@@ -2793,7 +2822,7 @@
mHasFds = false;
mFdsKnown = true;
mAllowFds = true;
- mOwner = NULL;
+ mOwner = nullptr;
mOpenAshmemSize = 0;
// racing multiple init leads only to multiple identical write
@@ -2840,7 +2869,7 @@
// --- Parcel::Blob ---
Parcel::Blob::Blob() :
- mFd(-1), mData(NULL), mSize(0), mMutable(false) {
+ mFd(-1), mData(nullptr), mSize(0), mMutable(false) {
}
Parcel::Blob::~Blob() {
@@ -2863,7 +2892,7 @@
void Parcel::Blob::clear() {
mFd = -1;
- mData = NULL;
+ mData = nullptr;
mSize = 0;
mMutable = false;
}
diff --git a/libs/binder/ParcelFileDescriptor.cpp b/libs/binder/ParcelFileDescriptor.cpp
new file mode 100644
index 0000000..4f8b76f
--- /dev/null
+++ b/libs/binder/ParcelFileDescriptor.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include <binder/ParcelFileDescriptor.h>
+
+namespace android {
+namespace os {
+
+ParcelFileDescriptor::ParcelFileDescriptor() = default;
+
+ParcelFileDescriptor::ParcelFileDescriptor(android::base::unique_fd fd) : mFd(std::move(fd)) {}
+
+ParcelFileDescriptor::~ParcelFileDescriptor() = default;
+
+status_t ParcelFileDescriptor::writeToParcel(Parcel* parcel) const {
+ return parcel->writeDupParcelFileDescriptor(mFd.get());
+}
+
+status_t ParcelFileDescriptor::readFromParcel(const Parcel* parcel) {
+ return parcel->readUniqueParcelFileDescriptor(&mFd);
+}
+
+} // namespace os
+} // namespace android
diff --git a/libs/binder/PermissionCache.cpp b/libs/binder/PermissionCache.cpp
index a503be8..a4c28ad 100644
--- a/libs/binder/PermissionCache.cpp
+++ b/libs/binder/PermissionCache.cpp
@@ -75,7 +75,7 @@
}
bool PermissionCache::checkCallingPermission(const String16& permission) {
- return PermissionCache::checkCallingPermission(permission, NULL, NULL);
+ return PermissionCache::checkCallingPermission(permission, nullptr, nullptr);
}
bool PermissionCache::checkCallingPermission(
diff --git a/libs/binder/PermissionController.cpp b/libs/binder/PermissionController.cpp
index 96df33c..34b2ca5 100644
--- a/libs/binder/PermissionController.cpp
+++ b/libs/binder/PermissionController.cpp
@@ -41,7 +41,7 @@
ALOGI("Waiting for permission service");
} else if ((uptimeMillis() - startTime) > 10000) {
ALOGW("Waiting too long for permission service, giving up");
- service = NULL;
+ service = nullptr;
break;
}
sleep(1);
@@ -56,13 +56,13 @@
bool PermissionController::checkPermission(const String16& permission, int32_t pid, int32_t uid)
{
sp<IPermissionController> service = getService();
- return service != NULL ? service->checkPermission(permission, pid, uid) : false;
+ return service != nullptr ? service->checkPermission(permission, pid, uid) : false;
}
int32_t PermissionController::noteOp(const String16& op, int32_t uid, const String16& packageName)
{
sp<IPermissionController> service = getService();
- return service != NULL ? service->noteOp(op, uid, packageName) : MODE_ERRORED;
+ return service != nullptr ? service->noteOp(op, uid, packageName) : MODE_ERRORED;
}
void PermissionController::getPackagesForUid(const uid_t uid, Vector<String16> &packages)
diff --git a/libs/binder/ProcessInfoService.cpp b/libs/binder/ProcessInfoService.cpp
index 8939d9c..5cb2033 100644
--- a/libs/binder/ProcessInfoService.cpp
+++ b/libs/binder/ProcessInfoService.cpp
@@ -36,7 +36,7 @@
for (int i = 0; i < BINDER_ATTEMPT_LIMIT; i++) {
- if (pis != NULL) {
+ if (pis != nullptr) {
err = pis->getProcessStatesFromPids(length, /*in*/ pids, /*out*/ states);
if (err == NO_ERROR) return NO_ERROR; // success
if (IInterface::asBinder(pis)->isBinderAlive()) return err;
@@ -68,7 +68,7 @@
for (int i = 0; i < BINDER_ATTEMPT_LIMIT; i++) {
- if (pis != NULL) {
+ if (pis != nullptr) {
err = pis->getProcessStatesAndOomScoresFromPids(length,
/*in*/ pids, /*out*/ states, /*out*/ scores);
if (err == NO_ERROR) return NO_ERROR; // success
@@ -93,7 +93,7 @@
void ProcessInfoService::updateBinderLocked() {
const sp<IServiceManager> sm(defaultServiceManager());
- if (sm != NULL) {
+ if (sm != nullptr) {
const String16 name("processinfo");
mProcessInfoService = interface_cast<IProcessInfoService>(sm->checkService(name));
}
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index d1c6f84..53f8ddd 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -43,6 +43,12 @@
#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)
#define DEFAULT_MAX_BINDER_THREADS 15
+#ifdef __ANDROID_VNDK__
+const char* kDefaultDriver = "/dev/vndbinder";
+#else
+const char* kDefaultDriver = "/dev/binder";
+#endif
+
// -------------------------------------------------------------------------
namespace android {
@@ -68,17 +74,17 @@
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
- if (gProcess != NULL) {
+ if (gProcess != nullptr) {
return gProcess;
}
- gProcess = new ProcessState("/dev/binder");
+ gProcess = new ProcessState(kDefaultDriver);
return gProcess;
}
sp<ProcessState> ProcessState::initWithDriver(const char* driver)
{
Mutex::Autolock _l(gProcessMutex);
- if (gProcess != NULL) {
+ if (gProcess != nullptr) {
// Allow for initWithDriver to be called repeatedly with the same
// driver.
if (!strcmp(gProcess->getDriverName().c_str(), driver)) {
@@ -122,18 +128,18 @@
{
mLock.lock();
sp<IBinder> object(
- mContexts.indexOfKey(name) >= 0 ? mContexts.valueFor(name) : NULL);
+ mContexts.indexOfKey(name) >= 0 ? mContexts.valueFor(name) : nullptr);
mLock.unlock();
//printf("Getting context object %s for %p\n", String8(name).string(), caller.get());
- if (object != NULL) return object;
+ if (object != nullptr) return object;
// Don't attempt to retrieve contexts if we manage them
if (mManagesContexts) {
ALOGE("getContextObject(%s) failed, but we manage the contexts!\n",
String8(name).string());
- return NULL;
+ return nullptr;
}
IPCThreadState* ipc = IPCThreadState::self();
@@ -150,7 +156,7 @@
ipc->flushCommands();
- if (object != NULL) setContextObject(object, name);
+ if (object != nullptr) setContextObject(object, name);
return object;
}
@@ -180,8 +186,8 @@
if (result == 0) {
mManagesContexts = true;
} else if (result == -1) {
- mBinderContextCheckFunc = NULL;
- mBinderContextUserData = NULL;
+ mBinderContextCheckFunc = nullptr;
+ mBinderContextUserData = nullptr;
ALOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno));
}
}
@@ -207,7 +213,7 @@
binder_node_debug_info info = {};
- uintptr_t* end = buf ? buf + buf_count : NULL;
+ uintptr_t* end = buf ? buf + buf_count : nullptr;
size_t count = 0;
do {
@@ -233,10 +239,10 @@
const size_t N=mHandleToObject.size();
if (N <= (size_t)handle) {
handle_entry e;
- e.binder = NULL;
- e.refs = NULL;
+ e.binder = nullptr;
+ e.refs = nullptr;
status_t err = mHandleToObject.insertAt(e, N, handle+1-N);
- if (err < NO_ERROR) return NULL;
+ if (err < NO_ERROR) return nullptr;
}
return &mHandleToObject.editItemAt(handle);
}
@@ -249,12 +255,12 @@
handle_entry* e = lookupHandleLocked(handle);
- if (e != NULL) {
+ if (e != nullptr) {
// We need to create a new BpBinder if there isn't currently one, OR we
// are unable to acquire a weak reference on this current one. See comment
// in getWeakProxyForHandle() for more info about this.
IBinder* b = e->binder;
- if (b == NULL || !e->refs->attemptIncWeak(this)) {
+ if (b == nullptr || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {
// Special case for context manager...
// The context manager is the only object for which we create
@@ -277,9 +283,9 @@
Parcel data;
status_t status = IPCThreadState::self()->transact(
- 0, IBinder::PING_TRANSACTION, data, NULL, 0);
+ 0, IBinder::PING_TRANSACTION, data, nullptr, 0);
if (status == DEAD_OBJECT)
- return NULL;
+ return nullptr;
}
b = BpBinder::create(handle);
@@ -306,7 +312,7 @@
handle_entry* e = lookupHandleLocked(handle);
- if (e != NULL) {
+ if (e != nullptr) {
// We need to create a new BpBinder if there isn't currently one, OR we
// are unable to acquire a weak reference on this current one. The
// attemptIncWeak() is safe because we know the BpBinder destructor will always
@@ -315,7 +321,7 @@
// releasing a reference on this BpBinder, and a new reference on its handle
// arriving from the driver.
IBinder* b = e->binder;
- if (b == NULL || !e->refs->attemptIncWeak(this)) {
+ if (b == nullptr || !e->refs->attemptIncWeak(this)) {
b = BpBinder::create(handle);
result = b;
e->binder = b;
@@ -338,7 +344,7 @@
// This handle may have already been replaced with a new BpBinder
// (if someone failed the AttemptIncWeak() above); we don't want
// to overwrite it.
- if (e && e->binder == binder) e->binder = NULL;
+ if (e && e->binder == binder) e->binder = nullptr;
}
String8 ProcessState::makeBinderThreadName() {
@@ -416,14 +422,14 @@
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mStarvationStartTimeMs(0)
, mManagesContexts(false)
- , mBinderContextCheckFunc(NULL)
- , mBinderContextUserData(NULL)
+ , mBinderContextCheckFunc(nullptr)
+ , mBinderContextUserData(nullptr)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
if (mDriverFD >= 0) {
// mmap the binder, providing a chunk of virtual address space to receive transactions.
- mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
+ mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
// *sigh*
ALOGE("Using %s failed: unable to mmap transaction memory.\n", mDriverName.c_str());
diff --git a/libs/binder/Static.cpp b/libs/binder/Static.cpp
index d6d0340..bd0e6f9 100644
--- a/libs/binder/Static.cpp
+++ b/libs/binder/Static.cpp
@@ -75,21 +75,6 @@
Mutex& gProcessMutex = *new Mutex;
sp<ProcessState> gProcess;
-class LibBinderIPCtStatics
-{
-public:
- LibBinderIPCtStatics()
- {
- }
-
- ~LibBinderIPCtStatics()
- {
- IPCThreadState::shutdown();
- }
-};
-
-static LibBinderIPCtStatics gIPCStatics;
-
// ------------ IServiceManager.cpp
Mutex gDefaultServiceManagerLock;
diff --git a/libs/binder/Status.cpp b/libs/binder/Status.cpp
index a9d5055..a3f8755 100644
--- a/libs/binder/Status.cpp
+++ b/libs/binder/Status.cpp
@@ -24,11 +24,17 @@
}
Status Status::fromExceptionCode(int32_t exceptionCode) {
+ if (exceptionCode == EX_TRANSACTION_FAILED) {
+ return Status(exceptionCode, FAILED_TRANSACTION);
+ }
return Status(exceptionCode, OK);
}
Status Status::fromExceptionCode(int32_t exceptionCode,
const String8& message) {
+ if (exceptionCode == EX_TRANSACTION_FAILED) {
+ return Status(exceptionCode, FAILED_TRANSACTION, message);
+ }
return Status(exceptionCode, OK, message);
}
@@ -158,7 +164,7 @@
void Status::setException(int32_t ex, const String8& message) {
mException = ex;
- mErrorCode = NO_ERROR; // an exception, not a transaction failure.
+ mErrorCode = ex == EX_TRANSACTION_FAILED ? FAILED_TRANSACTION : NO_ERROR;
mMessage.setTo(message);
}
diff --git a/libs/binder/Value.cpp b/libs/binder/Value.cpp
index 85cd739..a28a618 100644
--- a/libs/binder/Value.cpp
+++ b/libs/binder/Value.cpp
@@ -143,12 +143,12 @@
// ====================================================================
-Value::Value() : mContent(NULL)
+Value::Value() : mContent(nullptr)
{
}
Value::Value(const Value& value)
- : mContent(value.mContent ? value.mContent->clone() : NULL)
+ : mContent(value.mContent ? value.mContent->clone() : nullptr)
{
}
@@ -165,8 +165,8 @@
return true;
}
- if ( (lhs.mContent == NULL)
- || (rhs.mContent == NULL)
+ if ( (lhs.mContent == nullptr)
+ || (rhs.mContent == nullptr)
) {
return false;
}
@@ -186,25 +186,25 @@
delete mContent;
mContent = rhs.mContent
? rhs.mContent->clone()
- : NULL;
+ : nullptr;
}
return *this;
}
bool Value::empty() const
{
- return mContent == NULL;
+ return mContent == nullptr;
}
void Value::clear()
{
delete mContent;
- mContent = NULL;
+ mContent = nullptr;
}
int32_t Value::parcelType() const
{
- const void* t_info(mContent ? mContent->type_ptr() : NULL);
+ const void* t_info(mContent ? mContent->type_ptr() : nullptr);
if (t_info == internal_type_ptr<bool>()) return VAL_BOOLEAN;
if (t_info == internal_type_ptr<uint8_t>()) return VAL_BYTE;
@@ -229,7 +229,7 @@
#ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
const std::type_info& Value::type() const
{
- return mContent != NULL
+ return mContent != nullptr
? mContent->type()
: typeid(void);
}
@@ -306,7 +306,7 @@
#define BEGIN_HANDLE_WRITE() \
do { \
- const void* t_info(mContent?mContent->type_ptr():NULL); \
+ const void* t_info(mContent?mContent->type_ptr():nullptr); \
if (false) { }
#define HANDLE_WRITE_TYPE(T, TYPEVAL, TYPEMETHOD) \
else if (t_info == internal_type_ptr<T>()) { \
@@ -381,7 +381,7 @@
int32_t value_type = VAL_NULL;
delete mContent;
- mContent = NULL;
+ mContent = nullptr;
RETURN_IF_FAILED(parcel->readInt32(&value_type));
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 3404881..0b60b4e 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -40,13 +40,13 @@
uint32_t flags = 0);
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
- void* cookie = NULL,
+ void* cookie = nullptr,
uint32_t flags = 0);
virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
- void* cookie = NULL,
+ void* cookie = nullptr,
uint32_t flags = 0,
- wp<DeathRecipient>* outRecipient = NULL);
+ wp<DeathRecipient>* outRecipient = nullptr);
virtual void attachObject( const void* objectID,
void* object,
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 8bd297b..c4c8ba3 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -47,12 +47,12 @@
uint32_t flags = 0);
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
- void* cookie = NULL,
+ void* cookie = nullptr,
uint32_t flags = 0);
virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
- void* cookie = NULL,
+ void* cookie = nullptr,
uint32_t flags = 0,
- wp<DeathRecipient>* outRecipient = NULL);
+ wp<DeathRecipient>* outRecipient = nullptr);
virtual void attachObject( const void* objectID,
void* object,
diff --git a/libs/binder/include/binder/Debug.h b/libs/binder/include/binder/Debug.h
index be0266c..58e2b32 100644
--- a/libs/binder/include/binder/Debug.h
+++ b/libs/binder/include/binder/Debug.h
@@ -31,12 +31,12 @@
typedef void (*debugPrintFunc)(void* cookie, const char* txt);
void printTypeCode(uint32_t typeCode,
- debugPrintFunc func = 0, void* cookie = 0);
+ debugPrintFunc func = nullptr, void* cookie = nullptr);
void printHexData(int32_t indent, const void *buf, size_t length,
size_t bytesPerLine=16, int32_t singleLineBytesCutoff=16,
size_t alignment=0, bool cArrayStyle=false,
- debugPrintFunc func = 0, void* cookie = 0);
+ debugPrintFunc func = nullptr, void* cookie = nullptr);
ssize_t getBinderKernelReferences(size_t count, uintptr_t* buf);
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index 2e62957..3f0dad0 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -132,7 +132,7 @@
* directly do with it now that it has passed on.)
*/
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
- void* cookie = NULL,
+ void* cookie = nullptr,
uint32_t flags = 0) = 0;
/**
@@ -143,19 +143,39 @@
* added with that cookie will be unlinked.
*/
virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
- void* cookie = NULL,
+ void* cookie = nullptr,
uint32_t flags = 0,
- wp<DeathRecipient>* outRecipient = NULL) = 0;
+ wp<DeathRecipient>* outRecipient = nullptr) = 0;
virtual bool checkSubclass(const void* subclassID) const;
typedef void (*object_cleanup_func)(const void* id, void* obj, void* cleanupCookie);
+ /**
+ * This object is attached for the lifetime of this binder object. When
+ * this binder object is destructed, the cleanup function of all attached
+ * objects are invoked with their respective objectID, object, and
+ * cleanupCookie. Access to these APIs can be made from multiple threads,
+ * but calls from different threads are allowed to be interleaved.
+ */
virtual void attachObject( const void* objectID,
void* object,
void* cleanupCookie,
object_cleanup_func func) = 0;
+ /**
+ * Returns object attached with attachObject.
+ */
virtual void* findObject(const void* objectID) const = 0;
+ /**
+ * WARNING: this API does not call the cleanup function for legacy reasons.
+ * It also does not return void* for legacy reasons. If you need to detach
+ * an object and destroy it, there are two options:
+ * - if you can, don't call detachObject and instead wait for the destructor
+ * to clean it up.
+ * - manually retrieve and destruct the object (if multiple of your threads
+ * are accessing these APIs, you must guarantee that attachObject isn't
+ * called after findObject and before detachObject is called).
+ */
virtual void detachObject(const void* objectID) = 0;
virtual BBinder* localBinder();
diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h
index 0f1fe5b..5ec02b1 100644
--- a/libs/binder/include/binder/IInterface.h
+++ b/libs/binder/include/binder/IInterface.h
@@ -72,12 +72,18 @@
// ----------------------------------------------------------------------
#define DECLARE_META_INTERFACE(INTERFACE) \
+public: \
static const ::android::String16 descriptor; \
static ::android::sp<I##INTERFACE> asInterface( \
const ::android::sp<::android::IBinder>& obj); \
virtual const ::android::String16& getInterfaceDescriptor() const; \
I##INTERFACE(); \
virtual ~I##INTERFACE(); \
+ static bool setDefaultImpl(std::unique_ptr<I##INTERFACE> impl); \
+ static const std::unique_ptr<I##INTERFACE>& getDefaultImpl(); \
+private: \
+ static std::unique_ptr<I##INTERFACE> default_impl; \
+public: \
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
@@ -90,16 +96,29 @@
const ::android::sp<::android::IBinder>& obj) \
{ \
::android::sp<I##INTERFACE> intr; \
- if (obj != NULL) { \
+ if (obj != nullptr) { \
intr = static_cast<I##INTERFACE*>( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
- if (intr == NULL) { \
+ if (intr == nullptr) { \
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
} \
+ std::unique_ptr<I##INTERFACE> I##INTERFACE::default_impl; \
+ bool I##INTERFACE::setDefaultImpl(std::unique_ptr<I##INTERFACE> impl)\
+ { \
+ if (!I##INTERFACE::default_impl && impl) { \
+ I##INTERFACE::default_impl = std::move(impl); \
+ return true; \
+ } \
+ return false; \
+ } \
+ const std::unique_ptr<I##INTERFACE>& I##INTERFACE::getDefaultImpl() \
+ { \
+ return I##INTERFACE::default_impl; \
+ } \
I##INTERFACE::I##INTERFACE() { } \
I##INTERFACE::~I##INTERFACE() { } \
@@ -116,7 +135,7 @@
const String16& _descriptor)
{
if (_descriptor == INTERFACE::descriptor) return this;
- return NULL;
+ return nullptr;
}
template<typename INTERFACE>
@@ -142,7 +161,7 @@
{
return remote();
}
-
+
// ----------------------------------------------------------------------
}; // namespace android
diff --git a/libs/binder/include/binder/IMemory.h b/libs/binder/include/binder/IMemory.h
index 15a104f..3099bf5 100644
--- a/libs/binder/include/binder/IMemory.h
+++ b/libs/binder/include/binder/IMemory.h
@@ -72,7 +72,7 @@
public:
DECLARE_META_INTERFACE(Memory)
- virtual sp<IMemoryHeap> getMemory(ssize_t* offset=0, size_t* size=0) const = 0;
+ virtual sp<IMemoryHeap> getMemory(ssize_t* offset=nullptr, size_t* size=nullptr) const = 0;
// helpers
void* fastPointer(const sp<IBinder>& heap, ssize_t offset) const;
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index c1d9a9a..40b51ad 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -29,6 +29,8 @@
// ---------------------------------------------------------------------------
namespace android {
+class IPCThreadStateBase;
+
class IPCThreadState
{
public:
@@ -89,13 +91,40 @@
// the maximum number of binder threads threads allowed for this process.
void blockUntilThreadAvailable();
+
+ // Is this thread currently serving a binder call. This method
+ // returns true if while traversing backwards from the function call
+ // stack for this thread, we encounter a function serving a binder
+ // call before encountering a hwbinder call / hitting the end of the
+ // call stack.
+ // Eg: If thread T1 went through the following call pattern
+ // 1) T1 receives and executes hwbinder call H1.
+ // 2) While handling H1, T1 makes binder call B1.
+ // 3) The handler of B1, calls into T1 with a callback B2.
+ // If isServingCall() is called during H1 before 3), this method
+ // will return false, else true.
+ //
+ // ----
+ // | B2 | ---> While callback B2 is being handled, during 3).
+ // ----
+ // | H1 | ---> While H1 is being handled.
+ // ----
+ // Fig: Thread Call stack while handling B2
+ //
+ // This is since after 3), while traversing the thread call stack,
+ // we hit a binder call before a hwbinder call / end of stack. This
+ // method may be typically used to determine whether to use
+ // hardware::IPCThreadState methods or IPCThreadState methods to
+ // infer information about thread state.
+ bool isServingCall() const;
+
private:
IPCThreadState();
~IPCThreadState();
status_t sendReply(const Parcel& reply, uint32_t flags);
status_t waitForResponse(Parcel *reply,
- status_t *acquireResult=NULL);
+ status_t *acquireResult=nullptr);
status_t talkWithDriver(bool doReceive=true);
status_t writeTransactionData(int32_t cmd,
uint32_t binderFlags,
@@ -128,6 +157,7 @@
uid_t mCallingUid;
int32_t mStrictModePolicy;
int32_t mLastTransactionBinderFlags;
+ IPCThreadStateBase *mIPCThreadStateBase;
};
}; // namespace android
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index 197026d..a998529 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -84,7 +84,7 @@
status_t getService(const String16& name, sp<INTERFACE>* outService)
{
const sp<IServiceManager> sm = defaultServiceManager();
- if (sm != NULL) {
+ if (sm != nullptr) {
*outService = interface_cast<INTERFACE>(sm->getService(name));
if ((*outService) != NULL) return NO_ERROR;
}
diff --git a/libs/binder/include/binder/MemoryDealer.h b/libs/binder/include/binder/MemoryDealer.h
index 60a624c..fe5a31d 100644
--- a/libs/binder/include/binder/MemoryDealer.h
+++ b/libs/binder/include/binder/MemoryDealer.h
@@ -34,7 +34,7 @@
class MemoryDealer : public RefBase
{
public:
- MemoryDealer(size_t size, const char* name = 0,
+ MemoryDealer(size_t size, const char* name = nullptr,
uint32_t flags = 0 /* or bits such as MemoryHeapBase::READ_ONLY */ );
virtual sp<IMemory> allocate(size_t size);
diff --git a/libs/binder/include/binder/MemoryHeapBase.h b/libs/binder/include/binder/MemoryHeapBase.h
index ea9b66c..5e0a382 100644
--- a/libs/binder/include/binder/MemoryHeapBase.h
+++ b/libs/binder/include/binder/MemoryHeapBase.h
@@ -52,7 +52,7 @@
/*
* maps memory from ashmem, with the given name for debugging
*/
- MemoryHeapBase(size_t size, uint32_t flags = 0, char const* name = NULL);
+ MemoryHeapBase(size_t size, uint32_t flags = 0, char const* name = nullptr);
virtual ~MemoryHeapBase();
@@ -74,7 +74,7 @@
/* this is only needed as a workaround, use only if you know
* what you are doing */
status_t setDevice(const char* device) {
- if (mDevice == 0)
+ if (mDevice == nullptr)
mDevice = device;
return mDevice ? NO_ERROR : ALREADY_EXISTS;
}
@@ -83,7 +83,7 @@
MemoryHeapBase();
// init() takes ownership of fd
status_t init(int fd, void *base, int size,
- int flags = 0, const char* device = NULL);
+ int flags = 0, const char* device = nullptr);
private:
status_t mapfd(int fd, size_t size, uint32_t offset = 0);
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index dede78f..c9c273a 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -91,7 +91,7 @@
// IPCThreadState, which as an optimization may optionally be
// passed in.
bool enforceInterface(const String16& interface,
- IPCThreadState* threadState = NULL) const;
+ IPCThreadState* threadState = nullptr) const;
bool checkInterface(IBinder*) const;
void freeData();
@@ -205,6 +205,10 @@
// The Parcel does not take ownership of the given fd unless you ask it to.
status_t writeParcelFileDescriptor(int fd, bool takeOwnership = false);
+ // Place a Java "parcel file descriptor" into the parcel. A dup of the fd is made, which will
+ // be closed once the parcel is destroyed.
+ status_t writeDupParcelFileDescriptor(int fd);
+
// Place a file descriptor into the parcel. This will not affect the
// semantics of the smart file descriptor. A new descriptor will be
// created, and will be closed when the parcel is destroyed.
@@ -364,6 +368,9 @@
status_t readUniqueFileDescriptor(
base::unique_fd* val) const;
+ // Retrieve a Java "parcel file descriptor" from the parcel.
+ status_t readUniqueParcelFileDescriptor(base::unique_fd* val) const;
+
// Retrieve a vector of smart file descriptors from the parcel.
status_t readUniqueFileDescriptorVector(
@@ -547,7 +554,7 @@
friend class Parcel;
public:
inline const void* data() const { return mData; }
- inline void* mutableData() { return isMutable() ? mData : NULL; }
+ inline void* mutableData() { return isMutable() ? mData : nullptr; }
};
class WritableBlob : public Blob {
@@ -587,7 +594,7 @@
}
if (size) {
void* buffer = writeInplace(size);
- if (buffer == NULL)
+ if (buffer == nullptr)
return NO_MEMORY;
return val.flatten(buffer, size);
}
@@ -615,7 +622,7 @@
}
if (size) {
void const* buffer = readInplace(size);
- return buffer == NULL ? NO_MEMORY :
+ return buffer == nullptr ? NO_MEMORY :
val.unflatten(buffer, size);
}
return NO_ERROR;
diff --git a/libs/binder/include/binder/ParcelFileDescriptor.h b/libs/binder/include/binder/ParcelFileDescriptor.h
new file mode 100644
index 0000000..ad950af
--- /dev/null
+++ b/libs/binder/include/binder/ParcelFileDescriptor.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef ANDROID_PARCEL_FILE_DESCRIPTOR_H_
+#define ANDROID_PARCEL_FILE_DESCRIPTOR_H_
+
+#include <android-base/unique_fd.h>
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+
+namespace android {
+namespace os {
+
+/*
+ * C++ implementation of the Java class android.os.ParcelFileDescriptor
+ */
+class ParcelFileDescriptor : public android::Parcelable {
+public:
+ ParcelFileDescriptor();
+ explicit ParcelFileDescriptor(android::base::unique_fd fd);
+ explicit ParcelFileDescriptor(ParcelFileDescriptor&& other) : mFd(std::move(other.mFd)) { }
+ ~ParcelFileDescriptor() override;
+
+ int get() const { return mFd.get(); }
+ android::base::unique_fd release() { return std::move(mFd); }
+ void reset(android::base::unique_fd fd = android::base::unique_fd()) { mFd = std::move(fd); }
+
+ // android::Parcelable override:
+ android::status_t writeToParcel(android::Parcel* parcel) const override;
+ android::status_t readFromParcel(const android::Parcel* parcel) override;
+
+private:
+ android::base::unique_fd mFd;
+};
+
+} // namespace os
+} // namespace android
+
+#endif // ANDROID_OS_PARCEL_FILE_DESCRIPTOR_H_
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index f85c261..13f67ba 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -36,9 +36,12 @@
public:
static sp<ProcessState> self();
static sp<ProcessState> selfOrNull();
+
/* initWithDriver() can be used to configure libbinder to use
* a different binder driver dev node. It must be called *before*
- * any call to ProcessState::self(). /dev/binder remains the default.
+ * any call to ProcessState::self(). The default is /dev/vndbinder
+ * for processes built with the VNDK and /dev/binder for those
+ * which are not.
*/
static sp<ProcessState> initWithDriver(const char *driver);
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
new file mode 100644
index 0000000..5461b4f
--- /dev/null
+++ b/libs/binder/ndk/Android.bp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 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.
+ */
+
+cc_library {
+ name: "libbinder_ndk",
+ vendor_available: false,
+
+ export_include_dirs: [
+ "include_ndk",
+ "include_apex",
+ ],
+
+ srcs: [
+ "ibinder.cpp",
+ "ibinder_jni.cpp",
+ "parcel.cpp",
+ "process.cpp",
+ "status.cpp",
+ "service_manager.cpp",
+ ],
+
+ shared_libs: [
+ "libandroid_runtime",
+ "libbase",
+ "libbinder",
+ "libutils",
+ ],
+}
+
+ndk_headers {
+ name: "libbinder_ndk_headers",
+ from: "include_ndk/android",
+ to: "android",
+ srcs: [
+ "include_ndk/android/*.h",
+ ],
+ license: "NOTICE",
+}
+
+ndk_library {
+ name: "libbinder_ndk",
+ symbol_file: "libbinder_ndk.map.txt",
+ first_version: "29",
+}
diff --git a/libs/binder/ndk/NOTICE b/libs/binder/ndk/NOTICE
new file mode 100644
index 0000000..d1ab54c
--- /dev/null
+++ b/libs/binder/ndk/NOTICE
@@ -0,0 +1,189 @@
+
+ Copyright (c) 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.
+
+ 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.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
new file mode 100644
index 0000000..896c5c1
--- /dev/null
+++ b/libs/binder/ndk/ibinder.cpp
@@ -0,0 +1,497 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include <android/binder_ibinder.h>
+#include "ibinder_internal.h"
+
+#include <android/binder_status.h>
+#include "parcel_internal.h"
+#include "status_internal.h"
+
+#include <android-base/logging.h>
+
+using DeathRecipient = ::android::IBinder::DeathRecipient;
+
+using ::android::IBinder;
+using ::android::Parcel;
+using ::android::sp;
+using ::android::status_t;
+using ::android::String16;
+using ::android::wp;
+
+namespace ABBinderTag {
+
+static const void* kId = "ABBinder";
+static void* kValue = static_cast<void*>(new bool{true});
+void clean(const void* /*id*/, void* /*obj*/, void* /*cookie*/){/* do nothing */};
+
+static void attach(const sp<IBinder>& binder) {
+ binder->attachObject(kId, kValue, nullptr /*cookie*/, clean);
+}
+static bool has(const sp<IBinder>& binder) {
+ return binder != nullptr && binder->findObject(kId) == kValue;
+}
+
+} // namespace ABBinderTag
+
+namespace ABpBinderTag {
+
+static std::mutex gLock;
+static const void* kId = "ABpBinder";
+struct Value {
+ wp<ABpBinder> binder;
+};
+void clean(const void* id, void* obj, void* cookie) {
+ CHECK(id == kId) << id << " " << obj << " " << cookie;
+
+ delete static_cast<Value*>(obj);
+};
+
+} // namespace ABpBinderTag
+
+AIBinder::AIBinder(const AIBinder_Class* clazz) : mClazz(clazz) {}
+AIBinder::~AIBinder() {}
+
+bool AIBinder::associateClass(const AIBinder_Class* clazz) {
+ using ::android::String8;
+
+ if (clazz == nullptr) return false;
+ if (mClazz == clazz) return true;
+
+ String8 newDescriptor(clazz->getInterfaceDescriptor());
+
+ if (mClazz != nullptr) {
+ String8 currentDescriptor(mClazz->getInterfaceDescriptor());
+ if (newDescriptor == currentDescriptor) {
+ LOG(ERROR) << __func__ << ": Class descriptors '" << currentDescriptor
+ << "' match during associateClass, but they are different class objects. "
+ "Class descriptor collision?";
+ } else {
+ LOG(ERROR) << __func__
+ << ": Class cannot be associated on object which already has a class. "
+ "Trying to associate to '"
+ << newDescriptor.c_str() << "' but already set to '"
+ << currentDescriptor.c_str() << "'.";
+ }
+
+ // always a failure because we know mClazz != clazz
+ return false;
+ }
+
+ CHECK(asABpBinder() != nullptr); // ABBinder always has a descriptor
+
+ String8 descriptor(getBinder()->getInterfaceDescriptor());
+ if (descriptor != newDescriptor) {
+ LOG(ERROR) << __func__ << ": Expecting binder to have class '" << newDescriptor.c_str()
+ << "' but descriptor is actually '" << descriptor.c_str() << "'.";
+ return false;
+ }
+
+ // if this is a local object, it's not one known to libbinder_ndk
+ mClazz = clazz;
+
+ return true;
+}
+
+ABBinder::ABBinder(const AIBinder_Class* clazz, void* userData)
+ : AIBinder(clazz), BBinder(), mUserData(userData) {
+ CHECK(clazz != nullptr);
+}
+ABBinder::~ABBinder() {
+ getClass()->onDestroy(mUserData);
+}
+
+const String16& ABBinder::getInterfaceDescriptor() const {
+ return getClass()->getInterfaceDescriptor();
+}
+
+status_t ABBinder::onTransact(transaction_code_t code, const Parcel& data, Parcel* reply,
+ binder_flags_t flags) {
+ if (isUserCommand(code)) {
+ if (!data.checkInterface(this)) {
+ return STATUS_BAD_TYPE;
+ }
+
+ const AParcel in = AParcel::readOnly(this, &data);
+ AParcel out = AParcel(this, reply, false /*owns*/);
+
+ binder_status_t status = getClass()->onTransact(this, code, &in, &out);
+ return PruneStatusT(status);
+ } else {
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+ABpBinder::ABpBinder(const ::android::sp<::android::IBinder>& binder)
+ : AIBinder(nullptr /*clazz*/), BpRefBase(binder) {
+ CHECK(binder != nullptr);
+}
+ABpBinder::~ABpBinder() {}
+
+void ABpBinder::onLastStrongRef(const void* id) {
+ {
+ std::lock_guard<std::mutex> lock(ABpBinderTag::gLock);
+ // Since ABpBinder is OBJECT_LIFETIME_WEAK, we must remove this weak reference in order for
+ // the ABpBinder to be deleted. Since a strong reference to this ABpBinder object should no
+ // longer be able to exist at the time of this method call, there is no longer a need to
+ // recover it.
+
+ ABpBinderTag::Value* value =
+ static_cast<ABpBinderTag::Value*>(remote()->findObject(ABpBinderTag::kId));
+ if (value != nullptr) {
+ value->binder = nullptr;
+ }
+ }
+
+ BpRefBase::onLastStrongRef(id);
+}
+
+sp<AIBinder> ABpBinder::lookupOrCreateFromBinder(const ::android::sp<::android::IBinder>& binder) {
+ if (binder == nullptr) {
+ return nullptr;
+ }
+ if (ABBinderTag::has(binder)) {
+ return static_cast<ABBinder*>(binder.get());
+ }
+
+ // The following code ensures that for a given binder object (remote or local), if it is not an
+ // ABBinder then at most one ABpBinder object exists in a given process representing it.
+ std::lock_guard<std::mutex> lock(ABpBinderTag::gLock);
+
+ ABpBinderTag::Value* value =
+ static_cast<ABpBinderTag::Value*>(binder->findObject(ABpBinderTag::kId));
+ if (value == nullptr) {
+ value = new ABpBinderTag::Value;
+ binder->attachObject(ABpBinderTag::kId, static_cast<void*>(value), nullptr /*cookie*/,
+ ABpBinderTag::clean);
+ }
+
+ sp<ABpBinder> ret = value->binder.promote();
+ if (ret == nullptr) {
+ ret = new ABpBinder(binder);
+ value->binder = ret;
+ }
+
+ return ret;
+}
+
+struct AIBinder_Weak {
+ wp<AIBinder> binder;
+};
+AIBinder_Weak* AIBinder_Weak_new(AIBinder* binder) {
+ if (binder == nullptr) {
+ return nullptr;
+ }
+
+ return new AIBinder_Weak{wp<AIBinder>(binder)};
+}
+void AIBinder_Weak_delete(AIBinder_Weak* weakBinder) {
+ delete weakBinder;
+}
+AIBinder* AIBinder_Weak_promote(AIBinder_Weak* weakBinder) {
+ if (weakBinder == nullptr) {
+ return nullptr;
+ }
+
+ sp<AIBinder> binder = weakBinder->binder.promote();
+ AIBinder_incStrong(binder.get());
+ return binder.get();
+}
+
+AIBinder_Class::AIBinder_Class(const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate,
+ AIBinder_Class_onDestroy onDestroy,
+ AIBinder_Class_onTransact onTransact)
+ : onCreate(onCreate),
+ onDestroy(onDestroy),
+ onTransact(onTransact),
+ mInterfaceDescriptor(interfaceDescriptor) {}
+
+AIBinder_Class* AIBinder_Class_define(const char* interfaceDescriptor,
+ AIBinder_Class_onCreate onCreate,
+ AIBinder_Class_onDestroy onDestroy,
+ AIBinder_Class_onTransact onTransact) {
+ if (interfaceDescriptor == nullptr || onCreate == nullptr || onDestroy == nullptr ||
+ onTransact == nullptr) {
+ return nullptr;
+ }
+
+ return new AIBinder_Class(interfaceDescriptor, onCreate, onDestroy, onTransact);
+}
+
+void AIBinder_DeathRecipient::TransferDeathRecipient::binderDied(const wp<IBinder>& who) {
+ CHECK(who == mWho);
+
+ mOnDied(mCookie);
+ mWho = nullptr;
+}
+
+AIBinder_DeathRecipient::AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinderDied onDied)
+ : mOnDied(onDied) {
+ CHECK(onDied != nullptr);
+}
+
+binder_status_t AIBinder_DeathRecipient::linkToDeath(AIBinder* binder, void* cookie) {
+ CHECK(binder != nullptr);
+
+ std::lock_guard<std::mutex> l(mDeathRecipientsMutex);
+
+ sp<TransferDeathRecipient> recipient =
+ new TransferDeathRecipient(binder->getBinder(), cookie, mOnDied);
+
+ status_t status = binder->getBinder()->linkToDeath(recipient, cookie, 0 /*flags*/);
+ if (status != STATUS_OK) {
+ return PruneStatusT(status);
+ }
+
+ mDeathRecipients.push_back(recipient);
+ return STATUS_OK;
+}
+
+binder_status_t AIBinder_DeathRecipient::unlinkToDeath(AIBinder* binder, void* cookie) {
+ CHECK(binder != nullptr);
+
+ std::lock_guard<std::mutex> l(mDeathRecipientsMutex);
+
+ for (auto it = mDeathRecipients.rbegin(); it != mDeathRecipients.rend(); ++it) {
+ sp<TransferDeathRecipient> recipient = *it;
+
+ if (recipient->getCookie() == cookie && recipient->getWho() == binder->getBinder()) {
+ mDeathRecipients.erase(it.base() - 1);
+
+ status_t status = binder->getBinder()->unlinkToDeath(recipient, cookie, 0 /*flags*/);
+ if (status != ::android::OK) {
+ LOG(ERROR) << __func__
+ << ": removed reference to death recipient but unlink failed.";
+ }
+ return PruneStatusT(status);
+ }
+ }
+
+ return STATUS_NAME_NOT_FOUND;
+}
+
+// start of C-API methods
+
+AIBinder* AIBinder_new(const AIBinder_Class* clazz, void* args) {
+ if (clazz == nullptr) {
+ LOG(ERROR) << __func__ << ": Must provide class to construct local binder.";
+ return nullptr;
+ }
+
+ void* userData = clazz->onCreate(args);
+
+ sp<AIBinder> ret = new ABBinder(clazz, userData);
+ ABBinderTag::attach(ret->getBinder());
+
+ AIBinder_incStrong(ret.get());
+ return ret.get();
+}
+
+bool AIBinder_isRemote(const AIBinder* binder) {
+ if (binder == nullptr) {
+ return true;
+ }
+
+ return binder->isRemote();
+}
+
+bool AIBinder_isAlive(const AIBinder* binder) {
+ if (binder == nullptr) {
+ return false;
+ }
+
+ return const_cast<AIBinder*>(binder)->getBinder()->isBinderAlive();
+}
+
+binder_status_t AIBinder_ping(AIBinder* binder) {
+ if (binder == nullptr) {
+ return STATUS_UNEXPECTED_NULL;
+ }
+
+ return PruneStatusT(binder->getBinder()->pingBinder());
+}
+
+binder_status_t AIBinder_linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
+ void* cookie) {
+ if (binder == nullptr || recipient == nullptr) {
+ LOG(ERROR) << __func__ << ": Must provide binder and recipient.";
+ return STATUS_UNEXPECTED_NULL;
+ }
+
+ // returns binder_status_t
+ return recipient->linkToDeath(binder, cookie);
+}
+
+binder_status_t AIBinder_unlinkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
+ void* cookie) {
+ if (binder == nullptr || recipient == nullptr) {
+ LOG(ERROR) << __func__ << ": Must provide binder and recipient.";
+ return STATUS_UNEXPECTED_NULL;
+ }
+
+ // returns binder_status_t
+ return recipient->unlinkToDeath(binder, cookie);
+}
+
+void AIBinder_incStrong(AIBinder* binder) {
+ if (binder == nullptr) {
+ LOG(ERROR) << __func__ << ": on null binder";
+ return;
+ }
+
+ binder->incStrong(nullptr);
+}
+void AIBinder_decStrong(AIBinder* binder) {
+ if (binder == nullptr) {
+ LOG(ERROR) << __func__ << ": on null binder";
+ return;
+ }
+
+ binder->decStrong(nullptr);
+}
+int32_t AIBinder_debugGetRefCount(AIBinder* binder) {
+ if (binder == nullptr) {
+ LOG(ERROR) << __func__ << ": on null binder";
+ return -1;
+ }
+
+ return binder->getStrongCount();
+}
+
+bool AIBinder_associateClass(AIBinder* binder, const AIBinder_Class* clazz) {
+ if (binder == nullptr) {
+ return false;
+ }
+
+ return binder->associateClass(clazz);
+}
+
+const AIBinder_Class* AIBinder_getClass(AIBinder* binder) {
+ if (binder == nullptr) {
+ return nullptr;
+ }
+
+ return binder->getClass();
+}
+
+void* AIBinder_getUserData(AIBinder* binder) {
+ if (binder == nullptr) {
+ return nullptr;
+ }
+
+ ABBinder* bBinder = binder->asABBinder();
+ if (bBinder == nullptr) {
+ return nullptr;
+ }
+
+ return bBinder->getUserData();
+}
+
+binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in) {
+ if (binder == nullptr || in == nullptr) {
+ LOG(ERROR) << __func__ << ": requires non-null parameters.";
+ return STATUS_UNEXPECTED_NULL;
+ }
+ const AIBinder_Class* clazz = binder->getClass();
+ if (clazz == nullptr) {
+ LOG(ERROR) << __func__
+ << ": Class must be defined for a remote binder transaction. See "
+ "AIBinder_associateClass.";
+ return STATUS_INVALID_OPERATION;
+ }
+
+ if (!binder->isRemote()) {
+ LOG(WARNING) << "A binder object at " << binder
+ << " is being transacted on, however, this object is in the same process as "
+ "its proxy. Transacting with this binder is expensive compared to just "
+ "calling the corresponding functionality in the same process.";
+ }
+
+ *in = new AParcel(binder);
+ status_t status = (*in)->get()->writeInterfaceToken(clazz->getInterfaceDescriptor());
+ binder_status_t ret = PruneStatusT(status);
+
+ if (ret != STATUS_OK) {
+ delete *in;
+ *in = nullptr;
+ }
+
+ return ret;
+}
+
+static void DestroyParcel(AParcel** parcel) {
+ delete *parcel;
+ *parcel = nullptr;
+}
+
+binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, AParcel** in,
+ AParcel** out, binder_flags_t flags) {
+ if (in == nullptr) {
+ LOG(ERROR) << __func__ << ": requires non-null in parameter";
+ return STATUS_UNEXPECTED_NULL;
+ }
+
+ using AutoParcelDestroyer = std::unique_ptr<AParcel*, void (*)(AParcel**)>;
+ // This object is the input to the transaction. This function takes ownership of it and deletes
+ // it.
+ AutoParcelDestroyer forIn(in, DestroyParcel);
+
+ if (!isUserCommand(code)) {
+ LOG(ERROR) << __func__ << ": Only user-defined transactions can be made from the NDK.";
+ return STATUS_UNKNOWN_TRANSACTION;
+ }
+
+ if ((flags & ~FLAG_ONEWAY) != 0) {
+ LOG(ERROR) << __func__ << ": Unrecognized flags sent: " << flags;
+ return STATUS_BAD_VALUE;
+ }
+
+ if (binder == nullptr || *in == nullptr || out == nullptr) {
+ LOG(ERROR) << __func__ << ": requires non-null parameters.";
+ return STATUS_UNEXPECTED_NULL;
+ }
+
+ if ((*in)->getBinder() != binder) {
+ LOG(ERROR) << __func__ << ": parcel is associated with binder object " << binder
+ << " but called with " << (*in)->getBinder();
+ return STATUS_BAD_VALUE;
+ }
+
+ *out = new AParcel(binder);
+
+ status_t status = binder->getBinder()->transact(code, *(*in)->get(), (*out)->get(), flags);
+ binder_status_t ret = PruneStatusT(status);
+
+ if (ret != STATUS_OK) {
+ delete *out;
+ *out = nullptr;
+ }
+
+ return ret;
+}
+
+AIBinder_DeathRecipient* AIBinder_DeathRecipient_new(
+ AIBinder_DeathRecipient_onBinderDied onBinderDied) {
+ if (onBinderDied == nullptr) {
+ LOG(ERROR) << __func__ << ": requires non-null onBinderDied parameter.";
+ return nullptr;
+ }
+ return new AIBinder_DeathRecipient(onBinderDied);
+}
+
+void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient* recipient) {
+ delete recipient;
+}
diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h
new file mode 100644
index 0000000..5b6bc94
--- /dev/null
+++ b/libs/binder/ndk/ibinder_internal.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 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 <android/binder_ibinder.h>
+#include "ibinder_internal.h"
+
+#include <atomic>
+#include <mutex>
+#include <vector>
+
+#include <binder/Binder.h>
+#include <binder/IBinder.h>
+
+inline bool isUserCommand(transaction_code_t code) {
+ return code >= FIRST_CALL_TRANSACTION && code <= LAST_CALL_TRANSACTION;
+}
+
+struct ABBinder;
+struct ABpBinder;
+
+struct AIBinder : public virtual ::android::RefBase {
+ AIBinder(const AIBinder_Class* clazz);
+ virtual ~AIBinder();
+
+ bool associateClass(const AIBinder_Class* clazz);
+ const AIBinder_Class* getClass() const { return mClazz; }
+
+ virtual ::android::sp<::android::IBinder> getBinder() = 0;
+ virtual ABBinder* asABBinder() { return nullptr; }
+ virtual ABpBinder* asABpBinder() { return nullptr; }
+
+ bool isRemote() const {
+ ::android::sp<::android::IBinder> binder = const_cast<AIBinder*>(this)->getBinder();
+ return binder->remoteBinder() != nullptr;
+ }
+
+private:
+ // 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).
+ const AIBinder_Class* mClazz;
+};
+
+// This is a local AIBinder object with a known class.
+struct ABBinder : public AIBinder, public ::android::BBinder {
+ virtual ~ABBinder();
+
+ void* getUserData() { return mUserData; }
+
+ ::android::sp<::android::IBinder> getBinder() override { return this; }
+ ABBinder* asABBinder() override { return this; }
+
+ const ::android::String16& getInterfaceDescriptor() const override;
+ ::android::status_t onTransact(uint32_t code, const ::android::Parcel& data,
+ ::android::Parcel* reply, binder_flags_t flags) override;
+
+private:
+ ABBinder(const AIBinder_Class* clazz, void* userData);
+
+ // only thing that should create an ABBinder
+ friend AIBinder* AIBinder_new(const AIBinder_Class*, void*);
+
+ // Can contain implementation if this is a local binder. This can still be nullptr for a local
+ // binder. If it is nullptr, the implication is the implementation state is entirely external to
+ // this object and the functionality provided in the AIBinder_Class is sufficient.
+ void* mUserData;
+};
+
+// This binder object may be remote or local (even though it is 'Bp'). The implication if it is
+// local is that it is an IBinder object created outside of the domain of libbinder_ndk.
+struct ABpBinder : public AIBinder, public ::android::BpRefBase {
+ // Looks up to see if this object has or is an existing ABBinder or ABpBinder object, otherwise
+ // it creates an ABpBinder object.
+ static ::android::sp<AIBinder> lookupOrCreateFromBinder(
+ const ::android::sp<::android::IBinder>& binder);
+
+ virtual ~ABpBinder();
+
+ void onLastStrongRef(const void* id) override;
+
+ ::android::sp<::android::IBinder> getBinder() override { return remote(); }
+ ABpBinder* asABpBinder() override { return this; }
+
+private:
+ ABpBinder(const ::android::sp<::android::IBinder>& binder);
+};
+
+struct AIBinder_Class {
+ AIBinder_Class(const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate,
+ AIBinder_Class_onDestroy onDestroy, AIBinder_Class_onTransact onTransact);
+
+ const ::android::String16& getInterfaceDescriptor() const { return mInterfaceDescriptor; }
+
+ const AIBinder_Class_onCreate onCreate;
+ const AIBinder_Class_onDestroy onDestroy;
+ const AIBinder_Class_onTransact onTransact;
+
+private:
+ // This must be a String16 since BBinder virtual getInterfaceDescriptor returns a reference to
+ // one.
+ const ::android::String16 mInterfaceDescriptor;
+};
+
+// Ownership is like this (when linked to death):
+//
+// AIBinder_DeathRecipient -sp-> TransferDeathRecipient <-wp-> IBinder
+//
+// When the AIBinder_DeathRecipient is dropped, so are the actual underlying death recipients. When
+// the IBinder dies, only a wp to it is kept.
+struct AIBinder_DeathRecipient {
+ // One of these is created for every linkToDeath. This is to be able to recover data when a
+ // binderDied receipt only gives us information about the IBinder.
+ struct TransferDeathRecipient : ::android::IBinder::DeathRecipient {
+ TransferDeathRecipient(const ::android::wp<::android::IBinder>& who, void* cookie,
+ const AIBinder_DeathRecipient_onBinderDied& onDied)
+ : mWho(who), mCookie(cookie), mOnDied(onDied) {}
+
+ void binderDied(const ::android::wp<::android::IBinder>& who) override;
+
+ const ::android::wp<::android::IBinder>& getWho() { return mWho; }
+ void* getCookie() { return mCookie; }
+
+ private:
+ ::android::wp<::android::IBinder> mWho;
+ void* mCookie;
+ const AIBinder_DeathRecipient_onBinderDied& mOnDied;
+ };
+
+ AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinderDied onDied);
+ binder_status_t linkToDeath(AIBinder* binder, void* cookie);
+ binder_status_t unlinkToDeath(AIBinder* binder, void* cookie);
+
+private:
+ std::mutex mDeathRecipientsMutex;
+ std::vector<::android::sp<TransferDeathRecipient>> mDeathRecipients;
+ AIBinder_DeathRecipient_onBinderDied mOnDied;
+};
diff --git a/libs/binder/ndk/ibinder_jni.cpp b/libs/binder/ndk/ibinder_jni.cpp
new file mode 100644
index 0000000..baea2e8
--- /dev/null
+++ b/libs/binder/ndk/ibinder_jni.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include <android/binder_ibinder_jni.h>
+#include "ibinder_internal.h"
+
+#include <android_util_Binder.h>
+
+using ::android::IBinder;
+using ::android::ibinderForJavaObject;
+using ::android::javaObjectForIBinder;
+using ::android::sp;
+
+AIBinder* AIBinder_fromJavaBinder(JNIEnv* env, jobject binder) {
+ sp<IBinder> ibinder = ibinderForJavaObject(env, binder);
+
+ sp<AIBinder> cbinder = ABpBinder::lookupOrCreateFromBinder(ibinder);
+ AIBinder_incStrong(cbinder.get());
+
+ return cbinder.get();
+}
+
+jobject AIBinder_toJavaBinder(JNIEnv* env, AIBinder* binder) {
+ if (binder == nullptr) {
+ return nullptr;
+ }
+
+ return javaObjectForIBinder(env, binder->getBinder());
+}
diff --git a/libs/binder/ndk/include_apex/android/binder_manager.h b/libs/binder/ndk/include_apex/android/binder_manager.h
new file mode 100644
index 0000000..b8f38ba
--- /dev/null
+++ b/libs/binder/ndk/include_apex/android/binder_manager.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 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 <android/binder_ibinder.h>
+
+__BEGIN_DECLS
+
+/**
+ * This registers the service with the default service manager under this instance name.
+ */
+binder_status_t AServiceManager_addService(AIBinder* binder, const char* instance);
+
+/**
+ * Gets a binder object with this specific instance name. Blocks for a couple of seconds waiting on
+ * it. This also implicitly calls AIBinder_incStrong (so the caller of this function is responsible
+ * for calling AIBinder_decStrong).
+ */
+__attribute__((warn_unused_result)) AIBinder* AServiceManager_getService(const char* instance);
+
+__END_DECLS
diff --git a/libs/binder/ndk/include_apex/android/binder_process.h b/libs/binder/ndk/include_apex/android/binder_process.h
new file mode 100644
index 0000000..69e6387
--- /dev/null
+++ b/libs/binder/ndk/include_apex/android/binder_process.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 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 <stdint.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+/**
+ * This creates a threadpool for incoming binder transactions if it has not already been created.
+ */
+void ABinderProcess_startThreadPool();
+/**
+ * This sets the maximum number of threads that can be started in the threadpool. By default, after
+ * startThreadPool is called, this is one. If it is called additional times, it will only prevent
+ * the kernel from starting new threads and will not delete already existing threads.
+ */
+bool ABinderProcess_setThreadPoolMaxThreadCount(uint32_t numThreads);
+/**
+ * This adds the current thread to the threadpool. This may cause the threadpool to exceed the
+ * maximum size.
+ */
+void ABinderProcess_joinThreadPool();
+
+__END_DECLS
diff --git a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
new file mode 100644
index 0000000..cc0a29d
--- /dev/null
+++ b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 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.
+ */
+
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_auto_utils.h
+ * @brief These objects provide a more C++-like thin interface to the .
+ */
+
+#pragma once
+
+#include <android/binder_ibinder.h>
+#include <android/binder_parcel.h>
+#include <android/binder_status.h>
+
+#include <assert.h>
+
+#ifdef __cplusplus
+
+#include <cstddef>
+
+namespace ndk {
+
+/**
+ * Represents one strong pointer to an AIBinder object.
+ */
+class SpAIBinder {
+public:
+ /**
+ * Takes ownership of one strong refcount of binder.
+ */
+ explicit SpAIBinder(AIBinder* binder = nullptr) : mBinder(binder) {}
+
+ /**
+ * Convenience operator for implicitly constructing an SpAIBinder from nullptr. This is not
+ * explicit because it is not taking ownership of anything.
+ */
+ SpAIBinder(std::nullptr_t) : SpAIBinder() {}
+
+ /**
+ * This will delete the underlying object if it exists. See operator=.
+ */
+ SpAIBinder(const SpAIBinder& other) { *this = other; }
+
+ /**
+ * This deletes the underlying object if it exists. See set.
+ */
+ ~SpAIBinder() { set(nullptr); }
+
+ /**
+ * This takes ownership of a binder from another AIBinder object but it does not affect the
+ * ownership of that other object.
+ */
+ SpAIBinder& operator=(const SpAIBinder& other) {
+ AIBinder_incStrong(other.mBinder);
+ set(other.mBinder);
+ return *this;
+ }
+
+ /**
+ * Takes ownership of one strong refcount of binder
+ */
+ void set(AIBinder* binder) {
+ AIBinder* old = *const_cast<AIBinder* volatile*>(&mBinder);
+ if (old != nullptr) AIBinder_decStrong(old);
+ if (old != *const_cast<AIBinder* volatile*>(&mBinder)) {
+ __assert(__FILE__, __LINE__, "Race detected.");
+ }
+ mBinder = binder;
+ }
+
+ /**
+ * This returns the underlying binder object for transactions. If it is used to create another
+ * SpAIBinder object, it should first be incremented.
+ */
+ AIBinder* get() const { return mBinder; }
+
+ /**
+ * This allows the value in this class to be set from beneath it. If you call this method and
+ * then change the value of T*, you must take ownership of the value you are replacing and add
+ * ownership to the object that is put in here.
+ *
+ * Recommended use is like this:
+ * SpAIBinder a; // will be nullptr
+ * SomeInitFunction(a.getR()); // value is initialized with refcount
+ *
+ * Other usecases are discouraged.
+ *
+ */
+ AIBinder** getR() { return &mBinder; }
+
+private:
+ AIBinder* mBinder = nullptr;
+};
+
+/**
+ * This baseclass owns a single object, used to make various classes RAII.
+ */
+template <typename T, void (*Destroy)(T*)>
+class ScopedAResource {
+public:
+ /**
+ * Takes ownership of t.
+ */
+ explicit ScopedAResource(T* t = nullptr) : mT(t) {}
+
+ /**
+ * This deletes the underlying object if it exists. See set.
+ */
+ ~ScopedAResource() { set(nullptr); }
+
+ /**
+ * Takes ownership of t.
+ */
+ void set(T* t) {
+ Destroy(mT);
+ mT = t;
+ }
+
+ /**
+ * This returns the underlying object to be modified but does not affect ownership.
+ */
+ T* get() { return mT; }
+
+ /**
+ * This returns the const underlying object but does not affect ownership.
+ */
+ const T* get() const { return mT; }
+
+ /**
+ * This allows the value in this class to be set from beneath it. If you call this method and
+ * then change the value of T*, you must take ownership of the value you are replacing and add
+ * ownership to the object that is put in here.
+ *
+ * Recommended use is like this:
+ * ScopedAResource<T> a; // will be nullptr
+ * SomeInitFunction(a.getR()); // value is initialized with refcount
+ *
+ * Other usecases are discouraged.
+ *
+ */
+ T** getR() { return &mT; }
+
+ // copy-constructing, or move/copy assignment is disallowed
+ ScopedAResource(const ScopedAResource&) = delete;
+ ScopedAResource& operator=(const ScopedAResource&) = delete;
+ ScopedAResource& operator=(ScopedAResource&&) = delete;
+
+ // move-constructing is okay
+ ScopedAResource(ScopedAResource&&) = default;
+
+private:
+ T* mT;
+};
+
+/**
+ * Convenience wrapper. See AParcel.
+ */
+class ScopedAParcel : public ScopedAResource<AParcel, AParcel_delete> {
+public:
+ /**
+ * Takes ownership of a.
+ */
+ explicit ScopedAParcel(AParcel* a = nullptr) : ScopedAResource(a) {}
+ ~ScopedAParcel() {}
+ ScopedAParcel(ScopedAParcel&&) = default;
+};
+
+/**
+ * Convenience wrapper. See AStatus.
+ */
+class ScopedAStatus : public ScopedAResource<AStatus, AStatus_delete> {
+public:
+ /**
+ * Takes ownership of a.
+ */
+ explicit ScopedAStatus(AStatus* a = nullptr) : ScopedAResource(a) {}
+ ~ScopedAStatus() {}
+ ScopedAStatus(ScopedAStatus&&) = default;
+
+ /**
+ * See AStatus_isOk.
+ */
+ bool isOk() { return get() != nullptr && AStatus_isOk(get()); }
+};
+
+/**
+ * Convenience wrapper. See AIBinder_DeathRecipient.
+ */
+class ScopedAIBinder_DeathRecipient
+ : public ScopedAResource<AIBinder_DeathRecipient, AIBinder_DeathRecipient_delete> {
+public:
+ /**
+ * Takes ownership of a.
+ */
+ explicit ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient* a = nullptr)
+ : ScopedAResource(a) {}
+ ~ScopedAIBinder_DeathRecipient() {}
+ ScopedAIBinder_DeathRecipient(ScopedAIBinder_DeathRecipient&&) = default;
+};
+
+/**
+ * Convenience wrapper. See AIBinder_Weak.
+ */
+class ScopedAIBinder_Weak : public ScopedAResource<AIBinder_Weak, AIBinder_Weak_delete> {
+public:
+ /**
+ * Takes ownership of a.
+ */
+ explicit ScopedAIBinder_Weak(AIBinder_Weak* a = nullptr) : ScopedAResource(a) {}
+ ~ScopedAIBinder_Weak() {}
+ ScopedAIBinder_Weak(ScopedAIBinder_Weak&&) = default;
+
+ /**
+ * See AIBinder_Weak_promote.
+ */
+ SpAIBinder promote() { return SpAIBinder(AIBinder_Weak_promote(get())); }
+};
+
+} // namespace ndk
+
+#endif // __cplusplus
+
+/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
new file mode 100644
index 0000000..c222c16
--- /dev/null
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 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.
+ */
+
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_ibinder.h
+ * @brief Object which can receive transactions and be sent across processes.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+#include <android/binder_parcel.h>
+#include <android/binder_status.h>
+
+__BEGIN_DECLS
+#if __ANDROID_API__ >= __ANDROID_API_Q__
+
+// Also see TF_* in kernel's binder.h
+typedef uint32_t binder_flags_t;
+enum {
+ /**
+ * The transaction will be dispatched and then returned to the caller. The outgoing process
+ * cannot block a call made by this, and execution of the call will not be waited on. An error
+ * can still be returned if the call is unable to be processed by the binder driver. All oneway
+ * calls are guaranteed to be ordered if they are sent on the same AIBinder object.
+ */
+ FLAG_ONEWAY = 0x01,
+};
+
+// Also see IBinder.h in libbinder
+typedef uint32_t transaction_code_t;
+enum {
+ /**
+ * The first transaction code available for user commands (inclusive).
+ */
+ FIRST_CALL_TRANSACTION = 0x00000001,
+ /**
+ * The last transaction code available for user commands (inclusive).
+ */
+ LAST_CALL_TRANSACTION = 0x00ffffff,
+};
+
+/**
+ * Represents a type of AIBinder object which can be sent out.
+ */
+struct AIBinder_Class;
+typedef struct AIBinder_Class AIBinder_Class;
+
+/**
+ * Represents a local or remote object which can be used for IPC or which can itself be sent.
+ *
+ * This object has a refcount associated with it and will be deleted when its refcount reaches zero.
+ * How methods interactive with this refcount is described below. When using this API, it is
+ * intended for a client of a service to hold a strong reference to that service. This also means
+ * that user data typically should hold a strong reference to a local AIBinder object. A remote
+ * AIBinder object automatically holds a strong reference to the AIBinder object in the server's
+ * process. A typically memory layout looks like this:
+ *
+ * Key:
+ * ---> Ownership/a strong reference
+ * ...> A weak reference
+ *
+ * (process boundary)
+ * |
+ * MyInterface ---> AIBinder_Weak | ProxyForMyInterface
+ * ^ . | |
+ * | . | |
+ * | v | v
+ * UserData <--- AIBinder <-|- AIBinder
+ * |
+ *
+ * In this way, you'll notice that a proxy for the interface holds a strong reference to the
+ * implementation and that in the server process, the AIBinder object which was sent can be resent
+ * so that the same AIBinder object always represents the same object. This allows, for instance, an
+ * implementation (usually a callback) to transfer all ownership to a remote process and
+ * automatically be deleted when the remote process is done with it or dies. Other memory models are
+ * possible, but this is the standard one.
+ *
+ * If the process containing an AIBinder dies, it is possible to be holding a strong reference to
+ * an object which does not exist. In this case, transactions to this binder will return
+ * STATUS_DEAD_OBJECT. See also AIBinder_linkToDeath, AIBinder_unlinkToDeath, and AIBinder_isAlive.
+ *
+ * Once an AIBinder is created, anywhere it is passed (remotely or locally), there is a 1-1
+ * correspondence between the address of an AIBinder and the object it represents. This means that
+ * when two AIBinder pointers point to the same address, they represent the same object (whether
+ * that object is local or remote). This correspondance can be broken accidentally if AIBinder_new
+ * is erronesouly called to create the same object multiple times.
+ */
+struct AIBinder;
+typedef struct AIBinder AIBinder;
+
+/**
+ * The AIBinder object associated with this can be retrieved if it is still alive so that it can be
+ * re-used. The intention of this is to enable the same AIBinder object to always represent the same
+ * object.
+ */
+struct AIBinder_Weak;
+typedef struct AIBinder_Weak AIBinder_Weak;
+
+/**
+ * Represents a handle on a death notification. See AIBinder_linkToDeath/AIBinder_unlinkToDeath.
+ */
+struct AIBinder_DeathRecipient;
+typedef struct AIBinder_DeathRecipient AIBinder_DeathRecipient;
+
+/**
+ * This is called whenever a new AIBinder object is needed of a specific class.
+ *
+ * These arguments are passed from AIBinder_new. The return value is stored and can be retrieved
+ * using AIBinder_getUserData.
+ */
+typedef void* (*AIBinder_Class_onCreate)(void* args);
+
+/**
+ * This is called whenever an AIBinder object is no longer referenced and needs destroyed.
+ *
+ * Typically, this just deletes whatever the implementation is.
+ */
+typedef void (*AIBinder_Class_onDestroy)(void* userData);
+
+/**
+ * This is called whenever a transaction needs to be processed by a local implementation.
+ */
+typedef binder_status_t (*AIBinder_Class_onTransact)(AIBinder* binder, transaction_code_t code,
+ const AParcel* in, AParcel* out);
+
+/**
+ * An interfaceDescriptor uniquely identifies the type of object that is being created. This is used
+ * internally for sanity checks on transactions.
+ *
+ * None of these parameters can be nullptr.
+ *
+ * This is created one time during library initialization and cleaned up when the process exits or
+ * execs.
+ */
+__attribute__((warn_unused_result)) AIBinder_Class* AIBinder_Class_define(
+ const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate,
+ AIBinder_Class_onDestroy onDestroy, AIBinder_Class_onTransact onTransact)
+ __INTRODUCED_IN(29);
+
+/**
+ * Creates a new binder object of the appropriate class.
+ *
+ * Ownership of args is passed to this object. The lifecycle is implemented with AIBinder_incStrong
+ * and AIBinder_decStrong. When the reference count reaches zero, onDestroy is called.
+ *
+ * When this is called, the refcount is implicitly 1. So, calling decStrong exactly one time is
+ * required to delete this object.
+ *
+ * Once an AIBinder object is created using this API, re-creating that AIBinder for the same
+ * instance of the same class will break pointer equality for that specific AIBinder object. For
+ * instance, if someone erroneously created two AIBinder instances representing the same callback
+ * object and passed one to a hypothetical addCallback function and then later another one to a
+ * hypothetical removeCallback function, the remote process would have no way to determine that
+ * these two objects are actually equal using the AIBinder pointer alone (which they should be able
+ * to do). Also see the suggested memory ownership model suggested above.
+ */
+__attribute__((warn_unused_result)) AIBinder* AIBinder_new(const AIBinder_Class* clazz, void* args)
+ __INTRODUCED_IN(29);
+
+/**
+ * If this is hosted in a process other than the current one.
+ */
+bool AIBinder_isRemote(const AIBinder* binder) __INTRODUCED_IN(29);
+
+/**
+ * If this binder is known to be alive. This will not send a transaction to a remote process and
+ * returns a result based on the last known information. That is, whenever a transaction is made,
+ * this is automatically updated to reflect the current alive status of this binder. This will be
+ * updated as the result of a transaction made using AIBinder_transact, but it will also be updated
+ * based on the results of bookkeeping or other transactions made internally.
+ */
+bool AIBinder_isAlive(const AIBinder* binder) __INTRODUCED_IN(29);
+
+/**
+ * Built-in transaction for all binder objects. This sends a transaction which will immediately
+ * return. Usually this is used to make sure that a binder is alive, as a placeholder call, or as a
+ * sanity check.
+ */
+binder_status_t AIBinder_ping(AIBinder* binder) __INTRODUCED_IN(29);
+
+/**
+ * Registers for notifications that the associated binder is dead. The same death recipient may be
+ * associated with multiple different binders. If the binder is local, then no death recipient will
+ * be given (since if the local process dies, then no recipient will exist to recieve a
+ * transaction). The cookie is passed to recipient in the case that this binder dies and can be
+ * null. The exact cookie must also be used to unlink this transaction (see AIBinder_linkToDeath).
+ * This function may return a binder transaction failure. The cookie can be used both for
+ * identification and holding user data.
+ *
+ * If binder is local, this will return STATUS_INVALID_OPERATION.
+ */
+binder_status_t AIBinder_linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
+ void* cookie) __INTRODUCED_IN(29);
+
+/**
+ * Stops registration for the associated binder dying. Does not delete the recipient. This function
+ * may return a binder transaction failure and in case the death recipient cannot be found, it
+ * returns STATUS_NAME_NOT_FOUND.
+ */
+binder_status_t AIBinder_unlinkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
+ void* cookie) __INTRODUCED_IN(29);
+
+/**
+ * This can only be called if a strong reference to this object already exists in process.
+ */
+void AIBinder_incStrong(AIBinder* binder) __INTRODUCED_IN(29);
+
+/**
+ * This will delete the object and call onDestroy once the refcount reaches zero.
+ */
+void AIBinder_decStrong(AIBinder* binder) __INTRODUCED_IN(29);
+
+/**
+ * For debugging only!
+ */
+int32_t AIBinder_debugGetRefCount(AIBinder* binder) __INTRODUCED_IN(29);
+
+/**
+ * This sets the class of an AIBinder object. This checks to make sure the remote object is of
+ * the expected class. A class must be set in order to use transactions on an AIBinder object.
+ * However, if an object is just intended to be passed through to another process or used as a
+ * handle this need not be called.
+ *
+ * This returns true if the class association succeeds. If it fails, no change is made to the
+ * binder object.
+ */
+bool AIBinder_associateClass(AIBinder* binder, const AIBinder_Class* clazz) __INTRODUCED_IN(29);
+
+/**
+ * Returns the class that this binder was constructed with or associated with.
+ */
+const AIBinder_Class* AIBinder_getClass(AIBinder* binder) __INTRODUCED_IN(29);
+
+/**
+ * Value returned by onCreate for a local binder. For stateless classes (if onCreate returns
+ * nullptr), this also returns nullptr. For a remote binder, this will always return nullptr.
+ */
+void* AIBinder_getUserData(AIBinder* binder) __INTRODUCED_IN(29);
+
+/**
+ * A transaction is a series of calls to these functions which looks this
+ * - call AIBinder_prepareTransaction
+ * - fill out the in parcel with parameters (lifetime of the 'in' variable)
+ * - call AIBinder_transact
+ * - read results from the out parcel (lifetime of the 'out' variable)
+ */
+
+/**
+ * Creates a parcel to start filling out for a transaction. This may add data to the parcel for
+ * security, debugging, or other purposes. This parcel is to be sent via AIBinder_transact and it
+ * represents the input data to the transaction. It is recommended to check if the object is local
+ * and call directly into its user data before calling this as the parceling and unparceling cost
+ * can be avoided. This AIBinder must be either built with a class or associated with a class before
+ * using this API.
+ *
+ * This does not affect the ownership of binder. When this function succeeds, the in parcel's
+ * ownership is passed to the caller. At this point, the parcel can be filled out and passed to
+ * AIBinder_transact. Alternatively, if there is an error while filling out the parcel, it can be
+ * deleted with AParcel_delete.
+ */
+binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in) __INTRODUCED_IN(29);
+
+/**
+ * Transact using a parcel created from AIBinder_prepareTransaction. This actually communicates with
+ * the object representing this binder object. This also passes out a parcel to be used for the
+ * return transaction. This takes ownership of the in parcel and automatically deletes it after it
+ * is sent to the remote process. The output parcel is the result of the transaction. If the
+ * transaction has FLAG_ONEWAY, the out parcel will be empty. Otherwise, this will block until the
+ * remote process has processed the transaction, and the out parcel will contain the output data
+ * from transaction.
+ *
+ * This does not affect the ownership of binder. The out parcel's ownership is passed to the caller
+ * and must be released with AParcel_delete when finished reading.
+ */
+binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, AParcel** in,
+ AParcel** out, binder_flags_t flags) __INTRODUCED_IN(29);
+
+/**
+ * This does not take any ownership of the input binder, but it can be used to retrieve it if
+ * something else in some process still holds a reference to it.
+ */
+__attribute__((warn_unused_result)) AIBinder_Weak* AIBinder_Weak_new(AIBinder* binder)
+ __INTRODUCED_IN(29);
+
+/**
+ * Deletes the weak reference. This will have no impact on the lifetime of the binder.
+ */
+void AIBinder_Weak_delete(AIBinder_Weak* weakBinder) __INTRODUCED_IN(29);
+
+/**
+ * If promotion succeeds, result will have one strong refcount added to it. Otherwise, this returns
+ * nullptr.
+ */
+__attribute__((warn_unused_result)) AIBinder* AIBinder_Weak_promote(AIBinder_Weak* weakBinder)
+ __INTRODUCED_IN(29);
+
+/**
+ * This function is executed on death receipt. See AIBinder_linkToDeath/AIBinder_unlinkToDeath.
+ */
+typedef void (*AIBinder_DeathRecipient_onBinderDied)(void* cookie) __INTRODUCED_IN(29);
+
+/**
+ * Creates a new binder death recipient. This can be attached to multiple different binder objects.
+ */
+__attribute__((warn_unused_result)) AIBinder_DeathRecipient* AIBinder_DeathRecipient_new(
+ AIBinder_DeathRecipient_onBinderDied onBinderDied) __INTRODUCED_IN(29);
+
+/**
+ * Deletes a binder death recipient. It is not necessary to call AIBinder_unlinkToDeath before
+ * calling this as these will all be automatically unlinked.
+ */
+void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient* recipient) __INTRODUCED_IN(29);
+
+#endif //__ANDROID_API__ >= __ANDROID_API_Q__
+__END_DECLS
+
+/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h b/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
new file mode 100644
index 0000000..81fb3c5
--- /dev/null
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 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.
+ */
+
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_ibinder_jni.h
+ * @brief Conversions between AIBinder and android.os.IBinder
+ */
+
+#pragma once
+
+#include <android/binder_ibinder.h>
+
+#include <jni.h>
+
+__BEGIN_DECLS
+#if __ANDROID_API__ >= __ANDROID_API_Q__
+
+/**
+ * Converts an android.os.IBinder object into an AIBinder* object.
+ *
+ * If either env or the binder is null, null is returned. If this binder object was originally an
+ * AIBinder object, the original object is returned. The returned object has one refcount
+ * associated with it, and so this should be accompanied with an AIBinder_decStrong call.
+ */
+__attribute__((warn_unused_result)) AIBinder* AIBinder_fromJavaBinder(JNIEnv* env, jobject binder)
+ __INTRODUCED_IN(29);
+
+/**
+ * Converts an AIBinder* object into an android.os.IBinder object.
+ *
+ * If either env or the binder is null, null is returned. If this binder object was originally an
+ * IBinder object, the original java object will be returned.
+ */
+__attribute__((warn_unused_result)) jobject AIBinder_toJavaBinder(JNIEnv* env, AIBinder* binder)
+ __INTRODUCED_IN(29);
+
+#endif //__ANDROID_API__ >= __ANDROID_API_Q__
+__END_DECLS
+
+/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_interface_utils.h b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
new file mode 100644
index 0000000..e37c388
--- /dev/null
+++ b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 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.
+ */
+
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_interface_utils.h
+ * @brief This provides common C++ classes for common operations and as base classes for C++
+ * interfaces.
+ */
+
+#pragma once
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_ibinder.h>
+
+#include <assert.h>
+
+#ifdef __cplusplus
+
+#include <memory>
+#include <mutex>
+
+namespace ndk {
+
+/**
+ * analog using std::shared_ptr for internally held refcount
+ *
+ * ref must be called at least one time during the lifetime of this object. The recommended way to
+ * construct this object is with SharedRefBase::make.
+ */
+class SharedRefBase {
+public:
+ SharedRefBase() {}
+ virtual ~SharedRefBase() {
+ std::call_once(mFlagThis, [&]() {
+ __assert(__FILE__, __LINE__, "SharedRefBase: no ref created during lifetime");
+ });
+ }
+
+ /**
+ * A shared_ptr must be held to this object when this is called. This must be called once during
+ * the lifetime of this object.
+ */
+ std::shared_ptr<SharedRefBase> ref() {
+ std::shared_ptr<SharedRefBase> thiz = mThis.lock();
+
+ std::call_once(mFlagThis, [&]() { mThis = thiz = std::shared_ptr<SharedRefBase>(this); });
+
+ return thiz;
+ }
+
+ /**
+ * Convenience method for a ref (see above) which automatically casts to the desired child type.
+ */
+ template <typename CHILD>
+ std::shared_ptr<CHILD> ref() {
+ return std::static_pointer_cast<CHILD>(ref());
+ }
+
+ /**
+ * Convenience method for making an object directly with a reference.
+ */
+ template <class T, class... Args>
+ static std::shared_ptr<T> make(Args&&... args) {
+ T* t = new T(std::forward<Args>(args)...);
+ return t->template ref<T>();
+ }
+
+private:
+ std::once_flag mFlagThis;
+ std::weak_ptr<SharedRefBase> mThis;
+};
+
+/**
+ * wrapper analog to IInterface
+ */
+class ICInterface : public SharedRefBase {
+public:
+ ICInterface() {}
+ virtual ~ICInterface() {}
+
+ /**
+ * This either returns the single existing implementation or creates a new implementation.
+ */
+ virtual SpAIBinder asBinder() = 0;
+
+ /**
+ * Returns whether this interface is in a remote process. If it cannot be determined locally,
+ * this will be checked using AIBinder_isRemote.
+ */
+ virtual bool isRemote() = 0;
+};
+
+/**
+ * implementation of IInterface for server (n = native)
+ */
+template <typename INTERFACE>
+class BnCInterface : public INTERFACE {
+public:
+ BnCInterface() {}
+ virtual ~BnCInterface() {}
+
+ SpAIBinder asBinder() override;
+
+ bool isRemote() override { return true; }
+
+protected:
+ /**
+ * This function should only be called by asBinder. Otherwise, there is a possibility of
+ * multiple AIBinder* objects being created for the same instance of an object.
+ */
+ virtual SpAIBinder createBinder() = 0;
+
+private:
+ std::mutex mMutex; // for asBinder
+ ScopedAIBinder_Weak mWeakBinder;
+};
+
+/**
+ * implementation of IInterface for client (p = proxy)
+ */
+template <typename INTERFACE>
+class BpCInterface : public INTERFACE {
+public:
+ BpCInterface(const SpAIBinder& binder) : mBinder(binder) {}
+ virtual ~BpCInterface() {}
+
+ SpAIBinder asBinder() override;
+
+ bool isRemote() override { return AIBinder_isRemote(mBinder.get()); }
+
+private:
+ SpAIBinder mBinder;
+};
+
+template <typename INTERFACE>
+SpAIBinder BnCInterface<INTERFACE>::asBinder() {
+ std::lock_guard<std::mutex> l(mMutex);
+
+ SpAIBinder binder;
+ if (mWeakBinder.get() != nullptr) {
+ binder.set(AIBinder_Weak_promote(mWeakBinder.get()));
+ }
+ if (binder.get() == nullptr) {
+ binder = createBinder();
+ mWeakBinder.set(AIBinder_Weak_new(binder.get()));
+ }
+
+ return binder;
+}
+
+template <typename INTERFACE>
+SpAIBinder BpCInterface<INTERFACE>::asBinder() {
+ return mBinder;
+}
+
+} // namespace ndk
+
+#endif // __cplusplus
+
+/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
new file mode 100644
index 0000000..d36b3c0
--- /dev/null
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 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.
+ */
+
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_parcel.h
+ * @brief A collection of data that can be sent as a single packet.
+ */
+
+#pragma once
+
+#include <sys/cdefs.h>
+
+#include <android/binder_status.h>
+
+struct AIBinder;
+typedef struct AIBinder AIBinder;
+
+__BEGIN_DECLS
+#if __ANDROID_API__ >= __ANDROID_API_Q__
+
+/**
+ * This object represents a package of data that can be sent between processes. When transacting, an
+ * instance of it is automatically created to be used for the transaction. When two processes use
+ * binder to communicate, they must agree on a format of this parcel to be used in order to transfer
+ * data. This is usually done in an IDL (see AIDL, specificially).
+ */
+struct AParcel;
+typedef struct AParcel AParcel;
+
+/**
+ * Cleans up a parcel.
+ */
+void AParcel_delete(AParcel* parcel) __INTRODUCED_IN(29);
+
+/**
+ * This is called to allocate an array with a given length. If allocation fails, null should be
+ * returned.
+ */
+typedef void* (*AParcel_arrayReallocator)(void* vectorData, size_t length);
+
+// @START-PRIMITIVE-VECTOR-GETTERS
+/**
+ * This is called to get the underlying data from an arrayData object.
+ *
+ * This will never be called for an empty array.
+ */
+typedef int32_t* (*AParcel_int32ArrayGetter)(void* arrayData);
+
+/**
+ * This is called to get the underlying data from an arrayData object.
+ *
+ * This will never be called for an empty array.
+ */
+typedef uint32_t* (*AParcel_uint32ArrayGetter)(void* arrayData);
+
+/**
+ * This is called to get the underlying data from an arrayData object.
+ *
+ * This will never be called for an empty array.
+ */
+typedef int64_t* (*AParcel_int64ArrayGetter)(void* arrayData);
+
+/**
+ * This is called to get the underlying data from an arrayData object.
+ *
+ * This will never be called for an empty array.
+ */
+typedef uint64_t* (*AParcel_uint64ArrayGetter)(void* arrayData);
+
+/**
+ * This is called to get the underlying data from an arrayData object.
+ *
+ * This will never be called for an empty array.
+ */
+typedef float* (*AParcel_floatArrayGetter)(void* arrayData);
+
+/**
+ * This is called to get the underlying data from an arrayData object.
+ *
+ * This will never be called for an empty array.
+ */
+typedef double* (*AParcel_doubleArrayGetter)(void* arrayData);
+
+/**
+ * This is called to get the underlying data from an arrayData object.
+ *
+ * This will never be called for an empty array.
+ */
+typedef bool (*AParcel_boolArrayGetter)(const void* arrayData, size_t index);
+
+/**
+ * This is called to set an underlying value in an arrayData object at index.
+ */
+typedef void (*AParcel_boolArraySetter)(void* arrayData, size_t index, bool value);
+
+/**
+ * This is called to get the underlying data from an arrayData object.
+ *
+ * This will never be called for an empty array.
+ */
+typedef char16_t* (*AParcel_charArrayGetter)(void* arrayData);
+
+/**
+ * This is called to get the underlying data from an arrayData object.
+ *
+ * This will never be called for an empty array.
+ */
+typedef int8_t* (*AParcel_byteArrayGetter)(void* arrayData);
+
+// @END-PRIMITIVE-VECTOR-GETTERS
+
+/**
+ * This is called to allocate a buffer
+ *
+ * The length here includes the space required to insert a '\0' for a properly formed c-str. If the
+ * buffer returned from this function is retStr, it will be filled by AParcel_readString with the
+ * data from the remote process, and it will be filled such that retStr[length] == '\0'.
+ *
+ * If allocation fails, null should be returned.
+ */
+typedef void* (*AParcel_stringReallocator)(void* stringData, size_t length);
+
+/**
+ * This is called to get the buffer from a stringData object.
+ */
+typedef char* (*AParcel_stringGetter)(void* stringData);
+
+/**
+ * Writes an AIBinder to the next location in a non-null parcel. Can be null.
+ */
+binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder) __INTRODUCED_IN(29);
+
+/**
+ * Reads an AIBinder from the next location in a non-null parcel. This will fail if the binder is
+ * non-null. One strong ref-count of ownership is passed to the caller of this function.
+ */
+binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binder)
+ __INTRODUCED_IN(29);
+
+/**
+ * Reads an AIBinder from the next location in a non-null parcel. This may read a null. One strong
+ * ref-count of ownership is passed to the caller of this function.
+ */
+binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder** binder)
+ __INTRODUCED_IN(29);
+
+/**
+ * Writes an AStatus object to the next location in a non-null parcel.
+ *
+ * If the status is considered to be a low-level status and has no additional information other
+ * than a binder_status_t (for instance, if it is created with AStatus_fromStatus), then that
+ * status will be returned from this method and nothing will be written to the parcel. If either
+ * this happens or if writing the status object itself fails, the return value from this function
+ * should be propagated to the client, and AParcel_readStatusHeader shouldn't be called.
+ */
+binder_status_t AParcel_writeStatusHeader(AParcel* parcel, const AStatus* status)
+ __INTRODUCED_IN(29);
+
+/**
+ * Reads an AStatus from the next location in a non-null parcel. Ownership is passed to the caller
+ * of this function.
+ */
+binder_status_t AParcel_readStatusHeader(const AParcel* parcel, AStatus** status)
+ __INTRODUCED_IN(29);
+
+/**
+ * Writes string value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeString(AParcel* parcel, const char* string, size_t length)
+ __INTRODUCED_IN(29);
+
+/**
+ * Reads and allocates string value from the next location in a non-null parcel.
+ *
+ * Data is passed to the string allocator once the string size is known. This data should be used to
+ * point to some kind of string data. For instance, it could be a char*, and the string allocator
+ * could be realloc. Then the getter would simply be a cast to char*. In more complicated cases,
+ * stringData could be a structure containing additional string data.
+ *
+ * If this function returns a success, the buffer returned by allocator when passed stringData will
+ * contain a null-terminated c-str read from the binder.
+ */
+binder_status_t AParcel_readString(const AParcel* parcel, AParcel_stringReallocator reallocator,
+ AParcel_stringGetter getter, void** stringData)
+ __INTRODUCED_IN(29);
+
+// @START-PRIMITIVE-READ-WRITE
+/**
+ * Writes int32_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeInt32(AParcel* parcel, int32_t value) __INTRODUCED_IN(29);
+
+/**
+ * Writes uint32_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeUint32(AParcel* parcel, uint32_t value) __INTRODUCED_IN(29);
+
+/**
+ * Writes int64_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeInt64(AParcel* parcel, int64_t value) __INTRODUCED_IN(29);
+
+/**
+ * Writes uint64_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeUint64(AParcel* parcel, uint64_t value) __INTRODUCED_IN(29);
+
+/**
+ * Writes float value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeFloat(AParcel* parcel, float value) __INTRODUCED_IN(29);
+
+/**
+ * Writes double value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeDouble(AParcel* parcel, double value) __INTRODUCED_IN(29);
+
+/**
+ * Writes bool value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeBool(AParcel* parcel, bool value) __INTRODUCED_IN(29);
+
+/**
+ * Writes char16_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeChar(AParcel* parcel, char16_t value) __INTRODUCED_IN(29);
+
+/**
+ * Writes int8_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeByte(AParcel* parcel, int8_t value) __INTRODUCED_IN(29);
+
+/**
+ * Reads into int32_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readInt32(const AParcel* parcel, int32_t* value) __INTRODUCED_IN(29);
+
+/**
+ * Reads into uint32_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readUint32(const AParcel* parcel, uint32_t* value) __INTRODUCED_IN(29);
+
+/**
+ * Reads into int64_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readInt64(const AParcel* parcel, int64_t* value) __INTRODUCED_IN(29);
+
+/**
+ * Reads into uint64_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readUint64(const AParcel* parcel, uint64_t* value) __INTRODUCED_IN(29);
+
+/**
+ * Reads into float value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readFloat(const AParcel* parcel, float* value) __INTRODUCED_IN(29);
+
+/**
+ * Reads into double value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readDouble(const AParcel* parcel, double* value) __INTRODUCED_IN(29);
+
+/**
+ * Reads into bool value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readBool(const AParcel* parcel, bool* value) __INTRODUCED_IN(29);
+
+/**
+ * Reads into char16_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readChar(const AParcel* parcel, char16_t* value) __INTRODUCED_IN(29);
+
+/**
+ * Reads into int8_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readByte(const AParcel* parcel, int8_t* value) __INTRODUCED_IN(29);
+
+/**
+ * Writes an array of int32_t to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeInt32Array(AParcel* parcel, const int32_t* value, size_t length)
+ __INTRODUCED_IN(29);
+
+/**
+ * Writes an array of uint32_t to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeUint32Array(AParcel* parcel, const uint32_t* value, size_t length)
+ __INTRODUCED_IN(29);
+
+/**
+ * Writes an array of int64_t to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeInt64Array(AParcel* parcel, const int64_t* value, size_t length)
+ __INTRODUCED_IN(29);
+
+/**
+ * Writes an array of uint64_t to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeUint64Array(AParcel* parcel, const uint64_t* value, size_t length)
+ __INTRODUCED_IN(29);
+
+/**
+ * Writes an array of float to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeFloatArray(AParcel* parcel, const float* value, size_t length)
+ __INTRODUCED_IN(29);
+
+/**
+ * Writes an array of double to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeDoubleArray(AParcel* parcel, const double* value, size_t length)
+ __INTRODUCED_IN(29);
+
+/**
+ * Writes an array of bool to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeBoolArray(AParcel* parcel, const void* arrayData,
+ AParcel_boolArrayGetter getter, size_t length)
+ __INTRODUCED_IN(29);
+
+/**
+ * Writes an array of char16_t to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeCharArray(AParcel* parcel, const char16_t* value, size_t length)
+ __INTRODUCED_IN(29);
+
+/**
+ * Writes an array of int8_t to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeByteArray(AParcel* parcel, const int8_t* value, size_t length)
+ __INTRODUCED_IN(29);
+
+/**
+ * Reads an array of int32_t from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readInt32Array(const AParcel* parcel, void** arrayData,
+ AParcel_arrayReallocator reallocator,
+ AParcel_int32ArrayGetter getter) __INTRODUCED_IN(29);
+
+/**
+ * Reads an array of uint32_t from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readUint32Array(const AParcel* parcel, void** arrayData,
+ AParcel_arrayReallocator reallocator,
+ AParcel_uint32ArrayGetter getter) __INTRODUCED_IN(29);
+
+/**
+ * Reads an array of int64_t from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readInt64Array(const AParcel* parcel, void** arrayData,
+ AParcel_arrayReallocator reallocator,
+ AParcel_int64ArrayGetter getter) __INTRODUCED_IN(29);
+
+/**
+ * Reads an array of uint64_t from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readUint64Array(const AParcel* parcel, void** arrayData,
+ AParcel_arrayReallocator reallocator,
+ AParcel_uint64ArrayGetter getter) __INTRODUCED_IN(29);
+
+/**
+ * Reads an array of float from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readFloatArray(const AParcel* parcel, void** arrayData,
+ AParcel_arrayReallocator reallocator,
+ AParcel_floatArrayGetter getter) __INTRODUCED_IN(29);
+
+/**
+ * Reads an array of double from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readDoubleArray(const AParcel* parcel, void** arrayData,
+ AParcel_arrayReallocator reallocator,
+ AParcel_doubleArrayGetter getter) __INTRODUCED_IN(29);
+
+/**
+ * Reads an array of bool from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readBoolArray(const AParcel* parcel, void** arrayData,
+ AParcel_arrayReallocator reallocator,
+ AParcel_boolArraySetter setter) __INTRODUCED_IN(29);
+
+/**
+ * Reads an array of char16_t from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readCharArray(const AParcel* parcel, void** arrayData,
+ AParcel_arrayReallocator reallocator,
+ AParcel_charArrayGetter getter) __INTRODUCED_IN(29);
+
+/**
+ * Reads an array of int8_t from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readByteArray(const AParcel* parcel, void** arrayData,
+ AParcel_arrayReallocator reallocator,
+ AParcel_byteArrayGetter getter) __INTRODUCED_IN(29);
+
+// @END-PRIMITIVE-READ-WRITE
+
+#endif //__ANDROID_API__ >= __ANDROID_API_Q__
+__END_DECLS
+
+/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h b/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
new file mode 100644
index 0000000..faeb78f
--- /dev/null
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 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.
+ */
+
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_parcel_utils.h
+ * @brief A collection of helper wrappers for AParcel.
+ */
+
+#pragma once
+
+#include <android/binder_parcel.h>
+
+#ifdef __cplusplus
+
+#include <string>
+#include <vector>
+
+namespace ndk {
+
+/**
+ * This resizes a std::vector of some underlying type to the given length.
+ */
+template <typename T>
+static inline void* AParcel_stdVectorReallocator(void* vectorData, size_t length) {
+ std::vector<T>* vec = static_cast<std::vector<T>*>(vectorData);
+ if (length > vec->max_size()) return nullptr;
+
+ vec->resize(length);
+ return vec;
+}
+
+/**
+ * This retrieves the underlying contiguous vector from a corresponding vectorData.
+ */
+template <typename T>
+static inline T* AParcel_stdVectorGetter(void* vectorData) {
+ std::vector<T>* vec = static_cast<std::vector<T>*>(vectorData);
+ return vec->data();
+}
+
+/**
+ * This retrieves the underlying value in a vector which may not be contiguous at index from a
+ * corresponding vectorData.
+ */
+template <typename T>
+static inline T AParcel_stdVectorGetter(const void* vectorData, size_t index) {
+ const std::vector<T>* vec = static_cast<const std::vector<T>*>(vectorData);
+ return (*vec)[index];
+}
+
+/**
+ * This sets the underlying value in a corresponding vectorData which may not be contiguous at
+ * index.
+ */
+template <typename T>
+static inline void AParcel_stdVectorSetter(void* vectorData, size_t index, T value) {
+ std::vector<T>* vec = static_cast<std::vector<T>*>(vectorData);
+ (*vec)[index] = value;
+}
+
+/**
+ * Writes a vector to the next location in a non-null parcel.
+ */
+template <typename T>
+static inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<T>& vec);
+
+/**
+ * Reads a vector to the next location in a non-null parcel.
+ */
+template <typename T>
+static inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<T>* vec);
+
+// @START
+/**
+ * Writes a vector of int32_t to the next location in a non-null parcel.
+ */
+template <>
+inline binder_status_t AParcel_writeVector<int32_t>(AParcel* parcel,
+ const std::vector<int32_t>& vec) {
+ return AParcel_writeInt32Array(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Reads a vector of int32_t from the next location in a non-null parcel.
+ */
+template <>
+inline binder_status_t AParcel_readVector<int32_t>(const AParcel* parcel,
+ std::vector<int32_t>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readInt32Array(parcel, &vectorData, &AParcel_stdVectorReallocator<int32_t>,
+ AParcel_stdVectorGetter<int32_t>);
+}
+
+/**
+ * Writes a vector of uint32_t to the next location in a non-null parcel.
+ */
+template <>
+inline binder_status_t AParcel_writeVector<uint32_t>(AParcel* parcel,
+ const std::vector<uint32_t>& vec) {
+ return AParcel_writeUint32Array(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Reads a vector of uint32_t from the next location in a non-null parcel.
+ */
+template <>
+inline binder_status_t AParcel_readVector<uint32_t>(const AParcel* parcel,
+ std::vector<uint32_t>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readUint32Array(parcel, &vectorData, &AParcel_stdVectorReallocator<uint32_t>,
+ AParcel_stdVectorGetter<uint32_t>);
+}
+
+/**
+ * Writes a vector of int64_t to the next location in a non-null parcel.
+ */
+template <>
+inline binder_status_t AParcel_writeVector<int64_t>(AParcel* parcel,
+ const std::vector<int64_t>& vec) {
+ return AParcel_writeInt64Array(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Reads a vector of int64_t from the next location in a non-null parcel.
+ */
+template <>
+inline binder_status_t AParcel_readVector<int64_t>(const AParcel* parcel,
+ std::vector<int64_t>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readInt64Array(parcel, &vectorData, &AParcel_stdVectorReallocator<int64_t>,
+ AParcel_stdVectorGetter<int64_t>);
+}
+
+/**
+ * Writes a vector of uint64_t to the next location in a non-null parcel.
+ */
+template <>
+inline binder_status_t AParcel_writeVector<uint64_t>(AParcel* parcel,
+ const std::vector<uint64_t>& vec) {
+ return AParcel_writeUint64Array(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Reads a vector of uint64_t from the next location in a non-null parcel.
+ */
+template <>
+inline binder_status_t AParcel_readVector<uint64_t>(const AParcel* parcel,
+ std::vector<uint64_t>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readUint64Array(parcel, &vectorData, &AParcel_stdVectorReallocator<uint64_t>,
+ AParcel_stdVectorGetter<uint64_t>);
+}
+
+/**
+ * Writes a vector of float to the next location in a non-null parcel.
+ */
+template <>
+inline binder_status_t AParcel_writeVector<float>(AParcel* parcel, const std::vector<float>& vec) {
+ return AParcel_writeFloatArray(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Reads a vector of float from the next location in a non-null parcel.
+ */
+template <>
+inline binder_status_t AParcel_readVector<float>(const AParcel* parcel, std::vector<float>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readFloatArray(parcel, &vectorData, &AParcel_stdVectorReallocator<float>,
+ AParcel_stdVectorGetter<float>);
+}
+
+/**
+ * Writes a vector of double to the next location in a non-null parcel.
+ */
+template <>
+inline binder_status_t AParcel_writeVector<double>(AParcel* parcel,
+ const std::vector<double>& vec) {
+ return AParcel_writeDoubleArray(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Reads a vector of double from the next location in a non-null parcel.
+ */
+template <>
+inline binder_status_t AParcel_readVector<double>(const AParcel* parcel, std::vector<double>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readDoubleArray(parcel, &vectorData, &AParcel_stdVectorReallocator<double>,
+ AParcel_stdVectorGetter<double>);
+}
+
+/**
+ * Writes a vector of bool to the next location in a non-null parcel.
+ */
+template <>
+inline binder_status_t AParcel_writeVector<bool>(AParcel* parcel, const std::vector<bool>& vec) {
+ return AParcel_writeBoolArray(parcel, static_cast<const void*>(&vec),
+ AParcel_stdVectorGetter<bool>, vec.size());
+}
+
+/**
+ * Reads a vector of bool from the next location in a non-null parcel.
+ */
+template <>
+inline binder_status_t AParcel_readVector<bool>(const AParcel* parcel, std::vector<bool>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readBoolArray(parcel, &vectorData, &AParcel_stdVectorReallocator<bool>,
+ AParcel_stdVectorSetter<bool>);
+}
+
+/**
+ * Writes a vector of char16_t to the next location in a non-null parcel.
+ */
+template <>
+inline binder_status_t AParcel_writeVector<char16_t>(AParcel* parcel,
+ const std::vector<char16_t>& vec) {
+ return AParcel_writeCharArray(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Reads a vector of char16_t from the next location in a non-null parcel.
+ */
+template <>
+inline binder_status_t AParcel_readVector<char16_t>(const AParcel* parcel,
+ std::vector<char16_t>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readCharArray(parcel, &vectorData, &AParcel_stdVectorReallocator<char16_t>,
+ AParcel_stdVectorGetter<char16_t>);
+}
+
+/**
+ * Writes a vector of int8_t to the next location in a non-null parcel.
+ */
+template <>
+inline binder_status_t AParcel_writeVector<int8_t>(AParcel* parcel,
+ const std::vector<int8_t>& vec) {
+ return AParcel_writeByteArray(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Reads a vector of int8_t from the next location in a non-null parcel.
+ */
+template <>
+inline binder_status_t AParcel_readVector<int8_t>(const AParcel* parcel, std::vector<int8_t>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readByteArray(parcel, &vectorData, &AParcel_stdVectorReallocator<int8_t>,
+ AParcel_stdVectorGetter<int8_t>);
+}
+
+// @END
+
+/**
+ * Takes a std::string and reallocates it to the specified length. For use with AParcel_readString.
+ * See use below in AParcel_readString.
+ */
+static inline void* AParcel_stdStringReallocator(void* stringData, size_t length) {
+ std::string* str = static_cast<std::string*>(stringData);
+ str->resize(length - 1);
+ return stringData;
+}
+
+/**
+ * Takes a std::string and returns the inner char*.
+ */
+static inline char* AParcel_stdStringGetter(void* stringData) {
+ std::string* str = static_cast<std::string*>(stringData);
+ return &(*str)[0];
+}
+
+/**
+ * Convenience API for writing a std::string.
+ */
+static inline binder_status_t AParcel_writeString(AParcel* parcel, const std::string& str) {
+ return AParcel_writeString(parcel, str.c_str(), str.size());
+}
+
+/**
+ * Convenience API for reading a std::string.
+ */
+static inline binder_status_t AParcel_readString(const AParcel* parcel, std::string* str) {
+ void* stringData = static_cast<void*>(str);
+ return AParcel_readString(parcel, AParcel_stdStringReallocator, AParcel_stdStringGetter,
+ &stringData);
+}
+
+template <typename T>
+static inline binder_status_t AParcel_writeVectorSize(AParcel* parcel, const std::vector<T>& vec) {
+ if (vec.size() > INT32_MAX) {
+ return STATUS_BAD_VALUE;
+ }
+
+ return AParcel_writeInt32(parcel, static_cast<int32_t>(vec.size()));
+}
+
+template <typename T>
+static inline binder_status_t AParcel_resizeVector(const AParcel* parcel, std::vector<T>* vec) {
+ int32_t size;
+ binder_status_t err = AParcel_readInt32(parcel, &size);
+
+ if (err != STATUS_OK) return err;
+ if (size < 0) return STATUS_UNEXPECTED_NULL;
+
+ vec->resize(static_cast<size_t>(size));
+ return STATUS_OK;
+}
+
+} // namespace ndk
+
+#endif // __cplusplus
+
+/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_status.h b/libs/binder/ndk/include_ndk/android/binder_status.h
new file mode 100644
index 0000000..2d8b7fa
--- /dev/null
+++ b/libs/binder/ndk/include_ndk/android/binder_status.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 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.
+ */
+
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_status.h
+ */
+
+#pragma once
+
+#include <errno.h>
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+#if __ANDROID_API__ >= __ANDROID_API_Q__
+
+enum {
+ STATUS_OK = 0,
+
+ STATUS_UNKNOWN_ERROR = (-2147483647 - 1), // INT32_MIN value
+ STATUS_NO_MEMORY = -ENOMEM,
+ STATUS_INVALID_OPERATION = -ENOSYS,
+ STATUS_BAD_VALUE = -EINVAL,
+ STATUS_BAD_TYPE = (STATUS_UNKNOWN_ERROR + 1),
+ STATUS_NAME_NOT_FOUND = -ENOENT,
+ STATUS_PERMISSION_DENIED = -EPERM,
+ STATUS_NO_INIT = -ENODEV,
+ STATUS_ALREADY_EXISTS = -EEXIST,
+ STATUS_DEAD_OBJECT = -EPIPE,
+ STATUS_FAILED_TRANSACTION = (STATUS_UNKNOWN_ERROR + 2),
+ STATUS_BAD_INDEX = -EOVERFLOW,
+ STATUS_NOT_ENOUGH_DATA = -ENODATA,
+ STATUS_WOULD_BLOCK = -EWOULDBLOCK,
+ STATUS_TIMED_OUT = -ETIMEDOUT,
+ STATUS_UNKNOWN_TRANSACTION = -EBADMSG,
+ STATUS_FDS_NOT_ALLOWED = (STATUS_UNKNOWN_ERROR + 7),
+ STATUS_UNEXPECTED_NULL = (STATUS_UNKNOWN_ERROR + 8),
+};
+
+/**
+ * One of the STATUS_* values.
+ *
+ * All unrecognized values are coerced into STATUS_UNKNOWN_ERROR.
+ */
+typedef int32_t binder_status_t;
+
+enum {
+ EX_NONE = 0,
+ EX_SECURITY = -1,
+ EX_BAD_PARCELABLE = -2,
+ EX_ILLEGAL_ARGUMENT = -3,
+ EX_NULL_POINTER = -4,
+ EX_ILLEGAL_STATE = -5,
+ EX_NETWORK_MAIN_THREAD = -6,
+ EX_UNSUPPORTED_OPERATION = -7,
+ EX_SERVICE_SPECIFIC = -8,
+ EX_PARCELABLE = -9,
+
+ /**
+ * This is special, and indicates to native binder proxies that the
+ * transaction has failed at a low level.
+ */
+ EX_TRANSACTION_FAILED = -129,
+};
+
+/**
+ * One of the EXCEPTION_* types.
+ *
+ * All unrecognized values are coerced into EXCEPTION_TRANSACTION_FAILED.
+ *
+ * These exceptions values are used by the SDK for parcelables. Also see Parcel.java.
+ */
+typedef int32_t binder_exception_t;
+
+/**
+ * This is a helper class that encapsulates a standard way to keep track of and chain binder errors
+ * along with service specific errors.
+ *
+ * It is not required to be used in order to parcel/receive transactions, but it is required in
+ * order to be compatible with standard AIDL transactions.
+ */
+struct AStatus;
+typedef struct AStatus AStatus;
+
+/**
+ * New status which is considered a success.
+ */
+__attribute__((warn_unused_result)) AStatus* AStatus_newOk() __INTRODUCED_IN(29);
+
+/**
+ * New status with exception code.
+ */
+__attribute__((warn_unused_result)) AStatus* AStatus_fromExceptionCode(binder_exception_t exception)
+ __INTRODUCED_IN(29);
+
+/**
+ * New status with exception code and message.
+ */
+__attribute__((warn_unused_result)) AStatus* AStatus_fromExceptionCodeWithMessage(
+ binder_exception_t exception, const char* message) __INTRODUCED_IN(29);
+
+/**
+ * New status with a service speciic error.
+ *
+ * This is considered to be EX_TRANSACTION_FAILED with extra information.
+ */
+__attribute__((warn_unused_result)) AStatus* AStatus_fromServiceSpecificError(
+ int32_t serviceSpecific) __INTRODUCED_IN(29);
+
+/**
+ * New status with a service specific error and message.
+ *
+ * This is considered to be EX_TRANSACTION_FAILED with extra information.
+ */
+__attribute__((warn_unused_result)) AStatus* AStatus_fromServiceSpecificErrorWithMessage(
+ int32_t serviceSpecific, const char* message) __INTRODUCED_IN(29);
+
+/**
+ * New status with binder_status_t. This is typically for low level failures when a binder_status_t
+ * is returned by an API on AIBinder or AParcel, and that is to be returned from a method returning
+ * an AStatus instance.
+ */
+__attribute__((warn_unused_result)) AStatus* AStatus_fromStatus(binder_status_t status)
+ __INTRODUCED_IN(29);
+
+/**
+ * Whether this object represents a successful transaction. If this function returns true, then
+ * AStatus_getExceptionCode will return EX_NONE.
+ */
+bool AStatus_isOk(const AStatus* status) __INTRODUCED_IN(29);
+
+/**
+ * The exception that this status object represents.
+ */
+binder_exception_t AStatus_getExceptionCode(const AStatus* status) __INTRODUCED_IN(29);
+
+/**
+ * The service specific error if this object represents one. This function will only ever return a
+ * non-zero result if AStatus_getExceptionCode returns EX_SERVICE_SPECIFIC. If this function returns
+ * 0, the status object may still represent a different exception or status. To find out if this
+ * transaction as a whole is okay, use AStatus_isOk instead.
+ */
+int32_t AStatus_getServiceSpecificError(const AStatus* status) __INTRODUCED_IN(29);
+
+/**
+ * The status if this object represents one. This function will only ever return a non-zero result
+ * if AStatus_getExceptionCode returns EX_TRANSACTION_FAILED. If this function return 0, the status
+ * object may represent a different exception or a service specific error. To find out if this
+ * transaction as a whole is okay, use AStatus_isOk instead.
+ */
+binder_status_t AStatus_getStatus(const AStatus* status) __INTRODUCED_IN(29);
+
+/**
+ * If there is a message associated with this status, this will return that message. If there is no
+ * message, this will return an empty string.
+ *
+ * The returned string has the lifetime of the status object passed into this function.
+ */
+const char* AStatus_getMessage(const AStatus* status) __INTRODUCED_IN(29);
+
+/**
+ * Deletes memory associated with the status instance.
+ */
+void AStatus_delete(AStatus* status) __INTRODUCED_IN(29);
+
+#endif //__ANDROID_API__ >= __ANDROID_API_Q__
+__END_DECLS
+
+/** @} */
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
new file mode 100644
index 0000000..f84814f
--- /dev/null
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -0,0 +1,83 @@
+LIBBINDER_NDK { # introduced=29
+ global:
+ AIBinder_associateClass;
+ AIBinder_Class_define;
+ AIBinder_DeathRecipient_delete;
+ AIBinder_DeathRecipient_new;
+ AIBinder_debugGetRefCount;
+ AIBinder_decStrong;
+ AIBinder_fromJavaBinder;
+ AIBinder_getClass;
+ AIBinder_getUserData;
+ AIBinder_incStrong;
+ AIBinder_isAlive;
+ AIBinder_isRemote;
+ AIBinder_linkToDeath;
+ AIBinder_new;
+ AIBinder_ping;
+ AIBinder_prepareTransaction;
+ AIBinder_toJavaBinder;
+ AIBinder_transact;
+ AIBinder_unlinkToDeath;
+ AIBinder_Weak_delete;
+ AIBinder_Weak_new;
+ AIBinder_Weak_promote;
+ AParcel_delete;
+ AParcel_readBool;
+ AParcel_readBoolArray;
+ AParcel_readByte;
+ AParcel_readByteArray;
+ AParcel_readChar;
+ AParcel_readCharArray;
+ AParcel_readDouble;
+ AParcel_readDoubleArray;
+ AParcel_readFloat;
+ AParcel_readFloatArray;
+ AParcel_readInt32;
+ AParcel_readInt32Array;
+ AParcel_readInt64;
+ AParcel_readInt64Array;
+ AParcel_readNullableStrongBinder;
+ AParcel_readStatusHeader;
+ AParcel_readString;
+ AParcel_readStrongBinder;
+ AParcel_readUint32;
+ AParcel_readUint32Array;
+ AParcel_readUint64;
+ AParcel_readUint64Array;
+ AParcel_writeBool;
+ AParcel_writeBoolArray;
+ AParcel_writeByte;
+ AParcel_writeByteArray;
+ AParcel_writeChar;
+ AParcel_writeCharArray;
+ AParcel_writeDouble;
+ AParcel_writeDoubleArray;
+ AParcel_writeFloat;
+ AParcel_writeFloatArray;
+ AParcel_writeInt32;
+ AParcel_writeInt32Array;
+ AParcel_writeInt64;
+ AParcel_writeInt64Array;
+ AParcel_writeStatusHeader;
+ AParcel_writeString;
+ AParcel_writeStrongBinder;
+ AParcel_writeUint32;
+ AParcel_writeUint32Array;
+ AParcel_writeUint64;
+ AParcel_writeUint64Array;
+ AStatus_delete;
+ AStatus_fromExceptionCode;
+ AStatus_fromExceptionCodeWithMessage;
+ AStatus_fromServiceSpecificError;
+ AStatus_fromServiceSpecificErrorWithMessage;
+ AStatus_fromStatus;
+ AStatus_getExceptionCode;
+ AStatus_getMessage;
+ AStatus_getServiceSpecificError;
+ AStatus_getStatus;
+ AStatus_isOk;
+ AStatus_newOk;
+ local:
+ *;
+};
diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
new file mode 100644
index 0000000..29094db
--- /dev/null
+++ b/libs/binder/ndk/parcel.cpp
@@ -0,0 +1,483 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include <android/binder_parcel.h>
+#include "parcel_internal.h"
+
+#include "ibinder_internal.h"
+#include "status_internal.h"
+
+#include <limits>
+
+#include <android-base/logging.h>
+#include <binder/Parcel.h>
+#include <utils/Unicode.h>
+
+using ::android::IBinder;
+using ::android::Parcel;
+using ::android::sp;
+using ::android::status_t;
+
+template <typename T>
+using ContiguousArrayGetter = T* (*)(void* arrayData);
+template <typename T>
+using ArrayGetter = T (*)(const void* arrayData, size_t index);
+template <typename T>
+using ArraySetter = void (*)(void* arrayData, size_t index, T value);
+
+template <typename T>
+binder_status_t WriteArray(AParcel* parcel, const T* array, size_t length) {
+ if (length > std::numeric_limits<int32_t>::max()) return STATUS_BAD_VALUE;
+
+ Parcel* rawParcel = parcel->get();
+
+ status_t status = rawParcel->writeInt32(static_cast<int32_t>(length));
+ if (status != STATUS_OK) return PruneStatusT(status);
+
+ int32_t size = 0;
+ if (__builtin_smul_overflow(sizeof(T), length, &size)) return STATUS_NO_MEMORY;
+
+ void* const data = rawParcel->writeInplace(size);
+ if (data == nullptr) return STATUS_NO_MEMORY;
+
+ memcpy(data, array, size);
+
+ return STATUS_OK;
+}
+
+// Each element in a char16_t array is converted to an int32_t (not packed).
+template <>
+binder_status_t WriteArray<char16_t>(AParcel* parcel, const char16_t* array, size_t length) {
+ if (length > std::numeric_limits<int32_t>::max()) return STATUS_BAD_VALUE;
+
+ Parcel* rawParcel = parcel->get();
+
+ status_t status = rawParcel->writeInt32(static_cast<int32_t>(length));
+ if (status != STATUS_OK) return PruneStatusT(status);
+
+ int32_t size = 0;
+ if (__builtin_smul_overflow(sizeof(char16_t), length, &size)) return STATUS_NO_MEMORY;
+
+ for (int32_t i = 0; i < length; i++) {
+ status = rawParcel->writeChar(array[i]);
+
+ if (status != STATUS_OK) return PruneStatusT(status);
+ }
+
+ return STATUS_OK;
+}
+
+template <typename T>
+binder_status_t ReadArray(const AParcel* parcel, void** arrayData,
+ AParcel_arrayReallocator reallocator, ContiguousArrayGetter<T> getter) {
+ const Parcel* rawParcel = parcel->get();
+
+ int32_t length;
+ status_t status = rawParcel->readInt32(&length);
+
+ if (status != STATUS_OK) return PruneStatusT(status);
+ if (length < 0) return STATUS_UNEXPECTED_NULL;
+
+ *arrayData = reallocator(*arrayData, length);
+ if (*arrayData == nullptr) return STATUS_NO_MEMORY;
+
+ if (length == 0) return STATUS_OK;
+
+ T* array = getter(*arrayData);
+ if (array == nullptr) return STATUS_NO_MEMORY;
+
+ int32_t size = 0;
+ if (__builtin_smul_overflow(sizeof(T), length, &size)) return STATUS_NO_MEMORY;
+
+ const void* data = rawParcel->readInplace(size);
+ if (data == nullptr) return STATUS_NO_MEMORY;
+
+ memcpy(array, data, size);
+
+ return STATUS_OK;
+}
+
+// Each element in a char16_t array is converted to an int32_t (not packed)
+template <>
+binder_status_t ReadArray<char16_t>(const AParcel* parcel, void** arrayData,
+ AParcel_arrayReallocator reallocator,
+ ContiguousArrayGetter<char16_t> getter) {
+ const Parcel* rawParcel = parcel->get();
+
+ int32_t length;
+ status_t status = rawParcel->readInt32(&length);
+
+ if (status != STATUS_OK) return PruneStatusT(status);
+ if (length < 0) return STATUS_UNEXPECTED_NULL;
+
+ *arrayData = reallocator(*arrayData, length);
+ if (*arrayData == nullptr) return STATUS_NO_MEMORY;
+
+ if (length == 0) return STATUS_OK;
+
+ char16_t* array = getter(*arrayData);
+ if (array == nullptr) return STATUS_NO_MEMORY;
+
+ int32_t size = 0;
+ if (__builtin_smul_overflow(sizeof(char16_t), length, &size)) return STATUS_NO_MEMORY;
+
+ for (int32_t i = 0; i < length; i++) {
+ status = rawParcel->readChar(array + i);
+
+ if (status != STATUS_OK) return PruneStatusT(status);
+ }
+
+ return STATUS_OK;
+}
+
+template <typename T>
+binder_status_t WriteArray(AParcel* parcel, const void* arrayData, ArrayGetter<T> getter,
+ size_t length, status_t (Parcel::*write)(T)) {
+ if (length > std::numeric_limits<int32_t>::max()) return STATUS_BAD_VALUE;
+
+ Parcel* rawParcel = parcel->get();
+
+ status_t status = rawParcel->writeInt32(static_cast<int32_t>(length));
+ if (status != STATUS_OK) return PruneStatusT(status);
+
+ for (size_t i = 0; i < length; i++) {
+ status = (rawParcel->*write)(getter(arrayData, i));
+
+ if (status != STATUS_OK) return PruneStatusT(status);
+ }
+
+ return STATUS_OK;
+}
+
+template <typename T>
+binder_status_t ReadArray(const AParcel* parcel, void** arrayData,
+ AParcel_arrayReallocator reallocator, ArraySetter<T> setter,
+ status_t (Parcel::*read)(T*) const) {
+ const Parcel* rawParcel = parcel->get();
+
+ int32_t length;
+ status_t status = rawParcel->readInt32(&length);
+
+ if (status != STATUS_OK) return PruneStatusT(status);
+ if (length < 0) return STATUS_UNEXPECTED_NULL;
+
+ *arrayData = reallocator(*arrayData, length);
+ if (*arrayData == nullptr) return STATUS_NO_MEMORY;
+
+ for (size_t i = 0; i < length; i++) {
+ T readTarget;
+ status = (rawParcel->*read)(&readTarget);
+ if (status != STATUS_OK) return PruneStatusT(status);
+
+ setter(*arrayData, i, readTarget);
+ }
+
+ return STATUS_OK;
+}
+
+void AParcel_delete(AParcel* parcel) {
+ delete parcel;
+}
+
+binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder) {
+ sp<IBinder> writeBinder = binder != nullptr ? binder->getBinder() : nullptr;
+ return parcel->get()->writeStrongBinder(writeBinder);
+}
+binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binder) {
+ sp<IBinder> readBinder = nullptr;
+ status_t status = parcel->get()->readStrongBinder(&readBinder);
+ if (status != STATUS_OK) {
+ return PruneStatusT(status);
+ }
+ sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(readBinder);
+ AIBinder_incStrong(ret.get());
+ *binder = ret.get();
+ return PruneStatusT(status);
+}
+binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder** binder) {
+ sp<IBinder> readBinder = nullptr;
+ status_t status = parcel->get()->readNullableStrongBinder(&readBinder);
+ if (status != STATUS_OK) {
+ return PruneStatusT(status);
+ }
+ sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(readBinder);
+ AIBinder_incStrong(ret.get());
+ *binder = ret.get();
+ return PruneStatusT(status);
+}
+binder_status_t AParcel_writeStatusHeader(AParcel* parcel, const AStatus* status) {
+ return PruneStatusT(status->get()->writeToParcel(parcel->get()));
+}
+binder_status_t AParcel_readStatusHeader(const AParcel* parcel, AStatus** status) {
+ ::android::binder::Status bstatus;
+ binder_status_t ret = PruneStatusT(bstatus.readFromParcel(*parcel->get()));
+ if (ret == EX_NONE) {
+ *status = new AStatus(std::move(bstatus));
+ }
+ return ret;
+}
+
+binder_status_t AParcel_writeString(AParcel* parcel, const char* string, size_t length) {
+ const uint8_t* str8 = (uint8_t*)string;
+
+ const ssize_t len16 = utf8_to_utf16_length(str8, length);
+
+ if (len16 < 0 || len16 >= std::numeric_limits<int32_t>::max()) {
+ LOG(WARNING) << __func__ << ": Invalid string length: " << len16;
+ return STATUS_BAD_VALUE;
+ }
+
+ status_t err = parcel->get()->writeInt32(len16);
+ if (err) {
+ return PruneStatusT(err);
+ }
+
+ void* str16 = parcel->get()->writeInplace((len16 + 1) * sizeof(char16_t));
+ if (str16 == nullptr) {
+ return STATUS_NO_MEMORY;
+ }
+
+ utf8_to_utf16(str8, length, (char16_t*)str16, (size_t)len16 + 1);
+
+ return STATUS_OK;
+}
+
+binder_status_t AParcel_readString(const AParcel* parcel, AParcel_stringReallocator reallocator,
+ AParcel_stringGetter getter, void** stringData) {
+ size_t len16;
+ const char16_t* str16 = parcel->get()->readString16Inplace(&len16);
+
+ if (str16 == nullptr) {
+ LOG(WARNING) << __func__ << ": Failed to read string in place.";
+ return STATUS_UNEXPECTED_NULL;
+ }
+
+ ssize_t len8;
+
+ if (len16 == 0) {
+ len8 = 1;
+ } else {
+ len8 = utf16_to_utf8_length(str16, len16) + 1;
+ }
+
+ if (len8 <= 0 || len8 >= std::numeric_limits<int32_t>::max()) {
+ LOG(WARNING) << __func__ << ": Invalid string length: " << len8;
+ return STATUS_BAD_VALUE;
+ }
+
+ *stringData = reallocator(*stringData, len8);
+
+ if (*stringData == nullptr) {
+ return STATUS_NO_MEMORY;
+ }
+
+ char* str8 = getter(*stringData);
+
+ if (str8 == nullptr) {
+ LOG(WARNING) << __func__ << ": AParcel_stringReallocator failed to allocate.";
+ return STATUS_NO_MEMORY;
+ }
+
+ utf16_to_utf8(str16, len16, str8, len8);
+
+ return STATUS_OK;
+}
+
+// See gen_parcel_helper.py. These auto-generated read/write methods use the same types for
+// libbinder and this library.
+// @START
+binder_status_t AParcel_writeInt32(AParcel* parcel, int32_t value) {
+ status_t status = parcel->get()->writeInt32(value);
+ return PruneStatusT(status);
+}
+
+binder_status_t AParcel_writeUint32(AParcel* parcel, uint32_t value) {
+ status_t status = parcel->get()->writeUint32(value);
+ return PruneStatusT(status);
+}
+
+binder_status_t AParcel_writeInt64(AParcel* parcel, int64_t value) {
+ status_t status = parcel->get()->writeInt64(value);
+ return PruneStatusT(status);
+}
+
+binder_status_t AParcel_writeUint64(AParcel* parcel, uint64_t value) {
+ status_t status = parcel->get()->writeUint64(value);
+ return PruneStatusT(status);
+}
+
+binder_status_t AParcel_writeFloat(AParcel* parcel, float value) {
+ status_t status = parcel->get()->writeFloat(value);
+ return PruneStatusT(status);
+}
+
+binder_status_t AParcel_writeDouble(AParcel* parcel, double value) {
+ status_t status = parcel->get()->writeDouble(value);
+ return PruneStatusT(status);
+}
+
+binder_status_t AParcel_writeBool(AParcel* parcel, bool value) {
+ status_t status = parcel->get()->writeBool(value);
+ return PruneStatusT(status);
+}
+
+binder_status_t AParcel_writeChar(AParcel* parcel, char16_t value) {
+ status_t status = parcel->get()->writeChar(value);
+ return PruneStatusT(status);
+}
+
+binder_status_t AParcel_writeByte(AParcel* parcel, int8_t value) {
+ status_t status = parcel->get()->writeByte(value);
+ return PruneStatusT(status);
+}
+
+binder_status_t AParcel_readInt32(const AParcel* parcel, int32_t* value) {
+ status_t status = parcel->get()->readInt32(value);
+ return PruneStatusT(status);
+}
+
+binder_status_t AParcel_readUint32(const AParcel* parcel, uint32_t* value) {
+ status_t status = parcel->get()->readUint32(value);
+ return PruneStatusT(status);
+}
+
+binder_status_t AParcel_readInt64(const AParcel* parcel, int64_t* value) {
+ status_t status = parcel->get()->readInt64(value);
+ return PruneStatusT(status);
+}
+
+binder_status_t AParcel_readUint64(const AParcel* parcel, uint64_t* value) {
+ status_t status = parcel->get()->readUint64(value);
+ return PruneStatusT(status);
+}
+
+binder_status_t AParcel_readFloat(const AParcel* parcel, float* value) {
+ status_t status = parcel->get()->readFloat(value);
+ return PruneStatusT(status);
+}
+
+binder_status_t AParcel_readDouble(const AParcel* parcel, double* value) {
+ status_t status = parcel->get()->readDouble(value);
+ return PruneStatusT(status);
+}
+
+binder_status_t AParcel_readBool(const AParcel* parcel, bool* value) {
+ status_t status = parcel->get()->readBool(value);
+ return PruneStatusT(status);
+}
+
+binder_status_t AParcel_readChar(const AParcel* parcel, char16_t* value) {
+ status_t status = parcel->get()->readChar(value);
+ return PruneStatusT(status);
+}
+
+binder_status_t AParcel_readByte(const AParcel* parcel, int8_t* value) {
+ status_t status = parcel->get()->readByte(value);
+ return PruneStatusT(status);
+}
+
+binder_status_t AParcel_writeInt32Array(AParcel* parcel, const int32_t* value, size_t length) {
+ return WriteArray<int32_t>(parcel, value, length);
+}
+
+binder_status_t AParcel_writeUint32Array(AParcel* parcel, const uint32_t* value, size_t length) {
+ return WriteArray<uint32_t>(parcel, value, length);
+}
+
+binder_status_t AParcel_writeInt64Array(AParcel* parcel, const int64_t* value, size_t length) {
+ return WriteArray<int64_t>(parcel, value, length);
+}
+
+binder_status_t AParcel_writeUint64Array(AParcel* parcel, const uint64_t* value, size_t length) {
+ return WriteArray<uint64_t>(parcel, value, length);
+}
+
+binder_status_t AParcel_writeFloatArray(AParcel* parcel, const float* value, size_t length) {
+ return WriteArray<float>(parcel, value, length);
+}
+
+binder_status_t AParcel_writeDoubleArray(AParcel* parcel, const double* value, size_t length) {
+ return WriteArray<double>(parcel, value, length);
+}
+
+binder_status_t AParcel_writeBoolArray(AParcel* parcel, const void* arrayData,
+ AParcel_boolArrayGetter getter, size_t length) {
+ return WriteArray<bool>(parcel, arrayData, getter, length, &Parcel::writeBool);
+}
+
+binder_status_t AParcel_writeCharArray(AParcel* parcel, const char16_t* value, size_t length) {
+ return WriteArray<char16_t>(parcel, value, length);
+}
+
+binder_status_t AParcel_writeByteArray(AParcel* parcel, const int8_t* value, size_t length) {
+ return WriteArray<int8_t>(parcel, value, length);
+}
+
+binder_status_t AParcel_readInt32Array(const AParcel* parcel, void** arrayData,
+ AParcel_arrayReallocator reallocator,
+ AParcel_int32ArrayGetter getter) {
+ return ReadArray<int32_t>(parcel, arrayData, reallocator, getter);
+}
+
+binder_status_t AParcel_readUint32Array(const AParcel* parcel, void** arrayData,
+ AParcel_arrayReallocator reallocator,
+ AParcel_uint32ArrayGetter getter) {
+ return ReadArray<uint32_t>(parcel, arrayData, reallocator, getter);
+}
+
+binder_status_t AParcel_readInt64Array(const AParcel* parcel, void** arrayData,
+ AParcel_arrayReallocator reallocator,
+ AParcel_int64ArrayGetter getter) {
+ return ReadArray<int64_t>(parcel, arrayData, reallocator, getter);
+}
+
+binder_status_t AParcel_readUint64Array(const AParcel* parcel, void** arrayData,
+ AParcel_arrayReallocator reallocator,
+ AParcel_uint64ArrayGetter getter) {
+ return ReadArray<uint64_t>(parcel, arrayData, reallocator, getter);
+}
+
+binder_status_t AParcel_readFloatArray(const AParcel* parcel, void** arrayData,
+ AParcel_arrayReallocator reallocator,
+ AParcel_floatArrayGetter getter) {
+ return ReadArray<float>(parcel, arrayData, reallocator, getter);
+}
+
+binder_status_t AParcel_readDoubleArray(const AParcel* parcel, void** arrayData,
+ AParcel_arrayReallocator reallocator,
+ AParcel_doubleArrayGetter getter) {
+ return ReadArray<double>(parcel, arrayData, reallocator, getter);
+}
+
+binder_status_t AParcel_readBoolArray(const AParcel* parcel, void** arrayData,
+ AParcel_arrayReallocator reallocator,
+ AParcel_boolArraySetter setter) {
+ return ReadArray<bool>(parcel, arrayData, reallocator, setter, &Parcel::readBool);
+}
+
+binder_status_t AParcel_readCharArray(const AParcel* parcel, void** arrayData,
+ AParcel_arrayReallocator reallocator,
+ AParcel_charArrayGetter getter) {
+ return ReadArray<char16_t>(parcel, arrayData, reallocator, getter);
+}
+
+binder_status_t AParcel_readByteArray(const AParcel* parcel, void** arrayData,
+ AParcel_arrayReallocator reallocator,
+ AParcel_byteArrayGetter getter) {
+ return ReadArray<int8_t>(parcel, arrayData, reallocator, getter);
+}
+
+// @END
diff --git a/libs/binder/ndk/parcel_internal.h b/libs/binder/ndk/parcel_internal.h
new file mode 100644
index 0000000..d69971f
--- /dev/null
+++ b/libs/binder/ndk/parcel_internal.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 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 <android/binder_parcel.h>
+
+#include <sys/cdefs.h>
+
+#include <binder/Parcel.h>
+#include "ibinder_internal.h"
+
+struct AParcel {
+ const ::android::Parcel* get() const { return mParcel; }
+ ::android::Parcel* get() { return mParcel; }
+
+ AParcel(const AIBinder* binder) : AParcel(binder, new ::android::Parcel, true /*owns*/) {}
+ AParcel(const AIBinder* binder, ::android::Parcel* parcel, bool owns)
+ : mBinder(binder), mParcel(parcel), mOwns(owns) {}
+
+ ~AParcel() {
+ if (mOwns) {
+ delete mParcel;
+ }
+ }
+
+ static const AParcel readOnly(const AIBinder* binder, const ::android::Parcel* parcel) {
+ return AParcel(binder, const_cast<::android::Parcel*>(parcel), false);
+ }
+
+ const AIBinder* getBinder() { return mBinder; }
+
+private:
+ // This object is associated with a calls to a specific AIBinder object. This is used for sanity
+ // checking to make sure that a parcel is one that is expected.
+ const AIBinder* mBinder;
+
+ ::android::Parcel* mParcel;
+ bool mOwns;
+};
diff --git a/libs/binder/ndk/process.cpp b/libs/binder/ndk/process.cpp
new file mode 100644
index 0000000..c89caaf
--- /dev/null
+++ b/libs/binder/ndk/process.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include <android/binder_process.h>
+
+#include <mutex>
+
+#include <android-base/logging.h>
+#include <binder/IPCThreadState.h>
+
+using ::android::IPCThreadState;
+using ::android::ProcessState;
+
+void ABinderProcess_startThreadPool() {
+ ProcessState::self()->startThreadPool();
+ ProcessState::self()->giveThreadPoolName();
+}
+bool ABinderProcess_setThreadPoolMaxThreadCount(uint32_t numThreads) {
+ return ProcessState::self()->setThreadPoolMaxThreadCount(numThreads) == 0;
+}
+void ABinderProcess_joinThreadPool() {
+ IPCThreadState::self()->joinThreadPool();
+}
diff --git a/libs/binder/ndk/runtests.sh b/libs/binder/ndk/runtests.sh
new file mode 100755
index 0000000..2257eb2
--- /dev/null
+++ b/libs/binder/ndk/runtests.sh
@@ -0,0 +1,43 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 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.
+
+if [ -z $ANDROID_BUILD_TOP ]; then
+ echo "You need to source and lunch before you can use this script"
+ exit 1
+fi
+
+set -ex
+
+function run_libbinder_ndk_test() {
+ adb shell /data/nativetest64/libbinder_ndk_test_server/libbinder_ndk_test_server &
+ local pid=$!
+ trap "kill $pid" ERR
+ adb shell /data/nativetest64/libbinder_ndk_test_client/libbinder_ndk_test_client
+ trap '' ERR
+ kill $pid
+}
+
+[ "$1" != "--skip-build" ] && $ANDROID_BUILD_TOP/build/soong/soong_ui.bash --make-mode \
+ MODULES-IN-frameworks-native-libs-binder-ndk
+
+adb root
+adb wait-for-device
+adb sync data
+
+# very simple unit tests, tests things outside of the NDK as well
+run_libbinder_ndk_test
+
+atest android.binder.cts.NdkBinderTest
diff --git a/libs/binder/ndk/scripts/format.sh b/libs/binder/ndk/scripts/format.sh
new file mode 100755
index 0000000..698d291
--- /dev/null
+++ b/libs/binder/ndk/scripts/format.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 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.
+
+set -e
+
+echo "Formatting code"
+
+bpfmt -w $(find $ANDROID_BUILD_TOP/frameworks/native/libs/binder/ndk/ -name "Android.bp")
+clang-format -i $(find $ANDROID_BUILD_TOP/frameworks/native/libs/binder/ndk/ -\( -name "*.cpp" -o -name "*.h" -\))
diff --git a/libs/binder/ndk/scripts/gen_parcel_helper.py b/libs/binder/ndk/scripts/gen_parcel_helper.py
new file mode 100755
index 0000000..45f8d06
--- /dev/null
+++ b/libs/binder/ndk/scripts/gen_parcel_helper.py
@@ -0,0 +1,184 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 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.
+
+import os
+import sys
+
+# list (pretty, cpp)
+data_types = [
+ ("Int32", "int32_t"),
+ ("Uint32", "uint32_t"),
+ ("Int64", "int64_t"),
+ ("Uint64", "uint64_t"),
+ ("Float", "float"),
+ ("Double", "double"),
+ ("Bool", "bool"),
+ ("Char", "char16_t"),
+ ("Byte", "int8_t"),
+]
+
+non_contiguously_addressable = {"Bool"}
+
+def replaceFileTags(path, content, start_tag, end_tag):
+ print("Updating", path)
+ with open(path, "r+") as f:
+ lines = f.readlines()
+
+ start = lines.index("// @" + start_tag + "\n")
+ end = lines.index("// @" + end_tag + "\n")
+
+ if end <= start or start < 0 or end < 0:
+ print("Failed to find tags in", path)
+ exit(1)
+
+ f.seek(0)
+ f.write("".join(lines[:start+1]) + content + "".join(lines[end:]))
+ f.truncate()
+
+def main():
+ if len(sys.argv) != 1:
+ print("No arguments.")
+ exit(1)
+
+ ABT = os.environ.get('ANDROID_BUILD_TOP', None)
+ if ABT is None:
+ print("Can't get ANDROID_BUILD_TOP. Lunch?")
+ exit(1)
+ ROOT = ABT + "/frameworks/native/libs/binder/ndk/"
+
+ print("Updating auto-generated code")
+
+ pre_header = ""
+ header = ""
+ source = ""
+ cpp_helper = ""
+
+ for pretty, cpp in data_types:
+ header += "/**\n"
+ header += " * Writes " + cpp + " value to the next location in a non-null parcel.\n"
+ header += " */\n"
+ header += "binder_status_t AParcel_write" + pretty + "(AParcel* parcel, " + cpp + " value) __INTRODUCED_IN(29);\n\n"
+ source += "binder_status_t AParcel_write" + pretty + "(AParcel* parcel, " + cpp + " value) {\n"
+ source += " status_t status = parcel->get()->write" + pretty + "(value);\n"
+ source += " return PruneStatusT(status);\n"
+ source += "}\n\n"
+
+ for pretty, cpp in data_types:
+ header += "/**\n"
+ header += " * Reads into " + cpp + " value from the next location in a non-null parcel.\n"
+ header += " */\n"
+ header += "binder_status_t AParcel_read" + pretty + "(const AParcel* parcel, " + cpp + "* value) __INTRODUCED_IN(29);\n\n"
+ source += "binder_status_t AParcel_read" + pretty + "(const AParcel* parcel, " + cpp + "* value) {\n"
+ source += " status_t status = parcel->get()->read" + pretty + "(value);\n"
+ source += " return PruneStatusT(status);\n"
+ source += "}\n\n"
+
+ for pretty, cpp in data_types:
+ nca = pretty in non_contiguously_addressable
+
+ arg_type = "const " + cpp + "* value"
+ if nca: arg_type = "const void* arrayData, AParcel_" + pretty.lower() + "ArrayGetter getter"
+ args = "value, length"
+ if nca: args = "arrayData, getter, length, &Parcel::write" + pretty
+
+ header += "/**\n"
+ header += " * Writes an array of " + cpp + " to the next location in a non-null parcel.\n"
+ header += " */\n"
+ header += "binder_status_t AParcel_write" + pretty + "Array(AParcel* parcel, " + arg_type + ", size_t length) __INTRODUCED_IN(29);\n\n"
+ source += "binder_status_t AParcel_write" + pretty + "Array(AParcel* parcel, " + arg_type + ", size_t length) {\n"
+ source += " return WriteArray<" + cpp + ">(parcel, " + args + ");\n";
+ source += "}\n\n"
+
+ for pretty, cpp in data_types:
+ nca = pretty in non_contiguously_addressable
+
+ extra_getter_args = ""
+ if nca: extra_getter_args = ", size_t index"
+ getter_return = cpp + "*"
+ if nca: getter_return = cpp
+ getter_array_data = "void* arrayData"
+ if nca: getter_array_data = "const void* arrayData"
+
+ getter_type = "AParcel_" + pretty.lower() + "ArrayGetter"
+ setter_type = "AParcel_" + pretty.lower() + "ArraySetter"
+
+ pre_header += "/**\n"
+ pre_header += " * This is called to get the underlying data from an arrayData object.\n"
+ pre_header += " *\n"
+ pre_header += " * This will never be called for an empty array.\n"
+ pre_header += " */\n"
+ pre_header += "typedef " + getter_return + " (*" + getter_type + ")(" + getter_array_data + extra_getter_args + ");\n\n"
+
+ if nca:
+ pre_header += "/**\n"
+ pre_header += " * This is called to set an underlying value in an arrayData object at index.\n"
+ pre_header += " */\n"
+ pre_header += "typedef void (*" + setter_type + ")(void* arrayData, size_t index, " + cpp + " value);\n\n"
+
+ read_using = "getter"
+ if nca: read_using = "setter"
+ read_type = getter_type
+ if nca: read_type = setter_type
+
+ arguments = ["const AParcel* parcel"]
+ arguments += ["void** arrayData"]
+ arguments += ["AParcel_arrayReallocator reallocator"]
+ arguments += [read_type + " " + read_using]
+ arguments = ", ".join(arguments)
+
+ header += "/**\n"
+ header += " * Reads an array of " + cpp + " from the next location in a non-null parcel.\n"
+ header += " */\n"
+ header += "binder_status_t AParcel_read" + pretty + "Array(" + arguments + ") __INTRODUCED_IN(29);\n\n"
+ source += "binder_status_t AParcel_read" + pretty + "Array(" + arguments + ") {\n"
+ additional_args = ""
+ if nca: additional_args = ", &Parcel::read" + pretty
+ source += " return ReadArray<" + cpp + ">(parcel, arrayData, reallocator, " + read_using + additional_args + ");\n";
+ source += "}\n\n"
+
+ cpp_helper += "/**\n"
+ cpp_helper += " * Writes a vector of " + cpp + " to the next location in a non-null parcel.\n"
+ cpp_helper += " */\n"
+ cpp_helper += "template<>\n"
+ cpp_helper += "inline binder_status_t AParcel_writeVector<" + cpp + ">(AParcel* parcel, const std::vector<" + cpp + ">& vec) {\n"
+ write_args = "vec.data()"
+ if nca: write_args = "static_cast<const void*>(&vec), AParcel_stdVectorGetter<" + cpp + ">"
+ cpp_helper += " return AParcel_write" + pretty + "Array(parcel, " + write_args + ", vec.size());\n"
+ cpp_helper += "}\n\n"
+
+ cpp_helper += "/**\n"
+ cpp_helper += " * Reads a vector of " + cpp + " from the next location in a non-null parcel.\n"
+ cpp_helper += " */\n"
+ cpp_helper += "template<>\n"
+ cpp_helper += "inline binder_status_t AParcel_readVector<" + cpp + ">(const AParcel* parcel, std::vector<" + cpp + ">* vec) {\n"
+ cpp_helper += " void* vectorData = static_cast<void*>(vec);\n"
+ read_args = []
+ read_args += ["parcel"]
+ read_args += ["&vectorData"]
+ read_args += ["&AParcel_stdVectorReallocator<" + cpp + ">"]
+ read_args += ["AParcel_stdVector" + read_using.capitalize() + "<" + cpp + ">"]
+ cpp_helper += " return AParcel_read" + pretty + "Array(" + ", ".join(read_args) + ");\n"
+ cpp_helper += "}\n\n"
+
+ replaceFileTags(ROOT + "include_ndk/android/binder_parcel.h", pre_header, "START-PRIMITIVE-VECTOR-GETTERS", "END-PRIMITIVE-VECTOR-GETTERS")
+ replaceFileTags(ROOT + "include_ndk/android/binder_parcel.h", header, "START-PRIMITIVE-READ-WRITE", "END-PRIMITIVE-READ-WRITE")
+ replaceFileTags(ROOT + "parcel.cpp", source, "START", "END")
+ replaceFileTags(ROOT + "include_ndk/android/binder_parcel_utils.h", cpp_helper, "START", "END")
+
+ print("Updating DONE.")
+
+if __name__ == "__main__":
+ main()
diff --git a/libs/binder/ndk/scripts/init_map.sh b/libs/binder/ndk/scripts/init_map.sh
new file mode 100755
index 0000000..1f74e43
--- /dev/null
+++ b/libs/binder/ndk/scripts/init_map.sh
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+
+# Simple helper for ease of development until this API is frozen.
+
+echo "LIBBINDER_NDK { # introduced=29"
+echo " global:"
+{
+ grep -oP "AIBinder_[a-zA-Z0-9_]+(?=\()" include_ndk/android/binder_ibinder.h;
+ grep -oP "AIBinder_[a-zA-Z0-9_]+(?=\()" include_ndk/android/binder_ibinder_jni.h;
+ grep -oP "AParcel_[a-zA-Z0-9_]+(?=\()" include_ndk/android/binder_parcel.h;
+ grep -oP "AStatus_[a-zA-Z0-9_]+(?=\()" include_ndk/android/binder_status.h;
+} | sort | uniq | awk '{ print " " $0 ";"; }'
+echo " local:"
+echo " *;"
+echo "};"
diff --git a/libs/binder/ndk/service_manager.cpp b/libs/binder/ndk/service_manager.cpp
new file mode 100644
index 0000000..9ddc555
--- /dev/null
+++ b/libs/binder/ndk/service_manager.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include <android/binder_manager.h>
+
+#include "ibinder_internal.h"
+#include "status_internal.h"
+
+#include <binder/IServiceManager.h>
+
+using ::android::defaultServiceManager;
+using ::android::IBinder;
+using ::android::IServiceManager;
+using ::android::sp;
+using ::android::status_t;
+using ::android::String16;
+
+binder_status_t AServiceManager_addService(AIBinder* binder, const char* instance) {
+ if (binder == nullptr || instance == nullptr) {
+ return STATUS_UNEXPECTED_NULL;
+ }
+
+ sp<IServiceManager> sm = defaultServiceManager();
+ status_t status = sm->addService(String16(instance), binder->getBinder());
+ return PruneStatusT(status);
+}
+AIBinder* AServiceManager_getService(const char* instance) {
+ if (instance == nullptr) {
+ return nullptr;
+ }
+
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16(instance));
+
+ sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(binder);
+ AIBinder_incStrong(ret.get());
+ return ret.get();
+}
diff --git a/libs/binder/ndk/status.cpp b/libs/binder/ndk/status.cpp
new file mode 100644
index 0000000..1f75b0b
--- /dev/null
+++ b/libs/binder/ndk/status.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include <android/binder_status.h>
+#include "status_internal.h"
+
+#include <android-base/logging.h>
+
+using ::android::status_t;
+using ::android::binder::Status;
+
+AStatus* AStatus_newOk() {
+ return new AStatus();
+}
+
+AStatus* AStatus_fromExceptionCode(binder_exception_t exception) {
+ return new AStatus(Status::fromExceptionCode(PruneException(exception)));
+}
+
+AStatus* AStatus_fromExceptionCodeWithMessage(binder_exception_t exception, const char* message) {
+ return new AStatus(Status::fromExceptionCode(PruneException(exception), message));
+}
+
+AStatus* AStatus_fromServiceSpecificError(int32_t serviceSpecific) {
+ return new AStatus(Status::fromServiceSpecificError(serviceSpecific));
+}
+
+AStatus* AStatus_fromServiceSpecificErrorWithMessage(int32_t serviceSpecific, const char* message) {
+ return new AStatus(Status::fromServiceSpecificError(serviceSpecific, message));
+}
+
+AStatus* AStatus_fromStatus(binder_status_t status) {
+ return new AStatus(Status::fromStatusT(PruneStatusT(status)));
+}
+
+bool AStatus_isOk(const AStatus* status) {
+ return status->get()->isOk();
+}
+
+binder_exception_t AStatus_getExceptionCode(const AStatus* status) {
+ return PruneException(status->get()->exceptionCode());
+}
+
+int32_t AStatus_getServiceSpecificError(const AStatus* status) {
+ return status->get()->serviceSpecificErrorCode();
+}
+
+binder_status_t AStatus_getStatus(const AStatus* status) {
+ return PruneStatusT(status->get()->transactionError());
+}
+
+const char* AStatus_getMessage(const AStatus* status) {
+ return status->get()->exceptionMessage().c_str();
+}
+
+void AStatus_delete(AStatus* status) {
+ delete status;
+}
+
+binder_status_t PruneStatusT(status_t status) {
+ switch (status) {
+ case ::android::OK:
+ return STATUS_OK;
+ case ::android::NO_MEMORY:
+ return STATUS_NO_MEMORY;
+ case ::android::INVALID_OPERATION:
+ return STATUS_INVALID_OPERATION;
+ case ::android::BAD_VALUE:
+ return STATUS_BAD_VALUE;
+ case ::android::BAD_TYPE:
+ return STATUS_BAD_TYPE;
+ case ::android::NAME_NOT_FOUND:
+ return STATUS_NAME_NOT_FOUND;
+ case ::android::PERMISSION_DENIED:
+ return STATUS_PERMISSION_DENIED;
+ case ::android::NO_INIT:
+ return STATUS_NO_INIT;
+ case ::android::ALREADY_EXISTS:
+ return STATUS_ALREADY_EXISTS;
+ case ::android::DEAD_OBJECT:
+ return STATUS_DEAD_OBJECT;
+ case ::android::FAILED_TRANSACTION:
+ return STATUS_FAILED_TRANSACTION;
+ case ::android::BAD_INDEX:
+ return STATUS_BAD_INDEX;
+ case ::android::NOT_ENOUGH_DATA:
+ return STATUS_NOT_ENOUGH_DATA;
+ case ::android::WOULD_BLOCK:
+ return STATUS_WOULD_BLOCK;
+ case ::android::TIMED_OUT:
+ return STATUS_TIMED_OUT;
+ case ::android::UNKNOWN_TRANSACTION:
+ return STATUS_UNKNOWN_TRANSACTION;
+ case ::android::FDS_NOT_ALLOWED:
+ return STATUS_FDS_NOT_ALLOWED;
+ case ::android::UNEXPECTED_NULL:
+ return STATUS_UNEXPECTED_NULL;
+ case ::android::UNKNOWN_ERROR:
+ return STATUS_UNKNOWN_ERROR;
+
+ default:
+ LOG(WARNING) << __func__
+ << ": Unknown status_t pruned into STATUS_UNKNOWN_ERROR: " << status;
+ return STATUS_UNKNOWN_ERROR;
+ }
+}
+
+binder_exception_t PruneException(int32_t exception) {
+ switch (exception) {
+ case Status::EX_NONE:
+ return EX_NONE;
+ case Status::EX_SECURITY:
+ return EX_SECURITY;
+ case Status::EX_BAD_PARCELABLE:
+ return EX_BAD_PARCELABLE;
+ case Status::EX_ILLEGAL_ARGUMENT:
+ return EX_ILLEGAL_ARGUMENT;
+ case Status::EX_NULL_POINTER:
+ return EX_NULL_POINTER;
+ case Status::EX_ILLEGAL_STATE:
+ return EX_ILLEGAL_STATE;
+ case Status::EX_NETWORK_MAIN_THREAD:
+ return EX_NETWORK_MAIN_THREAD;
+ case Status::EX_UNSUPPORTED_OPERATION:
+ return EX_UNSUPPORTED_OPERATION;
+ case Status::EX_SERVICE_SPECIFIC:
+ return EX_SERVICE_SPECIFIC;
+ case Status::EX_PARCELABLE:
+ return EX_PARCELABLE;
+ case Status::EX_TRANSACTION_FAILED:
+ return EX_TRANSACTION_FAILED;
+
+ default:
+ LOG(WARNING) << __func__
+ << ": Unknown status_t pruned into EX_TRANSACTION_FAILED: " << exception;
+ return EX_TRANSACTION_FAILED;
+ }
+}
diff --git a/libs/binder/ndk/status_internal.h b/libs/binder/ndk/status_internal.h
new file mode 100644
index 0000000..8c32baf
--- /dev/null
+++ b/libs/binder/ndk/status_internal.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 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 <android/binder_status.h>
+
+#include <binder/Status.h>
+#include <utils/Errors.h>
+
+struct AStatus {
+ AStatus() {} // ok
+ AStatus(::android::binder::Status&& status) : mStatus(std::move(status)) {}
+
+ ::android::binder::Status* get() { return &mStatus; }
+ const ::android::binder::Status* get() const { return &mStatus; }
+
+private:
+ ::android::binder::Status mStatus;
+};
+
+// This collapses the statuses into the declared range.
+binder_status_t PruneStatusT(android::status_t status);
+
+// This collapses the exception into the declared range.
+binder_exception_t PruneException(int32_t exception);
diff --git a/libs/binder/ndk/test/Android.bp b/libs/binder/ndk/test/Android.bp
new file mode 100644
index 0000000..8e40a01
--- /dev/null
+++ b/libs/binder/ndk/test/Android.bp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 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.
+ */
+
+// This test is a unit test of the low-level API that is presented here.
+// Actual users should use AIDL to generate these complicated stubs.
+
+cc_defaults {
+ name: "test_libbinder_ndk_defaults",
+ shared_libs: [
+ "libbase",
+ ],
+ strip: {
+ none: true,
+ },
+ cflags: [
+ "-O0",
+ "-g",
+ ],
+}
+
+cc_library_static {
+ name: "test_libbinder_ndk_library",
+ defaults: ["test_libbinder_ndk_defaults"],
+ export_include_dirs: ["include"],
+ shared_libs: ["libbinder_ndk"],
+ export_shared_lib_headers: ["libbinder_ndk"],
+ srcs: ["iface.cpp"],
+}
+
+cc_defaults {
+ name: "test_libbinder_ndk_test_defaults",
+ defaults: ["test_libbinder_ndk_defaults"],
+ shared_libs: [
+ "libandroid_runtime",
+ "libbase",
+ "libbinder",
+ "libutils",
+ ],
+ static_libs: [
+ "libbinder_ndk",
+ "test_libbinder_ndk_library",
+ ],
+}
+
+cc_test {
+ name: "libbinder_ndk_test_client",
+ defaults: ["test_libbinder_ndk_test_defaults"],
+ srcs: ["main_client.cpp"],
+}
+
+cc_test {
+ name: "libbinder_ndk_test_server",
+ defaults: ["test_libbinder_ndk_test_defaults"],
+ srcs: ["main_server.cpp"],
+ gtest: false,
+}
diff --git a/libs/binder/ndk/test/iface.cpp b/libs/binder/ndk/test/iface.cpp
new file mode 100644
index 0000000..0dc3cc4
--- /dev/null
+++ b/libs/binder/ndk/test/iface.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <iface/iface.h>
+
+using ::android::sp;
+using ::android::wp;
+
+const char* IFoo::kSomeInstanceName = "libbinder_ndk-test-IFoo";
+const char* kIFooDescriptor = "my-special-IFoo-class";
+
+struct IFoo_Class_Data {
+ sp<IFoo> foo;
+};
+
+void* IFoo_Class_onCreate(void* args) {
+ IFoo_Class_Data* foo = static_cast<IFoo_Class_Data*>(args);
+ // This is a foo, but we're currently not verifying that. So, the method newLocalBinder is
+ // coupled with this.
+ return static_cast<void*>(foo);
+}
+
+void IFoo_Class_onDestroy(void* userData) {
+ delete static_cast<IFoo_Class_Data*>(userData);
+}
+
+binder_status_t IFoo_Class_onTransact(AIBinder* binder, transaction_code_t code, const AParcel* in,
+ AParcel* out) {
+ binder_status_t stat = STATUS_FAILED_TRANSACTION;
+
+ sp<IFoo> foo = static_cast<IFoo_Class_Data*>(AIBinder_getUserData(binder))->foo;
+ CHECK(foo != nullptr) << "Transaction made on already deleted object";
+
+ switch (code) {
+ case IFoo::DOFOO: {
+ int32_t valueIn;
+ stat = AParcel_readInt32(in, &valueIn);
+ if (stat != STATUS_OK) break;
+ int32_t valueOut = foo->doubleNumber(valueIn);
+ stat = AParcel_writeInt32(out, valueOut);
+ break;
+ }
+ }
+
+ return stat;
+}
+
+AIBinder_Class* IFoo::kClass = AIBinder_Class_define(kIFooDescriptor, IFoo_Class_onCreate,
+ IFoo_Class_onDestroy, IFoo_Class_onTransact);
+
+class BpFoo : public IFoo {
+public:
+ BpFoo(AIBinder* binder) : mBinder(binder) {}
+ virtual ~BpFoo() { AIBinder_decStrong(mBinder); }
+
+ virtual int32_t doubleNumber(int32_t in) {
+ AParcel* parcelIn;
+ CHECK(STATUS_OK == AIBinder_prepareTransaction(mBinder, &parcelIn));
+
+ CHECK(STATUS_OK == AParcel_writeInt32(parcelIn, in));
+
+ AParcel* parcelOut;
+ CHECK(STATUS_OK ==
+ AIBinder_transact(mBinder, IFoo::DOFOO, &parcelIn, &parcelOut, 0 /*flags*/));
+
+ int32_t out;
+ CHECK(STATUS_OK == AParcel_readInt32(parcelOut, &out));
+
+ AParcel_delete(parcelOut);
+
+ return out;
+ }
+
+private:
+ // Always assumes one refcount
+ AIBinder* mBinder;
+};
+
+IFoo::~IFoo() {
+ AIBinder_Weak_delete(mWeakBinder);
+}
+
+binder_status_t IFoo::addService(const char* instance) {
+ AIBinder* binder = nullptr;
+
+ if (mWeakBinder != nullptr) {
+ // one strong ref count of binder
+ binder = AIBinder_Weak_promote(mWeakBinder);
+ }
+ if (binder == nullptr) {
+ // or one strong refcount here
+ binder = AIBinder_new(IFoo::kClass, static_cast<void*>(new IFoo_Class_Data{this}));
+ if (mWeakBinder != nullptr) {
+ AIBinder_Weak_delete(mWeakBinder);
+ }
+ mWeakBinder = AIBinder_Weak_new(binder);
+ }
+
+ binder_status_t status = AServiceManager_addService(binder, instance);
+ // Strong references we care about kept by remote process
+ AIBinder_decStrong(binder);
+ return status;
+}
+
+sp<IFoo> IFoo::getService(const char* instance) {
+ AIBinder* binder = AServiceManager_getService(instance); // maybe nullptr
+ if (binder == nullptr) {
+ return nullptr;
+ }
+
+ if (!AIBinder_associateClass(binder, IFoo::kClass)) {
+ AIBinder_decStrong(binder);
+ return nullptr;
+ }
+
+ if (AIBinder_isRemote(binder)) {
+ sp<IFoo> ret = new BpFoo(binder); // takes ownership of binder
+ return ret;
+ }
+
+ IFoo_Class_Data* data = static_cast<IFoo_Class_Data*>(AIBinder_getUserData(binder));
+
+ CHECK(data != nullptr); // always created with non-null data
+
+ sp<IFoo> ret = data->foo;
+
+ AIBinder* held = AIBinder_Weak_promote(ret->mWeakBinder);
+ CHECK(held == binder);
+ AIBinder_decStrong(held);
+
+ // IFoo only keeps a weak reference to AIBinder, so we can drop this
+ AIBinder_decStrong(binder);
+ return ret;
+}
diff --git a/libs/binder/ndk/test/include/iface/iface.h b/libs/binder/ndk/test/include/iface/iface.h
new file mode 100644
index 0000000..4c61e9d
--- /dev/null
+++ b/libs/binder/ndk/test/include/iface/iface.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 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 <android/binder_ibinder.h>
+#include <utils/RefBase.h>
+
+class IFoo : public virtual ::android::RefBase {
+public:
+ static const char* kSomeInstanceName;
+ static AIBinder_Class* kClass;
+
+ // Takes ownership of IFoo
+ binder_status_t addService(const char* instance);
+ static ::android::sp<IFoo> getService(const char* instance);
+
+ enum Call {
+ DOFOO = FIRST_CALL_TRANSACTION + 0,
+ };
+
+ virtual ~IFoo();
+ virtual int32_t doubleNumber(int32_t in) = 0;
+
+private:
+ AIBinder_Weak* mWeakBinder = nullptr; // maybe owns AIBinder
+};
diff --git a/libs/binder/ndk/test/main_client.cpp b/libs/binder/ndk/test/main_client.cpp
new file mode 100644
index 0000000..6945cac
--- /dev/null
+++ b/libs/binder/ndk/test/main_client.cpp
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_ibinder_jni.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <gtest/gtest.h>
+#include <iface/iface.h>
+
+using ::android::sp;
+
+constexpr char kExistingNonNdkService[] = "SurfaceFlinger";
+
+// This is too slow
+// TEST(NdkBinder, GetServiceThatDoesntExist) {
+// sp<IFoo> foo = IFoo::getService("asdfghkl;");
+// EXPECT_EQ(nullptr, foo.get());
+// }
+
+TEST(NdkBinder, DoubleNumber) {
+ sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName);
+ ASSERT_NE(foo, nullptr);
+ EXPECT_EQ(2, foo->doubleNumber(1));
+}
+
+TEST(NdkBinder, RetrieveNonNdkService) {
+ AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
+ ASSERT_NE(nullptr, binder);
+ EXPECT_TRUE(AIBinder_isRemote(binder));
+ EXPECT_TRUE(AIBinder_isAlive(binder));
+ EXPECT_EQ(STATUS_OK, AIBinder_ping(binder));
+
+ AIBinder_decStrong(binder);
+}
+
+void OnBinderDeath(void* cookie) {
+ LOG(ERROR) << "BINDER DIED. COOKIE: " << cookie;
+}
+
+TEST(NdkBinder, LinkToDeath) {
+ ABinderProcess_setThreadPoolMaxThreadCount(1); // to recieve death notifications
+ ABinderProcess_startThreadPool();
+
+ AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
+ ASSERT_NE(nullptr, binder);
+
+ AIBinder_DeathRecipient* recipient = AIBinder_DeathRecipient_new(OnBinderDeath);
+ ASSERT_NE(nullptr, recipient);
+
+ EXPECT_EQ(STATUS_OK, AIBinder_linkToDeath(binder, recipient, nullptr));
+ EXPECT_EQ(STATUS_OK, AIBinder_linkToDeath(binder, recipient, nullptr));
+ EXPECT_EQ(STATUS_OK, AIBinder_unlinkToDeath(binder, recipient, nullptr));
+ EXPECT_EQ(STATUS_OK, AIBinder_unlinkToDeath(binder, recipient, nullptr));
+ EXPECT_EQ(STATUS_NAME_NOT_FOUND, AIBinder_unlinkToDeath(binder, recipient, nullptr));
+
+ AIBinder_DeathRecipient_delete(recipient);
+ AIBinder_decStrong(binder);
+}
+
+class MyTestFoo : public IFoo {
+ int32_t doubleNumber(int32_t in) override {
+ LOG(INFO) << "doubleNumber " << in;
+ return 2 * in;
+ }
+};
+
+TEST(NdkBinder, GetServiceInProcess) {
+ static const char* kInstanceName = "test-get-service-in-process";
+
+ sp<IFoo> foo = new MyTestFoo;
+ EXPECT_EQ(STATUS_OK, foo->addService(kInstanceName));
+
+ sp<IFoo> getFoo = IFoo::getService(kInstanceName);
+ EXPECT_EQ(foo.get(), getFoo.get());
+
+ EXPECT_EQ(2, getFoo->doubleNumber(1));
+}
+
+TEST(NdkBinder, EqualityOfRemoteBinderPointer) {
+ AIBinder* binderA = AServiceManager_getService(kExistingNonNdkService);
+ ASSERT_NE(nullptr, binderA);
+
+ AIBinder* binderB = AServiceManager_getService(kExistingNonNdkService);
+ ASSERT_NE(nullptr, binderB);
+
+ EXPECT_EQ(binderA, binderB);
+
+ AIBinder_decStrong(binderA);
+ AIBinder_decStrong(binderB);
+}
+
+TEST(NdkBinder, ToFromJavaNullptr) {
+ EXPECT_EQ(nullptr, AIBinder_toJavaBinder(nullptr, nullptr));
+ EXPECT_EQ(nullptr, AIBinder_fromJavaBinder(nullptr, nullptr));
+}
+
+TEST(NdkBinder, ABpBinderRefCount) {
+ AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
+ AIBinder_Weak* wBinder = AIBinder_Weak_new(binder);
+
+ ASSERT_NE(nullptr, binder);
+ EXPECT_EQ(1, AIBinder_debugGetRefCount(binder));
+
+ AIBinder_decStrong(binder);
+
+ // assert because would need to decStrong if non-null and we shouldn't need to add a no-op here
+ ASSERT_NE(nullptr, AIBinder_Weak_promote(wBinder));
+
+ AIBinder_Weak_delete(wBinder);
+}
+
+TEST(NdkBinder, AddServiceMultipleTimes) {
+ static const char* kInstanceName1 = "test-multi-1";
+ static const char* kInstanceName2 = "test-multi-2";
+ sp<IFoo> foo = new MyTestFoo;
+ EXPECT_EQ(STATUS_OK, foo->addService(kInstanceName1));
+ EXPECT_EQ(STATUS_OK, foo->addService(kInstanceName2));
+ EXPECT_EQ(IFoo::getService(kInstanceName1), IFoo::getService(kInstanceName2));
+}
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcel_utils.h>
diff --git a/libs/binder/ndk/test/main_server.cpp b/libs/binder/ndk/test/main_server.cpp
new file mode 100644
index 0000000..0718a69
--- /dev/null
+++ b/libs/binder/ndk/test/main_server.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_process.h>
+#include <iface/iface.h>
+
+using ::android::sp;
+
+class MyFoo : public IFoo {
+ int32_t doubleNumber(int32_t in) override {
+ LOG(INFO) << "doubling " << in;
+ return 2 * in;
+ }
+};
+
+int main() {
+ ABinderProcess_setThreadPoolMaxThreadCount(0);
+
+ // Strong reference to MyFoo kept by service manager.
+ binder_status_t status = (new MyFoo)->addService(IFoo::kSomeInstanceName);
+
+ if (status != STATUS_OK) {
+ LOG(FATAL) << "Could not register: " << status;
+ }
+
+ ABinderProcess_joinThreadPool();
+
+ return 1;
+}
diff --git a/libs/binder/ndk/update.sh b/libs/binder/ndk/update.sh
new file mode 100755
index 0000000..9a4577f
--- /dev/null
+++ b/libs/binder/ndk/update.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 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.
+
+
+set -ex
+
+# This script makes sure that the source code is in sync with the various scripts
+./scripts/gen_parcel_helper.py
+./scripts/format.sh
+./scripts/init_map.sh > libbinder_ndk.map.txt
diff --git a/libs/binder/tests/binderDriverInterfaceTest.cpp b/libs/binder/tests/binderDriverInterfaceTest.cpp
index 4f00bc1..77ebac8 100644
--- a/libs/binder/tests/binderDriverInterfaceTest.cpp
+++ b/libs/binder/tests/binderDriverInterfaceTest.cpp
@@ -36,8 +36,8 @@
m_binderFd = open(BINDER_DEV_NAME, O_RDWR | O_NONBLOCK | O_CLOEXEC);
ASSERT_GE(m_binderFd, 0);
- m_buffer = mmap(NULL, 64*1024, PROT_READ, MAP_SHARED, m_binderFd, 0);
- ASSERT_NE(m_buffer, (void *)NULL);
+ m_buffer = mmap(nullptr, 64*1024, PROT_READ, MAP_SHARED, m_binderFd, 0);
+ ASSERT_NE(m_buffer, (void *)nullptr);
ret = ioctl(m_binderFd, BINDER_SET_MAX_THREADS, &max_threads);
EXPECT_EQ(0, ret);
EnterLooper();
@@ -156,23 +156,23 @@
}
TEST_F(BinderDriverInterfaceTest, WriteReadNull) {
- binderTestIoctlErr1(BINDER_WRITE_READ, NULL, EFAULT);
+ binderTestIoctlErr1(BINDER_WRITE_READ, nullptr, EFAULT);
}
TEST_F(BinderDriverInterfaceTest, SetIdleTimeoutNull) {
- binderTestIoctlErr2(BINDER_SET_IDLE_TIMEOUT, NULL, EFAULT, EINVAL);
+ binderTestIoctlErr2(BINDER_SET_IDLE_TIMEOUT, nullptr, EFAULT, EINVAL);
}
TEST_F(BinderDriverInterfaceTest, SetMaxThreadsNull) {
- binderTestIoctlErr2(BINDER_SET_MAX_THREADS, NULL, EFAULT, EINVAL); /* TODO: don't accept EINVAL */
+ binderTestIoctlErr2(BINDER_SET_MAX_THREADS, nullptr, EFAULT, EINVAL); /* TODO: don't accept EINVAL */
}
TEST_F(BinderDriverInterfaceTest, SetIdlePriorityNull) {
- binderTestIoctlErr2(BINDER_SET_IDLE_PRIORITY, NULL, EFAULT, EINVAL);
+ binderTestIoctlErr2(BINDER_SET_IDLE_PRIORITY, nullptr, EFAULT, EINVAL);
}
TEST_F(BinderDriverInterfaceTest, VersionNull) {
- binderTestIoctlErr2(BINDER_VERSION, NULL, EFAULT, EINVAL); /* TODO: don't accept EINVAL */
+ binderTestIoctlErr2(BINDER_VERSION, nullptr, EFAULT, EINVAL); /* TODO: don't accept EINVAL */
}
TEST_F(BinderDriverInterfaceTest, SetIdleTimeoutNoTest) {
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 1611e11..73c2eba 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -65,6 +65,7 @@
BINDER_LIB_TEST_ADD_STRONG_REF_TRANSACTION,
BINDER_LIB_TEST_LINK_DEATH_TRANSACTION,
BINDER_LIB_TEST_WRITE_FILE_TRANSACTION,
+ BINDER_LIB_TEST_WRITE_PARCEL_FILE_DESCRIPTOR_TRANSACTION,
BINDER_LIB_TEST_PROMOTE_WEAK_REF_TRANSACTION,
BINDER_LIB_TEST_EXIT_TRANSACTION,
BINDER_LIB_TEST_DELAYED_EXIT_TRANSACTION,
@@ -88,7 +89,7 @@
strpipefd1,
usepoll,
binderserversuffix,
- NULL
+ nullptr
};
ret = pipe(pipefd);
@@ -123,7 +124,7 @@
}
}
if (ret < 0) {
- wait(NULL);
+ wait(nullptr);
return ret;
}
return pid;
@@ -145,7 +146,7 @@
sp<IServiceManager> sm = defaultServiceManager();
//printf("%s: pid %d, get service\n", __func__, m_pid);
m_server = sm->getService(binderLibTestServiceName);
- ASSERT_TRUE(m_server != NULL);
+ ASSERT_TRUE(m_server != nullptr);
//printf("%s: pid %d, get service done\n", __func__, m_pid);
}
virtual void TearDown() {
@@ -155,7 +156,7 @@
pid_t pid;
//printf("%s: pid %d\n", __func__, m_pid);
- if (m_server != NULL) {
+ if (m_server != nullptr) {
ret = m_server->transact(BINDER_LIB_TEST_GET_STATUS_TRANSACTION, data, &reply);
EXPECT_EQ(0, ret);
ret = m_server->transact(BINDER_LIB_TEST_EXIT_TRANSACTION, data, &reply, TF_ONE_WAY);
@@ -192,9 +193,9 @@
ret = m_server->transact(code, data, &reply);
EXPECT_EQ(NO_ERROR, ret);
- EXPECT_FALSE(binder != NULL);
+ EXPECT_FALSE(binder != nullptr);
binder = reply.readStrongBinder();
- EXPECT_TRUE(binder != NULL);
+ EXPECT_TRUE(binder != nullptr);
ret = reply.readInt32(&id);
EXPECT_EQ(NO_ERROR, ret);
if (idPtr)
@@ -202,12 +203,12 @@
return binder;
}
- sp<IBinder> addServer(int32_t *idPtr = NULL)
+ sp<IBinder> addServer(int32_t *idPtr = nullptr)
{
return addServerEtc(idPtr, BINDER_LIB_TEST_ADD_SERVER);
}
- sp<IBinder> addPollServer(int32_t *idPtr = NULL)
+ sp<IBinder> addPollServer(int32_t *idPtr = nullptr)
{
return addServerEtc(idPtr, BINDER_LIB_TEST_ADD_POLL_SERVER);
}
@@ -274,8 +275,8 @@
BinderLibTestEvent(void)
: m_eventTriggered(false)
{
- pthread_mutex_init(&m_waitMutex, NULL);
- pthread_cond_init(&m_waitCond, NULL);
+ pthread_mutex_init(&m_waitMutex, nullptr);
+ pthread_cond_init(&m_waitCond, nullptr);
}
int waitEvent(int timeout_s)
{
@@ -315,7 +316,7 @@
public:
BinderLibTestCallBack()
: m_result(NOT_ENOUGH_DATA)
- , m_prev_end(NULL)
+ , m_prev_end(nullptr)
{
}
status_t getResult(void)
@@ -413,7 +414,7 @@
int32_t ptrsize;
Parcel data, reply;
sp<IBinder> server = addServer();
- ASSERT_TRUE(server != NULL);
+ ASSERT_TRUE(server != nullptr);
ret = server->transact(BINDER_LIB_TEST_GET_PTR_SIZE_TRANSACTION, data, &reply);
EXPECT_EQ(NO_ERROR, ret);
ret = reply.readInt32(&ptrsize);
@@ -436,7 +437,7 @@
BinderLibTestBundle datai;
server = addServer(&serverId[i]);
- ASSERT_TRUE(server != NULL);
+ ASSERT_TRUE(server != nullptr);
data.writeStrongBinder(server);
data.writeInt32(BINDER_LIB_TEST_GET_ID_TRANSACTION);
datai.appendTo(&data);
@@ -480,7 +481,7 @@
BinderLibTestBundle datai2;
server = addServer(&serverId[i]);
- ASSERT_TRUE(server != NULL);
+ ASSERT_TRUE(server != nullptr);
data.writeStrongBinder(server);
data.writeInt32(BINDER_LIB_TEST_INDIRECT_TRANSACTION);
@@ -546,7 +547,7 @@
TEST_F(BinderLibTest, AddServer)
{
sp<IBinder> server = addServer();
- ASSERT_TRUE(server != NULL);
+ ASSERT_TRUE(server != nullptr);
}
TEST_F(BinderLibTest, DeathNotificationNoRefs)
@@ -557,7 +558,7 @@
{
sp<IBinder> binder = addServer();
- ASSERT_TRUE(binder != NULL);
+ ASSERT_TRUE(binder != nullptr);
ret = binder->linkToDeath(testDeathRecipient);
EXPECT_EQ(NO_ERROR, ret);
}
@@ -579,7 +580,7 @@
{
sp<IBinder> binder = addServer();
- ASSERT_TRUE(binder != NULL);
+ ASSERT_TRUE(binder != nullptr);
ret = binder->linkToDeath(testDeathRecipient);
EXPECT_EQ(NO_ERROR, ret);
wbinder = binder;
@@ -602,7 +603,7 @@
{
sp<IBinder> binder = addServer();
- ASSERT_TRUE(binder != NULL);
+ ASSERT_TRUE(binder != nullptr);
ret = binder->linkToDeath(testDeathRecipient);
EXPECT_EQ(NO_ERROR, ret);
sbinder = binder;
@@ -629,13 +630,13 @@
sp<IBinder> passiveclient[clientcount];
target = addServer();
- ASSERT_TRUE(target != NULL);
+ ASSERT_TRUE(target != nullptr);
for (int i = 0; i < clientcount; i++) {
{
Parcel data, reply;
linkedclient[i] = addServer();
- ASSERT_TRUE(linkedclient[i] != NULL);
+ ASSERT_TRUE(linkedclient[i] != nullptr);
callBack[i] = new BinderLibTestCallBack();
data.writeStrongBinder(target);
data.writeStrongBinder(callBack[i]);
@@ -646,7 +647,7 @@
Parcel data, reply;
passiveclient[i] = addServer();
- ASSERT_TRUE(passiveclient[i] != NULL);
+ ASSERT_TRUE(passiveclient[i] != nullptr);
data.writeStrongBinder(target);
ret = passiveclient[i]->transact(BINDER_LIB_TEST_ADD_STRONG_REF_TRANSACTION, data, &reply, TF_ONE_WAY);
EXPECT_EQ(NO_ERROR, ret);
@@ -671,9 +672,9 @@
status_t ret;
sp<BinderLibTestCallBack> callback;
sp<IBinder> target = addServer();
- ASSERT_TRUE(target != NULL);
+ ASSERT_TRUE(target != nullptr);
sp<IBinder> client = addServer();
- ASSERT_TRUE(client != NULL);
+ ASSERT_TRUE(client != nullptr);
sp<TestDeathRecipient> testDeathRecipient = new TestDeathRecipient();
@@ -763,16 +764,51 @@
close(pipefd[0]);
}
+TEST_F(BinderLibTest, PassParcelFileDescriptor) {
+ const int datasize = 123;
+ std::vector<uint8_t> writebuf(datasize);
+ for (size_t i = 0; i < writebuf.size(); ++i) {
+ writebuf[i] = i;
+ }
+
+ android::base::unique_fd read_end, write_end;
+ {
+ int pipefd[2];
+ ASSERT_EQ(0, pipe2(pipefd, O_NONBLOCK));
+ read_end.reset(pipefd[0]);
+ write_end.reset(pipefd[1]);
+ }
+ {
+ Parcel data;
+ EXPECT_EQ(NO_ERROR, data.writeDupParcelFileDescriptor(write_end.get()));
+ write_end.reset();
+ EXPECT_EQ(NO_ERROR, data.writeInt32(datasize));
+ EXPECT_EQ(NO_ERROR, data.write(writebuf.data(), datasize));
+
+ Parcel reply;
+ EXPECT_EQ(NO_ERROR,
+ m_server->transact(BINDER_LIB_TEST_WRITE_PARCEL_FILE_DESCRIPTOR_TRANSACTION, data,
+ &reply));
+ }
+ std::vector<uint8_t> readbuf(datasize);
+ EXPECT_EQ(datasize, read(read_end.get(), readbuf.data(), datasize));
+ EXPECT_EQ(writebuf, readbuf);
+
+ waitForReadData(read_end.get(), 5000); /* wait for other proccess to close pipe */
+
+ EXPECT_EQ(0, read(read_end.get(), readbuf.data(), datasize));
+}
+
TEST_F(BinderLibTest, PromoteLocal) {
sp<IBinder> strong = new BBinder();
wp<IBinder> weak = strong;
sp<IBinder> strong_from_weak = weak.promote();
- EXPECT_TRUE(strong != NULL);
+ EXPECT_TRUE(strong != nullptr);
EXPECT_EQ(strong, strong_from_weak);
- strong = NULL;
- strong_from_weak = NULL;
+ strong = nullptr;
+ strong_from_weak = nullptr;
strong_from_weak = weak.promote();
- EXPECT_TRUE(strong_from_weak == NULL);
+ EXPECT_TRUE(strong_from_weak == nullptr);
}
TEST_F(BinderLibTest, PromoteRemote) {
@@ -781,8 +817,8 @@
sp<IBinder> strong = new BBinder();
sp<IBinder> server = addServer();
- ASSERT_TRUE(server != NULL);
- ASSERT_TRUE(strong != NULL);
+ ASSERT_TRUE(server != nullptr);
+ ASSERT_TRUE(strong != nullptr);
ret = data.writeWeakBinder(strong);
EXPECT_EQ(NO_ERROR, ret);
@@ -799,7 +835,7 @@
EXPECT_EQ(NO_ERROR, ret);
const flat_binder_object *fb = reply.readObject(false);
- ASSERT_TRUE(fb != NULL);
+ ASSERT_TRUE(fb != nullptr);
EXPECT_EQ(BINDER_TYPE_HANDLE, fb->hdr.type);
EXPECT_EQ(m_server, ProcessState::self()->getStrongProxyForHandle(fb->handle));
EXPECT_EQ((binder_uintptr_t)0, fb->cookie);
@@ -810,7 +846,7 @@
status_t ret;
sp<IBinder> server = addServer();
- ASSERT_TRUE(server != NULL);
+ ASSERT_TRUE(server != nullptr);
__u32 freedHandle;
wp<IBinder> keepFreedBinder;
@@ -881,12 +917,12 @@
data2.writeStrongBinder(callBack2);
data2.writeInt32(0); // delay in us
- ret = pollServer->transact(BINDER_LIB_TEST_DELAYED_CALL_BACK, data, NULL, TF_ONE_WAY);
+ ret = pollServer->transact(BINDER_LIB_TEST_DELAYED_CALL_BACK, data, nullptr, TF_ONE_WAY);
EXPECT_EQ(NO_ERROR, ret);
// The delay ensures that this second transaction will end up on the async_todo list
// (for a single-threaded server)
- ret = pollServer->transact(BINDER_LIB_TEST_DELAYED_CALL_BACK, data2, NULL, TF_ONE_WAY);
+ ret = pollServer->transact(BINDER_LIB_TEST_DELAYED_CALL_BACK, data2, nullptr, TF_ONE_WAY);
EXPECT_EQ(NO_ERROR, ret);
// The server will ensure that the two transactions are handled in the expected order;
@@ -909,10 +945,10 @@
: m_id(id)
, m_nextServerId(id + 1)
, m_serverStartRequested(false)
- , m_callback(NULL)
+ , m_callback(nullptr)
{
- pthread_mutex_init(&m_serverWaitMutex, NULL);
- pthread_cond_init(&m_serverWaitCond, NULL);
+ pthread_mutex_init(&m_serverWaitMutex, nullptr);
+ pthread_cond_init(&m_serverWaitCond, nullptr);
}
~BinderLibTestService()
{
@@ -920,11 +956,11 @@
}
void processPendingCall() {
- if (m_callback != NULL) {
+ if (m_callback != nullptr) {
Parcel data;
data.writeInt32(NO_ERROR);
m_callback->transact(BINDER_LIB_TEST_CALL_BACK, data, nullptr, TF_ONE_WAY);
- m_callback = NULL;
+ m_callback = nullptr;
}
}
@@ -943,7 +979,7 @@
sp<IBinder> binder;
id = data.readInt32();
binder = data.readStrongBinder();
- if (binder == NULL) {
+ if (binder == nullptr) {
return BAD_VALUE;
}
@@ -993,7 +1029,7 @@
} else {
reply->writeStrongBinder(m_serverStarted);
reply->writeInt32(serverid);
- m_serverStarted = NULL;
+ m_serverStarted = nullptr;
ret = NO_ERROR;
}
} else if (ret >= 0) {
@@ -1008,7 +1044,7 @@
case BINDER_LIB_TEST_DELAYED_CALL_BACK: {
// Note: this transaction is only designed for use with a
// poll() server. See comments around epoll_wait().
- if (m_callback != NULL) {
+ if (m_callback != nullptr) {
// A callback was already pending; this means that
// we received a second call while still processing
// the first one. Fail the test.
@@ -1016,7 +1052,7 @@
Parcel data2;
data2.writeInt32(UNKNOWN_ERROR);
- callback->transact(BINDER_LIB_TEST_CALL_BACK, data2, NULL, TF_ONE_WAY);
+ callback->transact(BINDER_LIB_TEST_CALL_BACK, data2, nullptr, TF_ONE_WAY);
} else {
m_callback = data.readStrongBinder();
int32_t delayUs = data.readInt32();
@@ -1045,7 +1081,7 @@
Parcel data2, reply2;
sp<IBinder> binder;
binder = data.readStrongBinder();
- if (binder == NULL) {
+ if (binder == nullptr) {
return BAD_VALUE;
}
data2.writeInt32(NO_ERROR);
@@ -1068,7 +1104,7 @@
reply->writeInt32(count);
for (int i = 0; i < count; i++) {
binder = data.readStrongBinder();
- if (binder == NULL) {
+ if (binder == nullptr) {
return BAD_VALUE;
}
indirect_code = data.readInt32();
@@ -1101,11 +1137,11 @@
sp<IBinder> callback;
target = data.readStrongBinder();
- if (target == NULL) {
+ if (target == nullptr) {
return BAD_VALUE;
}
callback = data.readStrongBinder();
- if (callback == NULL) {
+ if (callback == nullptr) {
return BAD_VALUE;
}
ret = target->linkToDeath(testDeathRecipient);
@@ -1130,7 +1166,7 @@
return ret;
}
buf = data.readInplace(size);
- if (buf == NULL) {
+ if (buf == nullptr) {
return BAD_VALUE;
}
ret = write(fd, buf, size);
@@ -1138,6 +1174,28 @@
return UNKNOWN_ERROR;
return NO_ERROR;
}
+ case BINDER_LIB_TEST_WRITE_PARCEL_FILE_DESCRIPTOR_TRANSACTION: {
+ int ret;
+ int32_t size;
+ const void *buf;
+ android::base::unique_fd fd;
+
+ ret = data.readUniqueParcelFileDescriptor(&fd);
+ if (ret != NO_ERROR) {
+ return ret;
+ }
+ ret = data.readInt32(&size);
+ if (ret != NO_ERROR) {
+ return ret;
+ }
+ buf = data.readInplace(size);
+ if (buf == nullptr) {
+ return BAD_VALUE;
+ }
+ ret = write(fd.get(), buf, size);
+ if (ret != size) return UNKNOWN_ERROR;
+ return NO_ERROR;
+ }
case BINDER_LIB_TEST_PROMOTE_WEAK_REF_TRANSACTION: {
int ret;
wp<IBinder> weak;
@@ -1147,7 +1205,7 @@
sp<IBinder> server = sm->getService(binderLibTestServiceName);
weak = data.readWeakBinder();
- if (weak == NULL) {
+ if (weak == nullptr) {
return BAD_VALUE;
}
strong = weak.promote();
@@ -1156,7 +1214,7 @@
if (ret != NO_ERROR)
exit(EXIT_FAILURE);
- if (strong == NULL) {
+ if (strong == nullptr) {
reply->setError(1);
}
return NO_ERROR;
@@ -1165,7 +1223,7 @@
alarm(10);
return NO_ERROR;
case BINDER_LIB_TEST_EXIT_TRANSACTION:
- while (wait(NULL) != -1 || errno != ECHILD)
+ while (wait(nullptr) != -1 || errno != ECHILD)
;
exit(EXIT_SUCCESS);
case BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION: {
@@ -1300,4 +1358,3 @@
ProcessState::self()->startThreadPool();
return RUN_ALL_TESTS();
}
-
diff --git a/libs/binder/tests/binderTextOutputTest.cpp b/libs/binder/tests/binderTextOutputTest.cpp
index f6dd22d..ce99f59 100644
--- a/libs/binder/tests/binderTextOutputTest.cpp
+++ b/libs/binder/tests/binderTextOutputTest.cpp
@@ -28,15 +28,14 @@
#include <binder/TextOutput.h>
#include <binder/Debug.h>
-static void CheckMessage(const CapturedStderr& cap,
+static void CheckMessage(CapturedStderr& cap,
const char* expected,
bool singleline) {
- std::string output;
- ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
- android::base::ReadFdToString(cap.fd(), &output);
+ cap.Stop();
+ std::string output = cap.str();
if (singleline)
output.erase(std::remove(output.begin(), output.end(), '\n'));
- ASSERT_STREQ(output.c_str(), expected);
+ ASSERT_EQ(output, expected);
}
#define CHECK_LOG_(input, expect, singleline) \
@@ -60,28 +59,22 @@
TEST(TextOutput, HandlesStdEndl) {
CapturedStderr cap;
android::aerr << "foobar" << std::endl;
- std::string output;
- ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
- android::base::ReadFdToString(cap.fd(), &output);
- ASSERT_STREQ(output.c_str(), "foobar\n");
+ cap.Stop();
+ ASSERT_EQ(cap.str(), "foobar\n");
}
TEST(TextOutput, HandlesCEndl) {
CapturedStderr cap;
android::aerr << "foobar" << "\n";
- std::string output;
- ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
- android::base::ReadFdToString(cap.fd(), &output);
- ASSERT_STREQ(output.c_str(), "foobar\n");
+ cap.Stop();
+ ASSERT_EQ(cap.str(), "foobar\n");
}
TEST(TextOutput, HandlesAndroidEndl) {
CapturedStderr cap;
android::aerr << "foobar" << android::endl;
- std::string output;
- ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
- android::base::ReadFdToString(cap.fd(), &output);
- ASSERT_STREQ(output.c_str(), "foobar\n");
+ cap.Stop();
+ ASSERT_EQ(cap.str(), "foobar\n");
}
TEST(TextOutput, HandleEmptyString) {
diff --git a/libs/binder/tests/binderThroughputTest.cpp b/libs/binder/tests/binderThroughputTest.cpp
index bf41e0b..b790997 100644
--- a/libs/binder/tests/binderThroughputTest.cpp
+++ b/libs/binder/tests/binderThroughputTest.cpp
@@ -380,7 +380,7 @@
// Caller specified the max latency in microseconds.
// No need to run training round in this case.
if (atoi(argv[i+1]) > 0) {
- max_time_bucket = strtoull(argv[i+1], (char **)NULL, 10) * 1000;
+ max_time_bucket = strtoull(argv[i+1], (char **)nullptr, 10) * 1000;
time_per_bucket = max_time_bucket / num_buckets;
i++;
} else {
diff --git a/libs/binder/tests/schd-dbg.cpp b/libs/binder/tests/schd-dbg.cpp
index 13f03b1..6cf7f36 100644
--- a/libs/binder/tests/schd-dbg.cpp
+++ b/libs/binder/tests/schd-dbg.cpp
@@ -295,7 +295,7 @@
no_inherent += reply.readInt32();
no_sync += reply.readInt32();
- return 0;
+ return nullptr;
}
// create a fifo thread to transact and wait it to finished
diff --git a/libs/binderthreadstate/Android.bp b/libs/binderthreadstate/Android.bp
new file mode 100644
index 0000000..7106cbb
--- /dev/null
+++ b/libs/binderthreadstate/Android.bp
@@ -0,0 +1,44 @@
+// Copyright (C) 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.
+
+cc_library {
+ name: "libbinderthreadstate",
+ recovery_available: true,
+ vendor_available: false,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ },
+ srcs: [
+ "IPCThreadStateBase.cpp",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libcutils",
+ "libutils",
+ ],
+
+ export_include_dirs: ["include"],
+
+ sanitize: {
+ misc_undefined: ["integer"],
+ },
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+}
diff --git a/libs/binderthreadstate/IPCThreadStateBase.cpp b/libs/binderthreadstate/IPCThreadStateBase.cpp
new file mode 100644
index 0000000..fede151
--- /dev/null
+++ b/libs/binderthreadstate/IPCThreadStateBase.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#define LOG_TAG "IPCThreadStateBase"
+
+#include <binderthreadstate/IPCThreadStateBase.h>
+#include <android-base/macros.h>
+
+#include <utils/Log.h>
+
+#include <errno.h>
+#include <inttypes.h>
+#include <pthread.h>
+
+namespace android {
+
+static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
+static bool gHaveTLS = false;
+static pthread_key_t gTLS = 0;
+
+IPCThreadStateBase::IPCThreadStateBase() {
+ pthread_setspecific(gTLS, this);
+}
+
+IPCThreadStateBase* IPCThreadStateBase::self()
+{
+ if (gHaveTLS) {
+restart:
+ const pthread_key_t k = gTLS;
+ IPCThreadStateBase* st = (IPCThreadStateBase*)pthread_getspecific(k);
+ if (st) return st;
+ return new IPCThreadStateBase;
+ }
+
+ pthread_mutex_lock(&gTLSMutex);
+ if (!gHaveTLS) {
+ int key_create_value = pthread_key_create(&gTLS, threadDestructor);
+ if (key_create_value != 0) {
+ pthread_mutex_unlock(&gTLSMutex);
+ ALOGW("IPCThreadStateBase::self() unable to create TLS key, expect a crash: %s\n",
+ strerror(key_create_value));
+ return nullptr;
+ }
+ gHaveTLS = true;
+ }
+ pthread_mutex_unlock(&gTLSMutex);
+ goto restart;
+}
+
+void IPCThreadStateBase::pushCurrentState(CallState callState) {
+ mCallStateStack.emplace(callState);
+}
+
+IPCThreadStateBase::CallState IPCThreadStateBase::popCurrentState() {
+ ALOG_ASSERT(mCallStateStack.size > 0);
+ CallState val = mCallStateStack.top();
+ mCallStateStack.pop();
+ return val;
+}
+
+IPCThreadStateBase::CallState IPCThreadStateBase::getCurrentBinderCallState() {
+ if (mCallStateStack.size() > 0) {
+ return mCallStateStack.top();
+ }
+ return CallState::NONE;
+}
+
+void IPCThreadStateBase::threadDestructor(void *st)
+{
+ IPCThreadStateBase* const self = static_cast<IPCThreadStateBase*>(st);
+ if (self) {
+ delete self;
+ }
+}
+
+}; // namespace android
diff --git a/libs/binderthreadstate/include/binderthreadstate/IPCThreadStateBase.h b/libs/binderthreadstate/include/binderthreadstate/IPCThreadStateBase.h
new file mode 100644
index 0000000..6fdcc84
--- /dev/null
+++ b/libs/binderthreadstate/include/binderthreadstate/IPCThreadStateBase.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef BINDER_THREADSTATE_IPC_THREADSTATE_BASE_H
+#define BINDER_THREADSTATE_IPC_THREADSTATE_BASE_H
+
+#include <stack>
+namespace android {
+
+class IPCThreadStateBase {
+public:
+ enum CallState {
+ HWBINDER,
+ BINDER,
+ NONE,
+ };
+ static IPCThreadStateBase* self();
+ void pushCurrentState(CallState callState);
+ CallState popCurrentState();
+ CallState getCurrentBinderCallState();
+
+private:
+ IPCThreadStateBase();
+ static void threadDestructor(void *st);
+
+ std::stack<CallState> mCallStateStack;
+};
+
+}; // namespace android
+
+#endif // BINDER_THREADSTATE_IPC_THREADSTATE_BASE_H
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 961f101..a8ef7a0 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -56,7 +56,7 @@
mDriverPath = path;
}
-void GraphicsEnv::setLayerPaths(android_namespace_t* appNamespace, const std::string layerPaths) {
+void GraphicsEnv::setLayerPaths(NativeLoaderNamespace* appNamespace, const std::string layerPaths) {
if (mLayerPaths.empty()) {
mLayerPaths = layerPaths;
mAppNamespace = appNamespace;
@@ -66,7 +66,7 @@
}
}
-android_namespace_t* GraphicsEnv::getAppNamespace() {
+NativeLoaderNamespace* GraphicsEnv::getAppNamespace() {
return mAppNamespace;
}
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index 213580c..17e8f6b 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -23,6 +23,8 @@
namespace android {
+class NativeLoaderNamespace;
+
class GraphicsEnv {
public:
static GraphicsEnv& getInstance();
@@ -35,8 +37,8 @@
void setDriverPath(const std::string path);
android_namespace_t* getDriverNamespace();
- void setLayerPaths(android_namespace_t* appNamespace, const std::string layerPaths);
- android_namespace_t* getAppNamespace();
+ void setLayerPaths(NativeLoaderNamespace* appNamespace, const std::string layerPaths);
+ NativeLoaderNamespace* getAppNamespace();
const std::string getLayerPaths();
void setDebugLayers(const std::string layers);
@@ -48,7 +50,7 @@
std::string mDebugLayers;
std::string mLayerPaths;
android_namespace_t* mDriverNamespace = nullptr;
- android_namespace_t* mAppNamespace = nullptr;
+ NativeLoaderNamespace* mAppNamespace = nullptr;
};
} // namespace android
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 73f2147..b29c1d5 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -23,6 +23,7 @@
vndk: {
enabled: true,
},
+ double_loadable: true,
clang: true,
cflags: [
@@ -72,9 +73,6 @@
],
product_variables: {
- brillo: {
- cflags: ["-DHAVE_NO_SURFACE_FLINGER"],
- },
eng: {
cppflags: [
"-UDEBUG_ONLY_CODE",
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index c8021e4..c96a2dd 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -381,7 +381,6 @@
{ // Autolock scope
Mutex::Autolock lock(mCore->mMutex);
- mCore->waitWhileAllocatingLocked();
if (format == 0) {
format = mCore->mDefaultBufferFormat;
@@ -1345,7 +1344,9 @@
return;
}
- newBufferCount = mCore->mFreeSlots.size();
+ // Only allocate one buffer at a time to reduce risks of overlapping an allocation from
+ // both allocateBuffers and dequeueBuffer.
+ newBufferCount = mCore->mFreeSlots.empty() ? 0 : 1;
if (newBufferCount == 0) {
return;
}
@@ -1360,7 +1361,7 @@
} // Autolock scope
Vector<sp<GraphicBuffer>> buffers;
- for (size_t i = 0; i < newBufferCount; ++i) {
+ for (size_t i = 0; i < newBufferCount; ++i) {
sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
allocWidth, allocHeight, allocFormat, BQ_LAYER_COUNT,
allocUsage, allocName);
diff --git a/libs/gui/FrameTimestamps.cpp b/libs/gui/FrameTimestamps.cpp
index a379ad6..85ae433 100644
--- a/libs/gui/FrameTimestamps.cpp
+++ b/libs/gui/FrameTimestamps.cpp
@@ -621,7 +621,7 @@
// ============================================================================
FrameEventHistoryDelta& FrameEventHistoryDelta::operator=(
- FrameEventHistoryDelta&& src) {
+ FrameEventHistoryDelta&& src) noexcept {
mCompositorTiming = src.mCompositorTiming;
if (CC_UNLIKELY(!mDeltas.empty())) {
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 0749fde..0b37960 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -355,7 +355,7 @@
data.writeUint32(height);
data.writeInt32(static_cast<int32_t>(format));
data.writeUint64(usage);
- status_t result = remote()->transact(ALLOCATE_BUFFERS, data, &reply);
+ status_t result = remote()->transact(ALLOCATE_BUFFERS, data, &reply, TF_ONE_WAY);
if (result != NO_ERROR) {
ALOGE("allocateBuffers failed to transact: %d", result);
}
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 339bd0f..2de14c8 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -464,8 +464,12 @@
if (interval > maxSwapInterval)
interval = maxSwapInterval;
+ const bool wasSwapIntervalZero = mSwapIntervalZero;
mSwapIntervalZero = (interval == 0);
- mGraphicBufferProducer->setAsyncMode(mSwapIntervalZero);
+
+ if (mSwapIntervalZero != wasSwapIntervalZero) {
+ mGraphicBufferProducer->setAsyncMode(mSwapIntervalZero);
+ }
return NO_ERROR;
}
diff --git a/libs/gui/include/gui/FrameTimestamps.h b/libs/gui/include/gui/FrameTimestamps.h
index 9716be4..e06e40f 100644
--- a/libs/gui/include/gui/FrameTimestamps.h
+++ b/libs/gui/include/gui/FrameTimestamps.h
@@ -311,7 +311,7 @@
// Movable.
FrameEventHistoryDelta(FrameEventHistoryDelta&& src) = default;
- FrameEventHistoryDelta& operator=(FrameEventHistoryDelta&& src);
+ FrameEventHistoryDelta& operator=(FrameEventHistoryDelta&& src) noexcept;
// Not copyable.
FrameEventHistoryDelta(const FrameEventHistoryDelta& src) = delete;
FrameEventHistoryDelta& operator=(
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 2f39976..a2d6a8a 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -16,6 +16,7 @@
cc_library {
name: "libinput",
+ cpp_std: "c++17",
host_supported: true,
cflags: [
"-Wall",
diff --git a/libs/input/VelocityTracker.cpp b/libs/input/VelocityTracker.cpp
index c07a812..f72e49b 100644
--- a/libs/input/VelocityTracker.cpp
+++ b/libs/input/VelocityTracker.cpp
@@ -23,9 +23,11 @@
// Log debug messages about the progress of the algorithm itself.
#define DEBUG_STRATEGY 0
+#include <array>
#include <inttypes.h>
#include <limits.h>
#include <math.h>
+#include <optional>
#include <android-base/stringprintf.h>
#include <cutils/properties.h>
@@ -564,7 +566,9 @@
* Optimized unweighted second-order least squares fit. About 2x speed improvement compared to
* the default implementation
*/
-static float solveUnweightedLeastSquaresDeg2(const float* x, const float* y, size_t count) {
+static std::optional<std::array<float, 3>> solveUnweightedLeastSquaresDeg2(
+ const float* x, const float* y, size_t count) {
+ // Solving y = a*x^2 + b*x + c
float sxi = 0, sxiyi = 0, syi = 0, sxi2 = 0, sxi3 = 0, sxi2yi = 0, sxi4 = 0;
for (size_t i = 0; i < count; i++) {
@@ -573,8 +577,8 @@
float xi2 = xi*xi;
float xi3 = xi2*xi;
float xi4 = xi3*xi;
- float xi2yi = xi2*yi;
float xiyi = xi*yi;
+ float xi2yi = xi2*yi;
sxi += xi;
sxi2 += xi2;
@@ -591,13 +595,23 @@
float Sx2y = sxi2yi - sxi2*syi / count;
float Sx2x2 = sxi4 - sxi2*sxi2 / count;
- float numerator = Sxy*Sx2x2 - Sx2y*Sxx2;
float denominator = Sxx*Sx2x2 - Sxx2*Sxx2;
if (denominator == 0) {
ALOGW("division by 0 when computing velocity, Sxx=%f, Sx2x2=%f, Sxx2=%f", Sxx, Sx2x2, Sxx2);
- return 0;
+ return std::nullopt;
}
- return numerator/denominator;
+ // Compute a
+ float numerator = Sx2y*Sxx - Sxy*Sxx2;
+ float a = numerator / denominator;
+
+ // Compute b
+ numerator = Sxy*Sx2x2 - Sx2y*Sxx2;
+ float b = numerator / denominator;
+
+ // Compute c
+ float c = syi/count - b * sxi/count - a * sxi2/count;
+
+ return std::make_optional(std::array<float, 3>({c, b, a}));
}
bool LeastSquaresVelocityTrackerStrategy::getEstimator(uint32_t id,
@@ -640,20 +654,23 @@
if (degree > m - 1) {
degree = m - 1;
}
- if (degree >= 1) {
- if (degree == 2 && mWeighting == WEIGHTING_NONE) { // optimize unweighted, degree=2 fit
+
+ if (degree == 2 && mWeighting == WEIGHTING_NONE) {
+ // Optimize unweighted, quadratic polynomial fit
+ std::optional<std::array<float, 3>> xCoeff = solveUnweightedLeastSquaresDeg2(time, x, m);
+ std::optional<std::array<float, 3>> yCoeff = solveUnweightedLeastSquaresDeg2(time, y, m);
+ if (xCoeff && yCoeff) {
outEstimator->time = newestMovement.eventTime;
outEstimator->degree = 2;
outEstimator->confidence = 1;
- outEstimator->xCoeff[0] = 0; // only slope is calculated, set rest of coefficients = 0
- outEstimator->yCoeff[0] = 0;
- outEstimator->xCoeff[1] = solveUnweightedLeastSquaresDeg2(time, x, m);
- outEstimator->yCoeff[1] = solveUnweightedLeastSquaresDeg2(time, y, m);
- outEstimator->xCoeff[2] = 0;
- outEstimator->yCoeff[2] = 0;
+ for (size_t i = 0; i <= outEstimator->degree; i++) {
+ outEstimator->xCoeff[i] = (*xCoeff)[i];
+ outEstimator->yCoeff[i] = (*yCoeff)[i];
+ }
return true;
}
-
+ } else if (degree >= 1) {
+ // General case for an Nth degree polynomial fit
float xdet, ydet;
uint32_t n = degree + 1;
if (solveLeastSquares(time, x, w, m, n, outEstimator->xCoeff, &xdet)
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index aca9521..f06119f 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -1,7 +1,6 @@
// Build the unit tests.
cc_test {
name: "libinput_tests",
- test_per_src: true,
srcs: [
"InputChannel_test.cpp",
"InputEvent_test.cpp",
diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp
index 43b6012..9da2e2a 100644
--- a/libs/input/tests/VelocityTracker_test.cpp
+++ b/libs/input/tests/VelocityTracker_test.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "VelocityTracker_test"
+#include <array>
#include <math.h>
#include <android-base/stringprintf.h>
@@ -32,29 +33,35 @@
// here EV = expected value, tol = VELOCITY_TOLERANCE
constexpr float VELOCITY_TOLERANCE = 0.2;
+// estimate coefficients must be within 0.001% of the target value
+constexpr float COEFFICIENT_TOLERANCE = 0.00001;
+
// --- VelocityTrackerTest ---
class VelocityTrackerTest : public testing::Test { };
-static void checkVelocity(float Vactual, float Vtarget) {
- // Compare directions
- if ((Vactual > 0 && Vtarget <= 0) || (Vactual < 0 && Vtarget >= 0)) {
- FAIL() << StringPrintf("Velocity %f does not have the same direction"
- " as the target velocity %f", Vactual, Vtarget);
- }
+/*
+ * Similar to EXPECT_NEAR, but ensures that the difference between the two float values
+ * is at most a certain fraction of the target value.
+ * If fraction is zero, require exact match.
+ */
+static void EXPECT_NEAR_BY_FRACTION(float actual, float target, float fraction) {
+ float tolerance = fabsf(target * fraction);
- // Compare magnitudes
- const float Vlower = fabsf(Vtarget * (1 - VELOCITY_TOLERANCE));
- const float Vupper = fabsf(Vtarget * (1 + VELOCITY_TOLERANCE));
- if (fabsf(Vactual) < Vlower) {
- FAIL() << StringPrintf("Velocity %f is more than %.0f%% below target velocity %f",
- Vactual, VELOCITY_TOLERANCE * 100, Vtarget);
+ if (target == 0 && fraction != 0) {
+ // If target is zero, this would force actual == target, which is too harsh.
+ // Relax this requirement a little. The value is determined empirically from the
+ // coefficients computed by the quadratic least squares algorithms.
+ tolerance = 1E-6;
}
- if (fabsf(Vactual) > Vupper) {
- FAIL() << StringPrintf("Velocity %f is more than %.0f%% above target velocity %f",
- Vactual, VELOCITY_TOLERANCE * 100, Vtarget);
- }
- SUCCEED() << StringPrintf("Velocity %f within %.0f%% of target %f)",
- Vactual, VELOCITY_TOLERANCE * 100, Vtarget);
+ EXPECT_NEAR(actual, target, tolerance);
+}
+
+static void checkVelocity(float Vactual, float Vtarget) {
+ EXPECT_NEAR_BY_FRACTION(Vactual, Vtarget, VELOCITY_TOLERANCE);
+}
+
+static void checkCoefficient(float actual, float target) {
+ EXPECT_NEAR_BY_FRACTION(actual, target, COEFFICIENT_TOLERANCE);
}
void failWithMessage(std::string message) {
@@ -123,6 +130,19 @@
delete event;
}
+static void computeAndCheckQuadraticEstimate(const Position* positions, size_t numSamples,
+ const std::array<float, 3>& coefficients) {
+ VelocityTracker vt("lsq2");
+ MotionEvent* event = createSimpleMotionEvent(positions, numSamples);
+ vt.addMovement(event);
+ VelocityTracker::Estimator estimator;
+ EXPECT_TRUE(vt.getEstimator(0, &estimator));
+ for (size_t i = 0; i< coefficients.size(); i++) {
+ checkCoefficient(estimator.xCoeff[i], coefficients[i]);
+ checkCoefficient(estimator.yCoeff[i], coefficients[i]);
+ }
+}
+
/*
* ================== VelocityTracker tests generated manually =====================================
*/
@@ -660,5 +680,114 @@
computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 28354.796875); // lsq2
}
+/*
+ * Special care must be taken when constructing tests for LeastSquaresVelocityTrackerStrategy
+ * getEstimator function. In particular:
+ * - inside the function, time gets converted from nanoseconds to seconds
+ * before being used in the fit.
+ * - any values that are older than 100 ms are being discarded.
+ * - the newest time gets subtracted from all of the other times before being used in the fit.
+ * So these tests have to be designed with those limitations in mind.
+ *
+ * General approach for the tests below:
+ * We only used timestamps in milliseconds, 0 ms, 1 ms, and 2 ms, to be sure that
+ * we are well within the HORIZON range.
+ * When specifying the expected values of the coefficients, we treat the x values as if
+ * they were in ms. Then, to adjust for the time units, the coefficients get progressively
+ * multiplied by powers of 1E3.
+ * For example:
+ * data: t(ms), x
+ * 1 ms, 1
+ * 2 ms, 4
+ * 3 ms, 9
+ * The coefficients are (0, 0, 1).
+ * In the test, we would convert these coefficients to (0*(1E3)^0, 0*(1E3)^1, 1*(1E3)^2).
+ */
+TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Constant) {
+ Position values[] = {
+ { 0000000, 1, 1 }, // 0 s
+ { 1000000, 1, 1 }, // 0.001 s
+ { 2000000, 1, 1 }, // 0.002 s
+ };
+ // The data used for the fit will be as follows:
+ // time(s), position
+ // -0.002, 1
+ // -0.001, 1
+ // -0.000, 1
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckQuadraticEstimate(values, count, std::array<float, 3>({1, 0, 0}));
+}
+
+/*
+ * Straight line y = x :: the constant and quadratic coefficients are zero.
+ */
+TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Linear) {
+ Position values[] = {
+ { 0000000, -2, -2 },
+ { 1000000, -1, -1 },
+ { 2000000, -0, -0 },
+ };
+ // The data used for the fit will be as follows:
+ // time(s), position
+ // -0.002, -2
+ // -0.001, -1
+ // -0.000, 0
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckQuadraticEstimate(values, count, std::array<float, 3>({0, 1E3, 0}));
+}
+
+/*
+ * Parabola
+ */
+TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Parabolic) {
+ Position values[] = {
+ { 0000000, 1, 1 },
+ { 1000000, 4, 4 },
+ { 2000000, 8, 8 },
+ };
+ // The data used for the fit will be as follows:
+ // time(s), position
+ // -0.002, 1
+ // -0.001, 4
+ // -0.000, 8
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckQuadraticEstimate(values, count, std::array<float, 3>({8, 4.5E3, 0.5E6}));
+}
+
+/*
+ * Parabola
+ */
+TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Parabolic2) {
+ Position values[] = {
+ { 0000000, 1, 1 },
+ { 1000000, 4, 4 },
+ { 2000000, 9, 9 },
+ };
+ // The data used for the fit will be as follows:
+ // time(s), position
+ // -0.002, 1
+ // -0.001, 4
+ // -0.000, 9
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckQuadraticEstimate(values, count, std::array<float, 3>({9, 6E3, 1E6}));
+}
+
+/*
+ * Parabola :: y = x^2 :: the constant and linear coefficients are zero.
+ */
+TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Parabolic3) {
+ Position values[] = {
+ { 0000000, 4, 4 },
+ { 1000000, 1, 1 },
+ { 2000000, 0, 0 },
+ };
+ // The data used for the fit will be as follows:
+ // time(s), position
+ // -0.002, 4
+ // -0.001, 1
+ // -0.000, 0
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckQuadraticEstimate(values, count, std::array<float, 3>({0, 0E3, 1E6}));
+}
} // namespace android
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index 49ffc8f..7e26b0b 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -286,6 +286,35 @@
return gbuffer->handle;
}
+int AHardwareBuffer_createFromHandle(const AHardwareBuffer_Desc* desc,
+ const native_handle_t* handle, int32_t method,
+ AHardwareBuffer** outBuffer) {
+ static_assert(static_cast<int32_t>(AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_REGISTER) ==
+ static_cast<int32_t>(GraphicBuffer::TAKE_UNREGISTERED_HANDLE));
+ static_assert(static_cast<int32_t>(AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE) ==
+ static_cast<int32_t>(GraphicBuffer::CLONE_HANDLE));
+
+ if (!desc || !handle || !outBuffer) return BAD_VALUE;
+ if (!(method == AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_REGISTER ||
+ method == AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE))
+ return BAD_VALUE;
+ if (desc->rfu0 != 0 || desc->rfu1 != 0) return BAD_VALUE;
+ if (desc->format == AHARDWAREBUFFER_FORMAT_BLOB && desc->height != 1) return BAD_VALUE;
+
+ const int format = AHardwareBuffer_convertToPixelFormat(desc->format);
+ const uint64_t usage = AHardwareBuffer_convertToGrallocUsageBits(desc->usage);
+ const auto wrapMethod = static_cast<GraphicBuffer::HandleWrapMethod>(method);
+ sp<GraphicBuffer> gbuffer(new GraphicBuffer(handle, wrapMethod, desc->width, desc->height,
+ format, desc->layers, usage, desc->stride));
+ status_t err = gbuffer->initCheck();
+ if (err != 0 || gbuffer->handle == 0) return err;
+
+ *outBuffer = AHardwareBuffer_from_GraphicBuffer(gbuffer.get());
+ // Ensure the buffer doesn't get destroyed when the sp<> goes away.
+ AHardwareBuffer_acquire(*outBuffer);
+
+ return NO_ERROR;
+}
// ----------------------------------------------------------------------------
// Helpers implementation
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index 765dcd9..8435dac 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -126,12 +126,12 @@
}
int32_t ANativeWindow_setBuffersDataSpace(ANativeWindow* window, int32_t dataSpace) {
- static_assert(ADATASPACE_UNKNOWN == HAL_DATASPACE_UNKNOWN);
- static_assert(ADATASPACE_SCRGB_LINEAR == HAL_DATASPACE_V0_SCRGB_LINEAR);
- static_assert(ADATASPACE_SRGB == HAL_DATASPACE_V0_SRGB);
- static_assert(ADATASPACE_SCRGB == HAL_DATASPACE_V0_SCRGB);
- static_assert(ADATASPACE_DISPLAY_P3 == HAL_DATASPACE_DISPLAY_P3);
- static_assert(ADATASPACE_BT2020_PQ == HAL_DATASPACE_BT2020_PQ);
+ static_assert(static_cast<int>(ADATASPACE_UNKNOWN) == static_cast<int>(HAL_DATASPACE_UNKNOWN));
+ static_assert(static_cast<int>(ADATASPACE_SCRGB_LINEAR) == static_cast<int>(HAL_DATASPACE_V0_SCRGB_LINEAR));
+ static_assert(static_cast<int>(ADATASPACE_SRGB) == static_cast<int>(HAL_DATASPACE_V0_SRGB));
+ static_assert(static_cast<int>(ADATASPACE_SCRGB) == static_cast<int>(HAL_DATASPACE_V0_SCRGB));
+ static_assert(static_cast<int>(ADATASPACE_DISPLAY_P3) == static_cast<int>(HAL_DATASPACE_DISPLAY_P3));
+ static_assert(static_cast<int>(ADATASPACE_BT2020_PQ) == static_cast<int>(HAL_DATASPACE_BT2020_PQ));
if (!window || !query(window, NATIVE_WINDOW_IS_VALID) ||
!isDataSpaceValid(window, dataSpace)) {
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index 78cec41..9ca4941 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -15,6 +15,11 @@
*/
/**
+ * @addtogroup NativeActivity Native Activity
+ * @{
+ */
+
+/**
* @file hardware_buffer.h
*/
@@ -210,6 +215,8 @@
typedef struct AHardwareBuffer AHardwareBuffer;
+#if __ANDROID_API__ >= 26
+
/**
* Allocates a buffer that backs an AHardwareBuffer using the passed
* AHardwareBuffer_Desc.
@@ -218,25 +225,25 @@
* any reason. The returned buffer has a reference count of 1.
*/
int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc,
- AHardwareBuffer** outBuffer);
+ AHardwareBuffer** outBuffer) __INTRODUCED_IN(26);
/**
* Acquire a reference on the given AHardwareBuffer object. This prevents the
* object from being deleted until the last reference is removed.
*/
-void AHardwareBuffer_acquire(AHardwareBuffer* buffer);
+void AHardwareBuffer_acquire(AHardwareBuffer* buffer) __INTRODUCED_IN(26);
/**
* Remove a reference that was previously acquired with
* AHardwareBuffer_acquire().
*/
-void AHardwareBuffer_release(AHardwareBuffer* buffer);
+void AHardwareBuffer_release(AHardwareBuffer* buffer) __INTRODUCED_IN(26);
/**
* Return a description of the AHardwareBuffer in the passed
* AHardwareBuffer_Desc struct.
*/
void AHardwareBuffer_describe(const AHardwareBuffer* buffer,
- AHardwareBuffer_Desc* outDesc);
+ AHardwareBuffer_Desc* outDesc) __INTRODUCED_IN(26);
/**
* Lock the AHardwareBuffer for reading or writing, depending on the usage flags
@@ -272,7 +279,7 @@
* number of the lock fails for any reason.
*/
int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage,
- int32_t fence, const ARect* rect, void** outVirtualAddress);
+ int32_t fence, const ARect* rect, void** outVirtualAddress) __INTRODUCED_IN(26);
/**
* Unlock the AHardwareBuffer; must be called after all changes to the buffer
@@ -284,7 +291,7 @@
* \return 0 on success, -EINVAL if \a buffer is NULL, or an error
* number if the unlock fails for any reason.
*/
-int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence);
+int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) __INTRODUCED_IN(26);
/**
* Send the AHardwareBuffer to an AF_UNIX socket.
@@ -292,7 +299,7 @@
* \return 0 on success, -EINVAL if \a buffer is NULL, or an error
* number if the operation fails for any reason.
*/
-int AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* buffer, int socketFd);
+int AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* buffer, int socketFd) __INTRODUCED_IN(26);
/**
* Receive the AHardwareBuffer from an AF_UNIX socket.
@@ -300,8 +307,12 @@
* \return 0 on success, -EINVAL if \a outBuffer is NULL, or an error
* number if the operation fails for any reason.
*/
-int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** outBuffer);
+int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** outBuffer) __INTRODUCED_IN(26);
+
+#endif // __ANDROID_API__ >= 26
__END_DECLS
#endif // ANDROID_HARDWARE_BUFFER_H
+
+/** @} */
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index d5e5e9d..6831f91 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -178,7 +178,7 @@
*/
int32_t ANativeWindow_unlockAndPost(ANativeWindow* window);
-#if __ANDROID_API__ >= __ANDROID_API_O__
+#if __ANDROID_API__ >= 26
/**
* Set a transform that will be applied to future buffers posted to the window.
@@ -186,11 +186,11 @@
* \param transform combination of {@link ANativeWindowTransform} flags
* \return 0 for success, or -EINVAL if \p transform is invalid
*/
-int32_t ANativeWindow_setBuffersTransform(ANativeWindow* window, int32_t transform);
+int32_t ANativeWindow_setBuffersTransform(ANativeWindow* window, int32_t transform) __INTRODUCED_IN(26);
-#endif // __ANDROID_API__ >= __ANDROID_API_O__
+#endif // __ANDROID_API__ >= 26
-#if __ANDROID_API__ >= __ANDROID_API_P__
+#if __ANDROID_API__ >= 28
/**
* All buffers queued after this call will be associated with the dataSpace
@@ -206,16 +206,16 @@
* \return 0 for success, -EINVAL if window is invalid or the dataspace is not
* supported.
*/
-int32_t ANativeWindow_setBuffersDataSpace(ANativeWindow* window, int32_t dataSpace);
+int32_t ANativeWindow_setBuffersDataSpace(ANativeWindow* window, int32_t dataSpace) __INTRODUCED_IN(28);
/**
* Get the dataspace of the buffers in window.
* \return the dataspace of buffers in window, ADATASPACE_UNKNOWN is returned if
* dataspace is unknown, or -EINVAL if window is invalid.
*/
-int32_t ANativeWindow_getBuffersDataSpace(ANativeWindow* window);
+int32_t ANativeWindow_getBuffersDataSpace(ANativeWindow* window) __INTRODUCED_IN(28);
-#endif // __ANDROID_API__ >= __ANDROID_API_P__
+#endif // __ANDROID_API__ >= 28
#ifdef __cplusplus
};
diff --git a/libs/nativewindow/include/vndk/hardware_buffer.h b/libs/nativewindow/include/vndk/hardware_buffer.h
index 7a4b31f..6c9ec34 100644
--- a/libs/nativewindow/include/vndk/hardware_buffer.h
+++ b/libs/nativewindow/include/vndk/hardware_buffer.h
@@ -26,6 +26,28 @@
const native_handle_t* AHardwareBuffer_getNativeHandle(const AHardwareBuffer* buffer);
+enum CreateFromHandleMethod {
+ // enum values chosen to match internal GraphicBuffer::HandleWrapMethod
+ AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_REGISTER = 2,
+ AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE = 3,
+};
+
+/**
+ * Create a AHardwareBuffer from a native handle.
+ *
+ * This function wraps a native handle in a AHardwareBuffer suitable for use by applications or
+ * other parts of the system. The contents of desc will be returned by AHardwareBuffer_describe().
+ *
+ * If method is AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_REGISTER, the handle is assumed to be
+ * unregistered, and it will be registered/imported before being wrapped in the AHardwareBuffer.
+ * If successful, the AHardwareBuffer will own the handle.
+ *
+ * If method is AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE, the handle will be cloned and the
+ * clone registered. The AHardwareBuffer will own the cloned handle but not the original.
+ */
+int AHardwareBuffer_createFromHandle(const AHardwareBuffer_Desc* desc,
+ const native_handle_t* handle, int32_t method,
+ AHardwareBuffer** outBuffer);
/**
* Buffer pixel formats.
diff --git a/libs/nativewindow/libnativewindow.map.txt b/libs/nativewindow/libnativewindow.map.txt
index d2ba971..753954d 100644
--- a/libs/nativewindow/libnativewindow.map.txt
+++ b/libs/nativewindow/libnativewindow.map.txt
@@ -2,6 +2,7 @@
global:
AHardwareBuffer_acquire;
AHardwareBuffer_allocate;
+ AHardwareBuffer_createFromHandle; # vndk
AHardwareBuffer_describe;
AHardwareBuffer_getNativeHandle; # vndk
AHardwareBuffer_lock;
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index ff9d19e..d25ad1a 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -18,6 +18,7 @@
vndk: {
enabled: true,
},
+ double_loadable: true,
clang: true,
cflags: [
diff --git a/libs/ui/Fence.cpp b/libs/ui/Fence.cpp
index ff53aa8..ed7ccb0b 100644
--- a/libs/ui/Fence.cpp
+++ b/libs/ui/Fence.cpp
@@ -109,25 +109,25 @@
return SIGNAL_TIME_INVALID;
}
- struct sync_fence_info_data* finfo = sync_fence_info(mFenceFd);
+ struct sync_file_info* finfo = sync_file_info(mFenceFd);
if (finfo == NULL) {
- ALOGE("sync_fence_info returned NULL for fd %d", mFenceFd.get());
+ ALOGE("sync_file_info returned NULL for fd %d", mFenceFd.get());
return SIGNAL_TIME_INVALID;
}
if (finfo->status != 1) {
- sync_fence_info_free(finfo);
+ sync_file_info_free(finfo);
return SIGNAL_TIME_PENDING;
}
- struct sync_pt_info* pinfo = NULL;
uint64_t timestamp = 0;
- while ((pinfo = sync_pt_info(finfo, pinfo)) != NULL) {
- if (pinfo->timestamp_ns > timestamp) {
- timestamp = pinfo->timestamp_ns;
+ struct sync_fence_info* pinfo = sync_get_fence_info(finfo);
+ for (size_t i = 0; i < finfo->num_fences; i++) {
+ if (pinfo[i].timestamp_ns > timestamp) {
+ timestamp = pinfo[i].timestamp_ns;
}
}
- sync_fence_info_free(finfo);
+ sync_file_info_free(finfo);
return nsecs_t(timestamp);
}
diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp
index b92cbf3..37cf617 100644
--- a/libs/ui/Gralloc2.cpp
+++ b/libs/ui/Gralloc2.cpp
@@ -39,7 +39,7 @@
static const uint64_t valid10UsageBits = []() -> uint64_t {
using hardware::graphics::common::V1_0::BufferUsage;
uint64_t bits = 0;
- for (const auto bit : hardware::hidl_enum_iterator<BufferUsage>()) {
+ for (const auto bit : hardware::hidl_enum_range<BufferUsage>()) {
bits = bits | bit;
}
// TODO(b/72323293, b/72703005): Remove these additional bits
@@ -54,7 +54,7 @@
static const uint64_t valid11UsageBits = []() -> uint64_t {
using hardware::graphics::common::V1_1::BufferUsage;
uint64_t bits = 0;
- for (const auto bit : hardware::hidl_enum_iterator<BufferUsage>()) {
+ for (const auto bit : hardware::hidl_enum_range<BufferUsage>()) {
bits = bits | bit;
}
return bits;
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 254038b..0382479 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -123,7 +123,6 @@
ANativeWindowBuffer* GraphicBuffer::getNativeBuffer() const
{
- LOG_ALWAYS_FATAL_IF(this == NULL, "getNativeBuffer() called on NULL GraphicBuffer");
return static_cast<ANativeWindowBuffer*>(
const_cast<GraphicBuffer*>(this));
}
diff --git a/libs/ui/HdrCapabilities.cpp b/libs/ui/HdrCapabilities.cpp
index a36911d..a5b3e89 100644
--- a/libs/ui/HdrCapabilities.cpp
+++ b/libs/ui/HdrCapabilities.cpp
@@ -24,8 +24,8 @@
#endif
HdrCapabilities::~HdrCapabilities() = default;
-HdrCapabilities::HdrCapabilities(HdrCapabilities&& other) = default;
-HdrCapabilities& HdrCapabilities::operator=(HdrCapabilities&& other) = default;
+HdrCapabilities::HdrCapabilities(HdrCapabilities&& other) noexcept = default;
+HdrCapabilities& HdrCapabilities::operator=(HdrCapabilities&& other) noexcept = default;
size_t HdrCapabilities::getFlattenedSize() const {
return sizeof(mMaxLuminance) +
diff --git a/libs/ui/include/ui/HdrCapabilities.h b/libs/ui/include/ui/HdrCapabilities.h
index 4e98c28..65ac26c 100644
--- a/libs/ui/include/ui/HdrCapabilities.h
+++ b/libs/ui/include/ui/HdrCapabilities.h
@@ -37,8 +37,8 @@
mMinLuminance(minLuminance) {}
// Make this move-constructable and move-assignable
- HdrCapabilities(HdrCapabilities&& other);
- HdrCapabilities& operator=(HdrCapabilities&& other);
+ HdrCapabilities(HdrCapabilities&& other) noexcept;
+ HdrCapabilities& operator=(HdrCapabilities&& other) noexcept;
HdrCapabilities()
: mSupportedHdrTypes(),
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index 7b5ad44..69b6422 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -59,7 +59,6 @@
}
cc_test {
- tags: ["optional"],
srcs: ["buffer_hub-test.cpp"],
static_libs: ["libbufferhub"],
shared_libs: sharedLibraries,
diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
index f4918c4..04f4fb4 100644
--- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
+++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
@@ -103,8 +103,8 @@
opaque_ints_.push_back(buffer.handle()->data[fd_count + i]);
}
}
- NativeBufferHandle(NativeBufferHandle&& other) = default;
- NativeBufferHandle& operator=(NativeBufferHandle&& other) = default;
+ NativeBufferHandle(NativeBufferHandle&& other) noexcept = default;
+ NativeBufferHandle& operator=(NativeBufferHandle&& other) noexcept = default;
// Imports the native handle into the given IonBuffer instance.
int Import(IonBuffer* buffer) {
@@ -174,8 +174,8 @@
acquire_fence_fd_(acquire_fence_fd.Borrow()),
release_fence_fd_(release_fence_fd.Borrow()) {}
- BufferDescription(BufferDescription&& other) = default;
- BufferDescription& operator=(BufferDescription&& other) = default;
+ BufferDescription(BufferDescription&& other) noexcept = default;
+ BufferDescription& operator=(BufferDescription&& other) noexcept = default;
// ID of the buffer client. All BufferHubBuffer clients derived from the same
// buffer in bufferhubd share the same buffer id.
@@ -219,8 +219,8 @@
FenceHandle() = default;
explicit FenceHandle(int fence) : fence_{fence} {}
explicit FenceHandle(FileHandleType&& fence) : fence_{std::move(fence)} {}
- FenceHandle(FenceHandle&&) = default;
- FenceHandle& operator=(FenceHandle&&) = default;
+ FenceHandle(FenceHandle&&) noexcept = default;
+ FenceHandle& operator=(FenceHandle&&) noexcept = default;
explicit operator bool() const { return fence_.IsValid(); }
diff --git a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
index f6bc547..860f08a 100644
--- a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
@@ -20,8 +20,8 @@
uint64_t usage);
~IonBuffer();
- IonBuffer(IonBuffer&& other);
- IonBuffer& operator=(IonBuffer&& other);
+ IonBuffer(IonBuffer&& other) noexcept;
+ IonBuffer& operator=(IonBuffer&& other) noexcept;
// Returns check this IonBuffer holds a valid Gralloc buffer.
bool IsValid() const { return buffer_ && buffer_->initCheck() == NO_ERROR; }
diff --git a/libs/vr/libbufferhub/ion_buffer.cpp b/libs/vr/libbufferhub/ion_buffer.cpp
index cbaa24a..1295531 100644
--- a/libs/vr/libbufferhub/ion_buffer.cpp
+++ b/libs/vr/libbufferhub/ion_buffer.cpp
@@ -49,11 +49,11 @@
FreeHandle();
}
-IonBuffer::IonBuffer(IonBuffer&& other) : IonBuffer() {
+IonBuffer::IonBuffer(IonBuffer&& other) noexcept : IonBuffer() {
*this = std::move(other);
}
-IonBuffer& IonBuffer::operator=(IonBuffer&& other) {
+IonBuffer& IonBuffer::operator=(IonBuffer&& other) noexcept {
ALOGD_IF(TRACE, "IonBuffer::operator=: handle_=%p other.handle_=%p", handle(),
other.handle());
diff --git a/libs/vr/libbufferhubqueue/benchmarks/Android.bp b/libs/vr/libbufferhubqueue/benchmarks/Android.bp
index 8ae7a0b..5089b87 100644
--- a/libs/vr/libbufferhubqueue/benchmarks/Android.bp
+++ b/libs/vr/libbufferhubqueue/benchmarks/Android.bp
@@ -23,5 +23,4 @@
"-Werror",
],
name: "buffer_transport_benchmark",
- tags: ["optional"],
}
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h
index 4dea9b2..ad3f56b 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h
@@ -28,8 +28,8 @@
public:
BufferHubQueueParcelable() = default;
- BufferHubQueueParcelable(BufferHubQueueParcelable&& other) = default;
- BufferHubQueueParcelable& operator=(BufferHubQueueParcelable&& other) {
+ BufferHubQueueParcelable(BufferHubQueueParcelable&& other) noexcept = default;
+ BufferHubQueueParcelable& operator=(BufferHubQueueParcelable&& other) noexcept {
channel_parcelable_ = std::move(other.channel_parcelable_);
return *this;
}
diff --git a/libs/vr/libbufferhubqueue/tests/Android.bp b/libs/vr/libbufferhubqueue/tests/Android.bp
index ca1e7bd..a337921 100644
--- a/libs/vr/libbufferhubqueue/tests/Android.bp
+++ b/libs/vr/libbufferhubqueue/tests/Android.bp
@@ -38,7 +38,6 @@
"-Wno-error=sign-compare", // to fix later
],
name: "buffer_hub_queue-test",
- tags: ["optional"],
}
cc_test {
@@ -55,5 +54,4 @@
"-Werror",
],
name: "buffer_hub_queue_producer-test",
- tags: ["optional"],
}
diff --git a/libs/vr/libdisplay/Android.bp b/libs/vr/libdisplay/Android.bp
index 192fb5d..9c67881 100644
--- a/libs/vr/libdisplay/Android.bp
+++ b/libs/vr/libdisplay/Android.bp
@@ -50,7 +50,6 @@
]
cc_library {
- tags: ["tests"],
srcs: sourceFiles,
cflags: ["-DLOG_TAG=\"libdisplay\"",
"-DTRACE=0",
diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp
index 74cee3f..571558a 100644
--- a/libs/vr/libdvr/dvr_buffer_queue.cpp
+++ b/libs/vr/libdvr/dvr_buffer_queue.cpp
@@ -171,12 +171,12 @@
int DvrWriteBufferQueue::PostBuffer(DvrWriteBuffer* write_buffer,
const DvrNativeBufferMetadata* meta,
int ready_fence_fd) {
+ // Some basic sanity checks before we put the buffer back into a slot.
+ size_t slot = static_cast<size_t>(write_buffer->slot);
LOG_FATAL_IF(
(write_buffers->slot < 0 || write_buffers->slot >= write_buffers_.size()),
"DvrWriteBufferQueue::ReleaseBuffer: Invalid slot: %zu", slot);
- // Some basic sanity checks before we put the buffer back into a slot.
- size_t slot = static_cast<size_t>(write_buffer->slot);
if (write_buffers_[slot] != nullptr) {
ALOGE("DvrWriteBufferQueue::PostBuffer: Slot is not empty: %zu", slot);
return -EINVAL;
@@ -374,12 +374,12 @@
int DvrReadBufferQueue::ReleaseBuffer(DvrReadBuffer* read_buffer,
const DvrNativeBufferMetadata* meta,
int release_fence_fd) {
+ // Some basic sanity checks before we put the buffer back into a slot.
+ size_t slot = static_cast<size_t>(read_buffer->slot);
LOG_FATAL_IF(
(read_buffers->slot < 0 || read_buffers->slot >= read_buffers_size()),
"DvrReadBufferQueue::ReleaseBuffer: Invalid slot: %zu", slot);
- // Some basic sanity checks before we put the buffer back into a slot.
- size_t slot = static_cast<size_t>(read_buffer->slot);
if (read_buffers_[slot] != nullptr) {
ALOGE("DvrReadBufferQueue::ReleaseBuffer: Slot is not empty: %zu", slot);
return -EINVAL;
diff --git a/libs/vr/libdvrcommon/Android.bp b/libs/vr/libdvrcommon/Android.bp
index 32b793a..e751768 100644
--- a/libs/vr/libdvrcommon/Android.bp
+++ b/libs/vr/libdvrcommon/Android.bp
@@ -59,7 +59,6 @@
cc_test {
name: "libdvrcommon_test",
- tags: ["optional"],
srcs: testFiles,
cflags: [
diff --git a/libs/vr/libdvrcommon/include/private/dvr/ring_buffer.h b/libs/vr/libdvrcommon/include/private/dvr/ring_buffer.h
index 44485a7..1824241 100644
--- a/libs/vr/libdvrcommon/include/private/dvr/ring_buffer.h
+++ b/libs/vr/libdvrcommon/include/private/dvr/ring_buffer.h
@@ -23,9 +23,9 @@
explicit RingBuffer(size_t capacity) { Reset(capacity); }
RingBuffer(const RingBuffer& other) = default;
- RingBuffer(RingBuffer&& other) = default;
+ RingBuffer(RingBuffer&& other) noexcept = default;
RingBuffer& operator=(const RingBuffer& other) = default;
- RingBuffer& operator=(RingBuffer&& other) = default;
+ RingBuffer& operator=(RingBuffer&& other) noexcept = default;
void Append(const T& val) {
if (IsFull())
diff --git a/libs/vr/libpdx/private/pdx/channel_handle.h b/libs/vr/libpdx/private/pdx/channel_handle.h
index 1e62d25..daa08f4 100644
--- a/libs/vr/libpdx/private/pdx/channel_handle.h
+++ b/libs/vr/libpdx/private/pdx/channel_handle.h
@@ -50,14 +50,14 @@
public:
ChannelHandle() = default;
using ChannelHandleBase::ChannelHandleBase;
- ChannelHandle(ChannelHandle&& other) : ChannelHandleBase{other.value_} {
+ ChannelHandle(ChannelHandle&& other) noexcept : ChannelHandleBase{other.value_} {
other.value_ = kEmptyHandle;
}
~ChannelHandle() = default;
ChannelHandle Duplicate() const { return ChannelHandle{value_}; }
- ChannelHandle& operator=(ChannelHandle&& other) {
+ ChannelHandle& operator=(ChannelHandle&& other) noexcept {
value_ = other.value_;
other.value_ = kEmptyHandle;
return *this;
@@ -74,13 +74,13 @@
ChannelHandle(const ChannelHandle&) = delete;
ChannelHandle& operator=(const ChannelHandle&) = delete;
- ChannelHandle(ChannelHandle&& other)
+ ChannelHandle(ChannelHandle&& other) noexcept
: ChannelHandleBase{other.value_}, manager_{other.manager_} {
other.manager_ = nullptr;
other.value_ = kEmptyHandle;
}
- ChannelHandle& operator=(ChannelHandle&& other) {
+ ChannelHandle& operator=(ChannelHandle&& other) noexcept {
value_ = other.value_;
manager_ = other.manager_;
other.value_ = kEmptyHandle;
diff --git a/libs/vr/libpdx/private/pdx/file_handle.h b/libs/vr/libpdx/private/pdx/file_handle.h
index b3c3ad7..fed1529 100644
--- a/libs/vr/libpdx/private/pdx/file_handle.h
+++ b/libs/vr/libpdx/private/pdx/file_handle.h
@@ -43,7 +43,7 @@
// Move constructor that assumes ownership of the file descriptor, leaving the
// other FileHandle object empty.
- FileHandle(FileHandle&& other) {
+ FileHandle(FileHandle&& other) noexcept {
fd_ = other.fd_;
other.fd_ = kEmptyFileHandle;
}
@@ -62,7 +62,7 @@
// Move assignment operator that assumes ownership of the underlying file
// descriptor, leaving the other FileHandle object empty.
- FileHandle& operator=(FileHandle&& other) {
+ FileHandle& operator=(FileHandle&& other) noexcept {
if (this != &other) {
Reset(other.fd_);
other.fd_ = kEmptyFileHandle;
diff --git a/libs/vr/libpdx/private/pdx/rpc/array_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/array_wrapper.h
index 93d87f3..d835c57 100644
--- a/libs/vr/libpdx/private/pdx/rpc/array_wrapper.h
+++ b/libs/vr/libpdx/private/pdx/rpc/array_wrapper.h
@@ -39,7 +39,7 @@
ArrayWrapper(const ArrayWrapper& other) { *this = other; }
- ArrayWrapper(ArrayWrapper&& other) { *this = std::move(other); }
+ ArrayWrapper(ArrayWrapper&& other) noexcept { *this = std::move(other); }
ArrayWrapper& operator=(const ArrayWrapper& other) {
if (&other == this) {
@@ -53,7 +53,7 @@
return *this;
}
- ArrayWrapper& operator=(ArrayWrapper&& other) {
+ ArrayWrapper& operator=(ArrayWrapper&& other) noexcept {
if (&other == this) {
return *this;
} else {
diff --git a/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h
index aa86531..0421220 100644
--- a/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h
+++ b/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h
@@ -39,7 +39,7 @@
BufferWrapper(const BufferWrapper& other) { *this = other; }
- BufferWrapper(BufferWrapper&& other) { *this = std::move(other); }
+ BufferWrapper(BufferWrapper&& other) noexcept { *this = std::move(other); }
BufferWrapper& operator=(const BufferWrapper& other) {
if (&other == this) {
@@ -53,7 +53,7 @@
return *this;
}
- BufferWrapper& operator=(BufferWrapper&& other) {
+ BufferWrapper& operator=(BufferWrapper&& other) noexcept {
if (&other == this) {
return *this;
} else {
@@ -117,9 +117,9 @@
BufferWrapper(BufferType&& buffer, const Allocator& allocator)
: buffer_(std::move(buffer), allocator) {}
BufferWrapper(const BufferWrapper&) = default;
- BufferWrapper(BufferWrapper&&) = default;
+ BufferWrapper(BufferWrapper&&) noexcept = default;
BufferWrapper& operator=(const BufferWrapper&) = default;
- BufferWrapper& operator=(BufferWrapper&&) = default;
+ BufferWrapper& operator=(BufferWrapper&&) noexcept = default;
pointer data() { return buffer_.data(); }
const_pointer data() const { return buffer_.data(); }
diff --git a/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h
index d496719..1cb85de 100644
--- a/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h
+++ b/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h
@@ -15,9 +15,9 @@
PointerWrapper(T* pointer) : pointer_(pointer) {}
PointerWrapper(const PointerWrapper&) = default;
- PointerWrapper(PointerWrapper&&) = default;
+ PointerWrapper(PointerWrapper&&) noexcept = default;
PointerWrapper& operator=(const PointerWrapper&) = default;
- PointerWrapper& operator=(PointerWrapper&&) = default;
+ PointerWrapper& operator=(PointerWrapper&&) noexcept = default;
T& Dereference() { return *pointer_; }
const T& Dereference() const { return *pointer_; }
diff --git a/libs/vr/libpdx/private/pdx/rpc/string_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/string_wrapper.h
index 19fc4c1..2d0a4ea 100644
--- a/libs/vr/libpdx/private/pdx/rpc/string_wrapper.h
+++ b/libs/vr/libpdx/private/pdx/rpc/string_wrapper.h
@@ -44,7 +44,7 @@
StringWrapper(const StringWrapper& other) { *this = other; }
- StringWrapper(StringWrapper&& other) { *this = std::move(other); }
+ StringWrapper(StringWrapper&& other) noexcept { *this = std::move(other); }
StringWrapper& operator=(const StringWrapper& other) {
if (&other == this) {
@@ -58,7 +58,7 @@
return *this;
}
- StringWrapper& operator=(StringWrapper&& other) {
+ StringWrapper& operator=(StringWrapper&& other) noexcept {
if (&other == this) {
return *this;
} else {
diff --git a/libs/vr/libpdx/private/pdx/rpc/variant.h b/libs/vr/libpdx/private/pdx/rpc/variant.h
index 2cc9664..a1292b0 100644
--- a/libs/vr/libpdx/private/pdx/rpc/variant.h
+++ b/libs/vr/libpdx/private/pdx/rpc/variant.h
@@ -292,7 +292,7 @@
template <typename T>
T& get(TypeTag<T>) {
- return rest_.template get(TypeTag<T>{});
+ return rest_.get(TypeTag<T>{});
}
template <typename T>
const T& get(TypeTag<T>) const {
@@ -300,7 +300,7 @@
}
template <typename T>
constexpr std::int32_t index(TypeTag<T>) const {
- return 1 + rest_.template index(TypeTag<T>{});
+ return 1 + rest_.index(TypeTag<T>{});
}
template <typename... Args>
@@ -447,7 +447,7 @@
Variant(const Variant& other)
: index_{other.index_}, value_{other.value_, other.index_} {}
- Variant(Variant&& other)
+ Variant(Variant&& other) noexcept
: index_{other.index_}, value_{std::move(other.value_), other.index_} {}
// Recent Clang versions has a regression that produces bogus
@@ -472,7 +472,7 @@
other.Visit([this](const auto& value) { *this = value; });
return *this;
}
- Variant& operator=(Variant&& other) {
+ Variant& operator=(Variant&& other) noexcept {
other.Visit([this](auto&& value) { *this = std::move(value); });
return *this;
}
@@ -553,7 +553,7 @@
template <typename T>
constexpr std::int32_t index_of() const {
static_assert(HasType<T>::value, "T is not an element type of Variant.");
- return value_.template index(DecayedTypeTag<T>{});
+ return value_.index(DecayedTypeTag<T>{});
}
// Returns the index of the active type. If the Variant is empty -1 is
@@ -575,7 +575,7 @@
template <typename T>
T* get() {
if (is<T>())
- return &value_.template get(DecayedTypeTag<T>{});
+ return &value_.get(DecayedTypeTag<T>{});
else
return nullptr;
}
@@ -589,7 +589,7 @@
template <std::size_t I>
TypeForIndex<I>* get() {
if (is<TypeForIndex<I>>())
- return &value_.template get(TypeTagForIndex<I>{});
+ return &value_.get(TypeTagForIndex<I>{});
else
return nullptr;
}
diff --git a/libs/vr/libpdx/private/pdx/service.h b/libs/vr/libpdx/private/pdx/service.h
index 13aa3e9..234b24a 100644
--- a/libs/vr/libpdx/private/pdx/service.h
+++ b/libs/vr/libpdx/private/pdx/service.h
@@ -92,8 +92,8 @@
/*
* Message objects support move construction and assignment.
*/
- Message(Message&& other);
- Message& operator=(Message&& other);
+ Message(Message&& other) noexcept;
+ Message& operator=(Message&& other) noexcept;
/*
* Read/write payload, in either single buffer or iovec form.
diff --git a/libs/vr/libpdx/private/pdx/status.h b/libs/vr/libpdx/private/pdx/status.h
index 067fe25..7e51a52 100644
--- a/libs/vr/libpdx/private/pdx/status.h
+++ b/libs/vr/libpdx/private/pdx/status.h
@@ -41,14 +41,14 @@
// Copy/move constructors. Move constructor leaves |other| object in empty
// state.
Status(const Status& other) = default;
- Status(Status&& other)
+ Status(Status&& other) noexcept
: value_{std::move(other.value_)}, error_{other.error_} {
other.error_ = -1;
}
// Assignment operators.
Status& operator=(const Status& other) = default;
- Status& operator=(Status&& other) {
+ Status& operator=(Status&& other) noexcept {
error_ = other.error_;
value_ = std::move(other.value_);
other.error_ = -1;
diff --git a/libs/vr/libpdx/private/pdx/utility.h b/libs/vr/libpdx/private/pdx/utility.h
index 08fcaea..c9a0c21 100644
--- a/libs/vr/libpdx/private/pdx/utility.h
+++ b/libs/vr/libpdx/private/pdx/utility.h
@@ -33,7 +33,7 @@
return *this;
}
- ByteBuffer& operator=(ByteBuffer&& other) {
+ ByteBuffer& operator=(ByteBuffer&& other) noexcept {
std::swap(data_, other.data_);
std::swap(size_, other.size_);
std::swap(capacity_, other.capacity_);
diff --git a/libs/vr/libpdx/service.cpp b/libs/vr/libpdx/service.cpp
index 1d3b62a..68b8dd7 100644
--- a/libs/vr/libpdx/service.cpp
+++ b/libs/vr/libpdx/service.cpp
@@ -31,9 +31,9 @@
// C++11 specifies the move semantics for shared_ptr but not weak_ptr. This
// means we have to manually implement the desired move semantics for Message.
-Message::Message(Message&& other) { *this = std::move(other); }
+Message::Message(Message&& other) noexcept { *this = std::move(other); }
-Message& Message::operator=(Message&& other) {
+Message& Message::operator=(Message&& other) noexcept {
Destroy();
auto base = reinterpret_cast<std::uint8_t*>(&info_);
std::fill(&base[0], &base[sizeof(info_)], 0);
diff --git a/libs/vr/libpdx/service_tests.cpp b/libs/vr/libpdx/service_tests.cpp
index e623abf..938d737 100644
--- a/libs/vr/libpdx/service_tests.cpp
+++ b/libs/vr/libpdx/service_tests.cpp
@@ -51,22 +51,24 @@
// method(IoVecMatcher(IoVecArray{{ptr1, size1}, {ptr2, size2}})));
using IoVecArray = std::vector<iovec>;
MATCHER_P(IoVecMatcher, iovec_array, "") {
+ auto local_arg = arg;
for (const iovec& item : iovec_array) {
- if (arg->iov_base != item.iov_base || arg->iov_len != item.iov_len)
+ if (local_arg->iov_base != item.iov_base || local_arg->iov_len != item.iov_len)
return false;
- arg++;
+ local_arg++;
}
return true;
}
using IoVecData = std::vector<std::string>;
MATCHER_P(IoVecDataMatcher, iovec_data, "") {
+ auto local_arg = arg;
for (const std::string& item : iovec_data) {
- std::string data{reinterpret_cast<const char*>(arg->iov_base),
- arg->iov_len};
+ std::string data{reinterpret_cast<const char*>(local_arg->iov_base),
+ local_arg->iov_len};
if (data != item)
return false;
- arg++;
+ local_arg++;
}
return true;
}
diff --git a/libs/vr/libpdx_default_transport/Android.bp b/libs/vr/libpdx_default_transport/Android.bp
index 74b8c8b..1176abf 100644
--- a/libs/vr/libpdx_default_transport/Android.bp
+++ b/libs/vr/libpdx_default_transport/Android.bp
@@ -40,6 +40,7 @@
"liblog",
"libutils",
"libcrypto",
+ "libselinux",
],
}
diff --git a/libs/vr/libpdx_uds/Android.bp b/libs/vr/libpdx_uds/Android.bp
index d640950..1d6eea2 100644
--- a/libs/vr/libpdx_uds/Android.bp
+++ b/libs/vr/libpdx_uds/Android.bp
@@ -26,8 +26,6 @@
],
shared_libs: [
"libbinder",
- ],
- whole_static_libs: [
"libselinux",
],
}
@@ -57,5 +55,6 @@
"liblog",
"libutils",
"libbinder",
+ "libselinux",
],
}
diff --git a/libs/vr/libvr_manager/Android.bp b/libs/vr/libvr_manager/Android.bp
index 8784877..2cd6a28 100644
--- a/libs/vr/libvr_manager/Android.bp
+++ b/libs/vr/libvr_manager/Android.bp
@@ -12,25 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-exported_include_dirs = [ "include" ]
-
-include_dirs = ["frameworks/native/include/vr/vr_manager"]
-
-src_files = [
- "vr_manager.cpp",
- "trusted_uids.cpp",
-]
-
-static_libs = [
- "libutils",
- "libbinder",
-]
-
cc_library_static {
- srcs: src_files,
- include_dirs: include_dirs,
- export_include_dirs: exported_include_dirs,
- cflags: ["-Wall", "-Werror", "-Wunused", "-Wunreachable-code"],
- static_libs: static_libs,
name: "libvr_manager",
+ srcs: [
+ "vr_manager.cpp",
+ "trusted_uids.cpp",
+ ],
+ include_dirs: ["frameworks/native/include/vr/vr_manager"],
+ export_include_dirs: [ "include" ],
+ cflags: ["-Wall", "-Werror", "-Wunused", "-Wunreachable-code"],
+ shared_libs: [
+ "libutils",
+ "libbinder",
+ ],
}
diff --git a/libs/vr/libvrflinger/acquired_buffer.cpp b/libs/vr/libvrflinger/acquired_buffer.cpp
index 9614c6d..5d873d1 100644
--- a/libs/vr/libvrflinger/acquired_buffer.cpp
+++ b/libs/vr/libvrflinger/acquired_buffer.cpp
@@ -31,13 +31,13 @@
}
}
-AcquiredBuffer::AcquiredBuffer(AcquiredBuffer&& other) {
+AcquiredBuffer::AcquiredBuffer(AcquiredBuffer&& other) noexcept {
*this = std::move(other);
}
AcquiredBuffer::~AcquiredBuffer() { Release(LocalHandle(kEmptyFence)); }
-AcquiredBuffer& AcquiredBuffer::operator=(AcquiredBuffer&& other) {
+AcquiredBuffer& AcquiredBuffer::operator=(AcquiredBuffer&& other) noexcept {
if (this != &other) {
Release();
diff --git a/libs/vr/libvrflinger/acquired_buffer.h b/libs/vr/libvrflinger/acquired_buffer.h
index 32e912a..1a200aa 100644
--- a/libs/vr/libvrflinger/acquired_buffer.h
+++ b/libs/vr/libvrflinger/acquired_buffer.h
@@ -31,7 +31,7 @@
AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer, int* error);
// Move constructor. Behaves similarly to the move assignment operator below.
- AcquiredBuffer(AcquiredBuffer&& other);
+ AcquiredBuffer(AcquiredBuffer&& other) noexcept;
~AcquiredBuffer();
@@ -39,7 +39,7 @@
// |other| into this instance after RELEASING the current BufferConsumer and
// closing the acquire fence. After the move |other| is left in the empty
// state.
- AcquiredBuffer& operator=(AcquiredBuffer&& other);
+ AcquiredBuffer& operator=(AcquiredBuffer&& other) noexcept;
// Accessors for the underlying BufferConsumer, the acquire fence, and the
// use-case specific sequence value from the acquisition (see
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 44ce78c..b8d5e2b 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -1272,9 +1272,9 @@
Layer::~Layer() { Reset(); }
-Layer::Layer(Layer&& other) { *this = std::move(other); }
+Layer::Layer(Layer&& other) noexcept { *this = std::move(other); }
-Layer& Layer::operator=(Layer&& other) {
+Layer& Layer::operator=(Layer&& other) noexcept {
if (this != &other) {
Reset();
using std::swap;
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index 1d8d463..539a7fb 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -86,8 +86,8 @@
const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
HWC::Composition composition_type, size_t z_order);
- Layer(Layer&&);
- Layer& operator=(Layer&&);
+ Layer(Layer&&) noexcept;
+ Layer& operator=(Layer&&) noexcept;
~Layer();
diff --git a/opengl/libagl/state.cpp b/opengl/libagl/state.cpp
index 1d5def5..8bb7e83 100644
--- a/opengl/libagl/state.cpp
+++ b/opengl/libagl/state.cpp
@@ -181,7 +181,7 @@
case GL_FOG:
case GL_DEPTH_TEST:
ogles_invalidate_perspective(c);
- // fall-through...
+ [[fallthrough]];
case GL_BLEND:
case GL_SCISSOR_TEST:
case GL_ALPHA_TEST:
diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp
index aae8e05..4c5f3e9 100644
--- a/opengl/libagl/texture.cpp
+++ b/opengl/libagl/texture.cpp
@@ -401,14 +401,14 @@
switch (format) {
case GL_PALETTE4_RGB8_OES:
indexBits = 4;
- /* FALLTHROUGH */
+ [[fallthrough]];
case GL_PALETTE8_RGB8_OES:
entrySize = 3;
break;
case GL_PALETTE4_RGBA8_OES:
indexBits = 4;
- /* FALLTHROUGH */
+ [[fallthrough]];
case GL_PALETTE8_RGBA8_OES:
entrySize = 4;
break;
@@ -417,7 +417,7 @@
case GL_PALETTE4_RGBA4_OES:
case GL_PALETTE4_RGB5_A1_OES:
indexBits = 4;
- /* FALLTHROUGH */
+ [[fallthrough]];
case GL_PALETTE8_R5_G6_B5_OES:
case GL_PALETTE8_RGBA4_OES:
case GL_PALETTE8_RGB5_A1_OES:
@@ -446,14 +446,14 @@
switch (format) {
case GL_PALETTE4_RGB8_OES:
indexBits = 4;
- /* FALLTHROUGH */
+ [[fallthrough]];
case GL_PALETTE8_RGB8_OES:
entrySize = 3;
break;
case GL_PALETTE4_RGBA8_OES:
indexBits = 4;
- /* FALLTHROUGH */
+ [[fallthrough]];
case GL_PALETTE8_RGBA8_OES:
entrySize = 4;
break;
@@ -462,7 +462,7 @@
case GL_PALETTE4_RGBA4_OES:
case GL_PALETTE4_RGB5_A1_OES:
indexBits = 4;
- /* FALLTHROUGH */
+ [[fallthrough]];
case GL_PALETTE8_R5_G6_B5_OES:
case GL_PALETTE8_RGBA4_OES:
case GL_PALETTE8_RGB5_A1_OES:
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index c65bddf..40adf8e 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -456,7 +456,7 @@
// Translates EGL color spaces to Android data spaces.
static android_dataspace dataSpaceFromEGLColorSpace(EGLint colorspace) {
if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
- return HAL_DATASPACE_SRGB_LINEAR;
+ return HAL_DATASPACE_UNKNOWN;
} else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
return HAL_DATASPACE_SRGB;
} else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_EXT) {
@@ -562,6 +562,15 @@
break;
}
}
+
+ // If the driver doesn't understand it, we should map sRGB-encoded P3 to
+ // sRGB rather than just dropping the colorspace on the floor.
+ // For this format, the driver is expected to apply the sRGB
+ // transfer function during framebuffer operations.
+ if (!copyAttribute && attr[1] == EGL_GL_COLORSPACE_DISPLAY_P3_EXT) {
+ strippedAttribList->push_back(attr[0]);
+ strippedAttribList->push_back(EGL_GL_COLORSPACE_SRGB_KHR);
+ }
}
if (copyAttribute) {
strippedAttribList->push_back(attr[0]);
@@ -1054,38 +1063,6 @@
egl_tls_t::setContext(EGL_NO_CONTEXT);
}
} else {
-
- if (cur_c != NULL) {
- // Force return to current context for drivers that cannot handle errors
- EGLBoolean restore_result = EGL_FALSE;
- // get a reference to the old current objects
- ContextRef _c2(dp.get(), cur_c);
- SurfaceRef _d2(dp.get(), cur_c->draw);
- SurfaceRef _r2(dp.get(), cur_c->read);
-
- c = cur_c;
- impl_ctx = c->context;
- impl_draw = EGL_NO_SURFACE;
- if (cur_c->draw != EGL_NO_SURFACE) {
- d = get_surface(cur_c->draw);
- impl_draw = d->surface;
- }
- impl_read = EGL_NO_SURFACE;
- if (cur_c->read != EGL_NO_SURFACE) {
- r = get_surface(cur_c->read);
- impl_read = r->surface;
- }
- restore_result = dp->makeCurrent(c, cur_c,
- cur_c->draw, cur_c->read, cur_c->context,
- impl_draw, impl_read, impl_ctx);
- if (restore_result == EGL_TRUE) {
- _c2.acquire();
- _r2.acquire();
- _d2.acquire();
- } else {
- ALOGE("Could not restore original EGL context");
- }
- }
// this will ALOGE the error
egl_connection_t* const cnx = &gEGLImpl;
result = setError(cnx->egl.eglGetError(), (EGLBoolean)EGL_FALSE);
diff --git a/services/batteryservice/Android.bp b/services/batteryservice/Android.bp
index 186f399..66ee8ff 100644
--- a/services/batteryservice/Android.bp
+++ b/services/batteryservice/Android.bp
@@ -1,7 +1,8 @@
cc_library_headers {
name: "libbatteryservice_headers",
vendor_available: true,
+ recovery_available: true,
export_include_dirs: ["include"],
- header_libs: ["libbinder_headers"],
- export_header_lib_headers: ["libbinder_headers"],
+ header_libs: ["libutils_headers"],
+ export_header_lib_headers: ["libutils_headers"],
}
diff --git a/services/batteryservice/include/batteryservice/BatteryService.h b/services/batteryservice/include/batteryservice/BatteryService.h
index 80ab7f3..1e8eb1e 100644
--- a/services/batteryservice/include/batteryservice/BatteryService.h
+++ b/services/batteryservice/include/batteryservice/BatteryService.h
@@ -17,7 +17,6 @@
#ifndef ANDROID_BATTERYSERVICE_H
#define ANDROID_BATTERYSERVICE_H
-#include <binder/Parcel.h>
#include <sys/types.h>
#include <utils/Errors.h>
#include <utils/String8.h>
@@ -54,16 +53,10 @@
int batteryFullCharge;
int batteryChargeCounter;
String8 batteryTechnology;
-
- status_t writeToParcel(Parcel* parcel) const;
- status_t readFromParcel(Parcel* parcel);
};
struct BatteryProperty {
int64_t valueInt64;
-
- status_t writeToParcel(Parcel* parcel) const;
- status_t readFromParcel(Parcel* parcel);
};
}; // namespace android
diff --git a/services/batteryservice/include/batteryservice/IBatteryPropertiesListener.h b/services/batteryservice/include/batteryservice/IBatteryPropertiesListener.h
deleted file mode 100644
index b226dd6..0000000
--- a/services/batteryservice/include/batteryservice/IBatteryPropertiesListener.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_IBATTERYPROPERTIESLISTENER_H
-#define ANDROID_IBATTERYPROPERTIESLISTENER_H
-
-#include <binder/IBinder.h>
-#include <binder/IInterface.h>
-
-#include <batteryservice/BatteryService.h>
-
-namespace android {
-
-// must be kept in sync with interface defined in IBatteryPropertiesListener.aidl
-enum {
- TRANSACT_BATTERYPROPERTIESCHANGED = IBinder::FIRST_CALL_TRANSACTION,
-};
-
-// ----------------------------------------------------------------------------
-
-class IBatteryPropertiesListener : public IInterface {
-public:
- DECLARE_META_INTERFACE(BatteryPropertiesListener)
-
- virtual void batteryPropertiesChanged(struct BatteryProperties props) = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnBatteryPropertiesListener: public BnInterface<IBatteryPropertiesListener> {
-public:
- virtual status_t onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif // ANDROID_IBATTERYPROPERTIESLISTENER_H
diff --git a/services/batteryservice/include/batteryservice/IBatteryPropertiesRegistrar.h b/services/batteryservice/include/batteryservice/IBatteryPropertiesRegistrar.h
deleted file mode 100644
index a7dbea6..0000000
--- a/services/batteryservice/include/batteryservice/IBatteryPropertiesRegistrar.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_IBATTERYPROPERTIESREGISTRAR_H
-#define ANDROID_IBATTERYPROPERTIESREGISTRAR_H
-
-#include <binder/IInterface.h>
-#include <batteryservice/IBatteryPropertiesListener.h>
-
-namespace android {
-
-// must be kept in sync with interface defined in IBatteryPropertiesRegistrar.aidl
-enum {
- REGISTER_LISTENER = IBinder::FIRST_CALL_TRANSACTION,
- UNREGISTER_LISTENER,
- GET_PROPERTY,
- SCHEDULE_UPDATE,
-};
-
-class IBatteryPropertiesRegistrar : public IInterface {
-public:
- DECLARE_META_INTERFACE(BatteryPropertiesRegistrar)
-
- virtual void registerListener(const sp<IBatteryPropertiesListener>& listener) = 0;
- virtual void unregisterListener(const sp<IBatteryPropertiesListener>& listener) = 0;
- virtual status_t getProperty(int id, struct BatteryProperty *val) = 0;
- virtual void scheduleUpdate() = 0;
-};
-
-class BnBatteryPropertiesRegistrar : public BnInterface<IBatteryPropertiesRegistrar> {
-public:
- virtual status_t onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif // ANDROID_IBATTERYPROPERTIESREGISTRAR_H
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index a9e5a43..8871199 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -41,6 +41,8 @@
"-Wall",
"-Wextra",
"-Werror",
+ // Allow implicit fallthroughs in InputReader.cpp until they are fixed.
+ "-Wno-error=implicit-fallthrough",
"-Wno-unused-parameter",
// TODO: Move inputflinger to its own process and mark it hidden
//-fvisibility=hidden
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index e0cd8a0..21a9bce 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -3018,7 +3018,7 @@
if (!changes) {
mRotaryEncoderScrollAccumulator.configure(getDevice());
}
- if (!changes || (InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
+ if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
DisplayViewport v;
if (config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, NULL, &v)) {
mOrientation = v.orientation;
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index b1d5e61..afaf139 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -6,13 +6,13 @@
"InputReader_test.cpp",
"InputDispatcher_test.cpp",
],
- test_per_src: true,
cflags: [
"-Wall",
"-Werror",
"-Wno-unused-parameter",
],
shared_libs: [
+ "libbase",
"libcutils",
"liblog",
"libutils",
diff --git a/services/media/arcvideobridge/Android.bp b/services/media/arcvideobridge/Android.bp
deleted file mode 100644
index ca5b896..0000000
--- a/services/media/arcvideobridge/Android.bp
+++ /dev/null
@@ -1,28 +0,0 @@
-cc_library_shared {
- name: "libarcvideobridge",
- product_variables: {
- arc: {
- srcs: [
- "IArcVideoBridge.cpp",
- ],
- shared_libs: [
- "libarcbridge",
- "libarcbridgeservice",
- "libbinder",
- "libchrome",
- "liblog",
- "libmojo",
- "libutils",
- ],
- cflags: [
- "-Wall",
- "-Werror",
- "-Wunused",
- "-Wunreachable-code",
- ],
- include_dirs: [
- "frameworks/native/include/media/arcvideobridge",
- ]
- }
- }
-}
diff --git a/services/media/arcvideobridge/IArcVideoBridge.cpp b/services/media/arcvideobridge/IArcVideoBridge.cpp
deleted file mode 100644
index 468b76b..0000000
--- a/services/media/arcvideobridge/IArcVideoBridge.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "IArcVideoBridge"
-//#define LOG_NDEBUG 0
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include "IArcVideoBridge.h"
-#include <binder/Parcel.h>
-#include <utils/Log.h>
-
-namespace android {
-
-enum {
- BOOTSTRAP_VIDEO_ACCELERATOR_FACTORY = IBinder::FIRST_CALL_TRANSACTION,
- HOST_VERSION,
-};
-
-class BpArcVideoBridge : public BpInterface<IArcVideoBridge> {
-public:
- BpArcVideoBridge(const sp<IBinder>& impl) : BpInterface<IArcVideoBridge>(impl) { }
-
- virtual ::arc::MojoBootstrapResult bootstrapVideoAcceleratorFactory() {
- Parcel data, reply;
- ALOGV("bootstrapVideoAcceleratorFactory");
- data.writeInterfaceToken(IArcVideoBridge::getInterfaceDescriptor());
- status_t status = remote()->transact(
- BOOTSTRAP_VIDEO_ACCELERATOR_FACTORY, data, &reply, 0);
- if (status != 0) {
- ALOGE("transact failed: %d", status);
- return arc::MojoBootstrapResult();
- }
- return arc::MojoBootstrapResult::createFromParcel(reply);
- }
-
- virtual int32_t hostVersion() {
- Parcel data, reply;
- ALOGV("hostVersion");
- data.writeInterfaceToken(IArcVideoBridge::getInterfaceDescriptor());
- status_t status = remote()->transact(HOST_VERSION, data, &reply, 0);
- if (status != 0) {
- ALOGE("transact failed: %d", status);
- return false;
- }
- return reply.readInt32();
- }
-};
-
-IMPLEMENT_META_INTERFACE(ArcVideoBridge, "android.os.IArcVideoBridge");
-
-status_t BnArcVideoBridge::onTransact(
- uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
- switch(code) {
- case BOOTSTRAP_VIDEO_ACCELERATOR_FACTORY: {
- ALOGV("BOOTSTRAP_VIDEO_ACCELERATOR_FACTORY");
- CHECK_INTERFACE(IArcVideoBridge, data, reply);
- arc::MojoBootstrapResult result = bootstrapVideoAcceleratorFactory();
- return result.writeToParcel(reply);
- }
- case HOST_VERSION: {
- ALOGV("HOST_VERSION");
- CHECK_INTERFACE(IArcVideoBridge, data, reply);
- reply->writeInt32(hostVersion());
- return OK;
- }
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-} // namespace android
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index c2bb6ad..320e11f 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -27,6 +27,7 @@
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.composer@2.2",
"android.hardware.power@1.0",
+ "android.hardware.power@1.3",
"libbase",
"libbinder",
"libbufferhubqueue",
@@ -69,6 +70,7 @@
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.composer@2.2",
+ "android.hardware.power@1.3",
"libhidlbase",
"libhidltransport",
"libhwbinder",
@@ -96,6 +98,7 @@
"DisplayHardware/HWC2.cpp",
"DisplayHardware/HWComposer.cpp",
"DisplayHardware/HWComposerBufferCache.cpp",
+ "DisplayHardware/PowerAdvisor.cpp",
"DisplayHardware/VirtualDisplaySurface.cpp",
"DispSync.cpp",
"Effects/Daltonizer.cpp",
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index fda7906..3db633b 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -63,7 +63,7 @@
mRefreshPending(false) {
ALOGV("Creating Layer %s", name.string());
- mFlinger->getRenderEngine().genTextures(1, &mTextureName);
+ mTextureName = mFlinger->getNewTexture();
mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName);
if (flags & ISurfaceComposerClient::eNonPremultiplied) mPremultipliedAlpha = false;
@@ -622,6 +622,9 @@
const auto& viewport = displayDevice->getViewport();
Region visible = tr.transform(visibleRegion.intersect(viewport));
auto hwcId = displayDevice->getHwcDisplayId();
+ if (!hasHwcLayer(hwcId)) {
+ return;
+ }
auto& hwcInfo = getBE().mHwcLayers[hwcId];
auto& hwcLayer = hwcInfo.layer;
auto error = hwcLayer->setVisibleRegion(visible);
@@ -706,8 +709,12 @@
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer, true);
mProducer = new MonitoredProducer(producer, mFlinger, this);
- mConsumer = new BufferLayerConsumer(consumer,
- mFlinger->getRenderEngine(), mTextureName, this);
+ {
+ // Grab the SF state lock during this since it's the only safe way to access RenderEngine
+ Mutex::Autolock lock(mFlinger->mStateLock);
+ mConsumer = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName,
+ this);
+ }
mConsumer->setConsumerUsageBits(getEffectiveUsage(0));
mConsumer->setContentsChangedListener(this);
mConsumer->setName(mName);
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index 077469b..0b59147 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -170,48 +170,8 @@
}
}
- /*
- * createSurface must be called from the GL thread so that it can
- * have access to the GL context.
- */
- class MessageCreateLayer : public MessageBase {
- SurfaceFlinger* flinger;
- Client* client;
- sp<IBinder>* handle;
- sp<IGraphicBufferProducer>* gbp;
- status_t result;
- const String8& name;
- uint32_t w, h;
- PixelFormat format;
- uint32_t flags;
- sp<Layer>* parent;
- int32_t windowType;
- int32_t ownerUid;
- public:
- MessageCreateLayer(SurfaceFlinger* flinger,
- const String8& name, Client* client,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
- sp<IBinder>* handle, int32_t windowType, int32_t ownerUid,
- sp<IGraphicBufferProducer>* gbp,
- sp<Layer>* parent)
- : flinger(flinger), client(client),
- handle(handle), gbp(gbp), result(NO_ERROR),
- name(name), w(w), h(h), format(format), flags(flags),
- parent(parent), windowType(windowType), ownerUid(ownerUid) {
- }
- status_t getResult() const { return result; }
- virtual bool handler() {
- result = flinger->createLayer(name, client, w, h, format, flags,
- windowType, ownerUid, handle, gbp, parent);
- return true;
- }
- };
-
- sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),
- name, this, w, h, format, flags, handle,
- windowType, ownerUid, gbp, &parent);
- mFlinger->postMessageSync(msg);
- return static_cast<MessageCreateLayer*>( msg.get() )->getResult();
+ return mFlinger->createLayer(name, this, w, h, format, flags, windowType,
+ ownerUid, handle, gbp, &parent);
}
status_t Client::destroySurface(const sp<IBinder>& handle) {
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index 512564c..ff957c0 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -66,6 +66,9 @@
const auto& viewport = displayDevice->getViewport();
Region visible = tr.transform(visibleRegion.intersect(viewport));
auto hwcId = displayDevice->getHwcDisplayId();
+ if (!hasHwcLayer(hwcId)) {
+ return;
+ }
auto& hwcInfo = getBE().mHwcLayers[hwcId];
auto& hwcLayer = hwcInfo.layer;
auto error = hwcLayer->setVisibleRegion(visible);
diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h
index 543f60a..b352b96 100644
--- a/services/surfaceflinger/ContainerLayer.h
+++ b/services/surfaceflinger/ContainerLayer.h
@@ -35,6 +35,8 @@
bool isVisible() const override;
void setPerFrameData(const sp<const DisplayDevice>& displayDevice) override;
+
+ bool isCreatedFromMainThread() const override { return true; }
};
} // namespace android
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index 7acbd11..37dc27d 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -222,7 +222,13 @@
// Pretend that the last time this event was handled at the same frame but with the
// new offset to allow for a seamless offset change without double-firing or
// skipping.
- listener.mLastEventTime -= (oldPhase - phase);
+ nsecs_t diff = oldPhase - phase;
+ if (diff > mPeriod / 2) {
+ diff -= mPeriod;
+ } else if (diff < -mPeriod / 2) {
+ diff += mPeriod;
+ }
+ listener.mLastEventTime -= diff;
mCond.signal();
return NO_ERROR;
}
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index db095a5..309fd0a 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -781,9 +781,12 @@
*outMode = iter->second.colorMode;
*outIntent = iter->second.renderIntent;
} else {
- ALOGE("map unknown (%s)/(%s) to default color mode",
- dataspaceDetails(static_cast<android_dataspace_t>(dataspace)).c_str(),
- decodeRenderIntent(intent).c_str());
+ // this is unexpected on a WCG display
+ if (hasWideColorGamut()) {
+ ALOGE("map unknown (%s)/(%s) to default color mode",
+ dataspaceDetails(static_cast<android_dataspace_t>(dataspace)).c_str(),
+ decodeRenderIntent(intent).c_str());
+ }
*outDataspace = Dataspace::UNKNOWN;
*outMode = ColorMode::NATIVE;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 61758b6..1a60c83 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -138,7 +138,7 @@
}
auto display = std::make_unique<Display>(
- *mComposer.get(), mCapabilities, displayId, DisplayType::Virtual);
+ *mComposer.get(), mPowerAdvisor, mCapabilities, displayId, DisplayType::Virtual);
display->setConnected(true);
*outDisplay = display.get();
mDisplays.emplace(displayId, std::move(display));
@@ -177,7 +177,7 @@
}
auto newDisplay = std::make_unique<Display>(
- *mComposer.get(), mCapabilities, displayId, displayType);
+ *mComposer.get(), mPowerAdvisor, mCapabilities, displayId, displayType);
newDisplay->setConnected(true);
mDisplays.emplace(displayId, std::move(newDisplay));
} else if (connection == Connection::Disconnected) {
@@ -219,10 +219,11 @@
// Display methods
-Display::Display(android::Hwc2::Composer& composer,
+Display::Display(android::Hwc2::Composer& composer, android::Hwc2::PowerAdvisor& advisor,
const std::unordered_set<Capability>& capabilities, hwc2_display_t id,
DisplayType type)
: mComposer(composer),
+ mPowerAdvisor(advisor),
mCapabilities(capabilities),
mId(id),
mIsConnected(false),
@@ -605,6 +606,12 @@
Error Display::setColorMode(ColorMode mode, RenderIntent renderIntent)
{
+ // When the color mode is switched to DISPLAY_P3, we want to boost the GPU frequency
+ // so that GPU composition can finish in time. When color mode is switched from
+ // DISPLAY_P3, we want to reset GPU frequency.
+ const bool expensiveRenderingExpected = (mode == ColorMode::DISPLAY_P3);
+ mPowerAdvisor.setExpensiveRenderingExpected(mId, expensiveRenderingExpected);
+
auto intError = mComposer.setColorMode(mId, mode, renderIntent);
return static_cast<Error>(intError);
}
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 29d7a47..e423167 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -37,6 +37,8 @@
#include <unordered_set>
#include <vector>
+#include "PowerAdvisor.h"
+
namespace android {
class Fence;
class FloatRect;
@@ -119,6 +121,7 @@
std::unique_ptr<android::Hwc2::Composer> mComposer;
std::unordered_set<Capability> mCapabilities;
std::unordered_map<hwc2_display_t, std::unique_ptr<Display>> mDisplays;
+ android::Hwc2::impl::PowerAdvisor mPowerAdvisor;
bool mRegisteredCallback = false;
};
@@ -126,7 +129,8 @@
class Display
{
public:
- Display(android::Hwc2::Composer& composer, const std::unordered_set<Capability>& capabilities,
+ Display(android::Hwc2::Composer& composer, android::Hwc2::PowerAdvisor& advisor,
+ const std::unordered_set<Capability>& capabilities,
hwc2_display_t id, DisplayType type);
~Display();
@@ -282,6 +286,7 @@
// this HWC2::Display, so these references are guaranteed to be valid for
// the lifetime of this object.
android::Hwc2::Composer& mComposer;
+ android::Hwc2::PowerAdvisor& mPowerAdvisor;
const std::unordered_set<Capability>& mCapabilities;
hwc2_display_t mId;
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
new file mode 100644
index 0000000..12bbae2
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
@@ -0,0 +1,99 @@
+/*
+ * 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 "PowerAdvisor"
+
+#include <cinttypes>
+
+#include <utils/Log.h>
+#include <utils/Mutex.h>
+
+#include "PowerAdvisor.h"
+
+namespace android {
+namespace Hwc2 {
+
+PowerAdvisor::~PowerAdvisor() = default;
+
+namespace impl {
+
+namespace V1_0 = android::hardware::power::V1_0;
+using V1_3::PowerHint;
+
+PowerAdvisor::~PowerAdvisor() = default;
+
+PowerAdvisor::PowerAdvisor() = default;
+
+void PowerAdvisor::setExpensiveRenderingExpected(hwc2_display_t displayId, bool expected) {
+ if (expected) {
+ mExpensiveDisplays.insert(displayId);
+ } else {
+ mExpensiveDisplays.erase(displayId);
+ }
+
+ const bool expectsExpensiveRendering = !mExpensiveDisplays.empty();
+ if (mNotifiedExpensiveRendering != expectsExpensiveRendering) {
+ const sp<V1_3::IPower> powerHal = getPowerHal();
+ if (powerHal == nullptr) {
+ return;
+ }
+ auto ret = powerHal->powerHintAsync_1_3(PowerHint::EXPENSIVE_RENDERING,
+ expectsExpensiveRendering);
+ // If Power HAL 1.3 was available previously but now fails,
+ // it may restart, so attempt to reconnect next time
+ if (!ret.isOk()) {
+ mReconnectPowerHal = true;
+ return;
+ }
+ mNotifiedExpensiveRendering = expectsExpensiveRendering;
+ }
+}
+
+sp<V1_3::IPower> PowerAdvisor::getPowerHal() {
+ static sp<V1_3::IPower> sPowerHal_1_3 = nullptr;
+ static bool sHasPowerHal_1_3 = true;
+
+ if (mReconnectPowerHal) {
+ sPowerHal_1_3 = nullptr;
+ mReconnectPowerHal = false;
+ }
+
+ // Power HAL 1.3 is not guaranteed to be available, thus we need to query
+ // Power HAL 1.0 first and try to cast it to Power HAL 1.3.
+ // Power HAL 1.0 is always available, thus if we fail to query it, it means
+ // Power HAL is not available temporarily and we should retry later. However,
+ // if Power HAL 1.0 is available and we can't cast it to Power HAL 1.3,
+ // it means Power HAL 1.3 is not available at all, so we should stop trying.
+ if (sHasPowerHal_1_3 && sPowerHal_1_3 == nullptr) {
+ sp<V1_0::IPower> powerHal_1_0 = V1_0::IPower::getService();
+ if (powerHal_1_0 != nullptr) {
+ // Try to cast to Power HAL 1.3
+ sPowerHal_1_3 = V1_3::IPower::castFrom(powerHal_1_0);
+ if (sPowerHal_1_3 == nullptr) {
+ ALOGW("No Power HAL 1.3 service in system");
+ sHasPowerHal_1_3 = false;
+ } else {
+ ALOGI("Loaded Power HAL 1.3 service");
+ }
+ }
+ }
+ return sPowerHal_1_3;
+}
+
+} // namespace impl
+} // namespace Hwc2
+} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
new file mode 100644
index 0000000..573a1a9
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
@@ -0,0 +1,63 @@
+/*
+ * 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
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+#include <android/hardware/power/1.3/IPower.h>
+#include <utils/StrongPointer.h>
+
+#include <unordered_set>
+
+namespace android {
+namespace Hwc2 {
+
+class PowerAdvisor {
+public:
+ virtual ~PowerAdvisor();
+
+ virtual void setExpensiveRenderingExpected(hwc2_display_t displayId, bool expected) = 0;
+};
+
+namespace impl {
+
+namespace V1_3 = android::hardware::power::V1_3;
+
+// PowerAdvisor is a wrapper around IPower HAL which takes into account the
+// full state of the system when sending out power hints to things like the GPU.
+class PowerAdvisor final : public Hwc2::PowerAdvisor {
+public:
+ PowerAdvisor();
+ ~PowerAdvisor() override;
+
+ void setExpensiveRenderingExpected(hwc2_display_t displayId, bool expected) override;
+
+private:
+ sp<V1_3::IPower> getPowerHal();
+
+ std::unordered_set<hwc2_display_t> mExpensiveDisplays;
+ bool mNotifiedExpensiveRendering = false;
+ bool mReconnectPowerHal = false;
+};
+
+} // namespace impl
+} // namespace Hwc2
+} // namespace android
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 2595ec1..90e0e9e 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -130,17 +130,26 @@
// drawing state & current state are identical
mDrawingState = mCurrentState;
- const auto& hwc = flinger->getHwComposer();
- const auto& activeConfig = hwc.getActiveConfig(HWC_DISPLAY_PRIMARY);
- nsecs_t displayPeriod = activeConfig->getVsyncPeriod();
- mFrameTracker.setDisplayRefreshPeriod(displayPeriod);
-
CompositorTiming compositorTiming;
flinger->getCompositorTiming(&compositorTiming);
mFrameEventHistory.initializeCompositorTiming(compositorTiming);
}
-void Layer::onFirstRef() {}
+void Layer::onFirstRef() NO_THREAD_SAFETY_ANALYSIS {
+ if (!isCreatedFromMainThread()) {
+ // Grab the SF state lock during this since it's the only way to safely access HWC
+ mFlinger->mStateLock.lock();
+ }
+
+ const auto& hwc = mFlinger->getHwComposer();
+ const auto& activeConfig = hwc.getActiveConfig(HWC_DISPLAY_PRIMARY);
+ nsecs_t displayPeriod = activeConfig->getVsyncPeriod();
+ mFrameTracker.setDisplayRefreshPeriod(displayPeriod);
+
+ if (!isCreatedFromMainThread()) {
+ mFlinger->mStateLock.unlock();
+ }
+}
Layer::~Layer() {
sp<Client> c(mClientRef.promote());
@@ -345,20 +354,25 @@
win.intersect(s.crop, &win);
}
- Rect bounds = win;
const auto& p = mDrawingParent.promote();
+ FloatRect floatWin = win.toFloatRect();
+ FloatRect parentBounds = floatWin;
if (p != nullptr) {
- // Look in computeScreenBounds recursive call for explanation of
- // why we pass false here.
- bounds = p->computeScreenBounds(false /* reduceTransparentRegion */);
+ // We pass an empty Region here for reasons mirroring that of the case described in
+ // the computeScreenBounds reduceTransparentRegion=false case.
+ parentBounds = p->computeBounds(Region());
}
- Transform t = getTransform();
+ Transform t = s.active.transform;
- FloatRect floatWin = win.toFloatRect();
- if (p != nullptr) {
+
+ if (p != nullptr || !s.finalCrop.isEmpty()) {
floatWin = t.transform(floatWin);
- floatWin = floatWin.intersect(bounds.toFloatRect());
+ floatWin = floatWin.intersect(parentBounds);
+
+ if (!s.finalCrop.isEmpty()) {
+ floatWin = floatWin.intersect(s.finalCrop.toFloatRect());
+ }
floatWin = t.inverse().transform(floatWin);
}
@@ -486,6 +500,9 @@
void Layer::setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z)
{
const auto hwcId = displayDevice->getHwcDisplayId();
+ if (!hasHwcLayer(hwcId)) {
+ return;
+ }
auto& hwcInfo = getBE().mHwcLayers[hwcId];
// enable this layer
@@ -1249,7 +1266,15 @@
return true;
}
-bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) {
+bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix,
+ bool allowNonRectPreservingTransforms) {
+ Transform t;
+ t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
+
+ if (!allowNonRectPreservingTransforms && !t.preserveRects()) {
+ ALOGW("Attempt to set rotation matrix without permission ACCESS_SURFACE_FLINGER ignored");
+ return false;
+ }
mCurrentState.sequence++;
mCurrentState.requested.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
mCurrentState.modified = true;
@@ -1974,9 +1999,22 @@
layerInfo->set_refresh_pending(isBufferLatched());
layerInfo->set_window_type(state.type);
layerInfo->set_app_id(state.appId);
+ layerInfo->set_curr_frame(mCurrentFrameNumber);
+
+ for (const auto& pendingState : mPendingStates) {
+ auto barrierLayer = pendingState.barrierLayer.promote();
+ if (barrierLayer != nullptr) {
+ BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer();
+ barrierLayerProto->set_id(barrierLayer->sequence);
+ barrierLayerProto->set_frame_number(pendingState.frameNumber);
+ }
+ }
}
void Layer::writeToProto(LayerProto* layerInfo, int32_t hwcId) {
+ if (!hasHwcLayer(hwcId)) {
+ return;
+ }
writeToProto(layerInfo, LayerVector::StateSet::Drawing);
const auto& hwcInfo = getBE().mHwcLayers.at(hwcId);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 34811fb..2239679 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -258,7 +258,7 @@
// Set a 2x2 transformation matrix on the layer. This transform
// will be applied after parent transforms, but before any final
// producer specified transform.
- bool setMatrix(const layer_state_t::matrix22_t& matrix);
+ bool setMatrix(const layer_state_t::matrix22_t& matrix, bool allowNonRectPreservingTransforms);
// This second set of geometry attributes are controlled by
// setGeometryAppliesWithResize, and their default mode is to be
@@ -360,6 +360,11 @@
*/
virtual bool isFixedSize() const { return true; }
+ // Most layers aren't created from the main thread, and therefore need to
+ // grab the SF state lock to access HWC, but ContainerLayer does, so we need
+ // to avoid grabbing the lock again to avoid deadlock
+ virtual bool isCreatedFromMainThread() const { return false; }
+
bool isPendingRemoval() const { return mPendingRemoval; }
diff --git a/services/surfaceflinger/LayerStats.cpp b/services/surfaceflinger/LayerStats.cpp
index 04ab121..2a67955 100644
--- a/services/surfaceflinger/LayerStats.cpp
+++ b/services/surfaceflinger/LayerStats.cpp
@@ -68,7 +68,7 @@
base::StringAppendF(&key, ",%s", layerCompositionType(layer->hwcCompositionType));
base::StringAppendF(&key, ",%d", layer->isProtected);
base::StringAppendF(&key, ",%s", layerTransform(layer->hwcTransform));
- base::StringAppendF(&key, ",%s", layerPixelFormat(layer->activeBuffer.format));
+ base::StringAppendF(&key, ",%s", layerPixelFormat(layer->activeBuffer.format).c_str());
base::StringAppendF(&key, ",%s", layer->dataspace.c_str());
base::StringAppendF(&key, ",%s",
destinationLocation(layer->hwcFrame.left, layerGlobal.resolution[0],
@@ -162,8 +162,8 @@
return getCompositionName(static_cast<hwc2_composition_t>(compositionType));
}
-const char* LayerStats::layerPixelFormat(int32_t pixelFormat) {
- return decodePixelFormat(pixelFormat).c_str();
+std::string LayerStats::layerPixelFormat(int32_t pixelFormat) {
+ return decodePixelFormat(pixelFormat);
}
std::string LayerStats::scaleRatioWH(const LayerProtoParser::Layer* layer) {
diff --git a/services/surfaceflinger/LayerStats.h b/services/surfaceflinger/LayerStats.h
index 7a190fd..bd17d82 100644
--- a/services/surfaceflinger/LayerStats.h
+++ b/services/surfaceflinger/LayerStats.h
@@ -50,7 +50,7 @@
// Return the name of the composition type
static const char* layerCompositionType(int32_t compositionType);
// Return the name of the pixel format
- static const char* layerPixelFormat(int32_t pixelFormat);
+ 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
diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp
index 09414fd..c218e4d 100644
--- a/services/surfaceflinger/RenderEngine/Description.cpp
+++ b/services/surfaceflinger/RenderEngine/Description.cpp
@@ -51,10 +51,6 @@
mProjectionMatrix = mtx;
}
-void Description::setSaturationMatrix(const mat4& mtx) {
- mSaturationMatrix = mtx;
-}
-
void Description::setColorMatrix(const mat4& mtx) {
mColorMatrix = mtx;
}
@@ -82,11 +78,6 @@
return mColorMatrix != identity;
}
-bool Description::hasSaturationMatrix() const {
- const mat4 identity;
- return mSaturationMatrix != identity;
-}
-
const mat4& Description::getColorMatrix() const {
return mColorMatrix;
}
diff --git a/services/surfaceflinger/RenderEngine/Description.h b/services/surfaceflinger/RenderEngine/Description.h
index 06eaf35..6ebb340 100644
--- a/services/surfaceflinger/RenderEngine/Description.h
+++ b/services/surfaceflinger/RenderEngine/Description.h
@@ -42,14 +42,12 @@
void disableTexture();
void setColor(const half4& color);
void setProjectionMatrix(const mat4& mtx);
- void setSaturationMatrix(const mat4& mtx);
void setColorMatrix(const mat4& mtx);
void setInputTransformMatrix(const mat3& matrix);
void setOutputTransformMatrix(const mat4& matrix);
bool hasInputTransformMatrix() const;
bool hasOutputTransformMatrix() const;
bool hasColorMatrix() const;
- bool hasSaturationMatrix() const;
const mat4& getColorMatrix() const;
void setY410BT2020(bool enable);
@@ -92,7 +90,6 @@
// projection matrix
mat4 mProjectionMatrix;
mat4 mColorMatrix;
- mat4 mSaturationMatrix;
mat3 mInputTransformMatrix;
mat4 mOutputTransformMatrix;
};
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 0048000..744a70c 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -267,10 +267,6 @@
mState.setColorMatrix(colorTransform);
}
-void GLES20RenderEngine::setSaturationMatrix(const mat4& saturationMatrix) {
- mState.setSaturationMatrix(saturationMatrix);
-}
-
void GLES20RenderEngine::disableTexturing() {
mState.disableTexture();
}
@@ -383,11 +379,10 @@
// we need to convert the RGB value to linear space and convert it back when:
// - there is a color matrix that is not an identity matrix, or
- // - there is a saturation matrix that is not an identity matrix, or
// - there is an output transform matrix that is not an identity matrix, or
// - the input transfer function doesn't match the output transfer function.
- if (wideColorState.hasColorMatrix() || wideColorState.hasSaturationMatrix() ||
- wideColorState.hasOutputTransformMatrix() || inputTransfer != outputTransfer) {
+ if (wideColorState.hasColorMatrix() || wideColorState.hasOutputTransformMatrix() ||
+ inputTransfer != outputTransfer) {
switch (inputTransfer) {
case Dataspace::TRANSFER_ST2084:
wideColorState.setInputTransferFunction(Description::TransferFunction::ST2084);
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index de5761b..cc8eb1d 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -81,7 +81,6 @@
virtual void setupLayerBlackedOut();
virtual void setupFillWithColor(float r, float g, float b, float a);
virtual void setupColorTransform(const mat4& colorTransform);
- virtual void setSaturationMatrix(const mat4& saturationMatrix);
virtual void disableTexturing();
virtual void disableBlending();
diff --git a/services/surfaceflinger/RenderEngine/Program.cpp b/services/surfaceflinger/RenderEngine/Program.cpp
index 95adaca..fe536f0 100644
--- a/services/surfaceflinger/RenderEngine/Program.cpp
+++ b/services/surfaceflinger/RenderEngine/Program.cpp
@@ -135,22 +135,13 @@
glUniform4fv(mColorLoc, 1, color);
}
if (mInputTransformMatrixLoc >= 0) {
- // If the input transform matrix is not identity matrix, we want to merge
- // the saturation matrix with input transform matrix so that the saturation
- // matrix is applied at the correct stage.
- mat4 inputTransformMatrix = mat4(desc.mInputTransformMatrix) * desc.mSaturationMatrix;
+ mat4 inputTransformMatrix = mat4(desc.mInputTransformMatrix);
glUniformMatrix4fv(mInputTransformMatrixLoc, 1, GL_FALSE, inputTransformMatrix.asArray());
}
if (mOutputTransformMatrixLoc >= 0) {
// The output transform matrix and color matrix can be combined as one matrix
// that is applied right before applying OETF.
mat4 outputTransformMatrix = desc.mColorMatrix * desc.mOutputTransformMatrix;
- // If there is no input transform matrix, we want to merge the saturation
- // matrix with output transform matrix to avoid extra matrix multiplication
- // in shader.
- if (mInputTransformMatrixLoc < 0) {
- outputTransformMatrix *= desc.mSaturationMatrix;
- }
glUniformMatrix4fv(mOutputTransformMatrixLoc, 1, GL_FALSE,
outputTransformMatrix.asArray());
}
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
index 796901a..fe992f1 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -149,8 +149,7 @@
description.hasInputTransformMatrix() ?
Key::INPUT_TRANSFORM_MATRIX_ON : Key::INPUT_TRANSFORM_MATRIX_OFF)
.set(Key::Key::OUTPUT_TRANSFORM_MATRIX_MASK,
- description.hasOutputTransformMatrix() || description.hasColorMatrix() ||
- (!description.hasInputTransformMatrix() && description.hasSaturationMatrix()) ?
+ description.hasOutputTransformMatrix() || description.hasColorMatrix() ?
Key::OUTPUT_TRANSFORM_MATRIX_ON : Key::OUTPUT_TRANSFORM_MATRIX_OFF);
needs.set(Key::Y410_BT2020_MASK,
@@ -319,7 +318,7 @@
// scale [0.0, maxInLumi] to [0.0, maxOutLumi]
if (maxInLumi <= maxOutLumi) {
- nits *= maxOutLumi / maxInLumi;
+ return color * (maxOutLumi / maxInLumi);
} else {
// three control points
const float x0 = 10.0;
@@ -340,7 +339,7 @@
if (nits < x0) {
// scale [0.0, x0] to [0.0, y0] linearly
float slope = y0 / x0;
- nits *= slope;
+ return color * slope;
} else if (nits < x1) {
// scale [x0, x1] to [y0, y1] linearly
float slope = (y1 - y0) / (x1 - x0);
@@ -358,7 +357,8 @@
}
}
- return color * (nits / max(1e-6, color.y));
+ // color.y is greater than x0 and is thus non-zero
+ return color * (nits / color.y);
}
)__SHADER__";
break;
@@ -389,7 +389,7 @@
if (nits <= x0) {
// scale [0.0, x0] to [0.0, y0] linearly
const float slope = y0 / x0;
- nits *= slope;
+ return color * slope;
} else if (nits <= x1) {
// scale [x0, x1] to [y0, y1] using a curve
float t = (nits - x0) / (x1 - x0);
@@ -404,7 +404,8 @@
nits = (1.0 - t) * (1.0 - t) * y2 + 2.0 * (1.0 - t) * t * c3 + t * t * y3;
}
- return color * (nits / max(1e-6, color.y));
+ // color.y is greater than x0 and is thus non-zero
+ return color * (nits / color.y);
}
)__SHADER__";
break;
@@ -577,7 +578,7 @@
fs << "uniform mat4 inputTransformMatrix;";
fs << R"__SHADER__(
highp vec3 InputTransform(const highp vec3 color) {
- return vec3(inputTransformMatrix * vec4(color, 1.0));
+ return clamp(vec3(inputTransformMatrix * vec4(color, 1.0)), 0.0, 1.0);
}
)__SHADER__";
} else {
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 1196216..1786155 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -113,7 +113,6 @@
virtual void setupFillWithColor(float r, float g, float b, float a) = 0;
virtual void setupColorTransform(const mat4& /* colorTransform */) = 0;
- virtual void setSaturationMatrix(const mat4& /* saturationMatrix */) = 0;
virtual void disableTexturing() = 0;
virtual void disableBlending() = 0;
@@ -228,7 +227,6 @@
void checkErrors() const override;
void setupColorTransform(const mat4& /* colorTransform */) override {}
- void setSaturationMatrix(const mat4& /* saturationMatrix */) override {}
// internal to RenderEngine
EGLDisplay getEGLDisplay() const;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 87baf8c..cf53930 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -37,6 +37,7 @@
#include <dvr/vr_flinger.h>
+#include <ui/ColorSpace.h>
#include <ui/DebugUtils.h>
#include <ui/DisplayInfo.h>
#include <ui/DisplayStatInfo.h>
@@ -222,6 +223,7 @@
mVisibleRegionsDirty(false),
mGeometryInvalid(false),
mAnimCompositionPending(false),
+ mBootStage(BootStage::BOOTLOADER),
mDebugRegion(0),
mDebugDDMS(0),
mDebugDisableHWC(0),
@@ -230,7 +232,6 @@
mLastSwapBufferTime(0),
mDebugInTransaction(0),
mLastTransactionTime(0),
- mBootFinished(false),
mForceFullDamage(false),
mPrimaryDispSync("PrimaryDispSync"),
mPrimaryHWVsyncEnabled(false),
@@ -331,11 +332,26 @@
auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize));
mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize;
- property_get("debug.sf.early_phase_offset_ns", value, "0");
- const int earlyWakeupOffsetOffsetNs = atoi(value);
- ALOGI_IF(earlyWakeupOffsetOffsetNs != 0, "Enabling separate early offset");
- mVsyncModulator.setPhaseOffsets(sfVsyncPhaseOffsetNs - earlyWakeupOffsetOffsetNs,
- sfVsyncPhaseOffsetNs);
+ property_get("debug.sf.early_phase_offset_ns", value, "-1");
+ const int earlySfOffsetNs = atoi(value);
+
+ property_get("debug.sf.early_gl_phase_offset_ns", value, "-1");
+ const int earlyGlSfOffsetNs = atoi(value);
+
+ property_get("debug.sf.early_app_phase_offset_ns", value, "-1");
+ const int earlyAppOffsetNs = atoi(value);
+
+ property_get("debug.sf.early_gl_app_phase_offset_ns", value, "-1");
+ const int earlyGlAppOffsetNs = atoi(value);
+
+ const VSyncModulator::Offsets earlyOffsets =
+ {earlySfOffsetNs != -1 ? earlySfOffsetNs : sfVsyncPhaseOffsetNs,
+ earlyAppOffsetNs != -1 ? earlyAppOffsetNs : vsyncPhaseOffsetNs};
+ const VSyncModulator::Offsets earlyGlOffsets =
+ {earlyGlSfOffsetNs != -1 ? earlyGlSfOffsetNs : sfVsyncPhaseOffsetNs,
+ earlyGlAppOffsetNs != -1 ? earlyGlAppOffsetNs : vsyncPhaseOffsetNs};
+ mVsyncModulator.setPhaseOffsets(earlyOffsets, earlyGlOffsets,
+ {sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs});
// We should be reading 'persist.sys.sf.color_saturation' here
// but since /data may be encrypted, we need to wait until after vold
@@ -482,10 +498,32 @@
sp<LambdaMessage> readProperties = new LambdaMessage([&]() {
readPersistentProperties();
+ mBootStage = BootStage::FINISHED;
});
postMessageAsync(readProperties);
}
+uint32_t SurfaceFlinger::getNewTexture() {
+ {
+ std::lock_guard lock(mTexturePoolMutex);
+ if (!mTexturePool.empty()) {
+ uint32_t name = mTexturePool.back();
+ mTexturePool.pop_back();
+ ATRACE_INT("TexturePoolSize", mTexturePool.size());
+ return name;
+ }
+
+ // The pool was too small, so increase it for the future
+ ++mTexturePoolSize;
+ }
+
+ // The pool was empty, so we need to get a new texture name directly using a
+ // blocking call to the main thread
+ uint32_t name = 0;
+ postMessageSync(new LambdaMessage([&]() { getRenderEngine().genTextures(1, &name); }));
+ return name;
+}
+
void SurfaceFlinger::deleteTextureAsync(uint32_t texture) {
class MessageDestroyGLTexture : public MessageBase {
RE::RenderEngine& engine;
@@ -662,7 +700,7 @@
},
"sfEventThread");
mEventQueue->setEventThread(mSFEventThread.get());
- mVsyncModulator.setEventThread(mSFEventThread.get());
+ mVsyncModulator.setEventThreads(mSFEventThread.get(), mEventThread.get());
// Get a RenderEngine for the given display / config (can't fail)
getBE().mRenderEngine =
@@ -732,9 +770,24 @@
ALOGE("Run StartPropertySetThread failed!");
}
- mLegacySrgbSaturationMatrix = getBE().mHwc->getDataspaceSaturationMatrix(HWC_DISPLAY_PRIMARY,
+ // This is a hack. Per definition of getDataspaceSaturationMatrix, the returned matrix
+ // is used to saturate legacy sRGB content. However, to make sure the same color under
+ // Display P3 will be saturated to the same color, we intentionally break the API spec
+ // and apply this saturation matrix on Display P3 content. Unless the risk of applying
+ // such saturation matrix on Display P3 is understood fully, the API should always return
+ // identify matrix.
+ mEnhancedSaturationMatrix = getBE().mHwc->getDataspaceSaturationMatrix(HWC_DISPLAY_PRIMARY,
Dataspace::SRGB_LINEAR);
+ // we will apply this on Display P3.
+ if (mEnhancedSaturationMatrix != mat4()) {
+ ColorSpace srgb(ColorSpace::sRGB());
+ ColorSpace displayP3(ColorSpace::DisplayP3());
+ mat4 srgbToP3 = mat4(ColorSpaceConnector(srgb, displayP3).getTransform());
+ mat4 p3ToSrgb = mat4(ColorSpaceConnector(displayP3, srgb).getTransform());
+ mEnhancedSaturationMatrix = srgbToP3 * mEnhancedSaturationMatrix * p3ToSrgb;
+ }
+
ALOGV("Done initializing");
}
@@ -1496,7 +1549,7 @@
bool refreshNeeded = handleMessageTransaction();
refreshNeeded |= handleMessageInvalidate();
refreshNeeded |= mRepaintEverything;
- if (refreshNeeded) {
+ if (refreshNeeded && CC_LIKELY(mBootStage != BootStage::BOOTLOADER)) {
// Signal a refresh if a transaction modified the window state,
// a new buffer was latched, or if HWC has requested a full
// repaint
@@ -1809,6 +1862,17 @@
getBE().mTotalTime += elapsedTime;
}
getBE().mLastSwapTime = currentTime;
+
+ {
+ std::lock_guard lock(mTexturePoolMutex);
+ const size_t refillCount = mTexturePoolSize - mTexturePool.size();
+ if (refillCount > 0) {
+ const size_t offset = mTexturePool.size();
+ mTexturePool.resize(mTexturePoolSize);
+ getRenderEngine().genTextures(refillCount, mTexturePool.data() + offset);
+ ATRACE_INT("TexturePoolSize", mTexturePool.size());
+ }
+ }
}
void SurfaceFlinger::rebuildLayerStacks() {
@@ -2855,6 +2919,12 @@
signalLayerUpdate();
}
+ // enter boot animation on first buffer latch
+ if (CC_UNLIKELY(mBootStage == BootStage::BOOTLOADER && newDataLatched)) {
+ ALOGI("Enter boot animation");
+ mBootStage = BootStage::BOOTANIMATION;
+ }
+
// Only continue with the refresh if there is actually new work to do
return !mLayersWithQueuedFrames.empty() && newDataLatched;
}
@@ -2897,8 +2967,7 @@
ATRACE_INT("hasClientComposition", hasClientComposition);
bool applyColorMatrix = false;
- bool needsLegacyColorMatrix = false;
- bool legacyColorMatrixApplied = false;
+ bool needsEnhancedColorMatrix = false;
if (hasClientComposition) {
ALOGV("hasClientComposition");
@@ -2915,15 +2984,23 @@
const bool skipClientColorTransform = getBE().mHwc->hasCapability(
HWC2::Capability::SkipClientColorTransform);
+ mat4 colorMatrix;
applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform;
if (applyColorMatrix) {
- getRenderEngine().setupColorTransform(mDrawingState.colorMatrix);
+ colorMatrix = mDrawingState.colorMatrix;
}
- needsLegacyColorMatrix =
+ // The current enhanced saturation matrix is designed to enhance Display P3,
+ // thus we only apply this matrix when the render intent is not colorimetric
+ // and the output color space is Display P3.
+ needsEnhancedColorMatrix =
(displayDevice->getActiveRenderIntent() >= RenderIntent::ENHANCE &&
- outputDataspace != Dataspace::UNKNOWN &&
- outputDataspace != Dataspace::SRGB);
+ outputDataspace == Dataspace::DISPLAY_P3);
+ if (needsEnhancedColorMatrix) {
+ colorMatrix *= mEnhancedSaturationMatrix;
+ }
+
+ getRenderEngine().setupColorTransform(colorMatrix);
if (!displayDevice->makeCurrent()) {
ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
@@ -3010,17 +3087,6 @@
break;
}
case HWC2::Composition::Client: {
- // switch color matrices lazily
- if (layer->isLegacyDataSpace() && needsLegacyColorMatrix) {
- if (!legacyColorMatrixApplied) {
- getRenderEngine().setSaturationMatrix(mLegacySrgbSaturationMatrix);
- legacyColorMatrixApplied = true;
- }
- } else if (legacyColorMatrixApplied) {
- getRenderEngine().setSaturationMatrix(mat4());
- legacyColorMatrixApplied = false;
- }
-
layer->draw(renderArea, clip);
break;
}
@@ -3033,12 +3099,9 @@
firstLayer = false;
}
- if (applyColorMatrix) {
+ if (applyColorMatrix || needsEnhancedColorMatrix) {
getRenderEngine().setupColorTransform(mat4());
}
- if (needsLegacyColorMatrix && legacyColorMatrixApplied) {
- getRenderEngine().setSaturationMatrix(mat4());
- }
// disable scissor at the end of the frame
getBE().mRenderEngine->disableScissor();
@@ -3327,6 +3390,18 @@
return flags;
}
+bool callingThreadHasUnscopedSurfaceFlingerAccess() {
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ const int uid = ipc->getCallingUid();
+
+ if ((uid != AID_GRAPHICS && uid != AID_SYSTEM) &&
+ !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) {
+ return false;
+ }
+ return true;
+}
+
uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState) {
const layer_state_t& s = composerState.state;
sp<Client> client(static_cast<Client*>(composerState.client.get()));
@@ -3408,7 +3483,22 @@
flags |= eTraversalNeeded;
}
if (what & layer_state_t::eMatrixChanged) {
- if (layer->setMatrix(s.matrix))
+ // TODO: b/109894387
+ //
+ // SurfaceFlinger's renderer is not prepared to handle cropping in the face of arbitrary
+ // rotation. To see the problem observe that if we have a square parent, and a child
+ // of the same size, then we rotate the child 45 degrees around it's center, the child
+ // must now be cropped to a non rectangular 8 sided region.
+ //
+ // Of course we can fix this in the future. For now, we are lucky, SurfaceControl is
+ // private API, and the WindowManager only uses rotation in one case, which is on a top
+ // level layer in which cropping is not an issue.
+ //
+ // However given that abuse of rotation matrices could lead to surfaces extending outside
+ // of cropped areas, we need to prevent non-root clients without permission ACCESS_SURFACE_FLINGER
+ // (a.k.a. everyone except WindowManager and tests) from setting non rectangle preserving
+ // transformations.
+ if (layer->setMatrix(s.matrix, callingThreadHasUnscopedSurfaceFlingerAccess()))
flags |= eTraversalNeeded;
}
if (what & layer_state_t::eTransparentRegionChanged) {
@@ -3574,10 +3664,13 @@
// Tack on our counter whether there is a hit or not, so everyone gets a tag
String8 uniqueName = name + "#" + String8(std::to_string(dupeCounter).c_str());
+ // Grab the state lock since we're accessing mCurrentState
+ Mutex::Autolock lock(mStateLock);
+
// Loop over layers until we're sure there is no matching name
while (matchFound) {
matchFound = false;
- mDrawingState.traverseInZOrder([&](Layer* layer) {
+ mCurrentState.traverseInZOrder([&](Layer* layer) {
if (layer->getName() == uniqueName) {
matchFound = true;
uniqueName = name + "#" + String8(std::to_string(++dupeCounter).c_str());
@@ -4207,9 +4300,22 @@
colorizer.bold(result);
result.append("DispSync configuration: ");
colorizer.reset(result);
- result.appendFormat("app phase %" PRId64 " ns, sf phase %" PRId64 " ns, early sf phase %" PRId64
- " ns, present offset %" PRId64 " ns (refresh %" PRId64 " ns)",
- vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, mVsyncModulator.getEarlyPhaseOffset(),
+ const auto [sfEarlyOffset, appEarlyOffset] = mVsyncModulator.getEarlyOffsets();
+ const auto [sfEarlyGlOffset, appEarlyGlOffset] = mVsyncModulator.getEarlyGlOffsets();
+ result.appendFormat(
+ "app phase %" PRId64 " ns, "
+ "sf phase %" PRId64 " ns, "
+ "early app phase %" PRId64 " ns, "
+ "early sf phase %" PRId64 " ns, "
+ "early app gl phase %" PRId64 " ns, "
+ "early sf gl phase %" PRId64 " ns, "
+ "present offset %" PRId64 " ns (refresh %" PRId64 " ns)",
+ vsyncPhaseOffsetNs,
+ sfVsyncPhaseOffsetNs,
+ appEarlyOffset,
+ sfEarlyOffset,
+ appEarlyGlOffset,
+ sfEarlyOffset,
dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod());
result.append("\n");
@@ -4412,12 +4518,10 @@
case INJECT_VSYNC:
{
// codes that require permission check
- IPCThreadState* ipc = IPCThreadState::self();
- const int pid = ipc->getCallingPid();
- const int uid = ipc->getCallingUid();
- if ((uid != AID_GRAPHICS && uid != AID_SYSTEM) &&
- !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) {
- ALOGE("Permission Denial: can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
+ if (!callingThreadHasUnscopedSurfaceFlingerAccess()) {
+ IPCThreadState* ipc = IPCThreadState::self();
+ ALOGE("Permission Denial: can't access SurfaceFlinger pid=%d, uid=%d",
+ ipc->getCallingPid(), ipc->getCallingUid());
return PERMISSION_DENIED;
}
break;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 8566b03..8f724e9 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -320,6 +320,10 @@
return getDefaultDisplayDeviceLocked();
}
+ // Obtains a name from the texture pool, or, if the pool is empty, posts a
+ // synchronous message to the main thread to obtain one on the fly
+ uint32_t getNewTexture();
+
// utility function to delete a texture on the main thread
void deleteTextureAsync(uint32_t texture);
@@ -808,6 +812,13 @@
sp<Fence> mPreviousPresentFence = Fence::NO_FENCE;
bool mHadClientComposition = false;
+ enum class BootStage {
+ BOOTLOADER,
+ BOOTANIMATION,
+ FINISHED,
+ };
+ BootStage mBootStage;
+
struct HotplugEvent {
hwc2_display_t display;
HWC2::Connection connection = HWC2::Connection::Invalid;
@@ -828,7 +839,6 @@
nsecs_t mLastSwapBufferTime;
volatile nsecs_t mDebugInTransaction;
nsecs_t mLastTransactionTime;
- bool mBootFinished;
bool mForceFullDamage;
bool mPropagateBackpressure = true;
std::unique_ptr<SurfaceInterceptor> mInterceptor =
@@ -858,6 +868,13 @@
std::atomic<bool> mRefreshPending{false};
+ // We maintain a pool of pre-generated texture names to hand out to avoid
+ // layer creation needing to run on the main thread (which it would
+ // otherwise need to do to access RenderEngine).
+ std::mutex mTexturePoolMutex;
+ uint32_t mTexturePoolSize = 0;
+ std::vector<uint32_t> mTexturePool;
+
/* ------------------------------------------------------------------------
* Feature prototyping
*/
@@ -878,9 +895,9 @@
static bool useVrFlinger;
std::thread::id mMainThreadId;
- DisplayColorSetting mDisplayColorSetting = DisplayColorSetting::MANAGED;
- // Applied on sRGB layers when the render intent is non-colorimetric.
- mat4 mLegacySrgbSaturationMatrix;
+ DisplayColorSetting mDisplayColorSetting = DisplayColorSetting::ENHANCED;
+ // Applied on Display P3 layers when the render intent is non-colorimetric.
+ mat4 mEnhancedSaturationMatrix;
using CreateBufferQueueFunction =
std::function<void(sp<IGraphicBufferProducer>* /* outProducer */,
diff --git a/services/surfaceflinger/VSyncModulator.h b/services/surfaceflinger/VSyncModulator.h
index d526313..e071a59 100644
--- a/services/surfaceflinger/VSyncModulator.h
+++ b/services/surfaceflinger/VSyncModulator.h
@@ -36,6 +36,11 @@
public:
+ struct Offsets {
+ nsecs_t sf;
+ nsecs_t app;
+ };
+
enum TransactionStart {
EARLY,
NORMAL
@@ -43,21 +48,32 @@
// Sets the phase offsets
//
- // early: the phase offset when waking up early. May be the same as late, in which case we don't
- // shift offsets.
- // late: the regular sf phase offset.
- void setPhaseOffsets(nsecs_t early, nsecs_t late) {
- mEarlyPhaseOffset = early;
- mLatePhaseOffset = late;
- mPhaseOffset = late;
+ // sfEarly: The phase offset when waking up SF early, which happens when marking a transaction
+ // as early. May be the same as late, in which case we don't shift offsets.
+ // sfEarlyGl: Like sfEarly, but only if we used GL composition. If we use both GL composition
+ // and the transaction was marked as early, we'll use sfEarly.
+ // sfLate: The regular SF vsync phase offset.
+ // appEarly: Like sfEarly, but for the app-vsync
+ // appEarlyGl: Like sfEarlyGl, but for the app-vsync.
+ // appLate: The regular app vsync phase offset.
+ void setPhaseOffsets(Offsets early, Offsets earlyGl, Offsets late) {
+ mEarlyOffsets = early;
+ mEarlyGlOffsets = earlyGl;
+ mLateOffsets = late;
+ mOffsets = late;
}
- nsecs_t getEarlyPhaseOffset() const {
- return mEarlyPhaseOffset;
+ Offsets getEarlyOffsets() const {
+ return mEarlyOffsets;
}
- void setEventThread(EventThread* eventThread) {
- mEventThread = eventThread;
+ Offsets getEarlyGlOffsets() const {
+ return mEarlyGlOffsets;
+ }
+
+ void setEventThreads(EventThread* sfEventThread, EventThread* appEventThread) {
+ mSfEventThread = sfEventThread;
+ mAppEventThread = appEventThread;
}
void setTransactionStart(TransactionStart transactionStart) {
@@ -71,63 +87,70 @@
return;
}
mTransactionStart = transactionStart;
- updatePhaseOffsets();
+ updateOffsets();
}
void onTransactionHandled() {
if (mTransactionStart == TransactionStart::NORMAL) return;
mTransactionStart = TransactionStart::NORMAL;
- updatePhaseOffsets();
+ updateOffsets();
}
void onRefreshed(bool usedRenderEngine) {
- bool updatePhaseOffsetsNeeded = false;
+ bool updateOffsetsNeeded = false;
if (mRemainingEarlyFrameCount > 0) {
mRemainingEarlyFrameCount--;
- updatePhaseOffsetsNeeded = true;
+ updateOffsetsNeeded = true;
}
if (usedRenderEngine != mLastFrameUsedRenderEngine) {
mLastFrameUsedRenderEngine = usedRenderEngine;
- updatePhaseOffsetsNeeded = true;
+ updateOffsetsNeeded = true;
}
- if (updatePhaseOffsetsNeeded) {
- updatePhaseOffsets();
+ if (updateOffsetsNeeded) {
+ updateOffsets();
}
}
private:
- void updatePhaseOffsets() {
+ void updateOffsets() {
+ const Offsets desired = getOffsets();
+ const Offsets current = mOffsets;
- // Do not change phase offsets if disabled.
- if (mEarlyPhaseOffset == mLatePhaseOffset) return;
+ bool changed = false;
+ if (desired.sf != current.sf) {
+ mSfEventThread->setPhaseOffset(desired.sf);
+ changed = true;
+ }
+ if (desired.app != current.app) {
+ mAppEventThread->setPhaseOffset(desired.app);
+ changed = true;
+ }
- if (shouldUseEarlyOffset()) {
- if (mPhaseOffset != mEarlyPhaseOffset) {
- if (mEventThread) {
- mEventThread->setPhaseOffset(mEarlyPhaseOffset);
- }
- mPhaseOffset = mEarlyPhaseOffset;
- }
- } else {
- if (mPhaseOffset != mLatePhaseOffset) {
- if (mEventThread) {
- mEventThread->setPhaseOffset(mLatePhaseOffset);
- }
- mPhaseOffset = mLatePhaseOffset;
- }
+ if (changed) {
+ mOffsets = desired;
}
}
- bool shouldUseEarlyOffset() {
- return mTransactionStart == TransactionStart::EARLY || mLastFrameUsedRenderEngine
- || mRemainingEarlyFrameCount > 0;
+ Offsets getOffsets() {
+ if (mTransactionStart == TransactionStart::EARLY || mRemainingEarlyFrameCount > 0) {
+ return mEarlyOffsets;
+ } else if (mLastFrameUsedRenderEngine) {
+ return mEarlyGlOffsets;
+ } else {
+ return mLateOffsets;
+ }
}
- nsecs_t mLatePhaseOffset = 0;
- nsecs_t mEarlyPhaseOffset = 0;
- EventThread* mEventThread = nullptr;
- std::atomic<nsecs_t> mPhaseOffset = 0;
+ Offsets mLateOffsets;
+ Offsets mEarlyOffsets;
+ Offsets mEarlyGlOffsets;
+
+ EventThread* mSfEventThread = nullptr;
+ EventThread* mAppEventThread = nullptr;
+
+ std::atomic<Offsets> mOffsets;
+
std::atomic<TransactionStart> mTransactionStart = TransactionStart::NORMAL;
std::atomic<bool> mLastFrameUsedRenderEngine = false;
std::atomic<int> mRemainingEarlyFrameCount = 0;
diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
index 77c6675..edf56ab 100644
--- a/services/surfaceflinger/layerproto/layers.proto
+++ b/services/surfaceflinger/layerproto/layers.proto
@@ -80,6 +80,10 @@
optional int32 hwc_composition_type = 35;
// If it's a buffer layer, indicate if the content is protected
optional bool is_protected = 36;
+ // Current frame number being rendered.
+ optional uint64 curr_frame = 37;
+ // A list of barriers that the layer is waiting to update state.
+ repeated BarrierLayerProto barrier_layer = 38;
}
message PositionProto {
@@ -131,3 +135,10 @@
optional float b = 3;
optional float a = 4;
}
+
+message BarrierLayerProto {
+ // layer id the barrier is waiting on.
+ optional int32 id = 1;
+ // frame number the barrier is waiting on.
+ optional uint64 frame_number = 2;
+}
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index 8255b41..b1ff522 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -102,7 +102,7 @@
// publish surface flinger
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
- IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
+ IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);
// publish GpuService
sp<GpuService> gpuservice = new GpuService();
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index 322e8a0..c511c5e 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -15,7 +15,6 @@
cc_test {
name: "SurfaceFlinger_test",
defaults: ["surfaceflinger_defaults"],
- tags: ["test"],
test_suites: ["device-tests"],
srcs: [
"Stress_test.cpp",
diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
index 36424b9..cca84e5 100644
--- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter
+++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
@@ -1,5 +1,5 @@
{
"presubmit": {
- "filter": "LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:ScreenCaptureTest.*:DereferenceSurfaceControlTest.*"
+ "filter": "LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:ScreenCaptureTest.*:DereferenceSurfaceControlTest.*:-CropLatchingTest.FinalCropLatchingBufferOldSize"
}
}
diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp
index 520df2d..6ad1b87 100644
--- a/services/surfaceflinger/tests/fakehwc/Android.bp
+++ b/services/surfaceflinger/tests/fakehwc/Android.bp
@@ -1,7 +1,6 @@
cc_test {
name: "sffakehwc_test",
defaults: ["surfaceflinger_defaults"],
- tags: ["test"],
test_suites: ["device-tests"],
srcs: [
"FakeComposerClient.cpp",
@@ -12,6 +11,7 @@
shared_libs: [
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.power@1.3",
"libbase",
"libbinder",
"libcutils",
diff --git a/services/surfaceflinger/tests/hwc2/Android.bp b/services/surfaceflinger/tests/hwc2/Android.bp
index 0957d6a..1c8e396 100644
--- a/services/surfaceflinger/tests/hwc2/Android.bp
+++ b/services/surfaceflinger/tests/hwc2/Android.bp
@@ -15,7 +15,6 @@
cc_test {
name: "test-hwc2",
defaults: ["surfaceflinger_defaults"],
- tags: ["test"],
cflags: [
"-DEGL_EGLEXT_PROTOTYPES",
"-DGL_GLEXT_PROTOTYPES",
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 39761dd..9949bfa 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -14,7 +14,6 @@
cc_test {
name: "libsurfaceflinger_unittest",
- tags: ["test"],
defaults: ["libsurfaceflinger_defaults"],
test_suites: ["device-tests"],
srcs: [
@@ -24,6 +23,7 @@
"EventThreadTest.cpp",
"mock/DisplayHardware/MockComposer.cpp",
"mock/DisplayHardware/MockDisplaySurface.cpp",
+ "mock/DisplayHardware/MockPowerAdvisor.cpp",
"mock/gui/MockGraphicBufferConsumer.cpp",
"mock/gui/MockGraphicBufferProducer.cpp",
"mock/MockEventControlThread.cpp",
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index f1556d8..558845f 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -149,12 +149,18 @@
* Wrapper classes for Read-write access to private data to set up
* preconditions and assert post-conditions.
*/
+ class FakePowerAdvisor : public Hwc2::PowerAdvisor {
+ public:
+ FakePowerAdvisor() = default;
+ ~FakePowerAdvisor() override = default;
+ void setExpensiveRenderingExpected(hwc2_display_t, bool) override { }
+ };
struct HWC2Display : public HWC2::Display {
- HWC2Display(Hwc2::Composer& composer,
+ HWC2Display(Hwc2::Composer& composer, Hwc2::PowerAdvisor& advisor,
const std::unordered_set<HWC2::Capability>& capabilities, hwc2_display_t id,
HWC2::DisplayType type)
- : HWC2::Display(composer, capabilities, id, type) {}
+ : HWC2::Display(composer, advisor, capabilities, id, type) {}
~HWC2Display() {
// Prevents a call to disable vsyncs.
mType = HWC2::DisplayType::Invalid;
@@ -211,14 +217,28 @@
return *this;
}
- auto& addCapability(HWC2::Capability cap) {
- mCapabilities.emplace(cap);
+ auto& setCapabilities(const std::unordered_set<HWC2::Capability>* capabilities) {
+ mCapabilities = capabilities;
+ return *this;
+ }
+
+ auto& setPowerAdvisor(Hwc2::PowerAdvisor* powerAdvisor) {
+ mPowerAdvisor = powerAdvisor;
return *this;
}
void inject(TestableSurfaceFlinger* flinger, Hwc2::Composer* composer) {
- auto display = std::make_unique<HWC2Display>(*composer, mCapabilities, mHwcDisplayId,
- mHwcDisplayType);
+ static FakePowerAdvisor defaultPowerAdvisor;
+ if (mPowerAdvisor == nullptr) mPowerAdvisor = &defaultPowerAdvisor;
+ static const std::unordered_set<HWC2::Capability> defaultCapabilities;
+ if (mCapabilities == nullptr) mCapabilities = &defaultCapabilities;
+
+ // Caution - Make sure that any values passed by reference here do
+ // not refer to an instance owned by FakeHwcDisplayInjector. This
+ // class has temporary lifetime, while the constructed HWC2::Display
+ // is much longer lived.
+ auto display = std::make_unique<HWC2Display>(*composer, *mPowerAdvisor, *mCapabilities,
+ mHwcDisplayId, mHwcDisplayType);
auto config = HWC2::Display::Config::Builder(*display, mActiveConfig);
config.setWidth(mWidth);
@@ -247,7 +267,8 @@
int32_t mDpiX = DEFAULT_DPI;
int32_t mDpiY = DEFAULT_DPI;
int32_t mActiveConfig = DEFAULT_ACTIVE_CONFIG;
- std::unordered_set<HWC2::Capability> mCapabilities;
+ const std::unordered_set<HWC2::Capability>* mCapabilities = nullptr;
+ Hwc2::PowerAdvisor* mPowerAdvisor = nullptr;
};
class FakeDisplayDeviceInjector {
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.cpp b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.cpp
new file mode 100644
index 0000000..8be7077
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "MockPowerAdvisor.h"
+
+namespace android {
+namespace Hwc2 {
+namespace mock {
+
+// Explicit default instantiation is recommended.
+PowerAdvisor::PowerAdvisor() = default;
+PowerAdvisor::~PowerAdvisor() = default;
+
+} // namespace mock
+} // namespace Hwc2
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
new file mode 100644
index 0000000..dc6d83b
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
@@ -0,0 +1,37 @@
+/*
+ * 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 <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(hwc2_display_t displayId, bool expected));
+};
+
+} // namespace mock
+} // namespace Hwc2
+} // namespace android
diff --git a/services/surfaceflinger/tests/vsync/Android.bp b/services/surfaceflinger/tests/vsync/Android.bp
index d04efda..6a89945 100644
--- a/services/surfaceflinger/tests/vsync/Android.bp
+++ b/services/surfaceflinger/tests/vsync/Android.bp
@@ -15,7 +15,6 @@
cc_binary {
name: "test-vsync-events",
defaults: ["surfaceflinger_defaults"],
- tags: ["test"],
srcs: [
"vsync.cpp",
],
diff --git a/services/vr/performanced/directory_reader.h b/services/vr/performanced/directory_reader.h
index b9d27c3..f8359c4 100644
--- a/services/vr/performanced/directory_reader.h
+++ b/services/vr/performanced/directory_reader.h
@@ -16,10 +16,11 @@
class DirectoryReader {
public:
explicit DirectoryReader(base::unique_fd directory_fd) {
- directory_ = fdopendir(directory_fd.get());
+ int fd = directory_fd.release();
+ directory_ = fdopendir(fd);
error_ = errno;
- if (directory_ != nullptr)
- (void) directory_fd.release(); // ignore return result?
+ if (directory_ == nullptr)
+ close(fd);
}
~DirectoryReader() {
diff --git a/services/vr/performanced/task.cpp b/services/vr/performanced/task.cpp
index c2f078e..bda1682 100644
--- a/services/vr/performanced/task.cpp
+++ b/services/vr/performanced/task.cpp
@@ -115,7 +115,7 @@
std::istream file_stream(&filebuf);
for (std::string line; std::getline(file_stream, line);) {
- auto offset = line.find(":");
+ auto offset = line.find(':');
if (offset == std::string::npos) {
ALOGW("ReadStatusFields: Failed to find delimiter \":\" in line=\"%s\"",
line.c_str());
diff --git a/services/vr/virtual_touchpad/Android.bp b/services/vr/virtual_touchpad/Android.bp
index 513fcc1..0263481 100644
--- a/services/vr/virtual_touchpad/Android.bp
+++ b/services/vr/virtual_touchpad/Android.bp
@@ -22,14 +22,12 @@
export_include_dirs: ["include"],
shared_libs: shared_libs,
header_libs: header_libraries,
- cppflags: ["-std=c++11"],
cflags: [
"-DLOG_TAG=\"VrVirtualTouchpad\"",
"-Wall",
"-Werror",
],
name: "libvirtualtouchpad",
- tags: ["optional"],
}
// Touchpad unit tests.
@@ -52,15 +50,11 @@
"-Wall",
"-Werror",
],
- cppflags: [
- "-std=c++11",
- ],
host_ldlibs: [
"-llog",
],
name: "VirtualTouchpad_test",
stl: "libc++_static",
- tags: ["optional"],
}
// Service.
@@ -88,7 +82,6 @@
static_libs: service_static_libs,
shared_libs: service_shared_libs,
header_libs: header_libraries,
- cppflags: ["-std=c++11"],
cflags: [
"-DLOG_TAG=\"VrVirtualTouchpad\"",
"-Wall",
@@ -96,7 +89,6 @@
],
host_ldlibs: ["-llog"],
name: "virtual_touchpad",
- tags: ["optional"],
init_rc: ["virtual_touchpad.rc"],
compile_multilib: "64",
stl: "libc++_static",
@@ -121,7 +113,6 @@
srcs: client_src,
shared_libs: client_shared_libs,
header_libs: header_libraries,
- cppflags: ["-std=c++11"],
cflags: [
"-DLOG_TAG=\"VirtualTouchpadClient\"",
"-Wall",
@@ -129,6 +120,5 @@
],
host_ldlibs: ["-llog"],
name: "libvirtualtouchpadclient",
- tags: ["optional"],
export_include_dirs: ["include"],
}
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index d0e8346..5722810 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -28,7 +28,7 @@
// API version (major.minor.patch)
define VERSION_MAJOR 1
define VERSION_MINOR 1
-define VERSION_PATCH 68
+define VERSION_PATCH 86
// API limits
define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256
@@ -45,6 +45,10 @@
define VK_QUEUE_FAMILY_EXTERNAL -2
@extension("VK_EXT_queue_family_foreign")
define VK_QUEUE_FAMILY_FOREIGN_EXT -3
+@extension("VK_MAX_DRIVER_NAME_SIZE_KHR") // 197
+define VK_MAX_DRIVER_NAME_SIZE_KHR 256
+@extension("VK_MAX_DRIVER_NAME_SIZE_KHR") // 197
+define VK_MAX_DRIVER_INFO_SIZE_KHR 256
// API keywords
define VK_TRUE 1
@@ -173,6 +177,10 @@
@extension("VK_AMD_shader_image_load_store_lod") define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_SPEC_VERSION 1
@extension("VK_AMD_shader_image_load_store_lod") define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME "VK_AMD_shader_image_load_store_lod"
+// 51
+@extension("VK_NV_corner_sampled_image") define VK_NV_CORNER_SAMPLED_IMAGE_SPEC_VERSION 2
+@extension("VK_NV_corner_sampled_image") define VK_NV_CORNER_SAMPLED_IMAGE_EXTENSION_NAME "VK_NV_corner_sampled_image"
+
// 54
@extension("VK_KHR_multiview") define VK_KHR_MULTIVIEW_SPEC_VERSION 1
@extension("VK_KHR_multiview") define VK_KHR_MULTIVIEW_EXTENSION_NAME "VK_KHR_multiview"
@@ -221,8 +229,12 @@
@extension("VK_EXT_shader_subgroup_vote") define VK_EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION 1
@extension("VK_EXT_shader_subgroup_vote") define VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME "VK_EXT_shader_subgroup_vote"
+// 68
+@extension("VK_EXT_astc_decode_mode") define VK_EXT_ASTC_DECODE_MODE_SPEC_VERSION 1
+@extension("VK_EXT_astc_decode_mode") define VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME "VK_EXT_astc_decode_mode"
+
// 70
-@extension("VK_KHR_maintenance1") define VK_KHR_MAINTENANCE1_SPEC_VERSION 1
+@extension("VK_KHR_maintenance1") define VK_KHR_MAINTENANCE1_SPEC_VERSION 2
@extension("VK_KHR_maintenance1") define VK_KHR_MAINTENANCE1_EXTENSION_NAME "VK_KHR_maintenance1"
// 71
@@ -269,6 +281,10 @@
@extension("VK_KHR_push_descriptor") define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 2
@extension("VK_KHR_push_descriptor") define VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME "VK_KHR_push_descriptor"
+// 82
+@extension("VK_EXT_conditional_rendering") define VK_EXT_CONDITIONAL_RENDERING_SPEC_VERSION 1
+@extension("VK_EXT_conditional_rendering") define VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME "VK_EXT_conditional_rendering"
+
// 84
@extension("VK_KHR_16bit_storage") define VK_KHR_16BIT_STORAGE_SPEC_VERSION 1
@extension("VK_KHR_16bit_storage") define VK_KHR_16BIT_STORAGE_EXTENSION_NAME "VK_KHR_16bit_storage"
@@ -345,6 +361,10 @@
@extension("VK_EXT_hdr_metadata") define VK_EXT_HDR_METADATA_SPEC_VERSION 1
@extension("VK_EXT_hdr_metadata") define VK_EXT_HDR_METADATA_EXTENSION_NAME "VK_EXT_hdr_metadata"
+// 110
+@extension("VK_KHR_create_renderpass2") define VK_KHR_CREATE_RENDERPASS2_SPEC_VERSION 1
+@extension("VK_KHR_create_renderpass2") define VK_KHR_CREATE_RENDERPASS2_EXTENSION_NAME "VK_KHR_create_renderpass2"
+
// 112
@extension("VK_KHR_shared_presentable_image") define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1
@extension("VK_KHR_shared_presentable_image") define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image"
@@ -377,6 +397,10 @@
@extension("VK_KHR_variable_pointers") define VK_KHR_VARIABLE_POINTERS_SPEC_VERSION 1
@extension("VK_KHR_variable_pointers") define VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME "VK_KHR_variable_pointers"
+// 122
+@extension("VK_KHR_get_display_properties2") define VK_KHR_GET_DISPLAY_PROPERTIES_2_SPEC_VERSION 1
+@extension("VK_KHR_get_display_properties2") define VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_display_properties2"
+
// 123
@extension("VK_MVK_ios_surface") define VK_MVK_IOS_SURFACE_SPEC_VERSION 1
@extension("VK_MVK_ios_surface") define VK_MVK_IOS_SURFACE_EXTENSION_NAME "VK_MVK_ios_surface"
@@ -402,7 +426,7 @@
@extension("VK_EXT_debug_utils") define VK_EXT_DEBUG_UTILS_EXTENSION_NAME "VK_EXT_debug_utils"
// 130
-@extension("VK_ANDROID_external_memory_android_hardware_buffer") define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_SPEC_VERSION 2
+@extension("VK_ANDROID_external_memory_android_hardware_buffer") define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_SPEC_VERSION 3
@extension("VK_ANDROID_external_memory_android_hardware_buffer") define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME "VK_ANDROID_external_memory_android_hardware_buffer"
// 131
@@ -425,6 +449,10 @@
@extension("VK_AMD_shader_fragment_mask") define VK_AMD_SHADER_FRAGMENT_MASK_SPEC_VERSION 1
@extension("VK_AMD_shader_fragment_mask") define VK_AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME "VK_AMD_shader_fragment_mask"
+// 139
+@extension("VK_EXT_inline_uniform_block") define VK_EXT_INLINE_UNIFORM_BLOCK_SPEC_VERSION 1
+@extension("VK_EXT_inline_uniform_block") define VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME "VK_EXT_inline_uniform_block"
+
// 141
@extension("VK_EXT_shader_stencil_export") define VK_EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION 1
@extension("VK_EXT_shader_stencil_export") define VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME "VK_EXT_shader_stencil_export"
@@ -477,22 +505,98 @@
@extension("VK_EXT_validation_cache") define VK_EXT_VALIDATION_CACHE_SPEC_VERSION 1
@extension("VK_EXT_validation_cache") define VK_EXT_VALIDATION_CACHE_EXTENSION_NAME "VK_EXT_validation_cache"
-// 165
+// 162
+@extension("VK_EXT_descriptor_indexing") define VK_EXT_DESCRIPTOR_INDEXING_SPEC_VERSION 2
+@extension("VK_EXT_descriptor_indexing") define VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME "VK_EXT_descriptor_indexing"
+
+// 163
@extension("VK_EXT_shader_viewport_index_layer") define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_SPEC_VERSION 1
@extension("VK_EXT_shader_viewport_index_layer") define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME "VK_EXT_shader_viewport_index_layer"
+// 165
+@extension("VK_NV_shading_rate_image") define VK_NV_SHADING_RATE_IMAGE_SPEC_VERSION 3
+@extension("VK_NV_shading_rate_image") define VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME "VK_NV_shading_rate_image"
+
+// 166
+@extension("VK_NVX_raytracing") define VK_NVX_RAYTRACING_SPEC_VERSION 1
+@extension("VK_NVX_raytracing") define VK_NVX_RAYTRACING_EXTENSION_NAME "VK_NVX_raytracing"
+
+// 167
+@extension("VK_NV_representative_fragment_test") define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_SPEC_VERSION 1
+@extension("VK_NV_representative_fragment_test") define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_EXTENSION_NAME "VK_NV_representative_fragment_test"
+
// 169
@extension("VK_KHR_maintenance3") define VK_KHR_MAINTENANCE3_SPEC_VERSION 1
@extension("VK_KHR_maintenance3") define VK_KHR_MAINTENANCE3_EXTENSION_NAME "VK_KHR_maintenance3"
+// 170
+@extension("VK_KHR_draw_indirect_count") define VK_KHR_DRAW_INDIRECT_COUNT_SPEC_VERSION 1
+@extension("VK_KHR_draw_indirect_count") define VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_KHR_draw_indirect_count"
+
// 175
@extension("VK_EXT_global_priority") define VK_EXT_GLOBAL_PRIORITY_SPEC_VERSION 1
@extension("VK_EXT_global_priority") define VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME "VK_EXT_global_priority"
+// 178
+@extension("VK_KHR_8bit_storage") define VK_KHR_8BIT_STORAGE_SPEC_VERSION 1
+@extension("VK_KHR_8bit_storage") define VK_KHR_8BIT_STORAGE_EXTENSION_NAME "VK_KHR_8bit_storage"
+
// 179
@extension("VK_EXT_external_memory_host") define VK_EXT_EXTERNAL_MEMORY_HOST_SPEC_VERSION 1
@extension("VK_EXT_external_memory_host") define VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME "VK_EXT_external_memory_host"
+// 180
+@extension("VK_AMD_buffer_marker") define VK_AMD_BUFFER_MARKER_SPEC_VERSION 1
+@extension("VK_AMD_buffer_marker") define VK_AMD_BUFFER_MARKER_EXTENSION_NAME "VK_AMD_buffer_marker"
+
+// 181
+@extension("VK_KHR_shader_atomic_int64") define VK_KHR_SHADER_ATOMIC_INT64_SPEC_VERSION 1
+@extension("VK_KHR_shader_atomic_int64") define VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME "VK_KHR_shader_atomic_int64"
+
+// 186
+@extension("VK_AMD_shader_core_properties") define VK_AMD_SHADER_CORE_PROPERTIES_SPEC_VERSION 1
+@extension("VK_AMD_shader_core_properties") define VK_AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME "VK_AMD_shader_core_properties"
+
+// 191
+@extension("VK_EXT_vertex_attribute_divisor") define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 2
+@extension("VK_EXT_vertex_attribute_divisor") define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor"
+
+// 197
+@extension("VK_KHR_driver_properties") define VK_KHR_DRIVER_PROPERTIES_SPEC_VERSION 1
+@extension("VK_KHR_driver_properties") define VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME "VK_KHR_driver_properties"
+
+// 199
+@extension("VK_NV_shader_subgroup_partitioned") define VK_NV_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION 1
+@extension("VK_NV_shader_subgroup_partitioned") define VK_NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME "VK_NV_shader_subgroup_partitioned"
+
+// 202
+@extension("VK_NV_compute_shader_derivatives") define VK_NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION 1
+@extension("VK_NV_compute_shader_derivatives") define VK_NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME "VK_NV_compute_shader_derivatives"
+
+// 203
+@extension("VK_NV_mesh_shader") define VK_NV_MESH_SHADER_SPEC_VERSION 1
+@extension("VK_NV_mesh_shader") define VK_NV_MESH_SHADER_EXTENSION_NAME "VK_NV_mesh_shader"
+
+// 204
+@extension("VK_NV_fragment_shader_barycentric") define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION 1
+@extension("VK_NV_fragment_shader_barycentric") define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME "VK_NV_fragment_shader_barycentric"
+
+// 205
+@extension("VK_NV_shader_image_footprint") define VK_NV_SHADER_IMAGE_FOOTPRINT_SPEC_VERSION 1
+@extension("VK_NV_shader_image_footprint") define VK_NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME "VK_NV_shader_image_footprint"
+
+// 206
+@extension("VK_NV_scissor_exclusive") define VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION 1
+@extension("VK_NV_scissor_exclusive") define VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME "VK_NV_scissor_exclusive"
+
+// 207
+@extension("VK_NV_device_diagnostic_checkpoints") define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_SPEC_VERSION 2
+@extension("VK_NV_device_diagnostic_checkpoints") define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME "VK_NV_device_diagnostic_checkpoints"
+
+// 212
+@extension("VK_KHR_vulkan_memory_model") define VK_KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION 2
+@extension("VK_KHR_vulkan_memory_model") define VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME "VK_KHR_vulkan_memory_model"
+
/////////////
// Types //
/////////////
@@ -564,6 +668,9 @@
// 161
@extension("VK_EXT_validation_cache") @nonDispatchHandle type u64 VkValidationCacheEXT
+// 166
+@extension("VK_NVX_raytracing") @nonDispatchHandle type u64 VkAccelerationStructureNVX
+
/////////////
// Enums //
/////////////
@@ -592,6 +699,9 @@
//@extension("VK_KHR_maintenance2") // 118
VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = 1000117000,
VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = 1000117001,
+
+ //@extension("VK_NV_shading_rate_image") // 165
+ VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV = 1000164003,
}
enum VkAttachmentLoadOp {
@@ -653,12 +763,21 @@
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 0x00000008,
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 0x00000009,
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 0x0000000a,
+
+ //@extension("VK_EXT_inline_uniform_block") // 139
+ VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = 1000138000,
+
+ //@extension("VK_NVX_raytracing") // 166
+ VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NVX = 1000165000,
}
enum VkQueryType {
VK_QUERY_TYPE_OCCLUSION = 0x00000000,
VK_QUERY_TYPE_PIPELINE_STATISTICS = 0x00000001, /// Optional
VK_QUERY_TYPE_TIMESTAMP = 0x00000002,
+
+ //@extension("VK_NVX_raytracing") // 166
+ VK_QUERY_TYPE_COMPACTED_SIZE_NVX = 1000165000,
}
enum VkBorderColor {
@@ -673,6 +792,9 @@
enum VkPipelineBindPoint {
VK_PIPELINE_BIND_POINT_GRAPHICS = 0x00000000,
VK_PIPELINE_BIND_POINT_COMPUTE = 0x00000001,
+
+ //@extension("VK_NVX_raytracing") // 166
+ VK_PIPELINE_BIND_POINT_RAYTRACING_NVX = 1000165000,
}
enum VkPrimitiveTopology {
@@ -1328,6 +1450,9 @@
//@extension("VK_AMD_texture_gather_bias_lod") // 42
VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000,
+ //@extension("VK_NV_corner_sampled_image") // 51
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV = 1000050000,
+
//@extension("VK_KHR_multiview") // 54
VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR = 1000053000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR = 1000053001,
@@ -1372,6 +1497,10 @@
//@extension("VK_NN_vi_surface") // 63
VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN = 1000062000,
+ //@extension("VK_EXT_astc_decode_mode") // 68
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT = 1000067000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT = 1000067001,
+
//@extension("VK_KHR_device_group_creation") // 71
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHR = 1000070000,
VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR = 1000070001,
@@ -1425,6 +1554,11 @@
//@extension("VK_KHR_incremental_present") // 85
VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000,
+ //@extension("VK_EXT_conditional_rendering") // 82
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT = 1000081000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT = 1000081001,
+ VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT = 1000081002,
+
//@extension("VK_KHR_descriptor_update_template") // 86
VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = 1000085000,
@@ -1465,6 +1599,15 @@
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT = 1000101000,
VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT = 1000101001,
+ //@extension("VK_KHR_create_renderpass2") // 110
+ VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR = 1000109000,
+ VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR = 1000109001,
+ VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR = 1000109002,
+ VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2_KHR = 1000109003,
+ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR = 1000109004,
+ VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO_KHR = 1000109005,
+ VK_STRUCTURE_TYPE_SUBPASS_END_INFO_KHR = 1000109006,
+
//@extension("VK_EXT_hdr_metadata") // 106
VK_STRUCTURE_TYPE_HDR_METADATA_EXT = 1000105000,
@@ -1501,6 +1644,13 @@
//@extension("VK_KHR_variable_pointers") // 121
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR = 1000120000,
+ //@extension("VK_KHR_display_properties2") // 122
+ VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR = 1000121000,
+ VK_STRUCTURE_TYPE_DISPLAY_PLANE_PROPERTIES_2_KHR = 1000121001,
+ VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR = 1000121002,
+ VK_STRUCTURE_TYPE_DISPLAY_PLANE_INFO_2_KHR = 1000121003,
+ VK_STRUCTURE_TYPE_DISPLAY_PLANE_CAPABILITIES_2_KHR = 1000121004,
+
//@extension("VK_MVK_ios_surface") // 123
VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK = 1000122000,
@@ -1530,6 +1680,12 @@
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = 1000130000,
VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = 1000130001,
+ //@extension("VK_EXT_inline_uniform_block") // 139
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT = 1000138000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT = 1000138001,
+ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT = 1000138002,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT = 1000138003,
+
//@extension("VK_EXT_sample_locations") // 144
VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT = 1000143000,
VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT = 1000143001,
@@ -1574,6 +1730,36 @@
VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160000,
VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160001,
+ //@extension("VK_EXT_descriptor_indexing") // 162
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT = 1000161000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT = 1000161001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT = 1000161002,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT = 1000161003,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT = 1000161004,
+
+ //@extension("VK_NV_shading_rate_image") // 165
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV = 1000164000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV = 1000164001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV = 1000164002,
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV = 1000164005,
+
+ //@extension("VK_NVX_raytracing") // 166
+ VK_STRUCTURE_TYPE_RAYTRACING_PIPELINE_CREATE_INFO_NVX = 1000165000,
+ VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NVX = 1000165001,
+ VK_STRUCTURE_TYPE_GEOMETRY_INSTANCE_NVX = 1000165002,
+ VK_STRUCTURE_TYPE_GEOMETRY_NVX = 1000165003,
+ VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NVX = 1000165004,
+ VK_STRUCTURE_TYPE_GEOMETRY_AABB_NVX = 1000165005,
+ VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NVX = 1000165006,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_ACCELERATION_STRUCTURE_INFO_NVX = 1000165007,
+ VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NVX = 1000165008,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAYTRACING_PROPERTIES_NVX = 1000165009,
+ VK_STRUCTURE_TYPE_HIT_SHADER_MODULE_CREATE_INFO_NVX = 1000165010,
+
+ //@extension("VK_NV_representative_fragment_test") // 167
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV = 1000166000,
+ VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV = 1000166001,
+
//@extension("VK_KHR_maintenance3") // 169
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR = 1000168000,
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR = 1000168001,
@@ -1581,10 +1767,34 @@
//@extension("VK_EXT_global_priority") // 175
VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT = 1000174000,
+ //@extension("VK_KHR_8bit_storage") // 178
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR = 1000177000,
+
//@extension("VK_EXT_external_memory_host") // 179
VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT = 1000178000,
VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT = 1000178001,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT = 1000178002,
+
+ //@extension("VK_KHR_shader_atomic_int64") // 181
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR = 1000180000,
+
+ //@extension("VK_KHR_driver_properties") // 197
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR = 1000196000,
+
+ //@extension("VK_AMD_shader_core_properties") // 186
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD = 1000185000,
+
+ //@extension("VK_EXT_vertex_attribute_divisor") // 191
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT = 1000190000,
+ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = 1000190001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT = 1000190002,
+
+ //@extension("VK_NV_device_diagnostic_checkpoints") // 207
+ VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV = 1000206000,
+ VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV = 1000206001,
+
+ //@extension("VK_KHR_vulkan_memory_model") // 212
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = 1000211000,
}
enum VkSubpassContents {
@@ -1652,6 +1862,9 @@
//@extension("VK_KHR_external_memory") // 73
VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR = 0xC4641CBD, // -1000072003
+
+ //@extension("VK_EXT_descriptor_indexing") // 162
+ VK_ERROR_FRAGMENTATION_EXT = 0xc462c118, // -1000161000
}
enum VkDynamicState {
@@ -1673,6 +1886,13 @@
//@extension("VK_EXT_sample_locations") // 144
VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT = 1000143000,
+
+ //@extension("VK_NV_shading_rate_image") // 165
+ VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV = 1000164004,
+ VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV = 1000164006,
+
+ //@extension("VK_NV_scissor_exclusive") // 206
+ VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV = 1000205001,
}
enum VkObjectType {
@@ -1735,6 +1955,9 @@
//@extension("VK_EXT_validation_cache") // 161
VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000,
+
+ //@extension("VK_NVX_raytracing") // 166
+ VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NVX = 1000165000,
}
@@ -1773,6 +1996,12 @@
VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = 1,
}
+enum VkVendorId {
+ VK_VENDOR_ID_VIV = 0x10001,
+ VK_VENDOR_ID_VSI = 0x10002,
+ VK_VENDOR_ID_KAZAN = 0x10003,
+}
+
@extension("VK_KHR_surface") // 1
enum VkPresentModeKHR {
VK_PRESENT_MODE_IMMEDIATE_KHR = 0x00000000,
@@ -1850,6 +2079,9 @@
//@extension("VK_KHR_sampler_ycbcr_conversion") // 157
VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = 1000156000,
+
+ //@extension("VK_NVX_raytracing") // 166
+ VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NVX_EXT = 1000165000,
}
@extension("VK_AMD_rasterization_order") // 19
@@ -2000,6 +2232,48 @@
VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT = 1,
}
+@extension("VK_NV_shading_rate_image") // 165
+enum VkShadingRatePaletteEntryNV {
+ VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV = 0,
+ VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV = 1,
+ VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV = 2,
+ VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV = 3,
+ VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV = 4,
+ VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV = 5,
+ VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV = 6,
+ VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV = 7,
+ VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV = 8,
+ VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV = 9,
+ VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV = 10,
+ VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV = 11,
+}
+
+@extension("VK_NV_shading_rate_image") // 165
+enum VkCoarseSampleOrderTypeNV {
+ VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV = 0,
+ VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV = 1,
+ VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV = 2,
+ VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV = 3,
+}
+
+@extension("VK_NVX_raytracing") // 166
+enum VkGeometryTypeNVX {
+ VK_GEOMETRY_TYPE_TRIANGLES_NVX = 0,
+ VK_GEOMETRY_TYPE_AABBS_NVX = 1,
+}
+
+@extension("VK_NVX_raytracing") // 166
+enum VkAccelerationStructureTypeNVX {
+ VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NVX = 0,
+ VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NVX = 1,
+}
+
+@extension("VK_NVX_raytracing") // 166
+enum VkCopyAccelerationStructureModeNVX {
+ VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NVX = 0,
+ VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NVX = 1,
+}
+
@extension("VK_EXT_global_priority") // 175
enum VkQueueGlobalPriorityEXT {
VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT = 128,
@@ -2008,6 +2282,19 @@
VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT = 1024,
}
+@extension("VK_KHR_driver_properties") // 197
+enum VkDriverIdKHR {
+ VK_DRIVER_ID_AMD_PROPRIETARY_KHR = 1,
+ VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR = 2,
+ VK_DRIVER_ID_MESA_RADV_KHR = 3,
+ VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR = 4,
+ VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR = 5,
+ VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR = 6,
+ VK_DRIVER_ID_IMAGINATION_PROPRIETARY_KHR = 7,
+ VK_DRIVER_ID_QUALCOMM_PROPRIETARY_KHR = 8,
+ VK_DRIVER_ID_ARM_PROPRIETARY_KHR = 9,
+}
+
/////////////////
// Bitfields //
/////////////////
@@ -2076,6 +2363,16 @@
//@extension("VK_EXT_blend_operation_advanced") // 149
VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000,
+
+ //@extension("VK_EXT_conditional_rendering") // 82
+ VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000,
+
+ //@extension("VK_NV_shading_rate_image") // 165
+ VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV = 0x00800000,
+
+ //@extension("VK_NVX_raytracing") // 166
+ VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NVX = 0x00200000,
+ VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NVX = 0x00400000,
}
/// Buffer usage flags
@@ -2090,6 +2387,12 @@
VK_BUFFER_USAGE_INDEX_BUFFER_BIT = 0x00000040, /// Can be used as source of fixed function index fetch (index buffer)
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT = 0x00000080, /// Can be used as source of fixed function vertex fetch (VBO)
VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 0x00000100, /// Can be the source of indirect parameters (e.g. indirect buffer, parameter buffer)
+
+ //@extension("VK_EXT_conditional_rendering") // 82
+ VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00000200,
+
+ //@extension("VK_NVX_raytracing") // 166
+ VK_BUFFER_USAGE_RAYTRACING_BIT_NVX = 0x00000400,
}
/// Buffer creation flags
@@ -2115,12 +2418,27 @@
VK_SHADER_STAGE_ALL_GRAPHICS = 0x0000001F,
VK_SHADER_STAGE_ALL = 0x7FFFFFFF,
+
+ //@extension("VK_NVX_raytracing") // 166
+ VK_SHADER_STAGE_RAYGEN_BIT_NVX = 0x00000100,
+ VK_SHADER_STAGE_ANY_HIT_BIT_NVX = 0x00000200,
+ VK_SHADER_STAGE_CLOSEST_HIT_BIT_NVX = 0x00000400,
+ VK_SHADER_STAGE_MISS_BIT_NVX = 0x00000800,
+ VK_SHADER_STAGE_INTERSECTION_BIT_NVX = 0x00001000,
+ VK_SHADER_STAGE_CALLABLE_BIT_NVX = 0x00002000,
+
+ //@extension("VK_NV_mesh_shader") // 203
+ VK_SHADER_STAGE_TASK_BIT_NV = 0x00000040,
+ VK_SHADER_STAGE_MESH_BIT_NV = 0x00000080,
}
/// Descriptor pool create flags
type VkFlags VkDescriptorPoolCreateFlags
bitfield VkDescriptorPoolCreateFlagBits {
VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0x00000001,
+
+ //@extension("VK_EXT_descriptor_indexing") // 162
+ VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT = 0x00000002,
}
/// Descriptor pool reset flags
@@ -2139,6 +2457,9 @@
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020, /// Can be used as framebuffer depth/stencil attachment
VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040, /// Image data not needed outside of rendering
VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080, /// Can be used as framebuffer input attachment
+
+ //@extension("VK_NV_shading_rate_image") // 165
+ VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV = 0x00000100,
}
/// Image creation flags
@@ -2177,6 +2498,9 @@
//@extension("VK_EXT_sample_locations") // 144
VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0x00001000,
+
+ //@extension("VK_NV_corner_sampled_image") // 51
+ VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV = 0x00002000,
}
/// Image view creation flags
@@ -2198,6 +2522,9 @@
//@extension("VK_KHR_device_group") // 61
VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = 0x00000008,
VK_PIPELINE_CREATE_DISPATCH_BASE_KHR = 0x00000010,
+
+ //@extension("VK_NVX_raytracing") // 166
+ VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NVX = 0x00000020,
}
/// Color component flags
@@ -2379,6 +2706,19 @@
//@extension("VK_NVX_device_generated_commands") // 87
VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX = 0x00020000,
+
+ //@extension("VK_EXT_conditional_rendering") // 82
+ VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000,
+
+ //@extension("VK_NV_shading_rate_image") // 165
+ VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV = 0x00400000,
+
+ //@extension("VK_NVX_raytracing") // 166
+ VK_PIPELINE_STAGE_RAYTRACING_BIT_NVX = 0x00200000,
+
+ //@extension("VK_NV_mesh_shader") // 203
+ VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV = 0x00080000,
+ VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV = 0x00100000,
}
/// Render pass attachment description flags
@@ -2476,6 +2816,9 @@
bitfield VkDescriptorSetLayoutCreateFlagBits {
//@extension("VK_KHR_push_descriptor") // 81
VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR = 0x00000001,
+
+ //@extension("VK_EXT_descriptor_indexing") // 162
+ VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT = 0x00000002,
}
/// Pipeline vertex input state creation flags
@@ -2581,6 +2924,9 @@
VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT = 0x00000020,
VK_SUBGROUP_FEATURE_CLUSTERED_BIT = 0x00000040,
VK_SUBGROUP_FEATURE_QUAD_BIT = 0x00000080,
+
+ //@extension("VK_NV_shader_subgroup_partitioned") // 199
+ VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV = 0x00000100,
}
/// Peer memory feature flags
@@ -2899,6 +3245,13 @@
VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR = 0x00000001,
}
+@extension("VK_EXT_conditional_rendering") // 82
+type VkFlags VkConditionalRenderingFlagsEXT
+@extension("VK_EXT_conditional_rendering") // 82
+bitfield VkConditionalRenderingFlagBitsEXT {
+ VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT = 0x00000001,
+}
+
@extension("VK_KHR_descriptor_update_template") // 86
type VkFlags VkDescriptorUpdateTemplateCreateFlagsKHR
//@extension("VK_KHR_descriptor_update_template") // 86
@@ -3034,6 +3387,45 @@
//bitfield VkValidationCacheCreateFlagBitsEXT {
//}
+@extension("VK_EXT_descriptor_indexing") // 162
+type VkFlags VkDescriptorBindingFlagsEXT
+@extension("VK_EXT_descriptor_indexing") // 162
+bitfield VkDescriptorBindingFlagBitsEXT {
+ VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT = 0x00000001,
+ VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT = 0x00000002,
+ VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT = 0x00000004,
+ VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT = 0x00000008,
+}
+
+@extension("VK_NVX_raytracing") // 166
+type VkFlags VkGeometryFlagsNVX
+@extension("VK_NVX_raytracing") // 166
+bitfield VkGeometryFlagBitsNVX {
+ VK_GEOMETRY_OPAQUE_BIT_NVX = 0x00000001,
+ VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NVX = 0x00000002,
+}
+
+@extension("VK_NVX_raytracing") // 166
+type VkFlags VkGeometryInstanceFlagsNVX
+@extension("VK_NVX_raytracing") // 166
+bitfield VkGeometryInstanceFlagBitsNVX {
+ VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NVX = 0x00000001,
+ VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_FLIP_WINDING_BIT_NVX = 0x00000002,
+ VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NVX = 0x00000004,
+ VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NVX = 0x00000008,
+}
+
+@extension("VK_NVX_raytracing") // 166
+type VkFlags VkBuildAccelerationStructureFlagsNVX
+@extension("VK_NVX_raytracing") // 166
+bitfield VkBuildAccelerationStructureFlagBitsNVX {
+ VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NVX = 0x00000001,
+ VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NVX = 0x00000002,
+ VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NVX = 0x00000004,
+ VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NVX = 0x00000008,
+ VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NVX = 0x00000010,
+}
+
//////////////////
// Structures //
//////////////////
@@ -4138,6 +4530,16 @@
u32 z
}
+class VkBaseOutStructure {
+ VkStructureType sType
+ void* pNext
+}
+
+class VkBaseInStructure {
+ VkStructureType sType
+ const void* pNext
+}
+
//@vulkan1_1 structures
class VkPhysicalDeviceSubgroupProperties {
@@ -4985,6 +5387,13 @@
u32[3] computeWorkGroupSize
}
+@extension("VK_NV_corner_sampled_image") // 51
+class VkPhysicalDeviceCornerSampledImageFeaturesNV {
+ VkStructureType sType
+ void* pNext
+ VkBool32 cornerSampledImage
+}
+
@extension("VK_KHR_multiview") // 54
class VkRenderPassMultiviewCreateInfoKHR {
VkStructureType sType
@@ -5203,7 +5612,7 @@
VkStructureType sType
const void* pNext
u32 disabledValidationCheckCount
- VkValidationCheckEXT* pDisabledValidationChecks
+ const VkValidationCheckEXT* pDisabledValidationChecks
}
@extension("VK_NN_vi_surface") // 63
@@ -5214,6 +5623,20 @@
void* window
}
+@extension("VK_EXT_astc_decode_mode") // 68
+class VkImageViewASTCDecodeModeEXT {
+ VkStructureType sType
+ const void* pNext
+ VkFormat decodeMode
+}
+
+@extension("VK_EXT_astc_decode_mode") // 68
+class VkPhysicalDeviceASTCDecodeFeaturesEXT {
+ VkStructureType sType
+ void* pNext
+ VkBool32 decodeModeSharedExponent
+}
+
@extension("VK_KHR_device_group_creation") // 71
class VkPhysicalDeviceGroupPropertiesKHR {
VkStructureType sType
@@ -5455,6 +5878,30 @@
u32 maxPushDescriptors
}
+@extension("VK_EXT_conditional_rendering") // 82
+class VkConditionalRenderingBeginInfoEXT {
+ VkStructureType sType
+ const void* pNext
+ VkBuffer buffer
+ VkDeviceSize offset
+ VkConditionalRenderingFlagsEXT flags
+}
+
+@extension("VK_EXT_conditional_rendering") // 82
+class VkPhysicalDeviceConditionalRenderingFeaturesEXT {
+ VkStructureType sType
+ void* pNext
+ VkBool32 conditionalRendering
+ VkBool32 inheritedConditionalRendering
+}
+
+@extension("VK_EXT_conditional_rendering") // 82
+class VkCommandBufferInheritanceConditionalRenderingInfoEXT {
+ VkStructureType sType
+ const void* pNext
+ VkBool32 conditionalRenderingEnable
+}
+
@extension("VK_KHR_16bit_storage") // 84
class VkPhysicalDevice16BitStorageFeaturesKHR {
VkStructureType sType
@@ -5810,6 +6257,89 @@
f32 maxFrameAverageLightLevel
}
+@extension("VK_KHR_create_renderpass2") // 110
+class VkAttachmentDescription2KHR {
+ VkStructureType sType
+ const void* pNext
+ VkAttachmentDescriptionFlags flags
+ VkFormat format
+ VkSampleCountFlagBits samples
+ VkAttachmentLoadOp loadOp
+ VkAttachmentStoreOp storeOp
+ VkAttachmentLoadOp stencilLoadOp
+ VkAttachmentStoreOp stencilStoreOp
+ VkImageLayout initialLayout
+ VkImageLayout finalLayout
+}
+
+@extension("VK_KHR_create_renderpass2") // 110
+class VkAttachmentReference2KHR {
+ VkStructureType sType
+ const void* pNext
+ u32 attachment
+ VkImageLayout layout
+ VkImageAspectFlags aspectMask
+}
+
+@extension("VK_KHR_create_renderpass2") // 110
+class VkSubpassDescription2KHR {
+ VkStructureType sType
+ const void* pNext
+ VkSubpassDescriptionFlags flags
+ VkPipelineBindPoint pipelineBindPoint
+ u32 viewMask
+ u32 inputAttachmentCount
+ const VkAttachmentReference2KHR* pInputAttachments
+ u32 colorAttachmentCount
+ const VkAttachmentReference2KHR* pColorAttachments
+ const VkAttachmentReference2KHR* pResolveAttachments
+ const VkAttachmentReference2KHR* pDepthStencilAttachment
+ u32 preserveAttachmentCount
+ const u32* pPreserveAttachments
+}
+
+@extension("VK_KHR_create_renderpass2") // 110
+class VkSubpassDependency2KHR {
+ VkStructureType sType
+ const void* pNext
+ u32 srcSubpass
+ u32 dstSubpass
+ VkPipelineStageFlags srcStageMask
+ VkPipelineStageFlags dstStageMask
+ VkAccessFlags srcAccessMask
+ VkAccessFlags dstAccessMask
+ VkDependencyFlags dependencyFlags
+ s32 viewOffset
+}
+
+@extension("VK_KHR_create_renderpass2") // 110
+class VkRenderPassCreateInfo2KHR {
+ VkStructureType sType
+ const void* pNext
+ VkRenderPassCreateFlags flags
+ u32 attachmentCount
+ const VkAttachmentDescription2KHR* pAttachments
+ u32 subpassCount
+ const VkSubpassDescription2KHR* pSubpasses
+ u32 dependencyCount
+ const VkSubpassDependency2KHR* pDependencies
+ u32 correlatedViewMaskCount
+ const u32* pCorrelatedViewMasks
+}
+
+@extension("VK_KHR_create_renderpass2") // 110
+class VkSubpassBeginInfoKHR {
+ VkStructureType sType
+ const void* pNext
+ VkSubpassContents contents
+}
+
+@extension("VK_KHR_create_renderpass2") // 110
+class VkSubpassEndInfoKHR {
+ VkStructureType sType
+ const void* pNext
+}
+
@extension("VK_KHR_shared_presentable_image") // 112
class VkSharedPresentSurfaceCapabilitiesKHR {
VkStructureType sType
@@ -5951,6 +6481,42 @@
VkBool32 variablePointers
}
+@extension("VK_KHR_display_properties2") // 122
+class VkDisplayProperties2KHR {
+ VkStructureType sType
+ void* pNext
+ VkDisplayPropertiesKHR displayProperties
+}
+
+@extension("VK_KHR_display_properties2") // 122
+class VkDisplayPlaneProperties2KHR {
+ VkStructureType sType
+ void* pNext
+ VkDisplayPlanePropertiesKHR displayPlaneProperties
+}
+
+@extension("VK_KHR_display_properties2") // 122
+class VkDisplayModeProperties2KHR {
+ VkStructureType sType
+ void* pNext
+ VkDisplayModePropertiesKHR displayModeProperties
+}
+
+@extension("VK_KHR_display_properties2") // 122
+class VkDisplayPlaneInfo2KHR {
+ VkStructureType sType
+ const void* pNext
+ VkDisplayModeKHR mode
+ u32 planeIndex
+}
+
+@extension("VK_KHR_display_properties2") // 122
+class VkDisplayPlaneCapabilities2KHR {
+ VkStructureType sType
+ void* pNext
+ VkDisplayPlaneCapabilitiesKHR capabilities
+}
+
@extension("VK_MVK_ios_surface") // 123
class VkIOSSurfaceCreateInfoMVK {
VkStructureType sType
@@ -5991,7 +6557,7 @@
u64 objectHandle
const char* pObjectName
}
-
+
@extension("VK_EXT_debug_utils") // 129
class VkDebugUtilsObjectTagInfoEXT {
VkStructureType sType
@@ -6002,7 +6568,7 @@
platform.size_t tagSize
const void* pTag
}
-
+
@extension("VK_EXT_debug_utils") // 129
class VkDebugUtilsLabelEXT {
VkStructureType sType
@@ -6103,6 +6669,40 @@
VkBool32 filterMinmaxImageComponentMapping
}
+@extension("VK_EXT_inline_uniform_block") // 139
+class VkPhysicalDeviceInlineUniformBlockFeaturesEXT {
+ VkStructureType sType
+ void* pNext
+ VkBool32 inlineUniformBlock
+ VkBool32 descriptorBindingInlineUniformBlockUpdateAfterBind
+}
+
+@extension("VK_EXT_inline_uniform_block") // 139
+class VkPhysicalDeviceInlineUniformBlockPropertiesEXT {
+ VkStructureType sType
+ void* pNext
+ u32 maxInlineUniformBlockSize
+ u32 maxPerStageDescriptorInlineUniformBlocks
+ u32 maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks
+ u32 maxDescriptorSetInlineUniformBlocks
+ u32 maxDescriptorSetUpdateAfterBindInlineUniformBlocks
+}
+
+@extension("VK_EXT_inline_uniform_block") // 139
+class VkWriteDescriptorSetInlineUniformBlockEXT {
+ VkStructureType sType
+ const void* pNext
+ u32 dataSize
+ const void* pData
+}
+
+@extension("VK_EXT_inline_uniform_block") // 139
+class VkDescriptorPoolInlineUniformBlockCreateInfoEXT {
+ VkStructureType sType
+ const void* pNext
+ u32 maxInlineUniformBlockBindings
+}
+
@extension("VK_EXT_sample_locations") // 144
class VkSampleLocationEXT {
f32 x
@@ -6341,6 +6941,257 @@
VkValidationCacheEXT validationCache
}
+@extension("VK_EXT_descriptor_indexing") // 162
+class VkDescriptorSetLayoutBindingFlagsCreateInfoEXT {
+ VkStructureType sType
+ const void* pNext
+ u32 bindingCount
+ const VkDescriptorBindingFlagsEXT* pBindingFlags
+}
+
+@extension("VK_EXT_descriptor_indexing") // 162
+class VkPhysicalDeviceDescriptorIndexingFeaturesEXT {
+ VkStructureType sType
+ void* pNext
+ VkBool32 shaderInputAttachmentArrayDynamicIndexing
+ VkBool32 shaderUniformTexelBufferArrayDynamicIndexing
+ VkBool32 shaderStorageTexelBufferArrayDynamicIndexing
+ VkBool32 shaderUniformBufferArrayNonUniformIndexing
+ VkBool32 shaderSampledImageArrayNonUniformIndexing
+ VkBool32 shaderStorageBufferArrayNonUniformIndexing
+ VkBool32 shaderStorageImageArrayNonUniformIndexing
+ VkBool32 shaderInputAttachmentArrayNonUniformIndexing
+ VkBool32 shaderUniformTexelBufferArrayNonUniformIndexing
+ VkBool32 shaderStorageTexelBufferArrayNonUniformIndexing
+ VkBool32 descriptorBindingUniformBufferUpdateAfterBind
+ VkBool32 descriptorBindingSampledImageUpdateAfterBind
+ VkBool32 descriptorBindingStorageImageUpdateAfterBind
+ VkBool32 descriptorBindingStorageBufferUpdateAfterBind
+ VkBool32 descriptorBindingUniformTexelBufferUpdateAfterBind
+ VkBool32 descriptorBindingStorageTexelBufferUpdateAfterBind
+ VkBool32 descriptorBindingUpdateUnusedWhilePending
+ VkBool32 descriptorBindingPartiallyBound
+ VkBool32 descriptorBindingVariableDescriptorCount
+ VkBool32 runtimeDescriptorArray
+}
+
+@extension("VK_EXT_descriptor_indexing") // 162
+class VkPhysicalDeviceDescriptorIndexingPropertiesEXT {
+ VkStructureType sType
+ void* pNext
+ u32 maxUpdateAfterBindDescriptorsInAllPools
+ VkBool32 shaderUniformBufferArrayNonUniformIndexingNative
+ VkBool32 shaderSampledImageArrayNonUniformIndexingNative
+ VkBool32 shaderStorageBufferArrayNonUniformIndexingNative
+ VkBool32 shaderStorageImageArrayNonUniformIndexingNative
+ VkBool32 shaderInputAttachmentArrayNonUniformIndexingNative
+ VkBool32 robustBufferAccessUpdateAfterBind
+ VkBool32 quadDivergentImplicitLod
+ u32 maxPerStageDescriptorUpdateAfterBindSamplers
+ u32 maxPerStageDescriptorUpdateAfterBindUniformBuffers
+ u32 maxPerStageDescriptorUpdateAfterBindStorageBuffers
+ u32 maxPerStageDescriptorUpdateAfterBindSampledImages
+ u32 maxPerStageDescriptorUpdateAfterBindStorageImages
+ u32 maxPerStageDescriptorUpdateAfterBindInputAttachments
+ u32 maxPerStageUpdateAfterBindResources
+ u32 maxDescriptorSetUpdateAfterBindSamplers
+ u32 maxDescriptorSetUpdateAfterBindUniformBuffers
+ u32 maxDescriptorSetUpdateAfterBindUniformBuffersDynamic
+ u32 maxDescriptorSetUpdateAfterBindStorageBuffers
+ u32 maxDescriptorSetUpdateAfterBindStorageBuffersDynamic
+ u32 maxDescriptorSetUpdateAfterBindSampledImages
+ u32 maxDescriptorSetUpdateAfterBindStorageImages
+ u32 maxDescriptorSetUpdateAfterBindInputAttachments
+}
+
+@extension("VK_EXT_descriptor_indexing") // 162
+class VkDescriptorSetVariableDescriptorCountAllocateInfoEXT {
+ VkStructureType sType
+ const void* pNext
+ u32 descriptorSetCount
+ const u32* pDescriptorCounts
+}
+
+@extension("VK_EXT_descriptor_indexing") // 162
+class VkDescriptorSetVariableDescriptorCountLayoutSupportEXT {
+ VkStructureType sType
+ void* pNext
+ u32 maxVariableDescriptorCount
+}
+
+@extension("VK_NV_shading_rate_image") // 165
+class VkShadingRatePaletteNV {
+ u32 shadingRatePaletteEntryCount
+ const VkShadingRatePaletteEntryNV* pShadingRatePaletteEntries
+}
+
+@extension("VK_NV_shading_rate_image") // 165
+class VkPipelineViewportShadingRateImageStateCreateInfoNV {
+ VkStructureType sType
+ const void* pNext
+ VkBool32 shadingRateImageEnable
+ u32 viewportCount
+ const VkShadingRatePaletteNV* pShadingRatePalettes
+}
+
+@extension("VK_NV_shading_rate_image") // 165
+class VkPhysicalDeviceShadingRateImageFeaturesNV {
+ VkStructureType sType
+ void* pNext
+ VkBool32 shadingRateImage
+ VkBool32 shadingRateCoarseSampleOrder
+}
+
+@extension("VK_NV_shading_rate_image") // 165
+class VkPhysicalDeviceShadingRateImagePropertiesNV {
+ VkStructureType sType
+ void* pNext
+ VkExtent2D shadingRateTexelSize
+ u32 shadingRatePaletteSize
+ u32 shadingRateMaxCoarseSamples
+}
+
+@extension("VK_NV_shading_rate_image") // 165
+class VkCoarseSampleLocationNV {
+ u32 pixelX
+ u32 pixelY
+ u32 sample
+}
+
+@extension("VK_NV_shading_rate_image") // 165
+class VkCoarseSampleOrderCustomNV {
+ VkShadingRatePaletteEntryNV shadingRate
+ u32 sampleCount
+ u32 sampleLocationCount
+ const VkCoarseSampleLocationNV* pSampleLocations
+}
+
+@extension("VK_NV_shading_rate_image") // 165
+class VkPipelineViewportCoarseSampleOrderStateCreateInfoNV {
+ VkStructureType sType
+ const void* pNext
+ VkCoarseSampleOrderTypeNV sampleOrderType
+ u32 customSampleOrderCount
+ const VkCoarseSampleOrderCustomNV* pCustomSampleOrders
+}
+
+@extension("VK_NVX_raytracing") // 166
+class VkRaytracingPipelineCreateInfoNVX {
+ VkStructureType sType
+ const void* pNext
+ VkPipelineCreateFlags flags
+ u32 stageCount
+ const VkPipelineShaderStageCreateInfo* pStages
+ const u32* pGroupNumbers
+ u32 maxRecursionDepth
+ VkPipelineLayout layout
+ VkPipeline basePipelineHandle
+ s32 basePipelineIndex
+}
+
+@extension("VK_NVX_raytracing") // 166
+class VkGeometryTrianglesNVX {
+ VkStructureType sType
+ const void* pNext
+ VkBuffer vertexData
+ VkDeviceSize vertexOffset
+ u32 vertexCount
+ VkDeviceSize vertexStride
+ VkFormat vertexFormat
+ VkBuffer indexData
+ VkDeviceSize indexOffset
+ u32 indexCount
+ VkIndexType indexType
+ VkBuffer transformData
+ VkDeviceSize transformOffset
+}
+
+@extension("VK_NVX_raytracing") // 166
+class VkGeometryAABBNVX {
+ VkStructureType sType
+ const void* pNext
+ VkBuffer aabbData
+ u32 numAABBs
+ u32 stride
+ VkDeviceSize offset
+}
+
+@extension("VK_NVX_raytracing") // 166
+class VkGeometryDataNVX {
+ VkGeometryTrianglesNVX triangles
+ VkGeometryAABBNVX aabbs
+}
+
+@extension("VK_NVX_raytracing") // 166
+class VkGeometryNVX {
+ VkStructureType sType
+ const void* pNext
+ VkGeometryTypeNVX geometryType
+ VkGeometryDataNVX geometry
+ VkGeometryFlagsNVX flags
+}
+
+@extension("VK_NVX_raytracing") // 166
+class VkAccelerationStructureCreateInfoNVX {
+ VkStructureType sType
+ const void* pNext
+ VkAccelerationStructureTypeNVX type
+ VkBuildAccelerationStructureFlagsNVX flags
+ VkDeviceSize compactedSize
+ u32 instanceCount
+ u32 geometryCount
+ const VkGeometryNVX* pGeometries
+}
+
+@extension("VK_NVX_raytracing") // 166
+class VkBindAccelerationStructureMemoryInfoNVX {
+ VkStructureType sType
+ const void* pNext
+ VkAccelerationStructureNVX accelerationStructure
+ VkDeviceMemory memory
+ VkDeviceSize memoryOffset
+ u32 deviceIndexCount
+ const u32* pDeviceIndices
+}
+
+@extension("VK_NVX_raytracing") // 166
+class VkDescriptorAccelerationStructureInfoNVX {
+ VkStructureType sType
+ const void* pNext
+ u32 accelerationStructureCount
+ const VkAccelerationStructureNVX* pAccelerationStructures
+}
+
+@extension("VK_NVX_raytracing") // 166
+class VkAccelerationStructureMemoryRequirementsInfoNVX {
+ VkStructureType sType
+ const void* pNext
+ VkAccelerationStructureNVX accelerationStructure
+}
+
+@extension("VK_NVX_raytracing") // 166
+class VkPhysicalDeviceRaytracingPropertiesNVX {
+ VkStructureType sType
+ void* pNext
+ u32 shaderHeaderSize
+ u32 maxRecursionDepth
+ u32 maxGeometryCount
+}
+
+@extension("VK_NV_representative_fragment_test") // 167
+class VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV {
+ VkStructureType sType
+ void* pNext
+ VkBool32 representativeFragmentTest
+}
+
+@extension("VK_NV_representative_fragment_test") // 167
+class VkPipelineRepresentativeFragmentTestStateCreateInfoNV {
+ VkStructureType sType
+ const void* pNext
+ VkBool32 representativeFragmentTestEnable
+}
+
@extension("VK_KHR_maintenance3") // 169
class VkPhysicalDeviceMaintenance3PropertiesKHR {
VkStructureType sType
@@ -6363,6 +7214,15 @@
VkQueueGlobalPriorityEXT globalPriority
}
+@extension("VK_KHR_8bit_storage") // 178
+class VkPhysicalDevice8BitStorageFeaturesKHR {
+ VkStructureType sType
+ void* pNext
+ VkBool32 storageBuffer8BitAccess
+ VkBool32 uniformAndStorageBuffer8BitAccess
+ VkBool32 storagePushConstant8
+}
+
@extension("VK_EXT_external_memory_host") // 179
class VkImportMemoryHostPointerInfoEXT {
VkStructureType sType
@@ -6385,6 +7245,174 @@
VkDeviceSize minImportedHostPointerAlignment
}
+@extension("VK_KHR_shader_atomic_int64") // 181
+class VkPhysicalDeviceShaderAtomicInt64FeaturesKHR {
+ VkStructureType sType
+ void* pNext
+ VkBool32 shaderBufferInt64Atomics
+ VkBool32 shaderSharedInt64Atomics
+}
+
+@extension("VK_AMD_shader_core_properties") // 186
+class VkPhysicalDeviceShaderCorePropertiesAMD {
+ VkStructureType sType
+ void* pNext
+ u32 shaderEngineCount
+ u32 shaderArraysPerEngineCount
+ u32 computeUnitsPerShaderArray
+ u32 simdPerComputeUnit
+ u32 wavefrontsPerSimd
+ u32 wavefrontSize
+ u32 sgprsPerSimd
+ u32 minSgprAllocation
+ u32 maxSgprAllocation
+ u32 sgprAllocationGranularity
+ u32 vgprsPerSimd
+ u32 minVgprAllocation
+ u32 maxVgprAllocation
+ u32 vgprAllocationGranularity
+}
+
+@extension("VK_EXT_vertex_attribute_divisor") // 191
+class VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT {
+ VkStructureType sType
+ void* pNext
+ u32 maxVertexAttribDivisor
+}
+
+@extension("VK_EXT_vertex_attribute_divisor") // 191
+class VkVertexInputBindingDivisorDescriptionEXT {
+ u32 binding
+ u32 divisor
+}
+
+@extension("VK_EXT_vertex_attribute_divisor") // 191
+class VkPipelineVertexInputDivisorStateCreateInfoEXT {
+ VkStructureType sType
+ const void* pNext
+ u32 vertexBindingDivisorCount
+ const VkVertexInputBindingDivisorDescriptionEXT* pVertexBindingDivisors
+}
+
+@extension("VK_EXT_vertex_attribute_divisor") // 191
+class VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT {
+ VkStructureType sType
+ void* pNext
+ VkBool32 vertexAttributeInstanceRateDivisor
+ VkBool32 vertexAttributeInstanceRateZeroDivisor
+}
+
+@extension("VK_KHR_driver_properties") // 197
+class VkConformanceVersionKHR {
+ u8 major
+ u8 minor
+ u8 subminor
+ u8 patch
+}
+
+@extension("VK_KHR_driver_properties") // 197
+class VkPhysicalDeviceDriverPropertiesKHR {
+ VkStructureType sType
+ void* pNext
+ u32 driverID
+ char[VK_MAX_DRIVER_NAME_SIZE_KHR] driverName
+ char[VK_MAX_DRIVER_INFO_SIZE_KHR] driverInfo
+ VkConformanceVersionKHR conformanceVersion
+}
+
+@extension("VK_NV_compute_shader_derivatives") // 202
+class VkPhysicalDeviceComputeShaderDerivativesFeaturesNV {
+ VkStructureType sType
+ void* pNext
+ VkBool32 computeDerivativeGroupQuads
+ VkBool32 computeDerivativeGroupLinear
+}
+
+@extension("VK_NV_mesh_shader") // 203
+class VkPhysicalDeviceMeshShaderFeaturesNV {
+ VkStructureType sType
+ void* pNext
+ VkBool32 taskShader
+ VkBool32 meshShader
+}
+
+@extension("VK_NV_mesh_shader") // 203
+class VkPhysicalDeviceMeshShaderPropertiesNV {
+ VkStructureType sType
+ void* pNext
+ u32 maxDrawMeshTasksCount
+ u32 maxTaskWorkGroupInvocations
+ u32[3] maxTaskWorkGroupSize
+ u32 maxTaskTotalMemorySize
+ u32 maxTaskOutputCount
+ u32 maxMeshWorkGroupInvocations
+ u32[3] maxMeshWorkGroupSize
+ u32 maxMeshTotalMemorySize
+ u32 maxMeshOutputVertices
+ u32 maxMeshOutputPrimitives
+ u32 maxMeshMultiviewViewCount
+ u32 meshOutputPerVertexGranularity
+ u32 meshOutputPerPrimitiveGranularity
+}
+
+@extension("VK_NV_mesh_shader") // 203
+class VkDrawMeshTasksIndirectCommandNV {
+ u32 taskCount
+ u32 firstTask
+}
+
+@extension("VK_NV_fragment_shader_barycentric") // 204
+class VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV {
+ VkStructureType sType
+ void* pNext
+ VkBool32 fragmentShaderBarycentric
+}
+
+@extension("VK_NV_shader_image_footprint") // 205
+class VkPhysicalDeviceShaderImageFootprintFeaturesNV {
+ VkStructureType sType
+ void* pNext
+ VkBool32 imageFootprint
+}
+
+@extension("VK_NV_scissor_exclusive") // 206
+class VkPipelineViewportExclusiveScissorStateCreateInfoNV {
+ VkStructureType sType
+ const void* pNext
+ u32 exclusiveScissorCount
+ const VkRect2D* pExclusiveScissors
+}
+
+@extension("VK_NV_scissor_exclusive") // 206
+class VkPhysicalDeviceExclusiveScissorFeaturesNV {
+ VkStructureType sType
+ void* pNext
+ VkBool32 exclusiveScissor
+}
+
+@extension("VK_NV_device_diagnostic_checkpoints") // 207
+class VkQueueFamilyCheckpointPropertiesNV {
+ VkStructureType sType
+ void* pNext
+ VkPipelineStageFlags checkpointExecutionStageMask
+}
+
+@extension("VK_NV_device_diagnostic_checkpoints") // 207
+class VkCheckpointDataNV {
+ VkStructureType sType
+ void* pNext
+ VkPipelineStageFlagBits stage
+ void* pCheckpointMarker
+}
+
+@extension("VK_KHR_vulkan_memory_model") // 212
+class VkPhysicalDeviceVulkanMemoryModelFeaturesKHR {
+ VkStructureType sType
+ void* pNext
+ VkBool32 vulkanMemoryModel
+ VkBool32 vulkanMemoryModelDeviceScope
+}
+
////////////////
// Commands //
@@ -9563,6 +10591,17 @@
const VkWriteDescriptorSet* pDescriptorWrites) {
}
+@extension("VK_EXT_conditional_rendering") // 82
+cmd void vkCmdBeginConditionalRenderingEXT(
+ VkCommandBuffer commandBuffer,
+ const VkConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin) {
+}
+
+@extension("VK_EXT_conditional_rendering") // 82
+cmd void vkCmdEndConditionalRenderingEXT(
+ VkCommandBuffer commandBuffer) {
+}
+
@extension("VK_KHR_descriptor_update_template") // 86
cmd VkResult vkCreateDescriptorUpdateTemplateKHR(
VkDevice device,
@@ -9782,6 +10821,35 @@
const VkHdrMetadataEXT* pMetadata) {
}
+@extension("VK_KHR_create_renderpass2") // 110
+cmd VkResult vkCreateRenderPass2KHR(
+ VkDevice device,
+ const VkRenderPassCreateInfo2KHR* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkRenderPass* pRenderPass) {
+ return ?
+}
+
+@extension("VK_KHR_create_renderpass2") // 110
+cmd void vkCmdBeginRenderPass2KHR(
+ VkCommandBuffer commandBuffer,
+ const VkRenderPassBeginInfo* pRenderPassBegin,
+ const VkSubpassBeginInfoKHR* pSubpassBeginInfo) {
+}
+
+@extension("VK_KHR_create_renderpass2") // 110
+cmd void vkCmdNextSubpass2KHR(
+ VkCommandBuffer commandBuffer,
+ const VkSubpassBeginInfoKHR* pSubpassBeginInfo,
+ const VkSubpassEndInfoKHR* pSubpassEndInfo) {
+}
+
+@extension("VK_KHR_create_renderpass2") // 110
+cmd void vkCmdEndRenderPass2KHR(
+ VkCommandBuffer commandBuffer,
+ const VkSubpassEndInfoKHR* pSubpassEndInfo) {
+}
+
@extension("VK_KHR_shared_presentable_image") // 112
cmd VkResult vkGetSwapchainStatusKHR(
VkDevice device,
@@ -9843,6 +10911,39 @@
return ?
}
+@extension("VK_KHR_display_properties2") // 122
+cmd VkResult vkGetPhysicalDeviceDisplayProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ u32* pPropertyCount,
+ VkDisplayProperties2KHR* pProperties) {
+ return ?
+}
+
+@extension("VK_KHR_display_properties2") // 122
+cmd VkResult vkGetPhysicalDeviceDisplayPlaneProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ u32* pPropertyCount,
+ VkDisplayPlaneProperties2KHR* pProperties) {
+ return ?
+}
+
+@extension("VK_KHR_display_properties2") // 122
+cmd VkResult vkGetDisplayModeProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ VkDisplayKHR display,
+ u32* pPropertyCount,
+ VkDisplayModeProperties2KHR* pProperties) {
+ return ?
+}
+
+@extension("VK_KHR_display_properties2") // 122
+cmd VkResult vkGetDisplayPlaneCapabilities2KHR(
+ VkPhysicalDevice physicalDevice,
+ const VkDisplayPlaneInfo2KHR* pDisplayPlaneInfo,
+ VkDisplayPlaneCapabilities2KHR* pCapabilities) {
+ return ?
+}
+
@extension("VK_MVK_ios_surface") // 123
cmd VkResult vkCreateIOSSurfaceMVK(
VkInstance instance,
@@ -9878,36 +10979,36 @@
const VkDebugUtilsObjectNameInfoEXT* pNameInfo) {
return ?
}
-
+
@extension("VK_EXT_debug_utils") // 129
cmd VkResult vkSetDebugUtilsObjectTagEXT(
VkDevice device,
const VkDebugUtilsObjectTagInfoEXT* pTagInfo) {
return ?
}
-
+
@extension("VK_EXT_debug_utils") // 129
cmd void vkQueueBeginDebugUtilsLabelEXT(
VkQueue queue,
const VkDebugUtilsLabelEXT* pLabelInfo) {
}
-
+
@extension("VK_EXT_debug_utils") // 129
cmd void vkQueueEndDebugUtilsLabelEXT(VkQueue queue) {
}
-
+
@extension("VK_EXT_debug_utils") // 129
cmd void vkQueueInsertDebugUtilsLabelEXT(
VkQueue queue,
const VkDebugUtilsLabelEXT* pLabelInfo) {
}
-
+
@extension("VK_EXT_debug_utils") // 129
cmd void vkCmdBeginDebugUtilsLabelEXT(
VkCommandBuffer commandBuffer,
const VkDebugUtilsLabelEXT* pLabelInfo) {
}
-
+
@extension("VK_EXT_debug_utils") // 129
cmd void vkCmdEndDebugUtilsLabelEXT(VkCommandBuffer commandBuffer) {
}
@@ -10061,6 +11162,155 @@
return ?
}
+@extension("VK_NV_shading_rate_image") // 165
+cmd void vkCmdBindShadingRateImageNV(
+ VkCommandBuffer commandBuffer,
+ VkImageView imageView,
+ VkImageLayout imageLayout) {
+}
+
+@extension("VK_NV_shading_rate_image") // 165
+cmd void vkCmdSetViewportShadingRatePaletteNV(
+ VkCommandBuffer commandBuffer,
+ u32 firstViewport,
+ u32 viewportCount,
+ const VkShadingRatePaletteNV* pShadingRatePalettes) {
+}
+
+@extension("VK_NV_shading_rate_image") // 165
+cmd void vkCmdSetCoarseSampleOrderNV(
+ VkCommandBuffer commandBuffer,
+ VkCoarseSampleOrderTypeNV sampleOrderType,
+ u32 customSampleOrderCount,
+ const VkCoarseSampleOrderCustomNV* pCustomSampleOrders) {
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd VkResult vkCreateAccelerationStructureNVX(
+ VkDevice device,
+ const VkAccelerationStructureCreateInfoNVX* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkAccelerationStructureNVX* pAccelerationStructure) {
+ return ?
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd void vkDestroyAccelerationStructureNVX(
+ VkDevice device,
+ VkAccelerationStructureNVX accelerationStructure,
+ const VkAllocationCallbacks* pAllocator) {
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd void vkGetAccelerationStructureMemoryRequirementsNVX(
+ VkDevice device,
+ const VkAccelerationStructureMemoryRequirementsInfoNVX* pInfo,
+ VkMemoryRequirements2KHR* pMemoryRequirements) {
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd void vkGetAccelerationStructureScratchMemoryRequirementsNVX(
+ VkDevice device,
+ const VkAccelerationStructureMemoryRequirementsInfoNVX* pInfo,
+ VkMemoryRequirements2KHR* pMemoryRequirements) {
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd VkResult vkBindAccelerationStructureMemoryNVX(
+ VkDevice device,
+ u32 bindInfoCount,
+ const VkBindAccelerationStructureMemoryInfoNVX* pBindInfos) {
+ return ?
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd void vkCmdBuildAccelerationStructureNVX(
+ VkCommandBuffer commandBuffer,
+ VkAccelerationStructureTypeNVX type,
+ u32 instanceCount,
+ VkBuffer instanceData,
+ VkDeviceSize instanceOffset,
+ u32 geometryCount,
+ const VkGeometryNVX* pGeometries,
+ VkBuildAccelerationStructureFlagsNVX flags,
+ VkBool32 update,
+ VkAccelerationStructureNVX dst,
+ VkAccelerationStructureNVX src,
+ VkBuffer scratch,
+ VkDeviceSize scratchOffset) {
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd void vkCmdCopyAccelerationStructureNVX(
+ VkCommandBuffer commandBuffer,
+ VkAccelerationStructureNVX dst,
+ VkAccelerationStructureNVX src,
+ VkCopyAccelerationStructureModeNVX mode) {
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd void vkCmdTraceRaysNVX(
+ VkCommandBuffer commandBuffer,
+ VkBuffer raygenShaderBindingTableBuffer,
+ VkDeviceSize raygenShaderBindingOffset,
+ VkBuffer missShaderBindingTableBuffer,
+ VkDeviceSize missShaderBindingOffset,
+ VkDeviceSize missShaderBindingStride,
+ VkBuffer hitShaderBindingTableBuffer,
+ VkDeviceSize hitShaderBindingOffset,
+ VkDeviceSize hitShaderBindingStride,
+ u32 width,
+ u32 height) {
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd VkResult vkCreateRaytracingPipelinesNVX(
+ VkDevice device,
+ VkPipelineCache pipelineCache,
+ u32 createInfoCount,
+ const VkRaytracingPipelineCreateInfoNVX* pCreateInfos,
+ const VkAllocationCallbacks* pAllocator,
+ VkPipeline* pPipelines) {
+ return ?
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd VkResult vkGetRaytracingShaderHandlesNVX(
+ VkDevice device,
+ VkPipeline pipeline,
+ u32 firstGroup,
+ u32 groupCount,
+ platform.size_t dataSize,
+ void* pData) {
+ return ?
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd VkResult vkGetAccelerationStructureHandleNVX(
+ VkDevice device,
+ VkAccelerationStructureNVX accelerationStructure,
+ platform.size_t dataSize,
+ void* pData) {
+ return ?
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd void vkCmdWriteAccelerationStructurePropertiesNVX(
+ VkCommandBuffer commandBuffer,
+ VkAccelerationStructureNVX accelerationStructure,
+ VkQueryType queryType,
+ VkQueryPool queryPool,
+ u32 query) {
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd VkResult vkCompileDeferredNVX(
+ VkDevice device,
+ VkPipeline pipeline,
+ u32 shader) {
+ return ?
+}
+
@extension("VK_KHR_maintenance3") // 169
cmd void vkGetDescriptorSetLayoutSupportKHR(
VkDevice device,
@@ -10068,6 +11318,28 @@
VkDescriptorSetLayoutSupportKHR* pSupport) {
}
+@extension("VK_KHR_draw_indirect_count") // 170
+cmd void vkCmdDrawIndirectCountKHR(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ VkBuffer countBuffer,
+ VkDeviceSize countBufferOffset,
+ u32 maxDrawCount,
+ u32 stride) {
+}
+
+@extension("VK_KHR_draw_indirect_count") // 170
+cmd void vkCmdDrawIndexedIndirectCountKHR(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ VkBuffer countBuffer,
+ VkDeviceSize countBufferOffset,
+ u32 maxDrawCount,
+ u32 stride) {
+}
+
@extension("VK_EXT_external_memory_host") // 179
cmd VkResult vkGetMemoryHostPointerPropertiesEXT(
VkDevice device,
@@ -10077,6 +11349,64 @@
return ?
}
+@extension("VK_AMD_buffer_marker") // 180
+cmd void vkCmdWriteBufferMarkerAMD(
+ VkCommandBuffer commandBuffer,
+ VkPipelineStageFlagBits pipelineStage,
+ VkBuffer dstBuffer,
+ VkDeviceSize dstOffset,
+ u32 marker) {
+}
+
+@extension("VK_NV_mesh_shader") // 203
+cmd void vkCmdDrawMeshTasksNV(
+ VkCommandBuffer commandBuffer,
+ u32 taskCount,
+ u32 firstTask) {
+}
+
+@extension("VK_NV_mesh_shader") // 203
+cmd void vkCmdDrawMeshTasksIndirectNV(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ u32 drawCount,
+ u32 stride) {
+}
+
+@extension("VK_NV_mesh_shader") // 203
+cmd void vkCmdDrawMeshTasksIndirectCountNV(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ VkBuffer countBuffer,
+ VkDeviceSize countBufferOffset,
+ u32 maxDrawCount,
+ u32 stride) {
+}
+
+@extension("VK_NV_scissor_exclusive") // 206
+cmd void vkCmdSetExclusiveScissorNV(
+ VkCommandBuffer commandBuffer,
+ u32 firstExclusiveScissor,
+ u32 exclusiveScissorCount,
+ const VkRect2D* pExclusiveScissors) {
+}
+
+@extension("VK_NV_device_diagnostic_checkpoints") // 207
+cmd void vkCmdSetCheckpointNV(
+ VkCommandBuffer commandBuffer,
+ const void* pCheckpointMarker) {
+}
+
+@extension("VK_NV_device_diagnostic_checkpoints") // 207
+cmd void vkGetQueueCheckpointDataNV(
+ VkQueue queue,
+ u32* pCheckpointDataCount,
+ VkCheckpointDataNV* pCheckpointData) {
+}
+
+
////////////////
// Validation //
////////////////
diff --git a/vulkan/doc/README b/vulkan/doc/README
new file mode 100644
index 0000000..d1dc2e1
--- /dev/null
+++ b/vulkan/doc/README
@@ -0,0 +1,2 @@
+The former contents of implementors_guide/ are now at
+https://source.android.com/devices/graphics/implement-vulkan
diff --git a/vulkan/doc/implementors_guide/implementors_guide-docinfo.adoc b/vulkan/doc/implementors_guide/implementors_guide-docinfo.adoc
deleted file mode 100644
index 69b8c61..0000000
--- a/vulkan/doc/implementors_guide/implementors_guide-docinfo.adoc
+++ /dev/null
@@ -1,23 +0,0 @@
-<style type="text/css">
-
-code,div.listingblock {
- max-width: 68em;
-}
-
-p {
- max-width: 50em;
-}
-
-table {
- max-width: 50em;
-}
-
-table.tableblock {
- border-width: 1px;
-}
-
-h2 {
- max-width: 35em;
-}
-
-</style>
diff --git a/vulkan/doc/implementors_guide/implementors_guide.adoc b/vulkan/doc/implementors_guide/implementors_guide.adoc
deleted file mode 100644
index 24af950..0000000
--- a/vulkan/doc/implementors_guide/implementors_guide.adoc
+++ /dev/null
@@ -1,209 +0,0 @@
-// asciidoc -b html5 -d book -f implementors_guide.conf implementors_guide.adoc
-= Vulkan on Android Implementor's Guide =
-:toc: right
-:numbered:
-:revnumber: 5
-
-This document is intended for GPU IHVs writing Vulkan drivers for Android, and OEMs integrating them for specific devices. It describes how a Vulkan driver interacts with the system, how GPU-specific tools should be installed, and Android-specific requirements.
-
-== Architecture ==
-
-The primary interface between Vulkan applications and a device's Vulkan driver is the loader, which is part of AOSP and installed at +/system/lib[64]/libvulkan.so+. The loader provides the core Vulkan API entry points, as well as entry points of a few extensions that are required on Android and always present. In particular, the window system integration (WSI) extensions are exported by the loader and primarily implemented in it rather than the driver. The loader also supports enumerating and loading layers which can expose additional extensions and/or intercept core API calls on their way to the driver.
-
-The NDK will include a stub +libvulkan.so+ exporting the same symbols as the loader. Calling the Vulkan functions exported from +libvulkan.so+ will enter trampoline functions in the loader which will dispatch to the appropriate layer or driver based on their first argument. The +vkGet*ProcAddr+ calls will return the function pointers that the trampolines would dispatch to, so calling through these function pointers rather than the exported symbols will be slightly more efficient since it skips the trampoline and dispatch.
-
-=== Driver Enumeration and Loading ===
-
-Android expects the GPUs available to the system to be known when the system image is built, so its driver enumeration process isn't as elaborate as on other platforms. The loader will use the existing HAL mechanism for discovering and loading the driver. As of this writing, the preferred paths for 32-bit and 64-bit Vulkan drivers are:
-
- /vendor/lib/hw/vulkan.<ro.product.platform>.so
- /vendor/lib64/hw/vulkan.<ro.product.platform>.so
-
-where +<ro.product.platform>+ is replaced by the value of the system property of that name. See https://android.googlesource.com/platform/hardware/libhardware/+/master/hardware.c[libhardware/hardware.c] for details and supported alternative locations.
-
-The Vulkan +hw_module_t+ derivative is currently trivial. If support for multiple drivers is ever added, the HAL module will export a list of strings that can be passed to the module +open+ call. For the time being, only one driver is supported, and the constant string +HWVULKAN_DEVICE_0+ is passed to +open+.
-
-The Vulkan +hw_device_t+ derivative corresponds to a single driver, though that driver can support multiple Vulkan physical devices. The +hw_device_t+ structure contains a function pointer for the +vkGetInstanceProcAddr+ function. The loader finds all other driver Vulkan functions by calling that +vkGetInstanceProcAddr+ function.
-
-=== Layer Discovery and Loading ===
-
-Android's security model and policies differ significantly from other platforms. In particular, Android does not allow loading external code into a non-debuggable process on production (non-rooted) devices, nor does it allow external code to inspect or control the process's memory/state/etc. This includes a prohibition on saving core dumps, API traces, etc. to disk for later inspection. So only layers delivered as part of the application will be enabled on production devices, and drivers must also not provide functionality that violates these policies.
-
-There are three major use cases for layers:
-
-1. Development-time layers: validation layers, shims for tracing/profiling/debugging tools, etc. These shouldn't be installed on the system image of production devices: they would be a waste of space for most users, and they should be updateable without requiring a system update. A developer wishing to use one of these during development has the ability to modify their application package (e.g. adding a file to their native libraries directory). IHV and OEM engineers who are trying to diagnose failures in shipping, unmodifiable apps are assumed to have access to non-production (rooted) builds of the system image.
-
-2. Utility layers, such as a layer that implements a heap for device memory. These layers will almost always expose extensions. Developers choose which layers, and which versions of those layers, to use in their application; different applications that use the same layer may still use different versions. Developers will choose which of these layers to ship in their application package.
-
-3. Injected layers, like framerate, social network, or game launcher overlays, which are provided by the user or some other application without the application's knowledge or consent. These violate Android's security policies and will not be supported.
-
-In the normal state the loader will only search in the application's normal library search path (as defined by the system ClassLoader) for layers. It will attempt to load any shared library named +libVkLayer_*.so+ as a layer library. Android does not use manifests to describe layers: because layers must have been deliberately included in the application by the developer, the motivation for manifests on other platforms don't apply.
-
-On debuggable devices (+ro.debuggable+ property exists and is non-zero, generally rooted or engineering builds) the loader will also search the directory +/data/local/debug/vulkan+ and attempt to load layer libraries it finds there. This directory doesn't exist by default. On Android N and later, because this location is writable by adb, SELinux policies prevent mapping code located here as executable. So to use layers from here, SELinux enforcement must be disabled: +adb shell setenforce 0+. This mechanism is not intended for application developers, only for IHV and OEM engineers working on test devices that don't have private or sensitive data.
-
-Our goal is to allow layers to be ported with only build-environment changes between Android and other platforms. For this to work, layers must properly implement things like +vkGetInstanceLayerProperties+ and +vkGetInstanceExtensionProperties+, even though the LunarG loader doesn't use them (it gets the information from manifests instead).
-
-== Window System Integration ==
-
-The +vk_wsi_swapchin+ and +vk_wsi_device_swapchain+ extensions are primarily be implemented by the platform and live in +libvulkan.so+. The +VkSwapchain+ object and all interaction with +ANativeWindow+ will be handled by the platform and not exposed to drivers. The WSI implementation will rely on a few private interfaces to the driver for this implementation. These will be loaded through the driver's +vkGetDeviceProcAddr+ functions, after passing through any enabled layers.
-
-Implementations may need swapchain buffers to be allocated with implementation-defined private gralloc usage flags that depend not only on +format+ and +imageUsage+, but also on the intended usage of the swapchain. The swapchain usage bits are defined as
-[source,c]
-----
-typedef enum VkSwapchainImageUsageFlagBitsANDROID {
- VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID = 0x00000001,
- VK_SWAPCHAIN_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkSwapchainImageUsageFlagBitsANDROID;
-typedef VkFlags VkSwapchainImageUsageFlagsANDROID;
-----
-
-Implementations may need swapchain buffers to be allocated with implementation-defined private gralloc usage flags. When creating a swapchain, the platform will ask the driver to translate the requested format and image usage flags into gralloc usage flags by calling
-[source,c]
-----
-VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainGrallocUsage2ANDROID(
- VkDevice device,
- VkFormat format,
- VkImageUsageFlags imageUsage,
- VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,
- uint64_t* grallocConsumerUsage,
- uint64_t* grallocProducerUsage,
-);
-----
-The +format+ and +imageUsage+ parameters are taken from the +VkSwapchainCreateInfoKHR+ structure. The driver should fill +*grallocConsumerUsage+ and +*grallocProducerUsage+ with the gralloc usage flags it requires for that format and usage. These will be combined with the usage flags requested by the swapchain consumer when allocating buffers.
-
-An older version of this function is deprecated but still supported for backwards compatibility; it will be used if +vkGetSwapchainGrallocUsage2ANDROID+ is not supported:
-[source,c]
-----
-VkResult VKAPI vkGetSwapchainGrallocUsageANDROID(
- VkDevice device,
- VkFormat format,
- VkImageUsageFlags imageUsage,
- int* grallocUsage
-);
-----
-
-+VkNativeBufferANDROID+ is a +vkCreateImage+ extension structure for creating an image backed by a gralloc buffer. This structure is provided to +vkCreateImage+ in the +VkImageCreateInfo+ structure chain. Calls to +vkCreateImage+ with this structure will happen during the first call to +vkGetSwapChainInfoWSI(.. VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI ..)+. The WSI implementation will allocate the number of native buffers requested for the swapchain, then create a +VkImage+ for each one.
-
-[source,c]
-----
-typedef struct {
- VkStructureType sType; // must be VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID
- const void* pNext;
-
- // Buffer handle and stride returned from gralloc alloc()
- buffer_handle_t handle;
- int stride;
-
- // Gralloc format and usage requested when the buffer was allocated.
- int format;
- int usage; // deprecated
- struct {
- uint64_t consumer;
- uint64_t producer;
- } usage2;
-} VkNativeBufferANDROID;
-----
-
-When creating a gralloc-backed image, the +VkImageCreateInfo+ will have:
-[source,txt]
-----
- .imageType = VK_IMAGE_TYPE_2D
- .format = a VkFormat matching the format requested for the gralloc buffer
- .extent = the 2D dimensions requested for the gralloc buffer
- .mipLevels = 1
- .arraySize = 1
- .samples = 1
- .tiling = VK_IMAGE_TILING_OPTIMAL
- .usage = VkSwapChainCreateInfoWSI::imageUsageFlags
- .flags = 0
- .sharingMode = VkSwapChainCreateInfoWSI::sharingMode
- .queueFamilyCount = VkSwapChainCreateInfoWSI::queueFamilyCount
- .pQueueFamilyIndices = VkSwapChainCreateInfoWSI::pQueueFamilyIndices
-----
-
-Additionally, when any swapchain image usage flags are required for the swapchain, the platform will provide a +VkSwapchainImageCreateInfoANDROID+ extension structure in the +VkImageCreateInfo+ chain provided to +vkCreateImage+, containing the swapchain image usage flags:
-[source,c]
-----
-typedef struct {
- VkStructureType sType; // must be VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID
- const void* pNext;
-
- VkSwapchainImageUsageFlagsANDROID usage;
-} VkSwapchainImageCreateInfoANDROID;
-----
-
-+vkAcquireImageANDROID+ acquires ownership of a swapchain image and imports an
-externally-signalled native fence into both an existing VkSemaphore object
-and an existing VkFence object:
-
-[source,c]
-----
-VkResult VKAPI vkAcquireImageANDROID(
- VkDevice device,
- VkImage image,
- int nativeFenceFd,
- VkSemaphore semaphore,
- VkFence fence
-);
-----
-
-This function is called during +vkAcquireNextImageWSI+ to import a native
-fence into the +VkSemaphore+ and +VkFence+ objects provided by the
-application. Both semaphore and fence objects are optional in this call. The
-driver may also use this opportunity to recognize and handle any external
-changes to the gralloc buffer state; many drivers won't need to do anything
-here. This call puts the +VkSemaphore+ and +VkFence+ into the same "pending"
-state as +vkQueueSignalSemaphore+ and +vkQueueSubmit+ respectively, so queues
-can wait on the semaphore and the application can wait on the fence. Both
-objects become signalled when the underlying native fence signals; if the
-native fence has already signalled, then the semaphore will be in the signalled
-state when this function returns. The driver takes ownership of the fence fd
-and is responsible for closing it when no longer needed. It must do so even if
-neither a semaphore or fence object is provided, or even if
-+vkAcquireImageANDROID+ fails and returns an error. If +fenceFd+ is -1, it
-is as if the native fence was already signalled.
-
-+vkQueueSignalReleaseImageANDROID+ prepares a swapchain image for external use, and creates a native fence and schedules it to be signalled when prior work on the queue has completed.
-
-[source,c]
-----
-VkResult VKAPI vkQueueSignalReleaseImageANDROID(
- VkQueue queue,
- uint32_t waitSemaphoreCount,
- const VkSemaphore* pWaitSemaphores,
- VkImage image,
- int* pNativeFenceFd
-);
-----
-
-This will be called during +vkQueuePresentWSI+ on the provided queue. Effects are similar to +vkQueueSignalSemaphore+, except with a native fence instead of a semaphore. The native fence must: not signal until the +waitSemaphoreCount+ semaphores in +pWaitSemaphores+ have signaled. Unlike +vkQueueSignalSemaphore+, however, this call creates and returns the synchronization object that will be signalled rather than having it provided as input. If the queue is already idle when this function is called, it is allowed but not required to set +*pNativeFenceFd+ to -1. The file descriptor returned in +*pNativeFenceFd+ is owned and will be closed by the caller. Many drivers will be able to ignore the +image+ parameter, but some may need to prepare CPU-side data structures associated with a gralloc buffer for use by external image consumers. Preparing buffer contents for use by external consumers should have been done asynchronously as part of transitioning the image to +VK_IMAGE_LAYOUT_PRESENT_SRC_KHR+.
-
-If +image+ was created with +VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID+, then the driver must tolerate +vkQueueSignalReleaseImageANDROID+ being called repeatedly without intervening calls to +vkAcquireImageANDROID+.
-
-== History ==
-
-. *2015-07-08* Initial version
-. *2015-08-16*
- * Renamed to Implementor's Guide
- * Wording and formatting changes
- * Updated based on resolution of Khronos bug 14265
- * Deferred support for multiple drivers
-. *2015-11-04*
- * Added vkGetSwapchainGrallocUsageANDROID
- * Replaced vkImportNativeFenceANDROID and vkQueueSignalNativeFenceANDROID
- with vkAcquireImageANDROID and vkQueueSignalReleaseImageANDROID, to allow
- drivers to known the ownership state of swapchain images.
-. *2015-12-03*
- * Added a VkFence parameter to vkAcquireImageANDROID corresponding to the
- parameter added to vkAcquireNextImageKHR.
-. *2016-01-08*
- * Added waitSemaphoreCount and pWaitSemaphores parameters to vkQueueSignalReleaseImageANDROID.
-. *2016-06-17*
- * Updates to reflect final behavior, closed some TBDs now that they've BDed.
-. *2017-01-06*
- * Extension version 6
- * Added VkSwapchainImageUsageFlagBitsANDROID
- * Added vkGetSwapchainGrallocUsage2ANDROID
- * Added VkSwapchainImageCreateInfoANDROID
-. *2017-02-09*
- * Extended vkGetSwapchainGrallocUsage2ANDROID and VkNativeBufferANDROID to use gralloc1-style usage bitfields.
\ No newline at end of file
diff --git a/vulkan/doc/implementors_guide/implementors_guide.conf b/vulkan/doc/implementors_guide/implementors_guide.conf
deleted file mode 100644
index 572a4d9..0000000
--- a/vulkan/doc/implementors_guide/implementors_guide.conf
+++ /dev/null
@@ -1,5 +0,0 @@
-[attributes]
-newline=\n
-
-[replacements]
-\+\/-=±
diff --git a/vulkan/doc/implementors_guide/implementors_guide.html b/vulkan/doc/implementors_guide/implementors_guide.html
deleted file mode 100644
index 9fecce5..0000000
--- a/vulkan/doc/implementors_guide/implementors_guide.html
+++ /dev/null
@@ -1,1076 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<meta name="generator" content="AsciiDoc 8.6.9">
-<title>Vulkan on Android Implementor’s Guide</title>
-<style type="text/css">
-/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
-
-/* Default font. */
-body {
- font-family: Georgia,serif;
-}
-
-/* Title font. */
-h1, h2, h3, h4, h5, h6,
-div.title, caption.title,
-thead, p.table.header,
-#toctitle,
-#author, #revnumber, #revdate, #revremark,
-#footer {
- font-family: Arial,Helvetica,sans-serif;
-}
-
-body {
- margin: 1em 5% 1em 5%;
-}
-
-a {
- color: blue;
- text-decoration: underline;
-}
-a:visited {
- color: fuchsia;
-}
-
-em {
- font-style: italic;
- color: navy;
-}
-
-strong {
- font-weight: bold;
- color: #083194;
-}
-
-h1, h2, h3, h4, h5, h6 {
- color: #527bbd;
- margin-top: 1.2em;
- margin-bottom: 0.5em;
- line-height: 1.3;
-}
-
-h1, h2, h3 {
- border-bottom: 2px solid silver;
-}
-h2 {
- padding-top: 0.5em;
-}
-h3 {
- float: left;
-}
-h3 + * {
- clear: left;
-}
-h5 {
- font-size: 1.0em;
-}
-
-div.sectionbody {
- margin-left: 0;
-}
-
-hr {
- border: 1px solid silver;
-}
-
-p {
- margin-top: 0.5em;
- margin-bottom: 0.5em;
-}
-
-ul, ol, li > p {
- margin-top: 0;
-}
-ul > li { color: #aaa; }
-ul > li > * { color: black; }
-
-.monospaced, code, pre {
- font-family: "Courier New", Courier, monospace;
- font-size: inherit;
- color: navy;
- padding: 0;
- margin: 0;
-}
-pre {
- white-space: pre-wrap;
-}
-
-#author {
- color: #527bbd;
- font-weight: bold;
- font-size: 1.1em;
-}
-#email {
-}
-#revnumber, #revdate, #revremark {
-}
-
-#footer {
- font-size: small;
- border-top: 2px solid silver;
- padding-top: 0.5em;
- margin-top: 4.0em;
-}
-#footer-text {
- float: left;
- padding-bottom: 0.5em;
-}
-#footer-badges {
- float: right;
- padding-bottom: 0.5em;
-}
-
-#preamble {
- margin-top: 1.5em;
- margin-bottom: 1.5em;
-}
-div.imageblock, div.exampleblock, div.verseblock,
-div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
-div.admonitionblock {
- margin-top: 1.0em;
- margin-bottom: 1.5em;
-}
-div.admonitionblock {
- margin-top: 2.0em;
- margin-bottom: 2.0em;
- margin-right: 10%;
- color: #606060;
-}
-
-div.content { /* Block element content. */
- padding: 0;
-}
-
-/* Block element titles. */
-div.title, caption.title {
- color: #527bbd;
- font-weight: bold;
- text-align: left;
- margin-top: 1.0em;
- margin-bottom: 0.5em;
-}
-div.title + * {
- margin-top: 0;
-}
-
-td div.title:first-child {
- margin-top: 0.0em;
-}
-div.content div.title:first-child {
- margin-top: 0.0em;
-}
-div.content + div.title {
- margin-top: 0.0em;
-}
-
-div.sidebarblock > div.content {
- background: #ffffee;
- border: 1px solid #dddddd;
- border-left: 4px solid #f0f0f0;
- padding: 0.5em;
-}
-
-div.listingblock > div.content {
- border: 1px solid #dddddd;
- border-left: 5px solid #f0f0f0;
- background: #f8f8f8;
- padding: 0.5em;
-}
-
-div.quoteblock, div.verseblock {
- padding-left: 1.0em;
- margin-left: 1.0em;
- margin-right: 10%;
- border-left: 5px solid #f0f0f0;
- color: #888;
-}
-
-div.quoteblock > div.attribution {
- padding-top: 0.5em;
- text-align: right;
-}
-
-div.verseblock > pre.content {
- font-family: inherit;
- font-size: inherit;
-}
-div.verseblock > div.attribution {
- padding-top: 0.75em;
- text-align: left;
-}
-/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
-div.verseblock + div.attribution {
- text-align: left;
-}
-
-div.admonitionblock .icon {
- vertical-align: top;
- font-size: 1.1em;
- font-weight: bold;
- text-decoration: underline;
- color: #527bbd;
- padding-right: 0.5em;
-}
-div.admonitionblock td.content {
- padding-left: 0.5em;
- border-left: 3px solid #dddddd;
-}
-
-div.exampleblock > div.content {
- border-left: 3px solid #dddddd;
- padding-left: 0.5em;
-}
-
-div.imageblock div.content { padding-left: 0; }
-span.image img { border-style: none; vertical-align: text-bottom; }
-a.image:visited { color: white; }
-
-dl {
- margin-top: 0.8em;
- margin-bottom: 0.8em;
-}
-dt {
- margin-top: 0.5em;
- margin-bottom: 0;
- font-style: normal;
- color: navy;
-}
-dd > *:first-child {
- margin-top: 0.1em;
-}
-
-ul, ol {
- list-style-position: outside;
-}
-ol.arabic {
- list-style-type: decimal;
-}
-ol.loweralpha {
- list-style-type: lower-alpha;
-}
-ol.upperalpha {
- list-style-type: upper-alpha;
-}
-ol.lowerroman {
- list-style-type: lower-roman;
-}
-ol.upperroman {
- list-style-type: upper-roman;
-}
-
-div.compact ul, div.compact ol,
-div.compact p, div.compact p,
-div.compact div, div.compact div {
- margin-top: 0.1em;
- margin-bottom: 0.1em;
-}
-
-tfoot {
- font-weight: bold;
-}
-td > div.verse {
- white-space: pre;
-}
-
-div.hdlist {
- margin-top: 0.8em;
- margin-bottom: 0.8em;
-}
-div.hdlist tr {
- padding-bottom: 15px;
-}
-dt.hdlist1.strong, td.hdlist1.strong {
- font-weight: bold;
-}
-td.hdlist1 {
- vertical-align: top;
- font-style: normal;
- padding-right: 0.8em;
- color: navy;
-}
-td.hdlist2 {
- vertical-align: top;
-}
-div.hdlist.compact tr {
- margin: 0;
- padding-bottom: 0;
-}
-
-.comment {
- background: yellow;
-}
-
-.footnote, .footnoteref {
- font-size: 0.8em;
-}
-
-span.footnote, span.footnoteref {
- vertical-align: super;
-}
-
-#footnotes {
- margin: 20px 0 20px 0;
- padding: 7px 0 0 0;
-}
-
-#footnotes div.footnote {
- margin: 0 0 5px 0;
-}
-
-#footnotes hr {
- border: none;
- border-top: 1px solid silver;
- height: 1px;
- text-align: left;
- margin-left: 0;
- width: 20%;
- min-width: 100px;
-}
-
-div.colist td {
- padding-right: 0.5em;
- padding-bottom: 0.3em;
- vertical-align: top;
-}
-div.colist td img {
- margin-top: 0.3em;
-}
-
-@media print {
- #footer-badges { display: none; }
-}
-
-#toc {
- margin-bottom: 2.5em;
-}
-
-#toctitle {
- color: #527bbd;
- font-size: 1.1em;
- font-weight: bold;
- margin-top: 1.0em;
- margin-bottom: 0.1em;
-}
-
-div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
- margin-top: 0;
- margin-bottom: 0;
-}
-div.toclevel2 {
- margin-left: 2em;
- font-size: 0.9em;
-}
-div.toclevel3 {
- margin-left: 4em;
- font-size: 0.9em;
-}
-div.toclevel4 {
- margin-left: 6em;
- font-size: 0.9em;
-}
-
-span.aqua { color: aqua; }
-span.black { color: black; }
-span.blue { color: blue; }
-span.fuchsia { color: fuchsia; }
-span.gray { color: gray; }
-span.green { color: green; }
-span.lime { color: lime; }
-span.maroon { color: maroon; }
-span.navy { color: navy; }
-span.olive { color: olive; }
-span.purple { color: purple; }
-span.red { color: red; }
-span.silver { color: silver; }
-span.teal { color: teal; }
-span.white { color: white; }
-span.yellow { color: yellow; }
-
-span.aqua-background { background: aqua; }
-span.black-background { background: black; }
-span.blue-background { background: blue; }
-span.fuchsia-background { background: fuchsia; }
-span.gray-background { background: gray; }
-span.green-background { background: green; }
-span.lime-background { background: lime; }
-span.maroon-background { background: maroon; }
-span.navy-background { background: navy; }
-span.olive-background { background: olive; }
-span.purple-background { background: purple; }
-span.red-background { background: red; }
-span.silver-background { background: silver; }
-span.teal-background { background: teal; }
-span.white-background { background: white; }
-span.yellow-background { background: yellow; }
-
-span.big { font-size: 2em; }
-span.small { font-size: 0.6em; }
-
-span.underline { text-decoration: underline; }
-span.overline { text-decoration: overline; }
-span.line-through { text-decoration: line-through; }
-
-div.unbreakable { page-break-inside: avoid; }
-
-
-/*
- * xhtml11 specific
- *
- * */
-
-div.tableblock {
- margin-top: 1.0em;
- margin-bottom: 1.5em;
-}
-div.tableblock > table {
- border: 3px solid #527bbd;
-}
-thead, p.table.header {
- font-weight: bold;
- color: #527bbd;
-}
-p.table {
- margin-top: 0;
-}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
-div.tableblock > table[frame="void"] {
- border-style: none;
-}
-div.tableblock > table[frame="hsides"] {
- border-left-style: none;
- border-right-style: none;
-}
-div.tableblock > table[frame="vsides"] {
- border-top-style: none;
- border-bottom-style: none;
-}
-
-
-/*
- * html5 specific
- *
- * */
-
-table.tableblock {
- margin-top: 1.0em;
- margin-bottom: 1.5em;
-}
-thead, p.tableblock.header {
- font-weight: bold;
- color: #527bbd;
-}
-p.tableblock {
- margin-top: 0;
-}
-table.tableblock {
- border-width: 3px;
- border-spacing: 0px;
- border-style: solid;
- border-color: #527bbd;
- border-collapse: collapse;
-}
-th.tableblock, td.tableblock {
- border-width: 1px;
- padding: 4px;
- border-style: solid;
- border-color: #527bbd;
-}
-
-table.tableblock.frame-topbot {
- border-left-style: hidden;
- border-right-style: hidden;
-}
-table.tableblock.frame-sides {
- border-top-style: hidden;
- border-bottom-style: hidden;
-}
-table.tableblock.frame-none {
- border-style: hidden;
-}
-
-th.tableblock.halign-left, td.tableblock.halign-left {
- text-align: left;
-}
-th.tableblock.halign-center, td.tableblock.halign-center {
- text-align: center;
-}
-th.tableblock.halign-right, td.tableblock.halign-right {
- text-align: right;
-}
-
-th.tableblock.valign-top, td.tableblock.valign-top {
- vertical-align: top;
-}
-th.tableblock.valign-middle, td.tableblock.valign-middle {
- vertical-align: middle;
-}
-th.tableblock.valign-bottom, td.tableblock.valign-bottom {
- vertical-align: bottom;
-}
-
-
-/*
- * manpage specific
- *
- * */
-
-body.manpage h1 {
- padding-top: 0.5em;
- padding-bottom: 0.5em;
- border-top: 2px solid silver;
- border-bottom: 2px solid silver;
-}
-body.manpage h2 {
- border-style: none;
-}
-body.manpage div.sectionbody {
- margin-left: 3em;
-}
-
-@media print {
- body.manpage div#toc { display: none; }
-}
-
-
-</style>
-<script type="text/javascript">
-/*<![CDATA[*/
-var asciidoc = { // Namespace.
-
-/////////////////////////////////////////////////////////////////////
-// Table Of Contents generator
-/////////////////////////////////////////////////////////////////////
-
-/* Author: Mihai Bazon, September 2002
- * http://students.infoiasi.ro/~mishoo
- *
- * Table Of Content generator
- * Version: 0.4
- *
- * Feel free to use this script under the terms of the GNU General Public
- * License, as long as you do not remove or alter this notice.
- */
-
- /* modified by Troy D. Hanson, September 2006. License: GPL */
- /* modified by Stuart Rackham, 2006, 2009. License: GPL */
-
-// toclevels = 1..4.
-toc: function (toclevels) {
-
- function getText(el) {
- var text = "";
- for (var i = el.firstChild; i != null; i = i.nextSibling) {
- if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
- text += i.data;
- else if (i.firstChild != null)
- text += getText(i);
- }
- return text;
- }
-
- function TocEntry(el, text, toclevel) {
- this.element = el;
- this.text = text;
- this.toclevel = toclevel;
- }
-
- function tocEntries(el, toclevels) {
- var result = new Array;
- var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
- // Function that scans the DOM tree for header elements (the DOM2
- // nodeIterator API would be a better technique but not supported by all
- // browsers).
- var iterate = function (el) {
- for (var i = el.firstChild; i != null; i = i.nextSibling) {
- if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
- var mo = re.exec(i.tagName);
- if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
- result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
- }
- iterate(i);
- }
- }
- }
- iterate(el);
- return result;
- }
-
- var toc = document.getElementById("toc");
- if (!toc) {
- return;
- }
-
- // Delete existing TOC entries in case we're reloading the TOC.
- var tocEntriesToRemove = [];
- var i;
- for (i = 0; i < toc.childNodes.length; i++) {
- var entry = toc.childNodes[i];
- if (entry.nodeName.toLowerCase() == 'div'
- && entry.getAttribute("class")
- && entry.getAttribute("class").match(/^toclevel/))
- tocEntriesToRemove.push(entry);
- }
- for (i = 0; i < tocEntriesToRemove.length; i++) {
- toc.removeChild(tocEntriesToRemove[i]);
- }
-
- // Rebuild TOC entries.
- var entries = tocEntries(document.getElementById("content"), toclevels);
- for (var i = 0; i < entries.length; ++i) {
- var entry = entries[i];
- if (entry.element.id == "")
- entry.element.id = "_toc_" + i;
- var a = document.createElement("a");
- a.href = "#" + entry.element.id;
- a.appendChild(document.createTextNode(entry.text));
- var div = document.createElement("div");
- div.appendChild(a);
- div.className = "toclevel" + entry.toclevel;
- toc.appendChild(div);
- }
- if (entries.length == 0)
- toc.parentNode.removeChild(toc);
-},
-
-
-/////////////////////////////////////////////////////////////////////
-// Footnotes generator
-/////////////////////////////////////////////////////////////////////
-
-/* Based on footnote generation code from:
- * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
- */
-
-footnotes: function () {
- // Delete existing footnote entries in case we're reloading the footnodes.
- var i;
- var noteholder = document.getElementById("footnotes");
- if (!noteholder) {
- return;
- }
- var entriesToRemove = [];
- for (i = 0; i < noteholder.childNodes.length; i++) {
- var entry = noteholder.childNodes[i];
- if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
- entriesToRemove.push(entry);
- }
- for (i = 0; i < entriesToRemove.length; i++) {
- noteholder.removeChild(entriesToRemove[i]);
- }
-
- // Rebuild footnote entries.
- var cont = document.getElementById("content");
- var spans = cont.getElementsByTagName("span");
- var refs = {};
- var n = 0;
- for (i=0; i<spans.length; i++) {
- if (spans[i].className == "footnote") {
- n++;
- var note = spans[i].getAttribute("data-note");
- if (!note) {
- // Use [\s\S] in place of . so multi-line matches work.
- // Because JavaScript has no s (dotall) regex flag.
- note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
- spans[i].innerHTML =
- "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
- "' title='View footnote' class='footnote'>" + n + "</a>]";
- spans[i].setAttribute("data-note", note);
- }
- noteholder.innerHTML +=
- "<div class='footnote' id='_footnote_" + n + "'>" +
- "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
- n + "</a>. " + note + "</div>";
- var id =spans[i].getAttribute("id");
- if (id != null) refs["#"+id] = n;
- }
- }
- if (n == 0)
- noteholder.parentNode.removeChild(noteholder);
- else {
- // Process footnoterefs.
- for (i=0; i<spans.length; i++) {
- if (spans[i].className == "footnoteref") {
- var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
- href = href.match(/#.*/)[0]; // Because IE return full URL.
- n = refs[href];
- spans[i].innerHTML =
- "[<a href='#_footnote_" + n +
- "' title='View footnote' class='footnote'>" + n + "</a>]";
- }
- }
- }
-},
-
-install: function(toclevels) {
- var timerId;
-
- function reinstall() {
- asciidoc.footnotes();
- if (toclevels) {
- asciidoc.toc(toclevels);
- }
- }
-
- function reinstallAndRemoveTimer() {
- clearInterval(timerId);
- reinstall();
- }
-
- timerId = setInterval(reinstall, 500);
- if (document.addEventListener)
- document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
- else
- window.onload = reinstallAndRemoveTimer;
-}
-
-}
-asciidoc.install(2);
-/*]]>*/
-</script>
-</head>
-<body class="book">
-<div id="header">
-<h1>Vulkan on Android Implementor’s Guide</h1>
-<span id="revnumber">version 5</span>
-<div id="toc">
- <div id="toctitle">Table of Contents</div>
- <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
-</div>
-</div>
-<div id="content">
-<div id="preamble">
-<div class="sectionbody">
-<div class="paragraph"><p>This document is intended for GPU IHVs writing Vulkan drivers for Android, and OEMs integrating them for specific devices. It describes how a Vulkan driver interacts with the system, how GPU-specific tools should be installed, and Android-specific requirements.</p></div>
-</div>
-</div>
-<div class="sect1">
-<h2 id="_architecture">1. Architecture</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>The primary interface between Vulkan applications and a device’s Vulkan driver is the loader, which is part of AOSP and installed at <span class="monospaced">/system/lib[64]/libvulkan.so</span>. The loader provides the core Vulkan API entry points, as well as entry points of a few extensions that are required on Android and always present. In particular, the window system integration (WSI) extensions are exported by the loader and primarily implemented in it rather than the driver. The loader also supports enumerating and loading layers which can expose additional extensions and/or intercept core API calls on their way to the driver.</p></div>
-<div class="paragraph"><p>The NDK will include a stub <span class="monospaced">libvulkan.so</span> exporting the same symbols as the loader. Calling the Vulkan functions exported from <span class="monospaced">libvulkan.so</span> will enter trampoline functions in the loader which will dispatch to the appropriate layer or driver based on their first argument. The <span class="monospaced">vkGet*ProcAddr</span> calls will return the function pointers that the trampolines would dispatch to, so calling through these function pointers rather than the exported symbols will be slightly more efficient since it skips the trampoline and dispatch.</p></div>
-<div class="sect2">
-<h3 id="_driver_enumeration_and_loading">1.1. Driver Enumeration and Loading</h3>
-<div class="paragraph"><p>Android expects the GPUs available to the system to be known when the system image is built, so its driver enumeration process isn’t as elaborate as on other platforms. The loader will use the existing HAL mechanism for discovering and loading the driver. As of this writing, the preferred paths for 32-bit and 64-bit Vulkan drivers are:</p></div>
-<div class="literalblock">
-<div class="content monospaced">
-<pre>/vendor/lib/hw/vulkan.<ro.product.platform>.so
-/vendor/lib64/hw/vulkan.<ro.product.platform>.so</pre>
-</div></div>
-<div class="paragraph"><p>where <span class="monospaced"><ro.product.platform></span> is replaced by the value of the system property of that name. See <a href="https://android.googlesource.com/platform/hardware/libhardware/+/master/hardware.c">libhardware/hardware.c</a> for details and supported alternative locations.</p></div>
-<div class="paragraph"><p>The Vulkan <span class="monospaced">hw_module_t</span> derivative is currently trivial. If support for multiple drivers is ever added, the HAL module will export a list of strings that can be passed to the module <span class="monospaced">open</span> call. For the time being, only one driver is supported, and the constant string <span class="monospaced">HWVULKAN_DEVICE_0</span> is passed to <span class="monospaced">open</span>.</p></div>
-<div class="paragraph"><p>The Vulkan <span class="monospaced">hw_device_t</span> derivative corresponds to a single driver, though that driver can support multiple Vulkan physical devices. The <span class="monospaced">hw_device_t</span> structure contains a function pointer for the <span class="monospaced">vkGetInstanceProcAddr</span> function. The loader finds all other driver Vulkan functions by calling that <span class="monospaced">vkGetInstanceProcAddr</span> function.</p></div>
-</div>
-<div class="sect2">
-<h3 id="_layer_discovery_and_loading">1.2. Layer Discovery and Loading</h3>
-<div class="paragraph"><p>Android’s security model and policies differ significantly from other platforms. In particular, Android does not allow loading external code into a non-debuggable process on production (non-rooted) devices, nor does it allow external code to inspect or control the process’s memory/state/etc. This includes a prohibition on saving core dumps, API traces, etc. to disk for later inspection. So only layers delivered as part of the application will be enabled on production devices, and drivers must also not provide functionality that violates these policies.</p></div>
-<div class="paragraph"><p>There are three major use cases for layers:</p></div>
-<div class="olist arabic"><ol class="arabic">
-<li>
-<p>
-Development-time layers: validation layers, shims for tracing/profiling/debugging tools, etc. These shouldn’t be installed on the system image of production devices: they would be a waste of space for most users, and they should be updateable without requiring a system update. A developer wishing to use one of these during development has the ability to modify their application package (e.g. adding a file to their native libraries directory). IHV and OEM engineers who are trying to diagnose failures in shipping, unmodifiable apps are assumed to have access to non-production (rooted) builds of the system image.
-</p>
-</li>
-<li>
-<p>
-Utility layers, such as a layer that implements a heap for device memory. These layers will almost always expose extensions. Developers choose which layers, and which versions of those layers, to use in their application; different applications that use the same layer may still use different versions. Developers will choose which of these layers to ship in their application package.
-</p>
-</li>
-<li>
-<p>
-Injected layers, like framerate, social network, or game launcher overlays, which are provided by the user or some other application without the application’s knowledge or consent. These violate Android’s security policies and will not be supported.
-</p>
-</li>
-</ol></div>
-<div class="paragraph"><p>In the normal state the loader will only search in the application’s normal library search path (as defined by the system ClassLoader) for layers. It will attempt to load any shared library named <span class="monospaced">libVkLayer_*.so</span> as a layer library. Android does not use manifests to describe layers: because layers must have been deliberately included in the application by the developer, the motivation for manifests on other platforms don’t apply.</p></div>
-<div class="paragraph"><p>On debuggable devices (<span class="monospaced">ro.debuggable</span> property exists and is non-zero, generally rooted or engineering builds) the loader will also search the directory <span class="monospaced">/data/local/debug/vulkan</span> and attempt to load layer libraries it finds there. This directory doesn’t exist by default. On Android N and later, because this location is writable by adb, SELinux policies prevent mapping code located here as executable. So to use layers from here, SELinux enforcement must be disabled: <span class="monospaced">adb shell setenforce 0</span>. This mechanism is not intended for application developers, only for IHV and OEM engineers working on test devices that don’t have private or sensitive data.</p></div>
-<div class="paragraph"><p>Our goal is to allow layers to be ported with only build-environment changes between Android and other platforms. For this to work, layers must properly implement things like <span class="monospaced">vkGetInstanceLayerProperties</span> and <span class="monospaced">vkGetInstanceExtensionProperties</span>, even though the LunarG loader doesn’t use them (it gets the information from manifests instead).</p></div>
-</div>
-</div>
-</div>
-<div class="sect1">
-<h2 id="_window_system_integration">2. Window System Integration</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>The <span class="monospaced">vk_wsi_swapchin</span> and <span class="monospaced">vk_wsi_device_swapchain</span> extensions are primarily be implemented by the platform and live in <span class="monospaced">libvulkan.so</span>. The <span class="monospaced">VkSwapchain</span> object and all interaction with <span class="monospaced">ANativeWindow</span> will be handled by the platform and not exposed to drivers. The WSI implementation will rely on a few private interfaces to the driver for this implementation. These will be loaded through the driver’s <span class="monospaced">vkGetDeviceProcAddr</span> functions, after passing through any enabled layers.</p></div>
-<div class="paragraph"><p>Implementations may need swapchain buffers to be allocated with implementation-defined private gralloc usage flags that depend not only on <span class="monospaced">format</span> and <span class="monospaced">imageUsage</span>, but also on the intended usage of the swapchain. The swapchain usage bits are defined as</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.6
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">typedef</span></span> <span style="font-weight: bold"><span style="color: #0000FF">enum</span></span> VkSwapchainImageUsageFlagBitsANDROID <span style="color: #FF0000">{</span>
- VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID <span style="color: #990000">=</span> <span style="color: #993399">0x00000001</span><span style="color: #990000">,</span>
- VK_SWAPCHAIN_IMAGE_USAGE_FLAG_BITS_MAX_ENUM <span style="color: #990000">=</span> <span style="color: #993399">0x7FFFFFFF</span>
-<span style="color: #FF0000">}</span> VkSwapchainImageUsageFlagBitsANDROID<span style="color: #990000">;</span>
-<span style="font-weight: bold"><span style="color: #0000FF">typedef</span></span> <span style="color: #008080">VkFlags</span> VkSwapchainImageUsageFlagsANDROID<span style="color: #990000">;</span></tt></pre></div></div>
-<div class="paragraph"><p>Implementations may need swapchain buffers to be allocated with implementation-defined private gralloc usage flags. When creating a swapchain, the platform will ask the driver to translate the requested format and image usage flags into gralloc usage flags by calling</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.6
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt>VKAPI_ATTR <span style="color: #008080">VkResult</span> <span style="color: #008080">VKAPI_CALL</span> <span style="font-weight: bold"><span style="color: #000000">vkGetSwapchainGrallocUsage2ANDROID</span></span><span style="color: #990000">(</span>
- <span style="color: #008080">VkDevice</span> device<span style="color: #990000">,</span>
- <span style="color: #008080">VkFormat</span> format<span style="color: #990000">,</span>
- <span style="color: #008080">VkImageUsageFlags</span> imageUsage<span style="color: #990000">,</span>
- <span style="color: #008080">VkSwapchainImageUsageFlagsANDROID</span> swapchainImageUsage<span style="color: #990000">,</span>
- uint64_t<span style="color: #990000">*</span> grallocConsumerUsage<span style="color: #990000">,</span>
- uint64_t<span style="color: #990000">*</span> grallocProducerUsage<span style="color: #990000">,</span>
-<span style="color: #990000">);</span></tt></pre></div></div>
-<div class="paragraph"><p>The <span class="monospaced">format</span> and <span class="monospaced">imageUsage</span> parameters are taken from the <span class="monospaced">VkSwapchainCreateInfoKHR</span> structure. The driver should fill <span class="monospaced">*grallocConsumerUsage</span> and <span class="monospaced">*grallocProducerUsage</span> with the gralloc usage flags it requires for that format and usage. These will be combined with the usage flags requested by the swapchain consumer when allocating buffers.</p></div>
-<div class="paragraph"><p>An older version of this function is deprecated but still supported for backwards compatibility; it will be used if <span class="monospaced">vkGetSwapchainGrallocUsage2ANDROID</span> is not supported:</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.6
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt>VkResult <span style="color: #008080">VKAPI</span> <span style="font-weight: bold"><span style="color: #000000">vkGetSwapchainGrallocUsageANDROID</span></span><span style="color: #990000">(</span>
- <span style="color: #008080">VkDevice</span> device<span style="color: #990000">,</span>
- <span style="color: #008080">VkFormat</span> format<span style="color: #990000">,</span>
- <span style="color: #008080">VkImageUsageFlags</span> imageUsage<span style="color: #990000">,</span>
- <span style="color: #009900">int</span><span style="color: #990000">*</span> grallocUsage
-<span style="color: #990000">);</span></tt></pre></div></div>
-<div class="paragraph"><p><span class="monospaced">VkNativeBufferANDROID</span> is a <span class="monospaced">vkCreateImage</span> extension structure for creating an image backed by a gralloc buffer. This structure is provided to <span class="monospaced">vkCreateImage</span> in the <span class="monospaced">VkImageCreateInfo</span> structure chain. Calls to <span class="monospaced">vkCreateImage</span> with this structure will happen during the first call to <span class="monospaced">vkGetSwapChainInfoWSI(.. VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI ..)</span>. The WSI implementation will allocate the number of native buffers requested for the swapchain, then create a <span class="monospaced">VkImage</span> for each one.</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.6
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">typedef</span></span> <span style="font-weight: bold"><span style="color: #0000FF">struct</span></span> <span style="color: #FF0000">{</span>
- <span style="color: #008080">VkStructureType</span> sType<span style="color: #990000">;</span> <span style="font-style: italic"><span style="color: #9A1900">// must be VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID</span></span>
- <span style="font-weight: bold"><span style="color: #0000FF">const</span></span> <span style="color: #009900">void</span><span style="color: #990000">*</span> pNext<span style="color: #990000">;</span>
-
- <span style="font-style: italic"><span style="color: #9A1900">// Buffer handle and stride returned from gralloc alloc()</span></span>
- <span style="color: #008080">buffer_handle_t</span> handle<span style="color: #990000">;</span>
- <span style="color: #009900">int</span> stride<span style="color: #990000">;</span>
-
- <span style="font-style: italic"><span style="color: #9A1900">// Gralloc format and usage requested when the buffer was allocated.</span></span>
- <span style="color: #009900">int</span> format<span style="color: #990000">;</span>
- <span style="color: #009900">int</span> usage<span style="color: #990000">;</span> <span style="font-style: italic"><span style="color: #9A1900">// deprecated</span></span>
- <span style="font-weight: bold"><span style="color: #0000FF">struct</span></span> <span style="color: #FF0000">{</span>
- <span style="color: #008080">uint64_t</span> consumer<span style="color: #990000">;</span>
- <span style="color: #008080">uint64_t</span> producer<span style="color: #990000">;</span>
- <span style="color: #FF0000">}</span> usage2<span style="color: #990000">;</span>
-<span style="color: #FF0000">}</span> VkNativeBufferANDROID<span style="color: #990000">;</span></tt></pre></div></div>
-<div class="paragraph"><p>When creating a gralloc-backed image, the <span class="monospaced">VkImageCreateInfo</span> will have:</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.6
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt> .imageType = VK_IMAGE_TYPE_2D
- .format = a VkFormat matching the format requested for the gralloc buffer
- .extent = the 2D dimensions requested for the gralloc buffer
- .mipLevels = 1
- .arraySize = 1
- .samples = 1
- .tiling = VK_IMAGE_TILING_OPTIMAL
- .usage = VkSwapChainCreateInfoWSI::imageUsageFlags
- .flags = 0
- .sharingMode = VkSwapChainCreateInfoWSI::sharingMode
- .queueFamilyCount = VkSwapChainCreateInfoWSI::queueFamilyCount
- .pQueueFamilyIndices = VkSwapChainCreateInfoWSI::pQueueFamilyIndices</tt></pre></div></div>
-<div class="paragraph"><p>Additionally, when any swapchain image usage flags are required for the swapchain, the platform will provide a <span class="monospaced">VkSwapchainImageCreateInfoANDROID</span> extension structure in the <span class="monospaced">VkImageCreateInfo</span> chain provided to <span class="monospaced">vkCreateImage</span>, containing the swapchain image usage flags:</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.6
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">typedef</span></span> <span style="font-weight: bold"><span style="color: #0000FF">struct</span></span> <span style="color: #FF0000">{</span>
- <span style="color: #008080">VkStructureType</span> sType<span style="color: #990000">;</span> <span style="font-style: italic"><span style="color: #9A1900">// must be VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID</span></span>
- <span style="font-weight: bold"><span style="color: #0000FF">const</span></span> <span style="color: #009900">void</span><span style="color: #990000">*</span> pNext<span style="color: #990000">;</span>
-
- <span style="color: #008080">VkSwapchainImageUsageFlagsANDROID</span> usage<span style="color: #990000">;</span>
-<span style="color: #FF0000">}</span> VkSwapchainImageCreateInfoANDROID<span style="color: #990000">;</span></tt></pre></div></div>
-<div class="paragraph"><p><span class="monospaced">vkAcquireImageANDROID</span> acquires ownership of a swapchain image and imports an
-externally-signalled native fence into both an existing VkSemaphore object
-and an existing VkFence object:</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.6
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt>VkResult <span style="color: #008080">VKAPI</span> <span style="font-weight: bold"><span style="color: #000000">vkAcquireImageANDROID</span></span><span style="color: #990000">(</span>
- <span style="color: #008080">VkDevice</span> device<span style="color: #990000">,</span>
- <span style="color: #008080">VkImage</span> image<span style="color: #990000">,</span>
- <span style="color: #009900">int</span> nativeFenceFd<span style="color: #990000">,</span>
- <span style="color: #008080">VkSemaphore</span> semaphore<span style="color: #990000">,</span>
- VkFence fence
-<span style="color: #990000">);</span></tt></pre></div></div>
-<div class="paragraph"><p>This function is called during <span class="monospaced">vkAcquireNextImageWSI</span> to import a native
-fence into the <span class="monospaced">VkSemaphore</span> and <span class="monospaced">VkFence</span> objects provided by the
-application. Both semaphore and fence objects are optional in this call. The
-driver may also use this opportunity to recognize and handle any external
-changes to the gralloc buffer state; many drivers won’t need to do anything
-here. This call puts the <span class="monospaced">VkSemaphore</span> and <span class="monospaced">VkFence</span> into the same "pending"
-state as <span class="monospaced">vkQueueSignalSemaphore</span> and <span class="monospaced">vkQueueSubmit</span> respectively, so queues
-can wait on the semaphore and the application can wait on the fence. Both
-objects become signalled when the underlying native fence signals; if the
-native fence has already signalled, then the semaphore will be in the signalled
-state when this function returns. The driver takes ownership of the fence fd
-and is responsible for closing it when no longer needed. It must do so even if
-neither a semaphore or fence object is provided, or even if
-<span class="monospaced">vkAcquireImageANDROID</span> fails and returns an error. If <span class="monospaced">fenceFd</span> is -1, it
-is as if the native fence was already signalled.</p></div>
-<div class="paragraph"><p><span class="monospaced">vkQueueSignalReleaseImageANDROID</span> prepares a swapchain image for external use, and creates a native fence and schedules it to be signalled when prior work on the queue has completed.</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.6
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt>VkResult <span style="color: #008080">VKAPI</span> <span style="font-weight: bold"><span style="color: #000000">vkQueueSignalReleaseImageANDROID</span></span><span style="color: #990000">(</span>
- <span style="color: #008080">VkQueue</span> queue<span style="color: #990000">,</span>
- <span style="color: #008080">uint32_t</span> waitSemaphoreCount<span style="color: #990000">,</span>
- <span style="font-weight: bold"><span style="color: #0000FF">const</span></span> VkSemaphore<span style="color: #990000">*</span> pWaitSemaphores<span style="color: #990000">,</span>
- <span style="color: #008080">VkImage</span> image<span style="color: #990000">,</span>
- <span style="color: #009900">int</span><span style="color: #990000">*</span> pNativeFenceFd
-<span style="color: #990000">);</span></tt></pre></div></div>
-<div class="paragraph"><p>This will be called during <span class="monospaced">vkQueuePresentWSI</span> on the provided queue. Effects are similar to <span class="monospaced">vkQueueSignalSemaphore</span>, except with a native fence instead of a semaphore. The native fence must: not signal until the <span class="monospaced">waitSemaphoreCount</span> semaphores in <span class="monospaced">pWaitSemaphores</span> have signaled. Unlike <span class="monospaced">vkQueueSignalSemaphore</span>, however, this call creates and returns the synchronization object that will be signalled rather than having it provided as input. If the queue is already idle when this function is called, it is allowed but not required to set <span class="monospaced">*pNativeFenceFd</span> to -1. The file descriptor returned in <span class="monospaced">*pNativeFenceFd</span> is owned and will be closed by the caller. Many drivers will be able to ignore the <span class="monospaced">image</span> parameter, but some may need to prepare CPU-side data structures associated with a gralloc buffer for use by external image consumers. Preparing buffer contents for use by external consumers should have been done asynchronously as part of transitioning the image to <span class="monospaced">VK_IMAGE_LAYOUT_PRESENT_SRC_KHR</span>.</p></div>
-<div class="paragraph"><p>If <span class="monospaced">image</span> was created with <span class="monospaced">VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID</span>, then the driver must tolerate <span class="monospaced">vkQueueSignalReleaseImageANDROID</span> being called repeatedly without intervening calls to <span class="monospaced">vkAcquireImageANDROID</span>.</p></div>
-</div>
-</div>
-<div class="sect1">
-<h2 id="_history">3. History</h2>
-<div class="sectionbody">
-<div class="olist arabic"><ol class="arabic">
-<li>
-<p>
-<strong>2015-07-08</strong> Initial version
-</p>
-</li>
-<li>
-<p>
-<strong>2015-08-16</strong>
-</p>
-<div class="ulist"><ul>
-<li>
-<p>
-Renamed to Implementor’s Guide
-</p>
-</li>
-<li>
-<p>
-Wording and formatting changes
-</p>
-</li>
-<li>
-<p>
-Updated based on resolution of Khronos bug 14265
-</p>
-</li>
-<li>
-<p>
-Deferred support for multiple drivers
-</p>
-</li>
-</ul></div>
-</li>
-<li>
-<p>
-<strong>2015-11-04</strong>
-</p>
-<div class="ulist"><ul>
-<li>
-<p>
-Added vkGetSwapchainGrallocUsageANDROID
-</p>
-</li>
-<li>
-<p>
-Replaced vkImportNativeFenceANDROID and vkQueueSignalNativeFenceANDROID
- with vkAcquireImageANDROID and vkQueueSignalReleaseImageANDROID, to allow
- drivers to known the ownership state of swapchain images.
-</p>
-</li>
-</ul></div>
-</li>
-<li>
-<p>
-<strong>2015-12-03</strong>
-</p>
-<div class="ulist"><ul>
-<li>
-<p>
-Added a VkFence parameter to vkAcquireImageANDROID corresponding to the
- parameter added to vkAcquireNextImageKHR.
-</p>
-</li>
-</ul></div>
-</li>
-<li>
-<p>
-<strong>2016-01-08</strong>
-</p>
-<div class="ulist"><ul>
-<li>
-<p>
-Added waitSemaphoreCount and pWaitSemaphores parameters to vkQueueSignalReleaseImageANDROID.
-</p>
-</li>
-</ul></div>
-</li>
-<li>
-<p>
-<strong>2016-06-17</strong>
-</p>
-<div class="ulist"><ul>
-<li>
-<p>
-Updates to reflect final behavior, closed some TBDs now that they’ve BDed.
-</p>
-</li>
-</ul></div>
-</li>
-<li>
-<p>
-<strong>2017-01-06</strong>
-</p>
-<div class="ulist"><ul>
-<li>
-<p>
-Extension version 6
-</p>
-</li>
-<li>
-<p>
-Added VkSwapchainImageUsageFlagBitsANDROID
-</p>
-</li>
-<li>
-<p>
-Added vkGetSwapchainGrallocUsage2ANDROID
-</p>
-</li>
-<li>
-<p>
-Added VkSwapchainImageCreateInfoANDROID
-</p>
-</li>
-</ul></div>
-</li>
-<li>
-<p>
-<strong>2017-02-09</strong>
-</p>
-<div class="ulist"><ul>
-<li>
-<p>
-Extended vkGetSwapchainGrallocUsage2ANDROID and VkNativeBufferANDROID to use gralloc1-style usage bitfields.
-</p>
-</li>
-</ul></div>
-</li>
-</ol></div>
-</div>
-</div>
-</div>
-<div id="footnotes"><hr></div>
-<div id="footer">
-<div id="footer-text">
-Version 5<br>
-Last updated 2017-02-09 22:40:30 PST
-</div>
-</div>
-</body>
-</html>
diff --git a/vulkan/include/vulkan/vulkan_android.h b/vulkan/include/vulkan/vulkan_android.h
index 42521d9..07aaeda 100644
--- a/vulkan/include/vulkan/vulkan_android.h
+++ b/vulkan/include/vulkan/vulkan_android.h
@@ -56,7 +56,7 @@
#define VK_ANDROID_external_memory_android_hardware_buffer 1
struct AHardwareBuffer;
-#define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_SPEC_VERSION 2
+#define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_SPEC_VERSION 3
#define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME "VK_ANDROID_external_memory_android_hardware_buffer"
typedef struct VkAndroidHardwareBufferUsageANDROID {
diff --git a/vulkan/include/vulkan/vulkan_core.h b/vulkan/include/vulkan/vulkan_core.h
index 6e5ea80..39f4dc6 100644
--- a/vulkan/include/vulkan/vulkan_core.h
+++ b/vulkan/include/vulkan/vulkan_core.h
@@ -43,7 +43,7 @@
#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
// Version of this file
-#define VK_HEADER_VERSION 68
+#define VK_HEADER_VERSION 86
#define VK_NULL_HANDLE 0
@@ -147,6 +147,7 @@
VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001,
VK_ERROR_VALIDATION_FAILED_EXT = -1000011001,
VK_ERROR_INVALID_SHADER_NV = -1000012000,
+ VK_ERROR_FRAGMENTATION_EXT = -1000161000,
VK_ERROR_NOT_PERMITTED_EXT = -1000174001,
VK_ERROR_OUT_OF_POOL_MEMORY_KHR = VK_ERROR_OUT_OF_POOL_MEMORY,
VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR = VK_ERROR_INVALID_EXTERNAL_HANDLE,
@@ -297,6 +298,7 @@
VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001,
VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002,
VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV = 1000050000,
VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV = 1000056000,
VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV = 1000056001,
VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057000,
@@ -304,6 +306,8 @@
VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV = 1000058000,
VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT = 1000061000,
VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN = 1000062000,
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT = 1000067000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT = 1000067001,
VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073000,
VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073001,
VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR = 1000073002,
@@ -319,6 +323,9 @@
VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR = 1000079000,
VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR = 1000079001,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR = 1000080000,
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT = 1000081000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT = 1000081001,
+ VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT = 1000081002,
VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000,
VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX = 1000086000,
VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX = 1000086001,
@@ -340,6 +347,13 @@
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT = 1000101000,
VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT = 1000101001,
VK_STRUCTURE_TYPE_HDR_METADATA_EXT = 1000105000,
+ VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR = 1000109000,
+ VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR = 1000109001,
+ VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR = 1000109002,
+ VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2_KHR = 1000109003,
+ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR = 1000109004,
+ VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO_KHR = 1000109005,
+ VK_STRUCTURE_TYPE_SUBPASS_END_INFO_KHR = 1000109006,
VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR = 1000111000,
VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114000,
VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114001,
@@ -349,6 +363,11 @@
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR = 1000119000,
VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR = 1000119001,
VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR = 1000119002,
+ VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR = 1000121000,
+ VK_STRUCTURE_TYPE_DISPLAY_PLANE_PROPERTIES_2_KHR = 1000121001,
+ VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR = 1000121002,
+ VK_STRUCTURE_TYPE_DISPLAY_PLANE_INFO_2_KHR = 1000121003,
+ VK_STRUCTURE_TYPE_DISPLAY_PLANE_CAPABILITIES_2_KHR = 1000121004,
VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK = 1000122000,
VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000,
VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT = 1000128000,
@@ -364,6 +383,10 @@
VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID = 1000129005,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = 1000130000,
VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = 1000130001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT = 1000138000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT = 1000138001,
+ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT = 1000138002,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT = 1000138003,
VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT = 1000143000,
VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT = 1000143001,
VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT = 1000143002,
@@ -377,10 +400,50 @@
VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV = 1000152000,
VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160000,
VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160001,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT = 1000161000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT = 1000161001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT = 1000161002,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT = 1000161003,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT = 1000161004,
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV = 1000164000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV = 1000164001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV = 1000164002,
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV = 1000164005,
+ VK_STRUCTURE_TYPE_RAYTRACING_PIPELINE_CREATE_INFO_NVX = 1000165000,
+ VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NVX = 1000165001,
+ VK_STRUCTURE_TYPE_GEOMETRY_INSTANCE_NVX = 1000165002,
+ VK_STRUCTURE_TYPE_GEOMETRY_NVX = 1000165003,
+ VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NVX = 1000165004,
+ VK_STRUCTURE_TYPE_GEOMETRY_AABB_NVX = 1000165005,
+ VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NVX = 1000165006,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_ACCELERATION_STRUCTURE_INFO_NVX = 1000165007,
+ VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NVX = 1000165008,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAYTRACING_PROPERTIES_NVX = 1000165009,
+ VK_STRUCTURE_TYPE_HIT_SHADER_MODULE_CREATE_INFO_NVX = 1000165010,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV = 1000166000,
+ VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV = 1000166001,
VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT = 1000174000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR = 1000177000,
VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT = 1000178000,
VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT = 1000178001,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT = 1000178002,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR = 1000180000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD = 1000185000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT = 1000190000,
+ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = 1000190001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT = 1000190002,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR = 1000196000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV = 1000201000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV = 1000202000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV = 1000202001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_NV = 1000203000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV = 1000204000,
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_EXCLUSIVE_SCISSOR_STATE_CREATE_INFO_NV = 1000205000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV = 1000205002,
+ VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV = 1000206000,
+ VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV = 1000206001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = 1000211000,
+ VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT,
VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES,
@@ -415,6 +478,7 @@
VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES,
VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO,
+ VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
@@ -769,6 +833,7 @@
VK_QUERY_TYPE_OCCLUSION = 0,
VK_QUERY_TYPE_PIPELINE_STATISTICS = 1,
VK_QUERY_TYPE_TIMESTAMP = 2,
+ VK_QUERY_TYPE_COMPACTED_SIZE_NVX = 1000165000,
VK_QUERY_TYPE_BEGIN_RANGE = VK_QUERY_TYPE_OCCLUSION,
VK_QUERY_TYPE_END_RANGE = VK_QUERY_TYPE_TIMESTAMP,
VK_QUERY_TYPE_RANGE_SIZE = (VK_QUERY_TYPE_TIMESTAMP - VK_QUERY_TYPE_OCCLUSION + 1),
@@ -798,6 +863,7 @@
VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL = 1000117001,
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002,
VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR = 1000111000,
+ VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV = 1000164003,
VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL,
VK_IMAGE_LAYOUT_BEGIN_RANGE = VK_IMAGE_LAYOUT_UNDEFINED,
@@ -1031,6 +1097,9 @@
VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV = 1000087000,
VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT = 1000099000,
VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT = 1000143000,
+ VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV = 1000164004,
+ VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV = 1000164006,
+ VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV = 1000205001,
VK_DYNAMIC_STATE_BEGIN_RANGE = VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_END_RANGE = VK_DYNAMIC_STATE_STENCIL_REFERENCE,
VK_DYNAMIC_STATE_RANGE_SIZE = (VK_DYNAMIC_STATE_STENCIL_REFERENCE - VK_DYNAMIC_STATE_VIEWPORT + 1),
@@ -1093,6 +1162,8 @@
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8,
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9,
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10,
+ VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = 1000138000,
+ VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NVX = 1000165000,
VK_DESCRIPTOR_TYPE_BEGIN_RANGE = VK_DESCRIPTOR_TYPE_SAMPLER,
VK_DESCRIPTOR_TYPE_END_RANGE = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
VK_DESCRIPTOR_TYPE_RANGE_SIZE = (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT - VK_DESCRIPTOR_TYPE_SAMPLER + 1),
@@ -1121,6 +1192,7 @@
typedef enum VkPipelineBindPoint {
VK_PIPELINE_BIND_POINT_GRAPHICS = 0,
VK_PIPELINE_BIND_POINT_COMPUTE = 1,
+ VK_PIPELINE_BIND_POINT_RAYTRACING_NVX = 1000165000,
VK_PIPELINE_BIND_POINT_BEGIN_RANGE = VK_PIPELINE_BIND_POINT_GRAPHICS,
VK_PIPELINE_BIND_POINT_END_RANGE = VK_PIPELINE_BIND_POINT_COMPUTE,
VK_PIPELINE_BIND_POINT_RANGE_SIZE = (VK_PIPELINE_BIND_POINT_COMPUTE - VK_PIPELINE_BIND_POINT_GRAPHICS + 1),
@@ -1192,6 +1264,7 @@
VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX = 1000086001,
VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT = 1000128000,
VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000,
+ VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NVX = 1000165000,
VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE,
VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION,
VK_OBJECT_TYPE_BEGIN_RANGE = VK_OBJECT_TYPE_UNKNOWN,
@@ -1200,6 +1273,16 @@
VK_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF
} VkObjectType;
+typedef enum VkVendorId {
+ VK_VENDOR_ID_VIV = 0x10001,
+ VK_VENDOR_ID_VSI = 0x10002,
+ VK_VENDOR_ID_KAZAN = 0x10003,
+ VK_VENDOR_ID_BEGIN_RANGE = VK_VENDOR_ID_VIV,
+ VK_VENDOR_ID_END_RANGE = VK_VENDOR_ID_KAZAN,
+ VK_VENDOR_ID_RANGE_SIZE = (VK_VENDOR_ID_KAZAN - VK_VENDOR_ID_VIV + 1),
+ VK_VENDOR_ID_MAX_ENUM = 0x7FFFFFFF
+} VkVendorId;
+
typedef VkFlags VkInstanceCreateFlags;
typedef enum VkFormatFeatureFlagBits {
@@ -1249,6 +1332,7 @@
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020,
VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040,
VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080,
+ VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV = 0x00000100,
VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkImageUsageFlagBits;
typedef VkFlags VkImageUsageFlags;
@@ -1266,6 +1350,7 @@
VK_IMAGE_CREATE_EXTENDED_USAGE_BIT = 0x00000100,
VK_IMAGE_CREATE_PROTECTED_BIT = 0x00000800,
VK_IMAGE_CREATE_DISJOINT_BIT = 0x00000200,
+ VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV = 0x00002000,
VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0x00001000,
VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT,
VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT,
@@ -1343,7 +1428,12 @@
VK_PIPELINE_STAGE_HOST_BIT = 0x00004000,
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0x00008000,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000,
+ VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000,
VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX = 0x00020000,
+ VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV = 0x00400000,
+ VK_PIPELINE_STAGE_RAYTRACING_BIT_NVX = 0x00200000,
+ VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV = 0x00080000,
+ VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV = 0x00100000,
VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkPipelineStageFlagBits;
typedef VkFlags VkPipelineStageFlags;
@@ -1431,6 +1521,8 @@
VK_BUFFER_USAGE_INDEX_BUFFER_BIT = 0x00000040,
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT = 0x00000080,
VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 0x00000100,
+ VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00000200,
+ VK_BUFFER_USAGE_RAYTRACING_BIT_NVX = 0x00000400,
VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkBufferUsageFlagBits;
typedef VkFlags VkBufferUsageFlags;
@@ -1445,6 +1537,7 @@
VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004,
VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 0x00000008,
VK_PIPELINE_CREATE_DISPATCH_BASE = 0x00000010,
+ VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NVX = 0x00000020,
VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT,
VK_PIPELINE_CREATE_DISPATCH_BASE_KHR = VK_PIPELINE_CREATE_DISPATCH_BASE,
VK_PIPELINE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
@@ -1461,6 +1554,14 @@
VK_SHADER_STAGE_COMPUTE_BIT = 0x00000020,
VK_SHADER_STAGE_ALL_GRAPHICS = 0x0000001F,
VK_SHADER_STAGE_ALL = 0x7FFFFFFF,
+ VK_SHADER_STAGE_RAYGEN_BIT_NVX = 0x00000100,
+ VK_SHADER_STAGE_ANY_HIT_BIT_NVX = 0x00000200,
+ VK_SHADER_STAGE_CLOSEST_HIT_BIT_NVX = 0x00000400,
+ VK_SHADER_STAGE_MISS_BIT_NVX = 0x00000800,
+ VK_SHADER_STAGE_INTERSECTION_BIT_NVX = 0x00001000,
+ VK_SHADER_STAGE_CALLABLE_BIT_NVX = 0x00002000,
+ VK_SHADER_STAGE_TASK_BIT_NV = 0x00000040,
+ VK_SHADER_STAGE_MESH_BIT_NV = 0x00000080,
VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkShaderStageFlagBits;
typedef VkFlags VkPipelineVertexInputStateCreateFlags;
@@ -1496,12 +1597,14 @@
typedef enum VkDescriptorSetLayoutCreateFlagBits {
VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR = 0x00000001,
+ VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT = 0x00000002,
VK_DESCRIPTOR_SET_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkDescriptorSetLayoutCreateFlagBits;
typedef VkFlags VkDescriptorSetLayoutCreateFlags;
typedef enum VkDescriptorPoolCreateFlagBits {
VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0x00000001,
+ VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT = 0x00000002,
VK_DESCRIPTOR_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkDescriptorPoolCreateFlagBits;
typedef VkFlags VkDescriptorPoolCreateFlags;
@@ -1540,9 +1643,13 @@
VK_ACCESS_HOST_WRITE_BIT = 0x00004000,
VK_ACCESS_MEMORY_READ_BIT = 0x00008000,
VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000,
+ VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000,
VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX = 0x00020000,
VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX = 0x00040000,
VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000,
+ VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV = 0x00800000,
+ VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NVX = 0x00200000,
+ VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NVX = 0x00400000,
VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkAccessFlagBits;
typedef VkFlags VkAccessFlags;
@@ -2704,6 +2811,16 @@
uint32_t firstInstance;
} VkDrawIndirectCommand;
+typedef struct VkBaseOutStructure {
+ VkStructureType sType;
+ struct VkBaseOutStructure* pNext;
+} VkBaseOutStructure;
+
+typedef struct VkBaseInStructure {
+ VkStructureType sType;
+ const struct VkBaseInStructure* pNext;
+} VkBaseInStructure;
+
typedef VkResult (VKAPI_PTR *PFN_vkCreateInstance)(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance);
typedef void (VKAPI_PTR *PFN_vkDestroyInstance)(VkInstance instance, const VkAllocationCallbacks* pAllocator);
@@ -3736,6 +3853,7 @@
VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT = 0x00000020,
VK_SUBGROUP_FEATURE_CLUSTERED_BIT = 0x00000040,
VK_SUBGROUP_FEATURE_QUAD_BIT = 0x00000080,
+ VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV = 0x00000100,
VK_SUBGROUP_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkSubgroupFeatureFlagBits;
typedef VkFlags VkSubgroupFeatureFlags;
@@ -3998,6 +4116,8 @@
VkMemoryRequirements memoryRequirements;
} VkMemoryRequirements2;
+typedef VkMemoryRequirements2 VkMemoryRequirements2KHR;
+
typedef struct VkSparseImageMemoryRequirements2 {
VkStructureType sType;
void* pNext;
@@ -4522,7 +4642,6 @@
#define VK_KHR_SURFACE_SPEC_VERSION 25
#define VK_KHR_SURFACE_EXTENSION_NAME "VK_KHR_surface"
-#define VK_COLORSPACE_SRGB_NONLINEAR_KHR VK_COLOR_SPACE_SRGB_NONLINEAR_KHR
typedef enum VkColorSpaceKHR {
@@ -4541,6 +4660,7 @@
VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT = 1000104012,
VK_COLOR_SPACE_PASS_THROUGH_EXT = 1000104013,
VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT = 1000104014,
+ VK_COLORSPACE_SRGB_NONLINEAR_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
VK_COLOR_SPACE_BEGIN_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
VK_COLOR_SPACE_END_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
VK_COLOR_SPACE_RANGE_SIZE_KHR = (VK_COLOR_SPACE_SRGB_NONLINEAR_KHR - VK_COLOR_SPACE_SRGB_NONLINEAR_KHR + 1),
@@ -5095,7 +5215,7 @@
#define VK_KHR_maintenance1 1
-#define VK_KHR_MAINTENANCE1_SPEC_VERSION 1
+#define VK_KHR_MAINTENANCE1_SPEC_VERSION 2
#define VK_KHR_MAINTENANCE1_EXTENSION_NAME "VK_KHR_maintenance1"
typedef VkCommandPoolTrimFlags VkCommandPoolTrimFlagsKHR;
@@ -5398,6 +5518,114 @@
const void* pData);
#endif
+#define VK_KHR_create_renderpass2 1
+#define VK_KHR_CREATE_RENDERPASS_2_SPEC_VERSION 1
+#define VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME "VK_KHR_create_renderpass2"
+
+typedef struct VkAttachmentDescription2KHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkAttachmentDescriptionFlags flags;
+ VkFormat format;
+ VkSampleCountFlagBits samples;
+ VkAttachmentLoadOp loadOp;
+ VkAttachmentStoreOp storeOp;
+ VkAttachmentLoadOp stencilLoadOp;
+ VkAttachmentStoreOp stencilStoreOp;
+ VkImageLayout initialLayout;
+ VkImageLayout finalLayout;
+} VkAttachmentDescription2KHR;
+
+typedef struct VkAttachmentReference2KHR {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t attachment;
+ VkImageLayout layout;
+ VkImageAspectFlags aspectMask;
+} VkAttachmentReference2KHR;
+
+typedef struct VkSubpassDescription2KHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkSubpassDescriptionFlags flags;
+ VkPipelineBindPoint pipelineBindPoint;
+ uint32_t viewMask;
+ uint32_t inputAttachmentCount;
+ const VkAttachmentReference2KHR* pInputAttachments;
+ uint32_t colorAttachmentCount;
+ const VkAttachmentReference2KHR* pColorAttachments;
+ const VkAttachmentReference2KHR* pResolveAttachments;
+ const VkAttachmentReference2KHR* pDepthStencilAttachment;
+ uint32_t preserveAttachmentCount;
+ const uint32_t* pPreserveAttachments;
+} VkSubpassDescription2KHR;
+
+typedef struct VkSubpassDependency2KHR {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t srcSubpass;
+ uint32_t dstSubpass;
+ VkPipelineStageFlags srcStageMask;
+ VkPipelineStageFlags dstStageMask;
+ VkAccessFlags srcAccessMask;
+ VkAccessFlags dstAccessMask;
+ VkDependencyFlags dependencyFlags;
+ int32_t viewOffset;
+} VkSubpassDependency2KHR;
+
+typedef struct VkRenderPassCreateInfo2KHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkRenderPassCreateFlags flags;
+ uint32_t attachmentCount;
+ const VkAttachmentDescription2KHR* pAttachments;
+ uint32_t subpassCount;
+ const VkSubpassDescription2KHR* pSubpasses;
+ uint32_t dependencyCount;
+ const VkSubpassDependency2KHR* pDependencies;
+ uint32_t correlatedViewMaskCount;
+ const uint32_t* pCorrelatedViewMasks;
+} VkRenderPassCreateInfo2KHR;
+
+typedef struct VkSubpassBeginInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkSubpassContents contents;
+} VkSubpassBeginInfoKHR;
+
+typedef struct VkSubpassEndInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+} VkSubpassEndInfoKHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateRenderPass2KHR)(VkDevice device, const VkRenderPassCreateInfo2KHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass);
+typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderPass2KHR)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, const VkSubpassBeginInfoKHR* pSubpassBeginInfo);
+typedef void (VKAPI_PTR *PFN_vkCmdNextSubpass2KHR)(VkCommandBuffer commandBuffer, const VkSubpassBeginInfoKHR* pSubpassBeginInfo, const VkSubpassEndInfoKHR* pSubpassEndInfo);
+typedef void (VKAPI_PTR *PFN_vkCmdEndRenderPass2KHR)(VkCommandBuffer commandBuffer, const VkSubpassEndInfoKHR* pSubpassEndInfo);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass2KHR(
+ VkDevice device,
+ const VkRenderPassCreateInfo2KHR* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkRenderPass* pRenderPass);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass2KHR(
+ VkCommandBuffer commandBuffer,
+ const VkRenderPassBeginInfo* pRenderPassBegin,
+ const VkSubpassBeginInfoKHR* pSubpassBeginInfo);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass2KHR(
+ VkCommandBuffer commandBuffer,
+ const VkSubpassBeginInfoKHR* pSubpassBeginInfo,
+ const VkSubpassEndInfoKHR* pSubpassEndInfo);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass2KHR(
+ VkCommandBuffer commandBuffer,
+ const VkSubpassEndInfoKHR* pSubpassEndInfo);
+#endif
+
#define VK_KHR_shared_presentable_image 1
#define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1
#define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image"
@@ -5560,6 +5788,70 @@
+#define VK_KHR_get_display_properties2 1
+#define VK_KHR_GET_DISPLAY_PROPERTIES_2_SPEC_VERSION 1
+#define VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_display_properties2"
+
+typedef struct VkDisplayProperties2KHR {
+ VkStructureType sType;
+ void* pNext;
+ VkDisplayPropertiesKHR displayProperties;
+} VkDisplayProperties2KHR;
+
+typedef struct VkDisplayPlaneProperties2KHR {
+ VkStructureType sType;
+ void* pNext;
+ VkDisplayPlanePropertiesKHR displayPlaneProperties;
+} VkDisplayPlaneProperties2KHR;
+
+typedef struct VkDisplayModeProperties2KHR {
+ VkStructureType sType;
+ void* pNext;
+ VkDisplayModePropertiesKHR displayModeProperties;
+} VkDisplayModeProperties2KHR;
+
+typedef struct VkDisplayPlaneInfo2KHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkDisplayModeKHR mode;
+ uint32_t planeIndex;
+} VkDisplayPlaneInfo2KHR;
+
+typedef struct VkDisplayPlaneCapabilities2KHR {
+ VkStructureType sType;
+ void* pNext;
+ VkDisplayPlaneCapabilitiesKHR capabilities;
+} VkDisplayPlaneCapabilities2KHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayProperties2KHR* pProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlaneProperties2KHR* pProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayModeProperties2KHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModeProperties2KHR* pProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkDisplayPlaneInfo2KHR* pDisplayPlaneInfo, VkDisplayPlaneCapabilities2KHR* pCapabilities);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pPropertyCount,
+ VkDisplayProperties2KHR* pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPlaneProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pPropertyCount,
+ VkDisplayPlaneProperties2KHR* pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModeProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ VkDisplayKHR display,
+ uint32_t* pPropertyCount,
+ VkDisplayModeProperties2KHR* pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilities2KHR(
+ VkPhysicalDevice physicalDevice,
+ const VkDisplayPlaneInfo2KHR* pDisplayPlaneInfo,
+ VkDisplayPlaneCapabilities2KHR* pCapabilities);
+#endif
+
#define VK_KHR_dedicated_allocation 1
#define VK_KHR_DEDICATED_ALLOCATION_SPEC_VERSION 3
#define VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_KHR_dedicated_allocation"
@@ -5590,8 +5882,6 @@
typedef VkImageSparseMemoryRequirementsInfo2 VkImageSparseMemoryRequirementsInfo2KHR;
-typedef VkMemoryRequirements2 VkMemoryRequirements2KHR;
-
typedef VkSparseImageMemoryRequirements2 VkSparseImageMemoryRequirements2KHR;
@@ -5715,13 +6005,119 @@
VkDescriptorSetLayoutSupport* pSupport);
#endif
+#define VK_KHR_draw_indirect_count 1
+#define VK_KHR_DRAW_INDIRECT_COUNT_SPEC_VERSION 1
+#define VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_KHR_draw_indirect_count"
+
+typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCountKHR)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
+typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCountKHR)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountKHR(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ VkBuffer countBuffer,
+ VkDeviceSize countBufferOffset,
+ uint32_t maxDrawCount,
+ uint32_t stride);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountKHR(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ VkBuffer countBuffer,
+ VkDeviceSize countBufferOffset,
+ uint32_t maxDrawCount,
+ uint32_t stride);
+#endif
+
+#define VK_KHR_8bit_storage 1
+#define VK_KHR_8BIT_STORAGE_SPEC_VERSION 1
+#define VK_KHR_8BIT_STORAGE_EXTENSION_NAME "VK_KHR_8bit_storage"
+
+typedef struct VkPhysicalDevice8BitStorageFeaturesKHR {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 storageBuffer8BitAccess;
+ VkBool32 uniformAndStorageBuffer8BitAccess;
+ VkBool32 storagePushConstant8;
+} VkPhysicalDevice8BitStorageFeaturesKHR;
+
+
+
+#define VK_KHR_shader_atomic_int64 1
+#define VK_KHR_SHADER_ATOMIC_INT64_SPEC_VERSION 1
+#define VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME "VK_KHR_shader_atomic_int64"
+
+typedef struct VkPhysicalDeviceShaderAtomicInt64FeaturesKHR {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 shaderBufferInt64Atomics;
+ VkBool32 shaderSharedInt64Atomics;
+} VkPhysicalDeviceShaderAtomicInt64FeaturesKHR;
+
+
+
+#define VK_KHR_driver_properties 1
+#define VK_MAX_DRIVER_NAME_SIZE_KHR 256
+#define VK_MAX_DRIVER_INFO_SIZE_KHR 256
+#define VK_KHR_DRIVER_PROPERTIES_SPEC_VERSION 1
+#define VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME "VK_KHR_driver_properties"
+
+
+typedef enum VkDriverIdKHR {
+ VK_DRIVER_ID_AMD_PROPRIETARY_KHR = 1,
+ VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR = 2,
+ VK_DRIVER_ID_MESA_RADV_KHR = 3,
+ VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR = 4,
+ VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR = 5,
+ VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR = 6,
+ VK_DRIVER_ID_IMAGINATION_PROPRIETARY_KHR = 7,
+ VK_DRIVER_ID_QUALCOMM_PROPRIETARY_KHR = 8,
+ VK_DRIVER_ID_ARM_PROPRIETARY_KHR = 9,
+ VK_DRIVER_ID_BEGIN_RANGE_KHR = VK_DRIVER_ID_AMD_PROPRIETARY_KHR,
+ VK_DRIVER_ID_END_RANGE_KHR = VK_DRIVER_ID_ARM_PROPRIETARY_KHR,
+ VK_DRIVER_ID_RANGE_SIZE_KHR = (VK_DRIVER_ID_ARM_PROPRIETARY_KHR - VK_DRIVER_ID_AMD_PROPRIETARY_KHR + 1),
+ VK_DRIVER_ID_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkDriverIdKHR;
+
+typedef struct VkConformanceVersionKHR {
+ uint8_t major;
+ uint8_t minor;
+ uint8_t subminor;
+ uint8_t patch;
+} VkConformanceVersionKHR;
+
+typedef struct VkPhysicalDeviceDriverPropertiesKHR {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t driverID;
+ char driverName[VK_MAX_DRIVER_NAME_SIZE_KHR];
+ char driverInfo[VK_MAX_DRIVER_INFO_SIZE_KHR];
+ VkConformanceVersionKHR conformanceVersion;
+} VkPhysicalDeviceDriverPropertiesKHR;
+
+
+
+#define VK_KHR_vulkan_memory_model 1
+#define VK_KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION 2
+#define VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME "VK_KHR_vulkan_memory_model"
+
+typedef struct VkPhysicalDeviceVulkanMemoryModelFeaturesKHR {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 vulkanMemoryModel;
+ VkBool32 vulkanMemoryModelDeviceScope;
+} VkPhysicalDeviceVulkanMemoryModelFeaturesKHR;
+
+
+
#define VK_EXT_debug_report 1
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT)
#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 9
#define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report"
-#define VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT
-#define VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT
typedef enum VkDebugReportObjectTypeEXT {
@@ -5761,6 +6157,9 @@
VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT = 33,
VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT = 1000156000,
VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT = 1000085000,
+ VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NVX_EXT = 1000165000,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT,
+ VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT,
VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT,
VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT,
VK_DEBUG_REPORT_OBJECT_TYPE_BEGIN_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
@@ -6065,6 +6464,18 @@
#define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME "VK_AMD_shader_image_load_store_lod"
+#define VK_NV_corner_sampled_image 1
+#define VK_NV_CORNER_SAMPLED_IMAGE_SPEC_VERSION 2
+#define VK_NV_CORNER_SAMPLED_IMAGE_EXTENSION_NAME "VK_NV_corner_sampled_image"
+
+typedef struct VkPhysicalDeviceCornerSampledImageFeaturesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 cornerSampledImage;
+} VkPhysicalDeviceCornerSampledImageFeaturesNV;
+
+
+
#define VK_IMG_format_pvrtc 1
#define VK_IMG_FORMAT_PVRTC_SPEC_VERSION 1
#define VK_IMG_FORMAT_PVRTC_EXTENSION_NAME "VK_IMG_format_pvrtc"
@@ -6147,10 +6558,10 @@
} VkValidationCheckEXT;
typedef struct VkValidationFlagsEXT {
- VkStructureType sType;
- const void* pNext;
- uint32_t disabledValidationCheckCount;
- VkValidationCheckEXT* pDisabledValidationChecks;
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t disabledValidationCheckCount;
+ const VkValidationCheckEXT* pDisabledValidationChecks;
} VkValidationFlagsEXT;
@@ -6165,6 +6576,69 @@
#define VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME "VK_EXT_shader_subgroup_vote"
+#define VK_EXT_astc_decode_mode 1
+#define VK_EXT_ASTC_DECODE_MODE_SPEC_VERSION 1
+#define VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME "VK_EXT_astc_decode_mode"
+
+typedef struct VkImageViewASTCDecodeModeEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkFormat decodeMode;
+} VkImageViewASTCDecodeModeEXT;
+
+typedef struct VkPhysicalDeviceASTCDecodeFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 decodeModeSharedExponent;
+} VkPhysicalDeviceASTCDecodeFeaturesEXT;
+
+
+
+#define VK_EXT_conditional_rendering 1
+#define VK_EXT_CONDITIONAL_RENDERING_SPEC_VERSION 1
+#define VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME "VK_EXT_conditional_rendering"
+
+
+typedef enum VkConditionalRenderingFlagBitsEXT {
+ VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT = 0x00000001,
+ VK_CONDITIONAL_RENDERING_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkConditionalRenderingFlagBitsEXT;
+typedef VkFlags VkConditionalRenderingFlagsEXT;
+
+typedef struct VkConditionalRenderingBeginInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkBuffer buffer;
+ VkDeviceSize offset;
+ VkConditionalRenderingFlagsEXT flags;
+} VkConditionalRenderingBeginInfoEXT;
+
+typedef struct VkPhysicalDeviceConditionalRenderingFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 conditionalRendering;
+ VkBool32 inheritedConditionalRendering;
+} VkPhysicalDeviceConditionalRenderingFeaturesEXT;
+
+typedef struct VkCommandBufferInheritanceConditionalRenderingInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkBool32 conditionalRenderingEnable;
+} VkCommandBufferInheritanceConditionalRenderingInfoEXT;
+
+
+typedef void (VKAPI_PTR *PFN_vkCmdBeginConditionalRenderingEXT)(VkCommandBuffer commandBuffer, const VkConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin);
+typedef void (VKAPI_PTR *PFN_vkCmdEndConditionalRenderingEXT)(VkCommandBuffer commandBuffer);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdBeginConditionalRenderingEXT(
+ VkCommandBuffer commandBuffer,
+ const VkConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdEndConditionalRenderingEXT(
+ VkCommandBuffer commandBuffer);
+#endif
+
#define VK_NVX_device_generated_commands 1
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkObjectTableNVX)
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNVX)
@@ -6435,7 +6909,6 @@
#define VK_EXT_display_surface_counter 1
#define VK_EXT_DISPLAY_SURFACE_COUNTER_SPEC_VERSION 1
#define VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME "VK_EXT_display_surface_counter"
-#define VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT
typedef enum VkSurfaceCounterFlagBitsEXT {
@@ -6989,6 +7462,42 @@
#define VK_AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME "VK_AMD_shader_fragment_mask"
+#define VK_EXT_inline_uniform_block 1
+#define VK_EXT_INLINE_UNIFORM_BLOCK_SPEC_VERSION 1
+#define VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME "VK_EXT_inline_uniform_block"
+
+typedef struct VkPhysicalDeviceInlineUniformBlockFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 inlineUniformBlock;
+ VkBool32 descriptorBindingInlineUniformBlockUpdateAfterBind;
+} VkPhysicalDeviceInlineUniformBlockFeaturesEXT;
+
+typedef struct VkPhysicalDeviceInlineUniformBlockPropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t maxInlineUniformBlockSize;
+ uint32_t maxPerStageDescriptorInlineUniformBlocks;
+ uint32_t maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks;
+ uint32_t maxDescriptorSetInlineUniformBlocks;
+ uint32_t maxDescriptorSetUpdateAfterBindInlineUniformBlocks;
+} VkPhysicalDeviceInlineUniformBlockPropertiesEXT;
+
+typedef struct VkWriteDescriptorSetInlineUniformBlockEXT {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t dataSize;
+ const void* pData;
+} VkWriteDescriptorSetInlineUniformBlockEXT;
+
+typedef struct VkDescriptorPoolInlineUniformBlockCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t maxInlineUniformBlockBindings;
+} VkDescriptorPoolInlineUniformBlockCreateInfoEXT;
+
+
+
#define VK_EXT_shader_stencil_export 1
#define VK_EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION 1
#define VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME "VK_EXT_shader_stencil_export"
@@ -7172,7 +7681,6 @@
#define VK_EXT_VALIDATION_CACHE_SPEC_VERSION 1
#define VK_EXT_VALIDATION_CACHE_EXTENSION_NAME "VK_EXT_validation_cache"
-#define VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT
typedef enum VkValidationCacheHeaderVersionEXT {
@@ -7230,11 +7738,491 @@
void* pData);
#endif
+#define VK_EXT_descriptor_indexing 1
+#define VK_EXT_DESCRIPTOR_INDEXING_SPEC_VERSION 2
+#define VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME "VK_EXT_descriptor_indexing"
+
+
+typedef enum VkDescriptorBindingFlagBitsEXT {
+ VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT = 0x00000001,
+ VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT = 0x00000002,
+ VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT = 0x00000004,
+ VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT = 0x00000008,
+ VK_DESCRIPTOR_BINDING_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkDescriptorBindingFlagBitsEXT;
+typedef VkFlags VkDescriptorBindingFlagsEXT;
+
+typedef struct VkDescriptorSetLayoutBindingFlagsCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t bindingCount;
+ const VkDescriptorBindingFlagsEXT* pBindingFlags;
+} VkDescriptorSetLayoutBindingFlagsCreateInfoEXT;
+
+typedef struct VkPhysicalDeviceDescriptorIndexingFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 shaderInputAttachmentArrayDynamicIndexing;
+ VkBool32 shaderUniformTexelBufferArrayDynamicIndexing;
+ VkBool32 shaderStorageTexelBufferArrayDynamicIndexing;
+ VkBool32 shaderUniformBufferArrayNonUniformIndexing;
+ VkBool32 shaderSampledImageArrayNonUniformIndexing;
+ VkBool32 shaderStorageBufferArrayNonUniformIndexing;
+ VkBool32 shaderStorageImageArrayNonUniformIndexing;
+ VkBool32 shaderInputAttachmentArrayNonUniformIndexing;
+ VkBool32 shaderUniformTexelBufferArrayNonUniformIndexing;
+ VkBool32 shaderStorageTexelBufferArrayNonUniformIndexing;
+ VkBool32 descriptorBindingUniformBufferUpdateAfterBind;
+ VkBool32 descriptorBindingSampledImageUpdateAfterBind;
+ VkBool32 descriptorBindingStorageImageUpdateAfterBind;
+ VkBool32 descriptorBindingStorageBufferUpdateAfterBind;
+ VkBool32 descriptorBindingUniformTexelBufferUpdateAfterBind;
+ VkBool32 descriptorBindingStorageTexelBufferUpdateAfterBind;
+ VkBool32 descriptorBindingUpdateUnusedWhilePending;
+ VkBool32 descriptorBindingPartiallyBound;
+ VkBool32 descriptorBindingVariableDescriptorCount;
+ VkBool32 runtimeDescriptorArray;
+} VkPhysicalDeviceDescriptorIndexingFeaturesEXT;
+
+typedef struct VkPhysicalDeviceDescriptorIndexingPropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t maxUpdateAfterBindDescriptorsInAllPools;
+ VkBool32 shaderUniformBufferArrayNonUniformIndexingNative;
+ VkBool32 shaderSampledImageArrayNonUniformIndexingNative;
+ VkBool32 shaderStorageBufferArrayNonUniformIndexingNative;
+ VkBool32 shaderStorageImageArrayNonUniformIndexingNative;
+ VkBool32 shaderInputAttachmentArrayNonUniformIndexingNative;
+ VkBool32 robustBufferAccessUpdateAfterBind;
+ VkBool32 quadDivergentImplicitLod;
+ uint32_t maxPerStageDescriptorUpdateAfterBindSamplers;
+ uint32_t maxPerStageDescriptorUpdateAfterBindUniformBuffers;
+ uint32_t maxPerStageDescriptorUpdateAfterBindStorageBuffers;
+ uint32_t maxPerStageDescriptorUpdateAfterBindSampledImages;
+ uint32_t maxPerStageDescriptorUpdateAfterBindStorageImages;
+ uint32_t maxPerStageDescriptorUpdateAfterBindInputAttachments;
+ uint32_t maxPerStageUpdateAfterBindResources;
+ uint32_t maxDescriptorSetUpdateAfterBindSamplers;
+ uint32_t maxDescriptorSetUpdateAfterBindUniformBuffers;
+ uint32_t maxDescriptorSetUpdateAfterBindUniformBuffersDynamic;
+ uint32_t maxDescriptorSetUpdateAfterBindStorageBuffers;
+ uint32_t maxDescriptorSetUpdateAfterBindStorageBuffersDynamic;
+ uint32_t maxDescriptorSetUpdateAfterBindSampledImages;
+ uint32_t maxDescriptorSetUpdateAfterBindStorageImages;
+ uint32_t maxDescriptorSetUpdateAfterBindInputAttachments;
+} VkPhysicalDeviceDescriptorIndexingPropertiesEXT;
+
+typedef struct VkDescriptorSetVariableDescriptorCountAllocateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t descriptorSetCount;
+ const uint32_t* pDescriptorCounts;
+} VkDescriptorSetVariableDescriptorCountAllocateInfoEXT;
+
+typedef struct VkDescriptorSetVariableDescriptorCountLayoutSupportEXT {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t maxVariableDescriptorCount;
+} VkDescriptorSetVariableDescriptorCountLayoutSupportEXT;
+
+
+
#define VK_EXT_shader_viewport_index_layer 1
#define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_SPEC_VERSION 1
#define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME "VK_EXT_shader_viewport_index_layer"
+#define VK_NV_shading_rate_image 1
+#define VK_NV_SHADING_RATE_IMAGE_SPEC_VERSION 3
+#define VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME "VK_NV_shading_rate_image"
+
+
+typedef enum VkShadingRatePaletteEntryNV {
+ VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV = 0,
+ VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV = 1,
+ VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV = 2,
+ VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV = 3,
+ VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV = 4,
+ VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV = 5,
+ VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV = 6,
+ VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV = 7,
+ VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV = 8,
+ VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV = 9,
+ VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV = 10,
+ VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV = 11,
+ VK_SHADING_RATE_PALETTE_ENTRY_BEGIN_RANGE_NV = VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV,
+ VK_SHADING_RATE_PALETTE_ENTRY_END_RANGE_NV = VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV,
+ VK_SHADING_RATE_PALETTE_ENTRY_RANGE_SIZE_NV = (VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV - VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV + 1),
+ VK_SHADING_RATE_PALETTE_ENTRY_MAX_ENUM_NV = 0x7FFFFFFF
+} VkShadingRatePaletteEntryNV;
+
+typedef enum VkCoarseSampleOrderTypeNV {
+ VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV = 0,
+ VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV = 1,
+ VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV = 2,
+ VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV = 3,
+ VK_COARSE_SAMPLE_ORDER_TYPE_BEGIN_RANGE_NV = VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV,
+ VK_COARSE_SAMPLE_ORDER_TYPE_END_RANGE_NV = VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV,
+ VK_COARSE_SAMPLE_ORDER_TYPE_RANGE_SIZE_NV = (VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV - VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV + 1),
+ VK_COARSE_SAMPLE_ORDER_TYPE_MAX_ENUM_NV = 0x7FFFFFFF
+} VkCoarseSampleOrderTypeNV;
+
+typedef struct VkShadingRatePaletteNV {
+ uint32_t shadingRatePaletteEntryCount;
+ const VkShadingRatePaletteEntryNV* pShadingRatePaletteEntries;
+} VkShadingRatePaletteNV;
+
+typedef struct VkPipelineViewportShadingRateImageStateCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkBool32 shadingRateImageEnable;
+ uint32_t viewportCount;
+ const VkShadingRatePaletteNV* pShadingRatePalettes;
+} VkPipelineViewportShadingRateImageStateCreateInfoNV;
+
+typedef struct VkPhysicalDeviceShadingRateImageFeaturesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 shadingRateImage;
+ VkBool32 shadingRateCoarseSampleOrder;
+} VkPhysicalDeviceShadingRateImageFeaturesNV;
+
+typedef struct VkPhysicalDeviceShadingRateImagePropertiesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkExtent2D shadingRateTexelSize;
+ uint32_t shadingRatePaletteSize;
+ uint32_t shadingRateMaxCoarseSamples;
+} VkPhysicalDeviceShadingRateImagePropertiesNV;
+
+typedef struct VkCoarseSampleLocationNV {
+ uint32_t pixelX;
+ uint32_t pixelY;
+ uint32_t sample;
+} VkCoarseSampleLocationNV;
+
+typedef struct VkCoarseSampleOrderCustomNV {
+ VkShadingRatePaletteEntryNV shadingRate;
+ uint32_t sampleCount;
+ uint32_t sampleLocationCount;
+ const VkCoarseSampleLocationNV* pSampleLocations;
+} VkCoarseSampleOrderCustomNV;
+
+typedef struct VkPipelineViewportCoarseSampleOrderStateCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkCoarseSampleOrderTypeNV sampleOrderType;
+ uint32_t customSampleOrderCount;
+ const VkCoarseSampleOrderCustomNV* pCustomSampleOrders;
+} VkPipelineViewportCoarseSampleOrderStateCreateInfoNV;
+
+
+typedef void (VKAPI_PTR *PFN_vkCmdBindShadingRateImageNV)(VkCommandBuffer commandBuffer, VkImageView imageView, VkImageLayout imageLayout);
+typedef void (VKAPI_PTR *PFN_vkCmdSetViewportShadingRatePaletteNV)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkShadingRatePaletteNV* pShadingRatePalettes);
+typedef void (VKAPI_PTR *PFN_vkCmdSetCoarseSampleOrderNV)(VkCommandBuffer commandBuffer, VkCoarseSampleOrderTypeNV sampleOrderType, uint32_t customSampleOrderCount, const VkCoarseSampleOrderCustomNV* pCustomSampleOrders);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdBindShadingRateImageNV(
+ VkCommandBuffer commandBuffer,
+ VkImageView imageView,
+ VkImageLayout imageLayout);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportShadingRatePaletteNV(
+ VkCommandBuffer commandBuffer,
+ uint32_t firstViewport,
+ uint32_t viewportCount,
+ const VkShadingRatePaletteNV* pShadingRatePalettes);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetCoarseSampleOrderNV(
+ VkCommandBuffer commandBuffer,
+ VkCoarseSampleOrderTypeNV sampleOrderType,
+ uint32_t customSampleOrderCount,
+ const VkCoarseSampleOrderCustomNV* pCustomSampleOrders);
+#endif
+
+#define VK_NVX_raytracing 1
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureNVX)
+
+#define VK_NVX_RAYTRACING_SPEC_VERSION 1
+#define VK_NVX_RAYTRACING_EXTENSION_NAME "VK_NVX_raytracing"
+
+
+typedef enum VkGeometryTypeNVX {
+ VK_GEOMETRY_TYPE_TRIANGLES_NVX = 0,
+ VK_GEOMETRY_TYPE_AABBS_NVX = 1,
+ VK_GEOMETRY_TYPE_BEGIN_RANGE_NVX = VK_GEOMETRY_TYPE_TRIANGLES_NVX,
+ VK_GEOMETRY_TYPE_END_RANGE_NVX = VK_GEOMETRY_TYPE_AABBS_NVX,
+ VK_GEOMETRY_TYPE_RANGE_SIZE_NVX = (VK_GEOMETRY_TYPE_AABBS_NVX - VK_GEOMETRY_TYPE_TRIANGLES_NVX + 1),
+ VK_GEOMETRY_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF
+} VkGeometryTypeNVX;
+
+typedef enum VkAccelerationStructureTypeNVX {
+ VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NVX = 0,
+ VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NVX = 1,
+ VK_ACCELERATION_STRUCTURE_TYPE_BEGIN_RANGE_NVX = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NVX,
+ VK_ACCELERATION_STRUCTURE_TYPE_END_RANGE_NVX = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NVX,
+ VK_ACCELERATION_STRUCTURE_TYPE_RANGE_SIZE_NVX = (VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NVX - VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NVX + 1),
+ VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF
+} VkAccelerationStructureTypeNVX;
+
+typedef enum VkCopyAccelerationStructureModeNVX {
+ VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NVX = 0,
+ VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NVX = 1,
+ VK_COPY_ACCELERATION_STRUCTURE_MODE_BEGIN_RANGE_NVX = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NVX,
+ VK_COPY_ACCELERATION_STRUCTURE_MODE_END_RANGE_NVX = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NVX,
+ VK_COPY_ACCELERATION_STRUCTURE_MODE_RANGE_SIZE_NVX = (VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NVX - VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NVX + 1),
+ VK_COPY_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_NVX = 0x7FFFFFFF
+} VkCopyAccelerationStructureModeNVX;
+
+
+typedef enum VkGeometryFlagBitsNVX {
+ VK_GEOMETRY_OPAQUE_BIT_NVX = 0x00000001,
+ VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NVX = 0x00000002,
+ VK_GEOMETRY_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF
+} VkGeometryFlagBitsNVX;
+typedef VkFlags VkGeometryFlagsNVX;
+
+typedef enum VkGeometryInstanceFlagBitsNVX {
+ VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NVX = 0x00000001,
+ VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_FLIP_WINDING_BIT_NVX = 0x00000002,
+ VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NVX = 0x00000004,
+ VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NVX = 0x00000008,
+ VK_GEOMETRY_INSTANCE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF
+} VkGeometryInstanceFlagBitsNVX;
+typedef VkFlags VkGeometryInstanceFlagsNVX;
+
+typedef enum VkBuildAccelerationStructureFlagBitsNVX {
+ VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NVX = 0x00000001,
+ VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NVX = 0x00000002,
+ VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NVX = 0x00000004,
+ VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NVX = 0x00000008,
+ VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NVX = 0x00000010,
+ VK_BUILD_ACCELERATION_STRUCTURE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF
+} VkBuildAccelerationStructureFlagBitsNVX;
+typedef VkFlags VkBuildAccelerationStructureFlagsNVX;
+
+typedef struct VkRaytracingPipelineCreateInfoNVX {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineCreateFlags flags;
+ uint32_t stageCount;
+ const VkPipelineShaderStageCreateInfo* pStages;
+ const uint32_t* pGroupNumbers;
+ uint32_t maxRecursionDepth;
+ VkPipelineLayout layout;
+ VkPipeline basePipelineHandle;
+ int32_t basePipelineIndex;
+} VkRaytracingPipelineCreateInfoNVX;
+
+typedef struct VkGeometryTrianglesNVX {
+ VkStructureType sType;
+ const void* pNext;
+ VkBuffer vertexData;
+ VkDeviceSize vertexOffset;
+ uint32_t vertexCount;
+ VkDeviceSize vertexStride;
+ VkFormat vertexFormat;
+ VkBuffer indexData;
+ VkDeviceSize indexOffset;
+ uint32_t indexCount;
+ VkIndexType indexType;
+ VkBuffer transformData;
+ VkDeviceSize transformOffset;
+} VkGeometryTrianglesNVX;
+
+typedef struct VkGeometryAABBNVX {
+ VkStructureType sType;
+ const void* pNext;
+ VkBuffer aabbData;
+ uint32_t numAABBs;
+ uint32_t stride;
+ VkDeviceSize offset;
+} VkGeometryAABBNVX;
+
+typedef struct VkGeometryDataNVX {
+ VkGeometryTrianglesNVX triangles;
+ VkGeometryAABBNVX aabbs;
+} VkGeometryDataNVX;
+
+typedef struct VkGeometryNVX {
+ VkStructureType sType;
+ const void* pNext;
+ VkGeometryTypeNVX geometryType;
+ VkGeometryDataNVX geometry;
+ VkGeometryFlagsNVX flags;
+} VkGeometryNVX;
+
+typedef struct VkAccelerationStructureCreateInfoNVX {
+ VkStructureType sType;
+ const void* pNext;
+ VkAccelerationStructureTypeNVX type;
+ VkBuildAccelerationStructureFlagsNVX flags;
+ VkDeviceSize compactedSize;
+ uint32_t instanceCount;
+ uint32_t geometryCount;
+ const VkGeometryNVX* pGeometries;
+} VkAccelerationStructureCreateInfoNVX;
+
+typedef struct VkBindAccelerationStructureMemoryInfoNVX {
+ VkStructureType sType;
+ const void* pNext;
+ VkAccelerationStructureNVX accelerationStructure;
+ VkDeviceMemory memory;
+ VkDeviceSize memoryOffset;
+ uint32_t deviceIndexCount;
+ const uint32_t* pDeviceIndices;
+} VkBindAccelerationStructureMemoryInfoNVX;
+
+typedef struct VkDescriptorAccelerationStructureInfoNVX {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t accelerationStructureCount;
+ const VkAccelerationStructureNVX* pAccelerationStructures;
+} VkDescriptorAccelerationStructureInfoNVX;
+
+typedef struct VkAccelerationStructureMemoryRequirementsInfoNVX {
+ VkStructureType sType;
+ const void* pNext;
+ VkAccelerationStructureNVX accelerationStructure;
+} VkAccelerationStructureMemoryRequirementsInfoNVX;
+
+typedef struct VkPhysicalDeviceRaytracingPropertiesNVX {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t shaderHeaderSize;
+ uint32_t maxRecursionDepth;
+ uint32_t maxGeometryCount;
+} VkPhysicalDeviceRaytracingPropertiesNVX;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureNVX)(VkDevice device, const VkAccelerationStructureCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureNVX* pAccelerationStructure);
+typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureNVX)(VkDevice device, VkAccelerationStructureNVX accelerationStructure, const VkAllocationCallbacks* pAllocator);
+typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureMemoryRequirementsNVX)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNVX* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureScratchMemoryRequirementsNVX)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNVX* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements);
+typedef VkResult (VKAPI_PTR *PFN_vkBindAccelerationStructureMemoryNVX)(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoNVX* pBindInfos);
+typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureNVX)(VkCommandBuffer commandBuffer, VkAccelerationStructureTypeNVX type, uint32_t instanceCount, VkBuffer instanceData, VkDeviceSize instanceOffset, uint32_t geometryCount, const VkGeometryNVX* pGeometries, VkBuildAccelerationStructureFlagsNVX flags, VkBool32 update, VkAccelerationStructureNVX dst, VkAccelerationStructureNVX src, VkBuffer scratch, VkDeviceSize scratchOffset);
+typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureNVX)(VkCommandBuffer commandBuffer, VkAccelerationStructureNVX dst, VkAccelerationStructureNVX src, VkCopyAccelerationStructureModeNVX mode);
+typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysNVX)(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset, VkDeviceSize hitShaderBindingStride, uint32_t width, uint32_t height);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateRaytracingPipelinesNVX)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRaytracingPipelineCreateInfoNVX* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines);
+typedef VkResult (VKAPI_PTR *PFN_vkGetRaytracingShaderHandlesNVX)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData);
+typedef VkResult (VKAPI_PTR *PFN_vkGetAccelerationStructureHandleNVX)(VkDevice device, VkAccelerationStructureNVX accelerationStructure, size_t dataSize, void* pData);
+typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructurePropertiesNVX)(VkCommandBuffer commandBuffer, VkAccelerationStructureNVX accelerationStructure, VkQueryType queryType, VkQueryPool queryPool, uint32_t query);
+typedef VkResult (VKAPI_PTR *PFN_vkCompileDeferredNVX)(VkDevice device, VkPipeline pipeline, uint32_t shader);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureNVX(
+ VkDevice device,
+ const VkAccelerationStructureCreateInfoNVX* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkAccelerationStructureNVX* pAccelerationStructure);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureNVX(
+ VkDevice device,
+ VkAccelerationStructureNVX accelerationStructure,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureMemoryRequirementsNVX(
+ VkDevice device,
+ const VkAccelerationStructureMemoryRequirementsInfoNVX* pInfo,
+ VkMemoryRequirements2KHR* pMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureScratchMemoryRequirementsNVX(
+ VkDevice device,
+ const VkAccelerationStructureMemoryRequirementsInfoNVX* pInfo,
+ VkMemoryRequirements2KHR* pMemoryRequirements);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkBindAccelerationStructureMemoryNVX(
+ VkDevice device,
+ uint32_t bindInfoCount,
+ const VkBindAccelerationStructureMemoryInfoNVX* pBindInfos);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureNVX(
+ VkCommandBuffer commandBuffer,
+ VkAccelerationStructureTypeNVX type,
+ uint32_t instanceCount,
+ VkBuffer instanceData,
+ VkDeviceSize instanceOffset,
+ uint32_t geometryCount,
+ const VkGeometryNVX* pGeometries,
+ VkBuildAccelerationStructureFlagsNVX flags,
+ VkBool32 update,
+ VkAccelerationStructureNVX dst,
+ VkAccelerationStructureNVX src,
+ VkBuffer scratch,
+ VkDeviceSize scratchOffset);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureNVX(
+ VkCommandBuffer commandBuffer,
+ VkAccelerationStructureNVX dst,
+ VkAccelerationStructureNVX src,
+ VkCopyAccelerationStructureModeNVX mode);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysNVX(
+ VkCommandBuffer commandBuffer,
+ VkBuffer raygenShaderBindingTableBuffer,
+ VkDeviceSize raygenShaderBindingOffset,
+ VkBuffer missShaderBindingTableBuffer,
+ VkDeviceSize missShaderBindingOffset,
+ VkDeviceSize missShaderBindingStride,
+ VkBuffer hitShaderBindingTableBuffer,
+ VkDeviceSize hitShaderBindingOffset,
+ VkDeviceSize hitShaderBindingStride,
+ uint32_t width,
+ uint32_t height);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateRaytracingPipelinesNVX(
+ VkDevice device,
+ VkPipelineCache pipelineCache,
+ uint32_t createInfoCount,
+ const VkRaytracingPipelineCreateInfoNVX* pCreateInfos,
+ const VkAllocationCallbacks* pAllocator,
+ VkPipeline* pPipelines);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetRaytracingShaderHandlesNVX(
+ VkDevice device,
+ VkPipeline pipeline,
+ uint32_t firstGroup,
+ uint32_t groupCount,
+ size_t dataSize,
+ void* pData);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetAccelerationStructureHandleNVX(
+ VkDevice device,
+ VkAccelerationStructureNVX accelerationStructure,
+ size_t dataSize,
+ void* pData);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructurePropertiesNVX(
+ VkCommandBuffer commandBuffer,
+ VkAccelerationStructureNVX accelerationStructure,
+ VkQueryType queryType,
+ VkQueryPool queryPool,
+ uint32_t query);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCompileDeferredNVX(
+ VkDevice device,
+ VkPipeline pipeline,
+ uint32_t shader);
+#endif
+
+#define VK_NV_representative_fragment_test 1
+#define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_SPEC_VERSION 1
+#define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_EXTENSION_NAME "VK_NV_representative_fragment_test"
+
+typedef struct VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 representativeFragmentTest;
+} VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV;
+
+typedef struct VkPipelineRepresentativeFragmentTestStateCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkBool32 representativeFragmentTestEnable;
+} VkPipelineRepresentativeFragmentTestStateCreateInfoNV;
+
+
+
#define VK_EXT_global_priority 1
#define VK_EXT_GLOBAL_PRIORITY_SPEC_VERSION 2
#define VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME "VK_EXT_global_priority"
@@ -7293,6 +8281,241 @@
VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties);
#endif
+#define VK_AMD_buffer_marker 1
+#define VK_AMD_BUFFER_MARKER_SPEC_VERSION 1
+#define VK_AMD_BUFFER_MARKER_EXTENSION_NAME "VK_AMD_buffer_marker"
+
+typedef void (VKAPI_PTR *PFN_vkCmdWriteBufferMarkerAMD)(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdWriteBufferMarkerAMD(
+ VkCommandBuffer commandBuffer,
+ VkPipelineStageFlagBits pipelineStage,
+ VkBuffer dstBuffer,
+ VkDeviceSize dstOffset,
+ uint32_t marker);
+#endif
+
+#define VK_AMD_shader_core_properties 1
+#define VK_AMD_SHADER_CORE_PROPERTIES_SPEC_VERSION 1
+#define VK_AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME "VK_AMD_shader_core_properties"
+
+typedef struct VkPhysicalDeviceShaderCorePropertiesAMD {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t shaderEngineCount;
+ uint32_t shaderArraysPerEngineCount;
+ uint32_t computeUnitsPerShaderArray;
+ uint32_t simdPerComputeUnit;
+ uint32_t wavefrontsPerSimd;
+ uint32_t wavefrontSize;
+ uint32_t sgprsPerSimd;
+ uint32_t minSgprAllocation;
+ uint32_t maxSgprAllocation;
+ uint32_t sgprAllocationGranularity;
+ uint32_t vgprsPerSimd;
+ uint32_t minVgprAllocation;
+ uint32_t maxVgprAllocation;
+ uint32_t vgprAllocationGranularity;
+} VkPhysicalDeviceShaderCorePropertiesAMD;
+
+
+
+#define VK_EXT_vertex_attribute_divisor 1
+#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 3
+#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor"
+
+typedef struct VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t maxVertexAttribDivisor;
+} VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT;
+
+typedef struct VkVertexInputBindingDivisorDescriptionEXT {
+ uint32_t binding;
+ uint32_t divisor;
+} VkVertexInputBindingDivisorDescriptionEXT;
+
+typedef struct VkPipelineVertexInputDivisorStateCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t vertexBindingDivisorCount;
+ const VkVertexInputBindingDivisorDescriptionEXT* pVertexBindingDivisors;
+} VkPipelineVertexInputDivisorStateCreateInfoEXT;
+
+typedef struct VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 vertexAttributeInstanceRateDivisor;
+ VkBool32 vertexAttributeInstanceRateZeroDivisor;
+} VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT;
+
+
+
+#define VK_NV_shader_subgroup_partitioned 1
+#define VK_NV_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION 1
+#define VK_NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME "VK_NV_shader_subgroup_partitioned"
+
+
+#define VK_NV_compute_shader_derivatives 1
+#define VK_NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION 1
+#define VK_NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME "VK_NV_compute_shader_derivatives"
+
+typedef struct VkPhysicalDeviceComputeShaderDerivativesFeaturesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 computeDerivativeGroupQuads;
+ VkBool32 computeDerivativeGroupLinear;
+} VkPhysicalDeviceComputeShaderDerivativesFeaturesNV;
+
+
+
+#define VK_NV_mesh_shader 1
+#define VK_NV_MESH_SHADER_SPEC_VERSION 1
+#define VK_NV_MESH_SHADER_EXTENSION_NAME "VK_NV_mesh_shader"
+
+typedef struct VkPhysicalDeviceMeshShaderFeaturesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 taskShader;
+ VkBool32 meshShader;
+} VkPhysicalDeviceMeshShaderFeaturesNV;
+
+typedef struct VkPhysicalDeviceMeshShaderPropertiesNV {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t maxDrawMeshTasksCount;
+ uint32_t maxTaskWorkGroupInvocations;
+ uint32_t maxTaskWorkGroupSize[3];
+ uint32_t maxTaskTotalMemorySize;
+ uint32_t maxTaskOutputCount;
+ uint32_t maxMeshWorkGroupInvocations;
+ uint32_t maxMeshWorkGroupSize[3];
+ uint32_t maxMeshTotalMemorySize;
+ uint32_t maxMeshOutputVertices;
+ uint32_t maxMeshOutputPrimitives;
+ uint32_t maxMeshMultiviewViewCount;
+ uint32_t meshOutputPerVertexGranularity;
+ uint32_t meshOutputPerPrimitiveGranularity;
+} VkPhysicalDeviceMeshShaderPropertiesNV;
+
+typedef struct VkDrawMeshTasksIndirectCommandNV {
+ uint32_t taskCount;
+ uint32_t firstTask;
+} VkDrawMeshTasksIndirectCommandNV;
+
+
+typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksNV)(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask);
+typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectNV)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride);
+typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectCountNV)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksNV(
+ VkCommandBuffer commandBuffer,
+ uint32_t taskCount,
+ uint32_t firstTask);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectNV(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ uint32_t drawCount,
+ uint32_t stride);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectCountNV(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ VkBuffer countBuffer,
+ VkDeviceSize countBufferOffset,
+ uint32_t maxDrawCount,
+ uint32_t stride);
+#endif
+
+#define VK_NV_fragment_shader_barycentric 1
+#define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION 1
+#define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME "VK_NV_fragment_shader_barycentric"
+
+typedef struct VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 fragmentShaderBarycentric;
+} VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV;
+
+
+
+#define VK_NV_shader_image_footprint 1
+#define VK_NV_SHADER_IMAGE_FOOTPRINT_SPEC_VERSION 1
+#define VK_NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME "VK_NV_shader_image_footprint"
+
+typedef struct VkPhysicalDeviceShaderImageFootprintFeaturesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 imageFootprint;
+} VkPhysicalDeviceShaderImageFootprintFeaturesNV;
+
+
+
+#define VK_NV_scissor_exclusive 1
+#define VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION 1
+#define VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME "VK_NV_scissor_exclusive"
+
+typedef struct VkPipelineViewportExclusiveScissorStateCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t exclusiveScissorCount;
+ const VkRect2D* pExclusiveScissors;
+} VkPipelineViewportExclusiveScissorStateCreateInfoNV;
+
+typedef struct VkPhysicalDeviceExclusiveScissorFeaturesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 exclusiveScissor;
+} VkPhysicalDeviceExclusiveScissorFeaturesNV;
+
+
+typedef void (VKAPI_PTR *PFN_vkCmdSetExclusiveScissorNV)(VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor, uint32_t exclusiveScissorCount, const VkRect2D* pExclusiveScissors);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdSetExclusiveScissorNV(
+ VkCommandBuffer commandBuffer,
+ uint32_t firstExclusiveScissor,
+ uint32_t exclusiveScissorCount,
+ const VkRect2D* pExclusiveScissors);
+#endif
+
+#define VK_NV_device_diagnostic_checkpoints 1
+#define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_SPEC_VERSION 2
+#define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME "VK_NV_device_diagnostic_checkpoints"
+
+typedef struct VkQueueFamilyCheckpointPropertiesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkPipelineStageFlags checkpointExecutionStageMask;
+} VkQueueFamilyCheckpointPropertiesNV;
+
+typedef struct VkCheckpointDataNV {
+ VkStructureType sType;
+ void* pNext;
+ VkPipelineStageFlagBits stage;
+ void* pCheckpointMarker;
+} VkCheckpointDataNV;
+
+
+typedef void (VKAPI_PTR *PFN_vkCmdSetCheckpointNV)(VkCommandBuffer commandBuffer, const void* pCheckpointMarker);
+typedef void (VKAPI_PTR *PFN_vkGetQueueCheckpointDataNV)(VkQueue queue, uint32_t* pCheckpointDataCount, VkCheckpointDataNV* pCheckpointData);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdSetCheckpointNV(
+ VkCommandBuffer commandBuffer,
+ const void* pCheckpointMarker);
+
+VKAPI_ATTR void VKAPI_CALL vkGetQueueCheckpointDataNV(
+ VkQueue queue,
+ uint32_t* pCheckpointDataCount,
+ VkCheckpointDataNV* pCheckpointData);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 7f4f2c4..7eaf7b2 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -43,7 +43,6 @@
],
cppflags: [
- "-std=c++14",
"-Wno-c99-extensions",
"-Wno-c++98-compat-pedantic",
"-Wno-exit-time-destructors",
@@ -82,6 +81,8 @@
"libutils",
"libcutils",
"libz",
+ "libnativebridge",
+ "libnativeloader",
"libnativewindow",
"android.hardware.graphics.common@1.0",
],
diff --git a/vulkan/libvulkan/api_gen.cpp b/vulkan/libvulkan/api_gen.cpp
index 7650e0c..629ebb1 100644
--- a/vulkan/libvulkan/api_gen.cpp
+++ b/vulkan/libvulkan/api_gen.cpp
@@ -553,7 +553,11 @@
"vkEnumeratePhysicalDeviceGroups",
"vkEnumeratePhysicalDeviceGroupsKHR",
"vkEnumeratePhysicalDevices",
+ "vkGetDisplayModeProperties2KHR",
+ "vkGetDisplayPlaneCapabilities2KHR",
"vkGetInstanceProcAddr",
+ "vkGetPhysicalDeviceDisplayPlaneProperties2KHR",
+ "vkGetPhysicalDeviceDisplayProperties2KHR",
"vkGetPhysicalDeviceExternalBufferProperties",
"vkGetPhysicalDeviceExternalBufferPropertiesKHR",
"vkGetPhysicalDeviceExternalFenceProperties",
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 56bc35e..fdbd969 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -1165,27 +1165,28 @@
result = EnumeratePhysicalDevices(instance, &device_count, nullptr);
if (result < 0)
return result;
+
if (!pPhysicalDeviceGroupProperties) {
*pPhysicalDeviceGroupCount = device_count;
return result;
}
- device_count = std::min(device_count, *pPhysicalDeviceGroupCount);
if (!device_count) {
*pPhysicalDeviceGroupCount = 0;
return result;
}
+ device_count = std::min(device_count, *pPhysicalDeviceGroupCount);
+ if (!device_count)
+ return VK_INCOMPLETE;
android::Vector<VkPhysicalDevice> devices;
devices.resize(device_count);
-
+ *pPhysicalDeviceGroupCount = device_count;
result = EnumeratePhysicalDevices(instance, &device_count,
devices.editArray());
if (result < 0)
return result;
- devices.resize(device_count);
- *pPhysicalDeviceGroupCount = device_count;
for (uint32_t i = 0; i < device_count; ++i) {
pPhysicalDeviceGroupProperties[i].physicalDeviceCount = 1;
pPhysicalDeviceGroupProperties[i].physicalDevices[0] = devices[i];
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index 3a59208..009b257 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -31,6 +31,8 @@
#include <cutils/properties.h>
#include <graphicsenv/GraphicsEnv.h>
#include <log/log.h>
+#include <nativebridge/native_bridge.h>
+#include <nativeloader/native_loader.h>
#include <ziparchive/zip_archive.h>
// TODO(jessehall): The whole way we deal with extensions is pretty hokey, and
@@ -73,12 +75,14 @@
: path_(path),
filename_(filename),
dlhandle_(nullptr),
+ native_bridge_(false),
refcount_(0) {}
- LayerLibrary(LayerLibrary&& other)
+ LayerLibrary(LayerLibrary&& other) noexcept
: path_(std::move(other.path_)),
filename_(std::move(other.filename_)),
dlhandle_(other.dlhandle_),
+ native_bridge_(other.native_bridge_),
refcount_(other.refcount_) {
other.dlhandle_ = nullptr;
other.refcount_ = 0;
@@ -101,6 +105,17 @@
const std::string GetFilename() { return filename_; }
private:
+ // TODO(b/79940628): remove that adapter when we could use NativeBridgeGetTrampoline
+ // for native libraries.
+ template<typename Func = void*>
+ Func GetTrampoline(const char* name) const {
+ if (native_bridge_) {
+ return reinterpret_cast<Func>(android::NativeBridgeGetTrampoline(
+ dlhandle_, name, nullptr, 0));
+ }
+ return reinterpret_cast<Func>(dlsym(dlhandle_, name));
+ }
+
const std::string path_;
// Track the filename alone so we can detect duplicates
@@ -108,6 +123,7 @@
std::mutex mutex_;
void* dlhandle_;
+ bool native_bridge_;
size_t refcount_;
};
@@ -123,19 +139,23 @@
auto app_namespace = android::GraphicsEnv::getInstance().getAppNamespace();
if (app_namespace &&
!android::base::StartsWith(path_, kSystemLayerLibraryDir)) {
- android_dlextinfo dlextinfo = {};
- dlextinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
- dlextinfo.library_namespace = app_namespace;
- dlhandle_ = android_dlopen_ext(path_.c_str(), RTLD_NOW | RTLD_LOCAL,
- &dlextinfo);
+ std::string error_msg;
+ dlhandle_ = OpenNativeLibrary(
+ app_namespace, path_.c_str(), &native_bridge_, &error_msg);
+ if (!dlhandle_) {
+ ALOGE("failed to load layer library '%s': %s", path_.c_str(),
+ error_msg.c_str());
+ refcount_ = 0;
+ return false;
+ }
} else {
- dlhandle_ = dlopen(path_.c_str(), RTLD_NOW | RTLD_LOCAL);
- }
- if (!dlhandle_) {
- ALOGE("failed to load layer library '%s': %s", path_.c_str(),
- dlerror());
- refcount_ = 0;
- return false;
+ dlhandle_ = dlopen(path_.c_str(), RTLD_NOW | RTLD_LOCAL);
+ if (!dlhandle_) {
+ ALOGE("failed to load layer library '%s': %s", path_.c_str(),
+ dlerror());
+ refcount_ = 0;
+ return false;
+ }
}
}
return true;
@@ -145,19 +165,24 @@
std::lock_guard<std::mutex> lock(mutex_);
if (--refcount_ == 0) {
ALOGV("closing layer library '%s'", path_.c_str());
- dlclose(dlhandle_);
- dlhandle_ = nullptr;
+ std::string error_msg;
+ if (!android::CloseNativeLibrary(dlhandle_, native_bridge_, &error_msg)) {
+ ALOGE("failed to unload library '%s': %s", path_.c_str(), error_msg.c_str());
+ refcount_++;
+ } else {
+ dlhandle_ = nullptr;
+ }
}
}
bool LayerLibrary::EnumerateLayers(size_t library_idx,
std::vector<Layer>& instance_layers) const {
PFN_vkEnumerateInstanceLayerProperties enumerate_instance_layers =
- reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
- dlsym(dlhandle_, "vkEnumerateInstanceLayerProperties"));
+ GetTrampoline<PFN_vkEnumerateInstanceLayerProperties>(
+ "vkEnumerateInstanceLayerProperties");
PFN_vkEnumerateInstanceExtensionProperties enumerate_instance_extensions =
- reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
- dlsym(dlhandle_, "vkEnumerateInstanceExtensionProperties"));
+ GetTrampoline<PFN_vkEnumerateInstanceExtensionProperties>(
+ "vkEnumerateInstanceExtensionProperties");
if (!enumerate_instance_layers || !enumerate_instance_extensions) {
ALOGE("layer library '%s' missing some instance enumeration functions",
path_.c_str());
@@ -166,11 +191,11 @@
// device functions are optional
PFN_vkEnumerateDeviceLayerProperties enumerate_device_layers =
- reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(
- dlsym(dlhandle_, "vkEnumerateDeviceLayerProperties"));
+ GetTrampoline<PFN_vkEnumerateDeviceLayerProperties>(
+ "vkEnumerateDeviceLayerProperties");
PFN_vkEnumerateDeviceExtensionProperties enumerate_device_extensions =
- reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
- dlsym(dlhandle_, "vkEnumerateDeviceExtensionProperties"));
+ GetTrampoline<PFN_vkEnumerateDeviceExtensionProperties>(
+ "vkEnumerateDeviceExtensionProperties");
// get layer counts
uint32_t num_instance_layers = 0;
@@ -301,10 +326,10 @@
char* name = static_cast<char*>(alloca(layer_name_len + gpa_name_len + 1));
strcpy(name, layer.properties.layerName);
strcpy(name + layer_name_len, gpa_name);
- if (!(gpa = dlsym(dlhandle_, name))) {
+ if (!(gpa = GetTrampoline(name))) {
strcpy(name, "vk");
strcpy(name + 2, gpa_name);
- gpa = dlsym(dlhandle_, name);
+ gpa = GetTrampoline(name);
}
return gpa;
}
@@ -520,7 +545,7 @@
}
}
-LayerRef::LayerRef(LayerRef&& other) : layer_(other.layer_) {
+LayerRef::LayerRef(LayerRef&& other) noexcept : layer_(other.layer_) {
other.layer_ = nullptr;
}
diff --git a/vulkan/libvulkan/layers_extensions.h b/vulkan/libvulkan/layers_extensions.h
index 07ac1a3..1dae456 100644
--- a/vulkan/libvulkan/layers_extensions.h
+++ b/vulkan/libvulkan/layers_extensions.h
@@ -27,7 +27,7 @@
class LayerRef {
public:
explicit LayerRef(const Layer* layer);
- LayerRef(LayerRef&& other);
+ LayerRef(LayerRef&& other) noexcept;
~LayerRef();
LayerRef(const LayerRef&) = delete;
LayerRef& operator=(const LayerRef&) = delete;
diff --git a/vulkan/nulldrv/Android.bp b/vulkan/nulldrv/Android.bp
index 3329609..7be9c66 100644
--- a/vulkan/nulldrv/Android.bp
+++ b/vulkan/nulldrv/Android.bp
@@ -32,7 +32,6 @@
"-DLOG_NDEBUG=0",
],
cppflags: [
- "-std=c++1y",
"-Wno-c++98-compat-pedantic",
"-Wno-c99-extensions",
],
diff --git a/vulkan/tools/Android.bp b/vulkan/tools/Android.bp
index d81d9ec..2514094 100644
--- a/vulkan/tools/Android.bp
+++ b/vulkan/tools/Android.bp
@@ -29,7 +29,6 @@
"-Wno-switch-enum",
],
cppflags: [
- "-std=c++1y",
"-Wno-c++98-compat-pedantic",
"-Wno-c99-extensions",
"-Wno-old-style-cast",
diff --git a/vulkan/vkjson/Android.bp b/vulkan/vkjson/Android.bp
index e387165..93620f4 100644
--- a/vulkan/vkjson/Android.bp
+++ b/vulkan/vkjson/Android.bp
@@ -7,6 +7,7 @@
cflags: [
"-Wall",
"-Werror",
+ "-Wimplicit-fallthrough",
],
cppflags: [
"-std=c++11",
@@ -33,6 +34,7 @@
cflags: [
"-Wall",
"-Werror",
+ "-Wimplicit-fallthrough",
],
cppflags: [
"-std=c++11",
diff --git a/vulkan/vkjson/vkjson.cc b/vulkan/vkjson/vkjson.cc
index 6200383..efe622d 100644
--- a/vulkan/vkjson/vkjson.cc
+++ b/vulkan/vkjson/vkjson.cc
@@ -766,6 +766,7 @@
&device->external_fence_properties) &&
visitor->Visit("externalSemaphoreProperties",
&device->external_semaphore_properties);
+ FALLTHROUGH_INTENDED;
case VK_API_VERSION_1_0:
ret &= visitor->Visit("properties", &device->properties) &&
visitor->Visit("features", &device->features) &&
@@ -786,6 +787,7 @@
switch (instance->api_version ^ VK_VERSION_PATCH(instance->api_version)) {
case VK_API_VERSION_1_1:
ret &= visitor->Visit("deviceGroups", &instance->device_groups);
+ FALLTHROUGH_INTENDED;
case VK_API_VERSION_1_0:
ret &= visitor->Visit("layers", &instance->layers) &&
visitor->Visit("extensions", &instance->extensions) &&
diff --git a/vulkan/vkjson/vkjson.h b/vulkan/vkjson/vkjson.h
index 5e8428a..4f97c3e 100644
--- a/vulkan/vkjson/vkjson.h
+++ b/vulkan/vkjson/vkjson.h
@@ -41,6 +41,12 @@
#define VK_API_VERSION_1_1 VK_MAKE_VERSION(1, 1, 0)
#endif
+/*
+ * Annotation to tell clang that we intend to fall through from one case to
+ * another in a switch. Sourced from android-base/macros.h.
+ */
+#define FALLTHROUGH_INTENDED [[clang::fallthrough]]
+
struct VkJsonLayer {
VkLayerProperties properties;
std::vector<VkExtensionProperties> extensions;
diff --git a/vulkan/vkjson/vkjson_instance.cc b/vulkan/vkjson/vkjson_instance.cc
index db0450d..4ec442a 100644
--- a/vulkan/vkjson/vkjson_instance.cc
+++ b/vulkan/vkjson/vkjson_instance.cc
@@ -330,7 +330,7 @@
1,
"",
0,
- VK_API_VERSION_1_0};
+ VK_API_VERSION_1_1};
VkInstanceCreateInfo instance_info = {
VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
nullptr,