Merge "Add "ls -l /data/anr" output to bugreport"
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 2d780f5..73360a3 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -1,3 +1,17 @@
+[Builtin Hooks]
+clang_format = true
+
+[Builtin Hooks Options]
+# Only turn on clang-format check for the following subfolders.
+clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
+ libs/binder/ndk/
+ libs/graphicsenv/
+ libs/gui/
+ libs/ui/
+ libs/vr/
+ services/surfaceflinger/
+ services/vr/
+
[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/"
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 19c2830..53b3a00 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -228,6 +228,10 @@
{ OPT, "events/kmem/rss_stat/enable" },
{ OPT, "events/kmem/ion_heap_grow/enable" },
{ OPT, "events/kmem/ion_heap_shrink/enable" },
+ { OPT, "events/oom/oom_score_adj_update/enable" },
+ { OPT, "events/sched/sched_process_exit/enable" },
+ { OPT, "events/task/task_rename/enable" },
+ { OPT, "events/task/task_newtask/enable" },
} },
};
@@ -435,14 +439,10 @@
const char* path = category.sysfiles[i].path;
bool req = category.sysfiles[i].required == REQ;
if (path != nullptr) {
- if (req) {
- if (!fileIsWritable(path)) {
- return false;
- } else {
- ok = true;
- }
- } else {
+ if (fileIsWritable(path)) {
ok = true;
+ } else if (req) {
+ return false;
}
}
}
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index d950b7c..a282424 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -91,7 +91,26 @@
chmod 0666 /sys/kernel/tracing/events/sync/enable
chmod 0666 /sys/kernel/debug/tracing/events/fence/enable
chmod 0666 /sys/kernel/tracing/events/fence/enable
-
+ chmod 0666 /sys/kernel/debug/tracing/events/kmem/rss_stat/enable
+ chmod 0666 /sys/kernel/tracing/events/kmem/rss_stat/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/kmem/ion_heap_grow/enable
+ chmod 0666 /sys/kernel/tracing/events/kmem/ion_heap_grow/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/kmem/ion_heap_shrink/enable
+ chmod 0666 /sys/kernel/tracing/events/kmem/ion_heap_shrink/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/signal/signal_generate/enable
+ chmod 0666 /sys/kernel/tracing/events/signal/signal_generate/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/signal/signal_deliver/enable
+ chmod 0666 /sys/kernel/tracing/events/signal/signal_deliver/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/mm_event/mm_event_record/enable
+ chmod 0666 /sys/kernel/tracing/events/mm_event/mm_event_record/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/lowmemorykiller/lowmemory_kill/enable
+ chmod 0666 /sys/kernel/tracing/events/lowmemorykiller/lowmemory_kill/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/oom/oom_score_adj_update/enable
+ chmod 0666 /sys/kernel/tracing/events/oom/oom_score_adj_update/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/task/task_rename/enable
+ chmod 0666 /sys/kernel/tracing/events/task/task_rename/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/task/task_newtask/enable
+ chmod 0666 /sys/kernel/tracing/events/task/task_newtask/enable
# disk
chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_get_data_block/enable
@@ -125,6 +144,12 @@
chmod 0666 /sys/kernel/tracing/events/block/block_rq_complete/enable
chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_complete/enable
+ # filemap events for iorapd
+ chmod 0666 /sys/kernel/tracing/events/filemap/mm_filemap_add_to_page_cache/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/filemap/mm_filemap_add_to_page_cache/enable
+ chmod 0666 /sys/kernel/tracing/events/filemap/mm_filemap_delete_from_page_cache/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/filemap/mm_filemap_delete_from_page_cache/enable
+
# Tracing disabled by default
write /sys/kernel/debug/tracing/tracing_on 0
write /sys/kernel/tracing/tracing_on 0
@@ -150,7 +175,7 @@
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/debug/tracing/per_cpu/cpu7/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
diff --git a/cmds/atrace/atrace_userdebug.rc b/cmds/atrace/atrace_userdebug.rc
index f4e5b98..acc62c0 100644
--- a/cmds/atrace/atrace_userdebug.rc
+++ b/cmds/atrace/atrace_userdebug.rc
@@ -5,6 +5,12 @@
# Access control to these files is now entirely in selinux policy.
on post-fs
+ # On userdebug allow to enable any event via the generic
+ # set_event interface:
+ # echo sched/foo > set_event == echo 1 > events/sched/foo/enable.
+ chmod 0666 /sys/kernel/tracing/set_event
+ chmod 0666 /sys/kernel/debug/tracing/set_event
+
chmod 0666 /sys/kernel/tracing/events/workqueue/enable
chmod 0666 /sys/kernel/debug/tracing/events/workqueue/enable
chmod 0666 /sys/kernel/tracing/events/regulator/enable
diff --git a/cmds/bugreportz/Android.bp b/cmds/bugreportz/Android.bp
new file mode 100644
index 0000000..924a3a3
--- /dev/null
+++ b/cmds/bugreportz/Android.bp
@@ -0,0 +1,44 @@
+// bugreportz
+// ==========
+cc_binary {
+ name: "bugreportz",
+
+ srcs: [
+ "bugreportz.cpp",
+ "main.cpp",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libcutils",
+ ],
+}
+
+// bugreportz_test
+// ===============
+cc_test {
+ name: "bugreportz_test",
+ test_suites: ["device-tests"],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+
+ srcs: [
+ "bugreportz.cpp",
+ "bugreportz_test.cpp",
+ ],
+
+ static_libs: ["libgmock"],
+
+ shared_libs: [
+ "libbase",
+ "libutils",
+ ],
+}
diff --git a/cmds/bugreportz/Android.mk b/cmds/bugreportz/Android.mk
deleted file mode 100644
index 10dda56..0000000
--- a/cmds/bugreportz/Android.mk
+++ /dev/null
@@ -1,44 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-# bugreportz
-# ==========
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- bugreportz.cpp \
- main.cpp \
-
-LOCAL_MODULE:= bugreportz
-
-LOCAL_CFLAGS := -Werror -Wall
-
-LOCAL_SHARED_LIBRARIES := \
- libbase \
- libcutils \
-
-include $(BUILD_EXECUTABLE)
-
-# bugreportz_test
-# ===============
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := bugreportz_test
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_CFLAGS := -Werror -Wall
-
-LOCAL_SRC_FILES := \
- bugreportz.cpp \
- bugreportz_test.cpp \
-
-LOCAL_STATIC_LIBRARIES := \
- libgmock \
-
-LOCAL_SHARED_LIBRARIES := \
- libbase \
- libutils \
-
-include $(BUILD_NATIVE_TEST)
diff --git a/cmds/cmd/Android.bp b/cmds/cmd/Android.bp
new file mode 100644
index 0000000..8ea71cd
--- /dev/null
+++ b/cmds/cmd/Android.bp
@@ -0,0 +1,42 @@
+cc_library_static {
+ name: "libcmd",
+
+ srcs: ["cmd.cpp"],
+ export_include_dirs: ["."],
+
+ shared_libs: [
+ "libutils",
+ "liblog",
+ "libselinux",
+ "libbinder",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-DXP_UNIX",
+ ],
+}
+
+cc_binary {
+ name: "cmd",
+
+ srcs: ["main.cpp"],
+
+ static_libs: [
+ "libcmd",
+ ],
+
+ shared_libs: [
+ "libutils",
+ "liblog",
+ "libselinux",
+ "libbinder",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-DXP_UNIX",
+ ],
+}
diff --git a/cmds/cmd/Android.mk b/cmds/cmd/Android.mk
deleted file mode 100644
index 4868555..0000000
--- a/cmds/cmd/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- cmd.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libutils \
- liblog \
- libselinux \
- libbinder
-
-LOCAL_CFLAGS := -Wall -Werror
-
-LOCAL_C_INCLUDES += \
- $(JNI_H_INCLUDE)
-
-ifeq ($(TARGET_OS),linux)
- LOCAL_CFLAGS += -DXP_UNIX
- #LOCAL_SHARED_LIBRARIES += librt
-endif
-
-LOCAL_MODULE:= cmd
-
-include $(BUILD_EXECUTABLE)
diff --git a/cmds/cmd/cmd.cpp b/cmds/cmd/cmd.cpp
index 4238531..7b4aeb2 100644
--- a/cmds/cmd/cmd.cpp
+++ b/cmds/cmd/cmd.cpp
@@ -40,6 +40,8 @@
#include "selinux/selinux.h"
#include "selinux/android.h"
+#include "cmd.h"
+
#define DEBUG 0
using namespace android;
@@ -59,8 +61,11 @@
class MyShellCallback : public BnShellCallback
{
public:
+ TextOutput& mErrorLog;
bool mActive = true;
+ MyShellCallback(TextOutput& errorLog) : mErrorLog(errorLog) {}
+
virtual int openFile(const String16& path, const String16& seLinuxContext,
const String16& mode) {
String8 path8(path);
@@ -69,7 +74,7 @@
String8 fullPath(cwd);
fullPath.appendPath(path8);
if (!mActive) {
- aerr << "Open attempt after active for: " << fullPath << endl;
+ mErrorLog << "Open attempt after active for: " << fullPath << endl;
return -EPERM;
}
#if DEBUG
@@ -78,20 +83,20 @@
int flags = 0;
bool checkRead = false;
bool checkWrite = false;
- if (mode == String16("w")) {
+ if (mode == u"w") {
flags = O_WRONLY|O_CREAT|O_TRUNC;
checkWrite = true;
- } else if (mode == String16("w+")) {
+ } else if (mode == u"w+") {
flags = O_RDWR|O_CREAT|O_TRUNC;
checkRead = checkWrite = true;
- } else if (mode == String16("r")) {
+ } else if (mode == u"r") {
flags = O_RDONLY;
checkRead = true;
- } else if (mode == String16("r+")) {
+ } else if (mode == u"r+") {
flags = O_RDWR;
checkRead = checkWrite = true;
} else {
- aerr << "Invalid mode requested: " << mode.string() << endl;
+ mErrorLog << "Invalid mode requested: " << mode.string() << endl;
return -EINVAL;
}
int fd = open(fullPath.string(), flags, S_IRWXU|S_IRWXG);
@@ -103,34 +108,30 @@
}
if (is_selinux_enabled() && seLinuxContext.size() > 0) {
String8 seLinuxContext8(seLinuxContext);
- security_context_t tmp = NULL;
+ security_context_t tmp = nullptr;
getfilecon(fullPath.string(), &tmp);
Unique_SecurityContext context(tmp);
if (checkWrite) {
int accessGranted = selinux_check_access(seLinuxContext8.string(), context.get(),
- "file", "write", NULL);
+ "file", "write", nullptr);
if (accessGranted != 0) {
#if DEBUG
ALOGD("openFile: failed selinux write check!");
#endif
close(fd);
- aerr << "System server has no access to write file context " << context.get()
- << " (from path " << fullPath.string() << ", context "
- << seLinuxContext8.string() << ")" << endl;
+ mErrorLog << "System server has no access to write file context " << context.get() << " (from path " << fullPath.string() << ", context " << seLinuxContext8.string() << ")" << endl;
return -EPERM;
}
}
if (checkRead) {
int accessGranted = selinux_check_access(seLinuxContext8.string(), context.get(),
- "file", "read", NULL);
+ "file", "read", nullptr);
if (accessGranted != 0) {
#if DEBUG
ALOGD("openFile: failed selinux read check!");
#endif
close(fd);
- aerr << "System server has no access to read file context " << context.get()
- << " (from path " << fullPath.string() << ", context "
- << seLinuxContext8.string() << ")" << endl;
+ mErrorLog << "System server has no access to read file context " << context.get() << " (from path " << fullPath.string() << ", context " << seLinuxContext8.string() << ")" << endl;
return -EPERM;
}
}
@@ -163,9 +164,8 @@
}
};
-int main(int argc, char* const argv[])
-{
- signal(SIGPIPE, SIG_IGN);
+int cmdMain(const std::vector<std::string_view>& argv, TextOutput& outputLog, TextOutput& errorLog,
+ int in, int out, int err, RunMode runMode) {
sp<ProcessState> proc = ProcessState::self();
proc->startThreadPool();
@@ -173,68 +173,77 @@
ALOGD("cmd: starting");
#endif
sp<IServiceManager> sm = defaultServiceManager();
- fflush(stdout);
- if (sm == NULL) {
+ if (runMode == RunMode::kStandalone) {
+ fflush(stdout);
+ }
+ if (sm == nullptr) {
ALOGW("Unable to get default service manager!");
- aerr << "cmd: Unable to get default service manager!" << endl;
+ errorLog << "cmd: Unable to get default service manager!" << endl;
return 20;
}
- if (argc == 1) {
- aerr << "cmd: No service specified; use -l to list all services" << endl;
+ int argc = argv.size();
+
+ if (argc == 0) {
+ errorLog << "cmd: No service specified; use -l to list all services" << endl;
return 20;
}
- if ((argc == 2) && (strcmp(argv[1], "-l") == 0)) {
+ if ((argc == 1) && (argv[0] == "-l")) {
Vector<String16> services = sm->listServices();
services.sort(sort_func);
- aout << "Currently running services:" << endl;
+ outputLog << "Currently running services:" << endl;
for (size_t i=0; i<services.size(); i++) {
sp<IBinder> service = sm->checkService(services[i]);
- if (service != NULL) {
- aout << " " << services[i] << endl;
+ if (service != nullptr) {
+ outputLog << " " << services[i] << endl;
}
}
return 0;
}
+ const auto cmd = argv[0];
+
Vector<String16> args;
- for (int i=2; i<argc; i++) {
- args.add(String16(argv[i]));
+ String16 serviceName = String16(cmd.data(), cmd.size());
+ for (int i = 1; i < argc; i++) {
+ args.add(String16(argv[i].data(), argv[i].size()));
}
- String16 cmd = String16(argv[1]);
- sp<IBinder> service = sm->checkService(cmd);
- if (service == NULL) {
- ALOGW("Can't find service %s", argv[1]);
- aerr << "cmd: Can't find service: " << argv[1] << endl;
+ sp<IBinder> service = sm->checkService(serviceName);
+ if (service == nullptr) {
+ if (runMode == RunMode::kStandalone) {
+ ALOGW("Can't find service %.*s", static_cast<int>(cmd.size()), cmd.data());
+ }
+ errorLog << "cmd: Can't find service: " << cmd << endl;
return 20;
}
- sp<MyShellCallback> cb = new MyShellCallback();
+ sp<MyShellCallback> cb = new MyShellCallback(errorLog);
sp<MyResultReceiver> result = new MyResultReceiver();
#if DEBUG
- ALOGD("cmd: Invoking %s in=%d, out=%d, err=%d", argv[1], STDIN_FILENO, STDOUT_FILENO,
- STDERR_FILENO);
+ ALOGD("cmd: Invoking %s in=%d, out=%d, err=%d", cmd, in, out, err);
#endif
// TODO: block until a result is returned to MyResultReceiver.
- status_t err = IBinder::shellCommand(service, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, args,
- cb, result);
- if (err < 0) {
+ status_t error = IBinder::shellCommand(service, in, out, err, args, cb, result);
+ if (error < 0) {
const char* errstr;
- switch (err) {
+ switch (error) {
case BAD_TYPE: errstr = "Bad type"; break;
case FAILED_TRANSACTION: errstr = "Failed transaction"; break;
case FDS_NOT_ALLOWED: errstr = "File descriptors not allowed"; break;
case UNEXPECTED_NULL: errstr = "Unexpected null"; break;
- default: errstr = strerror(-err); break;
+ default: errstr = strerror(-error); break;
}
- ALOGW("Failure calling service %s: %s (%d)", argv[1], errstr, -err);
- aout << "cmd: Failure calling service " << argv[1] << ": " << errstr << " ("
- << (-err) << ")" << endl;
- return err;
+ if (runMode == RunMode::kStandalone) {
+ ALOGW("Failure calling service %.*s: %s (%d)", static_cast<int>(cmd.size()), cmd.data(),
+ errstr, -error);
+ }
+ outputLog << "cmd: Failure calling service " << cmd << ": " << errstr << " (" << (-error)
+ << ")" << endl;
+ return error;
}
cb->mActive = false;
diff --git a/cmds/cmd/cmd.h b/cmds/cmd/cmd.h
new file mode 100644
index 0000000..a91e009
--- /dev/null
+++ b/cmds/cmd/cmd.h
@@ -0,0 +1,30 @@
+/*
+ * 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 <binder/TextOutput.h>
+
+#include <string_view>
+#include <vector>
+
+enum class RunMode {
+ kStandalone,
+ kLibrary,
+};
+
+int cmdMain(const std::vector<std::string_view>& argv, android::TextOutput& outputLog,
+ android::TextOutput& errorLog, int in, int out, int err, RunMode runMode);
diff --git a/cmds/cmd/main.cpp b/cmds/cmd/main.cpp
new file mode 100644
index 0000000..2256e2a
--- /dev/null
+++ b/cmds/cmd/main.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <unistd.h>
+
+#include "cmd.h"
+
+int main(int argc, char* const argv[]) {
+ signal(SIGPIPE, SIG_IGN);
+
+ std::vector<std::string_view> arguments;
+ arguments.reserve(argc - 1);
+ // 0th argument is a program name, skipping.
+ for (int i = 1; i < argc; ++i) {
+ arguments.emplace_back(argv[i]);
+ }
+
+ return cmdMain(arguments, android::aout, android::aerr, STDIN_FILENO, STDOUT_FILENO,
+ STDERR_FILENO, RunMode::kStandalone);
+}
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index 9aa1075..ee32cb4 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -57,7 +57,6 @@
export_aidl_headers: true,
},
srcs: [
- "binder/android/os/DumpstateOptions.cpp",
":dumpstate_aidl",
],
export_include_dirs: ["binder"],
@@ -68,7 +67,6 @@
srcs: [
"binder/android/os/IDumpstateListener.aidl",
"binder/android/os/IDumpstateToken.aidl",
- //"binder/android/os/DumpstateOptions.aidl",
"binder/android/os/IDumpstate.aidl",
],
path: "binder",
@@ -99,8 +97,9 @@
"utils.cpp",
],
static_libs: [
+ "libincidentcompanion",
"libdumpsys",
- "libserviceutils"
+ "libserviceutils",
],
}
@@ -158,3 +157,22 @@
],
static_libs: ["libgmock"],
}
+
+
+// =======================#
+// dumpstate_test_fixture #
+// =======================#
+cc_test {
+
+ name: "dumpstate_test_fixture",
+ test_suites: ["device-tests"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-missing-field-initializers",
+ "-Wno-unused-variable",
+ "-Wunused-parameter",
+ ],
+ srcs: ["tests/dumpstate_test_fixture.cpp"],
+ data: ["tests/testdata/**/*"],
+}
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk
deleted file mode 100644
index ea5fbf1..0000000
--- a/cmds/dumpstate/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-# =======================#
-# dumpstate_test_fixture #
-# =======================#
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := dumpstate_test_fixture
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_CFLAGS := \
- -Wall -Werror -Wno-missing-field-initializers -Wno-unused-variable -Wunused-parameter
-
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_SRC_FILES := \
- tests/dumpstate_test_fixture.cpp
-
-LOCAL_TEST_DATA := $(call find-test-data-in-subdirs, $(LOCAL_PATH), *, tests/testdata)
-
-include $(BUILD_NATIVE_TEST)
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index 71658d8..bb089e6 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -18,20 +18,50 @@
#include "DumpstateService.h"
-#include <android-base/stringprintf.h>
+#include <memory>
+#include <android-base/stringprintf.h>
#include "android/os/BnDumpstate.h"
#include "DumpstateInternal.h"
+using android::base::StringPrintf;
+
namespace android {
namespace os {
namespace {
-class DumpstateToken : public BnDumpstateToken {};
+
+struct DumpstateInfo {
+ public:
+ Dumpstate* ds = nullptr;
+ int32_t calling_uid = -1;
+ std::string calling_package;
+};
+
+static binder::Status exception(uint32_t code, const std::string& msg) {
+ MYLOGE("%s (%d) ", msg.c_str(), code);
+ return binder::Status::fromExceptionCode(code, String8(msg.c_str()));
}
-DumpstateService::DumpstateService() : ds_(Dumpstate::GetInstance()) {
+static binder::Status error(uint32_t code, const std::string& msg) {
+ MYLOGE("%s (%d) ", msg.c_str(), code);
+ return binder::Status::fromServiceSpecificError(code, String8(msg.c_str()));
+}
+
+// Takes ownership of data.
+static void* callAndNotify(void* data) {
+ std::unique_ptr<DumpstateInfo> ds_info(static_cast<DumpstateInfo*>(data));
+ ds_info->ds->Run(ds_info->calling_uid, ds_info->calling_package);
+ MYLOGD("Finished Run()\n");
+ return nullptr;
+}
+
+class DumpstateToken : public BnDumpstateToken {};
+
+} // namespace
+
+DumpstateService::DumpstateService() : ds_(nullptr) {
}
char const* DumpstateService::getServiceName() {
@@ -50,6 +80,8 @@
return android::OK;
}
+// Note: this method is part of the old flow and is not expected to be used in combination
+// with startBugreport.
binder::Status DumpstateService::setListener(const std::string& name,
const sp<IDumpstateListener>& listener,
bool getSectionDetails,
@@ -64,50 +96,116 @@
return binder::Status::ok();
}
std::lock_guard<std::mutex> lock(lock_);
- if (ds_.listener_ != nullptr) {
- MYLOGE("setListener(%s): already set (%s)\n", name.c_str(), ds_.listener_name_.c_str());
+ if (ds_ == nullptr) {
+ ds_ = &(Dumpstate::GetInstance());
+ }
+ if (ds_->listener_ != nullptr) {
+ MYLOGE("setListener(%s): already set (%s)\n", name.c_str(), ds_->listener_name_.c_str());
return binder::Status::ok();
}
- ds_.listener_name_ = name;
- ds_.listener_ = listener;
- ds_.report_section_ = getSectionDetails;
+ ds_->listener_name_ = name;
+ ds_->listener_ = listener;
+ ds_->report_section_ = getSectionDetails;
*returned_token = new DumpstateToken();
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;
+binder::Status DumpstateService::startBugreport(int32_t calling_uid,
+ const std::string& calling_package,
+ const android::base::unique_fd& bugreport_fd,
+ const android::base::unique_fd& screenshot_fd,
+ int bugreport_mode,
+ const sp<IDumpstateListener>& listener) {
+ MYLOGI("startBugreport() with mode: %d\n", bugreport_mode);
+
+ if (bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_FULL &&
+ bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE &&
+ bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_REMOTE &&
+ bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_WEAR &&
+ bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_TELEPHONY &&
+ bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_WIFI &&
+ bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_DEFAULT) {
+ return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
+ StringPrintf("Invalid bugreport mode: %d", bugreport_mode));
+ }
+
+ if (bugreport_fd.get() == -1 || screenshot_fd.get() == -1) {
+ return exception(binder::Status::EX_ILLEGAL_ARGUMENT, "Invalid file descriptor");
+ }
+
+ std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
+ options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode), bugreport_fd,
+ screenshot_fd);
+
+ // This is the bugreporting API flow, so ensure there is only one bugreport in progress at a
+ // time.
+ std::lock_guard<std::mutex> lock(lock_);
+ if (ds_ != nullptr) {
+ return exception(binder::Status::EX_SERVICE_SPECIFIC,
+ "There is already a bugreport in progress");
+ }
+ ds_ = &(Dumpstate::GetInstance());
+ ds_->SetOptions(std::move(options));
+ if (listener != nullptr) {
+ ds_->listener_ = listener;
+ }
+
+ DumpstateInfo* ds_info = new DumpstateInfo();
+ ds_info->ds = ds_;
+ ds_info->calling_uid = calling_uid;
+ ds_info->calling_package = calling_package;
+
+ pthread_t thread;
+ status_t err = pthread_create(&thread, nullptr, callAndNotify, ds_info);
+ if (err != 0) {
+ delete ds_info;
+ ds_info = nullptr;
+ return error(err, "Could not create a background thread.");
+ }
+ return binder::Status::ok();
+}
+
+binder::Status DumpstateService::cancelBugreport() {
+ // This is a no-op since the cancellation is done from java side via setting sys properties.
+ // See BugreportManagerServiceImpl.
+ // TODO(b/111441001): maybe make native and java sides use different binder interface
+ // to avoid these annoyances.
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_);
- dprintf(fd, "update_progress: %s\n", ds_.options_->do_progress_updates ? "true" : "false");
- dprintf(fd, "update_progress_threshold: %d\n", ds_.update_progress_threshold_);
- dprintf(fd, "last_updated_progress: %d\n", ds_.last_updated_progress_);
+ if (ds_ == nullptr) {
+ dprintf(fd, "Bugreport not in progress yet");
+ return NO_ERROR;
+ }
+ std::string destination = ds_->options_->bugreport_fd.get() != -1
+ ? StringPrintf("[fd:%d]", ds_->options_->bugreport_fd.get())
+ : ds_->bugreport_internal_dir_.c_str();
+ dprintf(fd, "id: %d\n", ds_->id_);
+ dprintf(fd, "pid: %d\n", ds_->pid_);
+ dprintf(fd, "update_progress: %s\n", ds_->options_->do_progress_updates ? "true" : "false");
+ dprintf(fd, "update_progress_threshold: %d\n", ds_->update_progress_threshold_);
+ dprintf(fd, "last_updated_progress: %d\n", ds_->last_updated_progress_);
dprintf(fd, "progress:\n");
- ds_.progress_->Dump(fd, " ");
- dprintf(fd, "args: %s\n", ds_.options_->args.c_str());
- dprintf(fd, "extra_options: %s\n", ds_.options_->extra_options.c_str());
- dprintf(fd, "version: %s\n", ds_.version_.c_str());
- dprintf(fd, "bugreport_dir: %s\n", ds_.bugreport_dir_.c_str());
- dprintf(fd, "screenshot_path: %s\n", ds_.screenshot_path_.c_str());
- dprintf(fd, "log_path: %s\n", ds_.log_path_.c_str());
- dprintf(fd, "tmp_path: %s\n", ds_.tmp_path_.c_str());
- dprintf(fd, "path: %s\n", ds_.path_.c_str());
- dprintf(fd, "extra_options: %s\n", ds_.options_->extra_options.c_str());
- dprintf(fd, "base_name: %s\n", ds_.base_name_.c_str());
- dprintf(fd, "name: %s\n", ds_.name_.c_str());
- dprintf(fd, "now: %ld\n", ds_.now_);
- dprintf(fd, "is_zipping: %s\n", ds_.IsZipping() ? "true" : "false");
- dprintf(fd, "listener: %s\n", ds_.listener_name_.c_str());
- dprintf(fd, "notification title: %s\n", ds_.options_->notification_title.c_str());
- dprintf(fd, "notification description: %s\n", ds_.options_->notification_description.c_str());
+ ds_->progress_->Dump(fd, " ");
+ dprintf(fd, "args: %s\n", ds_->options_->args.c_str());
+ dprintf(fd, "extra_options: %s\n", ds_->options_->extra_options.c_str());
+ dprintf(fd, "version: %s\n", ds_->version_.c_str());
+ dprintf(fd, "bugreport_dir: %s\n", destination.c_str());
+ dprintf(fd, "screenshot_path: %s\n", ds_->screenshot_path_.c_str());
+ dprintf(fd, "log_path: %s\n", ds_->log_path_.c_str());
+ dprintf(fd, "tmp_path: %s\n", ds_->tmp_path_.c_str());
+ dprintf(fd, "path: %s\n", ds_->path_.c_str());
+ dprintf(fd, "extra_options: %s\n", ds_->options_->extra_options.c_str());
+ dprintf(fd, "base_name: %s\n", ds_->base_name_.c_str());
+ dprintf(fd, "name: %s\n", ds_->name_.c_str());
+ dprintf(fd, "now: %ld\n", ds_->now_);
+ dprintf(fd, "is_zipping: %s\n", ds_->IsZipping() ? "true" : "false");
+ dprintf(fd, "listener: %s\n", ds_->listener_name_.c_str());
+ dprintf(fd, "notification title: %s\n", ds_->options_->notification_title.c_str());
+ dprintf(fd, "notification description: %s\n", ds_->options_->notification_description.c_str());
return NO_ERROR;
}
diff --git a/cmds/dumpstate/DumpstateService.h b/cmds/dumpstate/DumpstateService.h
index 131aff3..68eda47 100644
--- a/cmds/dumpstate/DumpstateService.h
+++ b/cmds/dumpstate/DumpstateService.h
@@ -20,6 +20,7 @@
#include <mutex>
#include <vector>
+#include <android-base/unique_fd.h>
#include <binder/BinderService.h>
#include "android/os/BnDumpstate.h"
@@ -41,11 +42,20 @@
bool getSectionDetails,
sp<IDumpstateToken>* returned_token) override;
- binder::Status startBugreport(int fd, const sp<IDumpstateListener>& listener,
- const DumpstateOptions& options, int32_t* returned_id) override;
+ binder::Status startBugreport(int32_t calling_uid, const std::string& calling_package,
+ const android::base::unique_fd& bugreport_fd,
+ const android::base::unique_fd& screenshot_fd, int bugreport_mode,
+ const sp<IDumpstateListener>& listener) override;
+
+ // No-op
+ binder::Status cancelBugreport();
private:
- Dumpstate& ds_;
+ // Dumpstate object which contains all the bugreporting logic.
+ // Note that dumpstate is a oneshot service, so this object is meant to be used at most for
+ // one bugreport.
+ // This service does not own this object.
+ Dumpstate* ds_;
std::mutex lock_;
};
diff --git a/cmds/dumpstate/DumpstateUtil.cpp b/cmds/dumpstate/DumpstateUtil.cpp
index 600a500..97c8ae2 100644
--- a/cmds/dumpstate/DumpstateUtil.cpp
+++ b/cmds/dumpstate/DumpstateUtil.cpp
@@ -101,13 +101,16 @@
}
CommandOptions::CommandOptionsBuilder& CommandOptions::CommandOptionsBuilder::AsRoot() {
- values.account_mode_ = SU_ROOT;
+ if (!PropertiesHelper::IsUnroot()) {
+ values.account_mode_ = SU_ROOT;
+ }
return *this;
}
CommandOptions::CommandOptionsBuilder& CommandOptions::CommandOptionsBuilder::AsRootIfAvailable() {
- if (!PropertiesHelper::IsUserBuild())
- values.account_mode_ = SU_ROOT;
+ if (!PropertiesHelper::IsUserBuild()) {
+ return AsRoot();
+ }
return *this;
}
@@ -176,6 +179,7 @@
std::string PropertiesHelper::build_type_ = "";
int PropertiesHelper::dry_run_ = -1;
+int PropertiesHelper::unroot_ = -1;
bool PropertiesHelper::IsUserBuild() {
if (build_type_.empty()) {
@@ -191,6 +195,13 @@
return dry_run_ == 1;
}
+bool PropertiesHelper::IsUnroot() {
+ if (unroot_ == -1) {
+ unroot_ = android::base::GetBoolProperty("dumpstate.unroot", false) ? 1 : 0;
+ }
+ return unroot_ == 1;
+}
+
int DumpFileToFd(int out_fd, const std::string& title, const std::string& path) {
android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
if (fd.get() < 0) {
diff --git a/cmds/dumpstate/DumpstateUtil.h b/cmds/dumpstate/DumpstateUtil.h
index 8342099..d75b08c 100644
--- a/cmds/dumpstate/DumpstateUtil.h
+++ b/cmds/dumpstate/DumpstateUtil.h
@@ -76,7 +76,7 @@
private:
class CommandOptionsValues {
private:
- CommandOptionsValues(int64_t timeout_ms);
+ explicit CommandOptionsValues(int64_t timeout_ms);
int64_t timeout_ms_;
bool always_;
@@ -88,7 +88,7 @@
friend class CommandOptionsBuilder;
};
- CommandOptions(const CommandOptionsValues& values);
+ explicit CommandOptions(const CommandOptionsValues& values);
const CommandOptionsValues values;
@@ -97,9 +97,16 @@
public:
/* Sets the command to always run, even on `dry-run` mode. */
CommandOptionsBuilder& Always();
- /* Sets the command's PrivilegeMode as `SU_ROOT` */
+ /*
+ * Sets the command's PrivilegeMode as `SU_ROOT` unless overridden by system property
+ * 'dumpstate.unroot'.
+ */
CommandOptionsBuilder& AsRoot();
- /* If !IsUserBuild(), sets the command's PrivilegeMode as `SU_ROOT` */
+ /*
+ * Runs AsRoot() on userdebug builds. No-op on user builds since 'su' is
+ * not available. This is used for commands that return some useful information even
+ * when run as shell.
+ */
CommandOptionsBuilder& AsRootIfAvailable();
/* Sets the command's PrivilegeMode as `DROP_ROOT` */
CommandOptionsBuilder& DropRoot();
@@ -112,7 +119,7 @@
CommandOptions Build();
private:
- CommandOptionsBuilder(int64_t timeout_ms);
+ explicit CommandOptionsBuilder(int64_t timeout_ms);
CommandOptionsValues values;
friend class CommandOptions;
};
@@ -162,9 +169,17 @@
*/
static bool IsDryRun();
+ /**
+ * Checks whether root availability should be overridden.
+ *
+ * Useful to verify how dumpstate would work in a device with an user build.
+ */
+ static bool IsUnroot();
+
private:
static std::string build_type_;
static int dry_run_;
+ static int unroot_;
};
/*
diff --git a/cmds/dumpstate/README.md b/cmds/dumpstate/README.md
index 0302ea5..273a5a6 100644
--- a/cmds/dumpstate/README.md
+++ b/cmds/dumpstate/README.md
@@ -26,24 +26,36 @@
mmm -j frameworks/native/cmds/dumpstate && adb push ${OUT}/system/bin/dumpstate system/bin && adb shell am bug-report
```
+Make sure that the device is remounted before running the above command.
+* If you're working with `userdebug` variant, you may need to run the following to remount your device:
+
+ ```
+ adb root && adb remount -R && adb wait-for-device && adb root && adb remount
+ ```
+* If you're working with `eng` variant, you may need to run the following to remount your device:
+
+ ```
+ adb root && adb remount
+ ```
+
## To build, deploy, and run unit tests
-First create `/data/nativetest`:
+First create `/data/nativetest64`:
```
-adb shell mkdir /data/nativetest
+adb shell mkdir /data/nativetest64
```
Then run:
```
-mmm -j frameworks/native/cmds/dumpstate/ && adb push ${OUT}/data/nativetest/dumpstate_test* /data/nativetest && adb shell /data/nativetest/dumpstate_test/dumpstate_test
+mmm -j frameworks/native/cmds/dumpstate/ && adb push ${OUT}/data/nativetest64/dumpstate_* /data/nativetest64 && adb shell /data/nativetest64/dumpstate_test/dumpstate_test
```
And to run just one test (for example, `DumpstateTest.RunCommandNoArgs`):
```
-mmm -j frameworks/native/cmds/dumpstate/ && adb push ${OUT}/data/nativetest/dumpstate_test* /data/nativetest && adb shell /data/nativetest/dumpstate_test/dumpstate_test --gtest_filter=DumpstateTest.RunCommandNoArgs
+mmm -j frameworks/native/cmds/dumpstate/ && adb push ${OUT}/data/nativetest64/dumpstate_test* /data/nativetest64 && adb shell /data/nativetest64/dumpstate_test/dumpstate_test --gtest_filter=DumpstateTest.RunCommandNoArgs
```
## To take quick bugreports
@@ -52,6 +64,12 @@
adb shell setprop dumpstate.dry_run true
```
+## To emulate a device with user build
+
+```
+adb shell setprop dumpstate.unroot true
+```
+
## To change the `dumpstate` version
```
diff --git a/cmds/dumpstate/binder/android/os/DumpstateOptions.cpp b/cmds/dumpstate/binder/android/os/DumpstateOptions.cpp
deleted file mode 100644
index 5654190..0000000
--- a/cmds/dumpstate/binder/android/os/DumpstateOptions.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
- * 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
deleted file mode 100644
index a748e3c..0000000
--- a/cmds/dumpstate/binder/android/os/DumpstateOptions.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * 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 68a4f21..b1005d3 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
@@ -18,15 +18,12 @@
import android.os.IDumpstateListener;
import android.os.IDumpstateToken;
-import android.os.DumpstateOptions;
/**
* Binder interface for the currently running dumpstate process.
* {@hide}
*/
interface IDumpstate {
-
-
// TODO: remove method once startBugReport is used by Shell.
/*
* Sets the listener for this dumpstate progress.
@@ -39,10 +36,51 @@
IDumpstateToken setListener(@utf8InCpp String name, IDumpstateListener listener,
boolean getSectionDetails);
+ // These modes encapsulate a set of run time options for generating bugreports.
+ // Takes a bugreport without user interference.
+ const int BUGREPORT_MODE_FULL = 0;
+
+ // Interactive bugreport, i.e. triggered by the user.
+ const int BUGREPORT_MODE_INTERACTIVE = 1;
+
+ // Remote bugreport triggered by DevicePolicyManager, for e.g.
+ const int BUGREPORT_MODE_REMOTE = 2;
+
+ // Bugreport triggered on a wear device.
+ const int BUGREPORT_MODE_WEAR = 3;
+
+ // Bugreport limited to only telephony info.
+ const int BUGREPORT_MODE_TELEPHONY = 4;
+
+ // Bugreport limited to only wifi info.
+ const int BUGREPORT_MODE_WIFI = 5;
+
+ // Default mode.
+ const int BUGREPORT_MODE_DEFAULT = 6;
+
+ // TODO(b/111441001): Should the args be for the consuming application rather than triggering?
/*
- * Starts a bugreport in a child process.
+ * Starts a bugreport in the background.
*
- * Returns an identifier of the bugreport process running in the background.
+ *<p>Shows the user a dialog to get consent for sharing the bugreport with the calling
+ * application. If they deny {@link IDumpstateListener#onError} will be called. If they
+ * consent and bugreport generation is successful artifacts will be copied to the given fds and
+ * {@link IDumpstateListener#onFinished} will be called. If there
+ * are errors in bugreport generation {@link IDumpstateListener#onError} will be called.
+ *
+ * @param callingUid UID of the original application that requested the report.
+ * @param callingPackage package of the original application that requested the report.
+ * @param bugreportFd the file to which the zipped bugreport should be written
+ * @param screenshotFd the file to which screenshot should be written; optional
+ * @param bugreportMode the mode that specifies other run time options; must be one of above
+ * @param listener callback for updates; optional
*/
- int startBugreport(int fd, IDumpstateListener listener, in DumpstateOptions options);
+ void startBugreport(int callingUid, @utf8InCpp String callingPackage,
+ FileDescriptor bugreportFd, FileDescriptor screenshotFd,
+ int bugreportMode, IDumpstateListener listener);
+
+ /*
+ * Cancels the bugreport currently in progress.
+ */
+ void cancelBugreport();
}
diff --git a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
index 030d69d..907a67c 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
@@ -22,18 +22,49 @@
* {@hide}
*/
interface IDumpstateListener {
+ /**
+ * Called when there is a progress update.
+ *
+ * @param progress the progress in [0, 100]
+ */
+ oneway void onProgress(int progress);
+
+ /* Options specified are invalid or incompatible */
+ const int BUGREPORT_ERROR_INVALID_INPUT = 1;
+
+ /* Bugreport encountered a runtime error */
+ const int BUGREPORT_ERROR_RUNTIME_ERROR = 2;
+
+ /* User denied consent to share the bugreport with the specified app */
+ const int BUGREPORT_ERROR_USER_DENIED_CONSENT = 3;
+
+ /* The request to get user consent timed out */
+ const int BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT = 4;
+
+ /**
+ * Called on an error condition with one of the error codes listed above.
+ */
+ oneway void onError(int errorCode);
+
+ /**
+ * Called when taking bugreport finishes successfully.
+ */
+ oneway void onFinished();
+
+ // TODO(b/111441001): Remove old methods when not used anymore.
void onProgressUpdated(int progress);
void onMaxProgressUpdated(int maxProgress);
/**
- * Called after every section is complete.
- * @param name section name
- * @param status values from status_t
- * {@code OK} section completed successfully
- * {@code TIMEOUT} dump timed out
- * {@code != OK} error
- * @param size size in bytes, may be invalid if status != OK
- * @param durationMs duration in ms
- */
+ * Called after every section is complete.
+ *
+ * @param name section name
+ * @param status values from status_t
+ * {@code OK} section completed successfully
+ * {@code TIMEOUT} dump timed out
+ * {@code != OK} error
+ * @param size size in bytes, may be invalid if status != OK
+ * @param durationMs duration in ms
+ */
void onSectionComplete(@utf8InCpp String name, int status, int size, int durationMs);
}
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 69ced45..a91eafe 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -51,6 +51,7 @@
#include <android-base/unique_fd.h>
#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <android/os/IIncidentCompanion.h>
#include <cutils/native_handle.h>
#include <cutils/properties.h>
#include <dumpsys.h>
@@ -82,15 +83,20 @@
using android::TIMED_OUT;
using android::UNKNOWN_ERROR;
using android::Vector;
+using android::base::StringPrintf;
+using android::os::IDumpstateListener;
using android::os::dumpstate::CommandOptions;
using android::os::dumpstate::DumpFileToFd;
using android::os::dumpstate::DumpstateSectionReporter;
using android::os::dumpstate::GetPidByName;
using android::os::dumpstate::PropertiesHelper;
+typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
+
/* read before root is shed */
static char cmdline_buf[16384] = "(unknown)";
static const char *dump_traces_path = nullptr;
+static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
// TODO: variables and functions below should be part of dumpstate object
@@ -121,6 +127,61 @@
// TODO: temporary variables and functions used during C++ refactoring
static Dumpstate& ds = Dumpstate::GetInstance();
+
+namespace android {
+namespace os {
+namespace {
+
+static int Open(std::string path, int flags, mode_t mode = 0) {
+ int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
+ if (fd == -1) {
+ MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
+ }
+ return fd;
+}
+
+
+static int OpenForRead(std::string path) {
+ return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
+}
+
+bool CopyFile(int in_fd, int out_fd) {
+ char buf[4096];
+ ssize_t byte_count;
+ while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
+ if (!android::base::WriteFully(out_fd, buf, byte_count)) {
+ return false;
+ }
+ }
+ return (byte_count != -1);
+}
+
+static bool CopyFileToFd(const std::string& input_file, int out_fd) {
+ MYLOGD("Going to copy bugreport file (%s) to %d\n", ds.path_.c_str(), out_fd);
+
+ // Obtain a handle to the source file.
+ android::base::unique_fd in_fd(OpenForRead(input_file));
+ if (out_fd != -1 && in_fd.get() != -1) {
+ if (CopyFile(in_fd.get(), out_fd)) {
+ return true;
+ }
+ MYLOGE("Failed to copy zip file: %s\n", strerror(errno));
+ }
+ return false;
+}
+
+static bool UnlinkAndLogOnError(const std::string& file) {
+ if (unlink(file.c_str()) != -1) {
+ MYLOGE("Failed to remove file (%s): %s\n", file.c_str(), strerror(errno));
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+} // namespace os
+} // namespace android
+
static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
const CommandOptions& options = CommandOptions::DEFAULT) {
return ds.RunCommand(title, fullCommand, options);
@@ -137,8 +198,6 @@
// Relative directory (inside the zip) for all files copied as-is into the bugreport.
static const std::string ZIP_ROOT_DIR = "FS";
-// Must be hardcoded because dumpstate HAL implementation need SELinux access to it
-static const std::string kDumpstateBoardPath = "/bugreports/";
static const std::string kProtoPath = "proto/";
static const std::string kProtoExt = ".proto";
static const std::string kDumpstateBoardFiles[] = {
@@ -413,47 +472,6 @@
return false;
}
-static void dump_systrace() {
- if (!ds.IsZipping()) {
- MYLOGD("Not dumping systrace because it's not a zipped bugreport\n");
- return;
- }
- std::string systrace_path = ds.GetPath("-systrace.txt");
- if (systrace_path.empty()) {
- MYLOGE("Not dumping systrace because path is empty\n");
- return;
- }
- const char* path = "/sys/kernel/debug/tracing/tracing_on";
- long int is_tracing;
- if (read_file_as_long(path, &is_tracing)) {
- return; // error already logged
- }
- if (is_tracing <= 0) {
- MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
- return;
- }
-
- MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
- systrace_path.c_str());
- if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--async_dump", "-o", systrace_path},
- CommandOptions::WithTimeout(120).Build())) {
- MYLOGE("systrace timed out, its zip entry will be incomplete\n");
- // TODO: RunCommand tries to kill the process, but atrace doesn't die
- // peacefully; ideally, we should call strace to stop itself, but there is no such option
- // yet (just a --async_stop, which stops and dump
- // if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--kill"})) {
- // MYLOGE("could not stop systrace ");
- // }
- }
- if (!ds.AddZipEntry("systrace.txt", systrace_path)) {
- MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
- } else {
- if (remove(systrace_path.c_str())) {
- MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
- }
- }
-}
-
static bool skip_not_stat(const char *path) {
static const char stat[] = "/stat";
size_t len = strlen(path);
@@ -651,6 +669,32 @@
return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
}
+Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
+}
+
+android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
+ std::lock_guard<std::mutex> lock(lock_);
+ result_ = APPROVED;
+ MYLOGD("User approved consent to share bugreport\n");
+ return android::binder::Status::ok();
+}
+
+android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
+ std::lock_guard<std::mutex> lock(lock_);
+ result_ = DENIED;
+ MYLOGW("User denied consent to share bugreport\n");
+ return android::binder::Status::ok();
+}
+
+UserConsentResult Dumpstate::ConsentCallback::getResult() {
+ std::lock_guard<std::mutex> lock(lock_);
+ return result_;
+}
+
+uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
+ return Nanotime() - start_time_;
+}
+
void Dumpstate::PrintHeader() const {
std::string build, fingerprint, radio, bootloader, network;
char date[80];
@@ -1102,7 +1146,7 @@
}
}
-// Runs dumpsys on services that must dump first and and will take less than 100ms to dump.
+// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
static void RunDumpsysCritical() {
RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
/* timeout= */ 5s, /* service_timeout= */ 500ms);
@@ -1147,7 +1191,7 @@
return !isalnum(c) &&
std::string("@-_:.").find(c) == std::string::npos;
}, '_');
- const std::string path = kDumpstateBoardPath + "lshal_debug_" + cleanName;
+ const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
{
auto fd = android::base::unique_fd(
@@ -1380,12 +1424,8 @@
/* 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();
- }
+ // Try to dump anrd trace if the daemon is running.
+ dump_anrd_trace();
// Invoking the following dumpsys calls before dump_traces() to try and
// keep the system stats as close to its initial state as possible.
@@ -1506,6 +1546,15 @@
RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
SEC_TO_MSEC(10));
+ if (ds.IsZipping()) {
+ RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z"},
+ CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
+ DumpHals();
+ } else {
+ RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z", "--debug"},
+ CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
+ }
+
printf("========================================================\n");
printf("== dumpstate: done (id %d)\n", ds.id_);
printf("========================================================\n");
@@ -1525,7 +1574,8 @@
std::vector<std::string> paths;
std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
for (int i = 0; i < NUM_OF_DUMPS; i++) {
- paths.emplace_back(kDumpstateBoardPath + kDumpstateBoardFiles[i]);
+ paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
+ kDumpstateBoardFiles[i].c_str()));
remover.emplace_back(android::base::make_scope_guard(std::bind(
[](std::string path) {
if (remove(path.c_str()) != 0 && errno != ENOENT) {
@@ -1625,7 +1675,7 @@
printf("*** See dumpstate-board.txt entry ***\n");
}
-static void ShowUsageAndExit(int exit_code = 1) {
+static void ShowUsage() {
fprintf(stderr,
"usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
"[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
@@ -1644,13 +1694,8 @@
"progress (requires -o and -B)\n"
" -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
"shouldn't be used with -P)\n"
+ " -w: start binder service and make it wait for a call to startBugreport\n"
" -v: prints the dumpstate header and exit\n");
- exit(exit_code);
-}
-
-static void ExitOnInvalidArgs() {
- fprintf(stderr, "invalid combination of args\n");
- ShowUsageAndExit();
}
static void register_sig_handler() {
@@ -1683,7 +1728,8 @@
MYLOGE("Failed to add dumpstate log to .zip file\n");
return false;
}
- // ... and re-opens it for further logging.
+ // TODO: Should truncate the existing file.
+ // ... and re-open it for further logging.
redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
fprintf(stderr, "\n");
@@ -1766,17 +1812,23 @@
// clang-format on
}
+static void MaybeResolveSymlink(std::string* path) {
+ std::string resolved_path;
+ if (android::base::Readlink(*path, &resolved_path)) {
+ *path = resolved_path;
+ }
+}
+
/*
* 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() {
- ds.bugreport_dir_ = dirname(ds.options_->use_outfile.c_str());
+ MaybeResolveSymlink(&ds.bugreport_internal_dir_);
+
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(ds.options_->use_outfile.c_str()),
- device_name.c_str(), build_id.c_str());
+ ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
if (ds.options_->do_add_date) {
char date[80];
strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
@@ -1797,6 +1849,9 @@
ds.tmp_path_ = ds.GetPath(".tmp");
ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
+ std::string destination = ds.options_->bugreport_fd.get() != -1
+ ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
+ : ds.bugreport_internal_dir_.c_str();
MYLOGD(
"Bugreport dir: %s\n"
"Base name: %s\n"
@@ -1804,7 +1859,7 @@
"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(),
+ destination.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 (ds.options_->do_zip_file) {
@@ -1860,7 +1915,7 @@
do_text_file = true;
} else {
do_text_file = false;
- // Since zip file is already created, it needs to be renamed.
+ // If the user has changed the suffix, we need to change the zip file name.
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());
@@ -1895,6 +1950,7 @@
/* Broadcasts that we are done with the bugreport */
static void SendBugreportFinishedBroadcast() {
+ // TODO(b/111441001): use callback instead of broadcast.
if (!ds.path_.empty()) {
MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
// clang-format off
@@ -1913,7 +1969,7 @@
am_args.push_back("android.intent.extra.SCREENSHOT");
am_args.push_back(ds.screenshot_path_);
}
- if (ds.options_->notification_title.empty()) {
+ if (!ds.options_->notification_title.empty()) {
am_args.push_back("--es");
am_args.push_back("android.intent.extra.TITLE");
am_args.push_back(ds.options_->notification_title);
@@ -1936,44 +1992,110 @@
}
}
-// TODO: Move away from system properties when we have options passed via binder calls.
-/* Sets runtime options from the system properties and then clears those properties. */
-static void SetOptionsFromProperties(Dumpstate::DumpOptions* options) {
- options->extra_options = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
- if (!options->extra_options.empty()) {
- // Framework uses a system property to override some command-line args.
- // Currently, it contains the type of the requested bugreport.
- if (options->extra_options == "bugreportplus") {
+static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
+ switch (mode) {
+ case Dumpstate::BugreportMode::BUGREPORT_FULL:
+ return "BUGREPORT_FULL";
+ case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
+ return "BUGREPORT_INTERACTIVE";
+ case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
+ return "BUGREPORT_REMOTE";
+ case Dumpstate::BugreportMode::BUGREPORT_WEAR:
+ return "BUGREPORT_WEAR";
+ case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
+ return "BUGREPORT_TELEPHONY";
+ case Dumpstate::BugreportMode::BUGREPORT_WIFI:
+ return "BUGREPORT_WIFI";
+ case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
+ return "BUGREPORT_DEFAULT";
+ }
+}
+
+static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options) {
+ options->extra_options = ModeToString(mode);
+ switch (mode) {
+ case Dumpstate::BugreportMode::BUGREPORT_FULL:
+ options->do_broadcast = true;
+ options->do_fb = true;
+ break;
+ case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
// Currently, the dumpstate binder is only used by Shell to update progress.
options->do_start_service = true;
options->do_progress_updates = true;
options->do_fb = false;
- } else if (options->extra_options == "bugreportremote") {
+ options->do_broadcast = true;
+ break;
+ case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
options->do_vibrate = false;
options->is_remote_mode = true;
options->do_fb = false;
- } else if (options->extra_options == "bugreportwear") {
+ options->do_broadcast = true;
+ break;
+ case Dumpstate::BugreportMode::BUGREPORT_WEAR:
options->do_start_service = true;
options->do_progress_updates = true;
options->do_zip_file = true;
- } else if (options->extra_options == "bugreporttelephony") {
+ options->do_fb = true;
+ options->do_broadcast = true;
+ break;
+ case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
options->telephony_only = true;
- } else if (options->extra_options == "bugreportwifi") {
+ options->do_fb = true;
+ options->do_broadcast = true;
+ break;
+ case Dumpstate::BugreportMode::BUGREPORT_WIFI:
options->wifi_only = true;
options->do_zip_file = true;
+ options->do_fb = true;
+ options->do_broadcast = true;
+ break;
+ case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
+ break;
+ }
+}
+
+static Dumpstate::BugreportMode getBugreportModeFromProperty() {
+ // If the system property is not set, it's assumed to be a default bugreport.
+ Dumpstate::BugreportMode mode = Dumpstate::BugreportMode::BUGREPORT_DEFAULT;
+
+ std::string 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") {
+ mode = Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE;
+ } else if (extra_options == "bugreportfull") {
+ mode = Dumpstate::BugreportMode::BUGREPORT_FULL;
+ } else if (extra_options == "bugreportremote") {
+ mode = Dumpstate::BugreportMode::BUGREPORT_REMOTE;
+ } else if (extra_options == "bugreportwear") {
+ mode = Dumpstate::BugreportMode::BUGREPORT_WEAR;
+ } else if (extra_options == "bugreporttelephony") {
+ mode = Dumpstate::BugreportMode::BUGREPORT_TELEPHONY;
+ } else if (extra_options == "bugreportwifi") {
+ mode = Dumpstate::BugreportMode::BUGREPORT_WIFI;
} else {
- MYLOGE("Unknown extra option: %s\n", options->extra_options.c_str());
+ MYLOGE("Unknown extra option: %s\n", extra_options.c_str());
}
// Reset the property
android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
}
+ return mode;
+}
+
+// TODO: Move away from system properties when we have options passed via binder calls.
+/* Sets runtime options from the system properties and then clears those properties. */
+static void SetOptionsFromProperties(Dumpstate::DumpOptions* options) {
+ Dumpstate::BugreportMode mode = getBugreportModeFromProperty();
+ SetOptionsFromMode(mode, options);
options->notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
if (!options->notification_title.empty()) {
// Reset the property
android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
- options->extra_options = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
+ options->notification_description =
+ android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
if (!options->notification_description.empty()) {
// Reset the property
android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
@@ -1983,15 +2105,54 @@
}
}
+static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
+ MYLOGI("do_zip_file: %d\n", options.do_zip_file);
+ MYLOGI("do_add_date: %d\n", options.do_add_date);
+ MYLOGI("do_vibrate: %d\n", options.do_vibrate);
+ MYLOGI("use_socket: %d\n", options.use_socket);
+ MYLOGI("use_control_socket: %d\n", options.use_control_socket);
+ MYLOGI("do_fb: %d\n", options.do_fb);
+ MYLOGI("do_broadcast: %d\n", options.do_broadcast);
+ MYLOGI("is_remote_mode: %d\n", options.is_remote_mode);
+ MYLOGI("show_header_only: %d\n", options.show_header_only);
+ MYLOGI("do_start_service: %d\n", options.do_start_service);
+ MYLOGI("telephony_only: %d\n", options.telephony_only);
+ MYLOGI("wifi_only: %d\n", options.wifi_only);
+ MYLOGI("do_progress_updates: %d\n", options.do_progress_updates);
+ MYLOGI("fd: %d\n", options.bugreport_fd.get());
+ MYLOGI("extra_options: %s\n", options.extra_options.c_str());
+ MYLOGI("args: %s\n", options.args.c_str());
+ MYLOGI("notification_title: %s\n", options.notification_title.c_str());
+ MYLOGI("notification_description: %s\n", options.notification_description.c_str());
+}
+
+void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
+ const android::base::unique_fd& bugreport_fd_in,
+ const android::base::unique_fd& screenshot_fd_in) {
+ // In the new API world, date is always added; output is always a zip file.
+ // TODO(111441001): remove these options once they are obsolete.
+ do_add_date = true;
+ do_zip_file = true;
+
+ // Duplicate the fds because the passed in fds don't outlive the binder transaction.
+ bugreport_fd.reset(dup(bugreport_fd_in.get()));
+ screenshot_fd.reset(dup(screenshot_fd_in.get()));
+
+ extra_options = ModeToString(bugreport_mode);
+ SetOptionsFromMode(bugreport_mode, this);
+}
+
Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
RunStatus status = RunStatus::OK;
int c;
- while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
+ while ((c = getopt(argc, argv, "dho:svqzpPBRSV:w")) != -1) {
switch (c) {
// clang-format off
case 'd': do_add_date = true; break;
case 'z': do_zip_file = true; break;
- case 'o': use_outfile = optarg; break;
+ // o=use_outfile not supported anymore.
+ // TODO(b/111441001): Remove when all callers have migrated.
+ case 'o': break;
case 's': use_socket = true; break;
case 'S': use_control_socket = true; break;
case 'v': show_header_only = true; break;
@@ -2001,6 +2162,9 @@
case 'R': is_remote_mode = true; break;
case 'B': do_broadcast = true; break;
case 'V': break; // compatibility no-op
+ case 'w':
+ // This was already processed
+ break;
case 'h':
status = RunStatus::HELP;
break;
@@ -2028,8 +2192,11 @@
}
bool Dumpstate::DumpOptions::ValidateOptions() const {
- if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast)
- && use_outfile.empty()) {
+ if (bugreport_fd.get() != -1 && !do_zip_file) {
+ return false;
+ }
+
+ if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast) && !OutputToFile()) {
return false;
}
@@ -2047,11 +2214,64 @@
return true;
}
-Dumpstate::RunStatus Dumpstate::RunWithOptions(std::unique_ptr<DumpOptions> options) {
- if (!options->ValidateOptions()) {
+void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
+ options_ = std::move(options);
+}
+
+Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
+ Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
+ if (listener_ != nullptr) {
+ switch (status) {
+ case Dumpstate::RunStatus::OK:
+ listener_->onFinished();
+ break;
+ case Dumpstate::RunStatus::HELP:
+ break;
+ case Dumpstate::RunStatus::INVALID_INPUT:
+ listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
+ break;
+ case Dumpstate::RunStatus::ERROR:
+ listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
+ break;
+ case Dumpstate::RunStatus::USER_CONSENT_DENIED:
+ listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
+ break;
+ case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
+ listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
+ break;
+ }
+ }
+ return status;
+}
+
+/*
+ * Dumps relevant information to a bugreport based on the given options.
+ *
+ * The bugreport can be dumped to a file or streamed to a socket.
+ *
+ * How dumping to file works:
+ * stdout is redirected to a temporary file. This will later become the main bugreport entry.
+ * stderr is redirected a log file.
+ *
+ * The temporary bugreport is then populated via printfs, dumping contents of files and
+ * output of commands to stdout.
+ *
+ * If zipping, the temporary bugreport file is added to the zip archive. Else it's renamed to final
+ * text file.
+ *
+ * If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also
+ * gets added to the archive.
+ *
+ * Bugreports are first generated in a local directory and later copied to the caller's fd if
+ * supplied.
+ */
+Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
+ const std::string& calling_package) {
+ LogDumpOptions(*options_);
+ if (!options_->ValidateOptions()) {
+ MYLOGE("Invalid options specified\n");
return RunStatus::INVALID_INPUT;
}
- options_ = std::move(options);
/* set as high priority, and protect from OOM killer */
setpriority(PRIO_PROCESS, 0, -20);
@@ -2084,14 +2304,20 @@
return RunStatus::OK;
}
+ if (options_->bugreport_fd.get() != -1) {
+ // If the output needs to be copied over to the caller's fd, get user consent.
+ android::String16 package(calling_package.c_str());
+ CheckUserConsent(calling_uid, package);
+ }
+
// Redirect output if needed
- bool is_redirecting = !options_->use_socket && !options_->use_outfile.empty();
+ bool is_redirecting = options_->OutputToFile();
// 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(options_->use_outfile.c_str()))
- : "";
+ is_redirecting
+ ? android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str())
+ : "";
progress_.reset(new Progress(stats_path));
/* gets the sequential id */
@@ -2187,13 +2413,18 @@
int dup_stdout_fd;
int dup_stderr_fd;
if (is_redirecting) {
+ // Redirect stderr to log_path_ for debugging.
TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()));
if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
strerror(errno));
}
+
+ // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
+ // moved into zip file later, if zipping.
TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
+ // TODO: why not write to a file instead of stdout to overcome this problem?
/* TODO: rather than generating a text file now and zipping it later,
it would be more efficient to redirect stdout to the zip entry
directly, but the libziparchive doesn't support that option yet. */
@@ -2230,11 +2461,31 @@
TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
}
- /* rename or zip the (now complete) .tmp file to its final location */
- if (!options_->use_outfile.empty()) {
+ // Rename, and/or zip the (now complete) .tmp file within the internal directory.
+ if (options_->OutputToFile()) {
FinalizeFile();
}
+ // Share the final file with the caller if the user has consented.
+ Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
+ if (options_->bugreport_fd.get() != -1) {
+ status = CopyBugreportIfUserConsented();
+ if (status != Dumpstate::RunStatus::OK &&
+ status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
+ // Do an early return if there were errors. We make an exception for consent
+ // timing out because it's possible the user got distracted. In this case the
+ // bugreport is not shared but made available for manual retrieval.
+ return status;
+ }
+ if (options_->screenshot_fd.get() != -1) {
+ bool copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
+ options_->screenshot_fd.get());
+ if (copy_succeeded) {
+ android::os::UnlinkAndLogOnError(screenshot_path_);
+ }
+ }
+ }
+
/* vibrate a few but shortly times to let user know it's finished */
if (options_->do_vibrate) {
for (int i = 0; i < 3; i++) {
@@ -2246,6 +2497,7 @@
/* tell activity manager we're done */
if (options_->do_broadcast) {
SendBugreportFinishedBroadcast();
+ // Note that listener_ is notified in Run();
}
MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
@@ -2265,30 +2517,106 @@
tombstone_data_.clear();
anr_data_.clear();
- return RunStatus::OK;
+ return (consent_callback_ != nullptr &&
+ consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
+ ? USER_CONSENT_TIMED_OUT
+ : RunStatus::OK;
}
-/* Main entry point for dumpstate. */
+void Dumpstate::CheckUserConsent(int32_t calling_uid, const android::String16& calling_package) {
+ consent_callback_ = new ConsentCallback();
+ const String16 incidentcompanion("incidentcompanion");
+ sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
+ if (ics != nullptr) {
+ MYLOGD("Checking user consent via incidentcompanion service\n");
+ android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
+ calling_uid, calling_package, 0x1 /* FLAG_CONFIRMATION_DIALOG */,
+ consent_callback_.get());
+ } else {
+ MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
+ }
+}
+
+void Dumpstate::CleanupFiles() {
+ android::os::UnlinkAndLogOnError(tmp_path_);
+ android::os::UnlinkAndLogOnError(screenshot_path_);
+ android::os::UnlinkAndLogOnError(path_);
+}
+
+Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
+ MYLOGD("User denied consent; deleting files and returning\n");
+ CleanupFiles();
+ return USER_CONSENT_DENIED;
+}
+
+Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented() {
+ // If the caller has asked to copy the bugreport over to their directory, we need explicit
+ // user consent.
+ UserConsentResult consent_result = consent_callback_->getResult();
+ if (consent_result == UserConsentResult::UNAVAILABLE) {
+ // User has not responded yet.
+ uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
+ if (elapsed_ms < USER_CONSENT_TIMEOUT_MS) {
+ uint delay_seconds = (USER_CONSENT_TIMEOUT_MS - elapsed_ms) / 1000;
+ MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
+ sleep(delay_seconds);
+ }
+ consent_result = consent_callback_->getResult();
+ }
+ if (consent_result == UserConsentResult::DENIED) {
+ // User has explicitly denied sharing with the app. To be safe delete the
+ // internal bugreport & tmp files.
+ return HandleUserConsentDenied();
+ }
+ if (consent_result == UserConsentResult::APPROVED) {
+ bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
+ if (copy_succeeded) {
+ android::os::UnlinkAndLogOnError(path_);
+ }
+ return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
+ } else if (consent_result == UserConsentResult::UNAVAILABLE) {
+ // consent_result is still UNAVAILABLE. The user has likely not responded yet.
+ // Since we do not have user consent to share the bugreport it does not get
+ // copied over to the calling app but remains in the internal directory from
+ // where the user can manually pull it.
+ return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
+ }
+ // Unknown result; must be a programming error.
+ MYLOGE("Unknown user consent result:%d\n", consent_result);
+ return Dumpstate::RunStatus::ERROR;
+}
+
+/* Main entry point for dumpstate binary. */
int run_main(int argc, char* argv[]) {
std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
Dumpstate::RunStatus status = options->Initialize(argc, argv);
if (status == Dumpstate::RunStatus::OK) {
- status = ds.RunWithOptions(std::move(options));
+ ds.SetOptions(std::move(options));
+ // When directly running dumpstate binary, the output is not expected to be written
+ // to any external file descriptor.
+ assert(ds.options_->bugreport_fd.get() == -1);
+
+ // calling_uid and calling_package are for user consent to share the bugreport with
+ // an app; they are irrelvant here because bugreport is only written to a local
+ // directory, and not shared.
+ status = ds.Run(-1 /* calling_uid */, "" /* calling_package */);
}
switch (status) {
case Dumpstate::RunStatus::OK:
- return 0;
- break;
+ exit(0);
case Dumpstate::RunStatus::HELP:
- ShowUsageAndExit(0 /* exit code */);
- break;
+ ShowUsage();
+ exit(0);
case Dumpstate::RunStatus::INVALID_INPUT:
- ExitOnInvalidArgs();
- break;
+ fprintf(stderr, "Invalid combination of args\n");
+ ShowUsage();
+ exit(1);
case Dumpstate::RunStatus::ERROR:
- exit(-1);
- break;
+ FALLTHROUGH_INTENDED;
+ case Dumpstate::RunStatus::USER_CONSENT_DENIED:
+ FALLTHROUGH_INTENDED;
+ case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
+ exit(2);
}
- return 0;
}
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index c2f7f6a..7fb2f3b 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -27,6 +27,8 @@
#include <android-base/macros.h>
#include <android-base/unique_fd.h>
+#include <android/os/BnIncidentAuthListener.h>
+#include <android/os/IDumpstate.h>
#include <android/os/IDumpstateListener.h>
#include <utils/StrongPointer.h>
#include <ziparchive/zip_writer.h>
@@ -42,6 +44,9 @@
// TODO: and then remove explicitly android::os::dumpstate:: prefixes
namespace android {
namespace os {
+
+struct DumpstateOptions;
+
namespace dumpstate {
class DumpstateTest;
@@ -68,7 +73,7 @@
*/
class DurationReporter {
public:
- DurationReporter(const std::string& title, bool log_only = false);
+ explicit DurationReporter(const std::string& title, bool log_only = false);
~DurationReporter();
@@ -107,7 +112,7 @@
*/
static const int kDefaultMax;
- Progress(const std::string& path = "");
+ explicit Progress(const std::string& path = "");
// Gets the current progress.
int32_t Get() const;
@@ -138,7 +143,7 @@
float growth_factor_;
int32_t n_runs_;
int32_t average_max_;
- const std::string& path_;
+ std::string path_;
};
/*
@@ -160,6 +165,11 @@
static std::string VERSION_DEFAULT = "default";
/*
+ * Directory used by Dumpstate binary to keep its local files.
+ */
+static const std::string DUMPSTATE_DIRECTORY = "/bugreports";
+
+/*
* Structure that contains the information of an open dump file.
*/
struct DumpData {
@@ -183,7 +193,18 @@
friend class DumpstateTest;
public:
- enum RunStatus { OK, HELP, INVALID_INPUT, ERROR };
+ enum RunStatus { OK, HELP, INVALID_INPUT, ERROR, USER_CONSENT_DENIED, USER_CONSENT_TIMED_OUT };
+
+ // The mode under which the bugreport should be run. Each mode encapsulates a few options.
+ enum BugreportMode {
+ BUGREPORT_FULL = android::os::IDumpstate::BUGREPORT_MODE_FULL,
+ BUGREPORT_INTERACTIVE = android::os::IDumpstate::BUGREPORT_MODE_INTERACTIVE,
+ BUGREPORT_REMOTE = android::os::IDumpstate::BUGREPORT_MODE_REMOTE,
+ BUGREPORT_WEAR = android::os::IDumpstate::BUGREPORT_MODE_WEAR,
+ BUGREPORT_TELEPHONY = android::os::IDumpstate::BUGREPORT_MODE_TELEPHONY,
+ BUGREPORT_WIFI = android::os::IDumpstate::BUGREPORT_MODE_WIFI,
+ BUGREPORT_DEFAULT = android::os::IDumpstate::BUGREPORT_MODE_DEFAULT
+ };
static android::os::dumpstate::CommandOptions DEFAULT_DUMPSYS;
@@ -247,7 +268,7 @@
std::chrono::milliseconds timeout);
/*
- * Adds a text entry entry to the existing zip file.
+ * Adds a text entry to the existing zip file.
*/
bool AddTextZipEntry(const std::string& entry_name, const std::string& content);
@@ -286,7 +307,11 @@
*/
bool FinishZipFile();
- /* Gets the path of a bugreport file with the given suffix. */
+ /* Constructs a full path inside directory with file name formatted using the given suffix. */
+ std::string GetPath(const std::string& directory, const std::string& suffix) const;
+
+ /* Constructs a full path inside bugreport_internal_dir_ with file name formatted using the
+ * given suffix. */
std::string GetPath(const std::string& suffix) const;
/* Returns true if the current version supports priority dump feature. */
@@ -294,10 +319,12 @@
struct DumpOptions;
- /* Main entry point for running a complete bugreport. Takes ownership of options. */
- RunStatus RunWithOptions(std::unique_ptr<DumpOptions> options);
+ /* Main entry point for running a complete bugreport. */
+ RunStatus Run(int32_t calling_uid, const std::string& calling_package);
- // TODO: add other options from DumpState.
+ /* Sets runtime options. */
+ void SetOptions(std::unique_ptr<DumpOptions> options);
+
/*
* Structure to hold options that determine the behavior of dumpstate.
*/
@@ -305,6 +332,7 @@
bool do_add_date = false;
bool do_zip_file = false;
bool do_vibrate = true;
+ // Writes bugreport content to a socket; only flatfile format is supported.
bool use_socket = false;
bool use_control_socket = false;
bool do_fb = false;
@@ -316,7 +344,11 @@
bool wifi_only = false;
// Whether progress updates should be published.
bool do_progress_updates = false;
- std::string use_outfile;
+ // File descriptor to output zip file.
+ android::base::unique_fd bugreport_fd;
+ // File descriptor to screenshot file.
+ android::base::unique_fd screenshot_fd;
+ // TODO: rename to MODE.
// Extra options passed as system property.
std::string extra_options;
// Command-line arguments as string
@@ -328,8 +360,19 @@
/* Initializes options from commandline arguments and system properties. */
RunStatus Initialize(int argc, char* argv[]);
+ /* Initializes options from the requested mode. */
+ void Initialize(BugreportMode bugreport_mode, const android::base::unique_fd& bugreport_fd,
+ const android::base::unique_fd& screenshot_fd);
+
/* Returns true if the options set so far are consistent. */
bool ValidateOptions() const;
+
+ /* Returns if options specified require writing bugreport to a file */
+ bool OutputToFile() const {
+ // If we are not writing to socket, we will write to a file. If bugreport_fd is
+ // specified, it is preferred. If not bugreport is written to /bugreports.
+ return !use_socket;
+ }
};
// TODO: initialize fields on constructor
@@ -360,12 +403,6 @@
// Bugreport format version;
std::string version_ = VERSION_CURRENT;
- // Full path of the directory where the bugreport files will be written.
- std::string bugreport_dir_;
-
- // Full path of the temporary file containing the screenshot (when requested).
- std::string screenshot_path_;
-
time_t now_;
// Base name (without suffix or extensions) of the bugreport files, typically
@@ -376,15 +413,23 @@
// `-d`), but it could be changed by the user..
std::string name_;
- // Full path of the temporary file containing the bugreport.
+ std::string bugreport_internal_dir_ = DUMPSTATE_DIRECTORY;
+
+ // Full path of the temporary file containing the bugreport, inside bugreport_internal_dir_.
+ // At the very end this file is pulled into the zip file.
std::string tmp_path_;
- // Full path of the file containing the dumpstate logs.
+ // Full path of the file containing the dumpstate logs, inside bugreport_internal_dir_.
+ // This is useful for debugging.
std::string log_path_;
- // Pointer to the actual path, be it zip or text.
+ // Full path of the bugreport file, be it zip or text, inside bugreport_internal_dir_.
std::string path_;
+ // TODO: If temporary this should be removed at the end.
+ // Full path of the temporary file containing the screenshot (when requested).
+ std::string screenshot_path_;
+
// Pointer to the zipped file.
std::unique_ptr<FILE, int (*)(FILE*)> zip_file{nullptr, fclose};
@@ -402,9 +447,46 @@
// List of open ANR dump files.
std::vector<DumpData> anr_data_;
+ // A callback to IncidentCompanion service, which checks user consent for sharing the
+ // bugreport with the calling app. If the user has not responded yet to the dialog it will
+ // be neither confirmed nor denied.
+ class ConsentCallback : public android::os::BnIncidentAuthListener {
+ public:
+ ConsentCallback();
+ android::binder::Status onReportApproved() override;
+ android::binder::Status onReportDenied() override;
+
+ enum ConsentResult { APPROVED, DENIED, UNAVAILABLE };
+
+ ConsentResult getResult();
+
+ // Returns the time since creating this listener
+ uint64_t getElapsedTimeMs() const;
+
+ private:
+ ConsentResult result_;
+ uint64_t start_time_;
+ std::mutex lock_;
+ };
+
private:
+ RunStatus RunInternal(int32_t calling_uid, const std::string& calling_package);
+
+ void CheckUserConsent(int32_t calling_uid, const android::String16& calling_package);
+
+ // Removes the in progress files output files (tmp file, zip/txt file, screenshot),
+ // but leaves the log file alone.
+ void CleanupFiles();
+
+ RunStatus HandleUserConsentDenied();
+
+ // Copies bugreport artifacts over to the caller's directories provided there is user consent.
+ RunStatus CopyBugreportIfUserConsented();
+
// Used by GetInstance() only.
- Dumpstate(const std::string& version = VERSION_CURRENT);
+ explicit Dumpstate(const std::string& version = VERSION_CURRENT);
+
+ android::sp<ConsentCallback> consent_callback_;
DISALLOW_COPY_AND_ASSIGN(Dumpstate);
};
diff --git a/cmds/dumpstate/dumpstate.rc b/cmds/dumpstate/dumpstate.rc
index 2e72574..14937b8 100644
--- a/cmds/dumpstate/dumpstate.rc
+++ b/cmds/dumpstate/dumpstate.rc
@@ -17,3 +17,9 @@
class main
disabled
oneshot
+
+# bugreportd starts dumpstate binder service and makes it wait for a listener to connect.
+service bugreportd /system/bin/dumpstate -w
+ class main
+ disabled
+ oneshot
diff --git a/cmds/dumpstate/main.cpp b/cmds/dumpstate/main.cpp
index 78aad11..68d3733 100644
--- a/cmds/dumpstate/main.cpp
+++ b/cmds/dumpstate/main.cpp
@@ -14,8 +14,55 @@
* limitations under the License.
*/
+#define LOG_TAG "dumpstate"
+
+#include <binder/IPCThreadState.h>
+
+#include "DumpstateInternal.h"
+#include "DumpstateService.h"
#include "dumpstate.h"
+namespace {
+
+// Returns true if we should start the service and wait for a listener
+// to bind with bugreport options.
+bool ShouldStartServiceAndWait(int argc, char* argv[]) {
+ bool do_wait = false;
+ int c;
+ // Keep flags in sync with Dumpstate::DumpOptions::Initialize.
+ while ((c = getopt(argc, argv, "wdho:svqzpPBRSV:")) != -1 && !do_wait) {
+ switch (c) {
+ case 'w':
+ do_wait = true;
+ break;
+ default:
+ // Ignore all other options
+ break;
+ }
+ }
+
+ // Reset next index used by getopt so getopt can be called called again in Dumpstate::Run to
+ // parse bugreport options.
+ optind = 1;
+ return do_wait;
+}
+
+} // namespace
+
int main(int argc, char* argv[]) {
- return run_main(argc, argv);
+ if (ShouldStartServiceAndWait(argc, argv)) {
+ int ret;
+ if ((ret = android::os::DumpstateService::Start()) != android::OK) {
+ MYLOGE("Unable to start 'dumpstate' service: %d", ret);
+ exit(1);
+ }
+ MYLOGI("'dumpstate' service started and will wait for a call to startBugreport()");
+
+ // Waits forever for an incoming connection.
+ // TODO(b/111441001): should this time out?
+ android::IPCThreadState::self()->joinThreadPool();
+ return 0;
+ } else {
+ return run_main(argc, argv);
+ }
}
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
index 61a5ef5..570c6c9 100644
--- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -53,6 +53,18 @@
DumpstateListener(int fd, std::shared_ptr<std::vector<SectionInfo>> sections)
: outFd_(fd), max_progress_(5000), sections_(sections) {
}
+ binder::Status onProgress(int32_t progress) override {
+ dprintf(outFd_, "\rIn progress %d", progress);
+ return binder::Status::ok();
+ }
+ binder::Status onError(int32_t error_code) override {
+ dprintf(outFd_, "\rError %d", error_code);
+ return binder::Status::ok();
+ }
+ binder::Status onFinished() override {
+ dprintf(outFd_, "\rFinished");
+ return binder::Status::ok();
+ }
binder::Status onProgressUpdated(int32_t progress) override {
dprintf(outFd_, "\rIn progress %d/%d", progress, max_progress_);
return binder::Status::ok();
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index b675c51..eb73d41 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -36,6 +36,7 @@
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
+#include <cutils/properties.h>
namespace android {
namespace os {
@@ -58,6 +59,9 @@
class DumpstateListenerMock : public IDumpstateListener {
public:
+ MOCK_METHOD1(onProgress, binder::Status(int32_t progress));
+ MOCK_METHOD1(onError, binder::Status(int32_t error_code));
+ MOCK_METHOD0(onFinished, binder::Status());
MOCK_METHOD1(onProgressUpdated, binder::Status(int32_t progress));
MOCK_METHOD1(onMaxProgressUpdated, binder::Status(int32_t max_progress));
MOCK_METHOD4(onSectionComplete, binder::Status(const ::std::string& name, int32_t status,
@@ -85,6 +89,10 @@
PropertiesHelper::build_type_ = build_type;
}
+ void SetUnroot(bool unroot) const {
+ PropertiesHelper::unroot_ = unroot;
+ }
+
bool IsStandalone() const {
return calls_ == 1;
}
@@ -144,7 +152,10 @@
virtual void SetUp() {
options_ = Dumpstate::DumpOptions();
}
-
+ void TearDown() {
+ // Reset the property
+ property_set("dumpstate.options", "");
+ }
Dumpstate::DumpOptions options_;
};
@@ -155,13 +166,12 @@
};
// clang-format on
- Dumpstate::DumpOptions options;
Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
EXPECT_EQ(status, Dumpstate::RunStatus::OK);
+
EXPECT_FALSE(options_.do_add_date);
EXPECT_FALSE(options_.do_zip_file);
- EXPECT_EQ("", options_.use_outfile);
EXPECT_FALSE(options_.use_socket);
EXPECT_FALSE(options_.use_control_socket);
EXPECT_FALSE(options_.show_header_only);
@@ -172,13 +182,280 @@
EXPECT_FALSE(options_.do_broadcast);
}
+TEST_F(DumpOptionsTest, InitializeAdbBugreport) {
+ // clang-format off
+ char* argv[] = {
+ const_cast<char*>("dumpstatez"),
+ const_cast<char*>("-S"),
+ const_cast<char*>("-d"),
+ const_cast<char*>("-z"),
+ };
+ // clang-format on
+
+ Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
+
+ EXPECT_EQ(status, Dumpstate::RunStatus::OK);
+ EXPECT_TRUE(options_.do_add_date);
+ EXPECT_TRUE(options_.do_zip_file);
+ EXPECT_TRUE(options_.use_control_socket);
+
+ // Other options retain default values
+ EXPECT_TRUE(options_.do_vibrate);
+ EXPECT_FALSE(options_.show_header_only);
+ EXPECT_FALSE(options_.do_fb);
+ EXPECT_FALSE(options_.do_progress_updates);
+ EXPECT_FALSE(options_.is_remote_mode);
+ EXPECT_FALSE(options_.do_broadcast);
+ EXPECT_FALSE(options_.use_socket);
+}
+
+TEST_F(DumpOptionsTest, InitializeAdbShellBugreport) {
+ // clang-format off
+ char* argv[] = {
+ const_cast<char*>("dumpstate"),
+ const_cast<char*>("-s"),
+ };
+ // clang-format on
+
+ Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
+
+ EXPECT_EQ(status, Dumpstate::RunStatus::OK);
+ EXPECT_TRUE(options_.use_socket);
+
+ // Other options retain default values
+ EXPECT_TRUE(options_.do_vibrate);
+ EXPECT_FALSE(options_.do_add_date);
+ EXPECT_FALSE(options_.do_zip_file);
+ EXPECT_FALSE(options_.use_control_socket);
+ EXPECT_FALSE(options_.show_header_only);
+ EXPECT_FALSE(options_.do_fb);
+ EXPECT_FALSE(options_.do_progress_updates);
+ EXPECT_FALSE(options_.is_remote_mode);
+ EXPECT_FALSE(options_.do_broadcast);
+}
+
+TEST_F(DumpOptionsTest, InitializeFullBugReport) {
+ // clang-format off
+ char* argv[] = {
+ const_cast<char*>("bugreport"),
+ const_cast<char*>("-d"),
+ const_cast<char*>("-p"),
+ const_cast<char*>("-B"),
+ const_cast<char*>("-z"),
+ };
+ // clang-format on
+ property_set("dumpstate.options", "bugreportfull");
+
+ Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
+
+ EXPECT_EQ(status, Dumpstate::RunStatus::OK);
+ EXPECT_TRUE(options_.do_add_date);
+ EXPECT_TRUE(options_.do_fb);
+ EXPECT_TRUE(options_.do_zip_file);
+ EXPECT_TRUE(options_.do_broadcast);
+
+ // Other options retain default values
+ EXPECT_TRUE(options_.do_vibrate);
+ EXPECT_FALSE(options_.use_control_socket);
+ EXPECT_FALSE(options_.show_header_only);
+ EXPECT_FALSE(options_.do_progress_updates);
+ EXPECT_FALSE(options_.is_remote_mode);
+ EXPECT_FALSE(options_.use_socket);
+ EXPECT_FALSE(options_.do_start_service);
+}
+
+TEST_F(DumpOptionsTest, InitializeInteractiveBugReport) {
+ // clang-format off
+ char* argv[] = {
+ const_cast<char*>("bugreport"),
+ const_cast<char*>("-d"),
+ const_cast<char*>("-p"),
+ const_cast<char*>("-B"),
+ const_cast<char*>("-z"),
+ };
+ // clang-format on
+
+ property_set("dumpstate.options", "bugreportplus");
+
+ Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
+
+ EXPECT_EQ(status, Dumpstate::RunStatus::OK);
+ EXPECT_TRUE(options_.do_add_date);
+ EXPECT_TRUE(options_.do_broadcast);
+ EXPECT_TRUE(options_.do_zip_file);
+ EXPECT_TRUE(options_.do_progress_updates);
+ EXPECT_TRUE(options_.do_start_service);
+ EXPECT_FALSE(options_.do_fb);
+
+ // Other options retain default values
+ EXPECT_TRUE(options_.do_vibrate);
+ EXPECT_FALSE(options_.use_control_socket);
+ EXPECT_FALSE(options_.show_header_only);
+ EXPECT_FALSE(options_.is_remote_mode);
+ EXPECT_FALSE(options_.use_socket);
+}
+
+TEST_F(DumpOptionsTest, InitializeRemoteBugReport) {
+ // clang-format off
+ char* argv[] = {
+ const_cast<char*>("bugreport"),
+ const_cast<char*>("-d"),
+ const_cast<char*>("-p"),
+ const_cast<char*>("-B"),
+ const_cast<char*>("-z"),
+ };
+ // clang-format on
+
+ property_set("dumpstate.options", "bugreportremote");
+
+ Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
+
+ EXPECT_EQ(status, Dumpstate::RunStatus::OK);
+ EXPECT_TRUE(options_.do_add_date);
+ EXPECT_TRUE(options_.do_broadcast);
+ EXPECT_TRUE(options_.do_zip_file);
+ EXPECT_TRUE(options_.is_remote_mode);
+ EXPECT_FALSE(options_.do_vibrate);
+ EXPECT_FALSE(options_.do_fb);
+
+ // Other options retain default values
+ EXPECT_FALSE(options_.use_control_socket);
+ EXPECT_FALSE(options_.show_header_only);
+ EXPECT_FALSE(options_.do_progress_updates);
+ EXPECT_FALSE(options_.use_socket);
+}
+
+TEST_F(DumpOptionsTest, InitializeWearBugReport) {
+ // clang-format off
+ char* argv[] = {
+ const_cast<char*>("bugreport"),
+ const_cast<char*>("-d"),
+ const_cast<char*>("-p"),
+ const_cast<char*>("-B"),
+ const_cast<char*>("-z"),
+ };
+ // clang-format on
+
+ property_set("dumpstate.options", "bugreportwear");
+
+ Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
+
+ EXPECT_EQ(status, Dumpstate::RunStatus::OK);
+ EXPECT_TRUE(options_.do_add_date);
+ EXPECT_TRUE(options_.do_fb);
+ EXPECT_TRUE(options_.do_broadcast);
+ EXPECT_TRUE(options_.do_zip_file);
+ EXPECT_TRUE(options_.do_progress_updates);
+ EXPECT_TRUE(options_.do_start_service);
+
+ // Other options retain default values
+ EXPECT_TRUE(options_.do_vibrate);
+ EXPECT_FALSE(options_.use_control_socket);
+ EXPECT_FALSE(options_.show_header_only);
+ EXPECT_FALSE(options_.is_remote_mode);
+ EXPECT_FALSE(options_.use_socket);
+}
+
+TEST_F(DumpOptionsTest, InitializeTelephonyBugReport) {
+ // clang-format off
+ char* argv[] = {
+ const_cast<char*>("bugreport"),
+ const_cast<char*>("-d"),
+ const_cast<char*>("-p"),
+ const_cast<char*>("-B"),
+ const_cast<char*>("-z"),
+ };
+ // clang-format on
+
+ property_set("dumpstate.options", "bugreporttelephony");
+
+ Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
+
+ EXPECT_EQ(status, Dumpstate::RunStatus::OK);
+ EXPECT_TRUE(options_.do_add_date);
+ EXPECT_TRUE(options_.do_fb);
+ EXPECT_TRUE(options_.do_broadcast);
+ EXPECT_TRUE(options_.do_zip_file);
+ EXPECT_TRUE(options_.telephony_only);
+
+ // Other options retain default values
+ EXPECT_TRUE(options_.do_vibrate);
+ EXPECT_FALSE(options_.use_control_socket);
+ EXPECT_FALSE(options_.show_header_only);
+ EXPECT_FALSE(options_.do_progress_updates);
+ EXPECT_FALSE(options_.is_remote_mode);
+ EXPECT_FALSE(options_.use_socket);
+}
+
+TEST_F(DumpOptionsTest, InitializeWifiBugReport) {
+ // clang-format off
+ char* argv[] = {
+ const_cast<char*>("bugreport"),
+ const_cast<char*>("-d"),
+ const_cast<char*>("-p"),
+ const_cast<char*>("-B"),
+ const_cast<char*>("-z"),
+ };
+ // clang-format on
+
+ property_set("dumpstate.options", "bugreportwifi");
+
+ Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
+
+ EXPECT_EQ(status, Dumpstate::RunStatus::OK);
+ EXPECT_TRUE(options_.do_add_date);
+ EXPECT_TRUE(options_.do_fb);
+ EXPECT_TRUE(options_.do_broadcast);
+ EXPECT_TRUE(options_.do_zip_file);
+ EXPECT_TRUE(options_.wifi_only);
+
+ // Other options retain default values
+ EXPECT_TRUE(options_.do_vibrate);
+ EXPECT_FALSE(options_.use_control_socket);
+ EXPECT_FALSE(options_.show_header_only);
+ EXPECT_FALSE(options_.do_progress_updates);
+ EXPECT_FALSE(options_.is_remote_mode);
+ EXPECT_FALSE(options_.use_socket);
+}
+
+TEST_F(DumpOptionsTest, InitializeDefaultBugReport) {
+ // default: commandline options are not overridden
+ // clang-format off
+ char* argv[] = {
+ const_cast<char*>("bugreport"),
+ const_cast<char*>("-d"),
+ const_cast<char*>("-p"),
+ const_cast<char*>("-B"),
+ const_cast<char*>("-z"),
+ };
+ // clang-format on
+
+ property_set("dumpstate.options", "");
+
+ Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
+
+ EXPECT_EQ(status, Dumpstate::RunStatus::OK);
+ EXPECT_TRUE(options_.do_add_date);
+ EXPECT_TRUE(options_.do_fb);
+ EXPECT_TRUE(options_.do_zip_file);
+ EXPECT_TRUE(options_.do_broadcast);
+
+ // Other options retain default values
+ EXPECT_TRUE(options_.do_vibrate);
+ EXPECT_FALSE(options_.use_control_socket);
+ EXPECT_FALSE(options_.show_header_only);
+ EXPECT_FALSE(options_.do_progress_updates);
+ EXPECT_FALSE(options_.is_remote_mode);
+ EXPECT_FALSE(options_.use_socket);
+ EXPECT_FALSE(options_.wifi_only);
+}
+
TEST_F(DumpOptionsTest, InitializePartial1) {
// 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"),
@@ -191,7 +468,6 @@
EXPECT_TRUE(options_.do_add_date);
EXPECT_TRUE(options_.do_zip_file);
// TODO: Maybe we should trim the filename
- EXPECT_EQ(" abc", std::string(options_.use_outfile));
EXPECT_TRUE(options_.use_socket);
EXPECT_TRUE(options_.use_control_socket);
@@ -230,7 +506,6 @@
// Other options retain default values
EXPECT_FALSE(options_.do_add_date);
EXPECT_FALSE(options_.do_zip_file);
- EXPECT_EQ("", options_.use_outfile);
EXPECT_FALSE(options_.use_socket);
EXPECT_FALSE(options_.use_control_socket);
}
@@ -265,15 +540,21 @@
TEST_F(DumpOptionsTest, ValidateOptionsNeedOutfile1) {
options_.do_zip_file = true;
+ // Writing to socket = !writing to file.
+ options_.use_socket = true;
EXPECT_FALSE(options_.ValidateOptions());
- options_.use_outfile = "a/b/c";
+
+ options_.use_socket = false;
EXPECT_TRUE(options_.ValidateOptions());
}
TEST_F(DumpOptionsTest, ValidateOptionsNeedOutfile2) {
options_.do_broadcast = true;
+ // Writing to socket = !writing to file.
+ options_.use_socket = true;
EXPECT_FALSE(options_.ValidateOptions());
- options_.use_outfile = "a/b/c";
+
+ options_.use_socket = false;
EXPECT_TRUE(options_.ValidateOptions());
}
@@ -282,13 +563,11 @@
EXPECT_FALSE(options_.ValidateOptions());
options_.do_zip_file = true;
- options_.use_outfile = "a/b/c"; // do_zip_file needs outfile
EXPECT_TRUE(options_.ValidateOptions());
}
TEST_F(DumpOptionsTest, ValidateOptionsUpdateProgressNeedsBroadcast) {
options_.do_progress_updates = true;
- options_.use_outfile = "a/b/c"; // do_progress_updates needs outfile
EXPECT_FALSE(options_.ValidateOptions());
options_.do_broadcast = true;
@@ -302,7 +581,6 @@
options_.do_broadcast = true;
options_.do_zip_file = true;
options_.do_add_date = true;
- options_.use_outfile = "a/b/c"; // do_broadcast needs outfile
EXPECT_TRUE(options_.ValidateOptions());
}
@@ -359,8 +637,9 @@
}
if (update_progress) {
- message += android::base::StringPrintf("Setting progress (%s): %d/%d\n",
- listener_name.c_str(), progress, max);
+ message += android::base::StringPrintf("Setting progress (%s): %d/%d (%d%%)\n",
+ listener_name.c_str(), progress, max,
+ (100 * progress / max));
}
return message;
@@ -519,12 +798,14 @@
SetProgress(0, 30);
EXPECT_CALL(*listener, onProgressUpdated(20));
+ EXPECT_CALL(*listener, onProgress(66)); // 20/30 %
EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build()));
std::string progress_message = GetProgressMessage(ds.listener_name_, 20, 30);
EXPECT_THAT(out, StrEq("stdout\n"));
EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
EXPECT_CALL(*listener, onProgressUpdated(30));
+ EXPECT_CALL(*listener, onProgress(100)); // 35/35 %
EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Build()));
progress_message = GetProgressMessage(ds.listener_name_, 30, 30);
EXPECT_THAT(out, StrEq("stdout\n"));
@@ -533,6 +814,7 @@
// Run a command that will increase maximum timeout.
EXPECT_CALL(*listener, onProgressUpdated(31));
EXPECT_CALL(*listener, onMaxProgressUpdated(37));
+ EXPECT_CALL(*listener, onProgress(83)); // 31/37 %
EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
progress_message = GetProgressMessage(ds.listener_name_, 31, 37, 30); // 20% increase
EXPECT_THAT(out, StrEq("stdout\n"));
@@ -541,6 +823,7 @@
// Make sure command ran while in dry_run is counted.
SetDryRun(true);
EXPECT_CALL(*listener, onProgressUpdated(35));
+ EXPECT_CALL(*listener, onProgress(94)); // 35/37 %
EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
progress_message = GetProgressMessage(ds.listener_name_, 35, 37);
EXPECT_THAT(out, IsEmpty());
@@ -557,6 +840,7 @@
// First update should always be sent.
EXPECT_CALL(*listener, onProgressUpdated(1));
+ EXPECT_CALL(*listener, onProgress(12)); // 1/12 %
EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
std::string progress_message = GetProgressMessage(ds.listener_name_, 1, 8);
EXPECT_THAT(out, StrEq("stdout\n"));
@@ -569,6 +853,7 @@
// Third update should be sent because it reaches threshold (6 - 1 = 5).
EXPECT_CALL(*listener, onProgressUpdated(6));
+ EXPECT_CALL(*listener, onProgress(75)); // 6/8 %
EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
progress_message = GetProgressMessage(ds.listener_name_, 6, 8);
EXPECT_THAT(out, StrEq("stdout\n"));
@@ -650,6 +935,32 @@
EXPECT_THAT(err, StrEq("stderr\n"));
}
+TEST_F(DumpstateTest, RunCommandAsRootNonUserBuild_withUnroot) {
+ if (!IsStandalone()) {
+ // TODO: temporarily disabled because it might cause other tests to fail after dropping
+ // to Shell - need to refactor tests to avoid this problem)
+ MYLOGE(
+ "Skipping DumpstateTest.RunCommandAsRootNonUserBuild_withUnroot() "
+ "on test suite\n")
+ return;
+ }
+ if (PropertiesHelper::IsUserBuild()) {
+ ALOGI("Skipping RunCommandAsRootNonUserBuild_withUnroot on user builds\n");
+ return;
+ }
+
+ // Same test as above, but with unroot property set, which will override su availability.
+ SetUnroot(true);
+ DropRoot();
+
+ EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
+ CommandOptions::WithTimeout(1).AsRoot().Build()));
+
+ // AsRoot is ineffective.
+ EXPECT_THAT(out, StrEq("2000\nstdout\n"));
+ EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
+}
+
TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnUserBuild) {
if (!IsStandalone()) {
// TODO: temporarily disabled because it might cause other tests to fail after dropping
@@ -692,6 +1003,32 @@
EXPECT_THAT(err, StrEq("stderr\n"));
}
+TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnDebugBuild_withUnroot) {
+ if (!IsStandalone()) {
+ // TODO: temporarily disabled because it might cause other tests to fail after dropping
+ // to Shell - need to refactor tests to avoid this problem)
+ MYLOGE(
+ "Skipping DumpstateTest.RunCommandAsRootIfAvailableOnDebugBuild_withUnroot() "
+ "on test suite\n")
+ return;
+ }
+ if (PropertiesHelper::IsUserBuild()) {
+ ALOGI("Skipping RunCommandAsRootIfAvailableOnDebugBuild_withUnroot on user builds\n");
+ return;
+ }
+ // Same test as above, but with unroot property set, which will override su availability.
+ SetUnroot(true);
+
+ DropRoot();
+
+ EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
+ CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
+
+ // It's a userdebug build, so "su root" should be available, but unroot=true overrides it.
+ EXPECT_THAT(out, StrEq("2000\nstdout\n"));
+ EXPECT_THAT(err, StrEq("stderr\n"));
+}
+
TEST_F(DumpstateTest, DumpFileNotFoundNoTitle) {
EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
EXPECT_THAT(out,
@@ -756,6 +1093,7 @@
SetProgress(0, 30);
EXPECT_CALL(*listener, onProgressUpdated(5));
+ EXPECT_CALL(*listener, onProgress(16)); // 5/30 %
EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
std::string progress_message =
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 4ad5c4b..528e43d 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -82,8 +82,12 @@
CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
+// TODO(111441001): Default DumpOptions to sensible values.
Dumpstate::Dumpstate(const std::string& version)
- : pid_(getpid()), version_(version), now_(time(nullptr)) {
+ : pid_(getpid()),
+ options_(new Dumpstate::DumpOptions()),
+ version_(version),
+ now_(time(nullptr)) {
}
Dumpstate& Dumpstate::GetInstance() {
@@ -225,7 +229,11 @@
}
std::string Dumpstate::GetPath(const std::string& suffix) const {
- return android::base::StringPrintf("%s/%s-%s%s", bugreport_dir_.c_str(), base_name_.c_str(),
+ return GetPath(bugreport_internal_dir_, suffix);
+}
+
+std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
+ return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
name_.c_str(), suffix.c_str());
}
@@ -863,7 +871,11 @@
is_java_process ? 5 : 20, fd);
if (ret == -1) {
- dprintf(fd, "dumping failed, likely due to a timeout\n");
+ // For consistency, the header and footer to this message match those
+ // dumped by debuggerd in the success case.
+ dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
+ dprintf(fd, "Dump failed, likely due to a timeout.\n");
+ dprintf(fd, "---- end %d ----", pid);
timeout_failures++;
continue;
}
@@ -937,16 +949,22 @@
fsync(control_socket_fd_);
}
+ int percent = 100 * progress / max;
if (listener_ != nullptr) {
- if (progress % 100 == 0) {
- // We don't want to spam logcat, so only log multiples of 100.
- MYLOGD("Setting progress (%s): %d/%d\n", listener_name_.c_str(), progress, max);
+ if (percent % 5 == 0) {
+ // We don't want to spam logcat, so only log multiples of 5.
+ MYLOGD("Setting progress (%s): %d/%d (%d%%)\n", listener_name_.c_str(), progress, max,
+ percent);
} else {
// stderr is ignored on normal invocations, but useful when calling
// /system/bin/dumpstate directly for debuggging.
- fprintf(stderr, "Setting progress (%s): %d/%d\n", listener_name_.c_str(), progress, max);
+ fprintf(stderr, "Setting progress (%s): %d/%d (%d%%)\n", listener_name_.c_str(),
+ progress, max, percent);
}
+ // TODO(b/111441001): Remove in favor of onProgress
listener_->onProgressUpdated(progress);
+
+ listener_->onProgress(percent);
}
}
diff --git a/cmds/dumpsys/Android.bp b/cmds/dumpsys/Android.bp
index f68b862..f99588f 100644
--- a/cmds/dumpsys/Android.bp
+++ b/cmds/dumpsys/Android.bp
@@ -20,8 +20,6 @@
static_libs: [
"libserviceutils",
],
-
- clang: true,
}
//
@@ -36,7 +34,6 @@
export_include_dirs: ["."],
}
-
//
// Executable
//
@@ -51,4 +48,15 @@
],
}
-subdirs = ["tests"]
+cc_binary {
+ name: "dumpsys_vendor",
+ stem: "dumpsys",
+
+ vendor: true,
+
+ defaults: ["dumpsys_defaults"],
+
+ srcs: [
+ "main.cpp",
+ ],
+}
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index 5412d4d..8fbea8a 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -389,7 +389,7 @@
auto time_left_ms = [end]() {
auto now = std::chrono::steady_clock::now();
auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
- return std::max(diff.count(), 0ll);
+ return std::max(diff.count(), 0LL);
};
int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
diff --git a/cmds/dumpsys/dumpsys.h b/cmds/dumpsys/dumpsys.h
index 84f3b02..c48a1e9 100644
--- a/cmds/dumpsys/dumpsys.h
+++ b/cmds/dumpsys/dumpsys.h
@@ -26,7 +26,7 @@
class Dumpsys {
public:
- Dumpsys(android::IServiceManager* sm) : sm_(sm) {
+ explicit Dumpsys(android::IServiceManager* sm) : sm_(sm) {
}
/**
* Main entry point into dumpsys.
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index 9d0d8ba..65743d9 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -14,9 +14,11 @@
"CacheItem.cpp",
"CacheTracker.cpp",
"InstalldNativeService.cpp",
+ "QuotaUtils.cpp",
"dexopt.cpp",
"globals.cpp",
"utils.cpp",
+ "view_compiler.cpp",
":installd_aidl",
],
header_libs: [
@@ -29,10 +31,26 @@
"libcutils",
"liblog",
"liblogwrap",
+ "libprocessgroup",
"libselinux",
"libutils",
],
+ product_variables: {
+ arc: {
+ exclude_srcs: [
+ "QuotaUtils.cpp",
+ ],
+ static_libs: [
+ "libarcdiskquota",
+ "arc_services_aidl",
+ ],
+ cflags: [
+ "-DUSE_ARC",
+ ],
+ },
+ },
+
clang: true,
tidy: true,
@@ -59,6 +77,26 @@
aidl: {
export_aidl_headers: true,
},
+
+ product_variables: {
+ arc: {
+ exclude_srcs: [
+ "QuotaUtils.cpp",
+ ],
+ static_libs: [
+ "libarcdiskquota",
+ "arc_services_aidl",
+ ],
+ cflags: [
+ "-DUSE_ARC",
+ ],
+ },
+ },
+}
+
+cc_library_headers {
+ name: "libinstalld_headers",
+ export_include_dirs: ["."],
}
//
@@ -73,6 +111,21 @@
static_libs: ["libdiskusage"],
init_rc: ["installd.rc"],
+
+ product_variables: {
+ arc: {
+ exclude_srcs: [
+ "QuotaUtils.cpp",
+ ],
+ static_libs: [
+ "libarcdiskquota",
+ "arc_services_aidl",
+ ],
+ cflags: [
+ "-DUSE_ARC",
+ ],
+ },
+ },
}
// OTA chroot tool
@@ -85,10 +138,23 @@
],
clang: true,
- srcs: ["otapreopt_chroot.cpp"],
+ srcs: [
+ "otapreopt_chroot.cpp",
+ "otapreopt_utils.cpp",
+ ],
shared_libs: [
"libbase",
"liblog",
+ "libprotobuf-cpp-full",
+ "libselinux",
+ "libziparchive",
+ ],
+ static_libs: [
+ "libapex",
+ "libapexd",
+ "lib_apex_manifest_proto",
+ "libavb",
+ "libdm",
],
}
@@ -117,6 +183,7 @@
"libbase",
"libcutils",
"liblog",
+ "libprocessgroup",
"libutils",
],
}
@@ -136,7 +203,9 @@
"dexopt.cpp",
"globals.cpp",
"otapreopt.cpp",
+ "otapreopt_utils.cpp",
"utils.cpp",
+ "view_compiler.cpp",
],
header_libs: ["dex2oat_headers"],
@@ -153,7 +222,28 @@
"libcutils",
"liblog",
"liblogwrap",
+ "libprocessgroup",
"libselinux",
"libutils",
],
}
+
+// OTA slot script
+cc_prebuilt_binary {
+ name: "otapreopt_slot",
+ srcs: ["otapreopt_slot.sh"],
+ init_rc: ["otapreopt.rc"],
+}
+
+// OTA postinstall script
+cc_prebuilt_binary {
+ name: "otapreopt_script",
+ srcs: ["otapreopt_script.sh"],
+ // Let this depend on otapreopt, the chroot tool and the slot script,
+ // so we just have to mention one in a configuration.
+ required: [
+ "otapreopt",
+ "otapreopt_chroot",
+ "otapreopt_slot",
+ ],
+}
diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk
deleted file mode 100644
index 30de0b3..0000000
--- a/cmds/installd/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-# OTA slot script
-
-include $(CLEAR_VARS)
-LOCAL_MODULE:= otapreopt_slot
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_SRC_FILES := otapreopt_slot.sh
-LOCAL_INIT_RC := otapreopt.rc
-
-include $(BUILD_PREBUILT)
-
-# OTA postinstall script
-
-include $(CLEAR_VARS)
-LOCAL_MODULE:= otapreopt_script
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_SRC_FILES := otapreopt_script.sh
-
-# Let this depend on otapreopt, the chroot tool and the slot script, so we just have to mention one
-# in a configuration.
-LOCAL_REQUIRED_MODULES := otapreopt otapreopt_chroot otapreopt_slot
-
-include $(BUILD_PREBUILT)
diff --git a/cmds/installd/CacheTracker.cpp b/cmds/installd/CacheTracker.cpp
index a7242c3..8b868fb 100644
--- a/cmds/installd/CacheTracker.cpp
+++ b/cmds/installd/CacheTracker.cpp
@@ -19,13 +19,13 @@
#include "CacheTracker.h"
#include <fts.h>
-#include <sys/quota.h>
#include <sys/xattr.h>
#include <utils/Trace.h>
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
+#include "QuotaUtils.h"
#include "utils.h"
using android::base::StringPrintf;
@@ -33,9 +33,13 @@
namespace android {
namespace installd {
-CacheTracker::CacheTracker(userid_t userId, appid_t appId, const std::string& quotaDevice) :
- cacheUsed(0), cacheQuota(0), mUserId(userId), mAppId(appId), mQuotaDevice(quotaDevice),
- mItemsLoaded(false) {
+CacheTracker::CacheTracker(userid_t userId, appid_t appId, const std::string& uuid)
+ : cacheUsed(0),
+ cacheQuota(0),
+ mUserId(userId),
+ mAppId(appId),
+ mItemsLoaded(false),
+ mUuid(uuid) {
}
CacheTracker::~CacheTracker() {
@@ -72,26 +76,18 @@
bool CacheTracker::loadQuotaStats() {
int cacheGid = multiuser_get_cache_gid(mUserId, mAppId);
int extCacheGid = multiuser_get_ext_cache_gid(mUserId, mAppId);
- if (!mQuotaDevice.empty() && cacheGid != -1 && extCacheGid != -1) {
- struct dqblk dq;
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), cacheGid,
- reinterpret_cast<char*>(&dq)) != 0) {
- if (errno != ESRCH) {
- PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid;
- }
- return false;
+ if (IsQuotaSupported(mUuid) && cacheGid != -1 && extCacheGid != -1) {
+ int64_t space;
+ if ((space = GetOccupiedSpaceForGid(mUuid, cacheGid)) != -1) {
+ cacheUsed += space;
} else {
- cacheUsed += dq.dqb_curspace;
+ return false;
}
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), extCacheGid,
- reinterpret_cast<char*>(&dq)) != 0) {
- if (errno != ESRCH) {
- PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid;
- }
- return false;
+ if ((space = GetOccupiedSpaceForGid(mUuid, extCacheGid)) != -1) {
+ cacheUsed += space;
} else {
- cacheUsed += dq.dqb_curspace;
+ return false;
}
return true;
} else {
diff --git a/cmds/installd/CacheTracker.h b/cmds/installd/CacheTracker.h
index 44359b4..b0527e7 100644
--- a/cmds/installd/CacheTracker.h
+++ b/cmds/installd/CacheTracker.h
@@ -39,7 +39,7 @@
*/
class CacheTracker {
public:
- CacheTracker(userid_t userId, appid_t appId, const std::string& quotaDevice);
+ CacheTracker(userid_t userId, appid_t appId, const std::string& uuid);
~CacheTracker();
std::string toString();
@@ -61,8 +61,8 @@
private:
userid_t mUserId;
appid_t mAppId;
- std::string mQuotaDevice;
bool mItemsLoaded;
+ const std::string& mUuid;
std::vector<std::string> mDataPaths;
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 28ffdf1..ccffd29 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -31,7 +31,6 @@
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
-#include <sys/quota.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
@@ -42,6 +41,7 @@
#include <android-base/logging.h>
#include <android-base/properties.h>
+#include <android-base/scopeguard.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
@@ -61,9 +61,11 @@
#include "installd_deps.h"
#include "otapreopt_utils.h"
#include "utils.h"
+#include "view_compiler.h"
#include "CacheTracker.h"
#include "MatchExtensionGen.h"
+#include "QuotaUtils.h"
#ifndef LOG_TAG
#define LOG_TAG "installd"
@@ -75,6 +77,9 @@
namespace android {
namespace installd {
+// An uuid used in unit tests.
+static constexpr const char* kTestUuid = "TEST";
+
static constexpr const char* kCpPath = "/system/bin/cp";
static constexpr const char* kXattrDefault = "user.default";
@@ -162,6 +167,15 @@
}
}
+binder::Status checkArgumentUuidTestOrNull(const std::unique_ptr<std::string>& uuid) {
+ if (!uuid || strcmp(uuid->c_str(), kTestUuid) == 0) {
+ return ok();
+ } else {
+ return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
+ StringPrintf("UUID must be null or \"%s\", got: %s", kTestUuid, uuid->c_str()));
+ }
+}
+
binder::Status checkArgumentPackageName(const std::string& packageName) {
if (is_valid_package_name(packageName.c_str())) {
return ok();
@@ -214,6 +228,13 @@
} \
}
+#define CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(uuid) { \
+ auto status = checkArgumentUuidTestOrNull(uuid); \
+ if (!status.isOk()) { \
+ return status; \
+ } \
+} \
+
#define CHECK_ARGUMENT_PACKAGE_NAME(packageName) { \
binder::Status status = \
checkArgumentPackageName((packageName)); \
@@ -266,11 +287,6 @@
for (const auto& n : mStorageMounts) {
out << " " << n.first << " = " << n.second << endl;
}
-
- out << endl << "Quota reverse mounts:" << endl;
- for (const auto& n : mQuotaReverseMounts) {
- out << " " << n.first << " = " << n.second << endl;
- }
}
{
@@ -750,6 +766,233 @@
return ok();
}
+static int32_t copy_directory_recursive(const char* from, const char* to) {
+ char *argv[] = {
+ (char*) kCpPath,
+ (char*) "-F", /* delete any existing destination file first (--remove-destination) */
+ (char*) "-p", /* preserve timestamps, ownership, and permissions */
+ (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */
+ (char*) "-P", /* Do not follow symlinks [default] */
+ (char*) "-d", /* don't dereference symlinks */
+ (char*) from,
+ (char*) to
+ };
+
+ LOG(DEBUG) << "Copying " << from << " to " << to;
+ return android_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, true);
+}
+
+binder::Status InstalldNativeService::snapshotAppData(
+ const std::unique_ptr<std::string>& volumeUuid,
+ const std::string& packageName, int32_t user, int32_t storageFlags,
+ int64_t* _aidl_return) {
+ ENFORCE_UID(AID_SYSTEM);
+ CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid);
+ CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
+
+ const char* volume_uuid = volumeUuid ? volumeUuid->c_str() : nullptr;
+ const char* package_name = packageName.c_str();
+
+ binder::Status res = ok();
+ // Default result to 0, it will be populated with inode of ce data snapshot
+ // if FLAG_STORAGE_CE has been passed.
+ if (_aidl_return != nullptr) *_aidl_return = 0;
+
+ bool clear_ce_on_exit = false;
+ bool clear_de_on_exit = false;
+
+ auto deleter = [&clear_ce_on_exit, &clear_de_on_exit, &volume_uuid, &user, &package_name] {
+ if (clear_de_on_exit) {
+ auto to = create_data_misc_de_rollback_package_path(volume_uuid, user, package_name);
+ if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) {
+ LOG(WARNING) << "Failed to delete app data snapshot: " << to;
+ }
+ }
+
+ if (clear_ce_on_exit) {
+ auto to = create_data_misc_ce_rollback_package_path(volume_uuid, user, package_name);
+ if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) {
+ LOG(WARNING) << "Failed to delete app data snapshot: " << to;
+ }
+ }
+ };
+
+ auto scope_guard = android::base::make_scope_guard(deleter);
+
+ // The app may not have any data at all, in which case it's OK to skip here.
+ auto from_ce = create_data_user_ce_package_path(volume_uuid, user, package_name);
+ if (access(from_ce.c_str(), F_OK) != 0) {
+ LOG(INFO) << "Missing source " << from_ce;
+ return ok();
+ }
+
+ // ce_data_inode is not needed when FLAG_CLEAR_CACHE_ONLY is set.
+ binder::Status clear_cache_result = clearAppData(volumeUuid, packageName, user,
+ storageFlags | FLAG_CLEAR_CACHE_ONLY, 0);
+ if (!clear_cache_result.isOk()) {
+ // It should be fine to continue snapshot if we for some reason failed
+ // to clear cache.
+ LOG(WARNING) << "Failed to clear cache of app " << packageName;
+ }
+
+ // ce_data_inode is not needed when FLAG_CLEAR_CODE_CACHE_ONLY is set.
+ binder::Status clear_code_cache_result = clearAppData(volumeUuid, packageName, user,
+ storageFlags | FLAG_CLEAR_CODE_CACHE_ONLY, 0);
+ if (!clear_code_cache_result.isOk()) {
+ // It should be fine to continue snapshot if we for some reason failed
+ // to clear code_cache.
+ LOG(WARNING) << "Failed to clear code_cache of app " << packageName;
+ }
+
+ if (storageFlags & FLAG_STORAGE_DE) {
+ auto from = create_data_user_de_package_path(volume_uuid, user, package_name);
+ auto to = create_data_misc_de_rollback_path(volume_uuid, user);
+
+ int rd = delete_dir_contents(to, true /* ignore_if_missing */);
+ if (rd != 0) {
+ res = error(rd, "Failed clearing existing snapshot " + to);
+ return res;
+ }
+
+ int rc = copy_directory_recursive(from.c_str(), to.c_str());
+ if (rc != 0) {
+ res = error(rc, "Failed copying " + from + " to " + to);
+ clear_de_on_exit = true;
+ return res;
+ }
+ }
+
+ if (storageFlags & FLAG_STORAGE_CE) {
+ auto from = create_data_user_ce_package_path(volume_uuid, user, package_name);
+ auto to = create_data_misc_ce_rollback_path(volume_uuid, user);
+
+ int rd = delete_dir_contents(to, true /* ignore_if_missing */);
+ if (rd != 0) {
+ res = error(rd, "Failed clearing existing snapshot " + to);
+ return res;
+ }
+
+ int rc = copy_directory_recursive(from.c_str(), to.c_str());
+ if (rc != 0) {
+ res = error(rc, "Failed copying " + from + " to " + to);
+ clear_ce_on_exit = true;
+ return res;
+ }
+ if (_aidl_return != nullptr) {
+ auto ce_snapshot_path = create_data_misc_ce_rollback_package_path(volume_uuid, user,
+ package_name);
+ rc = get_path_inode(ce_snapshot_path, reinterpret_cast<ino_t*>(_aidl_return));
+ if (rc != 0) {
+ res = error(rc, "Failed to get_path_inode for " + ce_snapshot_path);
+ clear_ce_on_exit = true;
+ return res;
+ }
+ }
+ }
+
+ return res;
+}
+
+binder::Status InstalldNativeService::restoreAppDataSnapshot(
+ const std::unique_ptr<std::string>& volumeUuid, const std::string& packageName,
+ const int32_t appId, const int64_t ceDataInode, const std::string& seInfo,
+ const int32_t user, int32_t storageFlags) {
+ ENFORCE_UID(AID_SYSTEM);
+ CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid);
+ CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
+
+ const char* volume_uuid = volumeUuid ? volumeUuid->c_str() : nullptr;
+ const char* package_name = packageName.c_str();
+
+ auto from_ce = create_data_misc_ce_rollback_package_path(volume_uuid,
+ user, package_name);
+ auto from_de = create_data_misc_de_rollback_package_path(volume_uuid,
+ user, package_name);
+
+ const bool needs_ce_rollback = (storageFlags & FLAG_STORAGE_CE) &&
+ (access(from_ce.c_str(), F_OK) == 0);
+ const bool needs_de_rollback = (storageFlags & FLAG_STORAGE_DE) &&
+ (access(from_de.c_str(), F_OK) == 0);
+
+ if (!needs_ce_rollback && !needs_de_rollback) {
+ return ok();
+ }
+
+ // We know we're going to rollback one of the CE or DE data, so we clear
+ // application data first. Note that it's possible that we're asked to
+ // restore both CE & DE data but that one of the restores fail. Leaving the
+ // app with no data in those cases is arguably better than leaving the app
+ // with mismatched / stale data.
+ LOG(INFO) << "Clearing app data for " << packageName << " to restore snapshot.";
+ binder::Status res = clearAppData(volumeUuid, packageName, user, storageFlags, ceDataInode);
+ if (!res.isOk()) {
+ return res;
+ }
+
+ if (needs_ce_rollback) {
+ auto to_ce = create_data_user_ce_path(volume_uuid, user);
+ int rc = copy_directory_recursive(from_ce.c_str(), to_ce.c_str());
+ if (rc != 0) {
+ res = error(rc, "Failed copying " + from_ce + " to " + to_ce);
+ return res;
+ }
+ }
+
+ if (needs_de_rollback) {
+ auto to_de = create_data_user_de_path(volume_uuid, user);
+ int rc = copy_directory_recursive(from_de.c_str(), to_de.c_str());
+ if (rc != 0) {
+ if (needs_ce_rollback) {
+ auto ce_data = create_data_user_ce_package_path(volume_uuid, user, package_name);
+ LOG(WARNING) << "de_data rollback failed. Erasing rolled back ce_data " << ce_data;
+ if (delete_dir_contents(ce_data.c_str(), 1, nullptr) != 0) {
+ LOG(WARNING) << "Failed to delete rolled back ce_data " << ce_data;
+ }
+ }
+ res = error(rc, "Failed copying " + from_de + " to " + to_de);
+ return res;
+ }
+ }
+
+ // Finally, restore the SELinux label on the app data.
+ return restoreconAppData(volumeUuid, packageName, user, storageFlags, appId, seInfo);
+}
+
+binder::Status InstalldNativeService::destroyAppDataSnapshot(
+ const std::unique_ptr<std::string> &volumeUuid, const std::string& packageName,
+ const int32_t user, const int64_t ceSnapshotInode, int32_t storageFlags) {
+ ENFORCE_UID(AID_SYSTEM);
+ CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid);
+ CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
+
+ const char* volume_uuid = volumeUuid ? volumeUuid->c_str() : nullptr;
+ const char* package_name = packageName.c_str();
+
+ if (storageFlags & FLAG_STORAGE_DE) {
+ auto de_snapshot_path = create_data_misc_de_rollback_package_path(volume_uuid,
+ user, package_name);
+
+ int res = delete_dir_contents_and_dir(de_snapshot_path, true /* ignore_if_missing */);
+ if (res != 0) {
+ return error(res, "Failed clearing snapshot " + de_snapshot_path);
+ }
+ }
+
+ if (storageFlags & FLAG_STORAGE_CE) {
+ auto ce_snapshot_path = create_data_misc_ce_rollback_package_path(volume_uuid,
+ user, package_name, ceSnapshotInode);
+ int res = delete_dir_contents_and_dir(ce_snapshot_path, true /* ignore_if_missing */);
+ if (res != 0) {
+ return error(res, "Failed clearing snapshot " + ce_snapshot_path);
+ }
+ }
+ return ok();
+}
+
+
binder::Status InstalldNativeService::moveCompleteApp(const std::unique_ptr<std::string>& fromUuid,
const std::unique_ptr<std::string>& toUuid, const std::string& packageName,
const std::string& dataAppName, int32_t appId, const std::string& seInfo,
@@ -774,19 +1017,7 @@
auto to = create_data_app_package_path(to_uuid, data_app_name);
auto to_parent = create_data_app_path(to_uuid);
- char *argv[] = {
- (char*) kCpPath,
- (char*) "-F", /* delete any existing destination file first (--remove-destination) */
- (char*) "-p", /* preserve timestamps, ownership, and permissions */
- (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */
- (char*) "-P", /* Do not follow symlinks [default] */
- (char*) "-d", /* don't dereference symlinks */
- (char*) from.c_str(),
- (char*) to_parent.c_str()
- };
-
- LOG(DEBUG) << "Copying " << from << " to " << to;
- int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, true);
+ int rc = copy_directory_recursive(from.c_str(), to_parent.c_str());
if (rc != 0) {
res = error(rc, "Failed copying " + from + " to " + to);
goto fail;
@@ -814,25 +1045,11 @@
goto fail;
}
- char *argv[] = {
- (char*) kCpPath,
- (char*) "-F", /* delete any existing destination file first (--remove-destination) */
- (char*) "-p", /* preserve timestamps, ownership, and permissions */
- (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */
- (char*) "-P", /* Do not follow symlinks [default] */
- (char*) "-d", /* don't dereference symlinks */
- nullptr,
- nullptr
- };
-
{
auto from = create_data_user_de_package_path(from_uuid, user, package_name);
auto to = create_data_user_de_path(to_uuid, user);
- argv[6] = (char*) from.c_str();
- argv[7] = (char*) to.c_str();
- LOG(DEBUG) << "Copying " << from << " to " << to;
- int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, true);
+ int rc = copy_directory_recursive(from.c_str(), to.c_str());
if (rc != 0) {
res = error(rc, "Failed copying " + from + " to " + to);
goto fail;
@@ -841,11 +1058,8 @@
{
auto from = create_data_user_ce_package_path(from_uuid, user, package_name);
auto to = create_data_user_ce_path(to_uuid, user);
- argv[6] = (char*) from.c_str();
- argv[7] = (char*) to.c_str();
- LOG(DEBUG) << "Copying " << from << " to " << to;
- int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, true);
+ int rc = copy_directory_recursive(from.c_str(), to.c_str());
if (rc != 0) {
res = error(rc, "Failed copying " + from + " to " + to);
goto fail;
@@ -950,9 +1164,9 @@
CHECK_ARGUMENT_UUID(uuid);
std::lock_guard<std::recursive_mutex> lock(mLock);
+ auto uuidString = uuid ? *uuid : "";
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
auto data_path = create_data_path(uuid_);
- auto device = findQuotaDeviceForUuid(uuid);
auto noop = (flags & FLAG_FREE_CACHE_NOOP);
int64_t free = data_disk_free(data_path);
@@ -999,7 +1213,7 @@
search->second->addDataPath(p->fts_path);
} else {
auto tracker = std::shared_ptr<CacheTracker>(new CacheTracker(
- multiuser_get_user_id(uid), multiuser_get_app_id(uid), device));
+ multiuser_get_user_id(uid), multiuser_get_app_id(uid), uuidString));
tracker->addDataPath(p->fts_path);
{
std::lock_guard<std::recursive_mutex> lock(mQuotasLock);
@@ -1164,53 +1378,26 @@
}
#endif
-static void collectQuotaStats(const std::string& device, int32_t userId,
+static void collectQuotaStats(const std::string& uuid, int32_t userId,
int32_t appId, struct stats* stats, struct stats* extStats) {
- if (device.empty()) return;
-
- struct dqblk dq;
-
+ int64_t space;
if (stats != nullptr) {
uid_t uid = multiuser_get_uid(userId, appId);
- if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
- reinterpret_cast<char*>(&dq)) != 0) {
- if (errno != ESRCH) {
- PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid;
- }
- } else {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace;
-#endif
- stats->dataSize += dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForUid(uuid, uid)) != -1) {
+ stats->dataSize += space;
}
int cacheGid = multiuser_get_cache_gid(userId, appId);
if (cacheGid != -1) {
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), cacheGid,
- reinterpret_cast<char*>(&dq)) != 0) {
- if (errno != ESRCH) {
- PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << cacheGid;
- }
- } else {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for GID " << cacheGid << " " << dq.dqb_curspace;
-#endif
- stats->cacheSize += dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForGid(uuid, cacheGid)) != -1) {
+ stats->cacheSize += space;
}
}
int sharedGid = multiuser_get_shared_gid(0, appId);
if (sharedGid != -1) {
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), sharedGid,
- reinterpret_cast<char*>(&dq)) != 0) {
- if (errno != ESRCH) {
- PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << sharedGid;
- }
- } else {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for GID " << sharedGid << " " << dq.dqb_curspace;
-#endif
- stats->codeSize += dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForGid(uuid, sharedGid)) != -1) {
+ stats->codeSize += space;
}
}
}
@@ -1218,32 +1405,16 @@
if (extStats != nullptr) {
int extGid = multiuser_get_ext_gid(userId, appId);
if (extGid != -1) {
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), extGid,
- reinterpret_cast<char*>(&dq)) != 0) {
- if (errno != ESRCH) {
- PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << extGid;
- }
- } else {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for GID " << extGid << " " << dq.dqb_curspace;
-#endif
- extStats->dataSize += dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForGid(uuid, extGid)) != -1) {
+ extStats->dataSize += space;
}
}
int extCacheGid = multiuser_get_ext_cache_gid(userId, appId);
if (extCacheGid != -1) {
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), extCacheGid,
- reinterpret_cast<char*>(&dq)) != 0) {
- if (errno != ESRCH) {
- PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << extCacheGid;
- }
- } else {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for GID " << extCacheGid << " " << dq.dqb_curspace;
-#endif
- extStats->dataSize += dq.dqb_curspace;
- extStats->cacheSize += dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForGid(uuid, extCacheGid)) != -1) {
+ extStats->dataSize += space;
+ extStats->cacheSize += space;
}
}
}
@@ -1407,10 +1578,10 @@
memset(&stats, 0, sizeof(stats));
memset(&extStats, 0, sizeof(extStats));
+ auto uuidString = uuid ? *uuid : "";
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
- auto device = findQuotaDeviceForUuid(uuid);
- if (device.empty()) {
+ if (!IsQuotaSupported(uuidString)) {
flags &= ~FLAG_USE_QUOTA;
}
@@ -1430,7 +1601,7 @@
ATRACE_END();
ATRACE_BEGIN("quota");
- collectQuotaStats(device, userId, appId, &stats, &extStats);
+ collectQuotaStats(uuidString, userId, appId, &stats, &extStats);
ATRACE_END();
} else {
ATRACE_BEGIN("code");
@@ -1513,27 +1684,19 @@
memset(&stats, 0, sizeof(stats));
memset(&extStats, 0, sizeof(extStats));
+ auto uuidString = uuid ? *uuid : "";
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
- auto device = findQuotaDeviceForUuid(uuid);
- if (device.empty()) {
+ if (!IsQuotaSupported(uuidString)) {
flags &= ~FLAG_USE_QUOTA;
}
if (flags & FLAG_USE_QUOTA) {
- struct dqblk dq;
+ int64_t space;
ATRACE_BEGIN("obb");
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), AID_MEDIA_OBB,
- reinterpret_cast<char*>(&dq)) != 0) {
- if (errno != ESRCH) {
- PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << AID_MEDIA_OBB;
- }
- } else {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for GID " << AID_MEDIA_OBB << " " << dq.dqb_curspace;
-#endif
- extStats.codeSize += dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForGid(uuidString, AID_MEDIA_OBB)) != -1) {
+ extStats.codeSize += space;
}
ATRACE_END();
@@ -1559,16 +1722,8 @@
ATRACE_BEGIN("external");
uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW);
- if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
- reinterpret_cast<char*>(&dq)) != 0) {
- if (errno != ESRCH) {
- PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid;
- }
- } else {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace;
-#endif
- extStats.dataSize += dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForUid(uuidString, uid)) != -1) {
+ extStats.dataSize += space;
}
ATRACE_END();
@@ -1585,7 +1740,7 @@
int64_t dataSize = extStats.dataSize;
for (auto appId : appIds) {
if (appId >= AID_APP_START) {
- collectQuotaStats(device, userId, appId, &stats, &extStats);
+ collectQuotaStats(uuidString, userId, appId, &stats, &extStats);
#if MEASURE_DEBUG
// Sleep to make sure we don't lose logs
@@ -1667,6 +1822,7 @@
LOG(INFO) << "Measuring external " << userId;
#endif
+ auto uuidString = uuid ? *uuid : "";
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
int64_t totalSize = 0;
@@ -1676,58 +1832,33 @@
int64_t appSize = 0;
int64_t obbSize = 0;
- auto device = findQuotaDeviceForUuid(uuid);
- if (device.empty()) {
+ if (!IsQuotaSupported(uuidString)) {
flags &= ~FLAG_USE_QUOTA;
}
if (flags & FLAG_USE_QUOTA) {
- struct dqblk dq;
+ int64_t space;
ATRACE_BEGIN("quota");
uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW);
- if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
- reinterpret_cast<char*>(&dq)) != 0) {
- if (errno != ESRCH) {
- PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid;
- }
- } else {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace;
-#endif
- totalSize = dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForUid(uuidString, uid)) != -1) {
+ totalSize = space;
}
gid_t audioGid = multiuser_get_uid(userId, AID_MEDIA_AUDIO);
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), audioGid,
- reinterpret_cast<char*>(&dq)) == 0) {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for GID " << audioGid << " " << dq.dqb_curspace;
-#endif
- audioSize = dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForGid(uuidString, audioGid)) != -1) {
+ audioSize = space;
}
gid_t videoGid = multiuser_get_uid(userId, AID_MEDIA_VIDEO);
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), videoGid,
- reinterpret_cast<char*>(&dq)) == 0) {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for GID " << videoGid << " " << dq.dqb_curspace;
-#endif
- videoSize = dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForGid(uuidString, videoGid)) != -1) {
+ videoSize = space;
}
gid_t imageGid = multiuser_get_uid(userId, AID_MEDIA_IMAGE);
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), imageGid,
- reinterpret_cast<char*>(&dq)) == 0) {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for GID " << imageGid << " " << dq.dqb_curspace;
-#endif
- imageSize = dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForGid(uuidString, imageGid)) != -1) {
+ imageSize = space;
}
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), AID_MEDIA_OBB,
- reinterpret_cast<char*>(&dq)) == 0) {
-#if MEASURE_DEBUG
- LOG(DEBUG) << "quotactl() for GID " << AID_MEDIA_OBB << " " << dq.dqb_curspace;
-#endif
- obbSize = dq.dqb_curspace;
+ if ((space = GetOccupiedSpaceForGid(uuidString, AID_MEDIA_OBB)) != -1) {
+ obbSize = space;
}
ATRACE_END();
@@ -1736,7 +1867,7 @@
memset(&extStats, 0, sizeof(extStats));
for (auto appId : appIds) {
if (appId >= AID_APP_START) {
- collectQuotaStats(device, userId, appId, nullptr, &extStats);
+ collectQuotaStats(uuidString, userId, appId, nullptr, &extStats);
}
}
appSize = extStats.dataSize;
@@ -1919,6 +2050,17 @@
return res ? error(res, error_msg) : ok();
}
+binder::Status InstalldNativeService::compileLayouts(const std::string& apkPath,
+ const std::string& packageName,
+ const std ::string& outDexFile, int uid,
+ bool* _aidl_return) {
+ const char* apk_path = apkPath.c_str();
+ const char* package_name = packageName.c_str();
+ const char* out_dex_file = outDexFile.c_str();
+ *_aidl_return = android::installd::view_compiler(apk_path, package_name, out_dex_file, uid);
+ return *_aidl_return ? ok() : error("viewcompiler failed");
+}
+
binder::Status InstalldNativeService::markBootComplete(const std::string& instructionSet) {
ENFORCE_UID(AID_SYSTEM);
std::lock_guard<std::recursive_mutex> lock(mLock);
@@ -1964,8 +2106,14 @@
return error("Failed to stat " + _pkgdir);
}
+ char *con = nullptr;
+ if (lgetfilecon(pkgdir, &con) < 0) {
+ return error("Failed to lgetfilecon " + _pkgdir);
+ }
+
if (chown(pkgdir, AID_INSTALL, AID_INSTALL) < 0) {
- return error("Failed to chown " + _pkgdir);
+ res = error("Failed to chown " + _pkgdir);
+ goto out;
}
if (chmod(pkgdir, 0700) < 0) {
@@ -1997,7 +2145,13 @@
goto out;
}
+ if (lsetfilecon(libsymlink, con) < 0) {
+ res = error("Failed to lsetfilecon " + _libsymlink);
+ goto out;
+ }
+
out:
+ free(con);
if (chmod(pkgdir, s.st_mode) < 0) {
auto msg = "Failed to cleanup chmod " + _pkgdir;
if (res.isOk()) {
@@ -2524,7 +2678,12 @@
std::lock_guard<std::recursive_mutex> lock(mMountsLock);
mStorageMounts.clear();
- mQuotaReverseMounts.clear();
+
+#if !BYPASS_QUOTA
+ if (!InvalidateQuotaMounts()) {
+ return error("Failed to read mounts");
+ }
+#endif
std::ifstream in("/proc/mounts");
if (!in.is_open()) {
@@ -2545,17 +2704,6 @@
mStorageMounts[source] = target;
}
#endif
-
-#if !BYPASS_QUOTA
- if (source.compare(0, 11, "/dev/block/") == 0) {
- struct dqblk dq;
- if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), source.c_str(), 0,
- reinterpret_cast<char*>(&dq)) == 0) {
- LOG(DEBUG) << "Found quota mount " << source << " at " << target;
- mQuotaReverseMounts[target] = source;
- }
- }
-#endif
}
return ok();
}
@@ -2573,16 +2721,10 @@
return StringPrintf("%s/%u", resolved.c_str(), userid);
}
-std::string InstalldNativeService::findQuotaDeviceForUuid(
- const std::unique_ptr<std::string>& uuid) {
- std::lock_guard<std::recursive_mutex> lock(mMountsLock);
- auto path = create_data_path(uuid ? uuid->c_str() : nullptr);
- return mQuotaReverseMounts[path];
-}
-
binder::Status InstalldNativeService::isQuotaSupported(
- const std::unique_ptr<std::string>& volumeUuid, bool* _aidl_return) {
- *_aidl_return = !findQuotaDeviceForUuid(volumeUuid).empty();
+ const std::unique_ptr<std::string>& uuid, bool* _aidl_return) {
+ auto uuidString = uuid ? *uuid : "";
+ *_aidl_return = IsQuotaSupported(uuidString);
return ok();
}
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index cebd3f9..578132d 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -60,6 +60,16 @@
binder::Status fixupAppData(const std::unique_ptr<std::string>& uuid, int32_t flags);
+ binder::Status snapshotAppData(const std::unique_ptr<std::string>& volumeUuid,
+ const std::string& packageName, const int32_t user, int32_t storageFlags,
+ int64_t* _aidl_return);
+ binder::Status restoreAppDataSnapshot(const std::unique_ptr<std::string>& volumeUuid,
+ const std::string& packageName, const int32_t appId, const int64_t ceDataInode,
+ const std::string& seInfo, const int32_t user, int32_t storageFlags);
+ binder::Status destroyAppDataSnapshot(const std::unique_ptr<std::string> &volumeUuid,
+ const std::string& packageName, const int32_t user, const int64_t ceSnapshotInode,
+ int32_t storageFlags);
+
binder::Status getAppSize(const std::unique_ptr<std::string>& uuid,
const std::vector<std::string>& packageNames, int32_t userId, int32_t flags,
int32_t appId, const std::vector<int64_t>& ceDataInodes,
@@ -89,6 +99,9 @@
const std::unique_ptr<std::string>& dexMetadataPath,
const std::unique_ptr<std::string>& compilationReason);
+ binder::Status compileLayouts(const std::string& apkPath, const std::string& packageName,
+ const std::string& outDexFile, int uid, bool* _aidl_return);
+
binder::Status rmdex(const std::string& codePath, const std::string& instructionSet);
binder::Status mergeProfiles(int32_t uid, const std::string& packageName,
@@ -150,14 +163,11 @@
/* Map of all storage mounts from source to target */
std::unordered_map<std::string, std::string> mStorageMounts;
- /* Map of all quota mounts from target to source */
- std::unordered_map<std::string, std::string> mQuotaReverseMounts;
/* Map from UID to cache quota size */
std::unordered_map<uid_t, int64_t> mCacheQuotas;
std::string findDataMediaPath(const std::unique_ptr<std::string>& uuid, userid_t userid);
- std::string findQuotaDeviceForUuid(const std::unique_ptr<std::string>& uuid);
};
} // namespace installd
diff --git a/cmds/installd/QuotaUtils.cpp b/cmds/installd/QuotaUtils.cpp
new file mode 100644
index 0000000..b238dd3
--- /dev/null
+++ b/cmds/installd/QuotaUtils.cpp
@@ -0,0 +1,122 @@
+/*
+ * 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 "QuotaUtils.h"
+
+#include <fstream>
+#include <unordered_map>
+
+#include <sys/quota.h>
+
+#include <android-base/logging.h>
+
+#include "utils.h"
+
+namespace android {
+namespace installd {
+
+namespace {
+
+std::recursive_mutex mMountsLock;
+
+/* Map of all quota mounts from target to source */
+std::unordered_map<std::string, std::string> mQuotaReverseMounts;
+
+std::string& FindQuotaDeviceForUuid(const std::string& uuid) {
+ std::lock_guard<std::recursive_mutex> lock(mMountsLock);
+ auto path = create_data_path(uuid.empty() ? nullptr : uuid.c_str());
+ return mQuotaReverseMounts[path];
+}
+
+} // namespace
+
+bool InvalidateQuotaMounts() {
+ std::lock_guard<std::recursive_mutex> lock(mMountsLock);
+
+ mQuotaReverseMounts.clear();
+
+ std::ifstream in("/proc/mounts");
+ if (!in.is_open()) {
+ return false;
+ }
+
+ std::string source;
+ std::string target;
+ std::string ignored;
+ while (!in.eof()) {
+ std::getline(in, source, ' ');
+ std::getline(in, target, ' ');
+ std::getline(in, ignored);
+
+ if (source.compare(0, 11, "/dev/block/") == 0) {
+ struct dqblk dq;
+ if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), source.c_str(), 0,
+ reinterpret_cast<char*>(&dq)) == 0) {
+ LOG(DEBUG) << "Found quota mount " << source << " at " << target;
+ mQuotaReverseMounts[target] = source;
+ }
+ }
+ }
+ return true;
+}
+
+bool IsQuotaSupported(const std::string& uuid) {
+ return !FindQuotaDeviceForUuid(uuid).empty();
+}
+
+int64_t GetOccupiedSpaceForUid(const std::string& uuid, uid_t uid) {
+ const std::string device = FindQuotaDeviceForUuid(uuid);
+ if (device == "") {
+ return -1;
+ }
+ struct dqblk dq;
+ if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
+ reinterpret_cast<char*>(&dq)) != 0) {
+ if (errno != ESRCH) {
+ PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid;
+ }
+ return -1;
+ } else {
+#if MEASURE_DEBUG
+ LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace;
+#endif
+ return dq.dqb_curspace;
+ }
+}
+
+int64_t GetOccupiedSpaceForGid(const std::string& uuid, gid_t gid) {
+ const std::string device = FindQuotaDeviceForUuid(uuid);
+ if (device == "") {
+ return -1;
+ }
+ struct dqblk dq;
+ if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), gid,
+ reinterpret_cast<char*>(&dq)) != 0) {
+ if (errno != ESRCH) {
+ PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << gid;
+ }
+ return -1;
+ } else {
+#if MEASURE_DEBUG
+ LOG(DEBUG) << "quotactl() for GID " << gid << " " << dq.dqb_curspace;
+#endif
+ return dq.dqb_curspace;
+ }
+
+}
+
+} // namespace installd
+} // namespace android
diff --git a/cmds/installd/QuotaUtils.h b/cmds/installd/QuotaUtils.h
new file mode 100644
index 0000000..9ad170f
--- /dev/null
+++ b/cmds/installd/QuotaUtils.h
@@ -0,0 +1,41 @@
+/*
+ * 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_INSTALLD_QUOTA_UTILS_H_
+#define ANDROID_INSTALLD_QUOTA_UTILS_H_
+
+#include <memory>
+#include <string>
+
+namespace android {
+namespace installd {
+
+/* Clear and recompute the reverse mounts map */
+bool InvalidateQuotaMounts();
+
+/* Whether quota is supported in the device with the given uuid */
+bool IsQuotaSupported(const std::string& uuid);
+
+/* Get the current occupied space in bytes for a uid or -1 if fails */
+int64_t GetOccupiedSpaceForUid(const std::string& uuid, uid_t uid);
+
+/* Get the current occupied space in bytes for a gid or -1 if fails */
+int64_t GetOccupiedSpaceForGid(const std::string& uuid, gid_t gid);
+
+} // namespace installd
+} // namespace android
+
+#endif // ANDROID_INSTALLD_QUOTA_UTILS_H_
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 91e20b7..377074a 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -55,6 +55,8 @@
@nullable @utf8InCpp String profileName,
@nullable @utf8InCpp String dexMetadataPath,
@nullable @utf8InCpp String compilationReason);
+ boolean compileLayouts(@utf8InCpp String apkPath, @utf8InCpp String packageName,
+ @utf8InCpp String outDexFile, int uid);
void rmdex(@utf8InCpp String codePath, @utf8InCpp String instructionSet);
@@ -102,4 +104,14 @@
boolean prepareAppProfile(@utf8InCpp String packageName,
int userId, int appId, @utf8InCpp String profileName, @utf8InCpp String codePath,
@nullable @utf8InCpp String dexMetadata);
+
+ long snapshotAppData(@nullable @utf8InCpp String uuid, in @utf8InCpp String packageName,
+ int userId, int storageFlags);
+ void restoreAppDataSnapshot(@nullable @utf8InCpp String uuid, in @utf8InCpp String packageName,
+ int appId, long ceDataInode, @utf8InCpp String seInfo, int user, int storageflags);
+ void destroyAppDataSnapshot(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
+ int userId, long ceSnapshotInode, int storageFlags);
+
+ const int FLAG_STORAGE_DE = 0x1;
+ const int FLAG_STORAGE_CE = 0x2;
}
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 174ab21..940ba79 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -43,6 +43,7 @@
#include <log/log.h> // TODO: Move everything to base/logging.
#include <openssl/sha.h>
#include <private/android_filesystem_config.h>
+#include <processgroup/sched_policy.h>
#include <selinux/android.h>
#include <system/thread_defs.h>
@@ -54,6 +55,8 @@
#include "utils.h"
using android::base::EndsWith;
+using android::base::GetBoolProperty;
+using android::base::GetProperty;
using android::base::ReadFully;
using android::base::StringPrintf;
using android::base::WriteFully;
@@ -181,36 +184,11 @@
return clear_current_profile(package_name, location, user, /*is_secondary_dex*/false);
}
-static int split_count(const char *str)
-{
- char *ctx;
- int count = 0;
- char buf[kPropertyValueMax];
-
- strlcpy(buf, str, sizeof(buf));
- char *pBuf = buf;
-
- while(strtok_r(pBuf, " ", &ctx) != nullptr) {
- count++;
- pBuf = nullptr;
- }
-
- return count;
-}
-
-static int split(char *buf, const char **argv)
-{
- char *ctx;
- int count = 0;
- char *tok;
- char *pBuf = buf;
-
- while((tok = strtok_r(pBuf, " ", &ctx)) != nullptr) {
- argv[count++] = tok;
- pBuf = nullptr;
- }
-
- return count;
+static std::vector<std::string> SplitBySpaces(const std::string& str) {
+ if (str.empty()) {
+ return {};
+ }
+ return android::base::Split(str, " ");
}
static const char* get_location_from_path(const char* path) {
@@ -224,345 +202,284 @@
}
}
-[[ noreturn ]]
-static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vdex_fd, int image_fd,
- const char* input_file_name, const char* output_file_name, int swap_fd,
- const char* instruction_set, const char* compiler_filter,
- bool debuggable, bool post_bootcomplete, bool background_job_compile, int profile_fd,
- const char* class_loader_context, int target_sdk_version, bool enable_hidden_api_checks,
- bool generate_compact_dex, int dex_metadata_fd, const char* compilation_reason) {
- static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
+// ExecVHelper prepares and holds pointers to parsed command line arguments so that no allocations
+// need to be performed between the fork and exec.
+class ExecVHelper {
+ public:
+ // Store a placeholder for the binary name.
+ ExecVHelper() : args_(1u, std::string()) {}
- if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
- LOG(ERROR) << "Instruction set '" << instruction_set << "' longer than max length of "
- << MAX_INSTRUCTION_SET_LEN;
- exit(DexoptReturnCodes::kInstructionSetLength);
+ void PrepareArgs(const std::string& bin) {
+ CHECK(!args_.empty());
+ CHECK(args_[0].empty());
+ args_[0] = bin;
+ // Write char* into array.
+ for (const std::string& arg : args_) {
+ argv_.push_back(arg.c_str());
+ }
+ argv_.push_back(nullptr); // Add null terminator.
}
- // Get the relative path to the input file.
- const char* relative_input_file_name = get_location_from_path(input_file_name);
-
- char dex2oat_Xms_flag[kPropertyValueMax];
- bool have_dex2oat_Xms_flag = get_property("dalvik.vm.dex2oat-Xms", dex2oat_Xms_flag, nullptr) > 0;
-
- char dex2oat_Xmx_flag[kPropertyValueMax];
- bool have_dex2oat_Xmx_flag = get_property("dalvik.vm.dex2oat-Xmx", dex2oat_Xmx_flag, nullptr) > 0;
-
- char dex2oat_threads_buf[kPropertyValueMax];
- bool have_dex2oat_threads_flag = get_property(post_bootcomplete
- ? "dalvik.vm.dex2oat-threads"
- : "dalvik.vm.boot-dex2oat-threads",
- dex2oat_threads_buf,
- nullptr) > 0;
- char dex2oat_threads_arg[kPropertyValueMax + 2];
- if (have_dex2oat_threads_flag) {
- sprintf(dex2oat_threads_arg, "-j%s", dex2oat_threads_buf);
+ [[ noreturn ]]
+ void Exec(int exit_code) {
+ execv(argv_[0], (char * const *)&argv_[0]);
+ PLOG(ERROR) << "execv(" << argv_[0] << ") failed";
+ exit(exit_code);
}
- char dex2oat_isa_features_key[kPropertyKeyMax];
- sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", instruction_set);
- char dex2oat_isa_features[kPropertyValueMax];
- bool have_dex2oat_isa_features = get_property(dex2oat_isa_features_key,
- dex2oat_isa_features, nullptr) > 0;
-
- char dex2oat_isa_variant_key[kPropertyKeyMax];
- sprintf(dex2oat_isa_variant_key, "dalvik.vm.isa.%s.variant", instruction_set);
- char dex2oat_isa_variant[kPropertyValueMax];
- bool have_dex2oat_isa_variant = get_property(dex2oat_isa_variant_key,
- dex2oat_isa_variant, nullptr) > 0;
-
- const char *dex2oat_norelocation = "-Xnorelocate";
- bool have_dex2oat_relocation_skip_flag = false;
-
- char dex2oat_flags[kPropertyValueMax];
- int dex2oat_flags_count = get_property("dalvik.vm.dex2oat-flags",
- dex2oat_flags, nullptr) <= 0 ? 0 : split_count(dex2oat_flags);
- ALOGV("dalvik.vm.dex2oat-flags=%s\n", dex2oat_flags);
-
- // If we are booting without the real /data, don't spend time compiling.
- char vold_decrypt[kPropertyValueMax];
- bool have_vold_decrypt = get_property("vold.decrypt", vold_decrypt, "") > 0;
- bool skip_compilation = (have_vold_decrypt &&
- (strcmp(vold_decrypt, "trigger_restart_min_framework") == 0 ||
- (strcmp(vold_decrypt, "1") == 0)));
-
- bool generate_debug_info = property_get_bool("debug.generate-debug-info", false);
- const bool resolve_startup_strings =
- property_get_bool("dalvik.vm.dex2oat-resolve-startup-strings", false);
-
- char app_image_format[kPropertyValueMax];
- char image_format_arg[strlen("--image-format=") + kPropertyValueMax];
- bool have_app_image_format =
- image_fd >= 0 && get_property("dalvik.vm.appimageformat", app_image_format, nullptr) > 0;
- if (have_app_image_format) {
- sprintf(image_format_arg, "--image-format=%s", app_image_format);
- }
-
- char dex2oat_large_app_threshold[kPropertyValueMax];
- bool have_dex2oat_large_app_threshold =
- get_property("dalvik.vm.dex2oat-very-large", dex2oat_large_app_threshold, nullptr) > 0;
- char dex2oat_large_app_threshold_arg[strlen("--very-large-app-threshold=") + kPropertyValueMax];
- if (have_dex2oat_large_app_threshold) {
- sprintf(dex2oat_large_app_threshold_arg,
- "--very-large-app-threshold=%s",
- dex2oat_large_app_threshold);
- }
-
- // If the runtime was requested to use libartd.so, we'll run dex2oatd, otherwise dex2oat.
- const char* dex2oat_bin = "/system/bin/dex2oat";
- constexpr const char* kDex2oatDebugPath = "/system/bin/dex2oatd";
- // Do not use dex2oatd for release candidates (give dex2oat more soak time).
- bool is_release = android::base::GetProperty("ro.build.version.codename", "") == "REL";
- if (is_debug_runtime() || (background_job_compile && is_debuggable_build() && !is_release)) {
- if (access(kDex2oatDebugPath, X_OK) == 0) {
- dex2oat_bin = kDex2oatDebugPath;
+ // Add an arg if it's not empty.
+ void AddArg(const std::string& arg) {
+ if (!arg.empty()) {
+ args_.push_back(arg);
}
}
- bool generate_minidebug_info = kEnableMinidebugInfo &&
- android::base::GetBoolProperty(kMinidebugInfoSystemProperty,
- kMinidebugInfoSystemPropertyDefault);
-
- static const char* RUNTIME_ARG = "--runtime-arg";
-
- static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig
-
- // clang FORTIFY doesn't let us use strlen in constant array bounds, so we
- // use arraysize instead.
- char zip_fd_arg[arraysize("--zip-fd=") + MAX_INT_LEN];
- char zip_location_arg[arraysize("--zip-location=") + PKG_PATH_MAX];
- char input_vdex_fd_arg[arraysize("--input-vdex-fd=") + MAX_INT_LEN];
- char output_vdex_fd_arg[arraysize("--output-vdex-fd=") + MAX_INT_LEN];
- char oat_fd_arg[arraysize("--oat-fd=") + MAX_INT_LEN];
- char oat_location_arg[arraysize("--oat-location=") + PKG_PATH_MAX];
- char instruction_set_arg[arraysize("--instruction-set=") + MAX_INSTRUCTION_SET_LEN];
- char instruction_set_variant_arg[arraysize("--instruction-set-variant=") + kPropertyValueMax];
- char instruction_set_features_arg[arraysize("--instruction-set-features=") + kPropertyValueMax];
- char dex2oat_Xms_arg[arraysize("-Xms") + kPropertyValueMax];
- char dex2oat_Xmx_arg[arraysize("-Xmx") + kPropertyValueMax];
- char dex2oat_compiler_filter_arg[arraysize("--compiler-filter=") + kPropertyValueMax];
- bool have_dex2oat_swap_fd = false;
- char dex2oat_swap_fd[arraysize("--swap-fd=") + MAX_INT_LEN];
- bool have_dex2oat_image_fd = false;
- char dex2oat_image_fd[arraysize("--app-image-fd=") + MAX_INT_LEN];
- size_t class_loader_context_size = arraysize("--class-loader-context=") + PKG_PATH_MAX;
- char target_sdk_version_arg[arraysize("-Xtarget-sdk-version:") + MAX_INT_LEN];
- char class_loader_context_arg[class_loader_context_size];
- if (class_loader_context != nullptr) {
- snprintf(class_loader_context_arg, class_loader_context_size, "--class-loader-context=%s",
- class_loader_context);
- }
-
- sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);
- sprintf(zip_location_arg, "--zip-location=%s", relative_input_file_name);
- sprintf(input_vdex_fd_arg, "--input-vdex-fd=%d", input_vdex_fd);
- sprintf(output_vdex_fd_arg, "--output-vdex-fd=%d", output_vdex_fd);
- sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd);
- sprintf(oat_location_arg, "--oat-location=%s", output_file_name);
- sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set);
- sprintf(instruction_set_variant_arg, "--instruction-set-variant=%s", dex2oat_isa_variant);
- sprintf(instruction_set_features_arg, "--instruction-set-features=%s", dex2oat_isa_features);
- if (swap_fd >= 0) {
- have_dex2oat_swap_fd = true;
- sprintf(dex2oat_swap_fd, "--swap-fd=%d", swap_fd);
- }
- if (image_fd >= 0) {
- have_dex2oat_image_fd = true;
- sprintf(dex2oat_image_fd, "--app-image-fd=%d", image_fd);
- }
-
- if (have_dex2oat_Xms_flag) {
- sprintf(dex2oat_Xms_arg, "-Xms%s", dex2oat_Xms_flag);
- }
- if (have_dex2oat_Xmx_flag) {
- sprintf(dex2oat_Xmx_arg, "-Xmx%s", dex2oat_Xmx_flag);
- }
- sprintf(target_sdk_version_arg, "-Xtarget-sdk-version:%d", target_sdk_version);
-
- // Compute compiler filter.
-
- bool have_dex2oat_compiler_filter_flag = false;
- if (skip_compilation) {
- strlcpy(dex2oat_compiler_filter_arg, "--compiler-filter=extract",
- sizeof(dex2oat_compiler_filter_arg));
- have_dex2oat_compiler_filter_flag = true;
- have_dex2oat_relocation_skip_flag = true;
- } else if (compiler_filter != nullptr) {
- if (strlen(compiler_filter) + strlen("--compiler-filter=") <
- arraysize(dex2oat_compiler_filter_arg)) {
- sprintf(dex2oat_compiler_filter_arg, "--compiler-filter=%s", compiler_filter);
- have_dex2oat_compiler_filter_flag = true;
- } else {
- ALOGW("Compiler filter name '%s' is too large (max characters is %zu)",
- compiler_filter,
- kPropertyValueMax);
+ // Add a runtime arg if it's not empty.
+ void AddRuntimeArg(const std::string& arg) {
+ if (!arg.empty()) {
+ args_.push_back("--runtime-arg");
+ args_.push_back(arg);
}
}
- if (!have_dex2oat_compiler_filter_flag) {
- char dex2oat_compiler_filter_flag[kPropertyValueMax];
- have_dex2oat_compiler_filter_flag = get_property("dalvik.vm.dex2oat-filter",
- dex2oat_compiler_filter_flag, nullptr) > 0;
- if (have_dex2oat_compiler_filter_flag) {
- sprintf(dex2oat_compiler_filter_arg,
- "--compiler-filter=%s",
- dex2oat_compiler_filter_flag);
- }
- }
+ protected:
+ // Holder arrays for backing arg storage.
+ std::vector<std::string> args_;
- // Check whether all apps should be compiled debuggable.
- if (!debuggable) {
- char prop_buf[kPropertyValueMax];
- debuggable =
- (get_property("dalvik.vm.always_debuggable", prop_buf, "0") > 0) &&
- (prop_buf[0] == '1');
- }
- char profile_arg[strlen("--profile-file-fd=") + MAX_INT_LEN];
- if (profile_fd != -1) {
- sprintf(profile_arg, "--profile-file-fd=%d", profile_fd);
- }
+ // Argument poiners.
+ std::vector<const char*> argv_;
+};
- // Get the directory of the apk to pass as a base classpath directory.
- char base_dir[arraysize("--classpath-dir=") + PKG_PATH_MAX];
- std::string apk_dir(input_file_name);
- unsigned long dir_index = apk_dir.rfind('/');
- bool has_base_dir = dir_index != std::string::npos;
- if (has_base_dir) {
- apk_dir = apk_dir.substr(0, dir_index);
- sprintf(base_dir, "--classpath-dir=%s", apk_dir.c_str());
- }
-
- std::string dex_metadata_fd_arg = "--dm-fd=" + std::to_string(dex_metadata_fd);
-
- std::string compilation_reason_arg = compilation_reason == nullptr
- ? ""
- : std::string("--compilation-reason=") + compilation_reason;
-
- ALOGV("Running %s in=%s out=%s\n", dex2oat_bin, relative_input_file_name, output_file_name);
-
- // Disable cdex if update input vdex is true since this combination of options is not
- // supported.
- const bool disable_cdex = !generate_compact_dex || (input_vdex_fd == output_vdex_fd);
-
- const char* argv[10 // program name, mandatory arguments and the final NULL
- + (have_dex2oat_isa_variant ? 1 : 0)
- + (have_dex2oat_isa_features ? 1 : 0)
- + (have_dex2oat_Xms_flag ? 2 : 0)
- + (have_dex2oat_Xmx_flag ? 2 : 0)
- + (have_dex2oat_compiler_filter_flag ? 1 : 0)
- + (have_dex2oat_threads_flag ? 1 : 0)
- + (have_dex2oat_swap_fd ? 1 : 0)
- + (have_dex2oat_image_fd ? 1 : 0)
- + (have_dex2oat_relocation_skip_flag ? 2 : 0)
- + (generate_debug_info ? 1 : 0)
- + (debuggable ? 1 : 0)
- + (have_app_image_format ? 1 : 0)
- + dex2oat_flags_count
- + (profile_fd == -1 ? 0 : 1)
- + (class_loader_context != nullptr ? 1 : 0)
- + (has_base_dir ? 1 : 0)
- + (have_dex2oat_large_app_threshold ? 1 : 0)
- + (disable_cdex ? 1 : 0)
- + (generate_minidebug_info ? 1 : 0)
- + (target_sdk_version != 0 ? 2 : 0)
- + (enable_hidden_api_checks ? 2 : 0)
- + (dex_metadata_fd > -1 ? 1 : 0)
- + (compilation_reason != nullptr ? 1 : 0)];
- int i = 0;
- argv[i++] = dex2oat_bin;
- argv[i++] = zip_fd_arg;
- argv[i++] = zip_location_arg;
- argv[i++] = input_vdex_fd_arg;
- argv[i++] = output_vdex_fd_arg;
- argv[i++] = oat_fd_arg;
- argv[i++] = oat_location_arg;
- argv[i++] = instruction_set_arg;
- argv[i++] = resolve_startup_strings ? "--resolve-startup-const-strings=true" :
- "--resolve-startup-const-strings=false";
- if (have_dex2oat_isa_variant) {
- argv[i++] = instruction_set_variant_arg;
- }
- if (have_dex2oat_isa_features) {
- argv[i++] = instruction_set_features_arg;
- }
- if (have_dex2oat_Xms_flag) {
- argv[i++] = RUNTIME_ARG;
- argv[i++] = dex2oat_Xms_arg;
- }
- if (have_dex2oat_Xmx_flag) {
- argv[i++] = RUNTIME_ARG;
- argv[i++] = dex2oat_Xmx_arg;
- }
- if (have_dex2oat_compiler_filter_flag) {
- argv[i++] = dex2oat_compiler_filter_arg;
- }
- if (have_dex2oat_threads_flag) {
- argv[i++] = dex2oat_threads_arg;
- }
- if (have_dex2oat_swap_fd) {
- argv[i++] = dex2oat_swap_fd;
- }
- if (have_dex2oat_image_fd) {
- argv[i++] = dex2oat_image_fd;
- }
- if (generate_debug_info) {
- argv[i++] = "--generate-debug-info";
- }
- if (debuggable) {
- argv[i++] = "--debuggable";
- }
- if (have_app_image_format) {
- argv[i++] = image_format_arg;
- }
- if (have_dex2oat_large_app_threshold) {
- argv[i++] = dex2oat_large_app_threshold_arg;
- }
- if (dex2oat_flags_count) {
- i += split(dex2oat_flags, argv + i);
- }
- if (have_dex2oat_relocation_skip_flag) {
- argv[i++] = RUNTIME_ARG;
- argv[i++] = dex2oat_norelocation;
- }
- if (profile_fd != -1) {
- argv[i++] = profile_arg;
- }
- if (has_base_dir) {
- argv[i++] = base_dir;
- }
- if (class_loader_context != nullptr) {
- argv[i++] = class_loader_context_arg;
- }
- if (generate_minidebug_info) {
- argv[i++] = kMinidebugDex2oatFlag;
- }
- if (disable_cdex) {
- argv[i++] = kDisableCompactDexFlag;
- }
- if (target_sdk_version != 0) {
- argv[i++] = RUNTIME_ARG;
- argv[i++] = target_sdk_version_arg;
- }
- if (enable_hidden_api_checks) {
- argv[i++] = RUNTIME_ARG;
- argv[i++] = "-Xhidden-api-checks";
- }
-
- if (dex_metadata_fd > -1) {
- argv[i++] = dex_metadata_fd_arg.c_str();
- }
-
- if(compilation_reason != nullptr) {
- argv[i++] = compilation_reason_arg.c_str();
- }
- // Do not add after dex2oat_flags, they should override others for debugging.
- argv[i] = nullptr;
-
- execv(dex2oat_bin, (char * const *)argv);
- PLOG(ERROR) << "execv(" << dex2oat_bin << ") failed";
- exit(DexoptReturnCodes::kDex2oatExec);
+static std::string MapPropertyToArg(const std::string& property,
+ const std::string& format,
+ const std::string& default_value = "") {
+ std::string prop = GetProperty(property, default_value);
+ if (!prop.empty()) {
+ return StringPrintf(format.c_str(), prop.c_str());
+ }
+ return "";
}
+class RunDex2Oat : public ExecVHelper {
+ public:
+ RunDex2Oat(int zip_fd,
+ int oat_fd,
+ int input_vdex_fd,
+ int output_vdex_fd,
+ int image_fd,
+ const char* input_file_name,
+ const char* output_file_name,
+ int swap_fd,
+ const char* instruction_set,
+ const char* compiler_filter,
+ bool debuggable,
+ bool post_bootcomplete,
+ bool background_job_compile,
+ int profile_fd,
+ const char* class_loader_context,
+ int target_sdk_version,
+ bool enable_hidden_api_checks,
+ bool generate_compact_dex,
+ int dex_metadata_fd,
+ const char* compilation_reason) {
+ // Get the relative path to the input file.
+ const char* relative_input_file_name = get_location_from_path(input_file_name);
+
+ std::string dex2oat_Xms_arg = MapPropertyToArg("dalvik.vm.dex2oat-Xms", "-Xms%s");
+ std::string dex2oat_Xmx_arg = MapPropertyToArg("dalvik.vm.dex2oat-Xmx", "-Xmx%s");
+
+ const char* threads_property = post_bootcomplete
+ ? "dalvik.vm.dex2oat-threads"
+ : "dalvik.vm.boot-dex2oat-threads";
+ std::string dex2oat_threads_arg = MapPropertyToArg(threads_property, "-j%s");
+
+ const std::string dex2oat_isa_features_key =
+ StringPrintf("dalvik.vm.isa.%s.features", instruction_set);
+ std::string instruction_set_features_arg =
+ MapPropertyToArg(dex2oat_isa_features_key, "--instruction-set-features=%s");
+
+ const std::string dex2oat_isa_variant_key =
+ StringPrintf("dalvik.vm.isa.%s.variant", instruction_set);
+ std::string instruction_set_variant_arg =
+ MapPropertyToArg(dex2oat_isa_variant_key, "--instruction-set-variant=%s");
+
+ const char* dex2oat_norelocation = "-Xnorelocate";
+
+ const std::string dex2oat_flags = GetProperty("dalvik.vm.dex2oat-flags", "");
+ std::vector<std::string> dex2oat_flags_args = SplitBySpaces(dex2oat_flags);
+ ALOGV("dalvik.vm.dex2oat-flags=%s\n", dex2oat_flags.c_str());
+
+ // If we are booting without the real /data, don't spend time compiling.
+ std::string vold_decrypt = GetProperty("vold.decrypt", "");
+ bool skip_compilation = vold_decrypt == "trigger_restart_min_framework" ||
+ vold_decrypt == "1";
+
+ const std::string resolve_startup_string_arg =
+ MapPropertyToArg("dalvik.vm.dex2oat-resolve-startup-strings",
+ "--resolve-startup-const-strings=%s");
+
+ const std::string image_block_size_arg =
+ MapPropertyToArg("dalvik.vm.dex2oat-max-image-block-size",
+ "--max-image-block-size=%s");
+
+ const bool generate_debug_info = GetBoolProperty("debug.generate-debug-info", false);
+
+ std::string image_format_arg;
+ if (image_fd >= 0) {
+ image_format_arg = MapPropertyToArg("dalvik.vm.appimageformat", "--image-format=%s");
+ }
+
+ std::string dex2oat_large_app_threshold_arg =
+ MapPropertyToArg("dalvik.vm.dex2oat-very-large", "--very-large-app-threshold=%s");
+
+ // If the runtime was requested to use libartd.so, we'll run dex2oatd, otherwise dex2oat.
+ const char* dex2oat_bin = kDex2oatPath;
+ // Do not use dex2oatd for release candidates (give dex2oat more soak time).
+ bool is_release = android::base::GetProperty("ro.build.version.codename", "") == "REL";
+ if (is_debug_runtime() ||
+ (background_job_compile && is_debuggable_build() && !is_release)) {
+ if (access(kDex2oatDebugPath, X_OK) == 0) {
+ dex2oat_bin = kDex2oatDebugPath;
+ }
+ }
+
+ bool generate_minidebug_info = kEnableMinidebugInfo &&
+ GetBoolProperty(kMinidebugInfoSystemProperty, kMinidebugInfoSystemPropertyDefault);
+
+ // clang FORTIFY doesn't let us use strlen in constant array bounds, so we
+ // use arraysize instead.
+ std::string zip_fd_arg = StringPrintf("--zip-fd=%d", zip_fd);
+ std::string zip_location_arg = StringPrintf("--zip-location=%s", relative_input_file_name);
+ std::string input_vdex_fd_arg = StringPrintf("--input-vdex-fd=%d", input_vdex_fd);
+ std::string output_vdex_fd_arg = StringPrintf("--output-vdex-fd=%d", output_vdex_fd);
+ std::string oat_fd_arg = StringPrintf("--oat-fd=%d", oat_fd);
+ std::string oat_location_arg = StringPrintf("--oat-location=%s", output_file_name);
+ std::string instruction_set_arg = StringPrintf("--instruction-set=%s", instruction_set);
+ std::string dex2oat_compiler_filter_arg;
+ std::string dex2oat_swap_fd;
+ std::string dex2oat_image_fd;
+ std::string target_sdk_version_arg;
+ if (target_sdk_version != 0) {
+ StringPrintf("-Xtarget-sdk-version:%d", target_sdk_version);
+ }
+ std::string class_loader_context_arg;
+ if (class_loader_context != nullptr) {
+ class_loader_context_arg = StringPrintf("--class-loader-context=%s",
+ class_loader_context);
+ }
+
+ if (swap_fd >= 0) {
+ dex2oat_swap_fd = StringPrintf("--swap-fd=%d", swap_fd);
+ }
+ if (image_fd >= 0) {
+ dex2oat_image_fd = StringPrintf("--app-image-fd=%d", image_fd);
+ }
+
+ // Compute compiler filter.
+ bool have_dex2oat_relocation_skip_flag = false;
+ if (skip_compilation) {
+ dex2oat_compiler_filter_arg = "--compiler-filter=extract";
+ have_dex2oat_relocation_skip_flag = true;
+ } else if (compiler_filter != nullptr) {
+ dex2oat_compiler_filter_arg = StringPrintf("--compiler-filter=%s", compiler_filter);
+ }
+
+ if (dex2oat_compiler_filter_arg.empty()) {
+ dex2oat_compiler_filter_arg = MapPropertyToArg("dalvik.vm.dex2oat-filter",
+ "--compiler-filter=%s");
+ }
+
+ // Check whether all apps should be compiled debuggable.
+ if (!debuggable) {
+ debuggable = GetProperty("dalvik.vm.always_debuggable", "") == "1";
+ }
+ std::string profile_arg;
+ if (profile_fd != -1) {
+ profile_arg = StringPrintf("--profile-file-fd=%d", profile_fd);
+ }
+
+ // Get the directory of the apk to pass as a base classpath directory.
+ std::string base_dir;
+ std::string apk_dir(input_file_name);
+ unsigned long dir_index = apk_dir.rfind('/');
+ bool has_base_dir = dir_index != std::string::npos;
+ if (has_base_dir) {
+ apk_dir = apk_dir.substr(0, dir_index);
+ base_dir = StringPrintf("--classpath-dir=%s", apk_dir.c_str());
+ }
+
+ std::string dex_metadata_fd_arg = "--dm-fd=" + std::to_string(dex_metadata_fd);
+
+ std::string compilation_reason_arg = compilation_reason == nullptr
+ ? ""
+ : std::string("--compilation-reason=") + compilation_reason;
+
+ ALOGV("Running %s in=%s out=%s\n", dex2oat_bin, relative_input_file_name, output_file_name);
+
+ // Disable cdex if update input vdex is true since this combination of options is not
+ // supported.
+ const bool disable_cdex = !generate_compact_dex || (input_vdex_fd == output_vdex_fd);
+
+ AddArg(zip_fd_arg);
+ AddArg(zip_location_arg);
+ AddArg(input_vdex_fd_arg);
+ AddArg(output_vdex_fd_arg);
+ AddArg(oat_fd_arg);
+ AddArg(oat_location_arg);
+ AddArg(instruction_set_arg);
+
+ AddArg(instruction_set_variant_arg);
+ AddArg(instruction_set_features_arg);
+
+ AddRuntimeArg(dex2oat_Xms_arg);
+ AddRuntimeArg(dex2oat_Xmx_arg);
+
+ AddArg(resolve_startup_string_arg);
+ AddArg(image_block_size_arg);
+ AddArg(dex2oat_compiler_filter_arg);
+ AddArg(dex2oat_threads_arg);
+ AddArg(dex2oat_swap_fd);
+ AddArg(dex2oat_image_fd);
+
+ if (generate_debug_info) {
+ AddArg("--generate-debug-info");
+ }
+ if (debuggable) {
+ AddArg("--debuggable");
+ }
+ AddArg(image_format_arg);
+ AddArg(dex2oat_large_app_threshold_arg);
+
+ if (have_dex2oat_relocation_skip_flag) {
+ AddRuntimeArg(dex2oat_norelocation);
+ }
+ AddArg(profile_arg);
+ AddArg(base_dir);
+ AddArg(class_loader_context_arg);
+ if (generate_minidebug_info) {
+ AddArg(kMinidebugDex2oatFlag);
+ }
+ if (disable_cdex) {
+ AddArg(kDisableCompactDexFlag);
+ }
+ AddArg(target_sdk_version_arg);
+ if (enable_hidden_api_checks) {
+ AddRuntimeArg("-Xhidden-api-checks");
+ }
+
+ if (dex_metadata_fd > -1) {
+ AddArg(dex_metadata_fd_arg);
+ }
+
+ AddArg(compilation_reason_arg);
+
+ // Do not add args after dex2oat_flags, they should override others for debugging.
+ args_.insert(args_.end(), dex2oat_flags_args.begin(), dex2oat_flags_args.end());
+
+ PrepareArgs(dex2oat_bin);
+ }
+};
+
/*
* Whether dexopt should use a swap file when compiling an APK.
*
@@ -584,13 +501,9 @@
}
// Check the "override" property. If it exists, return value == "true".
- char dex2oat_prop_buf[kPropertyValueMax];
- if (get_property("dalvik.vm.dex2oat-swap", dex2oat_prop_buf, "") > 0) {
- if (strcmp(dex2oat_prop_buf, "true") == 0) {
- return true;
- } else {
- return false;
- }
+ std::string dex2oat_prop_buf = GetProperty("dalvik.vm.dex2oat-swap", "");
+ if (!dex2oat_prop_buf.empty()) {
+ return dex2oat_prop_buf == "true";
}
// Shortcut for default value. This is an implementation optimization for the process sketched
@@ -600,8 +513,7 @@
return true;
}
- bool is_low_mem = property_get_bool("ro.config.low_ram", false);
- if (is_low_mem) {
+ if (GetBoolProperty("ro.config.low_ram", false)) {
return true;
}
@@ -715,118 +627,111 @@
}
}
-static void drop_capabilities(uid_t uid) {
- if (setgid(uid) != 0) {
- PLOG(ERROR) << "setgid(" << uid << ") failed in installd during dexopt";
- exit(DexoptReturnCodes::kSetGid);
- }
- if (setuid(uid) != 0) {
- PLOG(ERROR) << "setuid(" << uid << ") failed in installd during dexopt";
- exit(DexoptReturnCodes::kSetUid);
- }
- // drop capabilities
- struct __user_cap_header_struct capheader;
- struct __user_cap_data_struct capdata[2];
- memset(&capheader, 0, sizeof(capheader));
- memset(&capdata, 0, sizeof(capdata));
- capheader.version = _LINUX_CAPABILITY_VERSION_3;
- if (capset(&capheader, &capdata[0]) < 0) {
- PLOG(ERROR) << "capset failed";
- exit(DexoptReturnCodes::kCapSet);
- }
-}
-
static constexpr int PROFMAN_BIN_RETURN_CODE_COMPILE = 0;
static constexpr int PROFMAN_BIN_RETURN_CODE_SKIP_COMPILATION = 1;
static constexpr int PROFMAN_BIN_RETURN_CODE_BAD_PROFILES = 2;
static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 3;
static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 4;
-[[ noreturn ]]
-static void run_profman(const std::vector<unique_fd>& profile_fds,
- const unique_fd& reference_profile_fd,
- const std::vector<unique_fd>* apk_fds,
- const std::vector<std::string>* dex_locations,
- bool copy_and_update) {
- const char* profman_bin = is_debug_runtime() ? "/system/bin/profmand" : "/system/bin/profman";
+class RunProfman : public ExecVHelper {
+ public:
+ void SetupArgs(const std::vector<unique_fd>& profile_fds,
+ const unique_fd& reference_profile_fd,
+ const std::vector<unique_fd>& apk_fds,
+ const std::vector<std::string>& dex_locations,
+ bool copy_and_update,
+ bool store_aggregation_counters) {
+ const char* profman_bin = is_debug_runtime() ? kProfmanDebugPath: kProfmanPath;
- if (copy_and_update) {
- CHECK_EQ(1u, profile_fds.size());
- CHECK(apk_fds != nullptr);
- CHECK_EQ(1u, apk_fds->size());
- }
- std::vector<std::string> profile_args(profile_fds.size());
- for (size_t k = 0; k < profile_fds.size(); k++) {
- profile_args[k] = "--profile-file-fd=" + std::to_string(profile_fds[k].get());
- }
- std::string reference_profile_arg = "--reference-profile-file-fd="
- + std::to_string(reference_profile_fd.get());
-
- std::vector<std::string> apk_args;
- if (apk_fds != nullptr) {
- for (size_t k = 0; k < apk_fds->size(); k++) {
- apk_args.push_back("--apk-fd=" + std::to_string((*apk_fds)[k].get()));
+ if (copy_and_update) {
+ CHECK_EQ(1u, profile_fds.size());
+ CHECK_EQ(1u, apk_fds.size());
}
- }
-
- std::vector<std::string> dex_location_args;
- if (dex_locations != nullptr) {
- for (size_t k = 0; k < dex_locations->size(); k++) {
- dex_location_args.push_back("--dex-location=" + (*dex_locations)[k]);
+ if (reference_profile_fd != -1) {
+ AddArg("--reference-profile-file-fd=" + std::to_string(reference_profile_fd.get()));
}
+
+ for (const unique_fd& fd : profile_fds) {
+ AddArg("--profile-file-fd=" + std::to_string(fd.get()));
+ }
+
+ for (const unique_fd& fd : apk_fds) {
+ AddArg("--apk-fd=" + std::to_string(fd.get()));
+ }
+
+ for (const std::string& dex_location : dex_locations) {
+ AddArg("--dex-location=" + dex_location);
+ }
+
+ if (copy_and_update) {
+ AddArg("--copy-and-update-profile-key");
+ }
+
+ if (store_aggregation_counters) {
+ AddArg("--store-aggregation-counters");
+ }
+
+ // Do not add after dex2oat_flags, they should override others for debugging.
+ PrepareArgs(profman_bin);
}
- // program name, reference profile fd, the final NULL and the profile fds
- 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();
- for (size_t k = 0; k < profile_args.size(); k++) {
- argv[i++] = profile_args[k].c_str();
- }
- for (size_t k = 0; k < apk_args.size(); k++) {
- argv[i++] = apk_args[k].c_str();
- }
- for (size_t k = 0; k < dex_location_args.size(); k++) {
- argv[i++] = dex_location_args[k].c_str();
- }
- if (copy_and_update) {
- argv[i++] = "--copy-and-update-profile-key";
+ void SetupMerge(const std::vector<unique_fd>& profiles_fd,
+ const unique_fd& reference_profile_fd,
+ const std::vector<unique_fd>& apk_fds = std::vector<unique_fd>(),
+ const std::vector<std::string>& dex_locations = std::vector<std::string>(),
+ bool store_aggregation_counters = false) {
+ SetupArgs(profiles_fd,
+ reference_profile_fd,
+ apk_fds,
+ dex_locations,
+ /*copy_and_update=*/false,
+ store_aggregation_counters);
}
- // Do not add after dex2oat_flags, they should override others for debugging.
- argv[i] = nullptr;
+ void SetupCopyAndUpdate(unique_fd&& profile_fd,
+ unique_fd&& reference_profile_fd,
+ unique_fd&& apk_fd,
+ const std::string& dex_location) {
+ // The fds need to stay open longer than the scope of the function, so put them into a local
+ // variable vector.
+ profiles_fd_.push_back(std::move(profile_fd));
+ apk_fds_.push_back(std::move(apk_fd));
+ reference_profile_fd_ = std::move(reference_profile_fd);
+ std::vector<std::string> dex_locations = {dex_location};
+ SetupArgs(profiles_fd_,
+ reference_profile_fd_,
+ apk_fds_,
+ dex_locations,
+ /*copy_and_update=*/true,
+ /*store_aggregation_counters=*/false);
+ }
- execv(profman_bin, (char * const *)argv);
- PLOG(ERROR) << "execv(" << profman_bin << ") failed";
- exit(DexoptReturnCodes::kProfmanExec); /* only get here on exec failure */
-}
+ void SetupDump(const std::vector<unique_fd>& profiles_fd,
+ const unique_fd& reference_profile_fd,
+ const std::vector<std::string>& dex_locations,
+ const std::vector<unique_fd>& apk_fds,
+ const unique_fd& output_fd) {
+ AddArg("--dump-only");
+ AddArg(StringPrintf("--dump-output-to-fd=%d", output_fd.get()));
+ SetupArgs(profiles_fd,
+ reference_profile_fd,
+ apk_fds,
+ dex_locations,
+ /*copy_and_update=*/false,
+ /*store_aggregation_counters=*/false);
+ }
-[[ noreturn ]]
-static void run_profman_merge(const std::vector<unique_fd>& profiles_fd,
- const unique_fd& reference_profile_fd,
- const std::vector<unique_fd>* apk_fds = nullptr,
- const std::vector<std::string>* dex_locations = nullptr) {
- run_profman(profiles_fd, reference_profile_fd, apk_fds, dex_locations,
- /*copy_and_update*/false);
-}
+ void Exec() {
+ ExecVHelper::Exec(DexoptReturnCodes::kProfmanExec);
+ }
-[[ noreturn ]]
-static void run_profman_copy_and_update(unique_fd&& profile_fd,
- unique_fd&& reference_profile_fd,
- unique_fd&& apk_fd,
- const std::string& dex_location) {
- std::vector<unique_fd> profiles_fd;
- profiles_fd.push_back(std::move(profile_fd));
- std::vector<unique_fd> apk_fds;
- apk_fds.push_back(std::move(apk_fd));
- std::vector<std::string> dex_locations;
- dex_locations.push_back(dex_location);
+ private:
+ unique_fd reference_profile_fd_;
+ std::vector<unique_fd> profiles_fd_;
+ std::vector<unique_fd> apk_fds_;
+};
- run_profman(profiles_fd, reference_profile_fd, &apk_fds, &dex_locations,
- /*copy_and_update*/true);
-}
+
// Decides if profile guided compilation is needed or not based on existing profiles.
// The location is the package name for primary apks or the dex path for secondary dex files.
@@ -846,11 +751,13 @@
return false;
}
+ RunProfman profman_merge;
+ profman_merge.SetupMerge(profiles_fd, reference_profile_fd);
pid_t pid = fork();
if (pid == 0) {
/* child -- drop privileges before continuing */
drop_capabilities(uid);
- run_profman_merge(profiles_fd, reference_profile_fd);
+ profman_merge.Exec();
}
/* parent */
int return_code = wait_child(pid);
@@ -923,42 +830,6 @@
return analyze_profiles(uid, package_name, profile_name, /*is_secondary_dex*/false);
}
-[[ noreturn ]]
-static void run_profman_dump(const std::vector<unique_fd>& profile_fds,
- const unique_fd& reference_profile_fd,
- const std::vector<std::string>& dex_locations,
- const std::vector<unique_fd>& apk_fds,
- const unique_fd& output_fd) {
- std::vector<std::string> profman_args;
- static const char* PROFMAN_BIN = "/system/bin/profman";
- profman_args.push_back(PROFMAN_BIN);
- profman_args.push_back("--dump-only");
- profman_args.push_back(StringPrintf("--dump-output-to-fd=%d", output_fd.get()));
- if (reference_profile_fd != -1) {
- profman_args.push_back(StringPrintf("--reference-profile-file-fd=%d",
- reference_profile_fd.get()));
- }
- for (size_t i = 0; i < profile_fds.size(); i++) {
- profman_args.push_back(StringPrintf("--profile-file-fd=%d", profile_fds[i].get()));
- }
- for (const std::string& dex_location : dex_locations) {
- profman_args.push_back(StringPrintf("--dex-location=%s", dex_location.c_str()));
- }
- for (size_t i = 0; i < apk_fds.size(); i++) {
- profman_args.push_back(StringPrintf("--apk-fd=%d", apk_fds[i].get()));
- }
- const char **argv = new const char*[profman_args.size() + 1];
- size_t i = 0;
- for (const std::string& profman_arg : profman_args) {
- argv[i++] = profman_arg.c_str();
- }
- argv[i] = nullptr;
-
- execv(PROFMAN_BIN, (char * const *)argv);
- PLOG(ERROR) << "execv(" << PROFMAN_BIN << ") failed";
- exit(DexoptReturnCodes::kProfmanExec); /* only get here on exec failure */
-}
-
bool dump_profiles(int32_t uid, const std::string& pkgname, const std::string& profile_name,
const std::string& code_path) {
std::vector<unique_fd> profile_fds;
@@ -995,12 +866,13 @@
apk_fds.push_back(std::move(apk_fd));
+ RunProfman profman_dump;
+ profman_dump.SetupDump(profile_fds, reference_profile_fd, dex_locations, apk_fds, output_fd);
pid_t pid = fork();
if (pid == 0) {
/* child -- drop privileges before continuing */
drop_capabilities(uid);
- run_profman_dump(profile_fds, reference_profile_fd, dex_locations,
- apk_fds, output_fd);
+ profman_dump.Exec();
}
/* parent */
int return_code = wait_child(pid);
@@ -1310,10 +1182,8 @@
if (!generate_app_image) {
return Dex2oatFileWrapper();
}
- char app_image_format[kPropertyValueMax];
- bool have_app_image_format =
- get_property("dalvik.vm.appimageformat", app_image_format, nullptr) > 0;
- if (!have_app_image_format) {
+ std::string app_image_format = GetProperty("dalvik.vm.appimageformat", "");
+ if (app_image_format.empty()) {
return Dex2oatFileWrapper();
}
// Recreate is true since we do not want to modify a mapped image. If the app is
@@ -1574,70 +1444,58 @@
// The analyzer will check if the dex_file needs to be (re)compiled to match the compiler_filter.
// If this is for a profile guided compilation, profile_was_updated will tell whether or not
// the profile has changed.
-static void exec_dexoptanalyzer(const std::string& dex_file, int vdex_fd, int oat_fd,
- int zip_fd, const std::string& instruction_set, const std::string& compiler_filter,
- bool profile_was_updated, bool downgrade,
- const char* class_loader_context) {
- CHECK_GE(zip_fd, 0);
- const char* dexoptanalyzer_bin =
- is_debug_runtime()
- ? "/system/bin/dexoptanalyzerd"
- : "/system/bin/dexoptanalyzer";
- static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
+class RunDexoptAnalyzer : public ExecVHelper {
+ public:
+ RunDexoptAnalyzer(const std::string& dex_file,
+ int vdex_fd,
+ int oat_fd,
+ int zip_fd,
+ const std::string& instruction_set,
+ const std::string& compiler_filter,
+ bool profile_was_updated,
+ bool downgrade,
+ const char* class_loader_context) {
+ CHECK_GE(zip_fd, 0);
+ const char* dexoptanalyzer_bin =
+ is_debug_runtime() ? kDexoptanalyzerDebugPath : kDexoptanalyzerPath;
- if (instruction_set.size() >= MAX_INSTRUCTION_SET_LEN) {
- LOG(ERROR) << "Instruction set " << instruction_set
- << " longer than max length of " << MAX_INSTRUCTION_SET_LEN;
- return;
- }
+ std::string dex_file_arg = "--dex-file=" + dex_file;
+ std::string oat_fd_arg = "--oat-fd=" + std::to_string(oat_fd);
+ std::string vdex_fd_arg = "--vdex-fd=" + std::to_string(vdex_fd);
+ std::string zip_fd_arg = "--zip-fd=" + std::to_string(zip_fd);
+ std::string isa_arg = "--isa=" + instruction_set;
+ std::string compiler_filter_arg = "--compiler-filter=" + compiler_filter;
+ const char* assume_profile_changed = "--assume-profile-changed";
+ const char* downgrade_flag = "--downgrade";
+ std::string class_loader_context_arg = "--class-loader-context=";
+ if (class_loader_context != nullptr) {
+ class_loader_context_arg += class_loader_context;
+ }
- std::string dex_file_arg = "--dex-file=" + dex_file;
- std::string oat_fd_arg = "--oat-fd=" + std::to_string(oat_fd);
- std::string vdex_fd_arg = "--vdex-fd=" + std::to_string(vdex_fd);
- std::string zip_fd_arg = "--zip-fd=" + std::to_string(zip_fd);
- std::string isa_arg = "--isa=" + instruction_set;
- std::string compiler_filter_arg = "--compiler-filter=" + compiler_filter;
- const char* assume_profile_changed = "--assume-profile-changed";
- const char* downgrade_flag = "--downgrade";
- std::string class_loader_context_arg = "--class-loader-context=";
- if (class_loader_context != nullptr) {
- class_loader_context_arg += class_loader_context;
- }
+ // program name, dex file, isa, filter
+ AddArg(dex_file_arg);
+ AddArg(isa_arg);
+ AddArg(compiler_filter_arg);
+ if (oat_fd >= 0) {
+ AddArg(oat_fd_arg);
+ }
+ if (vdex_fd >= 0) {
+ AddArg(vdex_fd_arg);
+ }
+ AddArg(zip_fd_arg.c_str());
+ if (profile_was_updated) {
+ AddArg(assume_profile_changed);
+ }
+ if (downgrade) {
+ AddArg(downgrade_flag);
+ }
+ if (class_loader_context != nullptr) {
+ AddArg(class_loader_context_arg.c_str());
+ }
- // program name, dex file, isa, filter, the final NULL
- const int argc = 6 +
- (profile_was_updated ? 1 : 0) +
- (vdex_fd >= 0 ? 1 : 0) +
- (oat_fd >= 0 ? 1 : 0) +
- (downgrade ? 1 : 0) +
- (class_loader_context != nullptr ? 1 : 0);
- const char* argv[argc];
- int i = 0;
- argv[i++] = dexoptanalyzer_bin;
- argv[i++] = dex_file_arg.c_str();
- argv[i++] = isa_arg.c_str();
- argv[i++] = compiler_filter_arg.c_str();
- if (oat_fd >= 0) {
- argv[i++] = oat_fd_arg.c_str();
+ PrepareArgs(dexoptanalyzer_bin);
}
- if (vdex_fd >= 0) {
- argv[i++] = vdex_fd_arg.c_str();
- }
- argv[i++] = zip_fd_arg.c_str();
- if (profile_was_updated) {
- argv[i++] = assume_profile_changed;
- }
- if (downgrade) {
- argv[i++] = downgrade_flag;
- }
- if (class_loader_context != nullptr) {
- argv[i++] = class_loader_context_arg.c_str();
- }
- argv[i] = nullptr;
-
- execv(dexoptanalyzer_bin, (char * const *)argv);
- ALOGE("execv(%s) failed: %s\n", dexoptanalyzer_bin, strerror(errno));
-}
+};
// Prepares the oat dir for the secondary dex files.
static bool prepare_secondary_dex_oat_dir(const std::string& dex_path, int uid,
@@ -1889,16 +1747,17 @@
/*is_secondary_dex*/true);
// Run dexoptanalyzer to get dexopt_needed code. This is not expected to return.
- exec_dexoptanalyzer(dex_path,
- vdex_file_fd.get(),
- oat_file_fd.get(),
- zip_fd.get(),
- instruction_set,
- compiler_filter, profile_was_updated,
- downgrade,
- class_loader_context);
- PLOG(ERROR) << "Failed to exec dexoptanalyzer";
- _exit(kSecondaryDexDexoptAnalyzerSkippedFailExec);
+ // Note that we do not do it before the fork since opening the files is required to happen
+ // after forking.
+ RunDexoptAnalyzer run_dexopt_analyzer(dex_path,
+ vdex_file_fd.get(),
+ oat_file_fd.get(),
+ zip_fd.get(),
+ instruction_set,
+ compiler_filter, profile_was_updated,
+ downgrade,
+ class_loader_context);
+ run_dexopt_analyzer.Exec(kSecondaryDexDexoptAnalyzerSkippedFailExec);
}
/* parent */
@@ -2067,6 +1926,27 @@
LOG(VERBOSE) << "DexInv: --- BEGIN '" << dex_path << "' ---";
+ RunDex2Oat runner(input_fd.get(),
+ out_oat_fd.get(),
+ in_vdex_fd.get(),
+ out_vdex_fd.get(),
+ image_fd.get(),
+ dex_path,
+ out_oat_path,
+ swap_fd.get(),
+ instruction_set,
+ compiler_filter,
+ debuggable,
+ boot_complete,
+ background_job_compile,
+ reference_profile_fd.get(),
+ class_loader_context,
+ target_sdk_version,
+ enable_hidden_api_checks,
+ generate_compact_dex,
+ dex_metadata_fd.get(),
+ compilation_reason);
+
pid_t pid = fork();
if (pid == 0) {
/* child -- drop privileges before continuing */
@@ -2078,26 +1958,7 @@
_exit(DexoptReturnCodes::kFlock);
}
- run_dex2oat(input_fd.get(),
- out_oat_fd.get(),
- in_vdex_fd.get(),
- out_vdex_fd.get(),
- image_fd.get(),
- dex_path,
- out_oat_path,
- swap_fd.get(),
- instruction_set,
- compiler_filter,
- debuggable,
- boot_complete,
- background_job_compile,
- reference_profile_fd.get(),
- class_loader_context,
- target_sdk_version,
- enable_hidden_api_checks,
- generate_compact_dex,
- dex_metadata_fd.get(),
- compilation_reason);
+ runner.Exec(DexoptReturnCodes::kDex2oatExec);
} else {
int res = wait_child(pid);
if (res == 0) {
@@ -2425,18 +2286,14 @@
bool move_ab(const char* apk_path, const char* instruction_set, const char* oat_dir) {
// Get the current slot suffix. No suffix, no A/B.
- std::string slot_suffix;
- {
- char buf[kPropertyValueMax];
- if (get_property("ro.boot.slot_suffix", buf, nullptr) <= 0) {
- return false;
- }
- slot_suffix = buf;
+ const std::string slot_suffix = GetProperty("ro.boot.slot_suffix", "");
+ if (slot_suffix.empty()) {
+ return false;
+ }
- if (!ValidateTargetSlotSuffix(slot_suffix)) {
- LOG(ERROR) << "Target slot suffix not legal: " << slot_suffix;
- return false;
- }
+ if (!ValidateTargetSlotSuffix(slot_suffix)) {
+ LOG(ERROR) << "Target slot suffix not legal: " << slot_suffix;
+ return false;
}
// Validate other inputs.
@@ -2665,11 +2522,13 @@
return false;
}
+ RunProfman args;
+ args.SetupMerge(profiles_fd, snapshot_fd, apk_fds, dex_locations);
pid_t pid = fork();
if (pid == 0) {
/* child -- drop privileges before continuing */
drop_capabilities(app_shared_gid);
- run_profman_merge(profiles_fd, snapshot_fd, &apk_fds, &dex_locations);
+ args.Exec();
}
/* parent */
@@ -2693,6 +2552,13 @@
return false;
}
+ // Return false for empty class path since it may otherwise return true below if profiles is
+ // empty.
+ if (classpath.empty()) {
+ PLOG(ERROR) << "Class path is empty";
+ return false;
+ }
+
// Open and create the snapshot profile.
unique_fd snapshot_fd = open_spnashot_profile(AID_SYSTEM, package_name, profile_name);
@@ -2742,6 +2608,12 @@
profiles_fd.push_back(std::move(fd));
}
}
+ RunProfman args;
+ args.SetupMerge(profiles_fd,
+ snapshot_fd,
+ apk_fds,
+ dex_locations,
+ /*store_aggregation_counters=*/true);
pid_t pid = fork();
if (pid == 0) {
/* child -- drop privileges before continuing */
@@ -2749,7 +2621,7 @@
// The introduction of new access flags into boot jars causes them to
// fail dex file verification.
- run_profman_merge(profiles_fd, snapshot_fd, &apk_fds, &dex_locations);
+ args.Exec();
}
/* parent */
@@ -2803,6 +2675,11 @@
return false;
}
+ RunProfman args;
+ args.SetupCopyAndUpdate(std::move(dex_metadata_fd),
+ std::move(ref_profile_fd),
+ std::move(apk_fd),
+ code_path);
pid_t pid = fork();
if (pid == 0) {
/* child -- drop privileges before continuing */
@@ -2810,10 +2687,7 @@
drop_capabilities(app_shared_gid);
// The copy and update takes ownership over the fds.
- run_profman_copy_and_update(std::move(dex_metadata_fd),
- std::move(ref_profile_fd),
- std::move(apk_fd),
- code_path);
+ args.Exec();
}
/* parent */
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index 0db11e1..5902659 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -32,6 +32,16 @@
static constexpr int DEX2OAT_FOR_BOOT_IMAGE = 2;
static constexpr int DEX2OAT_FOR_FILTER = 3;
+#define ANDROID_RUNTIME_APEX_BIN "/apex/com.android.runtime/bin"
+// Location of binaries in the Android Runtime APEX.
+static constexpr const char* kDex2oatPath = ANDROID_RUNTIME_APEX_BIN "/dex2oat";
+static constexpr const char* kDex2oatDebugPath = ANDROID_RUNTIME_APEX_BIN "/dex2oatd";
+static constexpr const char* kProfmanPath = ANDROID_RUNTIME_APEX_BIN "/profmand";
+static constexpr const char* kProfmanDebugPath = ANDROID_RUNTIME_APEX_BIN "/profmand";
+static constexpr const char* kDexoptanalyzerPath = ANDROID_RUNTIME_APEX_BIN "/dexoptanalyzer";
+static constexpr const char* kDexoptanalyzerDebugPath = ANDROID_RUNTIME_APEX_BIN "/dexoptanalyzerd";
+#undef ANDROID_RUNTIME_APEX_BIN
+
// Clear the reference profile identified by the given profile name.
bool clear_primary_reference_profile(const std::string& pkgname, const std::string& profile_name);
// Clear the current profile identified by the given profile name (for single user).
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index b2e7047..de7b249 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -26,7 +26,6 @@
#include <sys/capability.h>
#include <sys/prctl.h>
#include <sys/stat.h>
-#include <sys/wait.h>
#include <android-base/logging.h>
#include <android-base/macros.h>
@@ -58,7 +57,6 @@
#define REPLY_MAX 256 /* largest reply allowed */
using android::base::EndsWith;
-using android::base::Join;
using android::base::Split;
using android::base::StartsWith;
using android::base::StringPrintf;
@@ -440,7 +438,7 @@
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/dex2oat");
+ cmd.push_back(kDex2oatPath);
cmd.push_back(StringPrintf("--image=%s", art_path.c_str()));
for (const std::string& boot_part : Split(boot_cp, ":")) {
cmd.push_back(StringPrintf("--dex-file=%s", boot_part.c_str()));
@@ -619,61 +617,6 @@
// Helpers, mostly taken from ART //
////////////////////////////////////
- // Wrapper on fork/execv to run a command in a subprocess.
- static bool Exec(const std::vector<std::string>& arg_vector, std::string* error_msg) {
- const std::string command_line = Join(arg_vector, ' ');
-
- CHECK_GE(arg_vector.size(), 1U) << command_line;
-
- // Convert the args to char pointers.
- const char* program = arg_vector[0].c_str();
- std::vector<char*> args;
- for (size_t i = 0; i < arg_vector.size(); ++i) {
- const std::string& arg = arg_vector[i];
- char* arg_str = const_cast<char*>(arg.c_str());
- CHECK(arg_str != nullptr) << i;
- args.push_back(arg_str);
- }
- args.push_back(nullptr);
-
- // Fork and exec.
- pid_t pid = fork();
- if (pid == 0) {
- // No allocation allowed between fork and exec.
-
- // Change process groups, so we don't get reaped by ProcessManager.
- setpgid(0, 0);
-
- execv(program, &args[0]);
-
- PLOG(ERROR) << "Failed to execv(" << command_line << ")";
- // _exit to avoid atexit handlers in child.
- _exit(1);
- } else {
- if (pid == -1) {
- *error_msg = StringPrintf("Failed to execv(%s) because fork failed: %s",
- command_line.c_str(), strerror(errno));
- return false;
- }
-
- // wait for subprocess to finish
- int status;
- pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
- if (got_pid != pid) {
- *error_msg = StringPrintf("Failed after fork for execv(%s) because waitpid failed: "
- "wanted %d, got %d: %s",
- command_line.c_str(), pid, got_pid, strerror(errno));
- return false;
- }
- if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
- *error_msg = StringPrintf("Failed execv(%s) because non-0 exit status",
- command_line.c_str());
- return false;
- }
- }
- return true;
- }
-
// Choose a random relocation offset. Taken from art/runtime/gc/image_space.cc.
static int32_t ChooseRelocationOffsetDelta(int32_t min_delta, int32_t max_delta) {
constexpr size_t kPageSize = PAGE_SIZE;
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index e90cf3b..1c99663 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -17,6 +17,7 @@
#include <fcntl.h>
#include <linux/unistd.h>
#include <sys/mount.h>
+#include <sys/stat.h>
#include <sys/wait.h>
#include <sstream>
@@ -24,6 +25,9 @@
#include <android-base/logging.h>
#include <android-base/macros.h>
#include <android-base/stringprintf.h>
+#include <selinux/android.h>
+
+#include <apexd.h>
#include "installd_constants.h"
#include "otapreopt_utils.h"
@@ -54,6 +58,27 @@
}
}
+static std::vector<apex::ApexFile> ActivateApexPackages() {
+ // The logic here is (partially) copied and adapted from
+ // system/apex/apexd/apexd_main.cpp.
+ //
+ // Only scan the APEX directory under /system (within the chroot dir).
+ // Note that this leaves around the loop devices created and used by
+ // libapexd's code, but this is fine, as we expect to reboot soon after.
+ apex::scanPackagesDirAndActivate(apex::kApexPackageSystemDir);
+ return apex::getActivePackages();
+}
+
+static void DeactivateApexPackages(const std::vector<apex::ApexFile>& active_packages) {
+ for (const apex::ApexFile& apex_file : active_packages) {
+ const std::string& package_path = apex_file.GetPath();
+ apex::Status status = apex::deactivatePackage(package_path);
+ if (!status.Ok()) {
+ LOG(ERROR) << "Failed to deactivate " << package_path << ": " << status.ErrorMessage();
+ }
+ }
+}
+
// Entry for otapreopt_chroot. Expected parameters are:
// [cmd] [status-fd] [target-slot] "dexopt" [dexopt-params]
// The file descriptor denoted by status-fd will be closed. The rest of the parameters will
@@ -138,6 +163,44 @@
UNUSED(product_result);
}
+ // Setup APEX mount point and its security context.
+ static constexpr const char* kPostinstallApexDir = "/postinstall/apex";
+ // The following logic is similar to the one in system/core/rootdir/init.rc:
+ //
+ // mount tmpfs tmpfs /apex nodev noexec nosuid
+ // chmod 0755 /apex
+ // chown root root /apex
+ // restorecon /apex
+ //
+ // except we perform the `restorecon` step just after mounting the tmpfs
+ // filesystem in /postinstall/apex, so that this directory is correctly
+ // labeled (with type `postinstall_apex_mnt_dir`) and may be manipulated in
+ // following operations (`chmod`, `chown`, etc.) following policies
+ // restricted to `postinstall_apex_mnt_dir`:
+ //
+ // mount tmpfs tmpfs /postinstall/apex nodev noexec nosuid
+ // restorecon /postinstall/apex
+ // chmod 0755 /postinstall/apex
+ // chown root root /postinstall/apex
+ //
+ if (mount("tmpfs", kPostinstallApexDir, "tmpfs", MS_NODEV | MS_NOEXEC | MS_NOSUID, nullptr)
+ != 0) {
+ PLOG(ERROR) << "Failed to mount tmpfs in " << kPostinstallApexDir;
+ exit(209);
+ }
+ if (selinux_android_restorecon(kPostinstallApexDir, 0) < 0) {
+ PLOG(ERROR) << "Failed to restorecon " << kPostinstallApexDir;
+ exit(214);
+ }
+ if (chmod(kPostinstallApexDir, 0755) != 0) {
+ PLOG(ERROR) << "Failed to chmod " << kPostinstallApexDir << " to 0755";
+ exit(210);
+ }
+ if (chown(kPostinstallApexDir, 0, 0) != 0) {
+ PLOG(ERROR) << "Failed to chown " << kPostinstallApexDir << " to root:root";
+ exit(211);
+ }
+
// Chdir into /postinstall.
if (chdir("/postinstall") != 0) {
PLOG(ERROR) << "Unable to chdir into /postinstall.";
@@ -155,22 +218,38 @@
exit(205);
}
+ // Try to mount APEX packages in "/apex" in the chroot dir. We need at least
+ // the Android Runtime APEX, as it is required by otapreopt to run dex2oat.
+ std::vector<apex::ApexFile> active_packages = ActivateApexPackages();
+
// Now go on and run otapreopt.
- // Incoming: cmd + status-fd + target-slot + cmd... + null | Incoming | = argc + 1
- // Outgoing: cmd + target-slot + cmd... + null | Outgoing | = argc
- const char** argv = new const char*[argc];
-
- argv[0] = "/system/bin/otapreopt";
+ // Incoming: cmd + status-fd + target-slot + cmd... | Incoming | = argc
+ // Outgoing: cmd + target-slot + cmd... | Outgoing | = argc - 1
+ std::vector<std::string> cmd;
+ cmd.reserve(argc);
+ cmd.push_back("/system/bin/otapreopt");
// The first parameter is the status file descriptor, skip.
- for (size_t i = 2; i <= static_cast<size_t>(argc); ++i) {
- argv[i - 1] = arg[i];
+ for (size_t i = 2; i < static_cast<size_t>(argc); ++i) {
+ cmd.push_back(arg[i]);
}
- execv(argv[0], static_cast<char * const *>(const_cast<char**>(argv)));
- PLOG(ERROR) << "execv(OTAPREOPT) failed.";
- exit(99);
+ // Fork and execute otapreopt in its own process.
+ std::string error_msg;
+ bool exec_result = Exec(cmd, &error_msg);
+ if (!exec_result) {
+ LOG(ERROR) << "Running otapreopt failed: " << error_msg;
+ }
+
+ // Tear down the work down by the apexd logic. (i.e. deactivate packages).
+ DeactivateApexPackages(active_packages);
+
+ if (!exec_result) {
+ exit(213);
+ }
+
+ return 0;
}
} // namespace installd
diff --git a/cmds/installd/otapreopt_utils.cpp b/cmds/installd/otapreopt_utils.cpp
new file mode 100644
index 0000000..124f726
--- /dev/null
+++ b/cmds/installd/otapreopt_utils.cpp
@@ -0,0 +1,88 @@
+/*
+ ** Copyright 2019, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include "otapreopt_utils.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+
+using android::base::Join;
+using android::base::StringPrintf;
+
+namespace android {
+namespace installd {
+
+bool Exec(const std::vector<std::string>& arg_vector, std::string* error_msg) {
+ const std::string command_line = Join(arg_vector, ' ');
+
+ CHECK_GE(arg_vector.size(), 1U) << command_line;
+
+ // Convert the args to char pointers.
+ const char* program = arg_vector[0].c_str();
+ std::vector<char*> args;
+ for (size_t i = 0; i < arg_vector.size(); ++i) {
+ const std::string& arg = arg_vector[i];
+ char* arg_str = const_cast<char*>(arg.c_str());
+ CHECK(arg_str != nullptr) << i;
+ args.push_back(arg_str);
+ }
+ args.push_back(nullptr);
+
+ // Fork and exec.
+ pid_t pid = fork();
+ if (pid == 0) {
+ // No allocation allowed between fork and exec.
+
+ // Change process groups, so we don't get reaped by ProcessManager.
+ setpgid(0, 0);
+
+ execv(program, &args[0]);
+
+ PLOG(ERROR) << "Failed to execv(" << command_line << ")";
+ // _exit to avoid atexit handlers in child.
+ _exit(1);
+ } else {
+ if (pid == -1) {
+ *error_msg = StringPrintf("Failed to execv(%s) because fork failed: %s",
+ command_line.c_str(), strerror(errno));
+ return false;
+ }
+
+ // wait for subprocess to finish
+ int status;
+ pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
+ if (got_pid != pid) {
+ *error_msg = StringPrintf("Failed after fork for execv(%s) because waitpid failed: "
+ "wanted %d, got %d: %s",
+ command_line.c_str(), pid, got_pid, strerror(errno));
+ return false;
+ }
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+ *error_msg = StringPrintf("Failed execv(%s) because non-0 exit status",
+ command_line.c_str());
+ return false;
+ }
+ }
+ return true;
+}
+
+} // namespace installd
+} // namespace android
diff --git a/cmds/installd/otapreopt_utils.h b/cmds/installd/otapreopt_utils.h
index 436e554..03a6d87 100644
--- a/cmds/installd/otapreopt_utils.h
+++ b/cmds/installd/otapreopt_utils.h
@@ -18,6 +18,8 @@
#define OTAPREOPT_UTILS_H_
#include <regex>
+#include <string>
+#include <vector>
namespace android {
namespace installd {
@@ -28,6 +30,9 @@
return std::regex_match(input, slot_suffix_match, slot_suffix_regex);
}
+// Wrapper on fork/execv to run a command in a subprocess.
+bool Exec(const std::vector<std::string>& arg_vector, std::string* error_msg);
+
} // namespace installd
} // namespace android
diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp
index 739f33f..9c9db0f 100644
--- a/cmds/installd/tests/Android.bp
+++ b/cmds/installd/tests/Android.bp
@@ -28,6 +28,7 @@
"libbinder",
"libcrypto",
"libcutils",
+ "libprocessgroup",
"libselinux",
"libutils",
],
@@ -50,6 +51,7 @@
"libbinder",
"libcrypto",
"libcutils",
+ "libprocessgroup",
"libselinux",
"libutils",
],
@@ -72,6 +74,7 @@
"libbinder",
"libcrypto",
"libcutils",
+ "libprocessgroup",
"libselinux",
"libutils",
],
diff --git a/cmds/installd/tests/binder_test_utils.h b/cmds/installd/tests/binder_test_utils.h
new file mode 100644
index 0000000..efd1391
--- /dev/null
+++ b/cmds/installd/tests/binder_test_utils.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <binder/Status.h>
+#include <gtest/gtest.h>
+#include <utils/String8.h>
+
+#define ASSERT_BINDER_SUCCESS(expr) \
+ ({ \
+ binder::Status expect_status = (expr); \
+ ASSERT_TRUE(expect_status.isOk()) << expect_status.toString8().c_str(); \
+ expect_status; \
+ })
+#define ASSERT_BINDER_FAIL(expr) \
+ ({ \
+ binder::Status expect_status = (expr); \
+ ASSERT_FALSE(expect_status.isOk()); \
+ expect_status; \
+ })
+#define EXPECT_BINDER_SUCCESS(expr) \
+ ({ \
+ binder::Status expect_status = (expr); \
+ EXPECT_TRUE(expect_status.isOk()) << expect_status.toString8().c_str(); \
+ expect_status; \
+ })
+#define EXPECT_BINDER_FAIL(expr) \
+ ({ \
+ binder::Status expect_status = (expr); \
+ EXPECT_FALSE(expect_status.isOk()); \
+ expect_status; \
+ })
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index f216c53..e2afe1d 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -25,7 +25,7 @@
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
-
+#include <binder/Status.h>
#include <cutils/properties.h>
#include <gtest/gtest.h>
@@ -33,6 +33,7 @@
#include <selinux/android.h>
#include <selinux/avc.h>
+#include "binder_test_utils.h"
#include "dexopt.h"
#include "InstalldNativeService.h"
#include "globals.h"
@@ -143,6 +144,20 @@
"AAAACADojmFLPcugSwoBAAAUAgAACwAYAAAAAAAAAAAAoIEAAAAAY2xhc3Nlcy5kZXhVVAUAA/Ns"
"+ll1eAsAAQQj5QIABIgTAABQSwUGAAAAAAEAAQBRAAAATwEAAAAA";
+class DexoptTestEnvTest : public testing::Test {
+};
+
+TEST_F(DexoptTestEnvTest, CheckSelinux) {
+ ASSERT_EQ(1, is_selinux_enabled());
+
+ // Crude cutout for virtual devices.
+#if !defined(__i386__) && !defined(__x86_64__)
+ constexpr bool kIsX86 = false;
+#else
+ constexpr bool kIsX86 = true;
+#endif
+ ASSERT_TRUE(1 == security_getenforce() || kIsX86 || true /* b/119032200 */);
+}
class DexoptTest : public testing::Test {
protected:
@@ -437,11 +452,9 @@
std::unique_ptr<std::string> compilation_reason_ptr(new std::string("test-reason"));
bool prof_result;
- binder::Status prof_binder_result = service_->prepareAppProfile(
+ ASSERT_BINDER_SUCCESS(service_->prepareAppProfile(
package_name_, kTestUserId, kTestAppId, *profile_name_ptr, apk_path_,
- /*dex_metadata*/ nullptr, &prof_result);
-
- ASSERT_TRUE(prof_binder_result.isOk()) << prof_binder_result.toString8().c_str();
+ /*dex_metadata*/ nullptr, &prof_result));
ASSERT_TRUE(prof_result);
binder::Status result = service_->dexopt(apk_path_,
@@ -746,9 +759,8 @@
void createProfileSnapshot(int32_t appid, const std::string& package_name,
bool expected_result) {
bool result;
- binder::Status binder_result = service_->createProfileSnapshot(
- appid, package_name, kPrimaryProfile, apk_path_, &result);
- ASSERT_TRUE(binder_result.isOk()) << binder_result.toString8().c_str();
+ ASSERT_BINDER_SUCCESS(service_->createProfileSnapshot(
+ appid, package_name, kPrimaryProfile, apk_path_, &result));
ASSERT_EQ(expected_result, result);
if (!expected_result) {
@@ -788,9 +800,8 @@
const std::string& code_path,
bool expected_result) {
bool result;
- binder::Status binder_result = service_->mergeProfiles(
- kTestAppUid, package_name, code_path, &result);
- ASSERT_TRUE(binder_result.isOk()) << binder_result.toString8().c_str();
+ ASSERT_BINDER_SUCCESS(service_->mergeProfiles(
+ kTestAppUid, package_name, code_path, &result));
ASSERT_EQ(expected_result, result);
if (!expected_result) {
@@ -816,10 +827,9 @@
void preparePackageProfile(const std::string& package_name, const std::string& profile_name,
bool expected_result) {
bool result;
- binder::Status binder_result = service_->prepareAppProfile(
+ ASSERT_BINDER_SUCCESS(service_->prepareAppProfile(
package_name, kTestUserId, kTestAppId, profile_name, apk_path_,
- /*dex_metadata*/ nullptr, &result);
- ASSERT_TRUE(binder_result.isOk()) << binder_result.toString8().c_str();
+ /*dex_metadata*/ nullptr, &result));
ASSERT_EQ(expected_result, result);
if (!expected_result) {
@@ -905,8 +915,7 @@
SetupProfiles(/*setup_ref*/ true);
createProfileSnapshot(kTestAppId, package_name_, /*expected_result*/ true);
- binder::Status binder_result = service_->destroyProfileSnapshot(package_name_, kPrimaryProfile);
- ASSERT_TRUE(binder_result.isOk()) << binder_result.toString8().c_str();
+ ASSERT_BINDER_SUCCESS(service_->destroyProfileSnapshot(package_name_, kPrimaryProfile));
struct stat st;
ASSERT_EQ(-1, stat(snap_profile_.c_str(), &st));
ASSERT_EQ(ENOENT, errno);
@@ -964,7 +973,7 @@
ASSERT_EQ(0, chmod(ref_profile_dir.c_str(), 0700));
// Run createAppData again which will offer to fix-up the profile directories.
- ASSERT_TRUE(service_->createAppData(
+ ASSERT_BINDER_SUCCESS(service_->createAppData(
volume_uuid_,
package_name_,
kTestUserId,
@@ -972,7 +981,7 @@
kTestAppUid,
se_info_,
kOSdkVersion,
- &ce_data_inode_).isOk());
+ &ce_data_inode_));
// Check the file access.
CheckFileAccess(cur_profile_dir, kTestAppUid, kTestAppUid, 0700 | S_IFDIR);
@@ -1018,9 +1027,8 @@
void createBootImageProfileSnapshot(const std::string& classpath, bool expected_result) {
bool result;
- binder::Status binder_result = service_->createProfileSnapshot(
- -1, "android", "android.prof", classpath, &result);
- ASSERT_TRUE(binder_result.isOk());
+ ASSERT_BINDER_SUCCESS(service_->createProfileSnapshot(
+ -1, "android", "android.prof", classpath, &result));
ASSERT_EQ(expected_result, result);
if (!expected_result) {
diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp
index a5af5d7..cf7f1eb 100644
--- a/cmds/installd/tests/installd_service_test.cpp
+++ b/cmds/installd/tests/installd_service_test.cpp
@@ -15,16 +15,23 @@
*/
#include <sstream>
+#include <string>
+
+#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/statvfs.h>
#include <sys/xattr.h>
+#include <android-base/file.h>
#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/scopeguard.h>
#include <android-base/stringprintf.h>
#include <cutils/properties.h>
#include <gtest/gtest.h>
+#include "binder_test_utils.h"
#include "InstalldNativeService.h"
#include "dexopt.h"
#include "globals.h"
@@ -162,8 +169,8 @@
std::vector<uint8_t> result;
std::string dexPath = get_full_path("com.example/foo/file");
- EXPECT_TRUE(service->hashSecondaryDexFile(
- dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result).isOk());
+ EXPECT_BINDER_SUCCESS(service->hashSecondaryDexFile(
+ dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result));
EXPECT_EQ(result.size(), 32U);
@@ -182,8 +189,8 @@
std::vector<uint8_t> result;
std::string dexPath = get_full_path("com.example/foo/file");
- EXPECT_TRUE(service->hashSecondaryDexFile(
- dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result).isOk());
+ EXPECT_BINDER_SUCCESS(service->hashSecondaryDexFile(
+ dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result));
EXPECT_EQ(result.size(), 0U);
}
@@ -197,8 +204,8 @@
std::vector<uint8_t> result;
std::string dexPath = get_full_path("com.example/foo/file");
- EXPECT_TRUE(service->hashSecondaryDexFile(
- dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result).isOk());
+ EXPECT_BINDER_SUCCESS(service->hashSecondaryDexFile(
+ dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result));
EXPECT_EQ(result.size(), 0U);
}
@@ -212,8 +219,8 @@
std::vector<uint8_t> result;
std::string dexPath = get_full_path("com.example/foo/file");
- EXPECT_FALSE(service->hashSecondaryDexFile(
- dexPath, "com.wrong", 10000, testUuid, FLAG_STORAGE_CE, &result).isOk());
+ EXPECT_BINDER_FAIL(service->hashSecondaryDexFile(
+ dexPath, "com.wrong", 10000, testUuid, FLAG_STORAGE_CE, &result));
}
TEST_F(ServiceTest, CalculateOat) {
@@ -240,5 +247,472 @@
EXPECT_EQ("/data/dalvik-cache/isa/path@to@file.apk@classes.dex", std::string(buf));
}
+static bool mkdirs(const std::string& path, mode_t mode) {
+ struct stat sb;
+ if (stat(path.c_str(), &sb) != -1 && S_ISDIR(sb.st_mode)) {
+ return true;
+ }
+
+ if (!mkdirs(android::base::Dirname(path), mode)) {
+ return false;
+ }
+
+ return (::mkdir(path.c_str(), mode) != -1);
+}
+
+TEST_F(ServiceTest, CreateAppDataSnapshot) {
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
+
+ ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
+
+ auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
+ auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
+
+ ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
+ ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
+
+ auto deleter = [&rollback_ce_dir, &rollback_de_dir,
+ &fake_package_ce_path, &fake_package_de_path]() {
+ delete_dir_contents(rollback_ce_dir, true);
+ delete_dir_contents(rollback_de_dir, true);
+ delete_dir_contents(fake_package_ce_path, true);
+ delete_dir_contents(fake_package_de_path, true);
+ rmdir(rollback_ce_dir.c_str());
+ rmdir(rollback_de_dir.c_str());
+ };
+ auto scope_guard = android::base::make_scope_guard(deleter);
+
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "TEST_CONTENT_CE", fake_package_ce_path + "/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "TEST_CONTENT_DE", fake_package_de_path + "/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+
+ // Request a snapshot of the CE content but not the DE content.
+ int64_t ce_snapshot_inode;
+ ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
+ "com.foo", 0, FLAG_STORAGE_CE, &ce_snapshot_inode));
+ struct stat buf;
+ memset(&buf, 0, sizeof(buf));
+ ASSERT_EQ(0, stat((rollback_ce_dir + "/com.foo").c_str(), &buf));
+ ASSERT_EQ(ce_snapshot_inode, (int64_t) buf.st_ino);
+
+ std::string ce_content, de_content;
+ // At this point, we should have the CE content but not the DE content.
+ ASSERT_TRUE(android::base::ReadFileToString(
+ rollback_ce_dir + "/com.foo/file1", &ce_content, false /* follow_symlinks */));
+ ASSERT_FALSE(android::base::ReadFileToString(
+ rollback_de_dir + "/com.foo/file1", &de_content, false /* follow_symlinks */));
+ ASSERT_EQ("TEST_CONTENT_CE", ce_content);
+
+ // Modify the CE content, so we can assert later that it's reflected
+ // in the snapshot.
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "TEST_CONTENT_CE_MODIFIED", fake_package_ce_path + "/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+
+ // Request a snapshot of the DE content but not the CE content.
+ ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
+ "com.foo", 0, FLAG_STORAGE_DE, &ce_snapshot_inode));
+ // Only DE content snapshot was requested.
+ ASSERT_EQ(ce_snapshot_inode, 0);
+
+ // At this point, both the CE as well as the DE content should be fully
+ // populated.
+ ASSERT_TRUE(android::base::ReadFileToString(
+ rollback_ce_dir + "/com.foo/file1", &ce_content, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::ReadFileToString(
+ rollback_de_dir + "/com.foo/file1", &de_content, false /* follow_symlinks */));
+ ASSERT_EQ("TEST_CONTENT_CE", ce_content);
+ ASSERT_EQ("TEST_CONTENT_DE", de_content);
+
+ // Modify the DE content, so we can assert later that it's reflected
+ // in our final snapshot.
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "TEST_CONTENT_DE_MODIFIED", fake_package_de_path + "/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+
+ // Request a snapshot of both the CE as well as the DE content.
+ ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
+ "com.foo", 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
+
+ ASSERT_TRUE(android::base::ReadFileToString(
+ rollback_ce_dir + "/com.foo/file1", &ce_content, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::ReadFileToString(
+ rollback_de_dir + "/com.foo/file1", &de_content, false /* follow_symlinks */));
+ ASSERT_EQ("TEST_CONTENT_CE_MODIFIED", ce_content);
+ ASSERT_EQ("TEST_CONTENT_DE_MODIFIED", de_content);
+}
+
+TEST_F(ServiceTest, CreateAppDataSnapshot_AppDataAbsent) {
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
+
+ ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
+
+ auto deleter = [&rollback_ce_dir, &rollback_de_dir]() {
+ delete_dir_contents(rollback_ce_dir, true);
+ delete_dir_contents(rollback_de_dir, true);
+ rmdir(rollback_ce_dir.c_str());
+ rmdir(rollback_de_dir.c_str());
+ };
+
+ auto scope_guard = android::base::make_scope_guard(deleter);
+
+ int64_t ce_snapshot_inode;
+ ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
+ "com.foo", 0, FLAG_STORAGE_CE, &ce_snapshot_inode));
+ ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
+ "com.foo", 0, FLAG_STORAGE_DE, nullptr));
+ // No CE content snapshot was performed.
+ ASSERT_EQ(ce_snapshot_inode, 0);
+
+ // The snapshot calls must succeed but there should be no snapshot
+ // created.
+ struct stat sb;
+ ASSERT_EQ(-1, stat((rollback_ce_dir + "/com.foo").c_str(), &sb));
+ ASSERT_EQ(-1, stat((rollback_de_dir + "/com.foo").c_str(), &sb));
+}
+
+TEST_F(ServiceTest, CreateAppDataSnapshot_ClearsExistingSnapshot) {
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
+
+ ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
+
+ auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
+ auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
+
+ ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
+ ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
+
+ auto deleter = [&rollback_ce_dir, &rollback_de_dir,
+ &fake_package_ce_path, &fake_package_de_path]() {
+ delete_dir_contents(rollback_ce_dir, true);
+ delete_dir_contents(rollback_de_dir, true);
+ delete_dir_contents(fake_package_ce_path, true);
+ delete_dir_contents(fake_package_de_path, true);
+ rmdir(rollback_ce_dir.c_str());
+ rmdir(rollback_de_dir.c_str());
+ };
+ auto scope_guard = android::base::make_scope_guard(deleter);
+
+ // Simulate presence of an existing snapshot
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "TEST_CONTENT_CE", rollback_ce_dir + "/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "TEST_CONTENT_DE", rollback_de_dir + "/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+
+ // Create app data.
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "TEST_CONTENT_2_CE", fake_package_ce_path + "/file2",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "TEST_CONTENT_2_DE", fake_package_de_path + "/file2",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+
+ ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
+ "com.foo", 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
+
+ // Previous snapshot (with data for file1) must be cleared.
+ struct stat sb;
+ ASSERT_EQ(-1, stat((rollback_ce_dir + "/com.foo/file1").c_str(), &sb));
+ ASSERT_EQ(-1, stat((rollback_de_dir + "/com.foo/file1").c_str(), &sb));
+}
+
+TEST_F(ServiceTest, SnapshotAppData_WrongVolumeUuid) {
+ // Setup app data to make sure that fails due to wrong volumeUuid being
+ // passed, not because of some other reason.
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
+
+ ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
+
+ auto deleter = [&rollback_ce_dir, &rollback_de_dir]() {
+ delete_dir_contents(rollback_ce_dir, true);
+ delete_dir_contents(rollback_de_dir, true);
+ rmdir(rollback_ce_dir.c_str());
+ rmdir(rollback_de_dir.c_str());
+ };
+ auto scope_guard = android::base::make_scope_guard(deleter);
+
+ EXPECT_BINDER_FAIL(service->snapshotAppData(std::make_unique<std::string>("FOO"),
+ "com.foo", 0, FLAG_STORAGE_DE, nullptr));
+}
+
+TEST_F(ServiceTest, CreateAppDataSnapshot_ClearsCache) {
+ auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
+ auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
+ auto fake_package_ce_cache_path = read_path_inode(fake_package_ce_path,
+ "cache", kXattrInodeCache);
+ auto fake_package_ce_code_cache_path = read_path_inode(fake_package_ce_path,
+ "code_cache", kXattrInodeCache);
+ auto fake_package_de_cache_path = fake_package_de_path + "/cache";
+ auto fake_package_de_code_cache_path = fake_package_de_path + "/code_cache";
+
+ ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
+ ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
+ ASSERT_TRUE(mkdirs(fake_package_ce_cache_path, 700));
+ ASSERT_TRUE(mkdirs(fake_package_ce_code_cache_path, 700));
+ ASSERT_TRUE(mkdirs(fake_package_de_cache_path, 700));
+ ASSERT_TRUE(mkdirs(fake_package_de_code_cache_path, 700));
+
+ auto deleter = [&fake_package_ce_path, &fake_package_de_path,
+ &fake_package_ce_cache_path, &fake_package_ce_code_cache_path,
+ &fake_package_de_cache_path, &fake_package_de_code_cache_path]() {
+ delete_dir_contents(fake_package_ce_path, true);
+ delete_dir_contents(fake_package_de_path, true);
+ delete_dir_contents(fake_package_ce_cache_path, true);
+ delete_dir_contents(fake_package_ce_code_cache_path, true);
+ delete_dir_contents(fake_package_de_cache_path, true);
+ delete_dir_contents(fake_package_de_code_cache_path, true);
+ rmdir(fake_package_ce_cache_path.c_str());
+ rmdir(fake_package_ce_code_cache_path.c_str());
+ rmdir(fake_package_de_cache_path.c_str());
+ rmdir(fake_package_de_code_cache_path.c_str());
+ };
+ auto scope_guard = android::base::make_scope_guard(deleter);
+
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "TEST_CONTENT_CE", fake_package_ce_cache_path + "/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "TEST_CONTENT_CE", fake_package_ce_code_cache_path + "/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "TEST_CONTENT_DE", fake_package_de_cache_path + "/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "TEST_CONTENT_DE", fake_package_de_code_cache_path + "/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+ ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
+ "com.foo", 0, FLAG_STORAGE_CE | FLAG_STORAGE_DE, nullptr));
+ // The snapshot call must clear cache.
+ struct stat sb;
+ ASSERT_EQ(-1, stat((fake_package_ce_cache_path + "/file1").c_str(), &sb));
+ ASSERT_EQ(-1, stat((fake_package_ce_code_cache_path + "/file1").c_str(), &sb));
+ ASSERT_EQ(-1, stat((fake_package_de_cache_path + "/file1").c_str(), &sb));
+ ASSERT_EQ(-1, stat((fake_package_de_code_cache_path + "/file1").c_str(), &sb));
+}
+
+TEST_F(ServiceTest, RestoreAppDataSnapshot) {
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
+
+ ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
+
+ auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
+ auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
+
+ ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
+ ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
+
+ auto deleter = [&rollback_ce_dir, &rollback_de_dir,
+ &fake_package_ce_path, &fake_package_de_path]() {
+ delete_dir_contents(rollback_ce_dir, true);
+ delete_dir_contents(rollback_de_dir, true);
+ delete_dir_contents(fake_package_ce_path, true);
+ delete_dir_contents(fake_package_de_path, true);
+ rmdir(rollback_ce_dir.c_str());
+ rmdir(rollback_de_dir.c_str());
+ };
+ auto scope_guard = android::base::make_scope_guard(deleter);
+
+ // Write contents to the rollback location. We'll write the same files to the
+ // app data location and make sure the restore has overwritten them.
+ ASSERT_TRUE(mkdirs(rollback_ce_dir + "/com.foo/", 700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir + "/com.foo/", 700));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "CE_RESTORE_CONTENT", rollback_ce_dir + "/com.foo/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "DE_RESTORE_CONTENT", rollback_de_dir + "/com.foo/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "TEST_CONTENT_CE", fake_package_ce_path + "/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "TEST_CONTENT_DE", fake_package_de_path + "/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+
+ ASSERT_BINDER_SUCCESS(service->restoreAppDataSnapshot(std::make_unique<std::string>("TEST"),
+ "com.foo", 10000, -1, "", 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE));
+
+ std::string ce_content, de_content;
+ ASSERT_TRUE(android::base::ReadFileToString(
+ fake_package_ce_path + "/file1", &ce_content, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::ReadFileToString(
+ fake_package_de_path + "/file1", &de_content, false /* follow_symlinks */));
+ ASSERT_EQ("CE_RESTORE_CONTENT", ce_content);
+ ASSERT_EQ("DE_RESTORE_CONTENT", de_content);
+}
+
+TEST_F(ServiceTest, CreateSnapshotThenDestroyIt) {
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
+
+ ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
+
+ auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
+ auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
+
+ ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
+ ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
+
+ auto deleter = [&rollback_ce_dir, &rollback_de_dir,
+ &fake_package_ce_path, &fake_package_de_path]() {
+ delete_dir_contents(rollback_ce_dir, true);
+ delete_dir_contents(rollback_de_dir, true);
+ delete_dir_contents(fake_package_ce_path, true);
+ delete_dir_contents(fake_package_de_path, true);
+ rmdir(rollback_ce_dir.c_str());
+ rmdir(rollback_de_dir.c_str());
+ };
+ auto scope_guard = android::base::make_scope_guard(deleter);
+
+ // Prepare data for snapshot.
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "TEST_CONTENT_CE", fake_package_ce_path + "/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "TEST_CONTENT_DE", fake_package_de_path + "/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+
+ int64_t ce_snapshot_inode;
+ // Request a snapshot of both the CE as well as the DE content.
+ ASSERT_TRUE(service->snapshotAppData(std::make_unique<std::string>("TEST"),
+ "com.foo", 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE, &ce_snapshot_inode).isOk());
+ // Because CE data snapshot was requested, ce_snapshot_inode can't be null.
+ ASSERT_NE(0, ce_snapshot_inode);
+ // Check snapshot is there.
+ struct stat sb;
+ ASSERT_EQ(0, stat((rollback_ce_dir + "/com.foo").c_str(), &sb));
+ ASSERT_EQ(0, stat((rollback_de_dir + "/com.foo").c_str(), &sb));
+
+
+ ASSERT_TRUE(service->destroyAppDataSnapshot(std::make_unique<std::string>("TEST"),
+ "com.foo", 0, ce_snapshot_inode, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
+ // Check snapshot is deleted.
+ ASSERT_EQ(-1, stat((rollback_ce_dir + "/com.foo").c_str(), &sb));
+ ASSERT_EQ(-1, stat((rollback_de_dir + "/com.foo").c_str(), &sb));
+}
+
+TEST_F(ServiceTest, DestroyAppDataSnapshot_CeSnapshotInodeIsZero) {
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
+
+ ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
+
+ auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
+ auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
+
+ ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
+ ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
+
+ auto deleter = [&rollback_ce_dir, &rollback_de_dir,
+ &fake_package_ce_path, &fake_package_de_path]() {
+ delete_dir_contents(rollback_ce_dir, true);
+ delete_dir_contents(rollback_de_dir, true);
+ delete_dir_contents(fake_package_ce_path, true);
+ delete_dir_contents(fake_package_de_path, true);
+ rmdir(rollback_ce_dir.c_str());
+ rmdir(rollback_de_dir.c_str());
+ };
+ auto scope_guard = android::base::make_scope_guard(deleter);
+
+ // Create a snapshot
+ ASSERT_TRUE(mkdirs(rollback_ce_dir + "/com.foo/", 700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir + "/com.foo/", 700));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "CE_RESTORE_CONTENT", rollback_ce_dir + "/com.foo/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "DE_RESTORE_CONTENT", rollback_de_dir + "/com.foo/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+
+ ASSERT_TRUE(service->destroyAppDataSnapshot(std::make_unique<std::string>("TEST"),
+ "com.foo", 0, 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
+
+ // Check snapshot is deleted.
+ struct stat sb;
+ ASSERT_EQ(-1, stat((rollback_ce_dir + "/com.foo").c_str(), &sb));
+ ASSERT_EQ(-1, stat((rollback_de_dir + "/com.foo").c_str(), &sb));
+
+ // Check that deleting already deleted snapshot is no-op.
+ ASSERT_TRUE(service->destroyAppDataSnapshot(std::make_unique<std::string>("TEST"),
+ "com.foo", 0, 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
+}
+
+TEST_F(ServiceTest, DestroyAppDataSnapshot_WrongVolumeUuid) {
+ // Setup rollback data to make sure that test fails due to wrong volumeUuid
+ // being passed, not because of some other reason.
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
+
+ ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
+
+ auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
+ auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
+
+ ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
+ ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
+
+ auto deleter = [&rollback_ce_dir, &rollback_de_dir,
+ &fake_package_ce_path, &fake_package_de_path]() {
+ delete_dir_contents(rollback_ce_dir, true);
+ delete_dir_contents(rollback_de_dir, true);
+ delete_dir_contents(fake_package_ce_path, true);
+ delete_dir_contents(fake_package_de_path, true);
+ rmdir(rollback_ce_dir.c_str());
+ rmdir(rollback_de_dir.c_str());
+ };
+ auto scope_guard = android::base::make_scope_guard(deleter);
+
+ ASSERT_FALSE(service->destroyAppDataSnapshot(std::make_unique<std::string>("BAR"),
+ "com.foo", 0, 0, FLAG_STORAGE_DE).isOk());
+}
+
+TEST_F(ServiceTest, RestoreAppDataSnapshot_WrongVolumeUuid) {
+ // Setup rollback data to make sure that fails due to wrong volumeUuid being
+ // passed, not because of some other reason.
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
+
+ ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
+
+ auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
+ auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
+
+ ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
+ ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
+
+ auto deleter = [&rollback_ce_dir, &rollback_de_dir,
+ &fake_package_ce_path, &fake_package_de_path]() {
+ delete_dir_contents(rollback_ce_dir, true);
+ delete_dir_contents(rollback_de_dir, true);
+ delete_dir_contents(fake_package_ce_path, true);
+ delete_dir_contents(fake_package_de_path, true);
+ rmdir(rollback_ce_dir.c_str());
+ rmdir(rollback_de_dir.c_str());
+ };
+ auto scope_guard = android::base::make_scope_guard(deleter);
+
+ EXPECT_BINDER_FAIL(service->restoreAppDataSnapshot(std::make_unique<std::string>("BAR"),
+ "com.foo", 10000, -1, "", 0, FLAG_STORAGE_DE));
+}
+
} // namespace installd
} // namespace android
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index ad7a5ae..1782aa2 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -18,6 +18,7 @@
#include <string.h>
#include <android-base/logging.h>
+#include <android-base/scopeguard.h>
#include <gtest/gtest.h>
#include "InstalldNativeService.h"
@@ -544,5 +545,58 @@
EXPECT_EQ(0, MatchExtension("docx"));
}
+TEST_F(UtilsTest, TestRollbackPaths) {
+ EXPECT_EQ("/data/misc_ce/0/rollback/com.foo",
+ create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo"));
+ EXPECT_EQ("/data/misc_ce/10/rollback/com.foo",
+ create_data_misc_ce_rollback_package_path(nullptr, 10, "com.foo"));
+
+ EXPECT_EQ("/data/misc_de/0/rollback/com.foo",
+ create_data_misc_de_rollback_package_path(nullptr, 0, "com.foo"));
+ EXPECT_EQ("/data/misc_de/10/rollback/com.foo",
+ create_data_misc_de_rollback_package_path(nullptr, 10, "com.foo"));
+
+ EXPECT_EQ("/data/misc_ce/0/rollback",
+ create_data_misc_ce_rollback_path(nullptr, 0));
+ EXPECT_EQ("/data/misc_ce/10/rollback",
+ create_data_misc_ce_rollback_path(nullptr, 10));
+
+ EXPECT_EQ("/data/misc_de/0/rollback",
+ create_data_misc_de_rollback_path(nullptr, 0));
+ EXPECT_EQ("/data/misc_de/10/rollback",
+ create_data_misc_de_rollback_path(nullptr, 10));
+
+ EXPECT_EQ("/data/misc_ce/0/rollback/com.foo",
+ create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo", 0));
+ EXPECT_EQ("/data/misc_ce/0/rollback/com.foo",
+ create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo", 239));
+
+ auto rollback_ce_package_path = create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo");
+ auto deleter = [&rollback_ce_package_path]() {
+ delete_dir_contents_and_dir(rollback_ce_package_path, true /* ignore_if_missing */);
+ };
+ auto scope_guard = android::base::make_scope_guard(deleter);
+
+ ASSERT_NE(-1, mkdir(rollback_ce_package_path.c_str(), 700));
+
+ ino_t ce_data_inode;
+ ASSERT_EQ(0, get_path_inode(rollback_ce_package_path, &ce_data_inode));
+
+ EXPECT_EQ("/data/misc_ce/0/rollback/com.foo",
+ create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo", ce_data_inode));
+ // Check that path defined by inode is picked even if it's not the same as
+ // the fallback one.
+ EXPECT_EQ("/data/misc_ce/0/rollback/com.foo",
+ create_data_misc_ce_rollback_package_path(nullptr, 0, "com.bar", ce_data_inode));
+
+ // These last couple of cases are never exercised in production because we
+ // only snapshot apps in the primary data partition. Exercise them here for
+ // the sake of completeness.
+ EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/misc_ce/0/rollback/com.example",
+ create_data_misc_ce_rollback_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example"));
+ EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/misc_de/0/rollback/com.example",
+ create_data_misc_de_rollback_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example"));
+}
+
} // namespace installd
} // namespace android
diff --git a/cmds/installd/tests/test_utils.h b/cmds/installd/tests/test_utils.h
index a7ef674..70eefe2 100644
--- a/cmds/installd/tests/test_utils.h
+++ b/cmds/installd/tests/test_utils.h
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) 2017 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 <stdlib.h>
#include <string.h>
#include <sys/capability.h>
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 6b9cf0d..5b487bb 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -20,6 +20,7 @@
#include <fcntl.h>
#include <fts.h>
#include <stdlib.h>
+#include <sys/capability.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/xattr.h>
@@ -34,6 +35,7 @@
#include <log/log.h>
#include <private/android_filesystem_config.h>
+#include "dexopt_return_codes.h"
#include "globals.h" // extern variables.
#ifndef LOG_TAG
@@ -43,6 +45,7 @@
#define DEBUG_XATTRS 0
using android::base::EndsWith;
+using android::base::Fdopendir;
using android::base::StringPrintf;
using android::base::unique_fd;
@@ -67,6 +70,35 @@
CHECK(is_valid_package_name(package_name));
}
+static std::string resolve_ce_path_by_inode_or_fallback(const std::string& root_path,
+ ino_t ce_data_inode, const std::string& fallback) {
+ if (ce_data_inode != 0) {
+ DIR* dir = opendir(root_path.c_str());
+ if (dir == nullptr) {
+ PLOG(ERROR) << "Failed to opendir " << root_path;
+ return fallback;
+ }
+
+ struct dirent* ent;
+ while ((ent = readdir(dir))) {
+ if (ent->d_ino == ce_data_inode) {
+ auto resolved = StringPrintf("%s/%s", root_path.c_str(), ent->d_name);
+ if (resolved != fallback) {
+ LOG(DEBUG) << "Resolved path " << resolved << " for inode " << ce_data_inode
+ << " instead of " << fallback;
+ }
+ closedir(dir);
+ return resolved;
+ }
+ }
+ LOG(WARNING) << "Failed to resolve inode " << ce_data_inode << "; using " << fallback;
+ closedir(dir);
+ return fallback;
+ } else {
+ return fallback;
+ }
+}
+
/**
* Create the path name where package app contents should be stored for
* the given volume UUID and package name. An empty UUID is assumed to
@@ -110,34 +142,8 @@
// For testing purposes, rely on the inode when defined; this could be
// optimized to use access() in the future.
auto fallback = create_data_user_ce_package_path(volume_uuid, user, package_name);
- if (ce_data_inode != 0) {
- auto user_path = create_data_user_ce_path(volume_uuid, user);
- DIR* dir = opendir(user_path.c_str());
- if (dir == nullptr) {
- PLOG(ERROR) << "Failed to opendir " << user_path;
- return fallback;
- }
-
- struct dirent* ent;
- while ((ent = readdir(dir))) {
- if (ent->d_ino == ce_data_inode) {
- auto resolved = StringPrintf("%s/%s", user_path.c_str(), ent->d_name);
-#if DEBUG_XATTRS
- if (resolved != fallback) {
- LOG(DEBUG) << "Resolved path " << resolved << " for inode " << ce_data_inode
- << " instead of " << fallback;
- }
-#endif
- closedir(dir);
- return resolved;
- }
- }
- LOG(WARNING) << "Failed to resolve inode " << ce_data_inode << "; using " << fallback;
- closedir(dir);
- return fallback;
- } else {
- return fallback;
- }
+ auto user_path = create_data_user_ce_path(volume_uuid, user);
+ return resolve_ce_path_by_inode_or_fallback(user_path, ce_data_inode, fallback);
}
std::string create_data_user_de_package_path(const char* volume_uuid,
@@ -191,6 +197,34 @@
return StringPrintf("%s/user_de/%u", data.c_str(), userid);
}
+
+std::string create_data_misc_ce_rollback_path(const char* volume_uuid, userid_t user) {
+ return StringPrintf("%s/misc_ce/%u/rollback", create_data_path(volume_uuid).c_str(), user);
+}
+
+std::string create_data_misc_de_rollback_path(const char* volume_uuid, userid_t user) {
+ return StringPrintf("%s/misc_de/%u/rollback", create_data_path(volume_uuid).c_str(), user);
+}
+
+std::string create_data_misc_ce_rollback_package_path(const char* volume_uuid,
+ userid_t user, const char* package_name) {
+ return StringPrintf("%s/%s",
+ create_data_misc_ce_rollback_path(volume_uuid, user).c_str(), package_name);
+}
+
+std::string create_data_misc_ce_rollback_package_path(const char* volume_uuid,
+ userid_t user, const char* package_name, ino_t ce_rollback_inode) {
+ auto fallback = create_data_misc_ce_rollback_package_path(volume_uuid, user, package_name);
+ auto user_path = create_data_misc_ce_rollback_path(volume_uuid, user);
+ return resolve_ce_path_by_inode_or_fallback(user_path, ce_rollback_inode, fallback);
+}
+
+std::string create_data_misc_de_rollback_package_path(const char* volume_uuid,
+ userid_t user, const char* package_name) {
+ return StringPrintf("%s/%s",
+ create_data_misc_de_rollback_path(volume_uuid, user).c_str(), package_name);
+}
+
/**
* Create the path name for media for a certain userid.
*/
@@ -1036,7 +1070,7 @@
continue;
}
- DIR* subdir = fdopendir(subdir_fd);
+ DIR* subdir = Fdopendir(std::move(subdir_fd));
if (subdir == nullptr) {
PLOG(WARNING) << "Could not open dir path " << local_path;
result = false;
@@ -1062,5 +1096,26 @@
}
}
+void drop_capabilities(uid_t uid) {
+ if (setgid(uid) != 0) {
+ PLOG(ERROR) << "setgid(" << uid << ") failed in installd during dexopt";
+ exit(DexoptReturnCodes::kSetGid);
+ }
+ if (setuid(uid) != 0) {
+ PLOG(ERROR) << "setuid(" << uid << ") failed in installd during dexopt";
+ exit(DexoptReturnCodes::kSetUid);
+ }
+ // drop capabilities
+ struct __user_cap_header_struct capheader;
+ struct __user_cap_data_struct capdata[2];
+ memset(&capheader, 0, sizeof(capheader));
+ memset(&capdata, 0, sizeof(capdata));
+ capheader.version = _LINUX_CAPABILITY_VERSION_3;
+ if (capset(&capheader, &capdata[0]) < 0) {
+ PLOG(ERROR) << "capset failed";
+ exit(DexoptReturnCodes::kCapSet);
+ }
+}
+
} // namespace installd
} // namespace android
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index d05724a..5d3a97d 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -61,6 +61,15 @@
std::string create_data_user_ce_package_path_as_user_link(
const char* volume_uuid, userid_t userid, const char* package_name);
+std::string create_data_misc_ce_rollback_path(const char* volume_uuid, userid_t user);
+std::string create_data_misc_de_rollback_path(const char* volume_uuid, userid_t user);
+std::string create_data_misc_ce_rollback_package_path(const char* volume_uuid,
+ userid_t user, const char* package_name);
+std::string create_data_misc_ce_rollback_package_path(const char* volume_uuid,
+ userid_t user, const char* package_name, ino_t ce_rollback_inode);
+std::string create_data_misc_de_rollback_package_path(const char* volume_uuid,
+ userid_t user, const char* package_name);
+
std::string create_data_media_path(const char* volume_uuid, userid_t userid);
std::string create_data_media_obb_path(const char* volume_uuid, const char* package_name);
std::string create_data_media_package_path(const char* volume_uuid, userid_t userid,
@@ -140,6 +149,8 @@
// It returns true if there were no errors at all, and false otherwise.
bool collect_profiles(std::vector<std::string>* profiles_paths);
+void drop_capabilities(uid_t uid);
+
} // namespace installd
} // namespace android
diff --git a/cmds/installd/view_compiler.cpp b/cmds/installd/view_compiler.cpp
new file mode 100644
index 0000000..f1ac717
--- /dev/null
+++ b/cmds/installd/view_compiler.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "view_compiler.h"
+
+#include <string>
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "utils.h"
+
+#include "android-base/logging.h"
+#include "android-base/stringprintf.h"
+#include "android-base/unique_fd.h"
+
+namespace android {
+namespace installd {
+
+using base::unique_fd;
+
+bool view_compiler(const char* apk_path, const char* package_name, const char* out_dex_file,
+ int uid) {
+ CHECK(apk_path != nullptr);
+ CHECK(package_name != nullptr);
+ CHECK(out_dex_file != nullptr);
+
+ // viewcompiler won't have permission to open anything, so we have to open the files first
+ // and pass file descriptors.
+
+ // Open input file
+ unique_fd infd{open(apk_path, 0)};
+ if (infd.get() < 0) {
+ PLOG(ERROR) << "Could not open input file: " << apk_path;
+ return false;
+ }
+
+ // Set up output file. viewcompiler can't open outputs by fd, but it can write to stdout, so
+ // we close stdout and open it towards the right output.
+ unique_fd outfd{open(out_dex_file, O_CREAT | O_TRUNC | O_WRONLY, 0644)};
+ if (outfd.get() < 0) {
+ PLOG(ERROR) << "Could not open output file: " << out_dex_file;
+ return false;
+ }
+ if (fchmod(outfd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) != 0) {
+ PLOG(ERROR) << "Could not change output file permissions";
+ return false;
+ }
+ if (close(STDOUT_FILENO) != 0) {
+ PLOG(ERROR) << "Could not close stdout";
+ return false;
+ }
+ if (dup2(outfd, STDOUT_FILENO) < 0) {
+ PLOG(ERROR) << "Could not duplicate output file descriptor";
+ return false;
+ }
+
+ // Prepare command line arguments for viewcompiler
+ std::string args[] = {"/system/bin/viewcompiler",
+ "--apk",
+ "--infd",
+ android::base::StringPrintf("%d", infd.get()),
+ "--dex",
+ "--package",
+ package_name};
+ char* const argv[] = {const_cast<char*>(args[0].c_str()), const_cast<char*>(args[1].c_str()),
+ const_cast<char*>(args[2].c_str()), const_cast<char*>(args[3].c_str()),
+ const_cast<char*>(args[4].c_str()), const_cast<char*>(args[5].c_str()),
+ const_cast<char*>(args[6].c_str()), nullptr};
+
+ pid_t pid = fork();
+ if (pid == 0) {
+ // Now that we've opened the files we need, drop privileges.
+ drop_capabilities(uid);
+ execv("/system/bin/viewcompiler", argv);
+ _exit(1);
+ }
+
+ return wait_child(pid) == 0;
+}
+
+} // namespace installd
+} // namespace android
\ No newline at end of file
diff --git a/cmds/installd/view_compiler.h b/cmds/installd/view_compiler.h
new file mode 100644
index 0000000..f7c6e57
--- /dev/null
+++ b/cmds/installd/view_compiler.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef VIEW_COMPILER_H_
+#define VIEW_COMPILER_H_
+
+namespace android {
+namespace installd {
+
+bool view_compiler(const char* apk_path, const char* package_name, const char* out_dex_file,
+ int uid);
+
+} // namespace installd
+} // namespace android
+
+#endif // VIEW_COMPILER_H_
\ No newline at end of file
diff --git a/cmds/lshal/Command.h b/cmds/lshal/Command.h
index 4f128ab..e19e3f7 100644
--- a/cmds/lshal/Command.h
+++ b/cmds/lshal/Command.h
@@ -27,7 +27,7 @@
// Base class for all *Commands
class Command {
public:
- Command(Lshal& lshal) : mLshal(lshal) {}
+ explicit Command(Lshal& lshal) : mLshal(lshal) {}
virtual ~Command() = default;
// Expect optind to be set by Lshal::main and points to the next argument
// to process.
diff --git a/cmds/lshal/DebugCommand.h b/cmds/lshal/DebugCommand.h
index 6e12008..3c3f56f 100644
--- a/cmds/lshal/DebugCommand.h
+++ b/cmds/lshal/DebugCommand.h
@@ -31,7 +31,7 @@
class DebugCommand : public Command {
public:
- DebugCommand(Lshal &lshal) : Command(lshal) {}
+ explicit DebugCommand(Lshal &lshal) : Command(lshal) {}
~DebugCommand() = default;
Status main(const Arg &arg) override;
void usage() const override;
diff --git a/cmds/lshal/HelpCommand.h b/cmds/lshal/HelpCommand.h
index cc709f8..da0cba6 100644
--- a/cmds/lshal/HelpCommand.h
+++ b/cmds/lshal/HelpCommand.h
@@ -31,7 +31,7 @@
class HelpCommand : public Command {
public:
- HelpCommand(Lshal &lshal) : Command(lshal) {}
+ explicit HelpCommand(Lshal &lshal) : Command(lshal) {}
~HelpCommand() = default;
Status main(const Arg &arg) override;
void usage() const override;
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index a6d7a78..c706d91 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -376,23 +376,23 @@
}
mServicesTable.setDescription(
- "All binderized services (registered services through hwservicemanager)");
+ "| All binderized services (registered with hwservicemanager)");
mPassthroughRefTable.setDescription(
- "All interfaces that getService() has ever return as a passthrough interface;\n"
- "PIDs / processes shown below might be inaccurate because the process\n"
- "might have relinquished the interface or might have died.\n"
- "The Server / Server CMD column can be ignored.\n"
- "The Clients / Clients CMD column shows all process that have ever dlopen'ed \n"
- "the library and successfully fetched the passthrough implementation.");
+ "| All interfaces that getService() has ever returned as a passthrough interface;\n"
+ "| PIDs / processes shown below might be inaccurate because the process\n"
+ "| might have relinquished the interface or might have died.\n"
+ "| The Server / Server CMD column can be ignored.\n"
+ "| The Clients / Clients CMD column shows all process that have ever dlopen'ed \n"
+ "| the library and successfully fetched the passthrough implementation.");
mImplementationsTable.setDescription(
- "All available passthrough implementations (all -impl.so files).\n"
- "These may return subclasses through their respective HIDL_FETCH_I* functions.");
+ "| 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.");
+ "| 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.");
+ "| 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.");
}
bool ListCommand::addEntryWithInstance(const TableEntry& entry,
@@ -972,10 +972,10 @@
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"});
+ " - DM: if the HAL is in the device manifest\n"
+ " - DC: if the HAL is in the device compatibility matrix\n"
+ " - FM: if the HAL is in the framework manifest\n"
+ " - FC: if the HAL is in the 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;
@@ -1054,7 +1054,7 @@
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`."});
+ "passthrough_libs), (v|vintf), and (z|lazy).\nDefault is `bcl`."});
}
// Create 'longopts' argument to getopt_long. Caller is responsible for maintaining
@@ -1150,7 +1150,7 @@
}
if (mSelectedColumns.empty()) {
- mSelectedColumns = {TableColumnType::RELEASED,
+ mSelectedColumns = {TableColumnType::VINTF, TableColumnType::RELEASED,
TableColumnType::INTERFACE_NAME, TableColumnType::THREADS,
TableColumnType::SERVER_PID, TableColumnType::CLIENT_PIDS};
}
@@ -1210,7 +1210,7 @@
err() << "list:" << std::endl
<< " lshal" << std::endl
<< " lshal list" << std::endl
- << " List all hals with default ordering and columns (`lshal list -liepc`)" << std::endl
+ << " List all hals with default ordering and columns (`lshal list -Vliepc`)" << 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;
diff --git a/cmds/lshal/ListCommand.h b/cmds/lshal/ListCommand.h
index 3f7321d..85195fc 100644
--- a/cmds/lshal/ListCommand.h
+++ b/cmds/lshal/ListCommand.h
@@ -57,7 +57,7 @@
class ListCommand : public Command {
public:
- ListCommand(Lshal &lshal) : Command(lshal) {}
+ explicit ListCommand(Lshal &lshal) : Command(lshal) {}
virtual ~ListCommand() = default;
Status main(const Arg &arg) override;
void usage() const override;
diff --git a/cmds/lshal/NullableOStream.h b/cmds/lshal/NullableOStream.h
index ab37a04..737d3a2 100644
--- a/cmds/lshal/NullableOStream.h
+++ b/cmds/lshal/NullableOStream.h
@@ -25,8 +25,8 @@
template<typename S>
class NullableOStream {
public:
- NullableOStream(S &os) : mOs(&os) {}
- NullableOStream(S *os) : mOs(os) {}
+ explicit NullableOStream(S &os) : mOs(&os) {}
+ explicit NullableOStream(S *os) : mOs(os) {}
NullableOStream &operator=(S &os) {
mOs = &os;
return *this;
@@ -57,7 +57,7 @@
S& buf() const {
return *mOs;
}
- operator bool() const {
+ operator bool() const { // NOLINT(google-explicit-constructor)
return mOs != nullptr;
}
private:
diff --git a/cmds/lshal/OWNERS b/cmds/lshal/OWNERS
new file mode 100644
index 0000000..60038da
--- /dev/null
+++ b/cmds/lshal/OWNERS
@@ -0,0 +1,2 @@
+elsk@google.com
+smoreland@google.com
diff --git a/cmds/lshal/TableEntry.h b/cmds/lshal/TableEntry.h
index 7294b0a..601b7e2 100644
--- a/cmds/lshal/TableEntry.h
+++ b/cmds/lshal/TableEntry.h
@@ -149,7 +149,7 @@
class MergedTable {
public:
- MergedTable(std::vector<const Table*>&& tables) : mTables(std::move(tables)) {}
+ explicit MergedTable(std::vector<const Table*>&& tables) : mTables(std::move(tables)) {}
TextTable createTextTable();
private:
std::vector<const Table*> mTables;
diff --git a/cmds/lshal/TextTable.h b/cmds/lshal/TextTable.h
index 91d522a..301b4bd 100644
--- a/cmds/lshal/TextTable.h
+++ b/cmds/lshal/TextTable.h
@@ -33,11 +33,11 @@
TextTableRow() {}
// A row of cells.
- TextTableRow(std::vector<std::string>&& v) : mFields(std::move(v)) {}
+ explicit TextTableRow(std::vector<std::string>&& v) : mFields(std::move(v)) {}
// A single comment string.
- TextTableRow(std::string&& s) : mLine(std::move(s)) {}
- TextTableRow(const std::string& s) : mLine(s) {}
+ explicit TextTableRow(std::string&& s) : mLine(std::move(s)) {}
+ explicit TextTableRow(const std::string& s) : mLine(s) {}
// Whether this row is an actual row of cells.
bool isRow() const { return !fields().empty(); }
diff --git a/cmds/lshal/Timeout.h b/cmds/lshal/Timeout.h
index 58119a6..46d8177 100644
--- a/cmds/lshal/Timeout.h
+++ b/cmds/lshal/Timeout.h
@@ -29,7 +29,7 @@
class BackgroundTaskState {
public:
- BackgroundTaskState(std::function<void(void)> &&func)
+ explicit BackgroundTaskState(std::function<void(void)> &&func)
: mFunc(std::forward<decltype(func)>(func)) {}
void notify() {
std::unique_lock<std::mutex> lock(mMutex);
diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp
index 8d7405b..fc8d58b 100644
--- a/cmds/lshal/test.cpp
+++ b/cmds/lshal/test.cpp
@@ -191,7 +191,7 @@
// expose protected fields and methods for ListCommand
class MockListCommand : public ListCommand {
public:
- MockListCommand(Lshal* lshal) : ListCommand(*lshal) {}
+ explicit MockListCommand(Lshal* lshal) : ListCommand(*lshal) {}
Status parseArgs(const Arg& arg) { return ListCommand::parseArgs(arg); }
Status main(const Arg& arg) { return ListCommand::main(arg); }
@@ -308,7 +308,7 @@
// Fake service returned by mocked IServiceManager::get.
class TestService : public IBase {
public:
- TestService(pid_t id) : mId(id) {}
+ explicit TestService(pid_t id) : mId(id) {}
hardware::Return<void> getDebugInfo(getDebugInfo_cb cb) override {
cb({ mId /* pid */, getPtr(mId), DebugInfo::Architecture::IS_64BIT });
return hardware::Void();
diff --git a/cmds/rss_hwm_reset/Android.bp b/cmds/rss_hwm_reset/Android.bp
new file mode 100644
index 0000000..15f10ef
--- /dev/null
+++ b/cmds/rss_hwm_reset/Android.bp
@@ -0,0 +1,28 @@
+// 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
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_binary {
+ name: "rss_hwm_reset",
+
+ srcs: [
+ "rss_hwm_reset.cc",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "liblog",
+ ],
+
+ init_rc: ["rss_hwm_reset.rc"],
+}
diff --git a/cmds/rss_hwm_reset/rss_hwm_reset.cc b/cmds/rss_hwm_reset/rss_hwm_reset.cc
new file mode 100644
index 0000000..1626e7e
--- /dev/null
+++ b/cmds/rss_hwm_reset/rss_hwm_reset.cc
@@ -0,0 +1,72 @@
+/*
+ * 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
+ *
+ * https://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.
+ */
+
+ /*
+ * rss_hwm_reset clears the RSS high-water mark counters for all currently
+ * running processes. It writes "5" to /proc/PID/clear_refs for every PID.
+ *
+ * It runs in its own process becuase dac_override capability is required
+ * in order to write to other processes' clear_refs.
+ *
+ * It is invoked from a system service by flipping sys.rss_hwm_reset.on
+ * property to "1".
+ */
+
+#define LOG_TAG "rss_hwm_reset"
+
+#include <dirent.h>
+
+#include <string>
+
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include <log/log.h>
+
+namespace {
+// Resets RSS HWM counter for the selected process by writing 5 to
+// /proc/PID/clear_refs.
+void reset_rss_hwm(const char* pid) {
+ std::string clear_refs_path =
+ ::android::base::StringPrintf("/proc/%s/clear_refs", pid);
+ ::android::base::WriteStringToFile("5", clear_refs_path);
+}
+}
+
+// Clears RSS HWM counters for all currently running processes.
+int main(int /* argc */, char** /* argv[] */) {
+ DIR* dirp = opendir("/proc");
+ if (dirp == nullptr) {
+ ALOGE("unable to read /proc");
+ return 1;
+ }
+ struct dirent* entry;
+ while ((entry = readdir(dirp)) != nullptr) {
+ // Skip entries that are not directories.
+ if (entry->d_type != DT_DIR) continue;
+ // Skip entries that do not contain only numbers.
+ const char* pid = entry->d_name;
+ while (*pid) {
+ if (*pid < '0' || *pid > '9') break;
+ pid++;
+ }
+ if (*pid != 0) continue;
+
+ pid = entry->d_name;
+ reset_rss_hwm(pid);
+ }
+ closedir(dirp);
+ return 0;
+}
diff --git a/cmds/rss_hwm_reset/rss_hwm_reset.rc b/cmds/rss_hwm_reset/rss_hwm_reset.rc
new file mode 100644
index 0000000..fbbc820
--- /dev/null
+++ b/cmds/rss_hwm_reset/rss_hwm_reset.rc
@@ -0,0 +1,26 @@
+# 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
+#
+# https://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.
+
+service rss_hwm_reset /system/bin/rss_hwm_reset
+ class late_start
+ disabled
+ oneshot
+ user nobody
+ group nobody readproc
+ writepid /dev/cpuset/system-background/tasks
+ capabilities DAC_OVERRIDE
+
+on property:sys.rss_hwm_reset.on=1
+ start rss_hwm_reset
+ setprop sys.rss_hwm_reset.on 0
diff --git a/cmds/surfacereplayer/OWNERS b/cmds/surfacereplayer/OWNERS
new file mode 100644
index 0000000..cc4c842
--- /dev/null
+++ b/cmds/surfacereplayer/OWNERS
@@ -0,0 +1,2 @@
+mathias@google.com
+racarr@google.com
diff --git a/data/etc/android.hardware.telephony.ims.xml b/data/etc/android.hardware.telephony.ims.xml
new file mode 100644
index 0000000..eeb7b00
--- /dev/null
+++ b/data/etc/android.hardware.telephony.ims.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Feature for devices that support IMS via ImsService APIs. -->
+<permissions>
+ <feature name="android.hardware.telephony.ims" />
+</permissions>
diff --git a/headers/media_plugin/media/cas/DescramblerAPI.h b/headers/media_plugin/media/cas/DescramblerAPI.h
index 033c8ce..c57f606 100644
--- a/headers/media_plugin/media/cas/DescramblerAPI.h
+++ b/headers/media_plugin/media/cas/DescramblerAPI.h
@@ -72,12 +72,12 @@
// associated MediaCas session is used to load decryption keys
// into the crypto/cas plugin. The keys are then referenced by key-id
// in the 'key' parameter to the decrypt() method.
- // Should return NO_ERROR on success, ERROR_DRM_SESSION_NOT_OPENED if
+ // Should return NO_ERROR on success, ERROR_CAS_SESSION_NOT_OPENED if
// the session is not opened and a code from MediaErrors.h otherwise.
virtual status_t setMediaCasSession(const CasSessionId& sessionId) = 0;
// If the error returned falls into the range
- // ERROR_DRM_VENDOR_MIN..ERROR_DRM_VENDOR_MAX, errorDetailMsg should be
+ // ERROR_CAS_VENDOR_MIN..ERROR_CAS_VENDOR_MAX, errorDetailMsg should be
// filled in with an appropriate string.
// At the java level these special errors will then trigger a
// MediaCodec.CryptoException that gives clients access to both
diff --git a/include/OWNERS b/include/OWNERS
new file mode 100644
index 0000000..22be776
--- /dev/null
+++ b/include/OWNERS
@@ -0,0 +1,14 @@
+alexeykuzmin@google.com
+dangittik@google.com
+lajos@google.com
+mathias@google.com
+michaelwr@google.com
+racarr@google.com
+romainguy@android.com
+santoscordon@google.com
+stoza@google.com
+svv@google.com
+
+# For multinetwork.h only.
+lorenzo@google.com
+
diff --git a/include/android/multinetwork.h b/include/android/multinetwork.h
index 4d24680..d31d1f1 100644
--- a/include/android/multinetwork.h
+++ b/include/android/multinetwork.h
@@ -110,6 +110,74 @@
#endif /* __ANDROID_API__ >= 23 */
+#if __ANDROID_API__ >= 29
+
+/**
+ * Possible values of the flags argument to android_res_nsend and android_res_nquery.
+ * Values are ORed together.
+ */
+enum ResNsendFlags : uint32_t {
+ /**
+ * Send a single request to a single resolver and fail on timeout or network errors
+ */
+ ANDROID_RESOLV_NO_RETRY = 1 << 0,
+
+ /**
+ * Do not cache the result of the lookup. The lookup may return a result that is already
+ * in the cache, unless the ANDROID_RESOLV_NO_CACHE_LOOKUP flag is also specified.
+ */
+ ANDROID_RESOLV_NO_CACHE_STORE = 1 << 1,
+
+ /**
+ * Don't lookup the request in cache.
+ */
+ ANDROID_RESOLV_NO_CACHE_LOOKUP = 1 << 2,
+};
+
+/**
+ * Look up the {|ns_class|, |ns_type|} Resource Record (RR) associated
+ * with Domain Name |dname| on the given |network|.
+ * The typical value for |ns_class| is ns_c_in, while |type| can be any
+ * record type (for instance, ns_t_aaaa or ns_t_txt).
+ * |flags| is a additional config to control actual querying behavior, see
+ * ResNsendFlags for detail.
+ *
+ * Returns a file descriptor to watch for read events, or a negative
+ * POSIX error code (see errno.h) if an immediate error occurs.
+ */
+int android_res_nquery(net_handle_t network,
+ const char *dname, int ns_class, int ns_type, uint32_t flags) __INTRODUCED_IN(29);
+
+/**
+ * Issue the query |msg| on the given |network|.
+ * |flags| is a additional config to control actual querying behavior, see
+ * ResNsendFlags for detail.
+ *
+ * Returns a file descriptor to watch for read events, or a negative
+ * POSIX error code (see errno.h) if an immediate error occurs.
+ */
+int android_res_nsend(net_handle_t network,
+ const uint8_t *msg, size_t msglen, uint32_t flags) __INTRODUCED_IN(29);
+
+/**
+ * Read a result for the query associated with the |fd| descriptor.
+ * Closes |fd| before returning.
+ *
+ * Returns:
+ * < 0: negative POSIX error code (see errno.h for possible values). |rcode| is not set.
+ * >= 0: length of |answer|. |rcode| is the resolver return code (e.g., ns_r_nxdomain)
+ */
+int android_res_nresult(int fd,
+ int *rcode, uint8_t *answer, size_t anslen) __INTRODUCED_IN(29);
+
+/**
+ * Attempts to cancel the in-progress query associated with the |nsend_fd|
+ * descriptor.
+ */
+void android_res_cancel(int nsend_fd) __INTRODUCED_IN(29);
+
+#endif /* __ANDROID_API__ >= 29 */
+
__END_DECLS
#endif // ANDROID_MULTINETWORK_H
diff --git a/include/input/Input.h b/include/input/Input.h
index cfcafab..756b337 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -661,7 +661,7 @@
*/
class PooledInputEventFactory : public InputEventFactoryInterface {
public:
- PooledInputEventFactory(size_t maxPoolSize = 20);
+ explicit PooledInputEventFactory(size_t maxPoolSize = 20);
virtual ~PooledInputEventFactory();
virtual KeyEvent* createKeyEvent();
diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h
index 33d2757..5e542b8 100644
--- a/include/input/KeyCharacterMap.h
+++ b/include/input/KeyCharacterMap.h
@@ -196,7 +196,7 @@
};
struct Property {
- inline Property(int32_t property = 0, int32_t metaState = 0) :
+ inline explicit Property(int32_t property = 0, int32_t metaState = 0) :
property(property), metaState(metaState) { }
int32_t property;
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index f052bcb..22f6f54 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -23,7 +23,9 @@
#include <binder/BpBinder.h>
#include <binder/TextOutput.h>
+#include <android-base/macros.h>
#include <cutils/sched_policy.h>
+#include <utils/CallStack.h>
#include <utils/Log.h>
#include <utils/SystemClock.h>
#include <utils/threads.h>
@@ -617,6 +619,16 @@
}
if ((flags & TF_ONE_WAY) == 0) {
+ if (UNLIKELY(mCallRestriction != ProcessState::CallRestriction::NONE)) {
+ if (mCallRestriction == ProcessState::CallRestriction::ERROR_IF_NOT_ONEWAY) {
+ ALOGE("Process making non-oneway call but is restricted.");
+ CallStack::logStack("non-oneway call", CallStack::getCurrent(10).get(),
+ ANDROID_LOG_ERROR);
+ } else /* FATAL_IF_NOT_ONEWAY */ {
+ LOG_ALWAYS_FATAL("Process may not make oneway calls.");
+ }
+ }
+
#if 0
if (code == 4) { // relayout
ALOGI(">>>>>> CALLING transaction 4");
@@ -737,7 +749,8 @@
IPCThreadState::IPCThreadState()
: mProcess(ProcessState::self()),
mStrictModePolicy(0),
- mLastTransactionBinderFlags(0)
+ mLastTransactionBinderFlags(0),
+ mCallRestriction(mProcess->mCallRestriction)
{
pthread_setspecific(gTLS, this);
clearCaller();
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index b3ae09b..b2db945 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -467,7 +467,6 @@
status_t Parcel::appendFrom(const Parcel *parcel, size_t offset, size_t len)
{
- const sp<ProcessState> proc(ProcessState::self());
status_t err;
const uint8_t *data = parcel->mData;
const binder_size_t *objects = parcel->mObjects;
@@ -520,6 +519,7 @@
err = NO_ERROR;
if (numObjects > 0) {
+ const sp<ProcessState> proc(ProcessState::self());
// grow objects
if (mObjectsCapacity < mObjectsSize + numObjects) {
size_t newSize = ((mObjectsSize + numObjects)*3)/2;
@@ -2239,8 +2239,30 @@
int32_t hasComm = readInt32();
int fd = readFileDescriptor();
if (hasComm != 0) {
- // skip
- readFileDescriptor();
+ // detach (owned by the binder driver)
+ int comm = readFileDescriptor();
+
+ // warning: this must be kept in sync with:
+ // frameworks/base/core/java/android/os/ParcelFileDescriptor.java
+ enum ParcelFileDescriptorStatus {
+ DETACHED = 2,
+ };
+
+#if BYTE_ORDER == BIG_ENDIAN
+ const int32_t message = ParcelFileDescriptorStatus::DETACHED;
+#endif
+#if BYTE_ORDER == LITTLE_ENDIAN
+ const int32_t message = __builtin_bswap32(ParcelFileDescriptorStatus::DETACHED);
+#endif
+
+ ssize_t written = TEMP_FAILURE_RETRY(
+ ::write(comm, &message, sizeof(message)));
+
+ if (written == -1 || written != sizeof(message)) {
+ ALOGW("Failed to detach ParcelFileDescriptor written: %zd err: %s",
+ written, strerror(errno));
+ return BAD_TYPE;
+ }
}
return fd;
}
@@ -2521,8 +2543,11 @@
void Parcel::releaseObjects()
{
- const sp<ProcessState> proc(ProcessState::self());
size_t i = mObjectsSize;
+ if (i == 0) {
+ return;
+ }
+ sp<ProcessState> proc(ProcessState::self());
uint8_t* const data = mData;
binder_size_t* const objects = mObjects;
while (i > 0) {
@@ -2535,8 +2560,11 @@
void Parcel::acquireObjects()
{
- const sp<ProcessState> proc(ProcessState::self());
size_t i = mObjectsSize;
+ if (i == 0) {
+ return;
+ }
+ const sp<ProcessState> proc(ProcessState::self());
uint8_t* const data = mData;
binder_size_t* const objects = mObjects;
while (i > 0) {
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 53f8ddd..3798b61 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -234,6 +234,12 @@
return count;
}
+void ProcessState::setCallRestriction(CallRestriction restriction) {
+ LOG_ALWAYS_FATAL_IF(IPCThreadState::selfOrNull(), "Call restrictions must be set before the threadpool is started.");
+
+ mCallRestriction = restriction;
+}
+
ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
{
const size_t N=mHandleToObject.size();
@@ -426,6 +432,7 @@
, mBinderContextUserData(nullptr)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
+ , mCallRestriction(CallRestriction::NONE)
{
if (mDriverFD >= 0) {
// mmap the binder, providing a chunk of virtual address space to receive transactions.
diff --git a/libs/binder/Value.cpp b/libs/binder/Value.cpp
index a28a618..19c57ba 100644
--- a/libs/binder/Value.cpp
+++ b/libs/binder/Value.cpp
@@ -97,7 +97,7 @@
template<typename T> class Value::Content : public Value::ContentBase {
public:
Content() = default;
- Content(const T & value) : mValue(value) { }
+ explicit Content(const T & value) : mValue(value) { }
virtual ~Content() = default;
diff --git a/libs/binder/include/binder/BufferedTextOutput.h b/libs/binder/include/binder/BufferedTextOutput.h
index 9a7c43b..feae93d 100644
--- a/libs/binder/include/binder/BufferedTextOutput.h
+++ b/libs/binder/include/binder/BufferedTextOutput.h
@@ -32,7 +32,7 @@
MULTITHREADED = 0x0001
};
- BufferedTextOutput(uint32_t flags = 0);
+ explicit BufferedTextOutput(uint32_t flags = 0);
virtual ~BufferedTextOutput();
virtual status_t print(const char* txt, size_t len);
diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h
index 5ec02b1..f6381f7 100644
--- a/libs/binder/include/binder/IInterface.h
+++ b/libs/binder/include/binder/IInterface.h
@@ -124,7 +124,9 @@
#define CHECK_INTERFACE(interface, data, reply) \
- if (!(data).checkInterface(this)) { return PERMISSION_DENIED; } \
+ do { \
+ if (!(data).checkInterface(this)) { return PERMISSION_DENIED; } \
+ } while (false) \
// ----------------------------------------------------------------------
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 40b51ad..745f618 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -158,6 +158,8 @@
int32_t mStrictModePolicy;
int32_t mLastTransactionBinderFlags;
IPCThreadStateBase *mIPCThreadStateBase;
+
+ ProcessState::CallRestriction mCallRestriction;
};
}; // namespace android
diff --git a/libs/binder/include/binder/IpPrefix.h b/libs/binder/include/binder/IpPrefix.h
index dd5bc3a..c7e7a50 100644
--- a/libs/binder/include/binder/IpPrefix.h
+++ b/libs/binder/include/binder/IpPrefix.h
@@ -74,8 +74,8 @@
private:
union InternalUnion {
InternalUnion() = default;
- InternalUnion(const struct in6_addr &addr):mIn6Addr(addr) { };
- InternalUnion(const struct in_addr &addr):mInAddr(addr) { };
+ explicit InternalUnion(const struct in6_addr &addr):mIn6Addr(addr) { };
+ explicit InternalUnion(const struct in_addr &addr):mInAddr(addr) { };
struct in6_addr mIn6Addr;
struct in_addr mInAddr;
} mUnion;
diff --git a/libs/binder/include/binder/MemoryDealer.h b/libs/binder/include/binder/MemoryDealer.h
index fe5a31d..b483be0 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 = nullptr,
+ explicit 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 5e0a382..4be20a0 100644
--- a/libs/binder/include/binder/MemoryHeapBase.h
+++ b/libs/binder/include/binder/MemoryHeapBase.h
@@ -47,12 +47,12 @@
/*
* maps memory from the given device
*/
- MemoryHeapBase(const char* device, size_t size = 0, uint32_t flags = 0);
+ explicit MemoryHeapBase(const char* device, size_t size = 0, uint32_t flags = 0);
/*
* maps memory from ashmem, with the given name for debugging
*/
- MemoryHeapBase(size_t size, uint32_t flags = 0, char const* name = nullptr);
+ explicit MemoryHeapBase(size_t size, uint32_t flags = 0, char const* name = nullptr);
virtual ~MemoryHeapBase();
diff --git a/libs/binder/include/binder/ParcelFileDescriptor.h b/libs/binder/include/binder/ParcelFileDescriptor.h
index ad950af..662e56e 100644
--- a/libs/binder/include/binder/ParcelFileDescriptor.h
+++ b/libs/binder/include/binder/ParcelFileDescriptor.h
@@ -31,7 +31,7 @@
public:
ParcelFileDescriptor();
explicit ParcelFileDescriptor(android::base::unique_fd fd);
- explicit ParcelFileDescriptor(ParcelFileDescriptor&& other) : mFd(std::move(other.mFd)) { }
+ ParcelFileDescriptor(ParcelFileDescriptor&& other) : mFd(std::move(other.mFd)) { }
~ParcelFileDescriptor() override;
int get() const { return mFd.get(); }
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index 13f67ba..224cb36 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -77,10 +77,22 @@
ssize_t getKernelReferences(size_t count, uintptr_t* buf);
+ enum class CallRestriction {
+ // all calls okay
+ NONE,
+ // log when calls are blocking
+ ERROR_IF_NOT_ONEWAY,
+ // abort process on blocking calls
+ FATAL_IF_NOT_ONEWAY,
+ };
+ // Sets calling restrictions for all transactions in this process. This must be called
+ // before any threads are spawned.
+ void setCallRestriction(CallRestriction restriction);
+
private:
friend class IPCThreadState;
- ProcessState(const char* driver);
+ explicit ProcessState(const char* driver);
~ProcessState();
ProcessState(const ProcessState& o);
@@ -123,6 +135,8 @@
String8 mRootDir;
bool mThreadPoolStarted;
volatile int32_t mThreadPoolSeq;
+
+ CallRestriction mCallRestriction;
};
}; // namespace android
diff --git a/libs/binder/include/binder/TextOutput.h b/libs/binder/include/binder/TextOutput.h
index 851e01f..5b5f766 100644
--- a/libs/binder/include/binder/TextOutput.h
+++ b/libs/binder/include/binder/TextOutput.h
@@ -38,7 +38,7 @@
class Bundle {
public:
- inline Bundle(TextOutput& to) : mTO(to) { to.pushBundle(); }
+ inline explicit Bundle(TextOutput& to) : mTO(to) { to.pushBundle(); }
inline ~Bundle() { mTO.popBundle(); }
private:
TextOutput& mTO;
@@ -80,7 +80,7 @@
class TypeCode
{
public:
- inline TypeCode(uint32_t code);
+ inline explicit TypeCode(uint32_t code);
inline ~TypeCode();
inline uint32_t typeCode() const;
diff --git a/libs/binder/include/binder/Value.h b/libs/binder/include/binder/Value.h
index 4dee3d8..735f40e 100644
--- a/libs/binder/include/binder/Value.h
+++ b/libs/binder/include/binder/Value.h
@@ -74,20 +74,20 @@
bool operator!=(const Value& rhs) const { return !this->operator==(rhs); }
Value(const Value& value);
- Value(const bool& value);
- Value(const int8_t& value);
- Value(const int32_t& value);
- Value(const int64_t& value);
- Value(const double& value);
- Value(const String16& value);
- Value(const std::vector<bool>& value);
- Value(const std::vector<uint8_t>& value);
- Value(const std::vector<int32_t>& value);
- Value(const std::vector<int64_t>& value);
- Value(const std::vector<double>& value);
- Value(const std::vector<String16>& value);
- Value(const os::PersistableBundle& value);
- Value(const binder::Map& value);
+ Value(const bool& value); // NOLINT(google-explicit-constructor)
+ Value(const int8_t& value); // NOLINT(google-explicit-constructor)
+ Value(const int32_t& value); // NOLINT(google-explicit-constructor)
+ Value(const int64_t& value); // NOLINT(google-explicit-constructor)
+ Value(const double& value); // NOLINT(google-explicit-constructor)
+ Value(const String16& value); // NOLINT(google-explicit-constructor)
+ Value(const std::vector<bool>& value); // NOLINT(google-explicit-constructor)
+ Value(const std::vector<uint8_t>& value); // NOLINT(google-explicit-constructor)
+ Value(const std::vector<int32_t>& value); // NOLINT(google-explicit-constructor)
+ Value(const std::vector<int64_t>& value); // NOLINT(google-explicit-constructor)
+ Value(const std::vector<double>& value); // NOLINT(google-explicit-constructor)
+ Value(const std::vector<String16>& value); // NOLINT(google-explicit-constructor)
+ Value(const os::PersistableBundle& value); // NOLINT(google-explicit-constructor)
+ Value(const binder::Map& value); // NOLINT(google-explicit-constructor)
Value& operator=(const Value& rhs);
Value& operator=(const int8_t& rhs);
@@ -153,8 +153,8 @@
// String Convenience Adapters
// ---------------------------
- Value(const String8& value): Value(String16(value)) { }
- Value(const ::std::string& value): Value(String8(value.c_str())) { }
+ explicit Value(const String8& value): Value(String16(value)) { }
+ explicit Value(const ::std::string& value): Value(String8(value.c_str())) { }
void putString(const String8& value) { return putString(String16(value)); }
void putString(const ::std::string& value) { return putString(String8(value.c_str())); }
Value& operator=(const String8& rhs) { return *this = String16(rhs); }
diff --git a/libs/binder/ndk/.clang-format b/libs/binder/ndk/.clang-format
new file mode 100644
index 0000000..9a9d936
--- /dev/null
+++ b/libs/binder/ndk/.clang-format
@@ -0,0 +1,10 @@
+BasedOnStyle: Google
+ColumnLimit: 100
+IndentWidth: 4
+ContinuationIndentWidth: 8
+PointerAlignment: Left
+TabWidth: 4
+AllowShortFunctionsOnASingleLine: Inline
+PointerAlignment: Left
+TabWidth: 4
+UseTab: Never
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 5461b4f..68011bb 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -23,6 +23,12 @@
"include_apex",
],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+
srcs: [
"ibinder.cpp",
"ibinder_jni.cpp",
@@ -33,11 +39,22 @@
],
shared_libs: [
- "libandroid_runtime",
"libbase",
"libbinder",
"libutils",
],
+
+ required: [
+ // libbinder_ndk may be used by Java and non-Java things. When lower-level things use it,
+ // they shouldn't have to take on the cost of loading libandroid_runtime.
+ "libandroid_runtime",
+ ],
+
+ version_script: "libbinder_ndk.map.txt",
+ stubs: {
+ symbol_file: "libbinder_ndk.map.txt",
+ versions: ["29"],
+ },
}
ndk_headers {
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 896c5c1..f9c8c8a 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -22,6 +22,7 @@
#include "status_internal.h"
#include <android-base/logging.h>
+#include <binder/IPCThreadState.h>
using DeathRecipient = ::android::IBinder::DeathRecipient;
@@ -45,7 +46,7 @@
return binder != nullptr && binder->findObject(kId) == kValue;
}
-} // namespace ABBinderTag
+} // namespace ABBinderTag
namespace ABpBinderTag {
@@ -60,7 +61,7 @@
delete static_cast<Value*>(obj);
};
-} // namespace ABpBinderTag
+} // namespace ABpBinderTag
AIBinder::AIBinder(const AIBinder_Class* clazz) : mClazz(clazz) {}
AIBinder::~AIBinder() {}
@@ -91,7 +92,7 @@
return false;
}
- CHECK(asABpBinder() != nullptr); // ABBinder always has a descriptor
+ CHECK(asABpBinder() != nullptr); // ABBinder always has a descriptor
String8 descriptor(getBinder()->getInterfaceDescriptor());
if (descriptor != newDescriptor) {
@@ -107,7 +108,7 @@
}
ABBinder::ABBinder(const AIBinder_Class* clazz, void* userData)
- : AIBinder(clazz), BBinder(), mUserData(userData) {
+ : AIBinder(clazz), BBinder(), mUserData(userData) {
CHECK(clazz != nullptr);
}
ABBinder::~ABBinder() {
@@ -136,7 +137,7 @@
}
ABpBinder::ABpBinder(const ::android::sp<::android::IBinder>& binder)
- : AIBinder(nullptr /*clazz*/), BpRefBase(binder) {
+ : AIBinder(nullptr /*clazz*/), BpRefBase(binder) {
CHECK(binder != nullptr);
}
ABpBinder::~ABpBinder() {}
@@ -214,10 +215,10 @@
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) {}
+ : onCreate(onCreate),
+ onDestroy(onDestroy),
+ onTransact(onTransact),
+ mInterfaceDescriptor(interfaceDescriptor) {}
AIBinder_Class* AIBinder_Class_define(const char* interfaceDescriptor,
AIBinder_Class_onCreate onCreate,
@@ -239,7 +240,7 @@
}
AIBinder_DeathRecipient::AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinderDied onDied)
- : mOnDied(onDied) {
+ : mOnDied(onDied) {
CHECK(onDied != nullptr);
}
@@ -302,7 +303,7 @@
bool AIBinder_isRemote(const AIBinder* binder) {
if (binder == nullptr) {
- return true;
+ return false;
}
return binder->isRemote();
@@ -346,6 +347,14 @@
return recipient->unlinkToDeath(binder, cookie);
}
+uid_t AIBinder_getCallingUid() {
+ return ::android::IPCThreadState::self()->getCallingUid();
+}
+
+pid_t AIBinder_getCallingPid() {
+ return ::android::IPCThreadState::self()->getCallingPid();
+}
+
void AIBinder_incStrong(AIBinder* binder) {
if (binder == nullptr) {
LOG(ERROR) << __func__ << ": on null binder";
diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h
index 5b6bc94..7852298 100644
--- a/libs/binder/ndk/ibinder_internal.h
+++ b/libs/binder/ndk/ibinder_internal.h
@@ -34,7 +34,7 @@
struct ABpBinder;
struct AIBinder : public virtual ::android::RefBase {
- AIBinder(const AIBinder_Class* clazz);
+ explicit AIBinder(const AIBinder_Class* clazz);
virtual ~AIBinder();
bool associateClass(const AIBinder_Class* clazz);
@@ -49,7 +49,7 @@
return binder->remoteBinder() != nullptr;
}
-private:
+ 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).
@@ -69,7 +69,7 @@
::android::status_t onTransact(uint32_t code, const ::android::Parcel& data,
::android::Parcel* reply, binder_flags_t flags) override;
-private:
+ private:
ABBinder(const AIBinder_Class* clazz, void* userData);
// only thing that should create an ABBinder
@@ -96,8 +96,8 @@
::android::sp<::android::IBinder> getBinder() override { return remote(); }
ABpBinder* asABpBinder() override { return this; }
-private:
- ABpBinder(const ::android::sp<::android::IBinder>& binder);
+ private:
+ explicit ABpBinder(const ::android::sp<::android::IBinder>& binder);
};
struct AIBinder_Class {
@@ -110,7 +110,7 @@
const AIBinder_Class_onDestroy onDestroy;
const AIBinder_Class_onTransact onTransact;
-private:
+ private:
// This must be a String16 since BBinder virtual getInterfaceDescriptor returns a reference to
// one.
const ::android::String16 mInterfaceDescriptor;
@@ -128,24 +128,24 @@
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) {}
+ : 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:
+ private:
::android::wp<::android::IBinder> mWho;
void* mCookie;
const AIBinder_DeathRecipient_onBinderDied& mOnDied;
};
- AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinderDied onDied);
+ explicit AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinderDied onDied);
binder_status_t linkToDeath(AIBinder* binder, void* cookie);
binder_status_t unlinkToDeath(AIBinder* binder, void* cookie);
-private:
+ 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
index baea2e8..4a31080 100644
--- a/libs/binder/ndk/ibinder_jni.cpp
+++ b/libs/binder/ndk/ibinder_jni.cpp
@@ -17,15 +17,68 @@
#include <android/binder_ibinder_jni.h>
#include "ibinder_internal.h"
-#include <android_util_Binder.h>
+#include <android-base/logging.h>
+#include <binder/IBinder.h>
+
+#include <mutex>
+
+#include <dlfcn.h>
using ::android::IBinder;
-using ::android::ibinderForJavaObject;
-using ::android::javaObjectForIBinder;
using ::android::sp;
+struct LazyAndroidRuntime {
+ typedef sp<IBinder> (*FromJava)(JNIEnv* env, jobject obj);
+ typedef jobject (*ToJava)(JNIEnv* env, const sp<IBinder>& val);
+
+ static FromJava ibinderForJavaObject;
+ static ToJava javaObjectForIBinder;
+
+ static void load() {
+ std::call_once(mLoadFlag, []() {
+ void* handle = dlopen("libandroid_runtime.so", RTLD_LAZY);
+ if (handle == nullptr) {
+ LOG(WARNING) << "Could not open libandroid_runtime.";
+ return;
+ }
+
+ ibinderForJavaObject = reinterpret_cast<FromJava>(
+ dlsym(handle, "_ZN7android20ibinderForJavaObjectEP7_JNIEnvP8_jobject"));
+ if (ibinderForJavaObject == nullptr) {
+ LOG(WARNING) << "Could not find ibinderForJavaObject.";
+ // no return
+ }
+
+ javaObjectForIBinder = reinterpret_cast<ToJava>(dlsym(
+ handle, "_ZN7android20javaObjectForIBinderEP7_JNIEnvRKNS_2spINS_7IBinderEEE"));
+ if (javaObjectForIBinder == nullptr) {
+ LOG(WARNING) << "Could not find javaObjectForIBinder.";
+ // no return
+ }
+ });
+ }
+
+ private:
+ static std::once_flag mLoadFlag;
+
+ LazyAndroidRuntime(){};
+};
+
+LazyAndroidRuntime::FromJava LazyAndroidRuntime::ibinderForJavaObject = nullptr;
+LazyAndroidRuntime::ToJava LazyAndroidRuntime::javaObjectForIBinder = nullptr;
+std::once_flag LazyAndroidRuntime::mLoadFlag;
+
AIBinder* AIBinder_fromJavaBinder(JNIEnv* env, jobject binder) {
- sp<IBinder> ibinder = ibinderForJavaObject(env, binder);
+ if (binder == nullptr) {
+ return nullptr;
+ }
+
+ LazyAndroidRuntime::load();
+ if (LazyAndroidRuntime::ibinderForJavaObject == nullptr) {
+ return nullptr;
+ }
+
+ sp<IBinder> ibinder = (LazyAndroidRuntime::ibinderForJavaObject)(env, binder);
sp<AIBinder> cbinder = ABpBinder::lookupOrCreateFromBinder(ibinder);
AIBinder_incStrong(cbinder.get());
@@ -38,5 +91,10 @@
return nullptr;
}
- return javaObjectForIBinder(env, binder->getBinder());
+ LazyAndroidRuntime::load();
+ if (LazyAndroidRuntime::javaObjectForIBinder == nullptr) {
+ return nullptr;
+ }
+
+ return (LazyAndroidRuntime::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
index b8f38ba..80b6c07 100644
--- a/libs/binder/ndk/include_apex/android/binder_manager.h
+++ b/libs/binder/ndk/include_apex/android/binder_manager.h
@@ -17,11 +17,18 @@
#pragma once
#include <android/binder_ibinder.h>
+#include <android/binder_status.h>
__BEGIN_DECLS
/**
- * This registers the service with the default service manager under this instance name.
+ * This registers the service with the default service manager under this instance name. This does
+ * not take ownership of binder.
+ *
+ * \param binder object to register globally with the service manager.
+ * \param instance identifier of the service. This will be used to lookup the service.
+ *
+ * \return STATUS_OK on success.
*/
binder_status_t AServiceManager_addService(AIBinder* binder, const char* instance);
@@ -29,6 +36,8 @@
* 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).
+ *
+ * \param instance identifier of the service used to lookup the service.
*/
__attribute__((warn_unused_result)) AIBinder* AServiceManager_getService(const char* instance);
diff --git a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
index cc0a29d..c6868b0 100644
--- a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
@@ -32,8 +32,7 @@
#include <assert.h>
-#ifdef __cplusplus
-
+#include <unistd.h>
#include <cstddef>
namespace ndk {
@@ -42,7 +41,7 @@
* Represents one strong pointer to an AIBinder object.
*/
class SpAIBinder {
-public:
+ public:
/**
* Takes ownership of one strong refcount of binder.
*/
@@ -52,7 +51,7 @@
* 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() {}
+ SpAIBinder(std::nullptr_t) : SpAIBinder() {} // NOLINT(google-explicit-constructor)
/**
* This will delete the underlying object if it exists. See operator=.
@@ -106,30 +105,32 @@
*/
AIBinder** getR() { return &mBinder; }
-private:
+ private:
AIBinder* mBinder = nullptr;
};
+namespace impl {
+
/**
* This baseclass owns a single object, used to make various classes RAII.
*/
-template <typename T, void (*Destroy)(T*)>
+template <typename T, typename R, R (*Destroy)(T), T DEFAULT>
class ScopedAResource {
-public:
+ public:
/**
* Takes ownership of t.
*/
- explicit ScopedAResource(T* t = nullptr) : mT(t) {}
+ explicit ScopedAResource(T t = DEFAULT) : mT(t) {}
/**
* This deletes the underlying object if it exists. See set.
*/
- ~ScopedAResource() { set(nullptr); }
+ ~ScopedAResource() { set(DEFAULT); }
/**
* Takes ownership of t.
*/
- void set(T* t) {
+ void set(T t) {
Destroy(mT);
mT = t;
}
@@ -137,12 +138,12 @@
/**
* This returns the underlying object to be modified but does not affect ownership.
*/
- T* get() { return mT; }
+ T get() { return mT; }
/**
* This returns the const underlying object but does not affect ownership.
*/
- const T* get() const { return mT; }
+ 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
@@ -156,7 +157,7 @@
* Other usecases are discouraged.
*
*/
- T** getR() { return &mT; }
+ T* getR() { return &mT; }
// copy-constructing, or move/copy assignment is disallowed
ScopedAResource(const ScopedAResource&) = delete;
@@ -164,17 +165,19 @@
ScopedAResource& operator=(ScopedAResource&&) = delete;
// move-constructing is okay
- ScopedAResource(ScopedAResource&&) = default;
+ ScopedAResource(ScopedAResource&& other) : mT(std::move(other.mT)) { other.mT = DEFAULT; }
-private:
- T* mT;
+ private:
+ T mT;
};
+} // namespace impl
+
/**
* Convenience wrapper. See AParcel.
*/
-class ScopedAParcel : public ScopedAResource<AParcel, AParcel_delete> {
-public:
+class ScopedAParcel : public impl::ScopedAResource<AParcel*, void, AParcel_delete, nullptr> {
+ public:
/**
* Takes ownership of a.
*/
@@ -186,8 +189,8 @@
/**
* Convenience wrapper. See AStatus.
*/
-class ScopedAStatus : public ScopedAResource<AStatus, AStatus_delete> {
-public:
+class ScopedAStatus : public impl::ScopedAResource<AStatus*, void, AStatus_delete, nullptr> {
+ public:
/**
* Takes ownership of a.
*/
@@ -199,19 +202,25 @@
* See AStatus_isOk.
*/
bool isOk() { return get() != nullptr && AStatus_isOk(get()); }
+
+ /**
+ * Convenience method for okay status.
+ */
+ static ScopedAStatus ok() { return ScopedAStatus(AStatus_newOk()); }
};
/**
* Convenience wrapper. See AIBinder_DeathRecipient.
*/
class ScopedAIBinder_DeathRecipient
- : public ScopedAResource<AIBinder_DeathRecipient, AIBinder_DeathRecipient_delete> {
-public:
+ : public impl::ScopedAResource<AIBinder_DeathRecipient*, void, AIBinder_DeathRecipient_delete,
+ nullptr> {
+ public:
/**
* Takes ownership of a.
*/
explicit ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient* a = nullptr)
- : ScopedAResource(a) {}
+ : ScopedAResource(a) {}
~ScopedAIBinder_DeathRecipient() {}
ScopedAIBinder_DeathRecipient(ScopedAIBinder_DeathRecipient&&) = default;
};
@@ -219,8 +228,9 @@
/**
* Convenience wrapper. See AIBinder_Weak.
*/
-class ScopedAIBinder_Weak : public ScopedAResource<AIBinder_Weak, AIBinder_Weak_delete> {
-public:
+class ScopedAIBinder_Weak
+ : public impl::ScopedAResource<AIBinder_Weak*, void, AIBinder_Weak_delete, nullptr> {
+ public:
/**
* Takes ownership of a.
*/
@@ -234,8 +244,19 @@
SpAIBinder promote() { return SpAIBinder(AIBinder_Weak_promote(get())); }
};
-} // namespace ndk
+/**
+ * Convenience wrapper for a file descriptor.
+ */
+class ScopedFileDescriptor : public impl::ScopedAResource<int, int, close, -1> {
+ public:
+ /**
+ * Takes ownership of a.
+ */
+ explicit ScopedFileDescriptor(int a = -1) : ScopedAResource(a) {}
+ ~ScopedFileDescriptor() {}
+ ScopedFileDescriptor(ScopedFileDescriptor&&) = default;
+};
-#endif // __cplusplus
+} // namespace ndk
/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index c222c16..9c6c55e 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -28,6 +28,7 @@
#include <stdint.h>
#include <sys/cdefs.h>
+#include <sys/types.h>
#include <android/binder_parcel.h>
#include <android/binder_status.h>
@@ -126,8 +127,9 @@
/**
* 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.
+ * \param args these can be used to construct a new class. These are passed from AIBinder_new.
+ * \return this is the userdata representing the class. It can be retrieved using
+ * AIBinder_getUserData.
*/
typedef void* (*AIBinder_Class_onCreate)(void* args);
@@ -135,23 +137,41 @@
* This is called whenever an AIBinder object is no longer referenced and needs destroyed.
*
* Typically, this just deletes whatever the implementation is.
+ *
+ * \param userData this is the same object returned by AIBinder_Class_onCreate
*/
typedef void (*AIBinder_Class_onDestroy)(void* userData);
/**
* This is called whenever a transaction needs to be processed by a local implementation.
+ *
+ * \param binder the object being transacted on.
+ * \param code implementation-specific code representing which transaction should be taken.
+ * \param in the implementation-specific input data to this transaction.
+ * \param out the implementation-specific output data to this transaction.
+ *
+ * \return the implementation-specific output code. This may be forwarded from another service, the
+ * result of a parcel read or write, or another error as is applicable to the specific
+ * implementation. Usually, implementation-specific error codes are written to the output parcel,
+ * and the transaction code is reserved for kernel errors or error codes that have been repeated
+ * from subsequent transactions.
*/
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.
+ * This creates a new instance of a class of binders which can be instantiated. This is called one
+ * time during library initialization and cleaned up when the process exits or execs.
*
- * None of these parameters can be nullptr.
+ * None of these parameters can be null.
*
- * This is created one time during library initialization and cleaned up when the process exits or
- * execs.
+ * \param interfaceDescriptor this is a unique identifier for the class. This is used internally for
+ * sanity checks on transactions.
+ * \param onCreate see AIBinder_Class_onCreate.
+ * \param onDestroy see AIBinder_Class_onDestroy.
+ * \param onTransact see AIBinder_Class_onTransact.
+ *
+ * \return the class object representing these parameters or null on error.
*/
__attribute__((warn_unused_result)) AIBinder_Class* AIBinder_Class_define(
const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate,
@@ -174,12 +194,21 @@
* 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.
+ *
+ * \param clazz the type of the object to be created.
+ * \param args the args to pass to AIBinder_onCreate for that class.
+ *
+ * \return a binder object representing the newly instantiated object.
*/
__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.
+ *
+ * \param binder the binder being queried.
+ *
+ * \return true if the AIBinder represents an object in another process.
*/
bool AIBinder_isRemote(const AIBinder* binder) __INTRODUCED_IN(29);
@@ -189,13 +218,21 @@
* 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.
+ *
+ * \param binder the binder being queried.
+ *
+ * \return true if the binder is alive.
*/
bool AIBinder_isAlive(const AIBinder* binder) __INTRODUCED_IN(29);
/**
- * Built-in transaction for all binder objects. This sends a transaction which will immediately
+ * Built-in transaction for all binder objects. This sends a transaction that will immediately
* return. Usually this is used to make sure that a binder is alive, as a placeholder call, or as a
* sanity check.
+ *
+ * \param binder the binder being queried.
+ *
+ * \return STATUS_OK if the ping succeeds.
*/
binder_status_t AIBinder_ping(AIBinder* binder) __INTRODUCED_IN(29);
@@ -209,6 +246,12 @@
* identification and holding user data.
*
* If binder is local, this will return STATUS_INVALID_OPERATION.
+ *
+ * \param binder the binder object you want to receive death notifications from.
+ * \param recipient the callback that will receive notifications when/if the binder dies.
+ * \param cookie the value that will be passed to the death recipient on death.
+ *
+ * \return STATUS_OK on success.
*/
binder_status_t AIBinder_linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
void* cookie) __INTRODUCED_IN(29);
@@ -217,22 +260,62 @@
* 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.
+ *
+ * \param binder the binder object to remove a previously linked death recipient from.
+ * \param recipient the callback to remove.
+ * \param cookie the cookie used to link to death.
+ *
+ * \return STATUS_OK on success. STATUS_NAME_NOT_FOUND if the binder cannot be found to be unlinked.
*/
binder_status_t AIBinder_unlinkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
void* cookie) __INTRODUCED_IN(29);
/**
+ * This returns the calling UID assuming that this thread is called from a thread that is processing
+ * a binder transaction (for instance, in the implementation of AIBinder_Class_onTransact).
+ *
+ * This can be used with higher-level system services to determine the caller's identity and check
+ * permissions.
+ *
+ * \return calling uid or the current process's UID if this thread isn't processing a transaction.
+ */
+uid_t AIBinder_getCallingUid();
+
+/**
+ * This returns the calling PID assuming that this thread is called from a thread that is processing
+ * a binder transaction (for instance, in the implementation of AIBinder_Class_onTransact).
+ *
+ * This can be used with higher-level system services to determine the caller's identity and check
+ * permissions. However, when doing this, one should be aware of possible TOCTOU problems when the
+ * calling process dies and is replaced with another process with elevated permissions and the same
+ * PID.
+ *
+ * \return calling pid or the current process's PID if this thread isn't processing a transaction.
+ * If the transaction being processed is a oneway transaction, then this method will return 0.
+ */
+pid_t AIBinder_getCallingPid();
+
+/**
* This can only be called if a strong reference to this object already exists in process.
+ *
+ * \param binder the binder object to add a refcount to.
*/
void AIBinder_incStrong(AIBinder* binder) __INTRODUCED_IN(29);
/**
* This will delete the object and call onDestroy once the refcount reaches zero.
+ *
+ * \param binder the binder object to remove a refcount from.
*/
void AIBinder_decStrong(AIBinder* binder) __INTRODUCED_IN(29);
/**
* For debugging only!
+ *
+ * \param binder the binder object to retrieve the refcount of.
+ *
+ * \return the number of strong-refs on this binder in this process. If binder is null, this will be
+ * -1.
*/
int32_t AIBinder_debugGetRefCount(AIBinder* binder) __INTRODUCED_IN(29);
@@ -244,17 +327,32 @@
*
* This returns true if the class association succeeds. If it fails, no change is made to the
* binder object.
+ *
+ * \param binder the object to attach the class to.
+ * \param clazz the clazz to attach to binder.
+ *
+ * \return true if the binder has the class clazz and if the association was successful.
*/
bool AIBinder_associateClass(AIBinder* binder, const AIBinder_Class* clazz) __INTRODUCED_IN(29);
/**
* Returns the class that this binder was constructed with or associated with.
+ *
+ * \param binder the object that is being queried.
+ *
+ * \return the class that this binder is associated with. If this binder wasn't created with
+ * AIBinder_new, and AIBinder_associateClass hasn't been called, then this will return null.
*/
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.
+ * null), this also returns null. For a remote binder, this will always return null.
+ *
+ * \param binder the object that is being queried.
+ *
+ * \return the userdata returned from AIBinder_onCreate when this object was created. This may be
+ * null for stateless objects. For remote objects, this is always null.
*/
void* AIBinder_getUserData(AIBinder* binder) __INTRODUCED_IN(29);
@@ -278,6 +376,12 @@
* 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.
+ *
+ * \param binder the binder object to start a transaction on.
+ * \param in out parameter for input data to the transaction.
+ *
+ * \return STATUS_OK on success. This will return STATUS_INVALID_OPERATION if the binder has not yet
+ * been associated with a class (see AIBinder_new and AIBinder_associateClass).
*/
binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in) __INTRODUCED_IN(29);
@@ -292,6 +396,16 @@
*
* 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.
+ *
+ * \param binder the binder object to transact on.
+ * \param code the implementation-specific code representing which transaction should be taken.
+ * \param in the implementation-specific input data to this transaction.
+ * \param out the implementation-specific output data to this transaction.
+ * \param flags possible flags to alter the way in which the transaction is conducted or 0.
+ *
+ * \return the result from the kernel or from the remote process. Usually, implementation-specific
+ * error codes are written to the output parcel, and the transaction code is reserved for kernel
+ * errors or error codes that have been repeated from subsequent transactions.
*/
binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, AParcel** in,
AParcel** out, binder_flags_t flags) __INTRODUCED_IN(29);
@@ -299,29 +413,45 @@
/**
* 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.
+ *
+ * \param binder object to create a weak pointer to.
+ *
+ * \return object representing a weak pointer to binder (or null if binder is null).
*/
__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.
+ *
+ * \param weakBinder object created with AIBinder_Weak_new.
*/
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.
+ * null.
+ *
+ * \param weakBinder weak pointer to attempt retrieving the original object from.
+ *
+ * \return an AIBinder object with one refcount given to the caller or null.
*/
__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.
+ *
+ * \param cookie the cookie passed to AIBinder_linkToDeath.
*/
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.
+ *
+ * \param onBinderDied the callback to call when this death recipient is invoked.
+ *
+ * \return the newly constructed object (or null if onBinderDied is null).
*/
__attribute__((warn_unused_result)) AIBinder_DeathRecipient* AIBinder_DeathRecipient_new(
AIBinder_DeathRecipient_onBinderDied onBinderDied) __INTRODUCED_IN(29);
@@ -329,10 +459,12 @@
/**
* Deletes a binder death recipient. It is not necessary to call AIBinder_unlinkToDeath before
* calling this as these will all be automatically unlinked.
+ *
+ * \param recipient the binder to delete (previously created with AIBinder_DeathRecipient_new).
*/
void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient* recipient) __INTRODUCED_IN(29);
-#endif //__ANDROID_API__ >= __ANDROID_API_Q__
+#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
index 81fb3c5..124f36c 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
@@ -39,6 +39,12 @@
* 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.
+ *
+ * \param env Java environment.
+ * \param binder android.os.IBinder java object.
+ *
+ * \return an AIBinder object representing the Java binder object. If either parameter is null, or
+ * the Java object is of the wrong type, this will return null.
*/
__attribute__((warn_unused_result)) AIBinder* AIBinder_fromJavaBinder(JNIEnv* env, jobject binder)
__INTRODUCED_IN(29);
@@ -48,11 +54,16 @@
*
* 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.
+ *
+ * \param env Java environment.
+ * \param binder the object to convert.
+ *
+ * \return an android.os.IBinder object or null if the parameters were null.
*/
__attribute__((warn_unused_result)) jobject AIBinder_toJavaBinder(JNIEnv* env, AIBinder* binder)
__INTRODUCED_IN(29);
-#endif //__ANDROID_API__ >= __ANDROID_API_Q__
+#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
index e37c388..a42c60b 100644
--- a/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
@@ -32,8 +32,6 @@
#include <assert.h>
-#ifdef __cplusplus
-
#include <memory>
#include <mutex>
@@ -46,7 +44,7 @@
* construct this object is with SharedRefBase::make.
*/
class SharedRefBase {
-public:
+ public:
SharedRefBase() {}
virtual ~SharedRefBase() {
std::call_once(mFlagThis, [&]() {
@@ -83,7 +81,7 @@
return t->template ref<T>();
}
-private:
+ private:
std::once_flag mFlagThis;
std::weak_ptr<SharedRefBase> mThis;
};
@@ -92,7 +90,7 @@
* wrapper analog to IInterface
*/
class ICInterface : public SharedRefBase {
-public:
+ public:
ICInterface() {}
virtual ~ICInterface() {}
@@ -113,7 +111,7 @@
*/
template <typename INTERFACE>
class BnCInterface : public INTERFACE {
-public:
+ public:
BnCInterface() {}
virtual ~BnCInterface() {}
@@ -121,15 +119,15 @@
bool isRemote() override { return true; }
-protected:
+ 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
+ private:
+ std::mutex mMutex; // for asBinder
ScopedAIBinder_Weak mWeakBinder;
};
@@ -138,15 +136,15 @@
*/
template <typename INTERFACE>
class BpCInterface : public INTERFACE {
-public:
- BpCInterface(const SpAIBinder& binder) : mBinder(binder) {}
+ public:
+ explicit BpCInterface(const SpAIBinder& binder) : mBinder(binder) {}
virtual ~BpCInterface() {}
SpAIBinder asBinder() override;
bool isRemote() override { return AIBinder_isRemote(mBinder.get()); }
-private:
+ private:
SpAIBinder mBinder;
};
@@ -171,8 +169,6 @@
return mBinder;
}
-} // namespace ndk
-
-#endif // __cplusplus
+} // namespace ndk
/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
index 33c3f6c..2258210 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -47,88 +47,289 @@
/**
* Cleans up a parcel.
+ *
+ * \param parcel A parcel returned by AIBinder_prepareTransaction or AIBinder_transact when a
+ * transaction is being aborted.
*/
void AParcel_delete(AParcel* parcel) __INTRODUCED_IN(29);
+/**
+ * Sets the position within the parcel.
+ *
+ * \param parcel The parcel of which to set the position.
+ * \param position Position of the parcel to set. This must be a value returned by
+ * AParcel_getDataPosition. Positions are constant for a given parcel between processes.
+ *
+ * \return STATUS_OK on success. If position is negative, then STATUS_BAD_VALUE will be returned.
+ */
+binder_status_t AParcel_setDataPosition(const AParcel* parcel, int32_t position)
+ __INTRODUCED_IN(29);
+
+/**
+ * Gets the current position within the parcel.
+ *
+ * \param parcel The parcel of which to get the position.
+ *
+ * \return The size of the parcel. This will always be greater than 0. The values returned by this
+ * function before and after calling various reads and writes are not defined. Only the delta
+ * between two positions between a specific sequence of calls is defined. For instance, if position
+ * is X, writeBool is called, and then position is Y, readBool can be called from position X will
+ * return the same value, and then position will be Y.
+ */
+int32_t AParcel_getDataPosition(const AParcel* parcel) __INTRODUCED_IN(29);
+
+/**
+ * This is called to allocate a buffer for a C-style string (null-terminated). The returned buffer
+ * should be at least length bytes. This includes space for a null terminator. For a string, length
+ * will always be strictly less than or equal to the maximum size that can be held in a size_t and
+ * will always be greater than 0. However, if a 'null' string is being read, length will be -1.
+ *
+ * See also AParcel_readString.
+ *
+ * If allocation fails, null should be returned.
+ *
+ * \param stringData some external representation of a string
+ * \param length the length of the buffer needed to fill (including the null-terminator)
+ * \param buffer a buffer of size 'length' or null if allocation failed.
+ *
+ * \return true if the allocation succeeded, false otherwise. If length is -1, a true return here
+ * means that a 'null' value (or equivalent) was successfully stored.
+ */
+typedef bool (*AParcel_stringAllocator)(void* stringData, int32_t length, char** buffer);
+
+/**
+ * This is called to allocate an array of size 'length'. If length is -1, then a 'null' array (or
+ * equivalent) should be created.
+ *
+ * See also AParcel_readStringArray
+ *
+ * \param arrayData some external representation of an array
+ * \param length the length to allocate this array to
+ *
+ * \return true if allocation succeeded. If length is -1, a true return here means that a 'null'
+ * value (or equivalent) was successfully stored.
+ */
+typedef bool (*AParcel_stringArrayAllocator)(void* arrayData, int32_t length);
+
+/**
+ * This is called to allocate a string inside of an array that was allocated by an
+ * AParcel_stringArrayAllocator.
+ *
+ * The index returned will always be within the range [0, length of arrayData). The returned buffer
+ * should be at least length bytes. This includes space for a null-terminator. For a string, length
+ * will always be strictly less than or equal to the maximum size that can be held in a size_t and
+ * will always be greater than 0. However, if a 'null' string is being read, length will be -1.
+ *
+ * See also AParcel_readStringArray
+ *
+ * \param arrayData some external representation of an array.
+ * \param index the index at which a string should be allocated.
+ * \param length the length of the string to be allocated at this index. See also
+ * AParcel_stringAllocator. This includes the length required for a null-terminator.
+ * \param buffer a buffer of size 'length' or null if allocation failed.
+ *
+ * \return true if the allocation succeeded, false otherwise. If length is -1, a true return here
+ * means that a 'null' value (or equivalent) was successfully stored.
+ */
+typedef bool (*AParcel_stringArrayElementAllocator)(void* arrayData, size_t index, int32_t length,
+ char** buffer);
+
+/**
+ * This returns the length and buffer of an array at a specific index in an arrayData object.
+ *
+ * See also AParcel_writeStringArray
+ *
+ * \param arrayData some external representation of an array.
+ * \param index the index at which a string should be allocated.
+ * \param outLength an out parameter for the length of the string at the specified index. This
+ * should not include the length for a null-terminator if there is one. If the object at this index
+ * is 'null', then this should be set to -1.
+ *
+ * \param a buffer of size outLength or more representing the string at the provided index. This is
+ * not required to be null-terminated. If the object at index is null, then this should be null.
+ */
+typedef const char* (*AParcel_stringArrayElementGetter)(const void* arrayData, size_t index,
+ int32_t* outLength);
+
+/**
+ * This is called to allocate an array of size 'length'. If length is -1, then a 'null' array (or
+ * equivalent) should be created.
+ *
+ * See also AParcel_readParcelableArray
+ *
+ * \param arrayData some external representation of an array
+ * \param length the length to allocate this array to
+ *
+ * \return true if allocation succeeded. If length is -1, a true return here means that a 'null'
+ * value (or equivalent) was successfully stored.
+ */
+typedef bool (*AParcel_parcelableArrayAllocator)(void* arrayData, int32_t length);
+
+/**
+ * This is called to parcel the underlying data from an arrayData object at index.
+ *
+ * See also AParcel_writeParcelableArray
+ *
+ * \param parcel parcel to write the parcelable to
+ * \param arrayData some external representation of an array of parcelables (a user-defined type).
+ * \param index the index of the value to be retrieved.
+ *
+ * \return status (usually returned from other parceling functions). STATUS_OK for success.
+ */
+typedef binder_status_t (*AParcel_writeParcelableElement)(AParcel* parcel, const void* arrayData,
+ size_t index);
+
+/**
+ * This is called to set an underlying value in an arrayData object at index.
+ *
+ * See also AParcel_readParcelableArray
+ *
+ * \param parcel parcel to read the parcelable from
+ * \param arrayData some external representation of an array of parcelables (a user-defined type).
+ * \param index the index of the value to be set.
+ *
+ * \return status (usually returned from other parceling functions). STATUS_OK for success.
+ */
+typedef binder_status_t (*AParcel_readParcelableElement)(const AParcel* parcel, void* arrayData,
+ size_t index);
+
// @START-PRIMITIVE-VECTOR-GETTERS
/**
* This is called to get the underlying data from an arrayData object.
*
- * The implementation of this function should allocate a contiguous array of length length and
+ * The implementation of this function should allocate a contiguous array of size 'length' and
* return that underlying buffer to be filled out. If there is an error or length is 0, null may be
- * returned.
+ * returned. If length is -1, this should allocate some representation of a null array.
*
* See also AParcel_readInt32Array
+ *
+ * \param arrayData some external representation of an array of int32_t.
+ * \param length the length to allocate arrayData to.
+ * \param outBuffer a buffer of int32_t of size 'length' (if length is >= 0, if length is 0, this
+ * may be nullptr).
+ *
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
*/
-typedef int32_t* (*AParcel_int32Allocator)(void* arrayData, size_t length);
+typedef bool (*AParcel_int32ArrayAllocator)(void* arrayData, int32_t length, int32_t** outBuffer);
/**
* This is called to get the underlying data from an arrayData object.
*
- * The implementation of this function should allocate a contiguous array of length length and
+ * The implementation of this function should allocate a contiguous array of size 'length' and
* return that underlying buffer to be filled out. If there is an error or length is 0, null may be
- * returned.
+ * returned. If length is -1, this should allocate some representation of a null array.
*
* See also AParcel_readUint32Array
+ *
+ * \param arrayData some external representation of an array of uint32_t.
+ * \param length the length to allocate arrayData to.
+ * \param outBuffer a buffer of uint32_t of size 'length' (if length is >= 0, if length is 0, this
+ * may be nullptr).
+ *
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
*/
-typedef uint32_t* (*AParcel_uint32Allocator)(void* arrayData, size_t length);
+typedef bool (*AParcel_uint32ArrayAllocator)(void* arrayData, int32_t length, uint32_t** outBuffer);
/**
* This is called to get the underlying data from an arrayData object.
*
- * The implementation of this function should allocate a contiguous array of length length and
+ * The implementation of this function should allocate a contiguous array of size 'length' and
* return that underlying buffer to be filled out. If there is an error or length is 0, null may be
- * returned.
+ * returned. If length is -1, this should allocate some representation of a null array.
*
* See also AParcel_readInt64Array
+ *
+ * \param arrayData some external representation of an array of int64_t.
+ * \param length the length to allocate arrayData to.
+ * \param outBuffer a buffer of int64_t of size 'length' (if length is >= 0, if length is 0, this
+ * may be nullptr).
+ *
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
*/
-typedef int64_t* (*AParcel_int64Allocator)(void* arrayData, size_t length);
+typedef bool (*AParcel_int64ArrayAllocator)(void* arrayData, int32_t length, int64_t** outBuffer);
/**
* This is called to get the underlying data from an arrayData object.
*
- * The implementation of this function should allocate a contiguous array of length length and
+ * The implementation of this function should allocate a contiguous array of size 'length' and
* return that underlying buffer to be filled out. If there is an error or length is 0, null may be
- * returned.
+ * returned. If length is -1, this should allocate some representation of a null array.
*
* See also AParcel_readUint64Array
+ *
+ * \param arrayData some external representation of an array of uint64_t.
+ * \param length the length to allocate arrayData to.
+ * \param outBuffer a buffer of uint64_t of size 'length' (if length is >= 0, if length is 0, this
+ * may be nullptr).
+ *
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
*/
-typedef uint64_t* (*AParcel_uint64Allocator)(void* arrayData, size_t length);
+typedef bool (*AParcel_uint64ArrayAllocator)(void* arrayData, int32_t length, uint64_t** outBuffer);
/**
* This is called to get the underlying data from an arrayData object.
*
- * The implementation of this function should allocate a contiguous array of length length and
+ * The implementation of this function should allocate a contiguous array of size 'length' and
* return that underlying buffer to be filled out. If there is an error or length is 0, null may be
- * returned.
+ * returned. If length is -1, this should allocate some representation of a null array.
*
* See also AParcel_readFloatArray
+ *
+ * \param arrayData some external representation of an array of float.
+ * \param length the length to allocate arrayData to.
+ * \param outBuffer a buffer of float of size 'length' (if length is >= 0, if length is 0, this may
+ * be nullptr).
+ *
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
*/
-typedef float* (*AParcel_floatAllocator)(void* arrayData, size_t length);
+typedef bool (*AParcel_floatArrayAllocator)(void* arrayData, int32_t length, float** outBuffer);
/**
* This is called to get the underlying data from an arrayData object.
*
- * The implementation of this function should allocate a contiguous array of length length and
+ * The implementation of this function should allocate a contiguous array of size 'length' and
* return that underlying buffer to be filled out. If there is an error or length is 0, null may be
- * returned.
+ * returned. If length is -1, this should allocate some representation of a null array.
*
* See also AParcel_readDoubleArray
+ *
+ * \param arrayData some external representation of an array of double.
+ * \param length the length to allocate arrayData to.
+ * \param outBuffer a buffer of double of size 'length' (if length is >= 0, if length is 0, this may
+ * be nullptr).
+ *
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
*/
-typedef double* (*AParcel_doubleAllocator)(void* arrayData, size_t length);
+typedef bool (*AParcel_doubleArrayAllocator)(void* arrayData, int32_t length, double** outBuffer);
/**
- * This allocates an array of length length inside of arrayData and returns whether or not there was
- * a success.
+ * This allocates an array of size 'length' inside of arrayData and returns whether or not there was
+ * a success. If length is -1, then this should allocate some representation of a null array.
*
* See also AParcel_readBoolArray
+ *
+ * \param arrayData some external representation of an array of bool.
+ * \param length the length to allocate arrayData to (or -1 if this represents a null array).
+ *
+ * \return whether the allocation succeeded.
*/
-typedef bool (*AParcel_boolAllocator)(void* arrayData, size_t length);
+typedef bool (*AParcel_boolArrayAllocator)(void* arrayData, int32_t length);
/**
* This is called to get the underlying data from an arrayData object at index.
*
* See also AParcel_writeBoolArray
+ *
+ * \param arrayData some external representation of an array of bool.
+ * \param index the index of the value to be retrieved.
+ *
+ * \return the value of the array at index index.
*/
typedef bool (*AParcel_boolArrayGetter)(const void* arrayData, size_t index);
@@ -136,61 +337,103 @@
* This is called to set an underlying value in an arrayData object at index.
*
* See also AParcel_readBoolArray
+ *
+ * \param arrayData some external representation of an array of bool.
+ * \param index the index of the value to be set.
+ * \param value the value to set at index index.
*/
typedef void (*AParcel_boolArraySetter)(void* arrayData, size_t index, bool value);
/**
* This is called to get the underlying data from an arrayData object.
*
- * The implementation of this function should allocate a contiguous array of length length and
+ * The implementation of this function should allocate a contiguous array of size 'length' and
* return that underlying buffer to be filled out. If there is an error or length is 0, null may be
- * returned.
+ * returned. If length is -1, this should allocate some representation of a null array.
*
* See also AParcel_readCharArray
+ *
+ * \param arrayData some external representation of an array of char16_t.
+ * \param length the length to allocate arrayData to.
+ * \param outBuffer a buffer of char16_t of size 'length' (if length is >= 0, if length is 0, this
+ * may be nullptr).
+ *
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
*/
-typedef char16_t* (*AParcel_charAllocator)(void* arrayData, size_t length);
+typedef bool (*AParcel_charArrayAllocator)(void* arrayData, int32_t length, char16_t** outBuffer);
/**
* This is called to get the underlying data from an arrayData object.
*
- * The implementation of this function should allocate a contiguous array of length length and
+ * The implementation of this function should allocate a contiguous array of size 'length' and
* return that underlying buffer to be filled out. If there is an error or length is 0, null may be
- * returned.
+ * returned. If length is -1, this should allocate some representation of a null array.
*
* See also AParcel_readByteArray
+ *
+ * \param arrayData some external representation of an array of int8_t.
+ * \param length the length to allocate arrayData to.
+ * \param outBuffer a buffer of int8_t of size 'length' (if length is >= 0, if length is 0, this may
+ * be nullptr).
+ *
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
*/
-typedef int8_t* (*AParcel_byteAllocator)(void* arrayData, size_t length);
+typedef bool (*AParcel_byteArrayAllocator)(void* arrayData, int32_t length, int8_t** outBuffer);
// @END-PRIMITIVE-VECTOR-GETTERS
/**
- * This is called to allocate a buffer for a C-style string (null-terminated). The buffer should be
- * of length length which includes space for the null-terminator.
+ * Writes an AIBinder to the next location in a non-null parcel. Can be null. This does not take any
+ * refcounts of ownership of the binder from the client.
*
- * See also AParcel_readString.
+ * \param parcel the parcel to write to.
+ * \param binder the value to write to the parcel.
*
- * If allocation fails, null should be returned.
- */
-typedef char* (*AParcel_stringAllocator)(void* stringData, size_t length);
-
-/**
- * Writes an AIBinder to the next location in a non-null parcel. Can be null.
+ * \return STATUS_OK on successful write.
*/
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.
+ * Reads an AIBinder from the next location in a non-null parcel. One strong ref-count of ownership
+ * is passed to the caller of this function.
+ *
+ * \param parcel the parcel to read from.
+ * \param binder the out parameter for what is read from the parcel. This may be null.
+ *
+ * \return STATUS_OK on successful write.
*/
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.
+ * Writes a file descriptor to the next location in a non-null parcel. This does not take ownership
+ * of fd.
+ *
+ * This corresponds to the SDK's android.os.ParcelFileDescriptor.
+ *
+ * \param parcel the parcel to write to.
+ * \param fd the value to write to the parcel (-1 to represent a null ParcelFileDescriptor).
+ *
+ * \return STATUS_OK on successful write.
*/
-binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder** binder)
- __INTRODUCED_IN(29);
+binder_status_t AParcel_writeParcelFileDescriptor(AParcel* parcel, int fd);
+
+/**
+ * Reads an int from the next location in a non-null parcel.
+ *
+ * The returned fd must be closed.
+ *
+ * This corresponds to the SDK's android.os.ParcelFileDescriptor.
+ *
+ * \param parcel the parcel to read from.
+ * \param fd the out parameter for what is read from the parcel (or -1 to represent a null
+ * ParcelFileDescriptor)
+ *
+ * \return STATUS_OK on successful write.
+ */
+binder_status_t AParcel_readParcelFileDescriptor(const AParcel* parcel, int* fd);
/**
* Writes an AStatus object to the next location in a non-null parcel.
@@ -200,6 +443,11 @@
* 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.
+ *
+ * \param parcel the parcel to write to.
+ * \param status the value to write to the parcel.
+ *
+ * \return STATUS_OK on successful write.
*/
binder_status_t AParcel_writeStatusHeader(AParcel* parcel, const AStatus* status)
__INTRODUCED_IN(29);
@@ -207,151 +455,375 @@
/**
* Reads an AStatus from the next location in a non-null parcel. Ownership is passed to the caller
* of this function.
+ *
+ * \param parcel the parcel to read from.
+ * \param status the out parameter for what is read from the parcel.
+ *
+ * \return STATUS_OK on successful write.
*/
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.
+ * Writes utf-8 string value to the next location in a non-null parcel.
+ *
+ * If length is -1, and string is nullptr, this will write a 'null' string to the parcel.
+ *
+ * \param parcel the parcel to write to.
+ * \param string the null-terminated string to write to the parcel, at least of size 'length'.
+ * \param length the length of the string to be written.
+ *
+ * \return STATUS_OK on successful write.
*/
-binder_status_t AParcel_writeString(AParcel* parcel, const char* string, size_t length)
+binder_status_t AParcel_writeString(AParcel* parcel, const char* string, int32_t length)
__INTRODUCED_IN(29);
/**
- * Reads and allocates string value from the next location in a non-null parcel.
+ * Reads and allocates utf-8 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 size includes the
* space for the null-terminator of this string. This allocator returns a buffer which is used as
- * the output buffer from this read.
+ * the output buffer from this read. If there is a 'null' string on the binder buffer, the allocator
+ * will be called with length -1.
+ *
+ * \param parcel the parcel to read from.
+ * \param stringData some external representation of a string.
+ * \param allocator allocator that will be called once the size of the string is known.
+ *
+ * \return STATUS_OK on successful write.
*/
-binder_status_t AParcel_readString(const AParcel* parcel, AParcel_stringAllocator allocator,
- void* stringData) __INTRODUCED_IN(29);
+binder_status_t AParcel_readString(const AParcel* parcel, void* stringData,
+ AParcel_stringAllocator allocator) __INTRODUCED_IN(29);
+
+/**
+ * Writes utf-8 string array data to the next location in a non-null parcel.
+ *
+ * length is the length of the array. AParcel_stringArrayElementGetter will be called for all
+ * indices in range [0, length) with the arrayData provided here. The string length and buffer
+ * returned from this function will be used to fill out the data from the parcel. If length is -1,
+ * this will write a 'null' string array to the binder buffer.
+ *
+ * \param parcel the parcel to write to.
+ * \param arrayData some external representation of an array.
+ * \param length the length of the array to be written.
+ * \param getter the callback that will be called for every index of the array to retrieve the
+ * corresponding string buffer.
+ *
+ * \return STATUS_OK on successful write.
+ */
+binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData, int32_t length,
+ AParcel_stringArrayElementGetter getter)
+ __INTRODUCED_IN(29);
+
+/**
+ * Reads and allocates utf-8 string array value from the next location in a non-null parcel.
+ *
+ * First, AParcel_stringArrayAllocator will be called with the size of the array to be read where
+ * length is the length of the array to be read from the parcel. Then, for each index i in [0,
+ * length), AParcel_stringArrayElementAllocator will be called with the length of the string to be
+ * read from the parcel. The resultant buffer from each of these calls will be filled according to
+ * the contents of the string that is read. If the string array being read is 'null', this will
+ * instead just pass -1 to AParcel_stringArrayAllocator.
+ *
+ * \param parcel the parcel to read from.
+ * \param arrayData some external representation of an array.
+ * \param allocator the callback that will be called with arrayData once the size of the output
+ * array is known.
+ * \param elementAllocator the callback that will be called on every index of arrayData to allocate
+ * the string at that location.
+ *
+ * \return STATUS_OK on successful read.
+ */
+binder_status_t AParcel_readStringArray(const AParcel* parcel, void* arrayData,
+ AParcel_stringArrayAllocator allocator,
+ AParcel_stringArrayElementAllocator elementAllocator)
+ __INTRODUCED_IN(29);
+
+/**
+ * Writes an array of parcelables (user-defined types) to the next location in a non-null parcel.
+ *
+ * \param parcel the parcel to write to.
+ * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
+ * \param length the length of arrayData or -1 if this represents a null array.
+ * \param elementWriter function to be called for every array index to write the user-defined type
+ * at that location.
+ *
+ * \return STATUS_OK on successful write.
+ */
+binder_status_t AParcel_writeParcelableArray(AParcel* parcel, const void* arrayData, int32_t length,
+ AParcel_writeParcelableElement elementWriter)
+ __INTRODUCED_IN(29);
+
+/**
+ * Reads an array of parcelables (user-defined types) from the next location in a non-null parcel.
+ *
+ * First, allocator will be called with the length of the array. If the allocation succeeds and the
+ * length is greater than zero, elementReader will be called for every index to read the
+ * corresponding parcelable.
+ *
+ * \param parcel the parcel to read from.
+ * \param arrayData some external representation of an array.
+ * \param allocator the callback that will be called to allocate the array.
+ * \param elementReader the callback that will be called to fill out individual elements.
+ *
+ * \return STATUS_OK on successful read.
+ */
+binder_status_t AParcel_readParcelableArray(const AParcel* parcel, void* arrayData,
+ AParcel_parcelableArrayAllocator allocator,
+ AParcel_readParcelableElement elementReader)
+ __INTRODUCED_IN(29);
// @START-PRIMITIVE-READ-WRITE
/**
* Writes int32_t value to the next location in a non-null parcel.
+ *
+ * \param parcel the parcel to write to.
+ * \param value the value to write to the parcel.
+ *
+ * \return STATUS_OK on successful write.
*/
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.
+ *
+ * \param parcel the parcel to write to.
+ * \param value the value to write to the parcel.
+ *
+ * \return STATUS_OK on successful write.
*/
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.
+ *
+ * \param parcel the parcel to write to.
+ * \param value the value to write to the parcel.
+ *
+ * \return STATUS_OK on successful write.
*/
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.
+ *
+ * \param parcel the parcel to write to.
+ * \param value the value to write to the parcel.
+ *
+ * \return STATUS_OK on successful write.
*/
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.
+ *
+ * \param parcel the parcel to write to.
+ * \param value the value to write to the parcel.
+ *
+ * \return STATUS_OK on successful write.
*/
binder_status_t AParcel_writeFloat(AParcel* parcel, float value) __INTRODUCED_IN(29);
/**
* Writes double value to the next location in a non-null parcel.
+ *
+ * \param parcel the parcel to write to.
+ * \param value the value to write to the parcel.
+ *
+ * \return STATUS_OK on successful write.
*/
binder_status_t AParcel_writeDouble(AParcel* parcel, double value) __INTRODUCED_IN(29);
/**
* Writes bool value to the next location in a non-null parcel.
+ *
+ * \param parcel the parcel to write to.
+ * \param value the value to write to the parcel.
+ *
+ * \return STATUS_OK on successful write.
*/
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.
+ *
+ * \param parcel the parcel to write to.
+ * \param value the value to write to the parcel.
+ *
+ * \return STATUS_OK on successful write.
*/
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.
+ *
+ * \param parcel the parcel to write to.
+ * \param value the value to write to the parcel.
+ *
+ * \return STATUS_OK on successful write.
*/
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.
+ *
+ * \param parcel the parcel to read from.
+ * \param value the value to read from the parcel.
+ *
+ * \return STATUS_OK on successful read.
*/
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.
+ *
+ * \param parcel the parcel to read from.
+ * \param value the value to read from the parcel.
+ *
+ * \return STATUS_OK on successful read.
*/
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.
+ *
+ * \param parcel the parcel to read from.
+ * \param value the value to read from the parcel.
+ *
+ * \return STATUS_OK on successful read.
*/
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.
+ *
+ * \param parcel the parcel to read from.
+ * \param value the value to read from the parcel.
+ *
+ * \return STATUS_OK on successful read.
*/
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.
+ *
+ * \param parcel the parcel to read from.
+ * \param value the value to read from the parcel.
+ *
+ * \return STATUS_OK on successful read.
*/
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.
+ *
+ * \param parcel the parcel to read from.
+ * \param value the value to read from the parcel.
+ *
+ * \return STATUS_OK on successful read.
*/
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.
+ *
+ * \param parcel the parcel to read from.
+ * \param value the value to read from the parcel.
+ *
+ * \return STATUS_OK on successful read.
*/
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.
+ *
+ * \param parcel the parcel to read from.
+ * \param value the value to read from the parcel.
+ *
+ * \return STATUS_OK on successful read.
*/
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.
+ *
+ * \param parcel the parcel to read from.
+ * \param value the value to read from the parcel.
+ *
+ * \return STATUS_OK on successful read.
*/
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.
+ *
+ * \param parcel the parcel to write to.
+ * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
+ * \param length the length of arrayData or -1 if this represents a null array.
+ *
+ * \return STATUS_OK on successful write.
*/
-binder_status_t AParcel_writeInt32Array(AParcel* parcel, const int32_t* value, size_t length)
+binder_status_t AParcel_writeInt32Array(AParcel* parcel, const int32_t* arrayData, int32_t length)
__INTRODUCED_IN(29);
/**
* Writes an array of uint32_t to the next location in a non-null parcel.
+ *
+ * \param parcel the parcel to write to.
+ * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
+ * \param length the length of arrayData or -1 if this represents a null array.
+ *
+ * \return STATUS_OK on successful write.
*/
-binder_status_t AParcel_writeUint32Array(AParcel* parcel, const uint32_t* value, size_t length)
+binder_status_t AParcel_writeUint32Array(AParcel* parcel, const uint32_t* arrayData, int32_t length)
__INTRODUCED_IN(29);
/**
* Writes an array of int64_t to the next location in a non-null parcel.
+ *
+ * \param parcel the parcel to write to.
+ * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
+ * \param length the length of arrayData or -1 if this represents a null array.
+ *
+ * \return STATUS_OK on successful write.
*/
-binder_status_t AParcel_writeInt64Array(AParcel* parcel, const int64_t* value, size_t length)
+binder_status_t AParcel_writeInt64Array(AParcel* parcel, const int64_t* arrayData, int32_t length)
__INTRODUCED_IN(29);
/**
* Writes an array of uint64_t to the next location in a non-null parcel.
+ *
+ * \param parcel the parcel to write to.
+ * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
+ * \param length the length of arrayData or -1 if this represents a null array.
+ *
+ * \return STATUS_OK on successful write.
*/
-binder_status_t AParcel_writeUint64Array(AParcel* parcel, const uint64_t* value, size_t length)
+binder_status_t AParcel_writeUint64Array(AParcel* parcel, const uint64_t* arrayData, int32_t length)
__INTRODUCED_IN(29);
/**
* Writes an array of float to the next location in a non-null parcel.
+ *
+ * \param parcel the parcel to write to.
+ * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
+ * \param length the length of arrayData or -1 if this represents a null array.
+ *
+ * \return STATUS_OK on successful write.
*/
-binder_status_t AParcel_writeFloatArray(AParcel* parcel, const float* value, size_t length)
+binder_status_t AParcel_writeFloatArray(AParcel* parcel, const float* arrayData, int32_t length)
__INTRODUCED_IN(29);
/**
* Writes an array of double to the next location in a non-null parcel.
+ *
+ * \param parcel the parcel to write to.
+ * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
+ * \param length the length of arrayData or -1 if this represents a null array.
+ *
+ * \return STATUS_OK on successful write.
*/
-binder_status_t AParcel_writeDoubleArray(AParcel* parcel, const double* value, size_t length)
+binder_status_t AParcel_writeDoubleArray(AParcel* parcel, const double* arrayData, int32_t length)
__INTRODUCED_IN(29);
/**
@@ -359,21 +831,39 @@
*
* getter(arrayData, i) will be called for each i in [0, length) in order to get the underlying
* values to write to the parcel.
+ *
+ * \param parcel the parcel to write to.
+ * \param arrayData some external representation of an array.
+ * \param length the length of arrayData (or -1 if this represents a null array).
+ * \param getter the callback to retrieve data at specific locations in the array.
+ *
+ * \return STATUS_OK on successful write.
*/
-binder_status_t AParcel_writeBoolArray(AParcel* parcel, const void* arrayData,
- AParcel_boolArrayGetter getter, size_t length)
- __INTRODUCED_IN(29);
+binder_status_t AParcel_writeBoolArray(AParcel* parcel, const void* arrayData, int32_t length,
+ AParcel_boolArrayGetter getter) __INTRODUCED_IN(29);
/**
* Writes an array of char16_t to the next location in a non-null parcel.
+ *
+ * \param parcel the parcel to write to.
+ * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
+ * \param length the length of arrayData or -1 if this represents a null array.
+ *
+ * \return STATUS_OK on successful write.
*/
-binder_status_t AParcel_writeCharArray(AParcel* parcel, const char16_t* value, size_t length)
+binder_status_t AParcel_writeCharArray(AParcel* parcel, const char16_t* arrayData, int32_t length)
__INTRODUCED_IN(29);
/**
* Writes an array of int8_t to the next location in a non-null parcel.
+ *
+ * \param parcel the parcel to write to.
+ * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
+ * \param length the length of arrayData or -1 if this represents a null array.
+ *
+ * \return STATUS_OK on successful write.
*/
-binder_status_t AParcel_writeByteArray(AParcel* parcel, const int8_t* value, size_t length)
+binder_status_t AParcel_writeByteArray(AParcel* parcel, const int8_t* arrayData, int32_t length)
__INTRODUCED_IN(29);
/**
@@ -382,9 +872,15 @@
* First, allocator will be called with the length of the array. If the allocation succeeds and the
* length is greater than zero, the buffer returned by the allocator will be filled with the
* corresponding data
+ *
+ * \param parcel the parcel to read from.
+ * \param arrayData some external representation of an array.
+ * \param allocator the callback that will be called to allocate the array.
+ *
+ * \return STATUS_OK on successful read.
*/
binder_status_t AParcel_readInt32Array(const AParcel* parcel, void* arrayData,
- AParcel_int32Allocator allocator) __INTRODUCED_IN(29);
+ AParcel_int32ArrayAllocator allocator) __INTRODUCED_IN(29);
/**
* Reads an array of uint32_t from the next location in a non-null parcel.
@@ -392,9 +888,15 @@
* First, allocator will be called with the length of the array. If the allocation succeeds and the
* length is greater than zero, the buffer returned by the allocator will be filled with the
* corresponding data
+ *
+ * \param parcel the parcel to read from.
+ * \param arrayData some external representation of an array.
+ * \param allocator the callback that will be called to allocate the array.
+ *
+ * \return STATUS_OK on successful read.
*/
binder_status_t AParcel_readUint32Array(const AParcel* parcel, void* arrayData,
- AParcel_uint32Allocator allocator) __INTRODUCED_IN(29);
+ AParcel_uint32ArrayAllocator allocator) __INTRODUCED_IN(29);
/**
* Reads an array of int64_t from the next location in a non-null parcel.
@@ -402,9 +904,15 @@
* First, allocator will be called with the length of the array. If the allocation succeeds and the
* length is greater than zero, the buffer returned by the allocator will be filled with the
* corresponding data
+ *
+ * \param parcel the parcel to read from.
+ * \param arrayData some external representation of an array.
+ * \param allocator the callback that will be called to allocate the array.
+ *
+ * \return STATUS_OK on successful read.
*/
binder_status_t AParcel_readInt64Array(const AParcel* parcel, void* arrayData,
- AParcel_int64Allocator allocator) __INTRODUCED_IN(29);
+ AParcel_int64ArrayAllocator allocator) __INTRODUCED_IN(29);
/**
* Reads an array of uint64_t from the next location in a non-null parcel.
@@ -412,9 +920,15 @@
* First, allocator will be called with the length of the array. If the allocation succeeds and the
* length is greater than zero, the buffer returned by the allocator will be filled with the
* corresponding data
+ *
+ * \param parcel the parcel to read from.
+ * \param arrayData some external representation of an array.
+ * \param allocator the callback that will be called to allocate the array.
+ *
+ * \return STATUS_OK on successful read.
*/
binder_status_t AParcel_readUint64Array(const AParcel* parcel, void* arrayData,
- AParcel_uint64Allocator allocator) __INTRODUCED_IN(29);
+ AParcel_uint64ArrayAllocator allocator) __INTRODUCED_IN(29);
/**
* Reads an array of float from the next location in a non-null parcel.
@@ -422,9 +936,15 @@
* First, allocator will be called with the length of the array. If the allocation succeeds and the
* length is greater than zero, the buffer returned by the allocator will be filled with the
* corresponding data
+ *
+ * \param parcel the parcel to read from.
+ * \param arrayData some external representation of an array.
+ * \param allocator the callback that will be called to allocate the array.
+ *
+ * \return STATUS_OK on successful read.
*/
binder_status_t AParcel_readFloatArray(const AParcel* parcel, void* arrayData,
- AParcel_floatAllocator allocator) __INTRODUCED_IN(29);
+ AParcel_floatArrayAllocator allocator) __INTRODUCED_IN(29);
/**
* Reads an array of double from the next location in a non-null parcel.
@@ -432,18 +952,32 @@
* First, allocator will be called with the length of the array. If the allocation succeeds and the
* length is greater than zero, the buffer returned by the allocator will be filled with the
* corresponding data
+ *
+ * \param parcel the parcel to read from.
+ * \param arrayData some external representation of an array.
+ * \param allocator the callback that will be called to allocate the array.
+ *
+ * \return STATUS_OK on successful read.
*/
binder_status_t AParcel_readDoubleArray(const AParcel* parcel, void* arrayData,
- AParcel_doubleAllocator allocator) __INTRODUCED_IN(29);
+ AParcel_doubleArrayAllocator allocator) __INTRODUCED_IN(29);
/**
* Reads an array of bool from the next location in a non-null parcel.
*
* First, allocator will be called with the length of the array. Then, for every i in [0, length),
* setter(arrayData, i, x) will be called where x is the value at the associated index.
+ *
+ * \param parcel the parcel to read from.
+ * \param arrayData some external representation of an array.
+ * \param allocator the callback that will be called to allocate the array.
+ * \param setter the callback that will be called to set a value at a specific location in the
+ * array.
+ *
+ * \return STATUS_OK on successful read.
*/
binder_status_t AParcel_readBoolArray(const AParcel* parcel, void* arrayData,
- AParcel_boolAllocator allocator,
+ AParcel_boolArrayAllocator allocator,
AParcel_boolArraySetter setter) __INTRODUCED_IN(29);
/**
@@ -452,9 +986,15 @@
* First, allocator will be called with the length of the array. If the allocation succeeds and the
* length is greater than zero, the buffer returned by the allocator will be filled with the
* corresponding data
+ *
+ * \param parcel the parcel to read from.
+ * \param arrayData some external representation of an array.
+ * \param allocator the callback that will be called to allocate the array.
+ *
+ * \return STATUS_OK on successful read.
*/
binder_status_t AParcel_readCharArray(const AParcel* parcel, void* arrayData,
- AParcel_charAllocator allocator) __INTRODUCED_IN(29);
+ AParcel_charArrayAllocator allocator) __INTRODUCED_IN(29);
/**
* Reads an array of int8_t from the next location in a non-null parcel.
@@ -462,13 +1002,19 @@
* First, allocator will be called with the length of the array. If the allocation succeeds and the
* length is greater than zero, the buffer returned by the allocator will be filled with the
* corresponding data
+ *
+ * \param parcel the parcel to read from.
+ * \param arrayData some external representation of an array.
+ * \param allocator the callback that will be called to allocate the array.
+ *
+ * \return STATUS_OK on successful read.
*/
binder_status_t AParcel_readByteArray(const AParcel* parcel, void* arrayData,
- AParcel_byteAllocator allocator) __INTRODUCED_IN(29);
+ AParcel_byteArrayAllocator allocator) __INTRODUCED_IN(29);
// @END-PRIMITIVE-READ-WRITE
-#endif //__ANDROID_API__ >= __ANDROID_API_Q__
+#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
index 6e41a7f..f3bc31b 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
@@ -26,39 +26,103 @@
#pragma once
+#include <android/binder_auto_utils.h>
#include <android/binder_parcel.h>
-#ifdef __cplusplus
-
+#include <optional>
#include <string>
#include <vector>
namespace ndk {
/**
- * This retrieves and allocates a vector to length length and returns the underlying buffer.
+ * This retrieves and allocates a vector to size 'length' and returns the underlying buffer.
*/
template <typename T>
-static inline T* AParcel_stdVectorAllocator(void* vectorData, size_t length) {
+static inline bool AParcel_stdVectorAllocator(void* vectorData, int32_t length, T** outBuffer) {
+ if (length < 0) return false;
+
std::vector<T>* vec = static_cast<std::vector<T>*>(vectorData);
- if (length > vec->max_size()) return nullptr;
+ if (static_cast<size_t>(length) > vec->max_size()) return false;
vec->resize(length);
- return vec->data();
+ *outBuffer = vec->data();
+ return true;
}
/**
- * This allocates a vector to length length and returns whether the allocation is successful.
+ * This retrieves and allocates a vector to size 'length' and returns the underlying buffer.
*/
-static inline bool AParcel_stdVectorBoolAllocator(void* vectorData, size_t length) {
- std::vector<bool>* vec = static_cast<std::vector<bool>*>(vectorData);
- if (length > vec->max_size()) return false;
+template <typename T>
+static inline bool AParcel_nullableStdVectorAllocator(void* vectorData, int32_t length,
+ T** outBuffer) {
+ std::optional<std::vector<T>>* vec = static_cast<std::optional<std::vector<T>>*>(vectorData);
+
+ if (length < 0) {
+ *vec = std::nullopt;
+ return true;
+ }
+
+ *vec = std::optional<std::vector<T>>(std::vector<T>{});
+
+ if (static_cast<size_t>(length) > (*vec)->max_size()) return false;
+ (*vec)->resize(length);
+
+ *outBuffer = (*vec)->data();
+ return true;
+}
+
+/**
+ * This allocates a vector to size 'length' and returns whether the allocation is successful.
+ *
+ * See also AParcel_stdVectorAllocator. Types used with this allocator have their sizes defined
+ * externally with respect to the NDK, and that size information is not passed into the NDK.
+ * Instead, it is used in cases where callbacks are used. Note that when this allocator is used,
+ * null arrays are not supported.
+ *
+ * See AParcel_readVector(const AParcel* parcel, std::vector<bool>)
+ * See AParcel_readVector(const AParcel* parcel, std::vector<std::string>)
+ */
+template <typename T>
+static inline bool AParcel_stdVectorExternalAllocator(void* vectorData, int32_t length) {
+ if (length < 0) return false;
+
+ std::vector<T>* vec = static_cast<std::vector<T>*>(vectorData);
+ if (static_cast<size_t>(length) > vec->max_size()) return false;
vec->resize(length);
return true;
}
/**
+ * This allocates a vector to size 'length' and returns whether the allocation is successful.
+ *
+ * See also AParcel_stdVectorAllocator. Types used with this allocator have their sizes defined
+ * externally with respect to the NDK, and that size information is not passed into the NDK.
+ * Instead, it is used in cases where callbacks are used. Note, when this allocator is used,
+ * the vector itself can be nullable.
+ *
+ * See AParcel_readVector(const AParcel* parcel,
+ * std::optional<std::vector<std::optional<std::string>>>)
+ */
+template <typename T>
+static inline bool AParcel_nullableStdVectorExternalAllocator(void* vectorData, int32_t length) {
+ std::optional<std::vector<T>>* vec = static_cast<std::optional<std::vector<T>>*>(vectorData);
+
+ if (length < 0) {
+ *vec = std::nullopt;
+ return true;
+ }
+
+ *vec = std::optional<std::vector<T>>(std::vector<T>{});
+
+ if (static_cast<size_t>(length) > (*vec)->max_size()) return false;
+ (*vec)->resize(length);
+
+ return true;
+}
+
+/**
* This retrieves the underlying value in a vector which may not be contiguous at index from a
* corresponding vectorData.
*/
@@ -78,154 +142,203 @@
(*vec)[index] = value;
}
-// @START
/**
- * Writes a vector of int32_t to the next location in a non-null parcel.
+ * This sets the underlying value in a corresponding vectorData which may not be contiguous at
+ * index.
*/
-inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<int32_t>& vec) {
- return AParcel_writeInt32Array(parcel, vec.data(), vec.size());
+template <typename T>
+static inline void AParcel_nullableStdVectorSetter(void* vectorData, size_t index, T value) {
+ std::optional<std::vector<T>>* vec = static_cast<std::optional<std::vector<T>>*>(vectorData);
+ vec->value()[index] = value;
}
/**
- * Reads a vector of int32_t from the next location in a non-null parcel.
+ * Convenience method to write a nullable strong binder.
*/
-inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<int32_t>* vec) {
- void* vectorData = static_cast<void*>(vec);
- return AParcel_readInt32Array(parcel, vectorData, AParcel_stdVectorAllocator<int32_t>);
+static inline binder_status_t AParcel_writeNullableStrongBinder(AParcel* parcel,
+ const SpAIBinder& binder) {
+ return AParcel_writeStrongBinder(parcel, binder.get());
}
/**
- * Writes a vector of uint32_t to the next location in a non-null parcel.
+ * Convenience method to read a nullable strong binder.
*/
-inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<uint32_t>& vec) {
- return AParcel_writeUint32Array(parcel, vec.data(), vec.size());
+static inline binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel,
+ SpAIBinder* binder) {
+ AIBinder* readBinder;
+ binder_status_t status = AParcel_readStrongBinder(parcel, &readBinder);
+ if (status == STATUS_OK) {
+ binder->set(readBinder);
+ }
+ return status;
}
/**
- * Reads a vector of uint32_t from the next location in a non-null parcel.
+ * Convenience method to write a strong binder but return an error if it is null.
*/
-inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<uint32_t>* vec) {
- void* vectorData = static_cast<void*>(vec);
- return AParcel_readUint32Array(parcel, vectorData, AParcel_stdVectorAllocator<uint32_t>);
+static inline binder_status_t AParcel_writeRequiredStrongBinder(AParcel* parcel,
+ const SpAIBinder& binder) {
+ if (binder.get() == nullptr) {
+ return STATUS_UNEXPECTED_NULL;
+ }
+ return AParcel_writeStrongBinder(parcel, binder.get());
}
/**
- * Writes a vector of int64_t to the next location in a non-null parcel.
+ * Convenience method to read a strong binder but return an error if it is null.
*/
-inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<int64_t>& vec) {
- return AParcel_writeInt64Array(parcel, vec.data(), vec.size());
+static inline binder_status_t AParcel_readRequiredStrongBinder(const AParcel* parcel,
+ SpAIBinder* binder) {
+ AIBinder* readBinder;
+ binder_status_t ret = AParcel_readStrongBinder(parcel, &readBinder);
+ if (ret == STATUS_OK) {
+ if (readBinder == nullptr) {
+ return STATUS_UNEXPECTED_NULL;
+ }
+
+ binder->set(readBinder);
+ }
+ return ret;
}
/**
- * Reads a vector of int64_t from the next location in a non-null parcel.
+ * Convenience method to write a ParcelFileDescriptor where -1 represents a null value.
*/
-inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<int64_t>* vec) {
- void* vectorData = static_cast<void*>(vec);
- return AParcel_readInt64Array(parcel, vectorData, AParcel_stdVectorAllocator<int64_t>);
+static inline binder_status_t AParcel_writeNullableParcelFileDescriptor(
+ AParcel* parcel, const ScopedFileDescriptor& fd) {
+ return AParcel_writeParcelFileDescriptor(parcel, fd.get());
}
/**
- * Writes a vector of uint64_t to the next location in a non-null parcel.
+ * Convenience method to read a ParcelFileDescriptor where -1 represents a null value.
*/
-inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<uint64_t>& vec) {
- return AParcel_writeUint64Array(parcel, vec.data(), vec.size());
+static inline binder_status_t AParcel_readNullableParcelFileDescriptor(const AParcel* parcel,
+ ScopedFileDescriptor* fd) {
+ int readFd;
+ binder_status_t status = AParcel_readParcelFileDescriptor(parcel, &readFd);
+ if (status == STATUS_OK) {
+ fd->set(readFd);
+ }
+ return status;
}
/**
- * Reads a vector of uint64_t from the next location in a non-null parcel.
+ * Convenience method to write a valid ParcelFileDescriptor.
*/
-inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<uint64_t>* vec) {
- void* vectorData = static_cast<void*>(vec);
- return AParcel_readUint64Array(parcel, vectorData, AParcel_stdVectorAllocator<uint64_t>);
+static inline binder_status_t AParcel_writeRequiredParcelFileDescriptor(
+ AParcel* parcel, const ScopedFileDescriptor& fd) {
+ if (fd.get() < 0) {
+ return STATUS_UNEXPECTED_NULL;
+ }
+ return AParcel_writeParcelFileDescriptor(parcel, fd.get());
}
/**
- * Writes a vector of float to the next location in a non-null parcel.
+ * Convenience method to read a valid ParcelFileDescriptor.
*/
-inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<float>& vec) {
- return AParcel_writeFloatArray(parcel, vec.data(), vec.size());
+static inline binder_status_t AParcel_readRequiredParcelFileDescriptor(const AParcel* parcel,
+ ScopedFileDescriptor* fd) {
+ int readFd;
+ binder_status_t status = AParcel_readParcelFileDescriptor(parcel, &readFd);
+ if (status == STATUS_OK) {
+ if (readFd < 0) {
+ return STATUS_UNEXPECTED_NULL;
+ }
+ fd->set(readFd);
+ }
+ return status;
}
/**
- * Reads a vector of float from the next location in a non-null parcel.
- */
-inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<float>* vec) {
- void* vectorData = static_cast<void*>(vec);
- return AParcel_readFloatArray(parcel, vectorData, AParcel_stdVectorAllocator<float>);
-}
-
-/**
- * Writes a vector of double to the next location in a non-null parcel.
- */
-inline binder_status_t AParcel_writeVector(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.
- */
-inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<double>* vec) {
- void* vectorData = static_cast<void*>(vec);
- return AParcel_readDoubleArray(parcel, vectorData, AParcel_stdVectorAllocator<double>);
-}
-
-/**
- * Writes a vector of bool to the next location in a non-null parcel.
- */
-inline binder_status_t AParcel_writeVector(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.
- */
-inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<bool>* vec) {
- void* vectorData = static_cast<void*>(vec);
- return AParcel_readBoolArray(parcel, vectorData, AParcel_stdVectorBoolAllocator,
- AParcel_stdVectorSetter<bool>);
-}
-
-/**
- * Writes a vector of char16_t to the next location in a non-null parcel.
- */
-inline binder_status_t AParcel_writeVector(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.
- */
-inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<char16_t>* vec) {
- void* vectorData = static_cast<void*>(vec);
- return AParcel_readCharArray(parcel, vectorData, AParcel_stdVectorAllocator<char16_t>);
-}
-
-/**
- * Writes a vector of int8_t to the next location in a non-null parcel.
- */
-inline binder_status_t AParcel_writeVector(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.
- */
-inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<int8_t>* vec) {
- void* vectorData = static_cast<void*>(vec);
- return AParcel_readByteArray(parcel, vectorData, AParcel_stdVectorAllocator<int8_t>);
-}
-
-// @END
-
-/**
* Allocates a std::string to length and returns the underlying buffer. For use with
* AParcel_readString. See use below in AParcel_readString(const AParcel*, std::string*).
*/
-static inline char* AParcel_stdStringAllocator(void* stringData, size_t length) {
+static inline bool AParcel_stdStringAllocator(void* stringData, int32_t length, char** buffer) {
+ if (length <= 0) return false;
+
std::string* str = static_cast<std::string*>(stringData);
str->resize(length - 1);
- return &(*str)[0];
+ *buffer = &(*str)[0];
+ return true;
+}
+
+/**
+ * Allocates a string in a std::optional<std::string> to size 'length' (or to std::nullopt when
+ * length is -1) and returns the underlying buffer. For use with AParcel_readString. See use below
+ * in AParcel_readString(const AParcel*, std::optional<std::string>*).
+ */
+static inline bool AParcel_nullableStdStringAllocator(void* stringData, int32_t length,
+ char** buffer) {
+ if (length == 0) return false;
+
+ std::optional<std::string>* str = static_cast<std::optional<std::string>*>(stringData);
+
+ if (length < 0) {
+ *str = std::nullopt;
+ return true;
+ }
+
+ *str = std::optional<std::string>(std::string{});
+ (*str)->resize(length - 1);
+ *buffer = &(**str)[0];
+ return true;
+}
+
+/**
+ * Allocates a std::string inside of a std::vector<std::string> at index 'index' to size 'length'.
+ */
+static inline bool AParcel_stdVectorStringElementAllocator(void* vectorData, size_t index,
+ int32_t length, char** buffer) {
+ std::vector<std::string>* vec = static_cast<std::vector<std::string>*>(vectorData);
+ std::string& element = vec->at(index);
+ return AParcel_stdStringAllocator(static_cast<void*>(&element), length, buffer);
+}
+
+/**
+ * This gets the length and buffer of a std::string inside of a std::vector<std::string> at index
+ * index.
+ */
+static inline const char* AParcel_stdVectorStringElementGetter(const void* vectorData, size_t index,
+ int32_t* outLength) {
+ const std::vector<std::string>* vec = static_cast<const std::vector<std::string>*>(vectorData);
+ const std::string& element = vec->at(index);
+
+ *outLength = element.size();
+ return element.c_str();
+}
+
+/**
+ * Allocates a string in a std::optional<std::string> inside of a
+ * std::optional<std::vector<std::optional<std::string>>> at index 'index' to size 'length' (or to
+ * std::nullopt when length is -1).
+ */
+static inline bool AParcel_nullableStdVectorStringElementAllocator(void* vectorData, size_t index,
+ int32_t length, char** buffer) {
+ std::optional<std::vector<std::optional<std::string>>>* vec =
+ static_cast<std::optional<std::vector<std::optional<std::string>>>*>(vectorData);
+ std::optional<std::string>& element = vec->value().at(index);
+ return AParcel_nullableStdStringAllocator(static_cast<void*>(&element), length, buffer);
+}
+
+/**
+ * This gets the length and buffer of a std::optional<std::string> inside of a
+ * std::vector<std::string> at index index. If the string is null, then it returns null and a length
+ * of -1.
+ */
+static inline const char* AParcel_nullableStdVectorStringElementGetter(const void* vectorData,
+ size_t index,
+ int32_t* outLength) {
+ const std::optional<std::vector<std::optional<std::string>>>* vec =
+ static_cast<const std::optional<std::vector<std::optional<std::string>>>*>(vectorData);
+ const std::optional<std::string>& element = vec->value().at(index);
+
+ if (!element) {
+ *outLength = -1;
+ return nullptr;
+ }
+
+ *outLength = element->size();
+ return element->c_str();
}
/**
@@ -240,9 +353,422 @@
*/
static inline binder_status_t AParcel_readString(const AParcel* parcel, std::string* str) {
void* stringData = static_cast<void*>(str);
- return AParcel_readString(parcel, AParcel_stdStringAllocator, stringData);
+ return AParcel_readString(parcel, stringData, AParcel_stdStringAllocator);
}
+/**
+ * Convenience API for writing a std::optional<std::string>.
+ */
+static inline binder_status_t AParcel_writeString(AParcel* parcel,
+ const std::optional<std::string>& str) {
+ if (!str) {
+ return AParcel_writeString(parcel, nullptr, -1);
+ }
+
+ return AParcel_writeString(parcel, str->c_str(), str->size());
+}
+
+/**
+ * Convenience API for reading a std::optional<std::string>.
+ */
+static inline binder_status_t AParcel_readString(const AParcel* parcel,
+ std::optional<std::string>* str) {
+ void* stringData = static_cast<void*>(str);
+ return AParcel_readString(parcel, stringData, AParcel_nullableStdStringAllocator);
+}
+
+/**
+ * Convenience API for writing a std::vector<std::string>
+ */
+static inline binder_status_t AParcel_writeVector(AParcel* parcel,
+ const std::vector<std::string>& vec) {
+ const void* vectorData = static_cast<const void*>(&vec);
+ return AParcel_writeStringArray(parcel, vectorData, vec.size(),
+ AParcel_stdVectorStringElementGetter);
+}
+
+/**
+ * Convenience API for reading a std::vector<std::string>
+ */
+static inline binder_status_t AParcel_readVector(const AParcel* parcel,
+ std::vector<std::string>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readStringArray(parcel, vectorData,
+ AParcel_stdVectorExternalAllocator<std::string>,
+ AParcel_stdVectorStringElementAllocator);
+}
+
+/**
+ * Convenience API for writing a std::optional<std::vector<std::optional<std::string>>>
+ */
+static inline binder_status_t AParcel_writeVector(
+ AParcel* parcel, const std::optional<std::vector<std::optional<std::string>>>& vec) {
+ const void* vectorData = static_cast<const void*>(&vec);
+ return AParcel_writeStringArray(parcel, vectorData, (vec ? vec->size() : -1),
+ AParcel_nullableStdVectorStringElementGetter);
+}
+
+/**
+ * Convenience API for reading a std::optional<std::vector<std::optional<std::string>>>
+ */
+static inline binder_status_t AParcel_readVector(
+ const AParcel* parcel, std::optional<std::vector<std::optional<std::string>>>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readStringArray(
+ parcel, vectorData,
+ AParcel_nullableStdVectorExternalAllocator<std::optional<std::string>>,
+ AParcel_nullableStdVectorStringElementAllocator);
+}
+
+/**
+ * Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'.
+ */
+template <typename P>
+binder_status_t AParcel_writeStdVectorParcelableElement(AParcel* parcel, const void* vectorData,
+ size_t index) {
+ const std::vector<P>* vector = static_cast<const std::vector<P>*>(vectorData);
+ return vector->at(index).writeToParcel(parcel);
+}
+
+/**
+ * Reads a parcelable object of type P inside a std::vector<P> at index 'index' from 'parcel'.
+ */
+template <typename P>
+binder_status_t AParcel_readStdVectorParcelableElement(const AParcel* parcel, void* vectorData,
+ size_t index) {
+ std::vector<P>* vector = static_cast<std::vector<P>*>(vectorData);
+ return vector->at(index).readFromParcel(parcel);
+}
+
+/**
+ * Convenience API for writing a std::vector<P>
+ */
+template <typename P>
+static inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<P>& vec) {
+ const void* vectorData = static_cast<const void*>(&vec);
+ return AParcel_writeParcelableArray(parcel, vectorData, vec.size(),
+ AParcel_writeStdVectorParcelableElement<P>);
+}
+
+/**
+ * Convenience API for reading a std::vector<P>
+ */
+template <typename P>
+static inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<P>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readParcelableArray(parcel, vectorData, AParcel_stdVectorExternalAllocator<P>,
+ AParcel_readStdVectorParcelableElement<P>);
+}
+
+// @START
+/**
+ * Writes a vector of int32_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<int32_t>& vec) {
+ return AParcel_writeInt32Array(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Writes an optional vector of int32_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel,
+ const std::optional<std::vector<int32_t>>& vec) {
+ if (!vec) return AParcel_writeInt32Array(parcel, nullptr, -1);
+ return AParcel_writeVector(parcel, *vec);
+}
+
+/**
+ * Reads a vector of int32_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<int32_t>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readInt32Array(parcel, vectorData, AParcel_stdVectorAllocator<int32_t>);
+}
+
+/**
+ * Reads an optional vector of int32_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel,
+ std::optional<std::vector<int32_t>>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readInt32Array(parcel, vectorData, AParcel_nullableStdVectorAllocator<int32_t>);
+}
+
+/**
+ * Writes a vector of uint32_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<uint32_t>& vec) {
+ return AParcel_writeUint32Array(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Writes an optional vector of uint32_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel,
+ const std::optional<std::vector<uint32_t>>& vec) {
+ if (!vec) return AParcel_writeUint32Array(parcel, nullptr, -1);
+ return AParcel_writeVector(parcel, *vec);
+}
+
+/**
+ * Reads a vector of uint32_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<uint32_t>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readUint32Array(parcel, vectorData, AParcel_stdVectorAllocator<uint32_t>);
+}
+
+/**
+ * Reads an optional vector of uint32_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel,
+ std::optional<std::vector<uint32_t>>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readUint32Array(parcel, vectorData,
+ AParcel_nullableStdVectorAllocator<uint32_t>);
+}
+
+/**
+ * Writes a vector of int64_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<int64_t>& vec) {
+ return AParcel_writeInt64Array(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Writes an optional vector of int64_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel,
+ const std::optional<std::vector<int64_t>>& vec) {
+ if (!vec) return AParcel_writeInt64Array(parcel, nullptr, -1);
+ return AParcel_writeVector(parcel, *vec);
+}
+
+/**
+ * Reads a vector of int64_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<int64_t>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readInt64Array(parcel, vectorData, AParcel_stdVectorAllocator<int64_t>);
+}
+
+/**
+ * Reads an optional vector of int64_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel,
+ std::optional<std::vector<int64_t>>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readInt64Array(parcel, vectorData, AParcel_nullableStdVectorAllocator<int64_t>);
+}
+
+/**
+ * Writes a vector of uint64_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<uint64_t>& vec) {
+ return AParcel_writeUint64Array(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Writes an optional vector of uint64_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel,
+ const std::optional<std::vector<uint64_t>>& vec) {
+ if (!vec) return AParcel_writeUint64Array(parcel, nullptr, -1);
+ return AParcel_writeVector(parcel, *vec);
+}
+
+/**
+ * Reads a vector of uint64_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<uint64_t>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readUint64Array(parcel, vectorData, AParcel_stdVectorAllocator<uint64_t>);
+}
+
+/**
+ * Reads an optional vector of uint64_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel,
+ std::optional<std::vector<uint64_t>>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readUint64Array(parcel, vectorData,
+ AParcel_nullableStdVectorAllocator<uint64_t>);
+}
+
+/**
+ * Writes a vector of float to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<float>& vec) {
+ return AParcel_writeFloatArray(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Writes an optional vector of float to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel,
+ const std::optional<std::vector<float>>& vec) {
+ if (!vec) return AParcel_writeFloatArray(parcel, nullptr, -1);
+ return AParcel_writeVector(parcel, *vec);
+}
+
+/**
+ * Reads a vector of float from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<float>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readFloatArray(parcel, vectorData, AParcel_stdVectorAllocator<float>);
+}
+
+/**
+ * Reads an optional vector of float from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel,
+ std::optional<std::vector<float>>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readFloatArray(parcel, vectorData, AParcel_nullableStdVectorAllocator<float>);
+}
+
+/**
+ * Writes a vector of double to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<double>& vec) {
+ return AParcel_writeDoubleArray(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Writes an optional vector of double to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel,
+ const std::optional<std::vector<double>>& vec) {
+ if (!vec) return AParcel_writeDoubleArray(parcel, nullptr, -1);
+ return AParcel_writeVector(parcel, *vec);
+}
+
+/**
+ * Reads a vector of double from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<double>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readDoubleArray(parcel, vectorData, AParcel_stdVectorAllocator<double>);
+}
+
+/**
+ * Reads an optional vector of double from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel,
+ std::optional<std::vector<double>>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readDoubleArray(parcel, vectorData, AParcel_nullableStdVectorAllocator<double>);
+}
+
+/**
+ * Writes a vector of bool to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<bool>& vec) {
+ return AParcel_writeBoolArray(parcel, static_cast<const void*>(&vec), vec.size(),
+ AParcel_stdVectorGetter<bool>);
+}
+
+/**
+ * Writes an optional vector of bool to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel,
+ const std::optional<std::vector<bool>>& vec) {
+ if (!vec) return AParcel_writeBoolArray(parcel, nullptr, -1, AParcel_stdVectorGetter<bool>);
+ return AParcel_writeVector(parcel, *vec);
+}
+
+/**
+ * Reads a vector of bool from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<bool>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readBoolArray(parcel, vectorData, AParcel_stdVectorExternalAllocator<bool>,
+ AParcel_stdVectorSetter<bool>);
+}
+
+/**
+ * Reads an optional vector of bool from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel,
+ std::optional<std::vector<bool>>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readBoolArray(parcel, vectorData,
+ AParcel_nullableStdVectorExternalAllocator<bool>,
+ AParcel_nullableStdVectorSetter<bool>);
+}
+
+/**
+ * Writes a vector of char16_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<char16_t>& vec) {
+ return AParcel_writeCharArray(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Writes an optional vector of char16_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel,
+ const std::optional<std::vector<char16_t>>& vec) {
+ if (!vec) return AParcel_writeCharArray(parcel, nullptr, -1);
+ return AParcel_writeVector(parcel, *vec);
+}
+
+/**
+ * Reads a vector of char16_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<char16_t>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readCharArray(parcel, vectorData, AParcel_stdVectorAllocator<char16_t>);
+}
+
+/**
+ * Reads an optional vector of char16_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel,
+ std::optional<std::vector<char16_t>>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readCharArray(parcel, vectorData, AParcel_nullableStdVectorAllocator<char16_t>);
+}
+
+/**
+ * Writes a vector of int8_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<int8_t>& vec) {
+ return AParcel_writeByteArray(parcel, vec.data(), vec.size());
+}
+
+/**
+ * Writes an optional vector of int8_t to the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_writeVector(AParcel* parcel,
+ const std::optional<std::vector<int8_t>>& vec) {
+ if (!vec) return AParcel_writeByteArray(parcel, nullptr, -1);
+ return AParcel_writeVector(parcel, *vec);
+}
+
+/**
+ * Reads a vector of int8_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<int8_t>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readByteArray(parcel, vectorData, AParcel_stdVectorAllocator<int8_t>);
+}
+
+/**
+ * Reads an optional vector of int8_t from the next location in a non-null parcel.
+ */
+inline binder_status_t AParcel_readVector(const AParcel* parcel,
+ std::optional<std::vector<int8_t>>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readByteArray(parcel, vectorData, AParcel_nullableStdVectorAllocator<int8_t>);
+}
+
+// @END
+
+/**
+ * Convenience API for writing the size of a vector.
+ */
template <typename T>
static inline binder_status_t AParcel_writeVectorSize(AParcel* parcel, const std::vector<T>& vec) {
if (vec.size() > INT32_MAX) {
@@ -252,6 +778,26 @@
return AParcel_writeInt32(parcel, static_cast<int32_t>(vec.size()));
}
+/**
+ * Convenience API for writing the size of a vector.
+ */
+template <typename T>
+static inline binder_status_t AParcel_writeVectorSize(AParcel* parcel,
+ const std::optional<std::vector<T>>& vec) {
+ if (!vec) {
+ return AParcel_writeInt32(parcel, -1);
+ }
+
+ if (vec->size() > INT32_MAX) {
+ return STATUS_BAD_VALUE;
+ }
+
+ return AParcel_writeInt32(parcel, static_cast<int32_t>(vec->size()));
+}
+
+/**
+ * Convenience API for resizing a vector.
+ */
template <typename T>
static inline binder_status_t AParcel_resizeVector(const AParcel* parcel, std::vector<T>* vec) {
int32_t size;
@@ -264,8 +810,28 @@
return STATUS_OK;
}
-} // namespace ndk
+/**
+ * Convenience API for resizing a vector.
+ */
+template <typename T>
+static inline binder_status_t AParcel_resizeVector(const AParcel* parcel,
+ std::optional<std::vector<T>>* vec) {
+ int32_t size;
+ binder_status_t err = AParcel_readInt32(parcel, &size);
-#endif // __cplusplus
+ if (err != STATUS_OK) return err;
+ if (size < -1) return STATUS_UNEXPECTED_NULL;
+
+ if (size == -1) {
+ *vec = std::nullopt;
+ return STATUS_OK;
+ }
+
+ *vec = std::optional<std::vector<T>>(std::vector<T>{});
+ (*vec)->resize(static_cast<size_t>(size));
+ return STATUS_OK;
+}
+
+} // namespace ndk
/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_status.h b/libs/binder/ndk/include_ndk/android/binder_status.h
index 2d8b7fa..2671b9b 100644
--- a/libs/binder/ndk/include_ndk/android/binder_status.h
+++ b/libs/binder/ndk/include_ndk/android/binder_status.h
@@ -35,7 +35,7 @@
enum {
STATUS_OK = 0,
- STATUS_UNKNOWN_ERROR = (-2147483647 - 1), // INT32_MIN value
+ STATUS_UNKNOWN_ERROR = (-2147483647 - 1), // INT32_MIN value
STATUS_NO_MEMORY = -ENOMEM,
STATUS_INVALID_OPERATION = -ENOSYS,
STATUS_BAD_VALUE = -EINVAL,
@@ -95,24 +95,39 @@
* 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.
+ * order to be compatible with standard AIDL transactions since it is written as the header to the
+ * out parcel for transactions which get executed (don't fail during unparceling of input arguments
+ * or sooner).
*/
struct AStatus;
typedef struct AStatus AStatus;
/**
* New status which is considered a success.
+ *
+ * \return a newly constructed status object that the caller owns.
*/
__attribute__((warn_unused_result)) AStatus* AStatus_newOk() __INTRODUCED_IN(29);
/**
* New status with exception code.
+ *
+ * \param exception the code that this status should represent. If this is EX_NONE, then this
+ * constructs an non-error status object.
+ *
+ * \return a newly constructed status object that the caller owns.
*/
__attribute__((warn_unused_result)) AStatus* AStatus_fromExceptionCode(binder_exception_t exception)
__INTRODUCED_IN(29);
/**
* New status with exception code and message.
+ *
+ * \param exception the code that this status should represent. If this is EX_NONE, then this
+ * constructs an non-error status object.
+ * \param message the error message to associate with this status object.
+ *
+ * \return a newly constructed status object that the caller owns.
*/
__attribute__((warn_unused_result)) AStatus* AStatus_fromExceptionCodeWithMessage(
binder_exception_t exception, const char* message) __INTRODUCED_IN(29);
@@ -121,6 +136,10 @@
* New status with a service speciic error.
*
* This is considered to be EX_TRANSACTION_FAILED with extra information.
+ *
+ * \param serviceSpecific an implementation defined error code.
+ *
+ * \return a newly constructed status object that the caller owns.
*/
__attribute__((warn_unused_result)) AStatus* AStatus_fromServiceSpecificError(
int32_t serviceSpecific) __INTRODUCED_IN(29);
@@ -129,6 +148,11 @@
* New status with a service specific error and message.
*
* This is considered to be EX_TRANSACTION_FAILED with extra information.
+ *
+ * \param serviceSpecific an implementation defined error code.
+ * \param message the error message to associate with this status object.
+ *
+ * \return a newly constructed status object that the caller owns.
*/
__attribute__((warn_unused_result)) AStatus* AStatus_fromServiceSpecificErrorWithMessage(
int32_t serviceSpecific, const char* message) __INTRODUCED_IN(29);
@@ -137,6 +161,10 @@
* 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.
+ *
+ * \param a low-level error to associate with this status object.
+ *
+ * \return a newly constructed status object that the caller owns.
*/
__attribute__((warn_unused_result)) AStatus* AStatus_fromStatus(binder_status_t status)
__INTRODUCED_IN(29);
@@ -144,11 +172,19 @@
/**
* Whether this object represents a successful transaction. If this function returns true, then
* AStatus_getExceptionCode will return EX_NONE.
+ *
+ * \param status the status being queried.
+ *
+ * \return whether the status represents a successful transaction. For more details, see below.
*/
bool AStatus_isOk(const AStatus* status) __INTRODUCED_IN(29);
/**
* The exception that this status object represents.
+ *
+ * \param status the status being queried.
+ *
+ * \return the exception code that this object represents.
*/
binder_exception_t AStatus_getExceptionCode(const AStatus* status) __INTRODUCED_IN(29);
@@ -157,6 +193,10 @@
* 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.
+ *
+ * \param status the status being queried.
+ *
+ * \return the service-specific error code if the exception code is EX_SERVICE_SPECIFIC or 0.
*/
int32_t AStatus_getServiceSpecificError(const AStatus* status) __INTRODUCED_IN(29);
@@ -165,6 +205,10 @@
* 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.
+ *
+ * \param status the status being queried.
+ *
+ * \return the status code if the exception code is EX_TRANSACTION_FAILED or 0.
*/
binder_status_t AStatus_getStatus(const AStatus* status) __INTRODUCED_IN(29);
@@ -173,15 +217,21 @@
* message, this will return an empty string.
*
* The returned string has the lifetime of the status object passed into this function.
+ *
+ * \param status the status being queried.
+ *
+ * \return the message associated with this error.
*/
const char* AStatus_getMessage(const AStatus* status) __INTRODUCED_IN(29);
/**
* Deletes memory associated with the status instance.
+ *
+ * \param status the status to delete, returned from AStatus_newOk or one of the AStatus_from* APIs.
*/
void AStatus_delete(AStatus* status) __INTRODUCED_IN(29);
-#endif //__ANDROID_API__ >= __ANDROID_API_Q__
+#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
index f84814f..f0d25f7 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -7,6 +7,8 @@
AIBinder_debugGetRefCount;
AIBinder_decStrong;
AIBinder_fromJavaBinder;
+ AIBinder_getCallingPid;
+ AIBinder_getCallingUid;
AIBinder_getClass;
AIBinder_getUserData;
AIBinder_incStrong;
@@ -23,6 +25,7 @@
AIBinder_Weak_new;
AIBinder_Weak_promote;
AParcel_delete;
+ AParcel_getDataPosition;
AParcel_readBool;
AParcel_readBoolArray;
AParcel_readByte;
@@ -37,14 +40,17 @@
AParcel_readInt32Array;
AParcel_readInt64;
AParcel_readInt64Array;
- AParcel_readNullableStrongBinder;
+ AParcel_readParcelableArray;
+ AParcel_readParcelFileDescriptor;
AParcel_readStatusHeader;
AParcel_readString;
+ AParcel_readStringArray;
AParcel_readStrongBinder;
AParcel_readUint32;
AParcel_readUint32Array;
AParcel_readUint64;
AParcel_readUint64Array;
+ AParcel_setDataPosition;
AParcel_writeBool;
AParcel_writeBoolArray;
AParcel_writeByte;
@@ -59,8 +65,11 @@
AParcel_writeInt32Array;
AParcel_writeInt64;
AParcel_writeInt64Array;
+ AParcel_writeParcelableArray;
+ AParcel_writeParcelFileDescriptor;
AParcel_writeStatusHeader;
AParcel_writeString;
+ AParcel_writeStringArray;
AParcel_writeStrongBinder;
AParcel_writeUint32;
AParcel_writeUint32Array;
@@ -78,6 +87,11 @@
AStatus_getStatus;
AStatus_isOk;
AStatus_newOk;
+ ABinderProcess_joinThreadPool; # apex
+ ABinderProcess_setThreadPoolMaxThreadCount; # apex
+ ABinderProcess_startThreadPool; # apex
+ AServiceManager_addService; # apex
+ AServiceManager_getService; # apex
local:
*;
};
diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index 5ac3965..ae2276e 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -23,37 +23,59 @@
#include <limits>
#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
#include <binder/Parcel.h>
+#include <binder/ParcelFileDescriptor.h>
#include <utils/Unicode.h>
using ::android::IBinder;
using ::android::Parcel;
using ::android::sp;
using ::android::status_t;
+using ::android::base::unique_fd;
+using ::android::os::ParcelFileDescriptor;
template <typename T>
-using ContiguousArrayAllocator = T* (*)(void* arrayData, size_t length);
+using ContiguousArrayAllocator = bool (*)(void* arrayData, int32_t length, T** outBuffer);
template <typename T>
-using ArrayAllocator = bool (*)(void* arrayData, size_t length);
+using ArrayAllocator = bool (*)(void* arrayData, int32_t length);
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;
+binder_status_t WriteAndValidateArraySize(AParcel* parcel, bool isNullArray, int32_t length) {
+ // only -1 can be used to represent a null array
+ if (length < -1) return STATUS_BAD_VALUE;
+
+ if (!isNullArray && length < 0) {
+ LOG(ERROR) << __func__ << ": null array must be used with length == -1.";
+ return STATUS_BAD_VALUE;
+ }
+ if (isNullArray && length > 0) {
+ LOG(ERROR) << __func__ << ": null buffer cannot be for size " << length << " array.";
+ 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);
+ return STATUS_OK;
+}
+
+template <typename T>
+binder_status_t WriteArray(AParcel* parcel, const T* array, int32_t length) {
+ binder_status_t status = WriteAndValidateArraySize(parcel, array == nullptr, length);
+ if (status != STATUS_OK) return status;
+ if (length <= 0) return STATUS_OK;
+
int32_t size = 0;
if (__builtin_smul_overflow(sizeof(T), length, &size)) return STATUS_NO_MEMORY;
- void* const data = rawParcel->writeInplace(size);
+ void* const data = parcel->get()->writeInplace(size);
if (data == nullptr) return STATUS_NO_MEMORY;
memcpy(data, array, size);
@@ -63,17 +85,16 @@
// 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);
+binder_status_t WriteArray<char16_t>(AParcel* parcel, const char16_t* array, int32_t length) {
+ binder_status_t status = WriteAndValidateArraySize(parcel, array == nullptr, length);
+ if (status != STATUS_OK) return status;
+ if (length <= 0) return STATUS_OK;
int32_t size = 0;
if (__builtin_smul_overflow(sizeof(char16_t), length, &size)) return STATUS_NO_MEMORY;
+ Parcel* rawParcel = parcel->get();
+
for (int32_t i = 0; i < length; i++) {
status = rawParcel->writeChar(array[i]);
@@ -92,10 +113,12 @@
status_t status = rawParcel->readInt32(&length);
if (status != STATUS_OK) return PruneStatusT(status);
- if (length < 0) return STATUS_UNEXPECTED_NULL;
+ if (length < -1) return STATUS_BAD_VALUE;
- T* array = allocator(arrayData, length);
- if (length == 0) return STATUS_OK;
+ T* array;
+ if (!allocator(arrayData, length, &array)) return STATUS_NO_MEMORY;
+
+ if (length <= 0) return STATUS_OK;
if (array == nullptr) return STATUS_NO_MEMORY;
int32_t size = 0;
@@ -119,10 +142,12 @@
status_t status = rawParcel->readInt32(&length);
if (status != STATUS_OK) return PruneStatusT(status);
- if (length < 0) return STATUS_UNEXPECTED_NULL;
+ if (length < -1) return STATUS_BAD_VALUE;
- char16_t* array = allocator(arrayData, length);
- if (length == 0) return STATUS_OK;
+ char16_t* array;
+ if (!allocator(arrayData, length, &array)) return STATUS_NO_MEMORY;
+
+ if (length <= 0) return STATUS_OK;
if (array == nullptr) return STATUS_NO_MEMORY;
int32_t size = 0;
@@ -138,16 +163,17 @@
}
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;
+binder_status_t WriteArray(AParcel* parcel, const void* arrayData, int32_t length,
+ ArrayGetter<T> getter, status_t (Parcel::*write)(T)) {
+ // we have no clue if arrayData represents a null object or not, we can only infer from length
+ bool arrayIsNull = length < 0;
+ binder_status_t status = WriteAndValidateArraySize(parcel, arrayIsNull, length);
+ if (status != STATUS_OK) return status;
+ if (length <= 0) return STATUS_OK;
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++) {
+ for (int32_t i = 0; i < length; i++) {
status = (rawParcel->*write)(getter(arrayData, i));
if (status != STATUS_OK) return PruneStatusT(status);
@@ -165,11 +191,13 @@
status_t status = rawParcel->readInt32(&length);
if (status != STATUS_OK) return PruneStatusT(status);
- if (length < 0) return STATUS_UNEXPECTED_NULL;
+ if (length < -1) return STATUS_BAD_VALUE;
if (!allocator(arrayData, length)) return STATUS_NO_MEMORY;
- for (size_t i = 0; i < length; i++) {
+ if (length <= 0) return STATUS_OK;
+
+ for (int32_t i = 0; i < length; i++) {
T readTarget;
status = (rawParcel->*read)(&readTarget);
if (status != STATUS_OK) return PruneStatusT(status);
@@ -184,23 +212,25 @@
delete parcel;
}
+binder_status_t AParcel_setDataPosition(const AParcel* parcel, int32_t position) {
+ if (position < 0) {
+ return STATUS_BAD_VALUE;
+ }
+
+ parcel->get()->setDataPosition(position);
+ return STATUS_OK;
+}
+
+int32_t AParcel_getDataPosition(const AParcel* parcel) {
+ return parcel->get()->dataPosition();
+}
+
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);
@@ -210,6 +240,44 @@
*binder = ret.get();
return PruneStatusT(status);
}
+
+binder_status_t AParcel_writeParcelFileDescriptor(AParcel* parcel, int fd) {
+ std::unique_ptr<ParcelFileDescriptor> parcelFd;
+
+ if (fd < 0) {
+ if (fd != -1) {
+ return STATUS_UNKNOWN_ERROR;
+ }
+ // parcelFd = nullptr
+ } else { // fd >= 0
+ parcelFd = std::make_unique<ParcelFileDescriptor>(unique_fd(fd));
+ }
+
+ status_t status = parcel->get()->writeNullableParcelable(parcelFd);
+
+ // ownership is retained by caller
+ if (parcelFd != nullptr) {
+ (void)parcelFd->release().release();
+ }
+
+ return PruneStatusT(status);
+}
+
+binder_status_t AParcel_readParcelFileDescriptor(const AParcel* parcel, int* fd) {
+ std::unique_ptr<ParcelFileDescriptor> parcelFd;
+
+ status_t status = parcel->get()->readParcelable(&parcelFd);
+ if (status != STATUS_OK) return PruneStatusT(status);
+
+ if (parcelFd) {
+ *fd = parcelFd->release().release();
+ } else {
+ *fd = -1;
+ }
+
+ return STATUS_OK;
+}
+
binder_status_t AParcel_writeStatusHeader(AParcel* parcel, const AStatus* status) {
return PruneStatusT(status->get()->writeToParcel(parcel->get()));
}
@@ -222,9 +290,23 @@
return PruneStatusT(ret);
}
-binder_status_t AParcel_writeString(AParcel* parcel, const char* string, size_t length) {
- const uint8_t* str8 = (uint8_t*)string;
+binder_status_t AParcel_writeString(AParcel* parcel, const char* string, int32_t length) {
+ if (string == nullptr) {
+ if (length != -1) {
+ LOG(WARNING) << __func__ << ": null string must be used with length == -1.";
+ return STATUS_BAD_VALUE;
+ }
+ status_t err = parcel->get()->writeInt32(-1);
+ return PruneStatusT(err);
+ }
+
+ if (length < 0) {
+ LOG(WARNING) << __func__ << ": Negative string length: " << length;
+ return STATUS_BAD_VALUE;
+ }
+
+ 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()) {
@@ -247,13 +329,16 @@
return STATUS_OK;
}
-binder_status_t AParcel_readString(const AParcel* parcel, AParcel_stringAllocator allocator,
- void* stringData) {
+binder_status_t AParcel_readString(const AParcel* parcel, void* stringData,
+ AParcel_stringAllocator allocator) {
size_t len16;
const char16_t* str16 = parcel->get()->readString16Inplace(&len16);
if (str16 == nullptr) {
- LOG(WARNING) << __func__ << ": Failed to read string in place.";
+ if (allocator(stringData, -1, nullptr)) {
+ return STATUS_OK;
+ }
+
return STATUS_UNEXPECTED_NULL;
}
@@ -265,14 +350,15 @@
len8 = utf16_to_utf8_length(str16, len16) + 1;
}
- if (len8 <= 0 || len8 >= std::numeric_limits<int32_t>::max()) {
+ if (len8 <= 0 || len8 > std::numeric_limits<int32_t>::max()) {
LOG(WARNING) << __func__ << ": Invalid string length: " << len8;
return STATUS_BAD_VALUE;
}
- char* str8 = allocator(stringData, len8);
+ char* str8;
+ bool success = allocator(stringData, len8, &str8);
- if (str8 == nullptr) {
+ if (!success || str8 == nullptr) {
LOG(WARNING) << __func__ << ": AParcel_stringAllocator failed to allocate.";
return STATUS_NO_MEMORY;
}
@@ -282,6 +368,110 @@
return STATUS_OK;
}
+binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData, int32_t length,
+ AParcel_stringArrayElementGetter getter) {
+ // we have no clue if arrayData represents a null object or not, we can only infer from length
+ bool arrayIsNull = length < 0;
+ binder_status_t status = WriteAndValidateArraySize(parcel, arrayIsNull, length);
+ if (status != STATUS_OK) return status;
+ if (length <= 0) return STATUS_OK;
+
+ for (int32_t i = 0; i < length; i++) {
+ int32_t elementLength = 0;
+ const char* str = getter(arrayData, i, &elementLength);
+ if (str == nullptr && elementLength != -1) return STATUS_BAD_VALUE;
+
+ binder_status_t status = AParcel_writeString(parcel, str, elementLength);
+ if (status != STATUS_OK) return status;
+ }
+
+ return STATUS_OK;
+}
+
+// This implements AParcel_stringAllocator for a string using an array, index, and element
+// allocator.
+struct StringArrayElementAllocationAdapter {
+ void* arrayData; // stringData from the NDK
+ int32_t index; // index into the string array
+ AParcel_stringArrayElementAllocator elementAllocator;
+
+ static bool Allocator(void* stringData, int32_t length, char** buffer) {
+ StringArrayElementAllocationAdapter* adapter =
+ static_cast<StringArrayElementAllocationAdapter*>(stringData);
+ return adapter->elementAllocator(adapter->arrayData, adapter->index, length, buffer);
+ }
+};
+
+binder_status_t AParcel_readStringArray(const AParcel* parcel, void* arrayData,
+ AParcel_stringArrayAllocator allocator,
+ AParcel_stringArrayElementAllocator elementAllocator) {
+ const Parcel* rawParcel = parcel->get();
+
+ int32_t length;
+ status_t status = rawParcel->readInt32(&length);
+
+ if (status != STATUS_OK) return PruneStatusT(status);
+ if (length < -1) return STATUS_BAD_VALUE;
+
+ if (!allocator(arrayData, length)) return STATUS_NO_MEMORY;
+
+ if (length == -1) return STATUS_OK; // null string array
+
+ StringArrayElementAllocationAdapter adapter{
+ .arrayData = arrayData,
+ .index = 0,
+ .elementAllocator = elementAllocator,
+ };
+
+ for (; adapter.index < length; adapter.index++) {
+ binder_status_t status = AParcel_readString(parcel, static_cast<void*>(&adapter),
+ StringArrayElementAllocationAdapter::Allocator);
+
+ if (status != STATUS_OK) return status;
+ }
+
+ return STATUS_OK;
+}
+
+binder_status_t AParcel_writeParcelableArray(AParcel* parcel, const void* arrayData, int32_t length,
+ AParcel_writeParcelableElement elementWriter) {
+ // we have no clue if arrayData represents a null object or not, we can only infer from length
+ bool arrayIsNull = length < 0;
+ binder_status_t status = WriteAndValidateArraySize(parcel, arrayIsNull, length);
+ if (status != STATUS_OK) return status;
+ if (length <= 0) return STATUS_OK;
+
+ for (int32_t i = 0; i < length; i++) {
+ binder_status_t status = elementWriter(parcel, arrayData, i);
+ if (status != STATUS_OK) return status;
+ }
+
+ return STATUS_OK;
+}
+
+binder_status_t AParcel_readParcelableArray(const AParcel* parcel, void* arrayData,
+ AParcel_parcelableArrayAllocator allocator,
+ AParcel_readParcelableElement elementReader) {
+ const Parcel* rawParcel = parcel->get();
+
+ int32_t length;
+ status_t status = rawParcel->readInt32(&length);
+
+ if (status != STATUS_OK) return PruneStatusT(status);
+ if (length < -1) return STATUS_BAD_VALUE;
+
+ if (!allocator(arrayData, length)) return STATUS_NO_MEMORY;
+
+ if (length == -1) return STATUS_OK; // null array
+
+ for (int32_t i = 0; i < length; i++) {
+ binder_status_t status = elementReader(parcel, arrayData, i);
+ if (status != STATUS_OK) return status;
+ }
+
+ return STATUS_OK;
+}
+
// See gen_parcel_helper.py. These auto-generated read/write methods use the same types for
// libbinder and this library.
// @START
@@ -375,86 +565,88 @@
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_writeInt32Array(AParcel* parcel, const int32_t* arrayData, int32_t length) {
+ return WriteArray<int32_t>(parcel, arrayData, 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_writeUint32Array(AParcel* parcel, const uint32_t* arrayData,
+ int32_t length) {
+ return WriteArray<uint32_t>(parcel, arrayData, 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_writeInt64Array(AParcel* parcel, const int64_t* arrayData, int32_t length) {
+ return WriteArray<int64_t>(parcel, arrayData, 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_writeUint64Array(AParcel* parcel, const uint64_t* arrayData,
+ int32_t length) {
+ return WriteArray<uint64_t>(parcel, arrayData, length);
}
-binder_status_t AParcel_writeFloatArray(AParcel* parcel, const float* value, size_t length) {
- return WriteArray<float>(parcel, value, length);
+binder_status_t AParcel_writeFloatArray(AParcel* parcel, const float* arrayData, int32_t length) {
+ return WriteArray<float>(parcel, arrayData, length);
}
-binder_status_t AParcel_writeDoubleArray(AParcel* parcel, const double* value, size_t length) {
- return WriteArray<double>(parcel, value, length);
+binder_status_t AParcel_writeDoubleArray(AParcel* parcel, const double* arrayData, int32_t length) {
+ return WriteArray<double>(parcel, arrayData, 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_writeBoolArray(AParcel* parcel, const void* arrayData, int32_t length,
+ AParcel_boolArrayGetter getter) {
+ return WriteArray<bool>(parcel, arrayData, length, getter, &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_writeCharArray(AParcel* parcel, const char16_t* arrayData, int32_t length) {
+ return WriteArray<char16_t>(parcel, arrayData, 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_writeByteArray(AParcel* parcel, const int8_t* arrayData, int32_t length) {
+ return WriteArray<int8_t>(parcel, arrayData, length);
}
binder_status_t AParcel_readInt32Array(const AParcel* parcel, void* arrayData,
- AParcel_int32Allocator allocator) {
+ AParcel_int32ArrayAllocator allocator) {
return ReadArray<int32_t>(parcel, arrayData, allocator);
}
binder_status_t AParcel_readUint32Array(const AParcel* parcel, void* arrayData,
- AParcel_uint32Allocator allocator) {
+ AParcel_uint32ArrayAllocator allocator) {
return ReadArray<uint32_t>(parcel, arrayData, allocator);
}
binder_status_t AParcel_readInt64Array(const AParcel* parcel, void* arrayData,
- AParcel_int64Allocator allocator) {
+ AParcel_int64ArrayAllocator allocator) {
return ReadArray<int64_t>(parcel, arrayData, allocator);
}
binder_status_t AParcel_readUint64Array(const AParcel* parcel, void* arrayData,
- AParcel_uint64Allocator allocator) {
+ AParcel_uint64ArrayAllocator allocator) {
return ReadArray<uint64_t>(parcel, arrayData, allocator);
}
binder_status_t AParcel_readFloatArray(const AParcel* parcel, void* arrayData,
- AParcel_floatAllocator allocator) {
+ AParcel_floatArrayAllocator allocator) {
return ReadArray<float>(parcel, arrayData, allocator);
}
binder_status_t AParcel_readDoubleArray(const AParcel* parcel, void* arrayData,
- AParcel_doubleAllocator allocator) {
+ AParcel_doubleArrayAllocator allocator) {
return ReadArray<double>(parcel, arrayData, allocator);
}
binder_status_t AParcel_readBoolArray(const AParcel* parcel, void* arrayData,
- AParcel_boolAllocator allocator,
+ AParcel_boolArrayAllocator allocator,
AParcel_boolArraySetter setter) {
return ReadArray<bool>(parcel, arrayData, allocator, setter, &Parcel::readBool);
}
binder_status_t AParcel_readCharArray(const AParcel* parcel, void* arrayData,
- AParcel_charAllocator allocator) {
+ AParcel_charArrayAllocator allocator) {
return ReadArray<char16_t>(parcel, arrayData, allocator);
}
binder_status_t AParcel_readByteArray(const AParcel* parcel, void* arrayData,
- AParcel_byteAllocator allocator) {
+ AParcel_byteArrayAllocator allocator) {
return ReadArray<int8_t>(parcel, arrayData, allocator);
}
diff --git a/libs/binder/ndk/parcel_internal.h b/libs/binder/ndk/parcel_internal.h
index d69971f..6b7295e 100644
--- a/libs/binder/ndk/parcel_internal.h
+++ b/libs/binder/ndk/parcel_internal.h
@@ -27,9 +27,10 @@
const ::android::Parcel* get() const { return mParcel; }
::android::Parcel* get() { return mParcel; }
- AParcel(const AIBinder* binder) : AParcel(binder, new ::android::Parcel, true /*owns*/) {}
+ explicit 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) {}
+ : mBinder(binder), mParcel(parcel), mOwns(owns) {}
~AParcel() {
if (mOwns) {
@@ -43,7 +44,7 @@
const AIBinder* getBinder() { return mBinder; }
-private:
+ 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;
diff --git a/libs/binder/ndk/runtests.sh b/libs/binder/ndk/runtests.sh
index 2257eb2..a0c49fb 100755
--- a/libs/binder/ndk/runtests.sh
+++ b/libs/binder/ndk/runtests.sh
@@ -22,12 +22,13 @@
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
+ adb shell /data/nativetest64/libbinder_ndk_test_server/libbinder_ndk_test_server &
+
+ # avoid getService 1s delay for most runs, non-critical
+ sleep 0.1
+
+ adb shell /data/nativetest64/libbinder_ndk_test_client/libbinder_ndk_test_client; \
+ adb shell killall libbinder_ndk_test_server
}
[ "$1" != "--skip-build" ] && $ANDROID_BUILD_TOP/build/soong/soong_ui.bash --make-mode \
@@ -40,4 +41,5 @@
# very simple unit tests, tests things outside of the NDK as well
run_libbinder_ndk_test
-atest android.binder.cts.NdkBinderTest
+# CTS tests (much more comprehensive, new tests should ideally go here)
+atest android.binder.cts
diff --git a/libs/binder/ndk/scripts/gen_parcel_helper.py b/libs/binder/ndk/scripts/gen_parcel_helper.py
index 86cc57e..8f587d2 100755
--- a/libs/binder/ndk/scripts/gen_parcel_helper.py
+++ b/libs/binder/ndk/scripts/gen_parcel_helper.py
@@ -69,6 +69,11 @@
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 += " * \\param parcel the parcel to write to.\n"
+ header += " * \\param value the value to write to the parcel.\n"
+ header += " *\n"
+ header += " * \\return STATUS_OK on successful write.\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"
@@ -79,6 +84,11 @@
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 += " * \\param parcel the parcel to read from.\n"
+ header += " * \\param value the value to read from the parcel.\n"
+ header += " *\n"
+ header += " * \\return STATUS_OK on successful read.\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"
@@ -89,10 +99,10 @@
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
+ arg_types = "const " + cpp + "* arrayData, int32_t length"
+ if nca: arg_types = "const void* arrayData, int32_t length, AParcel_" + pretty.lower() + "ArrayGetter getter"
+ args = "arrayData, length"
+ if nca: args = "arrayData, length, getter, &Parcel::write" + pretty
header += "/**\n"
header += " * Writes an array of " + cpp + " to the next location in a non-null parcel.\n"
@@ -100,9 +110,20 @@
header += " *\n"
header += " * getter(arrayData, i) will be called for each i in [0, length) in order to get the underlying values to write "
header += "to the parcel.\n"
+ header += " *\n"
+ header += " * \\param parcel the parcel to write to.\n"
+ if nca:
+ header += " * \\param arrayData some external representation of an array.\n"
+ header += " * \\param length the length of arrayData (or -1 if this represents a null array).\n"
+ header += " * \\param getter the callback to retrieve data at specific locations in the array.\n"
+ else:
+ header += " * \\param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).\n"
+ header += " * \\param length the length of arrayData or -1 if this represents a null array.\n"
+ header += " *\n"
+ header += " * \\return STATUS_OK on successful write.\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"
+ header += "binder_status_t AParcel_write" + pretty + "Array(AParcel* parcel, " + arg_types + ") __INTRODUCED_IN(29);\n\n"
+ source += "binder_status_t AParcel_write" + pretty + "Array(AParcel* parcel, " + arg_types + ") {\n"
source += " return WriteArray<" + cpp + ">(parcel, " + args + ");\n";
source += "}\n\n"
@@ -111,23 +132,33 @@
read_func = "AParcel_read" + pretty + "Array"
write_func = "AParcel_write" + pretty + "Array"
- allocator_type = "AParcel_" + pretty.lower() + "Allocator"
+ allocator_type = "AParcel_" + pretty.lower() + "ArrayAllocator"
getter_type = "AParcel_" + pretty.lower() + "ArrayGetter"
setter_type = "AParcel_" + pretty.lower() + "ArraySetter"
if nca:
pre_header += "/**\n"
- pre_header += " * This allocates an array of length length inside of arrayData and returns whether or not there was "
- pre_header += "a success.\n"
+ pre_header += " * This allocates an array of size 'length' inside of arrayData and returns whether or not there was "
+ pre_header += "a success. If length is -1, then this should allocate some representation of a null array.\n"
pre_header += " *\n"
pre_header += " * See also " + read_func + "\n"
+ pre_header += " *\n"
+ pre_header += " * \\param arrayData some external representation of an array of " + cpp + ".\n"
+ pre_header += " * \\param length the length to allocate arrayData to (or -1 if this represents a null array).\n"
+ pre_header += " *\n"
+ pre_header += " * \\return whether the allocation succeeded.\n"
pre_header += " */\n"
- pre_header += "typedef bool (*" + allocator_type + ")(void* arrayData, size_t length);\n\n"
+ pre_header += "typedef bool (*" + allocator_type + ")(void* arrayData, int32_t length);\n\n"
pre_header += "/**\n"
pre_header += " * This is called to get the underlying data from an arrayData object at index.\n"
pre_header += " *\n"
pre_header += " * See also " + write_func + "\n"
+ pre_header += " *\n"
+ pre_header += " * \\param arrayData some external representation of an array of " + cpp + ".\n"
+ pre_header += " * \\param index the index of the value to be retrieved.\n"
+ pre_header += " *\n"
+ pre_header += " * \\return the value of the array at index index.\n"
pre_header += " */\n"
pre_header += "typedef " + cpp + " (*" + getter_type + ")(const void* arrayData, size_t index);\n\n"
@@ -135,19 +166,30 @@
pre_header += " * This is called to set an underlying value in an arrayData object at index.\n"
pre_header += " *\n"
pre_header += " * See also " + read_func + "\n"
+ pre_header += " *\n"
+ pre_header += " * \\param arrayData some external representation of an array of " + cpp + ".\n"
+ pre_header += " * \\param index the index of the value to be set.\n"
+ pre_header += " * \\param value the value to set at index index.\n"
pre_header += " */\n"
pre_header += "typedef void (*" + setter_type + ")(void* arrayData, size_t index, " + cpp + " value);\n\n"
else:
pre_header += "/**\n"
pre_header += " * This is called to get the underlying data from an arrayData object.\n"
pre_header += " *\n"
- pre_header += " * The implementation of this function should allocate a contiguous array of length length and "
+ pre_header += " * The implementation of this function should allocate a contiguous array of size 'length' and "
pre_header += "return that underlying buffer to be filled out. If there is an error or length is 0, null may be "
- pre_header += "returned.\n"
+ pre_header += "returned. If length is -1, this should allocate some representation of a null array.\n"
pre_header += " *\n"
pre_header += " * See also " + read_func + "\n"
+ pre_header += " *\n"
+ pre_header += " * \\param arrayData some external representation of an array of " + cpp + ".\n"
+ pre_header += " * \\param length the length to allocate arrayData to.\n"
+ pre_header += " * \\param outBuffer a buffer of " + cpp + " of size 'length' (if length is >= 0, if length is 0, "
+ pre_header += "this may be nullptr).\n"
+ pre_header += " *\n"
+ pre_header += " * \\return whether or not the allocation was successful (or whether a null array is represented when length is -1).\n"
pre_header += " */\n"
- pre_header += "typedef " + cpp + "* (*" + allocator_type + ")(void* arrayData, size_t length);\n\n"
+ pre_header += "typedef bool (*" + allocator_type + ")(void* arrayData, int32_t length, " + cpp + "** outBuffer);\n\n"
read_array_args = [("const AParcel*", "parcel")]
read_array_args += [("void*", "arrayData")]
@@ -166,6 +208,14 @@
else:
header += " * First, allocator will be called with the length of the array. If the allocation succeeds and the "
header += "length is greater than zero, the buffer returned by the allocator will be filled with the corresponding data\n"
+ header += " *\n"
+ header += " * \\param parcel the parcel to read from.\n"
+ header += " * \\param arrayData some external representation of an array.\n"
+ header += " * \\param allocator the callback that will be called to allocate the array.\n"
+ if nca:
+ header += " * \\param setter the callback that will be called to set a value at a specific location in the array.\n"
+ header += " *\n"
+ header += " * \\return STATUS_OK on successful read.\n"
header += " */\n"
header += "binder_status_t " + read_func + "(" + read_type_args + ") __INTRODUCED_IN(29);\n\n"
source += "binder_status_t " + read_func + "(" + read_type_args + ") {\n"
@@ -178,9 +228,19 @@
cpp_helper += " * Writes a vector of " + cpp + " to the next location in a non-null parcel.\n"
cpp_helper += " */\n"
cpp_helper += "inline binder_status_t AParcel_writeVector(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"
+ write_args = "vec.data(), vec.size()"
+ if nca: write_args = "static_cast<const void*>(&vec), vec.size(), AParcel_stdVectorGetter<" + cpp + ">"
+ cpp_helper += " return AParcel_write" + pretty + "Array(parcel, " + write_args + ");\n"
+ cpp_helper += "}\n\n"
+
+ cpp_helper += "/**\n"
+ cpp_helper += " * Writes an optional vector of " + cpp + " to the next location in a non-null parcel.\n"
+ cpp_helper += " */\n"
+ cpp_helper += "inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::optional<std::vector<" + cpp + ">>& vec) {\n"
+ extra_args = ""
+ if nca: extra_args = ", AParcel_stdVectorGetter<" + cpp + ">"
+ cpp_helper += " if (!vec) return AParcel_write" + pretty + "Array(parcel, nullptr, -1" + extra_args + ");\n"
+ cpp_helper += " return AParcel_writeVector(parcel, *vec);\n"
cpp_helper += "}\n\n"
cpp_helper += "/**\n"
@@ -192,13 +252,29 @@
read_args += ["parcel"]
read_args += ["vectorData"]
if nca:
- read_args += ["AParcel_stdVectorBoolAllocator"]
+ read_args += ["AParcel_stdVectorExternalAllocator<bool>"]
read_args += ["AParcel_stdVectorSetter<" + cpp + ">"]
else:
read_args += ["AParcel_stdVectorAllocator<" + cpp + ">"]
cpp_helper += " return AParcel_read" + pretty + "Array(" + ", ".join(read_args) + ");\n"
cpp_helper += "}\n\n"
+ cpp_helper += "/**\n"
+ cpp_helper += " * Reads an optional vector of " + cpp + " from the next location in a non-null parcel.\n"
+ cpp_helper += " */\n"
+ cpp_helper += "inline binder_status_t AParcel_readVector(const AParcel* parcel, std::optional<std::vector<" + cpp + ">>* vec) {\n"
+ cpp_helper += " void* vectorData = static_cast<void*>(vec);\n"
+ read_args = []
+ read_args += ["parcel"]
+ read_args += ["vectorData"]
+ if nca:
+ read_args += ["AParcel_nullableStdVectorExternalAllocator<bool>"]
+ read_args += ["AParcel_nullableStdVectorSetter<" + cpp + ">"]
+ else:
+ read_args += ["AParcel_nullableStdVectorAllocator<" + 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")
diff --git a/libs/binder/ndk/scripts/init_map.sh b/libs/binder/ndk/scripts/init_map.sh
index 1f74e43..3529b72 100755
--- a/libs/binder/ndk/scripts/init_map.sh
+++ b/libs/binder/ndk/scripts/init_map.sh
@@ -10,6 +10,10 @@
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 ";"; }'
+{
+ grep -oP "AServiceManager_[a-zA-Z0-9_]+(?=\()" include_apex/android/binder_manager.h;
+ grep -oP "ABinderProcess_[a-zA-Z0-9_]+(?=\()" include_apex/android/binder_process.h;
+} | sort | uniq | awk '{ print " " $0 "; # apex"; }'
echo " local:"
echo " *;"
echo "};"
diff --git a/libs/binder/ndk/status_internal.h b/libs/binder/ndk/status_internal.h
index 8c32baf..f6227f7 100644
--- a/libs/binder/ndk/status_internal.h
+++ b/libs/binder/ndk/status_internal.h
@@ -22,13 +22,13 @@
#include <utils/Errors.h>
struct AStatus {
- AStatus() {} // ok
- AStatus(::android::binder::Status&& status) : mStatus(std::move(status)) {}
+ AStatus() {} // ok
+ explicit AStatus(::android::binder::Status&& status) : mStatus(std::move(status)) {}
::android::binder::Status* get() { return &mStatus; }
const ::android::binder::Status* get() const { return &mStatus; }
-private:
+ private:
::android::binder::Status mStatus;
};
diff --git a/libs/binder/ndk/test/Android.bp b/libs/binder/ndk/test/Android.bp
index 8e40a01..b29b6e7 100644
--- a/libs/binder/ndk/test/Android.bp
+++ b/libs/binder/ndk/test/Android.bp
@@ -14,9 +14,6 @@
* 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: [
@@ -55,6 +52,9 @@
],
}
+// This test is a unit test of the low-level API that is presented here,
+// specifically the parts which are outside of the NDK. Actual users should
+// also instead use AIDL to generate these stubs. See android.binder.cts.
cc_test {
name: "libbinder_ndk_test_client",
defaults: ["test_libbinder_ndk_test_defaults"],
diff --git a/libs/binder/ndk/test/iface.cpp b/libs/binder/ndk/test/iface.cpp
index 0dc3cc4..64832f3 100644
--- a/libs/binder/ndk/test/iface.cpp
+++ b/libs/binder/ndk/test/iface.cpp
@@ -18,10 +18,13 @@
#include <android/binder_manager.h>
#include <iface/iface.h>
+#include <android/binder_auto_utils.h>
+
using ::android::sp;
using ::android::wp;
const char* IFoo::kSomeInstanceName = "libbinder_ndk-test-IFoo";
+const char* IFoo::kInstanceNameToDieFor = "libbinder_ndk-test-IFoo-to-die";
const char* kIFooDescriptor = "my-special-IFoo-class";
struct IFoo_Class_Data {
@@ -49,12 +52,18 @@
switch (code) {
case IFoo::DOFOO: {
int32_t valueIn;
+ int32_t valueOut;
stat = AParcel_readInt32(in, &valueIn);
if (stat != STATUS_OK) break;
- int32_t valueOut = foo->doubleNumber(valueIn);
+ stat = foo->doubleNumber(valueIn, &valueOut);
+ if (stat != STATUS_OK) break;
stat = AParcel_writeInt32(out, valueOut);
break;
}
+ case IFoo::DIE: {
+ stat = foo->die();
+ break;
+ }
}
return stat;
@@ -64,29 +73,43 @@
IFoo_Class_onDestroy, IFoo_Class_onTransact);
class BpFoo : public IFoo {
-public:
- BpFoo(AIBinder* binder) : mBinder(binder) {}
+ public:
+ explicit BpFoo(AIBinder* binder) : mBinder(binder) {}
virtual ~BpFoo() { AIBinder_decStrong(mBinder); }
- virtual int32_t doubleNumber(int32_t in) {
+ virtual binder_status_t doubleNumber(int32_t in, int32_t* out) {
+ binder_status_t stat = STATUS_OK;
+
AParcel* parcelIn;
- CHECK(STATUS_OK == AIBinder_prepareTransaction(mBinder, &parcelIn));
+ stat = AIBinder_prepareTransaction(mBinder, &parcelIn);
+ if (stat != STATUS_OK) return stat;
- CHECK(STATUS_OK == AParcel_writeInt32(parcelIn, in));
+ stat = AParcel_writeInt32(parcelIn, in);
+ if (stat != STATUS_OK) return stat;
- AParcel* parcelOut;
- CHECK(STATUS_OK ==
- AIBinder_transact(mBinder, IFoo::DOFOO, &parcelIn, &parcelOut, 0 /*flags*/));
+ ::ndk::ScopedAParcel parcelOut;
+ stat = AIBinder_transact(mBinder, IFoo::DOFOO, &parcelIn, parcelOut.getR(), 0 /*flags*/);
+ if (stat != STATUS_OK) return stat;
- int32_t out;
- CHECK(STATUS_OK == AParcel_readInt32(parcelOut, &out));
+ stat = AParcel_readInt32(parcelOut.get(), out);
+ if (stat != STATUS_OK) return stat;
- AParcel_delete(parcelOut);
-
- return out;
+ return stat;
}
-private:
+ virtual binder_status_t die() {
+ binder_status_t stat = STATUS_OK;
+
+ AParcel* parcelIn;
+ stat = AIBinder_prepareTransaction(mBinder, &parcelIn);
+
+ ::ndk::ScopedAParcel parcelOut;
+ stat = AIBinder_transact(mBinder, IFoo::DIE, &parcelIn, parcelOut.getR(), 0 /*flags*/);
+
+ return stat;
+ }
+
+ private:
// Always assumes one refcount
AIBinder* mBinder;
};
@@ -117,8 +140,8 @@
return status;
}
-sp<IFoo> IFoo::getService(const char* instance) {
- AIBinder* binder = AServiceManager_getService(instance); // maybe nullptr
+sp<IFoo> IFoo::getService(const char* instance, AIBinder** outBinder) {
+ AIBinder* binder = AServiceManager_getService(instance); // maybe nullptr
if (binder == nullptr) {
return nullptr;
}
@@ -128,14 +151,19 @@
return nullptr;
}
+ if (outBinder != nullptr) {
+ AIBinder_incStrong(binder);
+ *outBinder = binder;
+ }
+
if (AIBinder_isRemote(binder)) {
- sp<IFoo> ret = new BpFoo(binder); // takes ownership of 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
+ CHECK(data != nullptr); // always created with non-null data
sp<IFoo> ret = data->foo;
@@ -143,7 +171,6 @@
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
index 4c61e9d..cdf5493 100644
--- a/libs/binder/ndk/test/include/iface/iface.h
+++ b/libs/binder/ndk/test/include/iface/iface.h
@@ -19,22 +19,33 @@
#include <android/binder_ibinder.h>
#include <utils/RefBase.h>
+// warning: it is recommended to use AIDL output instead of this. binder_ibinder_utils.h and some of
+// the other niceties make sure that, for instance, binder proxies are always the same. They also
+// don't use internal Android APIs like refbase which are used here only for convenience.
+
class IFoo : public virtual ::android::RefBase {
-public:
+ public:
static const char* kSomeInstanceName;
+ static const char* kInstanceNameToDieFor;
+
static AIBinder_Class* kClass;
// Takes ownership of IFoo
binder_status_t addService(const char* instance);
- static ::android::sp<IFoo> getService(const char* instance);
+ static ::android::sp<IFoo> getService(const char* instance, AIBinder** outBinder = nullptr);
enum Call {
DOFOO = FIRST_CALL_TRANSACTION + 0,
+ DIE = FIRST_CALL_TRANSACTION + 1,
};
virtual ~IFoo();
- virtual int32_t doubleNumber(int32_t in) = 0;
-private:
- AIBinder_Weak* mWeakBinder = nullptr; // maybe owns AIBinder
+ virtual binder_status_t doubleNumber(int32_t in, int32_t* out) = 0;
+ virtual binder_status_t die() = 0;
+
+ private:
+ // this variable is only when IFoo is local (since this test combines 'IFoo' and 'BnFoo'), not
+ // for BpFoo.
+ AIBinder_Weak* mWeakBinder = nullptr;
};
diff --git a/libs/binder/ndk/test/main_client.cpp b/libs/binder/ndk/test/main_client.cpp
index 6945cac..c159d71 100644
--- a/libs/binder/ndk/test/main_client.cpp
+++ b/libs/binder/ndk/test/main_client.cpp
@@ -21,6 +21,10 @@
#include <gtest/gtest.h>
#include <iface/iface.h>
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+
using ::android::sp;
constexpr char kExistingNonNdkService[] = "SurfaceFlinger";
@@ -34,7 +38,47 @@
TEST(NdkBinder, DoubleNumber) {
sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName);
ASSERT_NE(foo, nullptr);
- EXPECT_EQ(2, foo->doubleNumber(1));
+
+ int32_t out;
+ EXPECT_EQ(STATUS_OK, foo->doubleNumber(1, &out));
+ EXPECT_EQ(2, out);
+}
+
+void LambdaOnDeath(void* cookie) {
+ auto onDeath = static_cast<std::function<void(void)>*>(cookie);
+ (*onDeath)();
+};
+TEST(NdkBinder, DeathRecipient) {
+ using namespace std::chrono_literals;
+
+ AIBinder* binder;
+ sp<IFoo> foo = IFoo::getService(IFoo::kInstanceNameToDieFor, &binder);
+ ASSERT_NE(nullptr, foo.get());
+ ASSERT_NE(nullptr, binder);
+
+ std::mutex deathMutex;
+ std::condition_variable deathCv;
+ bool deathRecieved = false;
+
+ std::function<void(void)> onDeath = [&] {
+ std::cerr << "Binder died (as requested)." << std::endl;
+ deathRecieved = true;
+ deathCv.notify_one();
+ };
+
+ AIBinder_DeathRecipient* recipient = AIBinder_DeathRecipient_new(LambdaOnDeath);
+
+ EXPECT_EQ(STATUS_OK, AIBinder_linkToDeath(binder, recipient, static_cast<void*>(&onDeath)));
+
+ // the binder driver should return this if the service dies during the transaction
+ EXPECT_EQ(STATUS_DEAD_OBJECT, foo->die());
+
+ std::unique_lock<std::mutex> lock(deathMutex);
+ EXPECT_TRUE(deathCv.wait_for(lock, 1s, [&] { return deathRecieved; }));
+ EXPECT_TRUE(deathRecieved);
+
+ AIBinder_DeathRecipient_delete(recipient);
+ AIBinder_decStrong(binder);
}
TEST(NdkBinder, RetrieveNonNdkService) {
@@ -52,9 +96,6 @@
}
TEST(NdkBinder, LinkToDeath) {
- ABinderProcess_setThreadPoolMaxThreadCount(1); // to recieve death notifications
- ABinderProcess_startThreadPool();
-
AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
ASSERT_NE(nullptr, binder);
@@ -72,9 +113,14 @@
}
class MyTestFoo : public IFoo {
- int32_t doubleNumber(int32_t in) override {
- LOG(INFO) << "doubleNumber " << in;
- return 2 * in;
+ binder_status_t doubleNumber(int32_t in, int32_t* out) override {
+ *out = 2 * in;
+ LOG(INFO) << "doubleNumber (" << in << ") => " << *out;
+ return STATUS_OK;
+ }
+ binder_status_t die() override {
+ ADD_FAILURE() << "die called on local instance";
+ return STATUS_OK;
}
};
@@ -87,7 +133,9 @@
sp<IFoo> getFoo = IFoo::getService(kInstanceName);
EXPECT_EQ(foo.get(), getFoo.get());
- EXPECT_EQ(2, getFoo->doubleNumber(1));
+ int32_t out;
+ EXPECT_EQ(STATUS_OK, getFoo->doubleNumber(1, &out));
+ EXPECT_EQ(2, out);
}
TEST(NdkBinder, EqualityOfRemoteBinderPointer) {
@@ -132,6 +180,15 @@
EXPECT_EQ(IFoo::getService(kInstanceName1), IFoo::getService(kInstanceName2));
}
+int main(int argc, char* argv[]) {
+ ::testing::InitGoogleTest(&argc, argv);
+
+ ABinderProcess_setThreadPoolMaxThreadCount(1); // to recieve death notifications/callbacks
+ ABinderProcess_startThreadPool();
+
+ return RUN_ALL_TESTS();
+}
+
#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
index 0718a69..a6e17e8 100644
--- a/libs/binder/ndk/test/main_server.cpp
+++ b/libs/binder/ndk/test/main_server.cpp
@@ -21,23 +21,37 @@
using ::android::sp;
class MyFoo : public IFoo {
- int32_t doubleNumber(int32_t in) override {
- LOG(INFO) << "doubling " << in;
- return 2 * in;
+ binder_status_t doubleNumber(int32_t in, int32_t* out) override {
+ *out = 2 * in;
+ LOG(INFO) << "doubleNumber (" << in << ") => " << *out;
+ return STATUS_OK;
+ }
+
+ binder_status_t die() override {
+ LOG(FATAL) << "IFoo::die called!";
+ return STATUS_UNKNOWN_ERROR;
}
};
-int main() {
+int service(const char* instance) {
ABinderProcess_setThreadPoolMaxThreadCount(0);
// Strong reference to MyFoo kept by service manager.
- binder_status_t status = (new MyFoo)->addService(IFoo::kSomeInstanceName);
+ binder_status_t status = (new MyFoo)->addService(instance);
if (status != STATUS_OK) {
- LOG(FATAL) << "Could not register: " << status;
+ LOG(FATAL) << "Could not register: " << status << " " << instance;
}
ABinderProcess_joinThreadPool();
- return 1;
+ return 1; // should not return
+}
+
+int main() {
+ if (fork() == 0) {
+ return service(IFoo::kInstanceNameToDieFor);
+ }
+
+ return service(IFoo::kSomeInstanceName);
}
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 73c2eba..99a71bd 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -230,7 +230,7 @@
{
public:
BinderLibTestBundle(void) {}
- BinderLibTestBundle(const Parcel *source) : m_isValid(false) {
+ explicit BinderLibTestBundle(const Parcel *source) : m_isValid(false) {
int32_t mark;
int32_t bundleLen;
size_t pos;
@@ -941,7 +941,7 @@
class BinderLibTestService : public BBinder
{
public:
- BinderLibTestService(int32_t id)
+ explicit BinderLibTestService(int32_t id)
: m_id(id)
, m_nextServerId(id + 1)
, m_serverStartRequested(false)
@@ -1295,7 +1295,7 @@
}
IPCThreadState::self()->flushCommands(); // flush BC_ENTER_LOOPER
- epoll_fd = epoll_create1(0);
+ epoll_fd = epoll_create1(EPOLL_CLOEXEC);
if (epoll_fd == -1) {
return 1;
}
diff --git a/libs/binder/tests/binderValueTypeTest.cpp b/libs/binder/tests/binderValueTypeTest.cpp
index c8f4697..f8922b0 100644
--- a/libs/binder/tests/binderValueTypeTest.cpp
+++ b/libs/binder/tests/binderValueTypeTest.cpp
@@ -22,7 +22,6 @@
#include <vector>
#include "android-base/file.h"
-#include "android-base/test_utils.h"
#include <gtest/gtest.h>
#include <binder/Parcel.h>
@@ -76,13 +75,13 @@
VALUE_TYPE_TEST(bool, Boolean, true)
VALUE_TYPE_TEST(int32_t, Int, 31337)
-VALUE_TYPE_TEST(int64_t, Long, 13370133701337l)
+VALUE_TYPE_TEST(int64_t, Long, 13370133701337L)
VALUE_TYPE_TEST(double, Double, 3.14159265358979323846)
VALUE_TYPE_TEST(String16, String, String16("Lovely"))
VALUE_TYPE_VECTOR_TEST(bool, Boolean, true)
VALUE_TYPE_VECTOR_TEST(int32_t, Int, 31337)
-VALUE_TYPE_VECTOR_TEST(int64_t, Long, 13370133701337l)
+VALUE_TYPE_VECTOR_TEST(int64_t, Long, 13370133701337L)
VALUE_TYPE_VECTOR_TEST(double, Double, 3.14159265358979323846)
VALUE_TYPE_VECTOR_TEST(String16, String, String16("Lovely"))
diff --git a/libs/binder/tests/schd-dbg.cpp b/libs/binder/tests/schd-dbg.cpp
index 6cf7f36..ec9534a 100644
--- a/libs/binder/tests/schd-dbg.cpp
+++ b/libs/binder/tests/schd-dbg.cpp
@@ -218,7 +218,7 @@
uint64_t m_total_time = 0;
uint64_t m_miss = 0;
bool tracing;
- Results(bool _tracing) : tracing(_tracing) {
+ explicit Results(bool _tracing) : tracing(_tracing) {
}
inline bool miss_deadline(uint64_t nano) {
return nano > deadline_us * 1000;
diff --git a/libs/binderthreadstate/Android.bp b/libs/binderthreadstate/Android.bp
index 7106cbb..512b069 100644
--- a/libs/binderthreadstate/Android.bp
+++ b/libs/binderthreadstate/Android.bp
@@ -24,11 +24,13 @@
"IPCThreadStateBase.cpp",
],
+ header_libs: [
+ "libbase_headers",
+ "libutils_headers",
+ ],
+
shared_libs: [
- "libbase",
"liblog",
- "libcutils",
- "libutils",
],
export_include_dirs: ["include"],
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 8b2f842..35296a9 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -47,6 +47,7 @@
"android.hardware.camera.provider@2.4::ICameraProvider",
"android.hardware.drm@1.0::IDrmFactory",
"android.hardware.graphics.composer@2.1::IComposer",
+ "android.hardware.health@2.0::IHealth",
"android.hardware.media.omx@1.0::IOmx",
"android.hardware.media.omx@1.0::IOmxStore",
"android.hardware.sensors@1.0::ISensors",
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index 17e8f6b..784e2c8 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -23,7 +23,7 @@
namespace android {
-class NativeLoaderNamespace;
+struct NativeLoaderNamespace;
class GraphicsEnv {
public:
diff --git a/libs/gui/FrameTimestamps.cpp b/libs/gui/FrameTimestamps.cpp
index 85ae433..8a14359 100644
--- a/libs/gui/FrameTimestamps.cpp
+++ b/libs/gui/FrameTimestamps.cpp
@@ -158,7 +158,7 @@
namespace {
struct FrameNumberEqual {
- FrameNumberEqual(uint64_t frameNumber) : mFrameNumber(frameNumber) {}
+ explicit FrameNumberEqual(uint64_t frameNumber) : mFrameNumber(frameNumber) {}
bool operator()(const FrameEvents& frame) {
return frame.valid && mFrameNumber == frame.frameNumber;
}
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 0b37960..74ab5ac 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -536,7 +536,7 @@
class HpGraphicBufferProducer : public HpInterface<
BpGraphicBufferProducer, H2BGraphicBufferProducer> {
public:
- HpGraphicBufferProducer(const sp<IBinder>& base) : PBase(base) {}
+ explicit HpGraphicBufferProducer(const sp<IBinder>& base) : PBase(base) {}
status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override {
return mBase->requestBuffer(slot, buf);
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index e22bc70..d2d27e8 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -332,6 +332,34 @@
return result;
}
+ virtual status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) {
+ Parcel data, reply;
+ status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ if (result != NO_ERROR) {
+ ALOGE("getDisplayViewport failed to writeInterfaceToken: %d", result);
+ return result;
+ }
+ result = data.writeStrongBinder(display);
+ if (result != NO_ERROR) {
+ ALOGE("getDisplayViewport failed to writeStrongBinder: %d", result);
+ return result;
+ }
+ result = remote()->transact(BnSurfaceComposer::GET_DISPLAY_VIEWPORT, data, &reply);
+ if (result != NO_ERROR) {
+ ALOGE("getDisplayViewport failed to transact: %d", result);
+ return result;
+ }
+ result = reply.readInt32();
+ if (result == NO_ERROR) {
+ result = reply.read(*outViewport);
+ if (result != NO_ERROR) {
+ ALOGE("getDisplayViewport failed to read: %d", result);
+ return result;
+ }
+ }
+ return result;
+ }
+
virtual int getActiveConfig(const sp<IBinder>& display)
{
Parcel data, reply;
@@ -724,6 +752,26 @@
}
return NO_ERROR;
}
+ case GET_DISPLAY_VIEWPORT: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ Rect outViewport;
+ sp<IBinder> display = nullptr;
+ status_t result = data.readStrongBinder(&display);
+ if (result != NO_ERROR) {
+ ALOGE("getDisplayViewport failed to readStrongBinder: %d", result);
+ return result;
+ }
+ result = getDisplayViewport(display, &outViewport);
+ result = reply->writeInt32(result);
+ if (result == NO_ERROR) {
+ result = reply->write(outViewport);
+ if (result != NO_ERROR) {
+ ALOGE("getDisplayViewport failed to write: %d", result);
+ return result;
+ }
+ }
+ return NO_ERROR;
+ }
case GET_ACTIVE_CONFIG: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IBinder> display = data.readStrongBinder();
diff --git a/libs/gui/OWNERS b/libs/gui/OWNERS
new file mode 100644
index 0000000..73150dc
--- /dev/null
+++ b/libs/gui/OWNERS
@@ -0,0 +1,7 @@
+jessehall@google.com
+jwcai@google.com
+lpy@google.com
+marissaw@google.com
+mathias@google.com
+racarr@google.com
+stoza@google.com
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 63560c4..f3c6fd2 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -718,6 +718,10 @@
return NO_ERROR;
}
+status_t SurfaceComposerClient::getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) {
+ return ComposerService::getComposerService()->getDisplayViewport(display, outViewport);
+}
+
int SurfaceComposerClient::getActiveConfig(const sp<IBinder>& display) {
return ComposerService::getComposerService()->getActiveConfig(display);
}
diff --git a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
index 3b89291..b1e44bb 100644
--- a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
+++ b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
@@ -896,7 +896,7 @@
int const* constFds = static_cast<int const*>(baseFds.get());
numFds = baseNumFds;
if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
- for (auto nhA : nhAA) {
+ for (const auto& nhA : nhAA) {
for (auto nh : nhA) {
if (nh != nullptr) {
native_handle_close(nh);
@@ -907,8 +907,8 @@
return false;
}
- for (auto nhA : nhAA) {
- for (auto nh : nhA) {
+ for (const auto& nhA : nhAA) {
+ for (const auto& nh : nhA) {
if (nh != nullptr) {
native_handle_delete(nh);
}
diff --git a/libs/gui/include/gui/BufferQueueConsumer.h b/libs/gui/include/gui/BufferQueueConsumer.h
index d108120..aa13c0c 100644
--- a/libs/gui/include/gui/BufferQueueConsumer.h
+++ b/libs/gui/include/gui/BufferQueueConsumer.h
@@ -31,7 +31,7 @@
class BufferQueueConsumer : public BnGraphicBufferConsumer {
public:
- BufferQueueConsumer(const sp<BufferQueueCore>& core);
+ explicit BufferQueueConsumer(const sp<BufferQueueCore>& core);
~BufferQueueConsumer() override;
// acquireBuffer attempts to acquire ownership of the next pending buffer in
diff --git a/libs/gui/include/gui/BufferQueueCore.h b/libs/gui/include/gui/BufferQueueCore.h
index 537c957..b377a41 100644
--- a/libs/gui/include/gui/BufferQueueCore.h
+++ b/libs/gui/include/gui/BufferQueueCore.h
@@ -40,13 +40,14 @@
#define BQ_LOGW(x, ...) ALOGW("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
#define BQ_LOGE(x, ...) ALOGE("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
-#define ATRACE_BUFFER_INDEX(index) \
- if (ATRACE_ENABLED()) { \
- char ___traceBuf[1024]; \
- snprintf(___traceBuf, 1024, "%s: %d", \
- mCore->mConsumerName.string(), (index)); \
- android::ScopedTrace ___bufTracer(ATRACE_TAG, ___traceBuf); \
- }
+#define ATRACE_BUFFER_INDEX(index) \
+ do { \
+ if (ATRACE_ENABLED()) { \
+ char ___traceBuf[1024]; \
+ snprintf(___traceBuf, 1024, "%s: %d", mCore->mConsumerName.string(), (index)); \
+ android::ScopedTrace ___bufTracer(ATRACE_TAG, ___traceBuf); \
+ } \
+ } while (false)
namespace android {
diff --git a/libs/gui/include/gui/BufferQueueProducer.h b/libs/gui/include/gui/BufferQueueProducer.h
index 5c7ffb4..73bc5dd 100644
--- a/libs/gui/include/gui/BufferQueueProducer.h
+++ b/libs/gui/include/gui/BufferQueueProducer.h
@@ -29,7 +29,8 @@
public:
friend class BufferQueue; // Needed to access binderDied
- BufferQueueProducer(const sp<BufferQueueCore>& core, bool consumerIsSurfaceFlinger = false);
+ explicit BufferQueueProducer(const sp<BufferQueueCore>& core,
+ bool consumerIsSurfaceFlinger = false);
~BufferQueueProducer() override;
// requestBuffer returns the GraphicBuffer for slot N.
diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h
index 32ce59a..a4102df 100644
--- a/libs/gui/include/gui/DisplayEventReceiver.h
+++ b/libs/gui/include/gui/DisplayEventReceiver.h
@@ -84,7 +84,7 @@
* or requestNextVsync to receive them.
* Other events start being delivered immediately.
*/
- DisplayEventReceiver(
+ explicit DisplayEventReceiver(
ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp);
/*
diff --git a/libs/gui/include/gui/GLConsumer.h b/libs/gui/include/gui/GLConsumer.h
index 71ed3bf..8bc7cbf 100644
--- a/libs/gui/include/gui/GLConsumer.h
+++ b/libs/gui/include/gui/GLConsumer.h
@@ -300,7 +300,7 @@
// also only creating new EGLImages from buffers when required.
class EglImage : public LightRefBase<EglImage> {
public:
- EglImage(sp<GraphicBuffer> graphicBuffer);
+ explicit EglImage(sp<GraphicBuffer> graphicBuffer);
// createIfNeeded creates an EGLImage if required (we haven't created
// one yet, or the EGLDisplay or crop-rect has changed).
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index e401572..99a3a75 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -157,6 +157,9 @@
virtual status_t getDisplayStats(const sp<IBinder>& display,
DisplayStatInfo* stats) = 0;
+ /* returns display viewport information of the given display */
+ virtual status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) = 0;
+
/* indicates which of the configurations returned by getDisplayInfo is
* currently active */
virtual int getActiveConfig(const sp<IBinder>& display) = 0;
@@ -250,7 +253,8 @@
ENABLE_VSYNC_INJECTIONS,
INJECT_VSYNC,
GET_LAYER_DEBUG_INFO,
- CREATE_SCOPED_CONNECTION
+ CREATE_SCOPED_CONNECTION,
+ GET_DISPLAY_VIEWPORT
};
virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h
index 8dfc99a..b4fd956 100644
--- a/libs/gui/include/gui/ISurfaceComposerClient.h
+++ b/libs/gui/include/gui/ISurfaceComposerClient.h
@@ -42,6 +42,7 @@
eFXSurfaceNormal = 0x00000000,
eFXSurfaceColor = 0x00020000,
+ eFXSurfaceContainer = 0x00080000,
eFXSurfaceMask = 0x000F0000,
};
diff --git a/libs/gui/include/gui/StreamSplitter.h b/libs/gui/include/gui/StreamSplitter.h
index 8f47eb4..b4eef29 100644
--- a/libs/gui/include/gui/StreamSplitter.h
+++ b/libs/gui/include/gui/StreamSplitter.h
@@ -128,7 +128,7 @@
class BufferTracker : public LightRefBase<BufferTracker> {
public:
- BufferTracker(const sp<GraphicBuffer>& buffer);
+ explicit BufferTracker(const sp<GraphicBuffer>& buffer);
const sp<GraphicBuffer>& getBuffer() const { return mBuffer; }
const sp<Fence>& getMergedFence() const { return mMergedFence; }
@@ -154,7 +154,7 @@
};
// Only called from createSplitter
- StreamSplitter(const sp<IGraphicBufferConsumer>& inputQueue);
+ explicit StreamSplitter(const sp<IGraphicBufferConsumer>& inputQueue);
// Must be accessed through RefBase
virtual ~StreamSplitter();
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 377fe68..ad8a8b0 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -79,6 +79,9 @@
static status_t getDisplayInfo(const sp<IBinder>& display,
DisplayInfo* info);
+ // Get the display viewport for the given display
+ static status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport);
+
// Get the index of the current active configuration (relative to the list
// returned by getDisplayInfo)
static int getActiveConfig(const sp<IBinder>& display);
diff --git a/libs/gui/include/gui/bufferqueue/1.0/B2HProducerListener.h b/libs/gui/include/gui/bufferqueue/1.0/B2HProducerListener.h
index fa6c2d9..0f6fb45 100644
--- a/libs/gui/include/gui/bufferqueue/1.0/B2HProducerListener.h
+++ b/libs/gui/include/gui/bufferqueue/1.0/B2HProducerListener.h
@@ -50,7 +50,7 @@
struct B2HProducerListener : public HProducerListener {
sp<BProducerListener> mBase;
- B2HProducerListener(sp<BProducerListener> const& base);
+ explicit B2HProducerListener(sp<BProducerListener> const& base);
Return<void> onBufferReleased() override;
Return<bool> needsReleaseNotify() override;
};
diff --git a/libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h b/libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
index 74850b4..c92fa9d 100644
--- a/libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
+++ b/libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
@@ -59,7 +59,7 @@
HGraphicBufferProducer,
BGraphicBufferProducer,
BnGraphicBufferProducer> {
- H2BGraphicBufferProducer(sp<HGraphicBufferProducer> const& base) : CBase(base) {}
+ explicit H2BGraphicBufferProducer(sp<HGraphicBufferProducer> const& base) : CBase(base) {}
status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override;
status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) override;
diff --git a/libs/gui/tests/Malicious.cpp b/libs/gui/tests/Malicious.cpp
index bb6b8a5..acd4297 100644
--- a/libs/gui/tests/Malicious.cpp
+++ b/libs/gui/tests/Malicious.cpp
@@ -27,7 +27,7 @@
class ProxyBQP : public BnGraphicBufferProducer {
public:
- ProxyBQP(const sp<IGraphicBufferProducer>& producer) : mProducer(producer) {}
+ explicit ProxyBQP(const sp<IGraphicBufferProducer>& producer) : mProducer(producer) {}
// Pass through calls to mProducer
status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override {
@@ -102,7 +102,7 @@
class MaliciousBQP : public ProxyBQP {
public:
- MaliciousBQP(const sp<IGraphicBufferProducer>& producer) : ProxyBQP(producer) {}
+ explicit MaliciousBQP(const sp<IGraphicBufferProducer>& producer) : ProxyBQP(producer) {}
void beMalicious(int32_t value) { mMaliciousValue = value; }
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 2c02ba6..959aafc 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -581,6 +581,9 @@
Vector<DisplayInfo>* /*configs*/) override { return NO_ERROR; }
status_t getDisplayStats(const sp<IBinder>& /*display*/,
DisplayStatInfo* /*stats*/) override { return NO_ERROR; }
+ status_t getDisplayViewport(const sp<IBinder>& /*display*/, Rect* /*outViewport*/) override {
+ return NO_ERROR;
+ }
int getActiveConfig(const sp<IBinder>& /*display*/) override { return 0; }
status_t setActiveConfig(const sp<IBinder>& /*display*/, int /*id*/)
override {
@@ -632,8 +635,7 @@
class FakeProducerFrameEventHistory : public ProducerFrameEventHistory {
public:
- FakeProducerFrameEventHistory(FenceToFenceTimeMap* fenceMap)
- : mFenceMap(fenceMap) {}
+ explicit FakeProducerFrameEventHistory(FenceToFenceTimeMap* fenceMap) : mFenceMap(fenceMap) {}
~FakeProducerFrameEventHistory() {}
diff --git a/libs/incidentcompanion/Android.bp b/libs/incidentcompanion/Android.bp
new file mode 100644
index 0000000..45eab00
--- /dev/null
+++ b/libs/incidentcompanion/Android.bp
@@ -0,0 +1,48 @@
+/**
+ * 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.
+ */
+
+filegroup {
+ name: "incidentcompanion_aidl",
+ srcs: [
+ "binder/android/os/IIncidentAuthListener.aidl",
+ "binder/android/os/IIncidentCompanion.aidl",
+ ],
+ path: "binder",
+}
+
+cc_library_static {
+ name: "libincidentcompanion",
+ shared_libs: [
+ "libbinder",
+ "libutils",
+ ],
+ aidl: {
+ local_include_dirs: ["binder"],
+ export_aidl_headers: true,
+ },
+ srcs: [
+ ":incidentcompanion_aidl",
+ ],
+ export_include_dirs: ["binder"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-missing-field-initializers",
+ "-Wno-unused-variable",
+ "-Wunused-parameter",
+ ],
+}
+
diff --git a/cmds/dumpstate/binder/android/os/DumpstateOptions.aidl b/libs/incidentcompanion/binder/android/os/IIncidentAuthListener.aidl
similarity index 66%
rename from cmds/dumpstate/binder/android/os/DumpstateOptions.aidl
rename to libs/incidentcompanion/binder/android/os/IIncidentAuthListener.aidl
index c1a7f15..5484be8 100644
--- a/cmds/dumpstate/binder/android/os/DumpstateOptions.aidl
+++ b/libs/incidentcompanion/binder/android/os/IIncidentAuthListener.aidl
@@ -17,7 +17,18 @@
package android.os;
/**
- * Specifies arguments for IDumpstate.
- * {@hide}
- */
-parcelable DumpstateOptions cpp_header "android/os/DumpstateOptions.h";
+ * Callback for IIncidentCompanion.
+ *
+ * @hide
+ */
+oneway interface IIncidentAuthListener {
+ /**
+ * The user approved the incident or bug report to be sent.
+ */
+ void onReportApproved();
+
+ /**
+ * The user did not approve the incident or bug report to be sent.
+ */
+ void onReportDenied();
+}
diff --git a/libs/incidentcompanion/binder/android/os/IIncidentCompanion.aidl b/libs/incidentcompanion/binder/android/os/IIncidentCompanion.aidl
new file mode 100644
index 0000000..6bf98d2
--- /dev/null
+++ b/libs/incidentcompanion/binder/android/os/IIncidentCompanion.aidl
@@ -0,0 +1,72 @@
+/**
+ * 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;
+
+import android.os.IIncidentAuthListener;
+
+/**
+ * Helper service for incidentd and dumpstated to provide user feedback
+ * and authorization for bug and inicdent reports to be taken.
+ *
+ * @hide
+ */
+interface IIncidentCompanion {
+ /**
+ * Request an authorization for an incident or bug report.
+ * // TODO(b/111441001): Add the permission
+ * <p>
+ * This function requires the ___ permission.
+ *
+ * @param callingUid The original application that requested the report. This function
+ * returns via the callback whether the application should be trusted. It is up
+ * to the caller to actually implement the restriction to take or not take
+ * the incident or bug report.
+ * @param flags FLAG_CONFIRMATION_DIALOG (0x1) - to show this as a dialog. Otherwise
+ * a dialog will be shown as a notification.
+ * @param callback Interface to receive results. The results may not come back for
+ * a long (user's choice) time, or ever (if they never respond to the notification).
+ * Authorization requests are not persisted across reboot. It is up to the calling
+ * service to request another authorization after reboot if they still would like
+ * to send their report.
+ */
+ oneway void authorizeReport(int callingUid, String callingPackage,
+ int flags, IIncidentAuthListener callback);
+
+ /**
+ * Cancel an authorization.
+ */
+ oneway void cancelAuthorization(IIncidentAuthListener callback);
+
+ /**
+ * Return the list of pending approvals.
+ */
+ List<String> getPendingReports();
+
+ /**
+ * The user has authorized the report to be shared.
+ *
+ * @param uri the report.
+ */
+ void approveReport(String uri);
+
+ /**
+ * The user has denied the report from being shared.
+ *
+ * @param uri the report.
+ */
+ void denyReport(String uri);
+}
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index a2d6a8a..2f39976 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -16,7 +16,6 @@
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 f72e49b..f834c55 100644
--- a/libs/input/VelocityTracker.cpp
+++ b/libs/input/VelocityTracker.cpp
@@ -327,8 +327,8 @@
eventTime = event->getHistoricalEventTime(h);
for (size_t i = 0; i < pointerCount; i++) {
uint32_t index = pointerIndex[i];
- positions[index].x = event->getHistoricalRawX(i, h);
- positions[index].y = event->getHistoricalRawY(i, h);
+ positions[index].x = event->getHistoricalX(i, h);
+ positions[index].y = event->getHistoricalY(i, h);
}
addMovement(eventTime, idBits, positions);
}
@@ -336,8 +336,8 @@
eventTime = event->getEventTime();
for (size_t i = 0; i < pointerCount; i++) {
uint32_t index = pointerIndex[i];
- positions[index].x = event->getRawX(i);
- positions[index].y = event->getRawY(i);
+ positions[index].x = event->getX(i);
+ positions[index].y = event->getY(i);
}
addMovement(eventTime, idBits, positions);
}
diff --git a/libs/input/tests/TestHelpers.h b/libs/input/tests/TestHelpers.h
index fe87bb9..343d81f 100644
--- a/libs/input/tests/TestHelpers.h
+++ b/libs/input/tests/TestHelpers.h
@@ -62,7 +62,7 @@
int mDelayMillis;
public:
- DelayedTask(int delayMillis) : mDelayMillis(delayMillis) { }
+ explicit DelayedTask(int delayMillis) : mDelayMillis(delayMillis) { }
protected:
virtual ~DelayedTask() { }
diff --git a/libs/math/OWNERS b/libs/math/OWNERS
new file mode 100644
index 0000000..6fb149a
--- /dev/null
+++ b/libs/math/OWNERS
@@ -0,0 +1,6 @@
+jaesoo@google.com
+jiyong@google.com
+mathias@google.com
+pawin@google.com
+randolphs@google.com
+romainguy@google.com
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index 5fbb3b2..d74bdb3 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -43,10 +43,6 @@
"-Wno-unused-function",
],
- cppflags: [
- "-std=c++1z"
- ],
-
version_script: "libnativewindow.map.txt",
srcs: [
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index 9ca4941..52b4582 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -15,12 +15,31 @@
*/
/**
- * @addtogroup NativeActivity Native Activity
- * @{
- */
-
-/**
* @file hardware_buffer.h
+ * @brief API for native hardware buffers.
+ */
+/**
+ * @defgroup AHardwareBuffer Native Hardware Buffer
+ *
+ * AHardwareBuffer objects represent chunks of memory that can be
+ * accessed by various hardware components in the system. It can be
+ * easily converted to the Java counterpart
+ * android.hardware.HardwareBuffer and passed between processes using
+ * Binder. All operations involving AHardwareBuffer and HardwareBuffer
+ * are zero-copy, i.e., passing AHardwareBuffer to another process
+ * creates a shared view of the same region of memory.
+ *
+ * AHardwareBuffers can be bound to EGL/OpenGL and Vulkan primitives.
+ * For EGL, use the extension function eglGetNativeClientBufferANDROID
+ * to obtain an EGLClientBuffer and pass it directly to
+ * eglCreateImageKHR. Refer to the EGL extensions
+ * EGL_ANDROID_get_native_client_buffer and
+ * EGL_ANDROID_image_native_buffer for more information. In Vulkan,
+ * the contents of the AHardwareBuffer can be accessed as external
+ * memory. See the VK_ANDROID_external_memory_android_hardware_buffer
+ * extension for details.
+ *
+ * @{
*/
#ifndef ANDROID_HARDWARE_BUFFER_H
@@ -37,7 +56,7 @@
/**
* Buffer pixel formats.
*/
-enum {
+enum AHardwareBuffer_Format {
/**
* Corresponding formats:
* Vulkan: VK_FORMAT_R8G8B8A8_UNORM
@@ -83,8 +102,10 @@
AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM = 0x2b,
/**
- * An opaque binary blob format that must have height 1, with width equal to
- * the buffer size in bytes.
+ * Opaque binary blob format.
+ * Must have height 1 and one layer, with width equal to the buffer
+ * size in bytes. Corresponds to Vulkan buffers and OpenGL buffer
+ * objects. Can be bound to the latter using GL_EXT_external_buffer.
*/
AHARDWAREBUFFER_FORMAT_BLOB = 0x21,
@@ -134,21 +155,39 @@
/**
* Buffer usage flags, specifying how the buffer will be accessed.
*/
-enum {
- /// The buffer will never be read by the CPU.
+enum AHardwareBuffer_UsageFlags {
+ /// The buffer will never be locked for direct CPU reads using the
+ /// AHardwareBuffer_lock() function. Note that reading the buffer
+ /// using OpenGL or Vulkan functions or memory mappings is still
+ /// allowed.
AHARDWAREBUFFER_USAGE_CPU_READ_NEVER = 0UL,
- /// The buffer will sometimes be read by the CPU.
+ /// The buffer will sometimes be locked for direct CPU reads using
+ /// the AHardwareBuffer_lock() function. Note that reading the
+ /// buffer using OpenGL or Vulkan functions or memory mappings
+ /// does not require the presence of this flag.
AHARDWAREBUFFER_USAGE_CPU_READ_RARELY = 2UL,
- /// The buffer will often be read by the CPU.
+ /// The buffer will often be locked for direct CPU reads using
+ /// the AHardwareBuffer_lock() function. Note that reading the
+ /// buffer using OpenGL or Vulkan functions or memory mappings
+ /// does not require the presence of this flag.
AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN = 3UL,
/// CPU read value mask.
AHARDWAREBUFFER_USAGE_CPU_READ_MASK = 0xFUL,
- /// The buffer will never be written by the CPU.
+ /// The buffer will never be locked for direct CPU writes using the
+ /// AHardwareBuffer_lock() function. Note that writing the buffer
+ /// using OpenGL or Vulkan functions or memory mappings is still
+ /// allowed.
AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER = 0UL << 4,
- /// The buffer will sometimes be written to by the CPU.
+ /// The buffer will sometimes be locked for direct CPU writes using
+ /// the AHardwareBuffer_lock() function. Note that writing the
+ /// buffer using OpenGL or Vulkan functions or memory mappings
+ /// does not require the presence of this flag.
AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY = 2UL << 4,
- /// The buffer will often be written to by the CPU.
+ /// The buffer will often be locked for direct CPU writes using
+ /// the AHardwareBuffer_lock() function. Note that writing the
+ /// buffer using OpenGL or Vulkan functions or memory mappings
+ /// does not require the presence of this flag.
AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN = 3UL << 4,
/// CPU write value mask.
AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK = 0xFUL << 4,
@@ -156,24 +195,51 @@
/// The buffer will be read from by the GPU as a texture.
AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE = 1UL << 8,
/**
- * The buffer will be written to by the GPU as a framebuffer attachment.
- * Note that the name of this flag is somewhat misleading: it does not imply
- * that the buffer contains a color format. A buffer with depth or stencil
- * format that will be used as a framebuffer attachment should also have
- * this flag.
+ * The buffer will be written to by the GPU as a framebuffer
+ * attachment.
+ *
+ * Note that the name of this flag is somewhat misleading: it does
+ * not imply that the buffer contains a color format. A buffer with
+ * depth or stencil format that will be used as a framebuffer
+ * attachment should also have this flag.
*/
AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT = 1UL << 9,
- /// The buffer must not be used outside of a protected hardware path.
+ /**
+ * The buffer is protected from direct CPU access or being read by
+ * non-secure hardware, such as video encoders.
+ *
+ * This flag is incompatible with CPU read and write flags. It is
+ * mainly used when handling DRM video. Refer to the EGL extension
+ * EGL_EXT_protected_content and GL extension
+ * GL_EXT_protected_textures for more information on how these
+ * buffers are expected to behave.
+ */
AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT = 1UL << 14,
/// The buffer will be read by a hardware video encoder.
AHARDWAREBUFFER_USAGE_VIDEO_ENCODE = 1UL << 16,
- /// The buffer will be used for direct writes from sensors.
+ /**
+ * The buffer will be used for direct writes from sensors.
+ * When this flag is present, the format must be AHARDWAREBUFFER_FORMAT_BLOB.
+ */
AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA = 1UL << 23,
- /// The buffer will be used as a shader storage or uniform buffer object.
+ /**
+ * The buffer will be used as a shader storage or uniform buffer object.
+ * When this flag is present, the format must be AHARDWAREBUFFER_FORMAT_BLOB.
+ */
AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER = 1UL << 24,
- /// The buffer will be used as a cube map texture.
+ /**
+ * The buffer will be used as a cube map texture.
+ * When this flag is present, the buffer must have a layer count
+ * that is a multiple of 6. Note that buffers with this flag must be
+ * bound to OpenGL textures using the extension
+ * GL_EXT_EGL_image_storage instead of GL_KHR_EGL_image.
+ */
AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP = 1UL << 25,
- /// The buffer contains a complete mipmap hierarchy.
+ /**
+ * The buffer contains a complete mipmap hierarchy.
+ * Note that buffers with this flag must be bound to OpenGL textures using
+ * the extension GL_EXT_EGL_image_storage instead of GL_KHR_EGL_image.
+ */
AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE = 1UL << 26,
AHARDWAREBUFFER_USAGE_VENDOR_0 = 1ULL << 28,
@@ -199,27 +265,42 @@
};
/**
- * Buffer description. Used for allocating new buffers and querying parameters
- * of existing ones.
+ * Buffer description. Used for allocating new buffers and querying
+ * parameters of existing ones.
*/
typedef struct AHardwareBuffer_Desc {
uint32_t width; ///< Width in pixels.
uint32_t height; ///< Height in pixels.
- uint32_t layers; ///< Number of images in an image array.
- uint32_t format; ///< One of AHARDWAREBUFFER_FORMAT_*
- uint64_t usage; ///< Combination of AHARDWAREBUFFER_USAGE_*
+ /**
+ * Number of images in an image array. AHardwareBuffers with one
+ * layer correspond to regular 2D textures. AHardwareBuffers with
+ * more than layer correspond to texture arrays. If the layer count
+ * is a multiple of 6 and the usage flag
+ * AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP is present, the buffer is
+ * a cube map or a cube map array.
+ */
+ uint32_t layers;
+ uint32_t format; ///< One of AHardwareBuffer_Format.
+ uint64_t usage; ///< Combination of AHardwareBuffer_UsageFlags.
uint32_t stride; ///< Row stride in pixels, ignored for AHardwareBuffer_allocate()
uint32_t rfu0; ///< Initialize to zero, reserved for future use.
uint64_t rfu1; ///< Initialize to zero, reserved for future use.
} AHardwareBuffer_Desc;
+/**
+ * Opaque handle for a native hardware buffer.
+ */
typedef struct AHardwareBuffer AHardwareBuffer;
#if __ANDROID_API__ >= 26
/**
- * Allocates a buffer that backs an AHardwareBuffer using the passed
- * AHardwareBuffer_Desc.
+ * Allocates a buffer that matches the passed AHardwareBuffer_Desc.
+ *
+ * If allocation succeeds, the buffer can be used according to the
+ * usage flags specified in its description. If a buffer is used in ways
+ * not compatible with its usage flags, the results are undefined and
+ * may include program termination.
*
* \return 0 on success, or an error number of the allocation fails for
* any reason. The returned buffer has a reference count of 1.
@@ -227,14 +308,16 @@
int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc,
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.
+ * 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) __INTRODUCED_IN(26);
/**
* Remove a reference that was previously acquired with
- * AHardwareBuffer_acquire().
+ * AHardwareBuffer_acquire() or AHardwareBuffer_allocate().
*/
void AHardwareBuffer_release(AHardwareBuffer* buffer) __INTRODUCED_IN(26);
@@ -246,50 +329,73 @@
AHardwareBuffer_Desc* outDesc) __INTRODUCED_IN(26);
/**
- * Lock the AHardwareBuffer for reading or writing, depending on the usage flags
- * passed. This call may block if the hardware needs to finish rendering or if
- * CPU caches need to be synchronized, or possibly for other implementation-
- * specific reasons. If fence is not negative, then it specifies a fence file
- * descriptor that will be signaled when the buffer is locked, otherwise the
- * caller will block until the buffer is available.
+ * Lock the AHardwareBuffer for direct CPU access.
*
- * If \a rect is not NULL, the caller promises to modify only data in the area
- * specified by rect. If rect is NULL, the caller may modify the contents of the
- * entire buffer.
+ * This function can lock the buffer for either reading or writing.
+ * It may block if the hardware needs to finish rendering, if CPU caches
+ * need to be synchronized, or possibly for other implementation-
+ * specific reasons.
*
- * The content of the buffer outside of the specified rect is NOT modified
- * by this call.
+ * The passed AHardwareBuffer must have one layer, otherwise the call
+ * will fail.
*
- * The \a usage parameter may only specify AHARDWAREBUFFER_USAGE_CPU_*. If set,
- * then outVirtualAddress is filled with the address of the buffer in virtual
+ * If \a fence is not negative, it specifies a fence file descriptor on
+ * which to wait before locking the buffer. If it's negative, the caller
+ * is responsible for ensuring that writes to the buffer have completed
+ * before calling this function. Using this parameter is more efficient
+ * than waiting on the fence and then calling this function.
+ *
+ * The \a usage parameter may only specify AHARDWAREBUFFER_USAGE_CPU_*.
+ * If set, then outVirtualAddress is filled with the address of the
+ * buffer in virtual memory. The flags must also be compatible with
+ * usage flags specified at buffer creation: if a read flag is passed,
+ * the buffer must have been created with
+ * AHARDWAREBUFFER_USAGE_CPU_READ_RARELY or
+ * AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN. If a write flag is passed, it
+ * must have been created with AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY or
+ * AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN.
+ *
+ * If \a rect is not NULL, the caller promises to modify only data in
+ * the area specified by rect. If rect is NULL, the caller may modify
+ * the contents of the entire buffer. The content of the buffer outside
+ * of the specified rect is NOT modified by this call.
+ *
+ * It is legal for several different threads to lock a buffer for read
+ * access; none of the threads are blocked.
+ *
+ * Locking a buffer simultaneously for write or read/write is undefined,
+ * but will neither terminate the process nor block the caller.
+ * AHardwareBuffer_lock may return an error or leave the buffer's
+ * content in an indeterminate state.
+ *
+ * If the buffer has AHARDWAREBUFFER_FORMAT_BLOB, it is legal lock it
+ * for reading and writing in multiple threads and/or processes
+ * simultaneously, and the contents of the buffer behave like shared
* memory.
*
- * THREADING CONSIDERATIONS:
- *
- * It is legal for several different threads to lock a buffer for read access;
- * none of the threads are blocked.
- *
- * Locking a buffer simultaneously for write or read/write is undefined, but
- * will neither terminate the process nor block the caller; AHardwareBuffer_lock
- * may return an error or leave the buffer's content into an indeterminate
- * state.
- *
- * \return 0 on success, -EINVAL if \a buffer is NULL or if the usage
- * flags are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or an error
- * number of the lock fails for any reason.
+ * \return 0 on success. -EINVAL if \a buffer is NULL, the usage flags
+ * are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or the buffer
+ * has more than one layer. Error number if the lock fails for any other
+ * reason.
*/
int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage,
int32_t fence, const ARect* rect, void** outVirtualAddress) __INTRODUCED_IN(26);
/**
- * Unlock the AHardwareBuffer; must be called after all changes to the buffer
- * are completed by the caller. If fence is not NULL then it will be set to a
- * file descriptor that is signaled when all pending work on the buffer is
- * completed. The caller is responsible for closing the fence when it is no
- * longer needed.
+ * Unlock the AHardwareBuffer from direct CPU access.
*
- * \return 0 on success, -EINVAL if \a buffer is NULL, or an error
- * number if the unlock fails for any reason.
+ * Must be called after all changes to the buffer are completed by the
+ * caller. If \a fence is NULL, the function will block until all work
+ * is completed. Otherwise, \a fence will be set either to a valid file
+ * descriptor or to -1. The file descriptor will become signaled once
+ * the unlocking is complete and buffer contents are updated.
+ * The caller is responsible for closing the file descriptor once it's
+ * no longer needed. The value -1 indicates that unlocking has already
+ * completed before the function returned and no further operations are
+ * necessary.
+ *
+ * \return 0 on success. -EINVAL if \a buffer is NULL. Error number if
+ * the unlock fails for any reason.
*/
int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) __INTRODUCED_IN(26);
@@ -302,7 +408,7 @@
int AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* buffer, int socketFd) __INTRODUCED_IN(26);
/**
- * Receive the AHardwareBuffer from an AF_UNIX socket.
+ * Receive an AHardwareBuffer from an AF_UNIX socket.
*
* \return 0 on success, -EINVAL if \a outBuffer is NULL, or an error
* number if the operation fails for any reason.
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index 6831f91..6730596 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -15,7 +15,13 @@
*/
/**
- * @addtogroup NativeActivity Native Activity
+ * @defgroup ANativeWindow Native Window
+ *
+ * ANativeWindow represents the producer end of an image queue.
+ * It is the C counterpart of the android.view.Surface object in Java,
+ * and can be converted both ways. Depending on the consumer, images
+ * submitted to ANativeWindow can be shown on the display or sent to
+ * other consumers, such as video encoders.
* @{
*/
@@ -41,7 +47,7 @@
* Legacy window pixel format names, kept for backwards compatibility.
* New code and APIs should use AHARDWAREBUFFER_FORMAT_*.
*/
-enum {
+enum ANativeWindow_LegacyFormat {
// NOTE: these values must match the values from graphics/common/x.x/types.hal
/** Red: 8 bits, Green: 8 bits, Blue: 8 bits, Alpha: 8 bits. **/
@@ -95,7 +101,7 @@
/// memory. This may be >= width.
int32_t stride;
- /// The format of the buffer. One of AHARDWAREBUFFER_FORMAT_*
+ /// The format of the buffer. One of AHardwareBuffer_Format.
int32_t format;
/// The actual bits.
@@ -151,7 +157,7 @@
*
* \param width width of the buffers in pixels.
* \param height height of the buffers in pixels.
- * \param format one of AHARDWAREBUFFER_FORMAT_* constants.
+ * \param format one of the AHardwareBuffer_Format constants.
* \return 0 for success, or a negative value on error.
*/
int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window,
diff --git a/libs/sensor/OWNERS b/libs/sensor/OWNERS
index d4393d6..81099e8 100644
--- a/libs/sensor/OWNERS
+++ b/libs/sensor/OWNERS
@@ -1,2 +1,3 @@
arthuri@google.com
bduddie@google.com
+bstack@google.com
diff --git a/libs/sensor/include/sensor/Sensor.h b/libs/sensor/include/sensor/Sensor.h
index 6926f7f..324d443 100644
--- a/libs/sensor/include/sensor/Sensor.h
+++ b/libs/sensor/include/sensor/Sensor.h
@@ -57,15 +57,15 @@
uint8_t b[16];
int64_t i64[2];
};
- uuid_t(const uint8_t (&uuid)[16]) { memcpy(b, uuid, sizeof(b));}
+ explicit uuid_t(const uint8_t (&uuid)[16]) { memcpy(b, uuid, sizeof(b));}
uuid_t() : b{0} {}
};
Sensor(const Sensor&) = default;
Sensor& operator=(const Sensor&) = default;
- Sensor(const char * name = "");
- Sensor(struct sensor_t const* hwSensor, int halVersion = 0);
+ explicit Sensor(const char * name = "");
+ explicit Sensor(struct sensor_t const* hwSensor, int halVersion = 0);
Sensor(struct sensor_t const& hwSensor, const uuid_t& uuid, int halVersion = 0);
~Sensor();
diff --git a/libs/sensor/include/sensor/SensorEventQueue.h b/libs/sensor/include/sensor/SensorEventQueue.h
index baed2ee..8176578 100644
--- a/libs/sensor/include/sensor/SensorEventQueue.h
+++ b/libs/sensor/include/sensor/SensorEventQueue.h
@@ -64,7 +64,7 @@
// Default sensor sample period
static constexpr int32_t SENSOR_DELAY_NORMAL = 200000;
- SensorEventQueue(const sp<ISensorEventConnection>& connection);
+ explicit SensorEventQueue(const sp<ISensorEventConnection>& connection);
virtual ~SensorEventQueue();
virtual void onFirstRef();
diff --git a/libs/sensor/include/sensor/SensorManager.h b/libs/sensor/include/sensor/SensorManager.h
index 23f7a91..f09c9c6 100644
--- a/libs/sensor/include/sensor/SensorManager.h
+++ b/libs/sensor/include/sensor/SensorManager.h
@@ -71,7 +71,7 @@
void sensorManagerDied();
static status_t waitForSensorService(sp<ISensorServer> *server);
- SensorManager(const String16& opPackageName);
+ explicit SensorManager(const String16& opPackageName);
status_t assertStateLocked();
private:
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 0382479..4aa9f62 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -65,12 +65,11 @@
{
}
-GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
- PixelFormat inFormat, uint32_t inLayerCount, uint64_t usage, std::string requestorName)
- : GraphicBuffer()
-{
- mInitCheck = initWithSize(inWidth, inHeight, inFormat, inLayerCount,
- usage, std::move(requestorName));
+GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
+ uint32_t inLayerCount, uint64_t inUsage, std::string requestorName)
+ : GraphicBuffer() {
+ mInitCheck = initWithSize(inWidth, inHeight, inFormat, inLayerCount, inUsage,
+ std::move(requestorName));
}
// deprecated
@@ -83,15 +82,12 @@
{
}
-GraphicBuffer::GraphicBuffer(const native_handle_t* handle,
- HandleWrapMethod method, uint32_t width, uint32_t height,
- PixelFormat format, uint32_t layerCount,
- uint64_t usage,
- uint32_t stride)
- : GraphicBuffer()
-{
- mInitCheck = initWithHandle(handle, method, width, height, format,
- layerCount, usage, stride);
+GraphicBuffer::GraphicBuffer(const native_handle_t* inHandle, HandleWrapMethod method,
+ uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
+ uint32_t inLayerCount, uint64_t inUsage, uint32_t inStride)
+ : GraphicBuffer() {
+ mInitCheck = initWithHandle(inHandle, method, inWidth, inHeight, inFormat, inLayerCount,
+ inUsage, inStride);
}
GraphicBuffer::~GraphicBuffer()
@@ -183,26 +179,24 @@
return err;
}
-status_t GraphicBuffer::initWithHandle(const native_handle_t* handle,
- HandleWrapMethod method, uint32_t width, uint32_t height,
- PixelFormat format, uint32_t layerCount, uint64_t usage,
- uint32_t stride)
-{
- ANativeWindowBuffer::width = static_cast<int>(width);
- ANativeWindowBuffer::height = static_cast<int>(height);
- ANativeWindowBuffer::stride = static_cast<int>(stride);
- ANativeWindowBuffer::format = format;
- ANativeWindowBuffer::usage = usage;
- ANativeWindowBuffer::usage_deprecated = int(usage);
+status_t GraphicBuffer::initWithHandle(const native_handle_t* inHandle, HandleWrapMethod method,
+ uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
+ uint32_t inLayerCount, uint64_t inUsage, uint32_t inStride) {
+ ANativeWindowBuffer::width = static_cast<int>(inWidth);
+ ANativeWindowBuffer::height = static_cast<int>(inHeight);
+ ANativeWindowBuffer::stride = static_cast<int>(inStride);
+ ANativeWindowBuffer::format = inFormat;
+ ANativeWindowBuffer::usage = inUsage;
+ ANativeWindowBuffer::usage_deprecated = int(inUsage);
- ANativeWindowBuffer::layerCount = layerCount;
+ ANativeWindowBuffer::layerCount = inLayerCount;
mOwner = (method == WRAP_HANDLE) ? ownNone : ownHandle;
if (method == TAKE_UNREGISTERED_HANDLE || method == CLONE_HANDLE) {
buffer_handle_t importedHandle;
- status_t err = mBufferMapper.importBuffer(handle, width, height,
- layerCount, format, usage, stride, &importedHandle);
+ status_t err = mBufferMapper.importBuffer(inHandle, inWidth, inHeight, inLayerCount,
+ inFormat, inUsage, inStride, &importedHandle);
if (err != NO_ERROR) {
initWithHandle(nullptr, WRAP_HANDLE, 0, 0, 0, 0, 0, 0);
@@ -210,15 +204,15 @@
}
if (method == TAKE_UNREGISTERED_HANDLE) {
- native_handle_close(handle);
- native_handle_delete(const_cast<native_handle_t*>(handle));
+ native_handle_close(inHandle);
+ native_handle_delete(const_cast<native_handle_t*>(inHandle));
}
- handle = importedHandle;
- mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts);
+ inHandle = importedHandle;
+ mBufferMapper.getTransportSize(inHandle, &mTransportNumFds, &mTransportNumInts);
}
- ANativeWindowBuffer::handle = handle;
+ ANativeWindowBuffer::handle = inHandle;
return NO_ERROR;
}
@@ -376,6 +370,10 @@
status_t GraphicBuffer::unflatten(
void const*& buffer, size_t& size, int const*& fds, size_t& count) {
+ if (size < 12 * sizeof(int)) {
+ android_errorWriteLog(0x534e4554, "114223584");
+ return NO_MEMORY;
+ }
int const* buf = static_cast<int const*>(buffer);
diff --git a/libs/ui/OWNERS b/libs/ui/OWNERS
new file mode 100644
index 0000000..97ead21
--- /dev/null
+++ b/libs/ui/OWNERS
@@ -0,0 +1,7 @@
+lpy@google.com
+marissaw@google.com
+mathias@google.com
+romainguy@google.com
+stoza@google.com
+jwcai@google.com
+tianyuj@google.com
diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h
index cc38982..315db11 100644
--- a/libs/ui/include/ui/GraphicBuffer.h
+++ b/libs/ui/include/ui/GraphicBuffer.h
@@ -118,18 +118,16 @@
// cannot be used directly, such as one from hidl_handle.
CLONE_HANDLE,
};
- GraphicBuffer(const native_handle_t* handle, HandleWrapMethod method,
- uint32_t width, uint32_t height,
- PixelFormat format, uint32_t layerCount,
- uint64_t usage, uint32_t stride);
+ GraphicBuffer(const native_handle_t* inHandle, HandleWrapMethod method, uint32_t inWidth,
+ uint32_t inHeight, PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage,
+ uint32_t inStride);
// These functions are deprecated because they only take 32 bits of usage
- GraphicBuffer(const native_handle_t* handle, HandleWrapMethod method,
- uint32_t width, uint32_t height,
- PixelFormat format, uint32_t layerCount,
- uint32_t usage, uint32_t stride)
- : GraphicBuffer(handle, method, width, height, format, layerCount,
- static_cast<uint64_t>(usage), stride) {}
+ GraphicBuffer(const native_handle_t* inHandle, HandleWrapMethod method, uint32_t inWidth,
+ uint32_t inHeight, PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage,
+ uint32_t inStride)
+ : GraphicBuffer(inHandle, method, inWidth, inHeight, inFormat, inLayerCount,
+ static_cast<uint64_t>(inUsage), inStride) {}
GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
uint32_t inLayerCount, uint32_t inUsage, uint32_t inStride,
native_handle_t* inHandle, bool keepOwnership);
@@ -226,10 +224,9 @@
PixelFormat inFormat, uint32_t inLayerCount,
uint64_t inUsage, std::string requestorName);
- status_t initWithHandle(const native_handle_t* handle,
- HandleWrapMethod method, uint32_t width, uint32_t height,
- PixelFormat format, uint32_t layerCount,
- uint64_t usage, uint32_t stride);
+ status_t initWithHandle(const native_handle_t* inHandle, HandleWrapMethod method,
+ uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
+ uint32_t inLayerCount, uint64_t inUsage, uint32_t inStride);
void free_handle();
diff --git a/libs/vr/OWNERS b/libs/vr/OWNERS
new file mode 100644
index 0000000..ec2d712
--- /dev/null
+++ b/libs/vr/OWNERS
@@ -0,0 +1,4 @@
+hendrikw@google.com
+jwcai@google.com
+steventhomas@google.com
+
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
index 60e1c4b..8f7b0a1 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
@@ -130,8 +130,8 @@
bool hung_up() const { return hung_up_; }
protected:
- BufferHubQueue(pdx::LocalChannelHandle channel);
- BufferHubQueue(const std::string& endpoint_path);
+ explicit BufferHubQueue(pdx::LocalChannelHandle channel);
+ explicit BufferHubQueue(const std::string& endpoint_path);
// Imports the queue parameters by querying BufferHub for the parameters for
// this channel.
@@ -417,7 +417,7 @@
private:
friend BufferHubQueue;
- ConsumerQueue(pdx::LocalChannelHandle handle);
+ explicit ConsumerQueue(pdx::LocalChannelHandle handle);
// Add a consumer buffer to populate the queue. Once added, a consumer buffer
// is NOT available to use until the producer side |Post| it. |WaitForBuffers|
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 ad3f56b..36ab5f6 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
@@ -35,7 +35,7 @@
}
// Constructs an parcelable contains the channel parcelable.
- BufferHubQueueParcelable(
+ explicit BufferHubQueueParcelable(
std::unique_ptr<pdx::ChannelParcelable> channel_parcelable)
: channel_parcelable_(std::move(channel_parcelable)) {}
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/epoll_file_descriptor.h b/libs/vr/libbufferhubqueue/include/private/dvr/epoll_file_descriptor.h
index 6e303a5..2f14f7c 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/epoll_file_descriptor.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/epoll_file_descriptor.h
@@ -28,7 +28,7 @@
return -EALREADY;
}
- fd_.reset(epoll_create(64));
+ fd_.reset(epoll_create1(EPOLL_CLOEXEC));
if (fd_.get() < 0)
return -errno;
diff --git a/libs/vr/libdisplay/include/private/dvr/display_protocol.h b/libs/vr/libdisplay/include/private/dvr/display_protocol.h
index eff50ba..3786d1d 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_protocol.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_protocol.h
@@ -60,11 +60,13 @@
using Base = Flags<Integer>;
using Type = Integer;
+ // NOLINTNEXTLINE(google-explicit-constructor)
Flags(const Integer& value) : value_{value} {}
Flags(const Flags&) = default;
Flags& operator=(const Flags&) = default;
Integer value() const { return value_; }
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator Integer() const { return value_; }
bool IsSet(Integer bits) const { return (value_ & bits) == bits; }
diff --git a/libs/vr/libpdx/private/pdx/channel_handle.h b/libs/vr/libpdx/private/pdx/channel_handle.h
index daa08f4..bd04305 100644
--- a/libs/vr/libpdx/private/pdx/channel_handle.h
+++ b/libs/vr/libpdx/private/pdx/channel_handle.h
@@ -26,7 +26,7 @@
class ChannelHandleBase {
public:
ChannelHandleBase() = default;
- ChannelHandleBase(const int32_t& value) : value_{value} {}
+ explicit ChannelHandleBase(const int32_t& value) : value_{value} {}
ChannelHandleBase(const ChannelHandleBase&) = delete;
ChannelHandleBase& operator=(const ChannelHandleBase&) = delete;
diff --git a/libs/vr/libpdx/private/pdx/client.h b/libs/vr/libpdx/private/pdx/client.h
index c35dabd..7e2d55c 100644
--- a/libs/vr/libpdx/private/pdx/client.h
+++ b/libs/vr/libpdx/private/pdx/client.h
@@ -206,7 +206,7 @@
class Transaction final : public OutputResourceMapper,
public InputResourceMapper {
public:
- Transaction(Client& client);
+ explicit Transaction(Client& client);
~Transaction();
template <typename T>
diff --git a/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h
index 0421220..43184dd 100644
--- a/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h
+++ b/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h
@@ -110,10 +110,10 @@
using const_iterator = typename BufferType::const_iterator;
BufferWrapper() {}
- BufferWrapper(const BufferType& buffer) : buffer_(buffer) {}
+ explicit BufferWrapper(const BufferType& buffer) : buffer_(buffer) {}
BufferWrapper(const BufferType& buffer, const Allocator& allocator)
: buffer_(buffer, allocator) {}
- BufferWrapper(BufferType&& buffer) : buffer_(std::move(buffer)) {}
+ explicit BufferWrapper(BufferType&& buffer) : buffer_(std::move(buffer)) {}
BufferWrapper(BufferType&& buffer, const Allocator& allocator)
: buffer_(std::move(buffer), allocator) {}
BufferWrapper(const BufferWrapper&) = default;
diff --git a/libs/vr/libpdx/private/pdx/rpc/payload.h b/libs/vr/libpdx/private/pdx/rpc/payload.h
index a48a64c..d2df14f 100644
--- a/libs/vr/libpdx/private/pdx/rpc/payload.h
+++ b/libs/vr/libpdx/private/pdx/rpc/payload.h
@@ -83,7 +83,7 @@
public MessageWriter,
public MessageReader {
public:
- ServicePayload(Message& message) : message_(message) {}
+ explicit ServicePayload(Message& message) : message_(message) {}
// MessageWriter
void* GetNextWriteBufferSection(size_t size) override {
@@ -120,7 +120,8 @@
MessageBuffer<ThreadLocalTypeSlot<ClientPayload<Slot>>, 1024u, int>;
using BufferType = typename ContainerType::BufferType;
- ClientPayload(Transaction& transaction) : transaction_{transaction} {}
+ explicit ClientPayload(Transaction& transaction)
+ : transaction_{transaction} {}
// MessageWriter
void* GetNextWriteBufferSection(size_t size) override {
diff --git a/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h
index 1cb85de..88868fe 100644
--- a/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h
+++ b/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h
@@ -13,7 +13,7 @@
public:
using BaseType = T;
- PointerWrapper(T* pointer) : pointer_(pointer) {}
+ explicit PointerWrapper(T* pointer) : pointer_(pointer) {}
PointerWrapper(const PointerWrapper&) = default;
PointerWrapper(PointerWrapper&&) noexcept = default;
PointerWrapper& operator=(const PointerWrapper&) = default;
diff --git a/libs/vr/libpdx/private/pdx/rpc/serialization.h b/libs/vr/libpdx/private/pdx/rpc/serialization.h
index f12aef1..914ea66 100644
--- a/libs/vr/libpdx/private/pdx/rpc/serialization.h
+++ b/libs/vr/libpdx/private/pdx/rpc/serialization.h
@@ -134,7 +134,7 @@
// ErrorType constructor for generic error codes. Explicitly not explicit,
// implicit conversion from ErrorCode to ErrorType is desirable behavior.
- // NOLINTNEXTLINE(runtime/explicit)
+ // NOLINTNEXTLINE(google-explicit-constructor)
ErrorType(ErrorCode error_code) : error_code_(error_code) {}
// ErrorType constructor for encoding type errors.
@@ -148,6 +148,7 @@
// Evaluates to true if the ErrorType represents an error.
explicit operator bool() const { return error_code_ != ErrorCode::NO_ERROR; }
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator ErrorCode() const { return error_code_; }
ErrorCode error_code() const { return error_code_; }
@@ -159,6 +160,7 @@
return unexpected_encoding_.encoding_type;
}
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator std::string() const {
std::ostringstream stream;
diff --git a/libs/vr/libpdx/private/pdx/service.h b/libs/vr/libpdx/private/pdx/service.h
index 234b24a..853d53c 100644
--- a/libs/vr/libpdx/private/pdx/service.h
+++ b/libs/vr/libpdx/private/pdx/service.h
@@ -86,7 +86,7 @@
class Message : public OutputResourceMapper, public InputResourceMapper {
public:
Message();
- Message(const MessageInfo& info);
+ explicit Message(const MessageInfo& info);
~Message();
/*
diff --git a/libs/vr/libpdx/private/pdx/status.h b/libs/vr/libpdx/private/pdx/status.h
index 7e51a52..498dd6d 100644
--- a/libs/vr/libpdx/private/pdx/status.h
+++ b/libs/vr/libpdx/private/pdx/status.h
@@ -11,6 +11,7 @@
// This is a helper class for constructing Status<T> with an error code.
struct ErrorStatus {
public:
+ // NOLINTNEXTLINE(google-explicit-constructor)
ErrorStatus(int error) : error_{error} {}
int error() const { return error_; }
@@ -31,12 +32,14 @@
// Value copy/move constructors. These are intentionally not marked as
// explicit to allow direct value returns from functions without having
// to explicitly wrap them into Status<T>().
- Status(const T& value) : value_{value} {} // NOLINT(runtime/explicit)
- Status(T&& value) : value_{std::move(value)} {} // NOLINT(runtime/explicit)
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ Status(const T& value) : value_{value} {}
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ Status(T&& value) : value_{std::move(value)} {}
// Constructor for storing an error code inside the Status object.
- Status(const ErrorStatus& error_status) // NOLINT(runtime/explicit)
- : error_{error_status.error()} {}
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ Status(const ErrorStatus& error_status) : error_{error_status.error()} {}
// Copy/move constructors. Move constructor leaves |other| object in empty
// state.
@@ -135,8 +138,8 @@
class Status<void> {
public:
Status() = default;
- Status(const ErrorStatus& error_status) // NOLINT(runtime/explicit)
- : error_{error_status.error()} {}
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ Status(const ErrorStatus& error_status) : error_{error_status.error()} {}
void SetValue() { error_ = 0; }
void SetError(int error) { error_ = error; }
diff --git a/libs/vr/libpdx/serialization_tests.cpp b/libs/vr/libpdx/serialization_tests.cpp
index 5ad1047..ee800f6 100644
--- a/libs/vr/libpdx/serialization_tests.cpp
+++ b/libs/vr/libpdx/serialization_tests.cpp
@@ -70,7 +70,7 @@
FileHandleType fd;
TestTemplateType() {}
- TestTemplateType(FileHandleType fd) : fd(std::move(fd)) {}
+ explicit TestTemplateType(FileHandleType fd) : fd(std::move(fd)) {}
bool operator==(const TestTemplateType& other) const {
return fd.Get() == other.fd.Get();
diff --git a/libs/vr/libpdx/status_tests.cpp b/libs/vr/libpdx/status_tests.cpp
index d4e697c..772c529 100644
--- a/libs/vr/libpdx/status_tests.cpp
+++ b/libs/vr/libpdx/status_tests.cpp
@@ -2,6 +2,8 @@
#include <gtest/gtest.h>
+#include <memory>
+
using android::pdx::ErrorStatus;
using android::pdx::Status;
@@ -84,8 +86,8 @@
Status<std::unique_ptr<int>> status1;
Status<std::unique_ptr<int>> status2;
- status1 = Status<std::unique_ptr<int>>{std::unique_ptr<int>{new int{11}}};
- status2 = Status<std::unique_ptr<int>>{std::unique_ptr<int>{new int{12}}};
+ status1 = Status<std::unique_ptr<int>>{std::make_unique<int>(int{11})};
+ status2 = Status<std::unique_ptr<int>>{std::make_unique<int>(int{12})};
EXPECT_FALSE(status1.empty());
EXPECT_FALSE(status2.empty());
EXPECT_TRUE(status1.ok());
@@ -114,7 +116,7 @@
}
TEST(Status, Take) {
- Status<std::unique_ptr<int>> status{std::unique_ptr<int>{new int{123}}};
+ Status<std::unique_ptr<int>> status{std::make_unique<int>(int{123})};
EXPECT_FALSE(status.empty());
EXPECT_NE(nullptr, status.get());
diff --git a/libs/vr/libpdx/variant_tests.cpp b/libs/vr/libpdx/variant_tests.cpp
index e3520f5..a977fd3 100644
--- a/libs/vr/libpdx/variant_tests.cpp
+++ b/libs/vr/libpdx/variant_tests.cpp
@@ -14,18 +14,22 @@
namespace {
struct BaseType {
+ // NOLINTNEXTLINE(google-explicit-constructor)
BaseType(int value) : value(value) {}
int value;
};
struct DerivedType : BaseType {
+ // NOLINTNEXTLINE(google-explicit-constructor)
DerivedType(int value) : BaseType{value} {};
};
template <typename T>
class TestType {
public:
+ // NOLINTNEXTLINE(google-explicit-constructor)
TestType(const T& value) : value_(value) {}
+ // NOLINTNEXTLINE(google-explicit-constructor)
TestType(T&& value) : value_(std::move(value)) {}
TestType(const TestType&) = default;
TestType(TestType&&) = default;
@@ -43,7 +47,9 @@
template <typename T>
class InstrumentType {
public:
+ // NOLINTNEXTLINE(google-explicit-constructor)
InstrumentType(const T& value) : value_(value) { constructor_count_++; }
+ // NOLINTNEXTLINE(google-explicit-constructor)
InstrumentType(T&& value) : value_(std::move(value)) { constructor_count_++; }
InstrumentType(const InstrumentType& other) : value_(other.value_) {
constructor_count_++;
@@ -51,9 +57,11 @@
InstrumentType(InstrumentType&& other) : value_(std::move(other.value_)) {
constructor_count_++;
}
+ // NOLINTNEXTLINE(google-explicit-constructor)
InstrumentType(const TestType<T>& other) : value_(other.get()) {
constructor_count_++;
}
+ // NOLINTNEXTLINE(google-explicit-constructor)
InstrumentType(TestType<T>&& other) : value_(other.take()) {
constructor_count_++;
}
@@ -1101,6 +1109,7 @@
TEST(Variant, IsConstructible) {
using ArrayType = const float[3];
struct ImplicitBool {
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator bool() const { return true; }
};
struct ExplicitBool {
diff --git a/libs/vr/libpdx_default_transport/pdx_benchmarks.cpp b/libs/vr/libpdx_default_transport/pdx_benchmarks.cpp
index fa0adf0..5c9e74c 100644
--- a/libs/vr/libpdx_default_transport/pdx_benchmarks.cpp
+++ b/libs/vr/libpdx_default_transport/pdx_benchmarks.cpp
@@ -66,7 +66,7 @@
prctl(PR_SET_NAME, reinterpret_cast<unsigned long>(name.c_str()), 0, 0, 0);
}
-constexpr uint64_t kNanosPerSecond = 1000000000llu;
+constexpr uint64_t kNanosPerSecond = 1000000000LLU;
uint64_t GetClockNs() {
timespec t;
@@ -82,7 +82,7 @@
class SchedStats {
public:
SchedStats() : SchedStats(gettid()) {}
- SchedStats(pid_t task_id) : task_id_(task_id) {}
+ explicit SchedStats(pid_t task_id) : task_id_(task_id) {}
SchedStats(const SchedStats&) = default;
SchedStats& operator=(const SchedStats&) = default;
@@ -379,7 +379,7 @@
private:
friend BASE;
- BenchmarkService(std::unique_ptr<Endpoint> endpoint)
+ explicit BenchmarkService(std::unique_ptr<Endpoint> endpoint)
: BASE("BenchmarkService", std::move(endpoint)),
send_buffer(kMaxMessageSize),
receive_buffer(kMaxMessageSize) {}
@@ -492,7 +492,7 @@
private:
friend BASE;
- BenchmarkClient(const std::string& service_path)
+ explicit BenchmarkClient(const std::string& service_path)
: BASE(ClientChannelFactory::Create(service_path),
ProgramOptions.timeout) {}
diff --git a/libs/vr/libpdx_default_transport/private/pdx/default_transport/service_utility.h b/libs/vr/libpdx_default_transport/private/pdx/default_transport/service_utility.h
index 81bb17b..3ebab86 100644
--- a/libs/vr/libpdx_default_transport/private/pdx/default_transport/service_utility.h
+++ b/libs/vr/libpdx_default_transport/private/pdx/default_transport/service_utility.h
@@ -41,7 +41,8 @@
private:
friend BASE;
- ServiceUtility(const std::string& endpoint_path, int* error = nullptr)
+ explicit ServiceUtility(const std::string& endpoint_path,
+ int* error = nullptr)
: BASE(ClientChannelFactory::Create(endpoint_path), 0) {
if (error)
*error = Client::error();
diff --git a/libs/vr/libpdx_uds/client_channel_tests.cpp b/libs/vr/libpdx_uds/client_channel_tests.cpp
index 1560030..c9c5d15 100644
--- a/libs/vr/libpdx_uds/client_channel_tests.cpp
+++ b/libs/vr/libpdx_uds/client_channel_tests.cpp
@@ -45,7 +45,7 @@
class TestService : public ServiceBase<TestService> {
public:
- TestService(std::unique_ptr<Endpoint> endpoint)
+ explicit TestService(std::unique_ptr<Endpoint> endpoint)
: ServiceBase{"TestService", std::move(endpoint)} {}
Status<void> HandleMessage(Message& message) override {
@@ -78,7 +78,7 @@
class TestServiceRunner {
public:
- TestServiceRunner(LocalHandle channel_socket) {
+ explicit TestServiceRunner(LocalHandle channel_socket) {
auto endpoint = Endpoint::CreateFromSocketFd(LocalHandle{});
endpoint->RegisterNewChannelForTests(std::move(channel_socket));
service_ = TestService::Create(std::move(endpoint));
diff --git a/libs/vr/libpdx_uds/private/uds/ipc_helper.h b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
index 63b5b10..704a569 100644
--- a/libs/vr/libpdx_uds/private/uds/ipc_helper.h
+++ b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
@@ -57,7 +57,7 @@
class SendPayload : public MessageWriter, public OutputResourceMapper {
public:
- SendPayload(SendInterface* sender = nullptr) : sender_{sender} {}
+ explicit SendPayload(SendInterface* sender = nullptr) : sender_{sender} {}
Status<void> Send(const BorrowedHandle& socket_fd);
Status<void> Send(const BorrowedHandle& socket_fd, const ucred* cred,
const iovec* data_vec = nullptr, size_t vec_count = 0);
@@ -85,7 +85,8 @@
class ReceivePayload : public MessageReader, public InputResourceMapper {
public:
- ReceivePayload(RecvInterface* receiver = nullptr) : receiver_{receiver} {}
+ explicit ReceivePayload(RecvInterface* receiver = nullptr)
+ : receiver_{receiver} {}
Status<void> Receive(const BorrowedHandle& socket_fd);
Status<void> Receive(const BorrowedHandle& socket_fd, ucred* cred);
diff --git a/libs/vr/libpdx_uds/private/uds/service_endpoint.h b/libs/vr/libpdx_uds/private/uds/service_endpoint.h
index 01ebf65..50fc484 100644
--- a/libs/vr/libpdx_uds/private/uds/service_endpoint.h
+++ b/libs/vr/libpdx_uds/private/uds/service_endpoint.h
@@ -117,7 +117,7 @@
// This class must be instantiated using Create() static methods above.
Endpoint(const std::string& endpoint_path, bool blocking,
bool use_init_socket_fd = true);
- Endpoint(LocalHandle socket_fd);
+ explicit Endpoint(LocalHandle socket_fd);
void Init(LocalHandle socket_fd);
diff --git a/libs/vr/libpdx_uds/remote_method_tests.cpp b/libs/vr/libpdx_uds/remote_method_tests.cpp
index 3f25776..4f0670e 100644
--- a/libs/vr/libpdx_uds/remote_method_tests.cpp
+++ b/libs/vr/libpdx_uds/remote_method_tests.cpp
@@ -94,7 +94,7 @@
FileHandleType fd;
TestTemplateType() {}
- TestTemplateType(FileHandleType fd) : fd(std::move(fd)) {}
+ explicit TestTemplateType(FileHandleType fd) : fd(std::move(fd)) {}
private:
PDX_SERIALIZABLE_MEMBERS(TestTemplateType<FileHandleType>, fd);
@@ -328,7 +328,7 @@
private:
friend BASE;
- TestClient(LocalChannelHandle channel_handle)
+ explicit TestClient(LocalChannelHandle channel_handle)
: BASE{android::pdx::uds::ClientChannel::Create(
std::move(channel_handle))} {}
TestClient()
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index 4dc669b..26e8201 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -47,6 +47,7 @@
"liblog",
"libhardware",
"libnativewindow",
+ "libprocessgroup",
"libutils",
"libEGL",
"libGLESv1_CM",
@@ -84,9 +85,6 @@
"-Wno-error=sign-compare", // to fix later
"-Wno-unused-variable",
],
- cppflags: [
- "-std=c++1z"
- ],
shared_libs: sharedLibraries,
whole_static_libs: staticLibraries,
header_libs: headerLibraries,
diff --git a/libs/vr/libvrflinger/epoll_event_dispatcher.cpp b/libs/vr/libvrflinger/epoll_event_dispatcher.cpp
index 962c745..1cf5f17 100644
--- a/libs/vr/libvrflinger/epoll_event_dispatcher.cpp
+++ b/libs/vr/libvrflinger/epoll_event_dispatcher.cpp
@@ -11,7 +11,7 @@
namespace dvr {
EpollEventDispatcher::EpollEventDispatcher() {
- epoll_fd_.Reset(epoll_create(64));
+ epoll_fd_.Reset(epoll_create1(EPOLL_CLOEXEC));
if (!epoll_fd_) {
ALOGE("Failed to create epoll fd: %s", strerror(errno));
return;
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index b8d5e2b..64079e1 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -99,7 +99,7 @@
class TraceArgs {
public:
template <typename... Args>
- TraceArgs(const char* format, Args&&... args) {
+ explicit TraceArgs(const char* format, Args&&... args) {
std::array<char, 1024> buffer;
snprintf(buffer.data(), buffer.size(), format, std::forward<Args>(args)...);
atrace_begin(ATRACE_TAG, buffer.data());
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index 539a7fb..f1a755b 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -195,7 +195,7 @@
AcquiredBuffer acquired_buffer;
pdx::LocalHandle release_fence;
- SourceSurface(const std::shared_ptr<DirectDisplaySurface>& surface)
+ explicit SourceSurface(const std::shared_ptr<DirectDisplaySurface>& surface)
: surface(surface) {}
// Attempts to acquire a new buffer from the surface and return a tuple with
diff --git a/libs/vr/libvrflinger/hwc_types.h b/libs/vr/libvrflinger/hwc_types.h
index cbf636c..8b5c3b3 100644
--- a/libs/vr/libvrflinger/hwc_types.h
+++ b/libs/vr/libvrflinger/hwc_types.h
@@ -116,19 +116,24 @@
Wrapper(const Wrapper&) = default;
// Implicit conversion from ValueType.
+ // NOLINTNEXTLINE(google-explicit-constructor)
Wrapper(ValueType value) : value(value) {}
// Implicit conversion from BaseType.
+ // NOLINTNEXTLINE(google-explicit-constructor)
Wrapper(BaseType value) : value(static_cast<ValueType>(value)) {}
// Implicit conversion from an enum type of the same underlying type.
template <typename T, typename = EnableIfMatchingEnum<T, ValueType>>
+ // NOLINTNEXTLINE(google-explicit-constructor)
Wrapper(const T& value) : value(static_cast<ValueType>(value)) {}
// Implicit conversion to BaseType.
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator BaseType() const { return static_cast<BaseType>(value); }
// Implicit conversion to ValueType.
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator ValueType() const { return value; }
template <typename T, typename = EnableIfMatchingEnum<T, ValueType>>
@@ -275,8 +280,10 @@
struct Color final {
Color(const Color&) = default;
Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) : r(r), g(g), b(b), a(a) {}
+ // NOLINTNEXTLINE(google-explicit-constructor)
Color(hwc_color_t color) : r(color.r), g(color.g), b(color.b), a(color.a) {}
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator hwc_color_t() const { return {r, g, b, a}; }
uint8_t r __attribute__((aligned(1)));
diff --git a/libs/vr/libvrflinger/include/dvr/vr_flinger.h b/libs/vr/libvrflinger/include/dvr/vr_flinger.h
index c740dde..ae52076 100644
--- a/libs/vr/libvrflinger/include/dvr/vr_flinger.h
+++ b/libs/vr/libvrflinger/include/dvr/vr_flinger.h
@@ -49,7 +49,8 @@
// Needs to be a separate class for binder's ref counting
class PersistentVrStateCallback : public BnPersistentVrStateCallbacks {
public:
- PersistentVrStateCallback(RequestDisplayCallback request_display_callback)
+ explicit PersistentVrStateCallback(
+ RequestDisplayCallback request_display_callback)
: request_display_callback_(request_display_callback) {}
void onPersistentVrStateChanged(bool enabled) override;
private:
diff --git a/libs/vr/libvrflinger/vr_flinger.cpp b/libs/vr/libvrflinger/vr_flinger.cpp
index 26aed4f..a27d58d 100644
--- a/libs/vr/libvrflinger/vr_flinger.cpp
+++ b/libs/vr/libvrflinger/vr_flinger.cpp
@@ -12,9 +12,9 @@
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <cutils/properties.h>
-#include <cutils/sched_policy.h>
#include <log/log.h>
#include <private/dvr/display_client.h>
+#include <processgroup/sched_policy.h>
#include <sys/prctl.h>
#include <sys/resource.h>
diff --git a/libs/vr/libvrsensor/include/private/dvr/latency_model.h b/libs/vr/libvrsensor/include/private/dvr/latency_model.h
index 40b4638..bf0e687 100644
--- a/libs/vr/libvrsensor/include/private/dvr/latency_model.h
+++ b/libs/vr/libvrsensor/include/private/dvr/latency_model.h
@@ -10,7 +10,7 @@
// window_size measurements and return their average after that.
class LatencyModel {
public:
- LatencyModel(size_t window_size);
+ explicit LatencyModel(size_t window_size);
~LatencyModel() = default;
void AddLatency(int64_t latency_ns);
diff --git a/opengl/OWNERS b/opengl/OWNERS
new file mode 100644
index 0000000..881f1b8
--- /dev/null
+++ b/opengl/OWNERS
@@ -0,0 +1,16 @@
+# alanward@google.com
+chiur@google.com
+chrisforbes@google.com
+cnorthrop@google.com
+courtneygo@google.com
+hliatis@google.com
+ianelliott@google.com
+jessehall@google.com
+lpy@google.com
+marissaw@google.com
+nduca@google.com
+pmuetschard@google.com
+timvp@google.com
+tobine@google.com
+vhau@google.com
+zzyiwei@google.com
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
deleted file mode 100644
index 2f42ab6..0000000
--- a/opengl/libs/Android.mk
+++ /dev/null
@@ -1 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 40adf8e..e824238 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -482,58 +482,35 @@
}
// Returns a list of color spaces understood by the vendor EGL driver.
-static std::vector<EGLint> getDriverColorSpaces(egl_display_ptr dp,
- android_pixel_format format) {
+static std::vector<EGLint> getDriverColorSpaces(egl_display_ptr dp) {
std::vector<EGLint> colorSpaces;
- if (!dp->hasColorSpaceSupport) return colorSpaces;
- // OpenGL drivers only support sRGB encoding with 8-bit formats.
- // RGB_888 is never returned by getNativePixelFormat, but is included for completeness.
- const bool formatSupportsSRGBEncoding =
- format == HAL_PIXEL_FORMAT_RGBA_8888 || format == HAL_PIXEL_FORMAT_RGBX_8888 ||
- format == HAL_PIXEL_FORMAT_RGB_888;
- const bool formatIsFloatingPoint = format == HAL_PIXEL_FORMAT_RGBA_FP16;
+ // sRGB and linear are always supported when color space support is present.
+ colorSpaces.push_back(EGL_GL_COLORSPACE_SRGB_KHR);
+ colorSpaces.push_back(EGL_GL_COLORSPACE_LINEAR_KHR);
- if (formatSupportsSRGBEncoding) {
- // sRGB and linear are always supported when color space support is present.
- colorSpaces.push_back(EGL_GL_COLORSPACE_SRGB_KHR);
- colorSpaces.push_back(EGL_GL_COLORSPACE_LINEAR_KHR);
- // DCI-P3 uses the sRGB transfer function, so it's only relevant for 8-bit formats.
- if (findExtension(dp->disp.queryString.extensions,
- "EGL_EXT_gl_colorspace_display_p3")) {
- colorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_EXT);
- }
- }
-
- // According to the spec, scRGB is only supported for floating point formats.
- // For non-linear scRGB, the application is responsible for applying the
- // transfer function.
- if (formatIsFloatingPoint) {
- if (findExtension(dp->disp.queryString.extensions,
- "EGL_EXT_gl_colorspace_scrgb")) {
- colorSpaces.push_back(EGL_GL_COLORSPACE_SCRGB_EXT);
- }
- if (findExtension(dp->disp.queryString.extensions,
- "EGL_EXT_gl_colorspace_scrgb_linear")) {
- colorSpaces.push_back(EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT);
- }
- }
-
- // BT2020 can be used with any pixel format. PQ encoding must be applied by the
- // application and does not affect the behavior of OpenGL.
if (findExtension(dp->disp.queryString.extensions,
- "EGL_EXT_gl_colorspace_bt2020_linear")) {
+ "EGL_EXT_gl_colorspace_display_p3")) {
+ colorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_EXT);
+ }
+ if (findExtension(dp->disp.queryString.extensions,
+ "EGL_EXT_gl_colorspace_scrgb")) {
+ colorSpaces.push_back(EGL_GL_COLORSPACE_SCRGB_EXT);
+ }
+ if (findExtension(dp->disp.queryString.extensions,
+ "EGL_EXT_gl_colorspace_scrgb_linear")) {
+ colorSpaces.push_back(EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT);
+ }
+ if (findExtension(dp->disp.queryString.extensions,
+ "EGL_EXT_gl_colorspace_bt2020_linear")) {
colorSpaces.push_back(EGL_GL_COLORSPACE_BT2020_LINEAR_EXT);
}
if (findExtension(dp->disp.queryString.extensions,
- "EGL_EXT_gl_colorspace_bt2020_pq")) {
+ "EGL_EXT_gl_colorspace_bt2020_pq")) {
colorSpaces.push_back(EGL_GL_COLORSPACE_BT2020_PQ_EXT);
}
-
- // Linear DCI-P3 simply uses different primaries than standard RGB and thus
- // can be used with any pixel format.
if (findExtension(dp->disp.queryString.extensions,
- "EGL_EXT_gl_colorspace_display_p3_linear")) {
+ "EGL_EXT_gl_colorspace_display_p3_linear")) {
colorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT);
}
return colorSpaces;
@@ -543,34 +520,38 @@
// If there is no color space attribute in attrib_list, colorSpace is left
// unmodified.
static EGLBoolean processAttributes(egl_display_ptr dp, NativeWindowType window,
- android_pixel_format format, const EGLint* attrib_list,
- EGLint* colorSpace,
+ const EGLint* attrib_list, EGLint* colorSpace,
std::vector<EGLint>* strippedAttribList) {
for (const EGLint* attr = attrib_list; attr && attr[0] != EGL_NONE; attr += 2) {
bool copyAttribute = true;
if (attr[0] == EGL_GL_COLORSPACE_KHR) {
- // Fail immediately if the driver doesn't have color space support at all.
- if (!dp->hasColorSpaceSupport) return false;
+ switch (attr[1]) {
+ case EGL_GL_COLORSPACE_LINEAR_KHR:
+ case EGL_GL_COLORSPACE_SRGB_KHR:
+ case EGL_GL_COLORSPACE_DISPLAY_P3_EXT:
+ case EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT:
+ case EGL_GL_COLORSPACE_SCRGB_EXT:
+ case EGL_GL_COLORSPACE_BT2020_LINEAR_EXT:
+ case EGL_GL_COLORSPACE_BT2020_PQ_EXT:
+ case EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT:
+ // Fail immediately if the driver doesn't have color space support at all.
+ if (!dp->hasColorSpaceSupport) return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+ break;
+ default:
+ // BAD_ATTRIBUTE if attr is not any of the EGL_GL_COLORSPACE_*
+ return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+ }
*colorSpace = attr[1];
// Strip the attribute if the driver doesn't understand it.
copyAttribute = false;
- std::vector<EGLint> driverColorSpaces = getDriverColorSpaces(dp, format);
+ std::vector<EGLint> driverColorSpaces = getDriverColorSpaces(dp);
for (auto driverColorSpace : driverColorSpaces) {
if (attr[1] == driverColorSpace) {
copyAttribute = true;
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]);
@@ -603,12 +584,12 @@
ALOGE("processAttributes: invalid window (win=%p) "
"failed (%#x) (already connected to another API?)",
window, err);
- return false;
+ return setError(EGL_BAD_NATIVE_WINDOW, EGL_FALSE);
}
if (!windowSupportsWideColor) {
// Application has asked for a wide-color colorspace but
// wide-color support isn't available on the display the window is on.
- return false;
+ return setError(EGL_BAD_MATCH, EGL_FALSE);
}
}
return true;
@@ -736,10 +717,11 @@
// now select correct colorspace and dataspace based on user's attribute list
EGLint colorSpace = EGL_UNKNOWN;
std::vector<EGLint> strippedAttribList;
- if (!processAttributes(dp, window, format, attrib_list, &colorSpace,
+ if (!processAttributes(dp, window, attrib_list, &colorSpace,
&strippedAttribList)) {
ALOGE("error invalid colorspace: %d", colorSpace);
- return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
+ return EGL_NO_SURFACE;
}
attrib_list = strippedAttribList.data();
@@ -754,14 +736,14 @@
}
android_dataspace dataSpace = dataSpaceFromEGLColorSpace(colorSpace);
- if (dataSpace != HAL_DATASPACE_UNKNOWN) {
- int err = native_window_set_buffers_data_space(window, dataSpace);
- if (err != 0) {
- ALOGE("error setting native window pixel dataSpace: %s (%d)",
- strerror(-err), err);
- native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
- return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
- }
+ // Set dataSpace even if it could be HAL_DATASPACE_UNKNOWN. HAL_DATASPACE_UNKNOWN
+ // is the default value, but it may have changed at this point.
+ int err = native_window_set_buffers_data_space(window, dataSpace);
+ if (err != 0) {
+ ALOGE("error setting native window pixel dataSpace: %s (%d)",
+ strerror(-err), err);
+ native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
+ return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
}
// the EGL spec requires that a new EGLSurface default to swap interval
@@ -801,10 +783,10 @@
// now select a corresponding sRGB format if needed
EGLint colorSpace = EGL_UNKNOWN;
std::vector<EGLint> strippedAttribList;
- if (!processAttributes(dp, nullptr, format, attrib_list, &colorSpace,
+ if (!processAttributes(dp, nullptr, attrib_list, &colorSpace,
&strippedAttribList)) {
ALOGE("error invalid colorspace: %d", colorSpace);
- return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ return EGL_NO_SURFACE;
}
attrib_list = strippedAttribList.data();
@@ -835,10 +817,10 @@
// Select correct colorspace based on user's attribute list
EGLint colorSpace = EGL_UNKNOWN;
std::vector<EGLint> strippedAttribList;
- if (!processAttributes(dp, nullptr, format, attrib_list, &colorSpace,
+ if (!processAttributes(dp, nullptr, attrib_list, &colorSpace,
&strippedAttribList)) {
ALOGE("error invalid colorspace: %d", colorSpace);
- return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ return EGL_NO_SURFACE;
}
attrib_list = strippedAttribList.data();
diff --git a/opengl/tests/Android.mk b/opengl/tests/Android.mk
deleted file mode 100644
index 134854a..0000000
--- a/opengl/tests/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-dirs := \
- linetex \
- swapinterval \
- textures \
- tritex \
-
-ifneq (,$(TARGET_BUILD_JAVA_SUPPORT_LEVEL))
-dirs += \
- gl2_cameraeye \
- gl2_java \
- gl2_jni \
- gldual \
- gl_jni \
- gl_perfapp \
- lighting1709 \
- testLatency \
- testPauseResume \
- testViewport \
-
-endif # JAVA_SUPPORT
-
-ifeq (platform,$(TARGET_BUILD_JAVA_SUPPORT_LEVEL))
-dirs += \
- testFramerate
-
-endif # JAVA_SUPPORT platform
-
-include $(call all-named-subdir-makefiles, $(dirs))
diff --git a/opengl/tests/EGLTest/Android.bp b/opengl/tests/EGLTest/Android.bp
index f246077..a9e873a 100644
--- a/opengl/tests/EGLTest/Android.bp
+++ b/opengl/tests/EGLTest/Android.bp
@@ -25,6 +25,7 @@
"libhidltransport",
"liblog",
"libutils",
+ "libnativewindow",
],
include_dirs: [
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
index 5927dc1..459b135 100644
--- a/opengl/tests/EGLTest/EGL_test.cpp
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -775,4 +775,169 @@
EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
}
+
+TEST_F(EGLTest, EGLInvalidColorspaceAttribute) {
+ EGLConfig config;
+
+ ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
+
+ struct DummyConsumer : public BnConsumerListener {
+ void onFrameAvailable(const BufferItem& /* item */) override {}
+ void onBuffersReleased() override {}
+ void onSidebandStreamChanged() override {}
+ };
+
+ // Create a EGLSurface
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ consumer->consumerConnect(new DummyConsumer, false);
+ sp<Surface> mSTC = new Surface(producer);
+ sp<ANativeWindow> mANW = mSTC;
+
+ EGLint winAttrs[] = {
+ // clang-format off
+ EGL_GL_COLORSPACE_KHR, EGL_BACK_BUFFER,
+ EGL_NONE,
+ // clang-format on
+ };
+
+ EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
+ ASSERT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
+ ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
+}
+
+TEST_F(EGLTest, EGLUnsupportedColorspaceFormatCombo) {
+ EGLint numConfigs;
+ EGLConfig config;
+ EGLBoolean success;
+
+ const EGLint attrs[] = {
+ // clang-format off
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE, 16,
+ EGL_GREEN_SIZE, 16,
+ EGL_BLUE_SIZE, 16,
+ EGL_ALPHA_SIZE, 16,
+ EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
+ EGL_NONE,
+ // clang-format on
+ };
+ success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ ASSERT_EQ(1, numConfigs);
+
+ struct DummyConsumer : public BnConsumerListener {
+ void onFrameAvailable(const BufferItem& /* item */) override {}
+ void onBuffersReleased() override {}
+ void onSidebandStreamChanged() override {}
+ };
+
+ // Create a EGLSurface
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ consumer->consumerConnect(new DummyConsumer, false);
+ sp<Surface> mSTC = new Surface(producer);
+ sp<ANativeWindow> mANW = mSTC;
+
+ const EGLint winAttrs[] = {
+ // clang-format off
+ EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
+ EGL_NONE,
+ // clang-format on
+ };
+
+ EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
+ ASSERT_EQ(EGL_BAD_MATCH, eglGetError());
+ ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
+}
+
+TEST_F(EGLTest, EGLCreateWindowFailAndSucceed) {
+ EGLConfig config;
+
+ ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
+
+ struct DummyConsumer : public BnConsumerListener {
+ void onFrameAvailable(const BufferItem& /* item */) override {}
+ void onBuffersReleased() override {}
+ void onSidebandStreamChanged() override {}
+ };
+
+ // Create a EGLSurface
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ consumer->consumerConnect(new DummyConsumer, false);
+ sp<Surface> mSTC = new Surface(producer);
+ sp<ANativeWindow> mANW = mSTC;
+
+ EGLint winAttrs[] = {
+ // clang-format off
+ EGL_GL_COLORSPACE_KHR, EGL_BACK_BUFFER,
+ EGL_NONE,
+ // clang-format on
+ };
+
+ EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
+ ASSERT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
+ ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
+
+ // Now recreate surface with a valid colorspace. Ensure proper cleanup is done
+ // in the first failed attempt (e.g. native_window_api_disconnect).
+ winAttrs[1] = EGL_GL_COLORSPACE_LINEAR_KHR;
+ eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_SURFACE, eglSurface);
+
+ EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
+}
+
+TEST_F(EGLTest, EGLCreateWindowTwoColorspaces) {
+ EGLConfig config;
+
+ ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
+
+ struct DummyConsumer : public BnConsumerListener {
+ void onFrameAvailable(const BufferItem& /* item */) override {}
+ void onBuffersReleased() override {}
+ void onSidebandStreamChanged() override {}
+ };
+
+ // Create a EGLSurface
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ consumer->consumerConnect(new DummyConsumer, false);
+ sp<Surface> mSTC = new Surface(producer);
+ sp<ANativeWindow> mANW = mSTC;
+
+ const EGLint winAttrs[] = {
+ // clang-format off
+ EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
+ EGL_NONE,
+ // clang-format on
+ };
+
+ EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_SURFACE, eglSurface);
+
+ android_dataspace dataspace = static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(mANW.get()));
+ ASSERT_EQ(dataspace, HAL_DATASPACE_DISPLAY_P3);
+
+ EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
+
+ // Now create with default attribute (EGL_GL_COLORSPACE_LINEAR_KHR)
+ eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_SURFACE, eglSurface);
+
+ dataspace = static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(mANW.get()));
+ // Make sure the dataspace has been reset to UNKNOWN
+ ASSERT_NE(dataspace, HAL_DATASPACE_DISPLAY_P3);
+
+ EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
+}
}
diff --git a/opengl/tests/gl2_cameraeye/Android.bp b/opengl/tests/gl2_cameraeye/Android.bp
new file mode 100644
index 0000000..00e00df
--- /dev/null
+++ b/opengl/tests/gl2_cameraeye/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+ name: "GL2CameraEye",
+ // Only compile source java files in this apk.
+ srcs: ["src/**/*.java"],
+ sdk_version: "current",
+}
diff --git a/opengl/tests/gl2_cameraeye/Android.mk b/opengl/tests/gl2_cameraeye/Android.mk
deleted file mode 100644
index 4a43a9e..0000000
--- a/opengl/tests/gl2_cameraeye/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := GL2CameraEye
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/opengl/tests/gl2_java/Android.bp b/opengl/tests/gl2_java/Android.bp
new file mode 100644
index 0000000..a8e5d7d
--- /dev/null
+++ b/opengl/tests/gl2_java/Android.bp
@@ -0,0 +1,8 @@
+//########################################################################
+// OpenGL ES 2.0 Java sample
+//########################################################################
+android_app {
+ name: "GL2Java",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+}
diff --git a/opengl/tests/gl2_java/Android.mk b/opengl/tests/gl2_java/Android.mk
deleted file mode 100644
index 71aa5a0..0000000
--- a/opengl/tests/gl2_java/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-#########################################################################
-# OpenGL ES 2.0 Java sample
-#########################################################################
-
-TOP_LOCAL_PATH:= $(call my-dir)
-
-# Build activity
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := GL2Java
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/opengl/tests/gl2_jni/Android.bp b/opengl/tests/gl2_jni/Android.bp
new file mode 100644
index 0000000..65f89b1
--- /dev/null
+++ b/opengl/tests/gl2_jni/Android.bp
@@ -0,0 +1,27 @@
+//########################################################################
+// OpenGL ES JNI sample
+// This makefile builds both an activity and a shared library.
+//########################################################################
+
+android_app {
+ name: "GL2JNI",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ jni_libs: ["libgl2jni"],
+}
+
+// Build JNI Shared Library
+cc_library_shared {
+ name: "libgl2jni",
+ cflags: [
+ "-Werror",
+ "-Wno-error=unused-parameter",
+ ],
+ srcs: ["jni/gl_code.cpp"],
+ shared_libs: [
+ "liblog",
+ "libEGL",
+ "libGLESv2",
+ ],
+ sdk_version: "current",
+}
diff --git a/opengl/tests/gl2_jni/Android.mk b/opengl/tests/gl2_jni/Android.mk
deleted file mode 100644
index b0081c2..0000000
--- a/opengl/tests/gl2_jni/Android.mk
+++ /dev/null
@@ -1,49 +0,0 @@
-#########################################################################
-# OpenGL ES JNI sample
-# This makefile builds both an activity and a shared library.
-#########################################################################
-TOP_LOCAL_PATH:= $(call my-dir)
-
-# Build activity
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := GL2JNI
-LOCAL_SDK_VERSION := current
-
-LOCAL_JNI_SHARED_LIBRARIES := libgl2jni
-
-include $(BUILD_PACKAGE)
-
-#########################################################################
-# Build JNI Shared Library
-#########################################################################
-
-LOCAL_PATH:= $(LOCAL_PATH)/jni
-
-include $(CLEAR_VARS)
-
-# Optional tag would mean it doesn't get installed by default
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS := -Werror -Wno-error=unused-parameter
-
-LOCAL_SRC_FILES:= \
- gl_code.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- liblog \
- libEGL \
- libGLESv2
-
-LOCAL_MODULE := libgl2jni
-
-LOCAL_SDK_VERSION := current
-
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/opengl/tests/gl_jni/Android.bp b/opengl/tests/gl_jni/Android.bp
new file mode 100644
index 0000000..5bec336
--- /dev/null
+++ b/opengl/tests/gl_jni/Android.bp
@@ -0,0 +1,34 @@
+//########################################################################
+// OpenGL ES JNI sample
+// This makefile builds both an activity and a shared library.
+//########################################################################
+// Build activity
+
+android_app {
+ name: "GLJNI",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ jni_libs: ["libgljni"],
+}
+
+// Build JNI Shared Library
+
+cc_library_shared {
+ name: "libgljni",
+ cflags: [
+ "-Werror",
+ "-Wno-error=unused-parameter",
+ ],
+ srcs: ["jni/gl_code.cpp"],
+ shared_libs: [
+ "liblog",
+ "libEGL",
+ "libGLESv1_CM",
+ ],
+ sdk_version: "current",
+ arch: {
+ arm: {
+ instruction_set: "arm",
+ },
+ },
+}
diff --git a/opengl/tests/gl_jni/Android.mk b/opengl/tests/gl_jni/Android.mk
deleted file mode 100644
index d64dfcf..0000000
--- a/opengl/tests/gl_jni/Android.mk
+++ /dev/null
@@ -1,52 +0,0 @@
-#########################################################################
-# OpenGL ES JNI sample
-# This makefile builds both an activity and a shared library.
-#########################################################################
-TOP_LOCAL_PATH:= $(call my-dir)
-
-# Build activity
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := GLJNI
-LOCAL_SDK_VERSION := current
-
-LOCAL_JNI_SHARED_LIBRARIES := libgljni
-
-include $(BUILD_PACKAGE)
-
-#########################################################################
-# Build JNI Shared Library
-#########################################################################
-
-LOCAL_PATH:= $(LOCAL_PATH)/jni
-
-include $(CLEAR_VARS)
-
-# Optional tag would mean it doesn't get installed by default
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS := -Werror -Wno-error=unused-parameter
-
-LOCAL_SRC_FILES:= \
- gl_code.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- liblog \
- libEGL \
- libGLESv1_CM
-
-LOCAL_MODULE := libgljni
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_ARM_MODE := arm
-
-
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/opengl/tests/gl_perfapp/Android.bp b/opengl/tests/gl_perfapp/Android.bp
new file mode 100644
index 0000000..cf899ac
--- /dev/null
+++ b/opengl/tests/gl_perfapp/Android.bp
@@ -0,0 +1,27 @@
+//########################################################################
+// OpenGL ES Perf App
+// This makefile builds both an activity and a shared library.
+//########################################################################
+android_app {
+ name: "GLPerf",
+ srcs: ["**/*.java"],
+ jni_libs: ["libglperf"],
+ // Run on Eclair
+ sdk_version: "7",
+}
+
+// Build JNI Shared Library
+cc_library_shared {
+ name: "libglperf",
+ cflags: [
+ "-Werror",
+ "-Wno-error=unused-parameter",
+ ],
+ srcs: ["jni/gl_code.cpp"],
+ shared_libs: [
+ "liblog",
+ "libEGL",
+ "libGLESv2",
+ ],
+ sdk_version: "current",
+}
diff --git a/opengl/tests/gl_perfapp/Android.mk b/opengl/tests/gl_perfapp/Android.mk
deleted file mode 100644
index 3f411ea..0000000
--- a/opengl/tests/gl_perfapp/Android.mk
+++ /dev/null
@@ -1,52 +0,0 @@
-#########################################################################
-# OpenGL ES Perf App
-# This makefile builds both an activity and a shared library.
-#########################################################################
-TOP_LOCAL_PATH:= $(call my-dir)
-
-# Build activity
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := GLPerf
-
-LOCAL_JNI_SHARED_LIBRARIES := libglperf
-
-# Run on Eclair
-LOCAL_SDK_VERSION := 7
-
-include $(BUILD_PACKAGE)
-
-#########################################################################
-# Build JNI Shared Library
-#########################################################################
-
-LOCAL_PATH:= $(LOCAL_PATH)/jni
-
-include $(CLEAR_VARS)
-
-# Optional tag would mean it doesn't get installed by default
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS := -Werror -Wno-error=unused-parameter
-
-LOCAL_SRC_FILES:= \
- gl_code.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- liblog \
- libEGL \
- libGLESv2
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE := libglperf
-
-
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/opengl/tests/gldual/Android.bp b/opengl/tests/gldual/Android.bp
new file mode 100644
index 0000000..2432566
--- /dev/null
+++ b/opengl/tests/gldual/Android.bp
@@ -0,0 +1,30 @@
+//########################################################################
+// OpenGL ES JNI sample
+// This makefile builds both an activity and a shared library.
+//########################################################################
+// Build activity
+
+android_app {
+ name: "GLDual",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ jni_libs: ["libgldualjni"],
+}
+
+//########################################################################
+// Build JNI Shared Library
+//########################################################################
+cc_library_shared {
+ name: "libgldualjni",
+ cflags: [
+ "-Werror",
+ "-Wno-error=unused-parameter",
+ ],
+ srcs: ["jni/gl_code.cpp"],
+ shared_libs: [
+ "liblog",
+ "libEGL",
+ "libGLESv2",
+ ],
+ sdk_version: "current",
+}
diff --git a/opengl/tests/gldual/Android.mk b/opengl/tests/gldual/Android.mk
deleted file mode 100644
index 5bdc0a8..0000000
--- a/opengl/tests/gldual/Android.mk
+++ /dev/null
@@ -1,49 +0,0 @@
-#########################################################################
-# OpenGL ES JNI sample
-# This makefile builds both an activity and a shared library.
-#########################################################################
-TOP_LOCAL_PATH:= $(call my-dir)
-
-# Build activity
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := GLDual
-LOCAL_SDK_VERSION := current
-
-LOCAL_JNI_SHARED_LIBRARIES := libgldualjni
-
-include $(BUILD_PACKAGE)
-
-#########################################################################
-# Build JNI Shared Library
-#########################################################################
-
-LOCAL_PATH:= $(LOCAL_PATH)/jni
-
-include $(CLEAR_VARS)
-
-# Optional tag would mean it doesn't get installed by default
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS := -Werror -Wno-error=unused-parameter
-
-LOCAL_SRC_FILES:= \
- gl_code.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- liblog \
- libEGL \
- libGLESv2
-
-LOCAL_MODULE := libgldualjni
-
-LOCAL_SDK_VERSION := current
-
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/opengl/tests/hwc/hwcCommit.cpp b/opengl/tests/hwc/hwcCommit.cpp
index 3686dab..0a6ff55 100644
--- a/opengl/tests/hwc/hwcCommit.cpp
+++ b/opengl/tests/hwc/hwcCommit.cpp
@@ -183,7 +183,7 @@
uint32_t lower(void) { return _l; }
uint32_t upper(void) { return _u; }
- operator string();
+ operator string(); // NOLINT(google-explicit-constructor)
private:
uint32_t _l; // lower
@@ -216,7 +216,9 @@
static void double2Rational(double f, Range nRange, Range dRange,
Rational& lower, Rational& upper);
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator string() const;
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator double() const { return (double) _n / (double) _d; }
diff --git a/opengl/tests/hwc/hwcTestLib.h b/opengl/tests/hwc/hwcTestLib.h
index 922fc19..5a49393 100644
--- a/opengl/tests/hwc/hwcTestLib.h
+++ b/opengl/tests/hwc/hwcTestLib.h
@@ -58,7 +58,7 @@
float c2(void) const { return _c2; }
float c3(void) const { return _c3; }
- operator std::string();
+ operator std::string(); // NOLINT(google-explicit-constructor)
private:
float _c1;
@@ -71,7 +71,7 @@
class ColorRGB {
public:
ColorRGB(): _r(0.0), _g(0.0), _b(0.0) {};
- ColorRGB(float f): _r(f), _g(f), _b(f) {}; // Gray, NOLINT(implicit)
+ ColorRGB(float f): _r(f), _g(f), _b(f) {}; // Gray, NOLINT(google-explicit-constructor)
ColorRGB(float r, float g, float b): _r(r), _g(g), _b(b) {};
float r(void) const { return _r; }
float g(void) const { return _g; }
@@ -93,8 +93,8 @@
void setWidth(uint32_t w) { _w = w; }
void setHeight(uint32_t h) { _h = h; }
- operator std::string();
- operator hwc_rect() const;
+ operator std::string(); // NOLINT(google-explicit-constructor)
+ operator hwc_rect() const; // NOLINT(google-explicit-constructor)
private:
uint32_t _w;
diff --git a/opengl/tests/lighting1709/Android.bp b/opengl/tests/lighting1709/Android.bp
new file mode 100644
index 0000000..e734dd1
--- /dev/null
+++ b/opengl/tests/lighting1709/Android.bp
@@ -0,0 +1,6 @@
+android_test {
+ name: "LightingTest",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ certificate: "platform",
+}
diff --git a/opengl/tests/lighting1709/Android.mk b/opengl/tests/lighting1709/Android.mk
deleted file mode 100644
index 0047231..0000000
--- a/opengl/tests/lighting1709/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := LightingTest
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/opengl/tests/linetex/Android.bp b/opengl/tests/linetex/Android.bp
new file mode 100644
index 0000000..dbc2cdb
--- /dev/null
+++ b/opengl/tests/linetex/Android.bp
@@ -0,0 +1,17 @@
+cc_binary {
+ name: "test-opengl-linetex",
+ srcs: ["linetex.cpp"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ shared_libs: [
+ "libcutils",
+ "libEGL",
+ "libGLESv1_CM",
+ "libui",
+ "libgui",
+ "libutils",
+ ],
+ static_libs: ["libglTest"],
+}
diff --git a/opengl/tests/linetex/Android.mk b/opengl/tests/linetex/Android.mk
deleted file mode 100644
index 3df0a0f..0000000
--- a/opengl/tests/linetex/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- linetex.cpp
-
-LOCAL_CFLAGS := -Wall -Werror
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libEGL \
- libGLESv1_CM \
- libui \
- libgui \
- libutils
-
-LOCAL_STATIC_LIBRARIES += libglTest
-
-LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
-
-LOCAL_MODULE:= test-opengl-linetex
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/swapinterval/Android.bp b/opengl/tests/swapinterval/Android.bp
new file mode 100644
index 0000000..eed4dff
--- /dev/null
+++ b/opengl/tests/swapinterval/Android.bp
@@ -0,0 +1,17 @@
+cc_binary {
+ name: "test-opengl-swapinterval",
+ srcs: ["swapinterval.cpp"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ shared_libs: [
+ "libcutils",
+ "libutils",
+ "libEGL",
+ "libGLESv1_CM",
+ "libui",
+ "libgui",
+ ],
+ static_libs: ["libglTest"],
+}
diff --git a/opengl/tests/swapinterval/Android.mk b/opengl/tests/swapinterval/Android.mk
deleted file mode 100644
index 2a2c12f..0000000
--- a/opengl/tests/swapinterval/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- swapinterval.cpp
-
-LOCAL_CFLAGS := -Wall -Werror
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libutils \
- libEGL \
- libGLESv1_CM \
- libui \
- libgui
-
-LOCAL_STATIC_LIBRARIES += libglTest
-
-LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
-
-LOCAL_MODULE:= test-opengl-swapinterval
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/testFramerate/Android.bp b/opengl/tests/testFramerate/Android.bp
new file mode 100644
index 0000000..5aa83b0
--- /dev/null
+++ b/opengl/tests/testFramerate/Android.bp
@@ -0,0 +1,9 @@
+//########################################################################
+// Test framerate and look for hiccups
+//########################################################################
+
+android_app {
+ name: "TestFramerate",
+ srcs: ["**/*.java"],
+ sdk_version: "system_current",
+}
diff --git a/opengl/tests/testFramerate/Android.mk b/opengl/tests/testFramerate/Android.mk
deleted file mode 100644
index ca6654a..0000000
--- a/opengl/tests/testFramerate/Android.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-#########################################################################
-# Test framerate and look for hiccups
-#########################################################################
-
-TOP_LOCAL_PATH:= $(call my-dir)
-
-# Build activity
-
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := TestFramerate
-LOCAL_SDK_VERSION := system_current
-
-include $(BUILD_PACKAGE)
diff --git a/opengl/tests/testLatency/Android.bp b/opengl/tests/testLatency/Android.bp
new file mode 100644
index 0000000..c516dc3
--- /dev/null
+++ b/opengl/tests/testLatency/Android.bp
@@ -0,0 +1,8 @@
+//########################################################################
+// Test end-to-end latency.
+//########################################################################
+android_app {
+ name: "TestLatency",
+ sdk_version: "8",
+ srcs: ["**/*.java"],
+}
diff --git a/opengl/tests/testLatency/Android.mk b/opengl/tests/testLatency/Android.mk
deleted file mode 100644
index 96417c7..0000000
--- a/opengl/tests/testLatency/Android.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-#########################################################################
-# Test end-to-end latency.
-#########################################################################
-
-TOP_LOCAL_PATH:= $(call my-dir)
-
-# Build activity
-
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SDK_VERSION := 8
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := TestLatency
-
-include $(BUILD_PACKAGE)
diff --git a/opengl/tests/testPauseResume/Android.bp b/opengl/tests/testPauseResume/Android.bp
new file mode 100644
index 0000000..810e895
--- /dev/null
+++ b/opengl/tests/testPauseResume/Android.bp
@@ -0,0 +1,6 @@
+// OpenGL ES JNI sample
+android_app {
+ name: "TestEGL",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+}
diff --git a/opengl/tests/testPauseResume/Android.mk b/opengl/tests/testPauseResume/Android.mk
deleted file mode 100644
index dda5424..0000000
--- a/opengl/tests/testPauseResume/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-#########################################################################
-# OpenGL ES JNI sample
-# This makefile builds both an activity and a shared library.
-#########################################################################
-TOP_LOCAL_PATH:= $(call my-dir)
-
-# Build activity
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := TestEGL
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/opengl/tests/testViewport/Android.bp b/opengl/tests/testViewport/Android.bp
new file mode 100644
index 0000000..629b573
--- /dev/null
+++ b/opengl/tests/testViewport/Android.bp
@@ -0,0 +1,9 @@
+//########################################################################
+// OpenGL ES JNI sample
+// This makefile builds both an activity and a shared library.
+//########################################################################
+android_app {
+ name: "TestViewport",
+ srcs: ["**/*.java"],
+ sdk_version: "8",
+}
diff --git a/opengl/tests/testViewport/Android.mk b/opengl/tests/testViewport/Android.mk
deleted file mode 100644
index 9980e7d..0000000
--- a/opengl/tests/testViewport/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-#########################################################################
-# OpenGL ES JNI sample
-# This makefile builds both an activity and a shared library.
-#########################################################################
-TOP_LOCAL_PATH:= $(call my-dir)
-
-# Build activity
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := TestViewport
-
-# Set a specific SDK version so we can run on Froyo.
-
-LOCAL_SDK_VERSION := 8
-
-include $(BUILD_PACKAGE)
diff --git a/opengl/tests/textures/Android.bp b/opengl/tests/textures/Android.bp
new file mode 100644
index 0000000..84adda2
--- /dev/null
+++ b/opengl/tests/textures/Android.bp
@@ -0,0 +1,18 @@
+cc_binary {
+ name: "test-opengl-textures",
+ srcs: ["textures.cpp"],
+ shared_libs: [
+ "libcutils",
+ "libEGL",
+ "libGLESv1_CM",
+ "libui",
+ "libgui",
+ "libutils",
+ ],
+ static_libs: ["libglTest"],
+ cflags: [
+ "-DGL_GLEXT_PROTOTYPES",
+ "-Wall",
+ "-Werror",
+ ],
+}
diff --git a/opengl/tests/textures/Android.mk b/opengl/tests/textures/Android.mk
deleted file mode 100644
index 629a2d2..0000000
--- a/opengl/tests/textures/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- textures.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libEGL \
- libGLESv1_CM \
- libui \
- libgui \
- libutils
-
-LOCAL_STATIC_LIBRARIES += libglTest
-
-LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
-
-LOCAL_MODULE:= test-opengl-textures
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES
-LOCAL_CFLAGS += -Wall -Werror
-
-include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/tritex/Android.bp b/opengl/tests/tritex/Android.bp
new file mode 100644
index 0000000..390397b
--- /dev/null
+++ b/opengl/tests/tritex/Android.bp
@@ -0,0 +1,17 @@
+cc_binary {
+ name: "test-opengl-tritex",
+ srcs: ["tritex.cpp"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ shared_libs: [
+ "libcutils",
+ "libEGL",
+ "libGLESv1_CM",
+ "libui",
+ "libgui",
+ "libutils",
+ ],
+ static_libs: ["libglTest"],
+}
diff --git a/opengl/tests/tritex/Android.mk b/opengl/tests/tritex/Android.mk
deleted file mode 100644
index 7055afa..0000000
--- a/opengl/tests/tritex/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- tritex.cpp
-
-LOCAL_CFLAGS := -Wall -Werror
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libEGL \
- libGLESv1_CM \
- libui \
- libgui \
- libutils
-
-LOCAL_STATIC_LIBRARIES += libglTest
-
-LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
-
-LOCAL_MODULE:= test-opengl-tritex
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/displayservice/OWNERS b/services/displayservice/OWNERS
new file mode 100644
index 0000000..7a3e4c2
--- /dev/null
+++ b/services/displayservice/OWNERS
@@ -0,0 +1,2 @@
+smoreland@google.com
+lpy@google.com
diff --git a/services/displayservice/include/displayservice/DisplayEventReceiver.h b/services/displayservice/include/displayservice/DisplayEventReceiver.h
index 5d569b6..042a054 100644
--- a/services/displayservice/include/displayservice/DisplayEventReceiver.h
+++ b/services/displayservice/include/displayservice/DisplayEventReceiver.h
@@ -45,7 +45,7 @@
using FwkReceiver = ::android::DisplayEventReceiver;
struct AttachedEvent : LooperCallback {
- AttachedEvent(const sp<IEventCallback> &callback);
+ explicit AttachedEvent(const sp<IEventCallback> &callback);
~AttachedEvent();
bool detach();
diff --git a/services/gpuservice/Android.bp b/services/gpuservice/Android.bp
new file mode 100644
index 0000000..47bed65
--- /dev/null
+++ b/services/gpuservice/Android.bp
@@ -0,0 +1,73 @@
+filegroup {
+ name: "gpuservice_sources",
+ srcs: [
+ "GpuService.cpp",
+ ],
+}
+
+filegroup {
+ name: "gpuservice_binary_sources",
+ srcs: ["main_gpuservice.cpp"],
+}
+
+cc_defaults {
+ name: "gpuservice_defaults",
+ cflags: [
+ "-DLOG_TAG=\"GpuService\"",
+ "-Wall",
+ "-Werror",
+ "-Wformat",
+ "-Wthread-safety",
+ "-Wunused",
+ "-Wunreachable-code",
+ ],
+ srcs: [
+ ":gpuservice_sources",
+ ],
+ include_dirs: [
+ "frameworks/native/vulkan/vkjson",
+ "frameworks/native/vulkan/include",
+ ],
+ shared_libs: [
+ "libbinder",
+ "liblog",
+ "libutils",
+ "libvulkan",
+ ],
+ static_libs: [
+ "libvkjson",
+ ],
+}
+
+cc_defaults {
+ name: "gpuservice_production_defaults",
+ defaults: ["gpuservice_defaults"],
+ cflags: [
+ "-fvisibility=hidden",
+ "-fwhole-program-vtables", // requires ThinLTO
+ ],
+ lto: {
+ thin: true,
+ },
+}
+
+cc_defaults {
+ name: "gpuservice_binary",
+ defaults: ["gpuservice_defaults"],
+ whole_static_libs: [
+ "libsigchain",
+ ],
+ shared_libs: [
+ "libbinder",
+ "liblog",
+ "libutils",
+ ],
+ ldflags: ["-Wl,--export-dynamic"],
+}
+
+cc_binary {
+ name: "gpuservice",
+ defaults: ["gpuservice_binary"],
+ init_rc: ["gpuservice.rc"],
+ srcs: [":gpuservice_binary_sources"],
+}
diff --git a/services/surfaceflinger/GpuService.cpp b/services/gpuservice/GpuService.cpp
similarity index 84%
rename from services/surfaceflinger/GpuService.cpp
rename to services/gpuservice/GpuService.cpp
index 71052fb..150896c 100644
--- a/services/surfaceflinger/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -23,10 +23,7 @@
namespace android {
-// ----------------------------------------------------------------------------
-
-class BpGpuService : public BpInterface<IGpuService>
-{
+class BpGpuService : public BpInterface<IGpuService> {
public:
explicit BpGpuService(const sp<IBinder>& impl) : BpInterface<IGpuService>(impl) {}
};
@@ -34,19 +31,15 @@
IMPLEMENT_META_INTERFACE(GpuService, "android.ui.IGpuService");
status_t BnGpuService::onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags)
-{
+ Parcel* reply, uint32_t flags) {
status_t status;
switch (code) {
case SHELL_COMMAND_TRANSACTION: {
int in = data.readFileDescriptor();
int out = data.readFileDescriptor();
int err = data.readFileDescriptor();
- int argc = data.readInt32();
- Vector<String16> args;
- for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
- args.add(data.readString16());
- }
+ std::vector<String16> args;
+ data.readString16Vector(&args);
sp<IBinder> unusedCallback;
sp<IResultReceiver> resultReceiver;
if ((status = data.readNullableStrongBinder(&unusedCallback)) != OK)
@@ -64,8 +57,6 @@
}
}
-// ----------------------------------------------------------------------------
-
namespace {
status_t cmd_help(int out);
status_t cmd_vkjson(int out, int err);
@@ -73,11 +64,10 @@
const char* const GpuService::SERVICE_NAME = "gpu";
-GpuService::GpuService() {}
+GpuService::GpuService() = default;
status_t GpuService::shellCommand(int /*in*/, int out, int err,
- Vector<String16>& args)
-{
+ std::vector<String16>& args) {
ALOGV("GpuService::shellCommand");
for (size_t i = 0, n = args.size(); i < n; i++)
ALOGV(" arg[%zu]: '%s'", i, String8(args[i]).string());
@@ -93,8 +83,6 @@
return BAD_VALUE;
}
-// ----------------------------------------------------------------------------
-
namespace {
status_t cmd_help(int out) {
diff --git a/services/surfaceflinger/GpuService.h b/services/gpuservice/GpuService.h
similarity index 80%
rename from services/surfaceflinger/GpuService.h
rename to services/gpuservice/GpuService.h
index b8c28d2..e2b396e 100644
--- a/services/surfaceflinger/GpuService.h
+++ b/services/gpuservice/GpuService.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_GPUSERVICE_H
#define ANDROID_GPUSERVICE_H
+#include <vector>
+
#include <binder/IInterface.h>
#include <cutils/compiler.h>
@@ -34,22 +36,21 @@
class BnGpuService: public BnInterface<IGpuService> {
protected:
virtual status_t shellCommand(int in, int out, int err,
- Vector<String16>& args) = 0;
+ std::vector<String16>& args) = 0;
- virtual status_t onTransact(uint32_t code, const Parcel& data,
+ status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags = 0) override;
};
-class GpuService : public BnGpuService
-{
+class GpuService : public BnGpuService {
public:
static const char* const SERVICE_NAME ANDROID_API;
GpuService() ANDROID_API;
protected:
- virtual status_t shellCommand(int in, int out, int err,
- Vector<String16>& args) override;
+ status_t shellCommand(int in, int out, int err,
+ std::vector<String16>& args) override;
};
} // namespace android
diff --git a/services/gpuservice/gpuservice.rc b/services/gpuservice/gpuservice.rc
new file mode 100644
index 0000000..65a5c27
--- /dev/null
+++ b/services/gpuservice/gpuservice.rc
@@ -0,0 +1,4 @@
+service gpu /system/bin/gpuservice
+ class core
+ user gpu_service
+ group graphics
diff --git a/services/gpuservice/main_gpuservice.cpp b/services/gpuservice/main_gpuservice.cpp
new file mode 100644
index 0000000..64aafca
--- /dev/null
+++ b/services/gpuservice/main_gpuservice.cpp
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <sys/resource.h>
+#include "GpuService.h"
+
+using namespace android;
+
+int main(int /* argc */, char** /* argv */) {
+ signal(SIGPIPE, SIG_IGN);
+
+ // publish GpuService
+ sp<GpuService> gpuservice = new GpuService();
+ sp<IServiceManager> sm(defaultServiceManager());
+ sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false);
+
+ // limit the number of binder threads to 4.
+ ProcessState::self()->setThreadPoolMaxThreadCount(4);
+
+ // start the thread pool
+ sp<ProcessState> ps(ProcessState::self());
+ ps->startThreadPool();
+ ps->giveThreadPoolName();
+ IPCThreadState::self()->joinThreadPool();
+
+ return 0;
+}
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index 4d9a2a0..ccc24b9 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -206,7 +206,7 @@
mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
- mEpollFd = epoll_create(EPOLL_SIZE_HINT);
+ mEpollFd = epoll_create1(EPOLL_CLOEXEC);
LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno);
mINotifyFd = inotify_init();
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index b37b7fd..efa6f88 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -3089,6 +3089,7 @@
InputMapper(device),
mSource(0), mDeviceMode(DEVICE_MODE_DISABLED),
mSurfaceWidth(-1), mSurfaceHeight(-1), mSurfaceLeft(0), mSurfaceTop(0),
+ mPhysicalWidth(-1), mPhysicalHeight(-1), mPhysicalLeft(0), mPhysicalTop(0),
mSurfaceOrientation(DISPLAY_ORIENTATION_0) {
}
@@ -3596,6 +3597,11 @@
break;
}
+ mPhysicalWidth = naturalPhysicalWidth;
+ mPhysicalHeight = naturalPhysicalHeight;
+ mPhysicalLeft = naturalPhysicalLeft;
+ mPhysicalTop = naturalPhysicalTop;
+
mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth;
mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight;
mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth;
@@ -3604,6 +3610,11 @@
mSurfaceOrientation = mParameters.orientationAware ?
mViewport.orientation : DISPLAY_ORIENTATION_0;
} else {
+ mPhysicalWidth = rawWidth;
+ mPhysicalHeight = rawHeight;
+ mPhysicalLeft = 0;
+ mPhysicalTop = 0;
+
mSurfaceWidth = rawWidth;
mSurfaceHeight = rawHeight;
mSurfaceLeft = 0;
@@ -3914,6 +3925,10 @@
dump += StringPrintf(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight);
dump += StringPrintf(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft);
dump += StringPrintf(INDENT3 "SurfaceTop: %d\n", mSurfaceTop);
+ dump += StringPrintf(INDENT3 "PhysicalWidth: %dpx\n", mPhysicalWidth);
+ dump += StringPrintf(INDENT3 "PhysicalHeight: %dpx\n", mPhysicalHeight);
+ dump += StringPrintf(INDENT3 "PhysicalLeft: %d\n", mPhysicalLeft);
+ dump += StringPrintf(INDENT3 "PhysicalTop: %d\n", mPhysicalTop);
dump += StringPrintf(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation);
}
@@ -5118,10 +5133,10 @@
}
break;
case DISPLAY_ORIENTATION_180:
- x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate;
+ x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale;
y = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate;
- left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
- right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
+ left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale;
+ right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale;
bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
orientation -= M_PI;
@@ -5130,10 +5145,10 @@
}
break;
case DISPLAY_ORIENTATION_270:
- x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate;
+ x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale;
y = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
- left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
- right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
+ left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale;
+ right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale;
bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
orientation += M_PI_2;
@@ -6531,8 +6546,12 @@
}
bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
+ const float scaledX = x * mXScale;
+ const float scaledY = y * mYScale;
return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue
- && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue;
+ && scaledX >= mPhysicalLeft && scaledX <= mPhysicalLeft + mPhysicalWidth
+ && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue
+ && scaledY >= mPhysicalTop && scaledY <= mPhysicalTop + mPhysicalHeight;
}
const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index cef3212..2f98e69 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -1517,13 +1517,21 @@
// in the natural orientation.
// The surface origin specifies how the surface coordinates should be translated
// to align with the logical display coordinate space.
- // The orientation may be different from the viewport orientation as it specifies
- // the rotation of the surface coordinates required to produce the viewport's
- // requested orientation, so it will depend on whether the device is orientation aware.
int32_t mSurfaceWidth;
int32_t mSurfaceHeight;
int32_t mSurfaceLeft;
int32_t mSurfaceTop;
+
+ // Similar to the surface coordinates, but in the raw display coordinate space rather than in
+ // the logical coordinate space.
+ int32_t mPhysicalWidth;
+ int32_t mPhysicalHeight;
+ int32_t mPhysicalLeft;
+ int32_t mPhysicalTop;
+
+ // The orientation may be different from the viewport orientation as it specifies
+ // the rotation of the surface coordinates required to produce the viewport's
+ // requested orientation, so it will depend on whether the device is orientation aware.
int32_t mSurfaceOrientation;
// Translation and scaling factors, orientation-independent.
diff --git a/services/inputflinger/OWNERS b/services/inputflinger/OWNERS
new file mode 100644
index 0000000..0313a40
--- /dev/null
+++ b/services/inputflinger/OWNERS
@@ -0,0 +1,2 @@
+michaelwr@google.com
+svv@google.com
diff --git a/services/nativeperms/Android.bp b/services/nativeperms/Android.bp
new file mode 100644
index 0000000..cbc7d66
--- /dev/null
+++ b/services/nativeperms/Android.bp
@@ -0,0 +1,34 @@
+// 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.
+//
+
+cc_binary {
+ name: "nativeperms",
+ srcs: [
+ "nativeperms.cpp",
+ "android/os/IPermissionController.aidl",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libbrillo",
+ "libbrillo-binder",
+ "libchrome",
+ "libutils",
+ ],
+ init_rc: ["nativeperms.rc"],
+}
diff --git a/services/nativeperms/Android.mk b/services/nativeperms/Android.mk
deleted file mode 100644
index 34ccd0b..0000000
--- a/services/nativeperms/Android.mk
+++ /dev/null
@@ -1,31 +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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := nativeperms
-LOCAL_SRC_FILES := \
- nativeperms.cpp \
- android/os/IPermissionController.aidl
-LOCAL_CFLAGS := -Wall -Werror
-LOCAL_SHARED_LIBRARIES := \
- libbinder \
- libbrillo \
- libbrillo-binder \
- libchrome \
- libutils
-LOCAL_INIT_RC := nativeperms.rc
-include $(BUILD_EXECUTABLE)
diff --git a/services/sensorservice/OWNERS b/services/sensorservice/OWNERS
index d4393d6..81099e8 100644
--- a/services/sensorservice/OWNERS
+++ b/services/sensorservice/OWNERS
@@ -1,2 +1,3 @@
arthuri@google.com
bduddie@google.com
+bstack@google.com
diff --git a/services/sensorservice/SensorRecord.h b/services/sensorservice/SensorRecord.h
index 5a35410..031744a 100644
--- a/services/sensorservice/SensorRecord.h
+++ b/services/sensorservice/SensorRecord.h
@@ -25,7 +25,7 @@
class SensorService::SensorRecord {
public:
- SensorRecord(const sp<const SensorEventConnection>& connection);
+ explicit SensorRecord(const sp<const SensorEventConnection>& connection);
bool addConnection(const sp<const SensorEventConnection>& connection);
bool removeConnection(const wp<const SensorEventConnection>& connection);
size_t getNumConnections() const { return mConnections.size(); }
diff --git a/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h b/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
index ddcee28..8d7a05b 100644
--- a/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
+++ b/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
@@ -43,7 +43,7 @@
struct SensorManager final : public ISensorManager {
- SensorManager(JavaVM* vm);
+ explicit SensorManager(JavaVM* vm);
~SensorManager();
// Methods from ::android::frameworks::sensorservice::V1_0::ISensorManager follow.
diff --git a/services/sensorservice/mat.h b/services/sensorservice/mat.h
index 495c14e..934ae58 100644
--- a/services/sensorservice/mat.h
+++ b/services/sensorservice/mat.h
@@ -139,13 +139,13 @@
mat() { }
mat(const mat& rhs) : base(rhs) { }
- mat(const base& rhs) : base(rhs) { } // NOLINT(implicit)
+ mat(const base& rhs) : base(rhs) { } // NOLINT(google-explicit-constructor)
// -----------------------------------------------------------------------
// conversion constructors
// sets the diagonal to the value, off-diagonal to zero
- mat(pTYPE rhs) { // NOLINT(implicit)
+ mat(pTYPE rhs) { // NOLINT(google-explicit-constructor)
helpers::doAssign(*this, rhs);
}
diff --git a/services/sensorservice/tests/Android.bp b/services/sensorservice/tests/Android.bp
new file mode 100644
index 0000000..d33c0ca
--- /dev/null
+++ b/services/sensorservice/tests/Android.bp
@@ -0,0 +1,13 @@
+cc_binary {
+ name: "test-sensorservice",
+ srcs: ["sensorservicetest.cpp"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ shared_libs: [
+ "libutils",
+ "libsensor",
+ "libandroid",
+ ],
+}
diff --git a/services/sensorservice/tests/Android.mk b/services/sensorservice/tests/Android.mk
deleted file mode 100644
index 8a9c36b..0000000
--- a/services/sensorservice/tests/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- sensorservicetest.cpp
-
-LOCAL_CFLAGS := -Wall -Werror
-
-LOCAL_SHARED_LIBRARIES := \
- libutils libsensor libandroid
-
-LOCAL_MODULE:= test-sensorservice
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/sensorservice/vec.h b/services/sensorservice/vec.h
index 9e5d280..c195434 100644
--- a/services/sensorservice/vec.h
+++ b/services/sensorservice/vec.h
@@ -322,12 +322,12 @@
vec() { }
vec(const vec& rhs) : base(rhs) { }
- vec(const base& rhs) : base(rhs) { } // NOLINT(implicit)
+ vec(const base& rhs) : base(rhs) { } // NOLINT(google-explicit-constructor)
// -----------------------------------------------------------------------
// conversion constructors
- vec(pTYPE rhs) { // NOLINT(implicit)
+ vec(pTYPE rhs) { // NOLINT(google-explicit-constructor)
for (size_t i=0 ; i<SIZE ; i++)
base::operator[](i) = rhs;
}
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 320e11f..22e7761 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -8,7 +8,6 @@
"-Wunused",
"-Wunreachable-code",
],
- cppflags: ["-std=c++1z"],
}
cc_defaults {
@@ -45,17 +44,16 @@
"liblayers_proto",
"liblog",
"libpdx_default_transport",
+ "libprocessgroup",
"libprotobuf-cpp-lite",
"libsync",
"libtimestats_proto",
"libui",
"libutils",
- "libvulkan",
],
static_libs: [
"libserviceutils",
"libtrace_proto",
- "libvkjson",
"libvr_manager",
"libvrflinger",
],
@@ -106,7 +104,6 @@
"EventLog/EventLog.cpp",
"EventThread.cpp",
"FrameTracker.cpp",
- "GpuService.cpp",
"Layer.cpp",
"LayerProtoHelper.cpp",
"LayerRejecter.cpp",
@@ -177,6 +174,7 @@
"libhidltransport",
"liblayers_proto",
"liblog",
+ "libprocessgroup",
"libsurfaceflinger",
"libtimestats_proto",
"libutils",
@@ -209,6 +207,7 @@
"libcutils",
"libdl",
"liblog",
+ "libprocessgroup",
],
product_variables: {
// uses jni which may not be available in PDK
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 3db633b..f5b5eda 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -704,6 +704,8 @@
}
void BufferLayer::onFirstRef() {
+ Layer::onFirstRef();
+
// Creates a custom BufferQueue for SurfaceFlingerConsumer to use
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp
index f259d93..6f5bd0e 100644
--- a/services/surfaceflinger/ContainerLayer.cpp
+++ b/services/surfaceflinger/ContainerLayer.cpp
@@ -30,10 +30,6 @@
void ContainerLayer::onDraw(const RenderArea&, const Region& /* clip */, bool) const {}
-bool ContainerLayer::isVisible() const {
- return !isHiddenByPolicy();
-}
-
void ContainerLayer::setPerFrameData(const sp<const DisplayDevice>&) {}
} // namespace android
diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h
index b352b96..38b1882 100644
--- a/services/surfaceflinger/ContainerLayer.h
+++ b/services/surfaceflinger/ContainerLayer.h
@@ -32,7 +32,7 @@
const char* getTypeId() const override { return "ContainerLayer"; }
void onDraw(const RenderArea& renderArea, const Region& clip,
bool useIdentityTransform) const override;
- bool isVisible() const override;
+ bool isVisible() const override { return false; }
void setPerFrameData(const sp<const DisplayDevice>& displayDevice) override;
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 37ba433..f190b71 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -41,13 +41,12 @@
class BufferHandle {
public:
- BufferHandle(const native_handle_t* buffer)
- {
+ explicit BufferHandle(const native_handle_t* buffer) {
// nullptr is not a valid handle to HIDL
mHandle = (buffer) ? buffer : native_handle_init(mStorage, 0, 0);
}
- operator const hidl_handle&() const
+ operator const hidl_handle&() const // NOLINT(google-explicit-constructor)
{
return mHandle;
}
@@ -81,7 +80,7 @@
}
}
- operator const hidl_handle&() const
+ operator const hidl_handle&() const // NOLINT(google-explicit-constructor)
{
return mHandle;
}
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index beee539..442006c 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -267,7 +267,7 @@
// Composer is a wrapper to IComposer, a proxy to server-side composer.
class Composer final : public Hwc2::Composer {
public:
- Composer(const std::string& serviceName);
+ explicit Composer(const std::string& serviceName);
~Composer() override;
std::vector<IComposer::Capability> getCapabilities() override;
@@ -383,7 +383,7 @@
private:
class CommandWriter : public CommandWriterBase {
public:
- CommandWriter(uint32_t initialMaxSize);
+ explicit CommandWriter(uint32_t initialMaxSize);
~CommandWriter() override;
void setLayerInfo(uint32_t type, uint32_t appId);
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 90e0e9e..0caac9b 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -133,22 +133,7 @@
CompositorTiming compositorTiming;
flinger->getCompositorTiming(&compositorTiming);
mFrameEventHistory.initializeCompositorTiming(compositorTiming);
-}
-
-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();
- }
+ mFrameTracker.setDisplayRefreshPeriod(compositorTiming.interval);
}
Layer::~Layer() {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 2239679..301f190 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -618,8 +618,6 @@
: mFlinger(flinger), mLayer(layer) {}
};
- virtual void onFirstRef();
-
friend class impl::SurfaceInterceptor;
void commitTransaction(const State& stateToCommit);
diff --git a/services/surfaceflinger/OWNERS b/services/surfaceflinger/OWNERS
new file mode 100644
index 0000000..dc2b300
--- /dev/null
+++ b/services/surfaceflinger/OWNERS
@@ -0,0 +1,5 @@
+chaviw@google.com
+lpy@google.com
+marissaw@google.com
+racarr@google.com
+stoza@google.com
\ No newline at end of file
diff --git a/services/surfaceflinger/StartPropertySetThread.h b/services/surfaceflinger/StartPropertySetThread.h
index a64c21b..bbdcde2 100644
--- a/services/surfaceflinger/StartPropertySetThread.h
+++ b/services/surfaceflinger/StartPropertySetThread.h
@@ -33,7 +33,7 @@
// Any property_set() will block during init stage so need to be offloaded
// to this thread. see b/63844978.
public:
- StartPropertySetThread(bool timestampPropertyValue);
+ explicit StartPropertySetThread(bool timestampPropertyValue);
status_t Start();
private:
virtual bool threadLoop();
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index cf53930..e693dd2 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -981,6 +981,21 @@
return NO_ERROR;
}
+status_t SurfaceFlinger::getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) {
+ if (outViewport == nullptr || display.get() == nullptr) {
+ return BAD_VALUE;
+ }
+
+ sp<const DisplayDevice> device(getDisplayDevice(display));
+ if (device == nullptr) {
+ return BAD_VALUE;
+ }
+
+ *outViewport = device->getViewport();
+
+ return NO_ERROR;
+}
+
int SurfaceFlinger::getActiveConfig(const sp<IBinder>& display) {
if (display == nullptr) {
ALOGE("%s : display is nullptr", __func__);
@@ -2180,11 +2195,15 @@
displayDevice->onSwapBuffersCompleted();
displayDevice->makeCurrent();
for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+ sp<Fence> releaseFence = Fence::NO_FENCE;
+
// The layer buffer from the previous frame (if any) is released
// by HWC only when the release fence from this frame (if any) is
// signaled. Always get the release fence from HWC first.
auto hwcLayer = layer->getHwcLayer(hwcId);
- sp<Fence> releaseFence = getBE().mHwc->getLayerReleaseFence(hwcId, hwcLayer);
+ if (hwcId >= 0) {
+ releaseFence = getBE().mHwc->getLayerReleaseFence(hwcId, hwcLayer);
+ }
// If the layer was client composited in the previous frame, we
// need to merge with the previous client target acquire fence.
@@ -2331,8 +2350,10 @@
const sp<DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer) {
bool hasWideColorGamut = false;
std::unordered_map<ColorMode, std::vector<RenderIntent>> hwcColorModes;
+ HdrCapabilities hdrCapabilities;
+ int32_t supportedPerFrameMetadata = 0;
- if (hasWideColorDisplay) {
+ if (hasWideColorDisplay && hwcId >= 0) {
std::vector<ColorMode> modes = getHwComposer().getColorModes(hwcId);
for (ColorMode colorMode : modes) {
switch (colorMode) {
@@ -2351,8 +2372,10 @@
}
}
- HdrCapabilities hdrCapabilities;
- getHwComposer().getHdrCapabilities(hwcId, &hdrCapabilities);
+ if (hwcId >= 0) {
+ getHwComposer().getHdrCapabilities(hwcId, &hdrCapabilities);
+ supportedPerFrameMetadata = getHwComposer().getSupportedPerFrameMetadata(hwcId);
+ }
auto nativeWindowSurface = mCreateNativeWindowSurface(producer);
auto nativeWindow = nativeWindowSurface->getNativeWindow();
@@ -2386,8 +2409,7 @@
new DisplayDevice(this, state.type, hwcId, state.isSecure, display, nativeWindow,
dispSurface, std::move(renderSurface), displayWidth, displayHeight,
hasWideColorGamut, hdrCapabilities,
- getHwComposer().getSupportedPerFrameMetadata(hwcId),
- hwcColorModes, initialPowerMode);
+ supportedPerFrameMetadata, hwcColorModes, initialPowerMode);
if (maxFrameBufferAcquiredBuffers >= 3) {
nativeWindowSurface->preallocateBuffers();
@@ -3038,22 +3060,17 @@
}
}
- if (displayDevice->getDisplayType() != DisplayDevice::DISPLAY_PRIMARY) {
- // just to be on the safe side, we don't set the
- // scissor on the main display. It should never be needed
- // anyways (though in theory it could since the API allows it).
- const Rect& bounds(displayDevice->getBounds());
- const Rect& scissor(displayDevice->getScissor());
- if (scissor != bounds) {
- // scissor doesn't match the screen's dimensions, so we
- // need to clear everything outside of it and enable
- // the GL scissor so we don't draw anything where we shouldn't
+ const Rect& bounds(displayDevice->getBounds());
+ const Rect& scissor(displayDevice->getScissor());
+ if (scissor != bounds) {
+ // scissor doesn't match the screen's dimensions, so we
+ // need to clear everything outside of it and enable
+ // the GL scissor so we don't draw anything where we shouldn't
- // enable scissor for this frame
- const uint32_t height = displayDevice->getHeight();
- getBE().mRenderEngine->setScissor(scissor.left, height - scissor.bottom,
- scissor.getWidth(), scissor.getHeight());
- }
+ // enable scissor for this frame
+ const uint32_t height = displayDevice->getHeight();
+ getBE().mRenderEngine->setScissor(scissor.left, height - scissor.bottom,
+ scissor.getWidth(), scissor.getHeight());
}
}
@@ -3628,6 +3645,11 @@
uniqueName, w, h, flags,
handle, &layer);
break;
+ case ISurfaceComposerClient::eFXSurfaceContainer:
+ result = createContainerLayer(client,
+ uniqueName, w, h, flags,
+ handle, &layer);
+ break;
default:
result = BAD_VALUE;
break;
@@ -3719,6 +3741,16 @@
return NO_ERROR;
}
+status_t SurfaceFlinger::createContainerLayer(const sp<Client>& client,
+ const String8& name, uint32_t w, uint32_t h, uint32_t flags,
+ sp<IBinder>* handle, sp<Layer>* outLayer)
+{
+ *outLayer = new ContainerLayer(this, client, name, w, h, flags);
+ *handle = (*outLayer)->getHandle();
+ return NO_ERROR;
+}
+
+
status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle)
{
// called by a client when it wants to remove a Layer
@@ -4821,6 +4853,16 @@
const sp<const DisplayDevice> device(getDisplayDeviceLocked(display));
if (CC_UNLIKELY(device == 0)) return BAD_VALUE;
+ const Rect& dispScissor = device->getScissor();
+ if (!dispScissor.isEmpty()) {
+ sourceCrop.set(dispScissor);
+ // adb shell screencap will default reqWidth and reqHeight to zeros.
+ if (reqWidth == 0 || reqHeight == 0) {
+ reqWidth = uint32_t(device->getViewport().width());
+ reqHeight = uint32_t(device->getViewport().height());
+ }
+ }
+
DisplayRenderArea renderArea(device, sourceCrop, reqHeight, reqWidth, rotation);
auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this,
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 8f724e9..463a551 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -429,6 +429,7 @@
const Rect& sourceCrop, float frameScale, bool childrenOnly);
virtual status_t getDisplayStats(const sp<IBinder>& display,
DisplayStatInfo* stats);
+ virtual status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport);
virtual status_t getDisplayConfigs(const sp<IBinder>& display,
Vector<DisplayInfo>* configs);
virtual int getActiveConfig(const sp<IBinder>& display);
@@ -540,6 +541,10 @@
uint32_t w, uint32_t h, uint32_t flags, sp<IBinder>* outHandle,
sp<Layer>* outLayer);
+ status_t createContainerLayer(const sp<Client>& client, const String8& name,
+ uint32_t w, uint32_t h, uint32_t flags, sp<IBinder>* outHandle,
+ sp<Layer>* outLayer);
+
String8 getUniqueLayerName(const String8& name);
// called in response to the window-manager calling
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/Android.bp b/services/surfaceflinger/TimeStats/timestatsproto/Android.bp
index bef6b7c..b937f41 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/Android.bp
+++ b/services/surfaceflinger/TimeStats/timestatsproto/Android.bp
@@ -17,7 +17,6 @@
},
cppflags: [
- "-std=c++1z",
"-Werror",
"-Wno-c++98-compat-pedantic",
"-Wno-disabled-macro-expansion",
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index b1ff522..aefe704 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -21,15 +21,14 @@
#include <android/frameworks/displayservice/1.0/IDisplayService.h>
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <cutils/sched_policy.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <displayservice/DisplayService.h>
#include <hidl/LegacySupport.h>
+#include <processgroup/sched_policy.h>
#include <configstore/Utils.h>
-#include "GpuService.h"
#include "SurfaceFlinger.h"
using namespace android;
@@ -104,10 +103,6 @@
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);
- // publish GpuService
- sp<GpuService> gpuservice = new GpuService();
- sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false);
-
startDisplayService(); // dependency on SF getting registered above
struct sched_param param = {0};
diff --git a/services/surfaceflinger/surfaceflinger.rc b/services/surfaceflinger/surfaceflinger.rc
index aea602b..5bec502 100644
--- a/services/surfaceflinger/surfaceflinger.rc
+++ b/services/surfaceflinger/surfaceflinger.rc
@@ -2,6 +2,7 @@
class core animation
user system
group graphics drmrpc readproc
+ updatable
onrestart restart zygote
writepid /dev/stune/foreground/tasks
socket pdx/system/vr/display/client stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 5108279..79f27df 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -281,7 +281,7 @@
void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); }
- ScreenCapture(const sp<GraphicBuffer>& outBuffer) : mOutBuffer(outBuffer) {
+ explicit ScreenCapture(const sp<GraphicBuffer>& outBuffer) : mOutBuffer(outBuffer) {
mOutBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&mPixels));
}
diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp
index 973156a..eeb6efe 100644
--- a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp
+++ b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp
@@ -81,7 +81,7 @@
class DelayedEventGenerator {
public:
- DelayedEventGenerator(std::function<void()> onTimerExpired)
+ explicit DelayedEventGenerator(std::function<void()> onTimerExpired)
: mOnTimerExpired(onTimerExpired), mThread([this]() { loop(); }) {}
~DelayedEventGenerator() {
diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerService.h b/services/surfaceflinger/tests/fakehwc/FakeComposerService.h
index c439b7e..a3fb8a6 100644
--- a/services/surfaceflinger/tests/fakehwc/FakeComposerService.h
+++ b/services/surfaceflinger/tests/fakehwc/FakeComposerService.h
@@ -26,7 +26,7 @@
class FakeComposerService : public IComposer {
public:
- FakeComposerService(android::sp<ComposerClient>& client);
+ explicit FakeComposerService(android::sp<ComposerClient>& client);
virtual ~FakeComposerService();
Return<void> getCapabilities(getCapabilities_cb hidl_cb) override;
diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h b/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h
index 1258a97..7d20d3c 100644
--- a/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h
+++ b/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h
@@ -100,10 +100,7 @@
*/
class TransactionScope : public android::SurfaceComposerClient::Transaction {
public:
- TransactionScope(FakeComposerClient& composer) :
- Transaction(),
- mComposer(composer) {
- }
+ explicit TransactionScope(FakeComposerClient& composer) : Transaction(), mComposer(composer) {}
~TransactionScope() {
int frameCount = mComposer.getFrameCount();
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
index d7082f3..06ae314 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
@@ -171,7 +171,7 @@
class Hwc2TestBlendMode : public Hwc2TestProperty<hwc2_blend_mode_t> {
public:
- Hwc2TestBlendMode(Hwc2TestCoverage coverage);
+ explicit Hwc2TestBlendMode(Hwc2TestCoverage coverage);
std::string dump() const override;
@@ -192,8 +192,8 @@
class Hwc2TestColor : public Hwc2TestProperty<hwc_color_t> {
public:
- Hwc2TestColor(Hwc2TestCoverage coverage,
- hwc2_blend_mode_t blendMode = HWC2_BLEND_MODE_NONE);
+ explicit Hwc2TestColor(Hwc2TestCoverage coverage,
+ hwc2_blend_mode_t blendMode = HWC2_BLEND_MODE_NONE);
std::string dump() const override;
@@ -217,7 +217,7 @@
class Hwc2TestComposition : public Hwc2TestProperty<hwc2_composition_t> {
public:
- Hwc2TestComposition(Hwc2TestCoverage coverage);
+ explicit Hwc2TestComposition(Hwc2TestCoverage coverage);
std::string dump() const override;
@@ -232,7 +232,7 @@
class Hwc2TestDataspace : public Hwc2TestProperty<android::ui::Dataspace> {
public:
- Hwc2TestDataspace(Hwc2TestCoverage coverage);
+ explicit Hwc2TestDataspace(Hwc2TestCoverage coverage);
std::string dump() const override;
@@ -248,7 +248,7 @@
class Hwc2TestDisplayDimension : public Hwc2TestProperty<UnsignedArea> {
public:
- Hwc2TestDisplayDimension(Hwc2TestCoverage coverage);
+ explicit Hwc2TestDisplayDimension(Hwc2TestCoverage coverage);
std::string dump() const;
@@ -291,7 +291,7 @@
class Hwc2TestPlaneAlpha : public Hwc2TestProperty<float> {
public:
- Hwc2TestPlaneAlpha(Hwc2TestCoverage coverage);
+ explicit Hwc2TestPlaneAlpha(Hwc2TestCoverage coverage);
std::string dump() const override;
@@ -306,7 +306,7 @@
class Hwc2TestSourceCrop : public Hwc2TestProperty<hwc_frect_t> {
public:
- Hwc2TestSourceCrop(Hwc2TestCoverage coverage, const Area& bufferArea = {0, 0});
+ explicit Hwc2TestSourceCrop(Hwc2TestCoverage coverage, const Area& bufferArea = {0, 0});
std::string dump() const override;
@@ -330,7 +330,7 @@
class Hwc2TestSurfaceDamage : public Hwc2TestProperty<hwc_region_t> {
public:
- Hwc2TestSurfaceDamage(Hwc2TestCoverage coverage);
+ explicit Hwc2TestSurfaceDamage(Hwc2TestCoverage coverage);
~Hwc2TestSurfaceDamage();
std::string dump() const override;
@@ -356,7 +356,7 @@
class Hwc2TestTransform : public Hwc2TestProperty<hwc_transform_t> {
public:
- Hwc2TestTransform(Hwc2TestCoverage coverage);
+ explicit Hwc2TestTransform(Hwc2TestCoverage coverage);
std::string dump() const override;
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h
index 10c8ef0..5a74a6c 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h
@@ -29,7 +29,7 @@
class Hwc2TestVirtualDisplay {
public:
- Hwc2TestVirtualDisplay(Hwc2TestCoverage coverage);
+ explicit Hwc2TestVirtualDisplay(Hwc2TestCoverage coverage);
std::string dump() const;
diff --git a/services/utils/Android.bp b/services/utils/Android.bp
index 6132956..f3d2bc9 100644
--- a/services/utils/Android.bp
+++ b/services/utils/Android.bp
@@ -18,6 +18,8 @@
cc_library_static {
name: "libserviceutils",
+ vendor_available: true,
+
cflags: [
"-Wall",
"-Werror",
@@ -27,8 +29,13 @@
"PriorityDumper.cpp",
],
- clang: true,
+ header_libs: [
+ "libutils_headers",
+ ],
+
+ export_header_lib_headers: [
+ "libutils_headers",
+ ],
+
export_include_dirs: ["include"],
}
-
-subdirs = ["tests"]
diff --git a/services/utils/tests/PriorityDumper_test.cpp b/services/utils/tests/PriorityDumper_test.cpp
index 90cc6de..2320a90 100644
--- a/services/utils/tests/PriorityDumper_test.cpp
+++ b/services/utils/tests/PriorityDumper_test.cpp
@@ -54,7 +54,7 @@
};
static void addAll(Vector<String16>& av, const std::vector<std::string>& v) {
- for (auto element : v) {
+ for (const auto& element : v) {
av.add(String16(element.c_str()));
}
}
diff --git a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.h b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.h
index b478bb5..a82df7f 100644
--- a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.h
+++ b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.h
@@ -10,7 +10,7 @@
class ParcelableComposerFrame : public Parcelable {
public:
ParcelableComposerFrame();
- ParcelableComposerFrame(const ComposerView::Frame& frame);
+ explicit ParcelableComposerFrame(const ComposerView::Frame& frame);
~ParcelableComposerFrame() override;
ComposerView::Frame frame() const { return frame_; }
diff --git a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.h b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.h
index 4cf48f1..6d2ac09 100644
--- a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.h
+++ b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.h
@@ -12,7 +12,7 @@
class ParcelableComposerLayer : public Parcelable {
public:
ParcelableComposerLayer();
- ParcelableComposerLayer(const ComposerView::ComposerLayer& layer);
+ explicit ParcelableComposerLayer(const ComposerView::ComposerLayer& layer);
~ParcelableComposerLayer() override;
ComposerView::ComposerLayer layer() const { return layer_; }
diff --git a/services/vr/hardware_composer/aidl/android/dvr/parcelable_unique_fd.h b/services/vr/hardware_composer/aidl/android/dvr/parcelable_unique_fd.h
index daf9e6d..c4216f6 100644
--- a/services/vr/hardware_composer/aidl/android/dvr/parcelable_unique_fd.h
+++ b/services/vr/hardware_composer/aidl/android/dvr/parcelable_unique_fd.h
@@ -13,7 +13,7 @@
class ParcelableUniqueFd : public Parcelable {
public:
ParcelableUniqueFd();
- ParcelableUniqueFd(const base::unique_fd& fence);
+ explicit ParcelableUniqueFd(const base::unique_fd& fence);
~ParcelableUniqueFd() override;
void set_fence(const base::unique_fd& fence) {
diff --git a/services/vr/hardware_composer/impl/vr_composer_client.cpp b/services/vr/hardware_composer/impl/vr_composer_client.cpp
index 4b90031..d775711 100644
--- a/services/vr/hardware_composer/impl/vr_composer_client.cpp
+++ b/services/vr/hardware_composer/impl/vr_composer_client.cpp
@@ -19,6 +19,8 @@
#include <hardware/gralloc1.h>
#include <log/log.h>
+#include <memory>
+
#include "impl/vr_hwc.h"
#include "impl/vr_composer_client.h"
@@ -39,7 +41,7 @@
std::unique_ptr<ComposerCommandEngine>
VrComposerClient::createCommandEngine() {
- return std::unique_ptr<VrCommandEngine>(new VrCommandEngine(*this));
+ return std::make_unique<VrCommandEngine>(*this);
}
VrComposerClient::VrCommandEngine::VrCommandEngine(VrComposerClient& client)
diff --git a/services/vr/hardware_composer/impl/vr_composer_client.h b/services/vr/hardware_composer/impl/vr_composer_client.h
index 76b1c4f..2ad95fc 100644
--- a/services/vr/hardware_composer/impl/vr_composer_client.h
+++ b/services/vr/hardware_composer/impl/vr_composer_client.h
@@ -35,13 +35,13 @@
class VrComposerClient : public ComposerClient {
public:
- VrComposerClient(android::dvr::VrHwc& hal);
+ explicit VrComposerClient(android::dvr::VrHwc& hal);
virtual ~VrComposerClient();
private:
class VrCommandEngine : public ComposerCommandEngine {
public:
- VrCommandEngine(VrComposerClient& client);
+ explicit VrCommandEngine(VrComposerClient& client);
~VrCommandEngine() override;
bool executeCommand(IComposerClient::Command command,
diff --git a/services/vr/hardware_composer/impl/vr_hwc.h b/services/vr/hardware_composer/impl/vr_hwc.h
index 85e587a..74c1699 100644
--- a/services/vr/hardware_composer/impl/vr_hwc.h
+++ b/services/vr/hardware_composer/impl/vr_hwc.h
@@ -112,9 +112,7 @@
using Composition =
hardware::graphics::composer::V2_1::IComposerClient::Composition;
- HwcLayer(Layer new_id) {
- info.id = new_id;
- }
+ explicit HwcLayer(Layer new_id) { info.id = new_id; }
void dumpDebugInfo(std::string* result) const;
diff --git a/services/vr/performanced/Android.bp b/services/vr/performanced/Android.bp
new file mode 100644
index 0000000..20301f6
--- /dev/null
+++ b/services/vr/performanced/Android.bp
@@ -0,0 +1,53 @@
+// Copyright (C) 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.
+
+cc_defaults {
+ name: "performanced_defaults",
+ static_libs: [
+ "libperformance",
+ "libvr_manager",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libbase",
+ "libcutils",
+ "liblog",
+ "libutils",
+ "libpdx_default_transport",
+ ],
+}
+
+cc_binary {
+ name: "performanced",
+ defaults: ["performanced_defaults"],
+ srcs: [
+ "cpu_set.cpp",
+ "main.cpp",
+ "performance_service.cpp",
+ "task.cpp",
+ ],
+ cflags: [
+ "-DLOG_TAG=\"performanced\"",
+ "-DTRACE=0",
+ "-Wall",
+ "-Werror",
+ ],
+ init_rc: ["performanced.rc"],
+}
+
+cc_test {
+ name: "performance_service_tests",
+ defaults: ["performanced_defaults"],
+ srcs: ["performance_service_tests.cpp"],
+}
diff --git a/services/vr/performanced/Android.mk b/services/vr/performanced/Android.mk
deleted file mode 100644
index a548ef0..0000000
--- a/services/vr/performanced/Android.mk
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright (C) 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.
-
-LOCAL_PATH := $(call my-dir)
-
-sourceFiles := \
- cpu_set.cpp \
- main.cpp \
- performance_service.cpp \
- task.cpp
-
-staticLibraries := \
- libperformance \
- libvr_manager
-
-sharedLibraries := \
- libbinder \
- libbase \
- libcutils \
- liblog \
- libutils \
- libpdx_default_transport \
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(sourceFiles)
-LOCAL_CFLAGS := -DLOG_TAG=\"performanced\"
-LOCAL_CFLAGS += -DTRACE=0
-LOCAL_CFLAGS += -Wall -Werror
-LOCAL_STATIC_LIBRARIES := $(staticLibraries)
-LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
-LOCAL_MODULE := performanced
-LOCAL_INIT_RC := performanced.rc
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := performance_service_tests.cpp
-LOCAL_STATIC_LIBRARIES := $(staticLibraries) libgtest_main
-LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
-LOCAL_MODULE := performance_service_tests
-LOCAL_MODULE_TAGS := optional
-include $(BUILD_NATIVE_TEST)
diff --git a/services/vr/performanced/performance_service_tests.cpp b/services/vr/performanced/performance_service_tests.cpp
index 4065785..a24c889 100644
--- a/services/vr/performanced/performance_service_tests.cpp
+++ b/services/vr/performanced/performance_service_tests.cpp
@@ -12,16 +12,16 @@
#include <thread>
#include <utility>
+#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <dvr/performance_client_api.h>
#include <gtest/gtest.h>
#include <private/android_filesystem_config.h>
#include "stdio_filebuf.h"
-#include "string_trim.h"
#include "unique_file.h"
-using android::dvr::Trim;
+using android::base::Trim;
using android::dvr::UniqueFile;
using android::dvr::stdio_filebuf;
diff --git a/services/vr/performanced/string_trim.h b/services/vr/performanced/string_trim.h
deleted file mode 100644
index 7094e9f..0000000
--- a/services/vr/performanced/string_trim.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef ANDROID_DVR_PERFORMANCED_STRING_TRIM_H_
-#define ANDROID_DVR_PERFORMANCED_STRING_TRIM_H_
-
-#include <functional>
-#include <locale>
-#include <string>
-
-namespace android {
-namespace dvr {
-
-// Trims whitespace from the left side of |subject| and returns the result as a
-// new string.
-inline std::string LeftTrim(std::string subject) {
- subject.erase(subject.begin(),
- std::find_if(subject.begin(), subject.end(),
- std::not1(std::ptr_fun<int, int>(std::isspace))));
- return subject;
-}
-
-// Trims whitespace from the right side of |subject| and returns the result as a
-// new string.
-inline std::string RightTrim(std::string subject) {
- subject.erase(std::find_if(subject.rbegin(), subject.rend(),
- std::not1(std::ptr_fun<int, int>(std::isspace)))
- .base(),
- subject.end());
- return subject;
-}
-
-// Trims whitespace from the both sides of |subject| and returns the result as a
-// new string.
-inline std::string Trim(std::string subject) {
- subject.erase(subject.begin(),
- std::find_if(subject.begin(), subject.end(),
- std::not1(std::ptr_fun<int, int>(std::isspace))));
- subject.erase(std::find_if(subject.rbegin(), subject.rend(),
- std::not1(std::ptr_fun<int, int>(std::isspace)))
- .base(),
- subject.end());
- return subject;
-}
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_PERFORMANCED_STRING_TRIM_H_
diff --git a/services/vr/performanced/task.cpp b/services/vr/performanced/task.cpp
index bda1682..2fc96bf 100644
--- a/services/vr/performanced/task.cpp
+++ b/services/vr/performanced/task.cpp
@@ -10,10 +10,10 @@
#include <memory>
#include <sstream>
+#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include "stdio_filebuf.h"
-#include "string_trim.h"
namespace {
@@ -102,7 +102,7 @@
// The status file has lines with the format <field>:<value>. Extract the
// value after the colon.
- return Trim(line.substr(offset + field.size() + 1));
+ return android::base::Trim(line.substr(offset + field.size() + 1));
}
}
@@ -123,7 +123,7 @@
}
std::string key = line.substr(0, offset);
- std::string value = Trim(line.substr(offset + 1));
+ std::string value = android::base::Trim(line.substr(offset + 1));
ALOGD_IF(TRACE, "Task::ReadStatusFields: key=\"%s\" value=\"%s\"",
key.c_str(), value.c_str());
@@ -156,7 +156,7 @@
std::string line = "";
std::getline(file_stream, line);
- return Trim(line);
+ return android::base::Trim(line);
} else {
return "";
}
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadService.h b/services/vr/virtual_touchpad/VirtualTouchpadService.h
index 2c46209..2c88aec 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadService.h
+++ b/services/vr/virtual_touchpad/VirtualTouchpadService.h
@@ -13,7 +13,7 @@
//
class VirtualTouchpadService : public BnVirtualTouchpadService {
public:
- VirtualTouchpadService(std::unique_ptr<VirtualTouchpad> touchpad)
+ explicit VirtualTouchpadService(std::unique_ptr<VirtualTouchpad> touchpad)
: touchpad_(std::move(touchpad)), client_pid_(0) {}
~VirtualTouchpadService() override;
diff --git a/vulkan/OWNERS b/vulkan/OWNERS
new file mode 100644
index 0000000..f4c7af9
--- /dev/null
+++ b/vulkan/OWNERS
@@ -0,0 +1 @@
+include ../opengl/OWNERS
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index e5b9b47..7604c95 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 90
+define VERSION_PATCH 96
// API limits
define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256
@@ -85,9 +85,7 @@
@extension("VK_KHR_wayland_surface") define VK_KHR_WAYLAND_SURFACE_SPEC_VERSION 6
@extension("VK_KHR_wayland_surface") define VK_KHR_WAYLAND_SURFACE_NAME "VK_KHR_wayland_surface"
-// 8
-@extension("VK_KHR_mir_surface") define VK_KHR_MIR_SURFACE_SPEC_VERSION 4
-@extension("VK_KHR_mir_surface") define VK_KHR_MIR_SURFACE_NAME "VK_KHR_mir_surface"
+// 8 - VK_KHR_mir_surface removed
// 9
@extension("VK_KHR_android_surface") define VK_KHR_ANDROID_SURFACE_SPEC_VERSION 6
@@ -289,6 +287,10 @@
@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"
+// 83
+@extension("VK_KHR_shader_float16_int8") define VK_KHR_SHADER_FLOAT16_INT8_SPEC_VERSION 1
+@extension("VK_KHR_shader_float16_int8") define VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME "VK_KHR_shader_float16_int8"
+
// 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"
@@ -526,8 +528,8 @@
@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"
+@extension("VK_NV_ray_tracing") define VK_NV_RAY_TRACING_SPEC_VERSION 3
+@extension("VK_NV_ray_tracing") define VK_NV_RAY_TRACING_EXTENSION_NAME "VK_NV_ray_tracing"
// 167
@extension("VK_NV_representative_fragment_test") define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_SPEC_VERSION 1
@@ -565,6 +567,10 @@
@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"
+// 190
+@extension("VK_AMD_memory_overallocation_behavior") define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_SPEC_VERSION 1
+@extension("VK_AMD_memory_overallocation_behavior") define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_EXTENSION_NAME "VK_AMD_memory_overallocation_behavior"
+
// 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"
@@ -573,10 +579,18 @@
@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"
+// 198
+@extension("VK_KHR_shader_float_controls") define VK_KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION 1
+@extension("VK_KHR_shader_float_controls") define VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME "VK_KHR_shader_float_controls"
+
// 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"
+// 201
+@extension("VK_KHR_swapchain_mutable_format") define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_SPEC_VERSION 1
+@extension("VK_KHR_swapchain_mutable_format") define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME "VK_KHR_swapchain_mutable_format"
+
// 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"
@@ -606,21 +620,33 @@
@extension("VK_KHR_vulkan_memory_model") define VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME "VK_KHR_vulkan_memory_model"
// 213
-@extension("VK_EXT_pci_bus_info") define VK_EXT_PCI_BUS_INFO_SPEC_VERSION 1
+@extension("VK_EXT_pci_bus_info") define VK_EXT_PCI_BUS_INFO_SPEC_VERSION 2
@extension("VK_EXT_pci_bus_info") define VK_EXT_PCI_BUS_INFO_EXENSION_NAME "VK_EXT_pci_bus_info"
// 215
@extension("VK_FUCHSIA_imagepipe_surface") define VK_FUCHSIA_IMAGEPIPE_SURFACE_SPEC_VERSION 1
@extension("VK_FUCHSIA_imagepipe_surface") define VK_FUCHSIA_IMAGEPIPE_SURFACE_EXTENSION_NAME "VK_FUCHSIA_imagepipe_surface"
+// 219
+@extension("VK_EXT_fragment_density_map") define VK_EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION 1
+@extension("VK_EXT_fragment_density_map") define VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME "VK_EXT_fragment_density_map"
+
+// 222
+@extension("VK_EXT_scalar_block_layout") define VK_EXT_SCALAR_BLOCK_LAYOUT_SPEC_VERSION 1
+@extension("VK_EXT_scalar_block_layout") define VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME "VK_EXT_scalar_block_layout"
+
// 224
-@extension("VK_GOOGLE_hlsl_functionality1") define VK_GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION 0
+@extension("VK_GOOGLE_hlsl_functionality1") define VK_GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION 1
@extension("VK_GOOGLE_hlsl_functionality1") define VK_GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME "VK_GOOGLE_hlsl_functionality1"
// 225
-@extension("VK_GOOGLE_decorate_string") define VK_GOOGLE_DECORATE_STRING_SPEC_VERSION 0
+@extension("VK_GOOGLE_decorate_string") define VK_GOOGLE_DECORATE_STRING_SPEC_VERSION 1
@extension("VK_GOOGLE_decorate_string") define VK_GOOGLE_DECORATE_STRING_EXTENSION_NAME "VK_GOOGLE_decorate_string"
+// 247
+@extension("VK_EXT_separate_stencil_usage") define VK_EXT_SEPARATE_STENCIL_USAGE_SPEC_VERSION 1
+@extension("VK_EXT_separate_stencil_usage") define VK_EXT_SEPARATE_STENCIL_USAGE_EXTENSION_NAME "VK_EXT_separate_stencil_usage"
+
/////////////
// Types //
/////////////
@@ -693,7 +719,7 @@
@extension("VK_EXT_validation_cache") @nonDispatchHandle type u64 VkValidationCacheEXT
// 166
-@extension("VK_NVX_raytracing") @nonDispatchHandle type u64 VkAccelerationStructureNVX
+@extension("VK_NV_ray_tracing") @nonDispatchHandle type u64 VkAccelerationStructureNV
/////////////
// Enums //
@@ -726,6 +752,9 @@
//@extension("VK_NV_shading_rate_image") // 165
VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV = 1000164003,
+
+ //@extension("VK_EXT_fragment_density_map") // 219
+ VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT = 1000218000,
}
enum VkAttachmentLoadOp {
@@ -794,8 +823,8 @@
//@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,
+ //@extension("VK_NV_ray_tracing") // 166
+ VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000,
}
enum VkQueryType {
@@ -806,8 +835,8 @@
//@extension("VK_EXT_transform_feedback") // 29
VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT = 1000028004,
- //@extension("VK_NVX_raytracing") // 166
- VK_QUERY_TYPE_COMPACTED_SIZE_NVX = 1000165000,
+ //@extension("VK_NV_ray_tracing") // 166
+ VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV = 1000165000,
}
enum VkBorderColor {
@@ -823,8 +852,8 @@
VK_PIPELINE_BIND_POINT_GRAPHICS = 0x00000000,
VK_PIPELINE_BIND_POINT_COMPUTE = 0x00000001,
- //@extension("VK_NVX_raytracing") // 166
- VK_PIPELINE_BIND_POINT_RAYTRACING_NVX = 1000165000,
+ //@extension("VK_NV_ray_tracing") // 166
+ VK_PIPELINE_BIND_POINT_RAY_TRACING_NV = 1000165000,
}
enum VkPrimitiveTopology {
@@ -849,6 +878,9 @@
enum VkIndexType {
VK_INDEX_TYPE_UINT16 = 0x00000000,
VK_INDEX_TYPE_UINT32 = 0x00000001,
+
+ //@extension("VK_NV_ray_tracing") // 166
+ VK_INDEX_TYPE_NONE_NV = 1000165000,
}
enum VkFilter {
@@ -1447,9 +1479,6 @@
//@extension("VK_KHR_wayland_surface") // 7
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
- //@extension("VK_KHR_mir_surface") // 8
- VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR = 1000007000,
-
//@extension("VK_KHR_android_surface") // 9
VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR = 1000008000,
@@ -1594,6 +1623,9 @@
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT = 1000081001,
VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT = 1000081002,
+ //@extension("VK_KHR_shader_float16_int8") // 83
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR = 1000082000,
+
//@extension("VK_KHR_descriptor_update_template") // 86
VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = 1000085000,
@@ -1786,18 +1818,18 @@
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_ray_tracing") // 166
+ VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV = 1000165000,
+ VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV = 1000165001,
+ VK_STRUCTURE_TYPE_GEOMETRY_NV = 1000165003,
+ VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV = 1000165004,
+ VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV = 1000165005,
+ VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV = 1000165006,
+ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV = 1000165007,
+ VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV = 1000165008,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV = 1000165009,
+ VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV = 1000165011,
+ VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV = 1000165012,
//@extension("VK_NV_representative_fragment_test") // 167
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV = 1000166000,
@@ -1827,9 +1859,15 @@
//@extension("VK_KHR_driver_properties") // 197
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR = 1000196000,
+ //@extension("VK_KHR_shader_float_controls") // 198
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR = 1000197000,
+
//@extension("VK_AMD_shader_core_properties") // 186
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD = 1000185000,
+ //@extension("VK_AMD_memory_overallocation_behavior") // 190
+ VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD = 1000189000,
+
//@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,
@@ -1843,10 +1881,21 @@
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = 1000211000,
//@extension("VK_EXT_pci_bus_info") // 213
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT = 1000212000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT = 1000212000,
//@extension("VK_FUCHSIA_imagepipe_surface") // 215
VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA = 1000214000,
+
+ //@extension("VK_EXT_fragment_density_map") // 219
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT = 1000218000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT = 1000218001,
+ VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT = 1000218002,
+
+ //@extension("VK_EXT_scalar_block_layout")
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT = 1000221000,
+
+ //@extension("VK_EXT_separate_stencil_usage") // 247
+ VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO_EXT = 1000246000,
}
enum VkSubpassContents {
@@ -2011,8 +2060,8 @@
//@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,
+ //@extension("VK_NV_ray_tracing") // 166
+ VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000,
}
@@ -2135,8 +2184,8 @@
//@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_NV_ray_tracing") // 166
+ VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT = 1000165000,
}
@extension("VK_AMD_rasterization_order") // 19
@@ -2311,22 +2360,36 @@
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_NV_ray_tracing") // 166
+enum VkRayTracingShaderGroupTypeNV {
+ VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV = 0,
+ VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV = 1,
+ VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV = 2,
}
-@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_NV_ray_tracing") // 166
+enum VkGeometryTypeNV {
+ VK_GEOMETRY_TYPE_TRIANGLES_NV = 0,
+ VK_GEOMETRY_TYPE_AABBS_NV = 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_NV_ray_tracing") // 166
+enum VkAccelerationStructureTypeNV {
+ VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV = 0,
+ VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV = 1,
+}
+
+@extension("VK_NV_ray_tracing") // 166
+enum VkCopyAccelerationStructureModeNV {
+ VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV = 0,
+ VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV = 1,
+}
+
+@extension("VK_NV_ray_tracing") // 166
+enum VkAccelerationStructureMemoryRequirementsTypeNV {
+ VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV = 0,
+ VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV = 1,
+ VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV = 2,
}
@extension("VK_EXT_global_priority") // 175
@@ -2345,6 +2408,13 @@
VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT = 3,
}
+@extension("VK_AMD_memory_overallocation_behavior") // 190
+enum VkMemoryOverallocationBehaviorAMD {
+ VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD = 0,
+ VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD = 1,
+ VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD = 2,
+}
+
@extension("VK_KHR_driver_properties") // 197
enum VkDriverIdKHR {
VK_DRIVER_ID_AMD_PROPRIETARY_KHR = 1,
@@ -2356,6 +2426,7 @@
VK_DRIVER_ID_IMAGINATION_PROPRIETARY_KHR = 7,
VK_DRIVER_ID_QUALCOMM_PROPRIETARY_KHR = 8,
VK_DRIVER_ID_ARM_PROPRIETARY_KHR = 9,
+ VK_DRIVER_ID_GOOGLE_PASTEL_KHR = 10,
}
/////////////////
@@ -2433,9 +2504,12 @@
//@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,
+ //@extension("VK_NV_ray_tracing") // 166
+ VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV = 0x00200000,
+ VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV = 0x00400000,
+
+ //@extension("VK_EXT_fragment_density_map") // 219
+ VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000,
//@extension("VK_EXT_transform_feedback") // 29
VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0x02000000,
@@ -2459,8 +2533,8 @@
//@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,
+ //@extension("VK_NV_ray_tracing") // 166
+ VK_BUFFER_USAGE_RAY_TRACING_BIT_NV = 0x00000400,
//@extension("VK_EXT_transform_feedback") // 29
VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT = 0x00000800,
@@ -2491,13 +2565,13 @@
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_ray_tracing") // 166
+ VK_SHADER_STAGE_RAYGEN_BIT_NV = 0x00000100,
+ VK_SHADER_STAGE_ANY_HIT_BIT_NV = 0x00000200,
+ VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV = 0x00000400,
+ VK_SHADER_STAGE_MISS_BIT_NV = 0x00000800,
+ VK_SHADER_STAGE_INTERSECTION_BIT_NV = 0x00001000,
+ VK_SHADER_STAGE_CALLABLE_BIT_NV = 0x00002000,
//@extension("VK_NV_mesh_shader") // 203
VK_SHADER_STAGE_TASK_BIT_NV = 0x00000040,
@@ -2532,6 +2606,9 @@
//@extension("VK_NV_shading_rate_image") // 165
VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV = 0x00000100,
+
+ //@extension("VK_EXT_fragment_density_map") // 219
+ VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x00000200,
}
/// Image creation flags
@@ -2573,12 +2650,17 @@
//@extension("VK_NV_corner_sampled_image") // 51
VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV = 0x00002000,
+
+ //@extension("VK_EXT_fragment_density_map") // 219
+ VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT = 0x00004000,
}
/// Image view creation flags
type VkFlags VkImageViewCreateFlags
-//bitfield VkImageViewCreateFlagBits {
-//}
+bitfield VkImageViewCreateFlagBits {
+ //@extension("VK_EXT_fragment_density_map") // 219
+ VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DYNAMIC_BIT_EXT = 0x00000001,
+}
/// Pipeline creation flags
type VkFlags VkPipelineCreateFlags
@@ -2595,8 +2677,8 @@
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,
+ //@extension("VK_NV_ray_tracing") // 166
+ VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV = 0x00000020,
}
/// Color component flags
@@ -2788,18 +2870,24 @@
//@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,
+ //@extension("VK_NV_ray_tracing") // 166
+ VK_PIPELINE_STAGE_RAY_TRACING_BIT_NV = 0x00200000,
+
+ //@extension("VK_NV_shading_rate_image") // 165
+ VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV = 0x00400000,
+
+ //@extension("VK_EXT_fragment_density_map") // 219
+ VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000,
+
//@extension("VK_EXT_transform_feedback") // 29
VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000,
+
+ //@extension("VK_NV_ray_tracing") // 166
+ VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV = 0x02000000,
}
/// Render pass attachment description flags
@@ -2954,8 +3042,11 @@
/// Sampler creation flags
type VkFlags VkSamplerCreateFlags
-//bitfield VkSamplerCreateFlagBits {
-//}
+bitfield VkSamplerCreateFlagBits {
+ //@extension("VK_EXT_fragment_density_map") // 219
+ VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT = 0x00000001,
+ VK_SAMPLER_CREATE_SUBSAMPLED_COARSE_RECONSTRUCTION_BIT_EXT = 0x00000002,
+}
/// Render pass creation flags
type VkFlags VkRenderPassCreateFlags
@@ -3140,6 +3231,9 @@
//@vulkan1_1
VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = 0x00000001,
VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR = 0x00000002,
+
+ //@extension("VK_KHR_swapchain_mutable_format") // 201
+ VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR = 0x00000004,
}
@vulkan1_1
@@ -3194,12 +3288,6 @@
//bitfield VkWaylandSurfaceCreateFlagBitsKHR {
//}
-@extension("VK_KHR_mir_surface") // 8
-type VkFlags VkMirSurfaceCreateFlagsKHR
-//@extension("VK_KHR_mir_surface") // 8
-//bitfield VkMirSurfaceCreateFlagBitsKHR {
-//}
-
@extension("VK_KHR_android_surface") // 9
type VkFlags VkAndroidSurfaceCreateFlagsKHR
//@extension("VK_KHR_android_surface") // 9
@@ -3484,33 +3572,33 @@
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_NV_ray_tracing") // 166
+type VkFlags VkGeometryFlagsNV
+@extension("VK_NV_ray_tracing") // 166
+bitfield VkGeometryFlagBitsNV {
+ VK_GEOMETRY_OPAQUE_BIT_NV = 0x00000001,
+ VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV = 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_NV_ray_tracing") // 166
+type VkFlags VkGeometryInstanceFlagsNV
+@extension("VK_NV_ray_tracing") // 166
+bitfield VkGeometryInstanceFlagBitsNV {
+ VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV = 0x00000001,
+ VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV = 0x00000002,
+ VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV = 0x00000004,
+ VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV = 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,
+@extension("VK_NV_ray_tracing") // 166
+type VkFlags VkBuildAccelerationStructureFlagsNV
+@extension("VK_NV_ray_tracing") // 166
+bitfield VkBuildAccelerationStructureFlagBitsNV {
+ VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV = 0x00000001,
+ VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV = 0x00000002,
+ VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV = 0x00000004,
+ VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV = 0x00000008,
+ VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV = 0x00000010,
}
@extension("VK_FUCHSIA_imagepipe_surface") // 215
@@ -4989,7 +5077,7 @@
class VkDescriptorUpdateTemplateCreateInfo {
VkStructureType sType
- void* pNext
+ const void* pNext
VkDescriptorUpdateTemplateCreateFlags flags
u32 descriptorUpdateEntryCount
const VkDescriptorUpdateTemplateEntry* pDescriptorUpdateEntries
@@ -5330,15 +5418,6 @@
platform.wl_surface* surface
}
-@extension("VK_KHR_mir_surface") // 8
-class VkMirSurfaceCreateInfoKHR {
- VkStructureType sType
- const void* pNext
- VkMirSurfaceCreateFlagsKHR flags
- platform.MirConnection* connection
- platform.MirSurface* mirSurface
-}
-
@extension("VK_KHR_android_surface") // 9
class VkAndroidSurfaceCreateInfoKHR {
VkStructureType sType
@@ -6027,6 +6106,14 @@
VkBool32 conditionalRenderingEnable
}
+@extension("VK_KHR_shader_float16_int8") // 83
+class VkPhysicalDeviceFloat16Int8FeaturesKHR {
+ VkStructureType sType
+ void* pNext
+ VkBool32 shaderFloat16
+ VkBool32 shaderInt8
+}
+
@extension("VK_KHR_16bit_storage") // 84
class VkPhysicalDevice16BitStorageFeaturesKHR {
VkStructureType sType
@@ -6711,11 +6798,11 @@
s32 messageIdNumber
const char* pMessage
u32 queueLabelCount
- VkDebugUtilsLabelEXT* pQueueLabels
+ const VkDebugUtilsLabelEXT* pQueueLabels
u32 cmdBufLabelCount
- VkDebugUtilsLabelEXT* pCmdBufLabels
+ const VkDebugUtilsLabelEXT* pCmdBufLabels
u32 objectCount
- VkDebugUtilsObjectNameInfoEXT* pObjects
+ const VkDebugUtilsObjectNameInfoEXT* pObjects
}
@extension("VK_EXT_debug_utils") // 129
@@ -7249,22 +7336,34 @@
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_NV_ray_tracing") // 166
+class VkRayTracingShaderGroupCreateInfoNV {
+ VkStructureType sType
+ const void* pNext
+ VkRayTracingShaderGroupTypeNV type
+ u32 generalShader
+ u32 closestHitShader
+ u32 anyHitShader
+ u32 intersectionShader
}
-@extension("VK_NVX_raytracing") // 166
-class VkGeometryTrianglesNVX {
+@extension("VK_NV_ray_tracing") // 166
+class VkRayTracingPipelineCreateInfoNV {
+ VkStructureType sType
+ const void* pNext
+ VkPipelineCreateFlags flags
+ u32 stageCount
+ const VkPipelineShaderStageCreateInfo* pStages
+ u32 groupCount
+ const VkRayTracingShaderGroupCreateInfoNV* pGroups
+ u32 maxRecursionDepth
+ VkPipelineLayout layout
+ VkPipeline basePipelineHandle
+ s32 basePipelineIndex
+}
+
+@extension("VK_NV_ray_tracing") // 166
+class VkGeometryTrianglesNV {
VkStructureType sType
const void* pNext
VkBuffer vertexData
@@ -7280,8 +7379,8 @@
VkDeviceSize transformOffset
}
-@extension("VK_NVX_raytracing") // 166
-class VkGeometryAABBNVX {
+@extension("VK_NV_ray_tracing") // 166
+class VkGeometryAABBNV {
VkStructureType sType
const void* pNext
VkBuffer aabbData
@@ -7290,66 +7389,79 @@
VkDeviceSize offset
}
-@extension("VK_NVX_raytracing") // 166
-class VkGeometryDataNVX {
- VkGeometryTrianglesNVX triangles
- VkGeometryAABBNVX aabbs
+@extension("VK_NV_ray_tracing") // 166
+class VkGeometryDataNV {
+ VkGeometryTrianglesNV triangles
+ VkGeometryAABBNV aabbs
}
-@extension("VK_NVX_raytracing") // 166
-class VkGeometryNVX {
+@extension("VK_NV_ray_tracing") // 166
+class VkGeometryNV {
VkStructureType sType
const void* pNext
- VkGeometryTypeNVX geometryType
- VkGeometryDataNVX geometry
- VkGeometryFlagsNVX flags
+ VkGeometryTypeNV geometryType
+ VkGeometryDataNV geometry
+ VkGeometryFlagsNV flags
}
-@extension("VK_NVX_raytracing") // 166
-class VkAccelerationStructureCreateInfoNVX {
+@extension("VK_NV_ray_tracing") // 166
+class VkAccelerationStructureInfoNV {
VkStructureType sType
const void* pNext
- VkAccelerationStructureTypeNVX type
- VkBuildAccelerationStructureFlagsNVX flags
- VkDeviceSize compactedSize
+ VkAccelerationStructureTypeNV type
+ VkBuildAccelerationStructureFlagsNV flags
u32 instanceCount
u32 geometryCount
- const VkGeometryNVX* pGeometries
+ const VkGeometryNV* pGeometries
}
-@extension("VK_NVX_raytracing") // 166
-class VkBindAccelerationStructureMemoryInfoNVX {
+@extension("VK_NV_ray_tracing") // 166
+class VkAccelerationStructureCreateInfoNV {
VkStructureType sType
const void* pNext
- VkAccelerationStructureNVX accelerationStructure
+ VkDeviceSize compactedSize
+ VkAccelerationStructureInfoNV info
+}
+
+@extension("VK_NV_ray_tracing") // 166
+class VkBindAccelerationStructureMemoryInfoNV {
+ VkStructureType sType
+ const void* pNext
+ VkAccelerationStructureNV accelerationStructure
VkDeviceMemory memory
VkDeviceSize memoryOffset
u32 deviceIndexCount
const u32* pDeviceIndices
}
-@extension("VK_NVX_raytracing") // 166
-class VkDescriptorAccelerationStructureInfoNVX {
+@extension("VK_NV_ray_tracing") // 166
+class VkDescriptorAccelerationStructureInfoNV {
VkStructureType sType
const void* pNext
u32 accelerationStructureCount
- const VkAccelerationStructureNVX* pAccelerationStructures
+ const VkAccelerationStructureNV* pAccelerationStructures
}
-@extension("VK_NVX_raytracing") // 166
-class VkAccelerationStructureMemoryRequirementsInfoNVX {
+@extension("VK_NV_ray_tracing") // 166
+class VkAccelerationStructureMemoryRequirementsInfoNV {
VkStructureType sType
const void* pNext
- VkAccelerationStructureNVX accelerationStructure
+ VkAccelerationStructureMemoryRequirementsTypeNV type
+ VkAccelerationStructureNV accelerationStructure
}
-@extension("VK_NVX_raytracing") // 166
-class VkPhysicalDeviceRaytracingPropertiesNVX {
+@extension("VK_NV_ray_tracing") // 166
+class VkPhysicalDeviceRaytracingPropertiesNV {
VkStructureType sType
void* pNext
- u32 shaderHeaderSize
+ u32 shaderGroupHandleSize
u32 maxRecursionDepth
- u32 maxGeometryCount
+ u32 maxShaderGroupStride
+ u32 shaderGroupBaseAlignment
+ u64 maxGeometryCount
+ u64 maxInstanceCount
+ u64 maxTriangleCount
+ u32 maxDescriptorSetAccelerationStructures
}
@extension("VK_NV_representative_fragment_test") // 167
@@ -7454,6 +7566,13 @@
u32 vgprAllocationGranularity
}
+@extension("VK_AMD_memory_overallocation_behavior") // 190
+class VkDeviceMemoryOverallocationCreateInfoAMD {
+ VkStructureType sType
+ const void* pNext
+ VkMemoryOverallocationBehaviorAMD overallocationBehavior
+}
+
@extension("VK_EXT_vertex_attribute_divisor") // 191
class VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT {
VkStructureType sType
@@ -7501,6 +7620,29 @@
VkConformanceVersionKHR conformanceVersion
}
+@extension("VK_KHR_shader_float_controls") // 198
+class VkPhysicalDeviceFloatControlsPropertiesKHR {
+ VkStructureType sType
+ void* pNext
+ VkBool32 separateDenormSettings
+ VkBool32 separateRoundingModeSettings
+ VkBool32 shaderSignedZeroInfNanPreserveFloat16
+ VkBool32 shaderSignedZeroInfNanPreserveFloat32
+ VkBool32 shaderSignedZeroInfNanPreserveFloat64
+ VkBool32 shaderDenormPreserveFloat16
+ VkBool32 shaderDenormPreserveFloat32
+ VkBool32 shaderDenormPreserveFloat64
+ VkBool32 shaderDenormFlushToZeroFloat16
+ VkBool32 shaderDenormFlushToZeroFloat32
+ VkBool32 shaderDenormFlushToZeroFloat64
+ VkBool32 shaderRoundingModeRTEFloat16
+ VkBool32 shaderRoundingModeRTEFloat32
+ VkBool32 shaderRoundingModeRTEFloat64
+ VkBool32 shaderRoundingModeRTZFloat16
+ VkBool32 shaderRoundingModeRTZFloat32
+ VkBool32 shaderRoundingModeRTZFloat64
+}
+
@extension("VK_NV_compute_shader_derivatives") // 202
class VkPhysicalDeviceComputeShaderDerivativesFeaturesNV {
VkStructureType sType
@@ -7598,10 +7740,10 @@
class VkPhysicalDevicePCIBusInfoPropertiesEXT {
VkStructureType sType
void* pNext
- u16 pciDomain
- u8 pciBus
- u8 pciDevice
- u8 pciFunction
+ u32 pciDomain
+ u32 pciBus
+ u32 pciDevice
+ u32 pciFunction
}
@extension("VK_FUCHSIA_imagepipe_surface") // 215
@@ -7612,6 +7754,45 @@
platform.zx_handle_t imagePipeHandle
}
+@extension("VK_EXT_fragment_density_map") // 219
+class VkPhysicalDeviceFragmentDensityMapFeaturesEXT {
+ VkStructureType sType
+ void* pNext
+ VkBool32 fragmentDensityMap
+ VkBool32 fragmentDensityMapDynamic
+ VkBool32 fragmentDensityMapNonSubsampledImages
+}
+
+@extension("VK_EXT_fragment_density_map") // 219
+class VkPhysicalDeviceFragmentDensityMapPropertiesEXT {
+ VkStructureType sType
+ void* pNext
+ VkExtent2D minFragmentDensityTexelSize
+ VkExtent2D maxFragmentDensityTexelSize
+ VkBool32 fragmentDensityInvocations
+}
+
+@extension("VK_EXT_fragment_density_map") // 219
+class VkRenderPassFragmentDensityMapCreateInfoEXT {
+ VkStructureType sType
+ const void* pNext
+ VkAttachmentReference fragmentDensityMapAttachment
+}
+
+@extension("VK_EXT_scalar_block_layout") // 222
+class VkPhysicalDeviceScalarBlockLayoutFeaturesEXT {
+ VkStructureType sType
+ void* pNext
+ VkBool32 scalarBlockLayout
+}
+
+@extension("VK_EXT_separate_stencil_usage") // 247
+class VkImageStencilUsageCreateInfoEXT {
+ VkStructureType sType
+ const void* pNext
+ VkImageUsageFlags stencilUsage
+}
+
////////////////
// Commands //
@@ -10370,25 +10551,6 @@
return ?
}
-@extension("VK_KHR_mir_surface") // 8
-cmd VkResult vkCreateMirSurfaceKHR(
- VkInstance instance,
- const VkMirSurfaceCreateInfoKHR* pCreateInfo,
- const VkAllocationCallbacks* pAllocator,
- VkSurfaceKHR* pSurface) {
- instanceObject := GetInstance(instance)
- return ?
-}
-
-@extension("VK_KHR_mir_surface") // 8
-cmd VkBool32 vkGetPhysicalDeviceMirPresentationSupportKHR(
- VkPhysicalDevice physicalDevice,
- u32 queueFamilyIndex,
- platform.MirConnection* connection) {
- physicalDeviceObject := GetPhysicalDevice(physicalDevice)
- return ?
-}
-
@extension("VK_KHR_android_surface") // 9
cmd VkResult vkCreateAndroidSurfaceKHR(
VkInstance instance,
@@ -11448,71 +11610,60 @@
const VkCoarseSampleOrderCustomNV* pCustomSampleOrders) {
}
-@extension("VK_NVX_raytracing") // 166
-cmd VkResult vkCreateAccelerationStructureNVX(
+@extension("VK_NV_ray_tracing") // 166
+cmd VkResult vkCreateAccelerationStructureNV(
VkDevice device,
- const VkAccelerationStructureCreateInfoNVX* pCreateInfo,
+ const VkAccelerationStructureCreateInfoNV* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
- VkAccelerationStructureNVX* pAccelerationStructure) {
+ VkAccelerationStructureNV* pAccelerationStructure) {
return ?
}
-@extension("VK_NVX_raytracing") // 166
-cmd void vkDestroyAccelerationStructureNVX(
+@extension("VK_NV_ray_tracing") // 166
+cmd void vkDestroyAccelerationStructureNV(
VkDevice device,
- VkAccelerationStructureNVX accelerationStructure,
+ VkAccelerationStructureNV accelerationStructure,
const VkAllocationCallbacks* pAllocator) {
}
-@extension("VK_NVX_raytracing") // 166
-cmd void vkGetAccelerationStructureMemoryRequirementsNVX(
+@extension("VK_NV_ray_tracing") // 166
+cmd void vkGetAccelerationStructureMemoryRequirementsNV(
VkDevice device,
- const VkAccelerationStructureMemoryRequirementsInfoNVX* pInfo,
+ const VkAccelerationStructureMemoryRequirementsInfoNV* 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(
+@extension("VK_NV_ray_tracing") // 166
+cmd VkResult vkBindAccelerationStructureMemoryNV(
VkDevice device,
u32 bindInfoCount,
- const VkBindAccelerationStructureMemoryInfoNVX* pBindInfos) {
+ const VkBindAccelerationStructureMemoryInfoNV* pBindInfos) {
return ?
}
-@extension("VK_NVX_raytracing") // 166
-cmd void vkCmdBuildAccelerationStructureNVX(
+@extension("VK_NV_ray_tracing") // 166
+cmd void vkCmdBuildAccelerationStructureNV(
VkCommandBuffer commandBuffer,
- VkAccelerationStructureTypeNVX type,
- u32 instanceCount,
+ const VkAccelerationStructureInfoNV* pInfo,
VkBuffer instanceData,
VkDeviceSize instanceOffset,
- u32 geometryCount,
- const VkGeometryNVX* pGeometries,
- VkBuildAccelerationStructureFlagsNVX flags,
VkBool32 update,
- VkAccelerationStructureNVX dst,
- VkAccelerationStructureNVX src,
+ VkAccelerationStructureNV dst,
+ VkAccelerationStructureNV src,
VkBuffer scratch,
VkDeviceSize scratchOffset) {
}
-@extension("VK_NVX_raytracing") // 166
-cmd void vkCmdCopyAccelerationStructureNVX(
+@extension("VK_NV_ray_tracing") // 166
+cmd void vkCmdCopyAccelerationStructureNV(
VkCommandBuffer commandBuffer,
- VkAccelerationStructureNVX dst,
- VkAccelerationStructureNVX src,
- VkCopyAccelerationStructureModeNVX mode) {
+ VkAccelerationStructureNV dst,
+ VkAccelerationStructureNV src,
+ VkCopyAccelerationStructureModeNV mode) {
}
-@extension("VK_NVX_raytracing") // 166
-cmd void vkCmdTraceRaysNVX(
+@extension("VK_NV_ray_tracing") // 166
+cmd void vkCmdTraceRaysNV(
VkCommandBuffer commandBuffer,
VkBuffer raygenShaderBindingTableBuffer,
VkDeviceSize raygenShaderBindingOffset,
@@ -11522,23 +11673,27 @@
VkBuffer hitShaderBindingTableBuffer,
VkDeviceSize hitShaderBindingOffset,
VkDeviceSize hitShaderBindingStride,
+ VkBuffer callableShaderBindingTableBuffer,
+ VkDeviceSize callableShaderBindingOffset,
+ VkDeviceSize callableShaderBindingStride,
u32 width,
- u32 height) {
+ u32 height,
+ u32 depth) {
}
-@extension("VK_NVX_raytracing") // 166
-cmd VkResult vkCreateRaytracingPipelinesNVX(
+@extension("VK_NV_ray_tracing") // 166
+cmd VkResult vkCreateRaytracingPipelinesNV(
VkDevice device,
VkPipelineCache pipelineCache,
u32 createInfoCount,
- const VkRaytracingPipelineCreateInfoNVX* pCreateInfos,
+ const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
const VkAllocationCallbacks* pAllocator,
VkPipeline* pPipelines) {
return ?
}
-@extension("VK_NVX_raytracing") // 166
-cmd VkResult vkGetRaytracingShaderHandlesNVX(
+@extension("VK_NV_ray_tracing") // 166
+cmd VkResult vkGetRaytracingShaderHandlesNV(
VkDevice device,
VkPipeline pipeline,
u32 firstGroup,
@@ -11548,26 +11703,27 @@
return ?
}
-@extension("VK_NVX_raytracing") // 166
-cmd VkResult vkGetAccelerationStructureHandleNVX(
+@extension("VK_NV_ray_tracing") // 166
+cmd VkResult vkGetAccelerationStructureHandleNV(
VkDevice device,
- VkAccelerationStructureNVX accelerationStructure,
+ VkAccelerationStructureNV accelerationStructure,
platform.size_t dataSize,
void* pData) {
return ?
}
-@extension("VK_NVX_raytracing") // 166
-cmd void vkCmdWriteAccelerationStructurePropertiesNVX(
+@extension("VK_NV_ray_tracing") // 166
+cmd void vkCmdWriteAccelerationStructurePropertiesNV(
VkCommandBuffer commandBuffer,
- VkAccelerationStructureNVX accelerationStructure,
+ u32 accelerationStructureCount,
+ const VkAccelerationStructureNV* pAccelerationStructures,
VkQueryType queryType,
VkQueryPool queryPool,
- u32 query) {
+ u32 firstQuery) {
}
-@extension("VK_NVX_raytracing") // 166
-cmd VkResult vkCompileDeferredNVX(
+@extension("VK_NV_ray_tracing") // 166
+cmd VkResult vkCompileDeferredNV(
VkDevice device,
VkPipeline pipeline,
u32 shader) {
diff --git a/vulkan/include/vulkan/vulkan.h b/vulkan/include/vulkan/vulkan.h
index d05c849..77da637 100644
--- a/vulkan/include/vulkan/vulkan.h
+++ b/vulkan/include/vulkan/vulkan.h
@@ -24,6 +24,10 @@
#include "vulkan_android.h"
#endif
+#ifdef VK_USE_PLATFORM_FUCHSIA
+#include <zircon/types.h>
+#include "vulkan_fuchsia.h"
+#endif
#ifdef VK_USE_PLATFORM_IOS_MVK
#include "vulkan_ios.h"
@@ -35,12 +39,6 @@
#endif
-#ifdef VK_USE_PLATFORM_MIR_KHR
-#include <mir_toolkit/client_types.h>
-#include "vulkan_mir.h"
-#endif
-
-
#ifdef VK_USE_PLATFORM_VI_NN
#include "vulkan_vi.h"
#endif
diff --git a/vulkan/include/vulkan/vulkan_core.h b/vulkan/include/vulkan/vulkan_core.h
index ac9bb66..72542c7 100644
--- a/vulkan/include/vulkan/vulkan_core.h
+++ b/vulkan/include/vulkan/vulkan_core.h
@@ -43,13 +43,12 @@
#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 90
+#define VK_HEADER_VERSION 96
#define VK_NULL_HANDLE 0
-
#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
@@ -62,7 +61,6 @@
#endif
-
typedef uint32_t VkFlags;
typedef uint32_t VkBool32;
typedef uint64_t VkDeviceSize;
@@ -287,7 +285,6 @@
VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR = 1000004000,
VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR = 1000005000,
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
- VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR = 1000007000,
VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR = 1000008000,
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT = 1000011000,
@@ -330,6 +327,7 @@
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_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR = 1000082000,
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,
@@ -419,17 +417,17 @@
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_RAY_TRACING_PIPELINE_CREATE_INFO_NV = 1000165000,
+ VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV = 1000165001,
+ VK_STRUCTURE_TYPE_GEOMETRY_NV = 1000165003,
+ VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV = 1000165004,
+ VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV = 1000165005,
+ VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV = 1000165006,
+ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV = 1000165007,
+ VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV = 1000165008,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV = 1000165009,
+ VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV = 1000165011,
+ VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV = 1000165012,
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,
@@ -440,10 +438,12 @@
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR = 1000180000,
VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT = 1000184000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD = 1000185000,
+ VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD = 1000189000,
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_FLOAT_CONTROLS_PROPERTIES_KHR = 1000197000,
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,
@@ -456,6 +456,11 @@
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = 1000211000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT = 1000212000,
VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA = 1000214000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT = 1000218000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT = 1000218001,
+ VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT = 1000218002,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT = 1000221000,
+ VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO_EXT = 1000246000,
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,
@@ -848,7 +853,7 @@
VK_QUERY_TYPE_PIPELINE_STATISTICS = 1,
VK_QUERY_TYPE_TIMESTAMP = 2,
VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT = 1000028004,
- VK_QUERY_TYPE_COMPACTED_SIZE_NVX = 1000165000,
+ VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV = 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),
@@ -879,6 +884,7 @@
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_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT = 1000218000,
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,
@@ -1178,7 +1184,7 @@
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_ACCELERATION_STRUCTURE_NV = 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),
@@ -1207,7 +1213,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_RAY_TRACING_NV = 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),
@@ -1226,6 +1232,7 @@
typedef enum VkIndexType {
VK_INDEX_TYPE_UINT16 = 0,
VK_INDEX_TYPE_UINT32 = 1,
+ VK_INDEX_TYPE_NONE_NV = 1000165000,
VK_INDEX_TYPE_BEGIN_RANGE = VK_INDEX_TYPE_UINT16,
VK_INDEX_TYPE_END_RANGE = VK_INDEX_TYPE_UINT32,
VK_INDEX_TYPE_RANGE_SIZE = (VK_INDEX_TYPE_UINT32 - VK_INDEX_TYPE_UINT16 + 1),
@@ -1279,7 +1286,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_ACCELERATION_STRUCTURE_NV = 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,
@@ -1325,6 +1332,7 @@
VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT = 0x00800000,
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG = 0x00002000,
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT = 0x00010000,
+ VK_FORMAT_FEATURE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x01000000,
VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT,
VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_DST_BIT,
VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT_KHR = VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT,
@@ -1348,6 +1356,7 @@
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_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x00000200,
VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkImageUsageFlagBits;
typedef VkFlags VkImageUsageFlags;
@@ -1367,6 +1376,7 @@
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_SUBSAMPLED_BIT_EXT = 0x00004000,
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,
VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR = VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT,
@@ -1447,9 +1457,11 @@
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_RAY_TRACING_SHADER_BIT_NV = 0x00200000,
+ VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV = 0x02000000,
VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV = 0x00080000,
VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV = 0x00100000,
+ VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000,
VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkPipelineStageFlagBits;
typedef VkFlags VkPipelineStageFlags;
@@ -1544,11 +1556,16 @@
VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT = 0x00000800,
VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT = 0x00001000,
VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00000200,
- VK_BUFFER_USAGE_RAYTRACING_BIT_NVX = 0x00000400,
+ VK_BUFFER_USAGE_RAY_TRACING_BIT_NV = 0x00000400,
VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkBufferUsageFlagBits;
typedef VkFlags VkBufferUsageFlags;
typedef VkFlags VkBufferViewCreateFlags;
+
+typedef enum VkImageViewCreateFlagBits {
+ VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DYNAMIC_BIT_EXT = 0x00000001,
+ VK_IMAGE_VIEW_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkImageViewCreateFlagBits;
typedef VkFlags VkImageViewCreateFlags;
typedef VkFlags VkShaderModuleCreateFlags;
typedef VkFlags VkPipelineCacheCreateFlags;
@@ -1559,7 +1576,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_DEFER_COMPILE_BIT_NV = 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
@@ -1576,12 +1593,12 @@
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_RAYGEN_BIT_NV = 0x00000100,
+ VK_SHADER_STAGE_ANY_HIT_BIT_NV = 0x00000200,
+ VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV = 0x00000400,
+ VK_SHADER_STAGE_MISS_BIT_NV = 0x00000800,
+ VK_SHADER_STAGE_INTERSECTION_BIT_NV = 0x00001000,
+ VK_SHADER_STAGE_CALLABLE_BIT_NV = 0x00002000,
VK_SHADER_STAGE_TASK_BIT_NV = 0x00000040,
VK_SHADER_STAGE_MESH_BIT_NV = 0x00000080,
VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
@@ -1615,6 +1632,12 @@
typedef VkFlags VkPipelineDynamicStateCreateFlags;
typedef VkFlags VkPipelineLayoutCreateFlags;
typedef VkFlags VkShaderStageFlags;
+
+typedef enum VkSamplerCreateFlagBits {
+ VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT = 0x00000001,
+ VK_SAMPLER_CREATE_SUBSAMPLED_COARSE_RECONSTRUCTION_BIT_EXT = 0x00000002,
+ VK_SAMPLER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkSamplerCreateFlagBits;
typedef VkFlags VkSamplerCreateFlags;
typedef enum VkDescriptorSetLayoutCreateFlagBits {
@@ -1673,8 +1696,9 @@
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_ACCELERATION_STRUCTURE_READ_BIT_NV = 0x00200000,
+ VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV = 0x00400000,
+ VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000,
VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkAccessFlagBits;
typedef VkFlags VkAccessFlags;
@@ -4355,7 +4379,7 @@
typedef struct VkDescriptorUpdateTemplateCreateInfo {
VkStructureType sType;
- void* pNext;
+ const void* pNext;
VkDescriptorUpdateTemplateCreateFlags flags;
uint32_t descriptorUpdateEntryCount;
const VkDescriptorUpdateTemplateEntry* pDescriptorUpdateEntries;
@@ -4794,6 +4818,7 @@
typedef enum VkSwapchainCreateFlagBitsKHR {
VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = 0x00000001,
VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR = 0x00000002,
+ VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR = 0x00000004,
VK_SWAPCHAIN_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
} VkSwapchainCreateFlagBitsKHR;
typedef VkFlags VkSwapchainCreateFlagsKHR;
@@ -5470,6 +5495,19 @@
const void* pData);
#endif
+#define VK_KHR_shader_float16_int8 1
+#define VK_KHR_SHADER_FLOAT16_INT8_SPEC_VERSION 1
+#define VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME "VK_KHR_shader_float16_int8"
+
+typedef struct VkPhysicalDeviceFloat16Int8FeaturesKHR {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 shaderFloat16;
+ VkBool32 shaderInt8;
+} VkPhysicalDeviceFloat16Int8FeaturesKHR;
+
+
+
#define VK_KHR_16bit_storage 1
#define VK_KHR_16BIT_STORAGE_SPEC_VERSION 1
#define VK_KHR_16BIT_STORAGE_EXTENSION_NAME "VK_KHR_16bit_storage"
@@ -6101,9 +6139,10 @@
VK_DRIVER_ID_IMAGINATION_PROPRIETARY_KHR = 7,
VK_DRIVER_ID_QUALCOMM_PROPRIETARY_KHR = 8,
VK_DRIVER_ID_ARM_PROPRIETARY_KHR = 9,
+ VK_DRIVER_ID_GOOGLE_PASTEL_KHR = 10,
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_END_RANGE_KHR = VK_DRIVER_ID_GOOGLE_PASTEL_KHR,
+ VK_DRIVER_ID_RANGE_SIZE_KHR = (VK_DRIVER_ID_GOOGLE_PASTEL_KHR - VK_DRIVER_ID_AMD_PROPRIETARY_KHR + 1),
VK_DRIVER_ID_MAX_ENUM_KHR = 0x7FFFFFFF
} VkDriverIdKHR;
@@ -6125,6 +6164,39 @@
+#define VK_KHR_shader_float_controls 1
+#define VK_KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION 1
+#define VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME "VK_KHR_shader_float_controls"
+
+typedef struct VkPhysicalDeviceFloatControlsPropertiesKHR {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 separateDenormSettings;
+ VkBool32 separateRoundingModeSettings;
+ VkBool32 shaderSignedZeroInfNanPreserveFloat16;
+ VkBool32 shaderSignedZeroInfNanPreserveFloat32;
+ VkBool32 shaderSignedZeroInfNanPreserveFloat64;
+ VkBool32 shaderDenormPreserveFloat16;
+ VkBool32 shaderDenormPreserveFloat32;
+ VkBool32 shaderDenormPreserveFloat64;
+ VkBool32 shaderDenormFlushToZeroFloat16;
+ VkBool32 shaderDenormFlushToZeroFloat32;
+ VkBool32 shaderDenormFlushToZeroFloat64;
+ VkBool32 shaderRoundingModeRTEFloat16;
+ VkBool32 shaderRoundingModeRTEFloat32;
+ VkBool32 shaderRoundingModeRTEFloat64;
+ VkBool32 shaderRoundingModeRTZFloat16;
+ VkBool32 shaderRoundingModeRTZFloat32;
+ VkBool32 shaderRoundingModeRTZFloat64;
+} VkPhysicalDeviceFloatControlsPropertiesKHR;
+
+
+
+#define VK_KHR_swapchain_mutable_format 1
+#define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_SPEC_VERSION 1
+#define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME "VK_KHR_swapchain_mutable_format"
+
+
#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"
@@ -6182,7 +6254,7 @@
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_ACCELERATION_STRUCTURE_NV_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,
@@ -7446,11 +7518,11 @@
int32_t messageIdNumber;
const char* pMessage;
uint32_t queueLabelCount;
- VkDebugUtilsLabelEXT* pQueueLabels;
+ const VkDebugUtilsLabelEXT* pQueueLabels;
uint32_t cmdBufLabelCount;
- VkDebugUtilsLabelEXT* pCmdBufLabels;
+ const VkDebugUtilsLabelEXT* pCmdBufLabels;
uint32_t objectCount;
- VkDebugUtilsObjectNameInfoEXT* pObjects;
+ const VkDebugUtilsObjectNameInfoEXT* pObjects;
} VkDebugUtilsMessengerCallbackDataEXT;
typedef VkBool32 (VKAPI_PTR *PFN_vkDebugUtilsMessengerCallbackEXT)(
@@ -7791,8 +7863,6 @@
#define VK_EXT_image_drm_format_modifier 1
-#define VK_EXT_EXTENSION_159_SPEC_VERSION 0
-#define VK_EXT_EXTENSION_159_EXTENSION_NAME "VK_EXT_extension_159"
#define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_SPEC_VERSION 1
#define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME "VK_EXT_image_drm_format_modifier"
@@ -8113,81 +8183,113 @@
const VkCoarseSampleOrderCustomNV* pCustomSampleOrders);
#endif
-#define VK_NVX_raytracing 1
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureNVX)
+#define VK_NV_ray_tracing 1
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureNV)
-#define VK_NVX_RAYTRACING_SPEC_VERSION 1
-#define VK_NVX_RAYTRACING_EXTENSION_NAME "VK_NVX_raytracing"
+#define VK_NV_RAY_TRACING_SPEC_VERSION 3
+#define VK_NV_RAY_TRACING_EXTENSION_NAME "VK_NV_ray_tracing"
+#define VK_SHADER_UNUSED_NV (~0U)
-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 VkRayTracingShaderGroupTypeNV {
+ VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV = 0,
+ VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV = 1,
+ VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV = 2,
+ VK_RAY_TRACING_SHADER_GROUP_TYPE_BEGIN_RANGE_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV,
+ VK_RAY_TRACING_SHADER_GROUP_TYPE_END_RANGE_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV,
+ VK_RAY_TRACING_SHADER_GROUP_TYPE_RANGE_SIZE_NV = (VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV - VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV + 1),
+ VK_RAY_TRACING_SHADER_GROUP_TYPE_MAX_ENUM_NV = 0x7FFFFFFF
+} VkRayTracingShaderGroupTypeNV;
-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 VkGeometryTypeNV {
+ VK_GEOMETRY_TYPE_TRIANGLES_NV = 0,
+ VK_GEOMETRY_TYPE_AABBS_NV = 1,
+ VK_GEOMETRY_TYPE_BEGIN_RANGE_NV = VK_GEOMETRY_TYPE_TRIANGLES_NV,
+ VK_GEOMETRY_TYPE_END_RANGE_NV = VK_GEOMETRY_TYPE_AABBS_NV,
+ VK_GEOMETRY_TYPE_RANGE_SIZE_NV = (VK_GEOMETRY_TYPE_AABBS_NV - VK_GEOMETRY_TYPE_TRIANGLES_NV + 1),
+ VK_GEOMETRY_TYPE_MAX_ENUM_NV = 0x7FFFFFFF
+} VkGeometryTypeNV;
-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 VkAccelerationStructureTypeNV {
+ VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV = 0,
+ VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV = 1,
+ VK_ACCELERATION_STRUCTURE_TYPE_BEGIN_RANGE_NV = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV,
+ VK_ACCELERATION_STRUCTURE_TYPE_END_RANGE_NV = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV,
+ VK_ACCELERATION_STRUCTURE_TYPE_RANGE_SIZE_NV = (VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV - VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV + 1),
+ VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF
+} VkAccelerationStructureTypeNV;
+
+typedef enum VkCopyAccelerationStructureModeNV {
+ VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV = 0,
+ VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV = 1,
+ VK_COPY_ACCELERATION_STRUCTURE_MODE_BEGIN_RANGE_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV,
+ VK_COPY_ACCELERATION_STRUCTURE_MODE_END_RANGE_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV,
+ VK_COPY_ACCELERATION_STRUCTURE_MODE_RANGE_SIZE_NV = (VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV - VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV + 1),
+ VK_COPY_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_NV = 0x7FFFFFFF
+} VkCopyAccelerationStructureModeNV;
+
+typedef enum VkAccelerationStructureMemoryRequirementsTypeNV {
+ VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV = 0,
+ VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV = 1,
+ VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV = 2,
+ VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BEGIN_RANGE_NV = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV,
+ VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_END_RANGE_NV = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV,
+ VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_RANGE_SIZE_NV = (VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV + 1),
+ VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_MAX_ENUM_NV = 0x7FFFFFFF
+} VkAccelerationStructureMemoryRequirementsTypeNV;
-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 VkGeometryFlagBitsNV {
+ VK_GEOMETRY_OPAQUE_BIT_NV = 0x00000001,
+ VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV = 0x00000002,
+ VK_GEOMETRY_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF
+} VkGeometryFlagBitsNV;
+typedef VkFlags VkGeometryFlagsNV;
-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 VkGeometryInstanceFlagBitsNV {
+ VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV = 0x00000001,
+ VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV = 0x00000002,
+ VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV = 0x00000004,
+ VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV = 0x00000008,
+ VK_GEOMETRY_INSTANCE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF
+} VkGeometryInstanceFlagBitsNV;
+typedef VkFlags VkGeometryInstanceFlagsNV;
-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 enum VkBuildAccelerationStructureFlagBitsNV {
+ VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV = 0x00000001,
+ VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV = 0x00000002,
+ VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV = 0x00000004,
+ VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV = 0x00000008,
+ VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV = 0x00000010,
+ VK_BUILD_ACCELERATION_STRUCTURE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF
+} VkBuildAccelerationStructureFlagBitsNV;
+typedef VkFlags VkBuildAccelerationStructureFlagsNV;
-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 VkRayTracingShaderGroupCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkRayTracingShaderGroupTypeNV type;
+ uint32_t generalShader;
+ uint32_t closestHitShader;
+ uint32_t anyHitShader;
+ uint32_t intersectionShader;
+} VkRayTracingShaderGroupCreateInfoNV;
-typedef struct VkGeometryTrianglesNVX {
+typedef struct VkRayTracingPipelineCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineCreateFlags flags;
+ uint32_t stageCount;
+ const VkPipelineShaderStageCreateInfo* pStages;
+ uint32_t groupCount;
+ const VkRayTracingShaderGroupCreateInfoNV* pGroups;
+ uint32_t maxRecursionDepth;
+ VkPipelineLayout layout;
+ VkPipeline basePipelineHandle;
+ int32_t basePipelineIndex;
+} VkRayTracingPipelineCreateInfoNV;
+
+typedef struct VkGeometryTrianglesNV {
VkStructureType sType;
const void* pNext;
VkBuffer vertexData;
@@ -8201,136 +8303,138 @@
VkIndexType indexType;
VkBuffer transformData;
VkDeviceSize transformOffset;
-} VkGeometryTrianglesNVX;
+} VkGeometryTrianglesNV;
-typedef struct VkGeometryAABBNVX {
+typedef struct VkGeometryAABBNV {
VkStructureType sType;
const void* pNext;
VkBuffer aabbData;
uint32_t numAABBs;
uint32_t stride;
VkDeviceSize offset;
-} VkGeometryAABBNVX;
+} VkGeometryAABBNV;
-typedef struct VkGeometryDataNVX {
- VkGeometryTrianglesNVX triangles;
- VkGeometryAABBNVX aabbs;
-} VkGeometryDataNVX;
+typedef struct VkGeometryDataNV {
+ VkGeometryTrianglesNV triangles;
+ VkGeometryAABBNV aabbs;
+} VkGeometryDataNV;
-typedef struct VkGeometryNVX {
- VkStructureType sType;
- const void* pNext;
- VkGeometryTypeNVX geometryType;
- VkGeometryDataNVX geometry;
- VkGeometryFlagsNVX flags;
-} VkGeometryNVX;
+typedef struct VkGeometryNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkGeometryTypeNV geometryType;
+ VkGeometryDataNV geometry;
+ VkGeometryFlagsNV flags;
+} VkGeometryNV;
-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 VkAccelerationStructureInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkAccelerationStructureTypeNV type;
+ VkBuildAccelerationStructureFlagsNV flags;
+ uint32_t instanceCount;
+ uint32_t geometryCount;
+ const VkGeometryNV* pGeometries;
+} VkAccelerationStructureInfoNV;
-typedef struct VkBindAccelerationStructureMemoryInfoNVX {
- VkStructureType sType;
- const void* pNext;
- VkAccelerationStructureNVX accelerationStructure;
- VkDeviceMemory memory;
- VkDeviceSize memoryOffset;
- uint32_t deviceIndexCount;
- const uint32_t* pDeviceIndices;
-} VkBindAccelerationStructureMemoryInfoNVX;
+typedef struct VkAccelerationStructureCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceSize compactedSize;
+ VkAccelerationStructureInfoNV info;
+} VkAccelerationStructureCreateInfoNV;
-typedef struct VkDescriptorAccelerationStructureInfoNVX {
- VkStructureType sType;
- const void* pNext;
- uint32_t accelerationStructureCount;
- const VkAccelerationStructureNVX* pAccelerationStructures;
-} VkDescriptorAccelerationStructureInfoNVX;
+typedef struct VkBindAccelerationStructureMemoryInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkAccelerationStructureNV accelerationStructure;
+ VkDeviceMemory memory;
+ VkDeviceSize memoryOffset;
+ uint32_t deviceIndexCount;
+ const uint32_t* pDeviceIndices;
+} VkBindAccelerationStructureMemoryInfoNV;
-typedef struct VkAccelerationStructureMemoryRequirementsInfoNVX {
- VkStructureType sType;
- const void* pNext;
- VkAccelerationStructureNVX accelerationStructure;
-} VkAccelerationStructureMemoryRequirementsInfoNVX;
+typedef struct VkWriteDescriptorSetAccelerationStructureNV {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t accelerationStructureCount;
+ const VkAccelerationStructureNV* pAccelerationStructures;
+} VkWriteDescriptorSetAccelerationStructureNV;
-typedef struct VkPhysicalDeviceRaytracingPropertiesNVX {
+typedef struct VkAccelerationStructureMemoryRequirementsInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkAccelerationStructureMemoryRequirementsTypeNV type;
+ VkAccelerationStructureNV accelerationStructure;
+} VkAccelerationStructureMemoryRequirementsInfoNV;
+
+typedef struct VkPhysicalDeviceRayTracingPropertiesNV {
VkStructureType sType;
void* pNext;
- uint32_t shaderHeaderSize;
+ uint32_t shaderGroupHandleSize;
uint32_t maxRecursionDepth;
- uint32_t maxGeometryCount;
-} VkPhysicalDeviceRaytracingPropertiesNVX;
+ uint32_t maxShaderGroupStride;
+ uint32_t shaderGroupBaseAlignment;
+ uint64_t maxGeometryCount;
+ uint64_t maxInstanceCount;
+ uint64_t maxTriangleCount;
+ uint32_t maxDescriptorSetAccelerationStructures;
+} VkPhysicalDeviceRayTracingPropertiesNV;
-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);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureNV)(VkDevice device, const VkAccelerationStructureCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureNV* pAccelerationStructure);
+typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, const VkAllocationCallbacks* pAllocator);
+typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureMemoryRequirementsNV)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements);
+typedef VkResult (VKAPI_PTR *PFN_vkBindAccelerationStructureMemoryNV)(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoNV* pBindInfos);
+typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureNV)(VkCommandBuffer commandBuffer, const VkAccelerationStructureInfoNV* pInfo, VkBuffer instanceData, VkDeviceSize instanceOffset, VkBool32 update, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkBuffer scratch, VkDeviceSize scratchOffset);
+typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureNV)(VkCommandBuffer commandBuffer, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkCopyAccelerationStructureModeNV mode);
+typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysNV)(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset, VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer, VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride, uint32_t width, uint32_t height, uint32_t depth);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateRayTracingPipelinesNV)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines);
+typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupHandlesNV)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData);
+typedef VkResult (VKAPI_PTR *PFN_vkGetAccelerationStructureHandleNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, size_t dataSize, void* pData);
+typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesNV)(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureNV* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery);
+typedef VkResult (VKAPI_PTR *PFN_vkCompileDeferredNV)(VkDevice device, VkPipeline pipeline, uint32_t shader);
#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureNVX(
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureNV(
VkDevice device,
- const VkAccelerationStructureCreateInfoNVX* pCreateInfo,
+ const VkAccelerationStructureCreateInfoNV* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
- VkAccelerationStructureNVX* pAccelerationStructure);
+ VkAccelerationStructureNV* pAccelerationStructure);
-VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureNVX(
+VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureNV(
VkDevice device,
- VkAccelerationStructureNVX accelerationStructure,
+ VkAccelerationStructureNV accelerationStructure,
const VkAllocationCallbacks* pAllocator);
-VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureMemoryRequirementsNVX(
+VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureMemoryRequirementsNV(
VkDevice device,
- const VkAccelerationStructureMemoryRequirementsInfoNVX* pInfo,
+ const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo,
VkMemoryRequirements2KHR* pMemoryRequirements);
-VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureScratchMemoryRequirementsNVX(
- VkDevice device,
- const VkAccelerationStructureMemoryRequirementsInfoNVX* pInfo,
- VkMemoryRequirements2KHR* pMemoryRequirements);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkBindAccelerationStructureMemoryNVX(
+VKAPI_ATTR VkResult VKAPI_CALL vkBindAccelerationStructureMemoryNV(
VkDevice device,
uint32_t bindInfoCount,
- const VkBindAccelerationStructureMemoryInfoNVX* pBindInfos);
+ const VkBindAccelerationStructureMemoryInfoNV* pBindInfos);
-VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureNVX(
+VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureNV(
VkCommandBuffer commandBuffer,
- VkAccelerationStructureTypeNVX type,
- uint32_t instanceCount,
+ const VkAccelerationStructureInfoNV* pInfo,
VkBuffer instanceData,
VkDeviceSize instanceOffset,
- uint32_t geometryCount,
- const VkGeometryNVX* pGeometries,
- VkBuildAccelerationStructureFlagsNVX flags,
VkBool32 update,
- VkAccelerationStructureNVX dst,
- VkAccelerationStructureNVX src,
+ VkAccelerationStructureNV dst,
+ VkAccelerationStructureNV src,
VkBuffer scratch,
VkDeviceSize scratchOffset);
-VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureNVX(
+VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureNV(
VkCommandBuffer commandBuffer,
- VkAccelerationStructureNVX dst,
- VkAccelerationStructureNVX src,
- VkCopyAccelerationStructureModeNVX mode);
+ VkAccelerationStructureNV dst,
+ VkAccelerationStructureNV src,
+ VkCopyAccelerationStructureModeNV mode);
-VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysNVX(
+VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysNV(
VkCommandBuffer commandBuffer,
VkBuffer raygenShaderBindingTableBuffer,
VkDeviceSize raygenShaderBindingOffset,
@@ -8340,18 +8444,22 @@
VkBuffer hitShaderBindingTableBuffer,
VkDeviceSize hitShaderBindingOffset,
VkDeviceSize hitShaderBindingStride,
+ VkBuffer callableShaderBindingTableBuffer,
+ VkDeviceSize callableShaderBindingOffset,
+ VkDeviceSize callableShaderBindingStride,
uint32_t width,
- uint32_t height);
+ uint32_t height,
+ uint32_t depth);
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateRaytracingPipelinesNVX(
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateRayTracingPipelinesNV(
VkDevice device,
VkPipelineCache pipelineCache,
uint32_t createInfoCount,
- const VkRaytracingPipelineCreateInfoNVX* pCreateInfos,
+ const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
const VkAllocationCallbacks* pAllocator,
VkPipeline* pPipelines);
-VKAPI_ATTR VkResult VKAPI_CALL vkGetRaytracingShaderHandlesNVX(
+VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesNV(
VkDevice device,
VkPipeline pipeline,
uint32_t firstGroup,
@@ -8359,20 +8467,21 @@
size_t dataSize,
void* pData);
-VKAPI_ATTR VkResult VKAPI_CALL vkGetAccelerationStructureHandleNVX(
+VKAPI_ATTR VkResult VKAPI_CALL vkGetAccelerationStructureHandleNV(
VkDevice device,
- VkAccelerationStructureNVX accelerationStructure,
+ VkAccelerationStructureNV accelerationStructure,
size_t dataSize,
void* pData);
-VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructurePropertiesNVX(
+VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructuresPropertiesNV(
VkCommandBuffer commandBuffer,
- VkAccelerationStructureNVX accelerationStructure,
+ uint32_t accelerationStructureCount,
+ const VkAccelerationStructureNV* pAccelerationStructures,
VkQueryType queryType,
VkQueryPool queryPool,
- uint32_t query);
+ uint32_t firstQuery);
-VKAPI_ATTR VkResult VKAPI_CALL vkCompileDeferredNVX(
+VKAPI_ATTR VkResult VKAPI_CALL vkCompileDeferredNV(
VkDevice device,
VkPipeline pipeline,
uint32_t shader);
@@ -8534,6 +8643,29 @@
+#define VK_AMD_memory_overallocation_behavior 1
+#define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_SPEC_VERSION 1
+#define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_EXTENSION_NAME "VK_AMD_memory_overallocation_behavior"
+
+
+typedef enum VkMemoryOverallocationBehaviorAMD {
+ VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD = 0,
+ VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD = 1,
+ VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD = 2,
+ VK_MEMORY_OVERALLOCATION_BEHAVIOR_BEGIN_RANGE_AMD = VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD,
+ VK_MEMORY_OVERALLOCATION_BEHAVIOR_END_RANGE_AMD = VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD,
+ VK_MEMORY_OVERALLOCATION_BEHAVIOR_RANGE_SIZE_AMD = (VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD - VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD + 1),
+ VK_MEMORY_OVERALLOCATION_BEHAVIOR_MAX_ENUM_AMD = 0x7FFFFFFF
+} VkMemoryOverallocationBehaviorAMD;
+
+typedef struct VkDeviceMemoryOverallocationCreateInfoAMD {
+ VkStructureType sType;
+ const void* pNext;
+ VkMemoryOverallocationBehaviorAMD overallocationBehavior;
+} VkDeviceMemoryOverallocationCreateInfoAMD;
+
+
+
#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"
@@ -8730,30 +8862,82 @@
#endif
#define VK_EXT_pci_bus_info 1
-#define VK_EXT_PCI_BUS_INFO_SPEC_VERSION 1
+#define VK_EXT_PCI_BUS_INFO_SPEC_VERSION 2
#define VK_EXT_PCI_BUS_INFO_EXTENSION_NAME "VK_EXT_pci_bus_info"
typedef struct VkPhysicalDevicePCIBusInfoPropertiesEXT {
VkStructureType sType;
void* pNext;
- uint16_t pciDomain;
- uint8_t pciBus;
- uint8_t pciDevice;
- uint8_t pciFunction;
+ uint32_t pciDomain;
+ uint32_t pciBus;
+ uint32_t pciDevice;
+ uint32_t pciFunction;
} VkPhysicalDevicePCIBusInfoPropertiesEXT;
+#define VK_EXT_fragment_density_map 1
+#define VK_EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION 1
+#define VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME "VK_EXT_fragment_density_map"
+
+typedef struct VkPhysicalDeviceFragmentDensityMapFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 fragmentDensityMap;
+ VkBool32 fragmentDensityMapDynamic;
+ VkBool32 fragmentDensityMapNonSubsampledImages;
+} VkPhysicalDeviceFragmentDensityMapFeaturesEXT;
+
+typedef struct VkPhysicalDeviceFragmentDensityMapPropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkExtent2D minFragmentDensityTexelSize;
+ VkExtent2D maxFragmentDensityTexelSize;
+ VkBool32 fragmentDensityInvocations;
+} VkPhysicalDeviceFragmentDensityMapPropertiesEXT;
+
+typedef struct VkRenderPassFragmentDensityMapCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkAttachmentReference fragmentDensityMapAttachment;
+} VkRenderPassFragmentDensityMapCreateInfoEXT;
+
+
+
+#define VK_EXT_scalar_block_layout 1
+#define VK_EXT_SCALAR_BLOCK_LAYOUT_SPEC_VERSION 1
+#define VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME "VK_EXT_scalar_block_layout"
+
+typedef struct VkPhysicalDeviceScalarBlockLayoutFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 scalarBlockLayout;
+} VkPhysicalDeviceScalarBlockLayoutFeaturesEXT;
+
+
+
#define VK_GOOGLE_hlsl_functionality1 1
-#define VK_GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION 0
+#define VK_GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION 1
#define VK_GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME "VK_GOOGLE_hlsl_functionality1"
#define VK_GOOGLE_decorate_string 1
-#define VK_GOOGLE_DECORATE_STRING_SPEC_VERSION 0
+#define VK_GOOGLE_DECORATE_STRING_SPEC_VERSION 1
#define VK_GOOGLE_DECORATE_STRING_EXTENSION_NAME "VK_GOOGLE_decorate_string"
+#define VK_EXT_separate_stencil_usage 1
+#define VK_EXT_SEPARATE_STENCIL_USAGE_SPEC_VERSION 1
+#define VK_EXT_SEPARATE_STENCIL_USAGE_EXTENSION_NAME "VK_EXT_separate_stencil_usage"
+
+typedef struct VkImageStencilUsageCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkImageUsageFlags stencilUsage;
+} VkImageStencilUsageCreateInfoEXT;
+
+
+
#ifdef __cplusplus
}
#endif
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 7eaf7b2..fed8481 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -39,6 +39,9 @@
"-Wno-switch-enum",
"-Wno-undef",
+ // Have clang emit complete debug_info.
+ "-fstandalone-debug",
+
//"-DLOG_NDEBUG=0",
],
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index 009b257..ba4cf00 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -139,12 +139,12 @@
auto app_namespace = android::GraphicsEnv::getInstance().getAppNamespace();
if (app_namespace &&
!android::base::StartsWith(path_, kSystemLayerLibraryDir)) {
- std::string error_msg;
- dlhandle_ = OpenNativeLibrary(
+ char* error_msg = nullptr;
+ dlhandle_ = OpenNativeLibraryInNamespace(
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());
+ ALOGE("failed to load layer library '%s': %s", path_.c_str(), error_msg);
+ android::NativeLoaderFreeErrorMessage(error_msg);
refcount_ = 0;
return false;
}
@@ -165,9 +165,10 @@
std::lock_guard<std::mutex> lock(mutex_);
if (--refcount_ == 0) {
ALOGV("closing layer library '%s'", path_.c_str());
- std::string error_msg;
+ char* error_msg = nullptr;
if (!android::CloseNativeLibrary(dlhandle_, native_bridge_, &error_msg)) {
- ALOGE("failed to unload library '%s': %s", path_.c_str(), error_msg.c_str());
+ ALOGE("failed to unload library '%s': %s", path_.c_str(), error_msg);
+ android::NativeLoaderFreeErrorMessage(error_msg);
refcount_++;
} else {
dlhandle_ = nullptr;
diff --git a/vulkan/libvulkan/layers_extensions.h b/vulkan/libvulkan/layers_extensions.h
index 1dae456..9e2ff5b 100644
--- a/vulkan/libvulkan/layers_extensions.h
+++ b/vulkan/libvulkan/layers_extensions.h
@@ -33,6 +33,7 @@
LayerRef& operator=(const LayerRef&) = delete;
// provides bool-like behavior
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator const Layer*() const { return layer_; }
PFN_vkGetInstanceProcAddr GetGetInstanceProcAddr() const;