Merge "SF: Import ring buffer with size control in SurfaceTracing"
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 1855d26..6a9007c 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -34,23 +34,21 @@
# made today requires touching the same file, just copy the old
# touch step and add it to the end of the list.
#
-# *****************************************************************
-# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THE BANNER
-# *****************************************************************
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
# For example:
#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
$(call add-clean-step, find $(PRODUCT_OUT) -type f -name "libdvr.so" -print0 | xargs -0 rm -f)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libdvr_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libdvr_intermediates)
$(call add-clean-step, find $(PRODUCT_OUT) -type f -name "libgui*" -print0 | xargs -0 rm -f)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libgui_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libgui_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/thermalserviced)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/init/thermalservice.rc)
-# ******************************************************************
-# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
-# ******************************************************************
+$(call add-clean-step, find $(PRODUCT_OUT) -type f -name "gpuservice*" -print0 | xargs -0 rm -f)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/gpuservice_intermediates)
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..d91184a
--- /dev/null
+++ b/cmds/cmd/Android.bp
@@ -0,0 +1,18 @@
+cc_binary {
+ name: "cmd",
+
+ srcs: ["cmd.cpp"],
+
+ 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/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index 71658d8..0ee6c3a 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -24,10 +24,31 @@
#include "DumpstateInternal.h"
+using android::base::StringPrintf;
+
namespace android {
namespace os {
namespace {
+
+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()));
+}
+
+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()));
+}
+
+static void* callAndNotify(void* data) {
+ Dumpstate& ds = *static_cast<Dumpstate*>(data);
+ // TODO(111441001): Return status on listener.
+ ds.Run();
+ MYLOGE("Finished Run()\n");
+ return nullptr;
+}
+
class DumpstateToken : public BnDumpstateToken {};
}
@@ -77,10 +98,30 @@
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.
+binder::Status DumpstateService::startBugreport(int, int bugreport_mode, int32_t* returned_id) {
+ // TODO(111441001): return a request id here.
*returned_id = -1;
+ 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) {
+ return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
+ StringPrintf("Invalid bugreport mode: %d", bugreport_mode));
+ }
+
+ std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
+ options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode));
+ ds_.SetOptions(std::move(options));
+
+ pthread_t thread;
+ status_t err = pthread_create(&thread, nullptr, callAndNotify, &ds_);
+ if (err != 0) {
+ return error(err, "Could not create a background thread.");
+ }
return binder::Status::ok();
}
diff --git a/cmds/dumpstate/DumpstateService.h b/cmds/dumpstate/DumpstateService.h
index 131aff3..58095b3 100644
--- a/cmds/dumpstate/DumpstateService.h
+++ b/cmds/dumpstate/DumpstateService.h
@@ -41,8 +41,7 @@
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(int fd, int bugreport_mode, int32_t* returned_id) override;
private:
Dumpstate& ds_;
diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
index 68a4f21..9e59f58 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
@@ -39,10 +39,27 @@
IDumpstateToken setListener(@utf8InCpp String name, IDumpstateListener listener,
boolean getSectionDetails);
+ // These modes encapsulate a set of run time options for generating bugreports.
+ // A zipped bugreport; default mode.
+ 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;
+
/*
- * Starts a bugreport in a child process.
- *
- * Returns an identifier of the bugreport process running in the background.
+ * Starts a bugreport in the background.
*/
- int startBugreport(int fd, IDumpstateListener listener, in DumpstateOptions options);
+ int startBugreport(int fd, int bugreportMode);
}
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 1a45436..72d1de9 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1917,7 +1917,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);
@@ -1940,37 +1940,95 @@
}
}
-// 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";
+ }
+}
+
+static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options) {
+ 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;
+ }
+}
+
+static Dumpstate::BugreportMode getBugreportModeFromProperty() {
+ // If the system property is not set, it's assumed to be a full bugreport.
+ Dumpstate::BugreportMode mode = Dumpstate::BugreportMode::BUGREPORT_FULL;
+
+ 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 == "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()) {
@@ -1988,6 +2046,40 @@
}
}
+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("use_outfile: %s\n", options.use_outfile.c_str());
+ 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) {
+ // 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;
+
+ // STOPSHIP b/111441001: Remove hardcoded output file path; accept fd.
+ use_outfile = "/data/user_de/0/com.android.shell/files/bugreports/bugreport";
+
+ extra_options = ModeToString(bugreport_mode);
+ SetOptionsFromMode(bugreport_mode, this);
+}
+
Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
RunStatus status = RunStatus::OK;
int c;
@@ -2052,11 +2144,16 @@
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() {
+ if (!options_->ValidateOptions()) {
+ MYLOGE("Invalid options specified\n");
+ LogDumpOptions(*options_);
return RunStatus::INVALID_INPUT;
}
- options_ = std::move(options);
/* set as high priority, and protect from OOM killer */
setpriority(PRIO_PROCESS, 0, -20);
@@ -2278,7 +2375,8 @@
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));
+ status = ds.Run();
}
switch (status) {
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index c2f7f6a..5e7f71d 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -27,6 +27,7 @@
#include <android-base/macros.h>
#include <android-base/unique_fd.h>
+#include <android/os/IDumpstate.h>
#include <android/os/IDumpstateListener.h>
#include <utils/StrongPointer.h>
#include <ziparchive/zip_writer.h>
@@ -42,6 +43,9 @@
// TODO: and then remove explicitly android::os::dumpstate:: prefixes
namespace android {
namespace os {
+
+struct DumpstateOptions;
+
namespace dumpstate {
class DumpstateTest;
@@ -185,6 +189,16 @@
public:
enum RunStatus { OK, HELP, INVALID_INPUT, ERROR };
+ // 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
+ };
+
static android::os::dumpstate::CommandOptions DEFAULT_DUMPSYS;
static Dumpstate& GetInstance();
@@ -294,8 +308,11 @@
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();
+
+ /* Sets runtime options. */
+ void SetOptions(std::unique_ptr<DumpOptions> options);
// TODO: add other options from DumpState.
/*
@@ -317,6 +334,7 @@
// Whether progress updates should be published.
bool do_progress_updates = false;
std::string use_outfile;
+ // TODO: rename to MODE.
// Extra options passed as system property.
std::string extra_options;
// Command-line arguments as string
@@ -328,6 +346,9 @@
/* 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);
+
/* Returns true if the options set so far are consistent. */
bool ValidateOptions() const;
};
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 2cb9800..9ca894d 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -159,10 +159,11 @@
};
// clang-format on
- Dumpstate::DumpOptions options;
Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
EXPECT_EQ(status, Dumpstate::RunStatus::OK);
+
+ // These correspond to bugreport_mode = full, because that's the default.
EXPECT_FALSE(options_.do_add_date);
EXPECT_FALSE(options_.do_zip_file);
EXPECT_EQ("", options_.use_outfile);
@@ -170,10 +171,10 @@
EXPECT_FALSE(options_.use_control_socket);
EXPECT_FALSE(options_.show_header_only);
EXPECT_TRUE(options_.do_vibrate);
- EXPECT_FALSE(options_.do_fb);
+ EXPECT_TRUE(options_.do_fb);
EXPECT_FALSE(options_.do_progress_updates);
EXPECT_FALSE(options_.is_remote_mode);
- EXPECT_FALSE(options_.do_broadcast);
+ EXPECT_TRUE(options_.do_broadcast);
}
TEST_F(DumpOptionsTest, InitializePartial1) {
@@ -202,10 +203,10 @@
// Other options retain default values
EXPECT_FALSE(options_.show_header_only);
EXPECT_TRUE(options_.do_vibrate);
- EXPECT_FALSE(options_.do_fb);
+ EXPECT_TRUE(options_.do_fb);
EXPECT_FALSE(options_.do_progress_updates);
EXPECT_FALSE(options_.is_remote_mode);
- EXPECT_FALSE(options_.do_broadcast);
+ EXPECT_TRUE(options_.do_broadcast);
}
TEST_F(DumpOptionsTest, InitializePartial2) {
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 4ad5c4b..6cbb691 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() {
diff --git a/include/input/IInputFlinger.h b/include/input/IInputFlinger.h
index 11bb721..1ef8986 100644
--- a/include/input/IInputFlinger.h
+++ b/include/input/IInputFlinger.h
@@ -22,6 +22,9 @@
#include <binder/IInterface.h>
+#include <utils/Vector.h>
+#include <input/InputWindow.h>
+
namespace android {
/*
@@ -31,6 +34,8 @@
class IInputFlinger : public IInterface {
public:
DECLARE_META_INTERFACE(InputFlinger)
+
+ virtual void setInputWindows(const Vector<InputWindowInfo>& inputHandles) = 0;
};
@@ -40,7 +45,7 @@
class BnInputFlinger : public BnInterface<IInputFlinger> {
public:
enum {
- DO_SOMETHING_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
+ SET_INPUT_WINDOWS_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
};
virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/include/input/Input.h b/include/input/Input.h
index 819a89f..d35354b 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -17,6 +17,8 @@
#ifndef _LIBINPUT_INPUT_H
#define _LIBINPUT_INPUT_H
+#pragma GCC system_header
+
/**
* Native input event structures.
*/
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 4782c9b..d906db3 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -17,6 +17,8 @@
#ifndef _LIBINPUT_INPUT_TRANSPORT_H
#define _LIBINPUT_INPUT_TRANSPORT_H
+#pragma GCC system_header
+
/**
* Native input transport.
*
@@ -29,6 +31,7 @@
#include <string>
+#include <binder/IBinder.h>
#include <input/Input.h>
#include <utils/Errors.h>
#include <utils/Timers.h>
@@ -188,11 +191,16 @@
status_t write(Parcel& out) const;
status_t read(const Parcel& from);
+ sp<IBinder> getToken() const;
+ void setToken(const sp<IBinder>& token);
+
private:
void setFd(int fd);
std::string mName;
int mFd = -1;
+
+ sp<IBinder> mToken = nullptr;
};
/*
diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h
index 918b9e1..9e3d334 100644
--- a/include/input/InputWindow.h
+++ b/include/input/InputWindow.h
@@ -33,6 +33,9 @@
* Describes the properties of a window that can receive input.
*/
struct InputWindowInfo {
+ InputWindowInfo() = default;
+ InputWindowInfo(const Parcel& from);
+
// Window flags from WindowManager.LayoutParams
enum {
FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001,
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 7a47724..f0c21f5 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -387,23 +387,28 @@
return mStrictModePolicy;
}
-uid_t IPCThreadState::setWorkSource(uid_t uid)
+int64_t IPCThreadState::setCallingWorkSourceUid(uid_t uid)
{
- uid_t returnValue = mWorkSource;
+ // Note: we currently only use half of the int64. We return an int64 for extensibility.
+ int64_t token = mWorkSource;
mWorkSource = uid;
- return returnValue;
+ return token;
}
-uid_t IPCThreadState::getWorkSource() const
+uid_t IPCThreadState::getCallingWorkSourceUid() const
{
return mWorkSource;
}
-uid_t IPCThreadState::clearWorkSource()
+int64_t IPCThreadState::clearCallingWorkSource()
{
- uid_t returnValue = mWorkSource;
- mWorkSource = kUnsetWorkSource;
- return returnValue;
+ return setCallingWorkSourceUid(kUnsetWorkSource);
+}
+
+void IPCThreadState::restoreCallingWorkSource(int64_t token)
+{
+ uid_t uid = (int)token;
+ setCallingWorkSourceUid(uid);
}
void IPCThreadState::setLastTransactionBinderFlags(int32_t flags)
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 532f7f1..643f428 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -601,7 +601,7 @@
{
writeInt32(IPCThreadState::self()->getStrictModePolicy() |
STRICT_MODE_PENALTY_GATHER);
- writeInt32(IPCThreadState::self()->getWorkSource());
+ writeInt32(IPCThreadState::self()->getCallingWorkSourceUid());
// currently the interface identification token is just its name as a string
return writeString16(interface);
}
@@ -631,7 +631,7 @@
}
// WorkSource.
int32_t workSource = readInt32();
- threadState->setWorkSource(workSource);
+ threadState->setCallingWorkSourceUid(workSource);
// Interface descriptor.
const String16 str(readString16());
if (str == interface) {
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 5888e14..de126d5 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -47,12 +47,14 @@
void setStrictModePolicy(int32_t policy);
int32_t getStrictModePolicy() const;
- // See Binder#setThreadWorkSource in Binder.java.
- uid_t setWorkSource(uid_t uid);
- // See Binder#getThreadWorkSource in Binder.java.
- uid_t getWorkSource() const;
- // See Binder#clearThreadWorkSource in Binder.java.
- uid_t clearWorkSource();
+ // See Binder#setCallingWorkSourceUid in Binder.java.
+ int64_t setCallingWorkSourceUid(uid_t uid);
+ // See Binder#getCallingWorkSourceUid in Binder.java.
+ uid_t getCallingWorkSourceUid() const;
+ // See Binder#clearCallingWorkSource in Binder.java.
+ int64_t clearCallingWorkSource();
+ // See Binder#restoreCallingWorkSource in Binder.java.
+ void restoreCallingWorkSource(int64_t token);
void setLastTransactionBinderFlags(int32_t flags);
int32_t getLastTransactionBinderFlags() const;
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index d16502f..14ce4cb 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -39,6 +39,8 @@
"libutils",
],
+ cpp_std: "c++17",
+
version_script: "libbinder_ndk.map.txt",
}
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 5c26039..e2c0cfa 100644
--- a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
@@ -198,6 +198,11 @@
* See AStatus_isOk.
*/
bool isOk() { return get() != nullptr && AStatus_isOk(get()); }
+
+ /**
+ * Convenience method for okay status.
+ */
+ static ScopedAStatus ok() { return ScopedAStatus(AStatus_newOk()); }
};
/**
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
index 4ee1b67..3594349 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -55,9 +55,9 @@
/**
* 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. 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.
+ * 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.
*
@@ -65,31 +65,35 @@
*
* \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 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 char* (*AParcel_stringAllocator)(void* stringData, size_t length);
+typedef bool (*AParcel_stringAllocator)(void* stringData, int32_t length, char** buffer);
/**
- * This is called to allocate an array of size 'length'.
+ * 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
+ * \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, size_t length);
+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. 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.
+ * 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
*
@@ -97,10 +101,13 @@
* \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 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 char* (*AParcel_stringArrayElementAllocator)(void* arrayData, size_t index, size_t length);
+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.
@@ -110,10 +117,11 @@
* \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.
+ * 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.
+ * 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,
size_t* outLength);
@@ -124,109 +132,127 @@
*
* 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 a buffer of int32_t of size 'length'.
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
*/
-typedef int32_t* (*AParcel_int32ArrayAllocator)(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 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 a buffer of uint32_t of size 'length'.
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
*/
-typedef uint32_t* (*AParcel_uint32ArrayAllocator)(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 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 a buffer of int64_t of size 'length'.
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
*/
-typedef int64_t* (*AParcel_int64ArrayAllocator)(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 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 a buffer of uint64_t of size 'length'.
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
*/
-typedef uint64_t* (*AParcel_uint64ArrayAllocator)(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 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 a buffer of float of size 'length'.
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
*/
-typedef float* (*AParcel_floatArrayAllocator)(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 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 a buffer of double of size 'length'.
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
*/
-typedef double* (*AParcel_doubleArrayAllocator)(void* arrayData, size_t length);
+typedef bool (*AParcel_doubleArrayAllocator)(void* arrayData, int32_t length, double** outBuffer);
/**
* This allocates an array of size 'length' inside of arrayData and returns whether or not there was
- * a success.
+ * 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.
+ * \param length the length to allocate arrayData to (or -1 if this represents a null array).
*
* \return whether the allocation succeeded.
*/
-typedef bool (*AParcel_boolArrayAllocator)(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.
@@ -256,32 +282,38 @@
*
* 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 a buffer of char16_t of size 'length'.
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
*/
-typedef char16_t* (*AParcel_charArrayAllocator)(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 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 a buffer of int8_t of size 'length'.
+ * \return whether or not the allocation was successful (or whether a null array is represented when
+ * length is -1).
*/
-typedef int8_t* (*AParcel_byteArrayAllocator)(void* arrayData, size_t length);
+typedef bool (*AParcel_byteArrayAllocator)(void* arrayData, int32_t length, int8_t** outBuffer);
// @END-PRIMITIVE-VECTOR-GETTERS
@@ -297,12 +329,11 @@
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 will not be null on
- * success.
+ * \param binder the out parameter for what is read from the parcel. This may be null.
*
* \return STATUS_OK on successful write.
*/
@@ -310,26 +341,13 @@
__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.
- *
- * \param parcel the parcel to read from.
- * \param binder the out parameter for what is read from the parcel. This may be null even on
- * success.
- *
- * \return STATUS_OK on successful write.
- */
-binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder** binder)
- __INTRODUCED_IN(29);
-
-/**
* 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.
+ * \param fd the value to write to the parcel (-1 to represent a null ParcelFileDescriptor).
*
* \return STATUS_OK on successful write.
*/
@@ -343,7 +361,8 @@
* This corresponds to the SDK's android.os.ParcelFileDescriptor.
*
* \param parcel the parcel to read from.
- * \param binder the out parameter for what is read from the parcel.
+ * \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.
*/
@@ -381,13 +400,15 @@
/**
* 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);
/**
@@ -395,7 +416,8 @@
*
* 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.
@@ -411,7 +433,8 @@
*
* 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.
+ * 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.
@@ -421,7 +444,7 @@
*
* \return STATUS_OK on successful write.
*/
-binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData, size_t length,
+binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData, int32_t length,
AParcel_stringArrayElementGetter getter)
__INTRODUCED_IN(29);
@@ -432,7 +455,8 @@
* 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.
+ * 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.
@@ -633,72 +657,72 @@
* 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'.
- * \param length the length of arrayData.
+ * \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* arrayData, 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'.
- * \param length the length of arrayData.
+ * \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* arrayData, 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'.
- * \param length the length of arrayData.
+ * \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* arrayData, 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'.
- * \param length the length of arrayData.
+ * \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* arrayData, 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'.
- * \param length the length of arrayData.
+ * \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* arrayData, 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'.
- * \param length the length of arrayData.
+ * \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* arrayData, size_t length)
+binder_status_t AParcel_writeDoubleArray(AParcel* parcel, const double* arrayData, int32_t length)
__INTRODUCED_IN(29);
/**
@@ -709,36 +733,36 @@
*
* \param parcel the parcel to write to.
* \param arrayData some external representation of an array.
- * \param length the length of arrayData.
+ * \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, size_t length,
+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'.
- * \param length the length of arrayData.
+ * \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* arrayData, 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'.
- * \param length the length of arrayData.
+ * \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* arrayData, size_t length)
+binder_status_t AParcel_writeByteArray(AParcel* parcel, const int8_t* arrayData, int32_t length)
__INTRODUCED_IN(29);
/**
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 2ccbe5a..f99c3a9 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
@@ -26,8 +26,10 @@
#pragma once
+#include <android/binder_auto_utils.h>
#include <android/binder_parcel.h>
+#include <optional>
#include <string>
#include <vector>
@@ -37,12 +39,37 @@
* 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 (length > vec->max_size()) return false;
vec->resize(length);
- return vec->data();
+ *outBuffer = vec->data();
+ return true;
+}
+
+/**
+ * This retrieves and allocates a vector to size 'length' and returns the underlying buffer.
+ */
+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 (length > (*vec)->max_size()) return false;
+ (*vec)->resize(length);
+
+ *outBuffer = (*vec)->data();
+ return true;
}
/**
@@ -50,13 +77,16 @@
*
* 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.
+ * 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, size_t length) {
+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 (length > vec->max_size()) return false;
@@ -65,6 +95,34 @@
}
/**
+ * 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 (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.
*/
@@ -84,166 +142,156 @@
(*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), vec.size(),
- AParcel_stdVectorGetter<bool>);
-}
-
-/**
- * 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>);
-}
-
-/**
- * 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 std::string inside of a std::vector<std::string> at index index to size 'length'.
+ * 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 char* AParcel_stdVectorStringElementAllocator(void* vectorData, size_t index,
- size_t length) {
- std::vector<std::string>* vec = static_cast<std::vector<std::string>*>(vectorData);
+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);
- element.resize(length - 1);
- return &element[0];
+ return AParcel_stdStringAllocator(static_cast<void*>(&element), length, buffer);
}
/**
@@ -253,7 +301,6 @@
static inline const char* AParcel_stdVectorStringElementGetter(const void* vectorData, size_t index,
size_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();
@@ -261,6 +308,40 @@
}
/**
+ * 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,
+ size_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();
+}
+
+/**
* Convenience API for writing a std::string.
*/
static inline binder_status_t AParcel_writeString(AParcel* parcel, const std::string& str) {
@@ -276,6 +357,27 @@
}
/**
+ * 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,
@@ -297,6 +399,334 @@
}
/**
+ * 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);
+}
+
+// @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>
@@ -309,6 +739,23 @@
}
/**
+ * 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>
@@ -323,6 +770,28 @@
return STATUS_OK;
}
+/**
+ * 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);
+
+ 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/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 7a75942..41df90b 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -39,7 +39,6 @@
AParcel_readInt32Array;
AParcel_readInt64;
AParcel_readInt64Array;
- AParcel_readNullableStrongBinder;
AParcel_readParcelFileDescriptor;
AParcel_readStatusHeader;
AParcel_readString;
diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index 8e5b477..3c32100 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -36,28 +36,46 @@
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);
@@ -67,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]);
@@ -96,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;
@@ -123,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;
@@ -142,15 +163,16 @@
}
template <typename T>
-binder_status_t WriteArray(AParcel* parcel, const void* arrayData, size_t length,
+binder_status_t WriteArray(AParcel* parcel, const void* arrayData, int32_t length,
ArrayGetter<T> getter, status_t (Parcel::*write)(T)) {
- if (length > std::numeric_limits<int32_t>::max()) return STATUS_BAD_VALUE;
+ // 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++) {
status = (rawParcel->*write)(getter(arrayData, i));
@@ -169,10 +191,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;
if (!allocator(arrayData, length)) return STATUS_NO_MEMORY;
+ if (length <= 0) return STATUS_OK;
+
for (size_t i = 0; i < length; i++) {
T readTarget;
status = (rawParcel->*read)(&readTarget);
@@ -194,17 +218,6 @@
}
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);
@@ -216,23 +229,39 @@
}
binder_status_t AParcel_writeParcelFileDescriptor(AParcel* parcel, int fd) {
- ParcelFileDescriptor parcelFd((unique_fd(fd)));
+ std::unique_ptr<ParcelFileDescriptor> parcelFd;
- status_t status = parcel->get()->writeParcelable(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
- (void)parcelFd.release().release();
+ if (parcelFd != nullptr) {
+ (void)parcelFd->release().release();
+ }
return PruneStatusT(status);
}
binder_status_t AParcel_readParcelFileDescriptor(const AParcel* parcel, int* fd) {
- ParcelFileDescriptor parcelFd;
- // status_t status = parcelFd.readFromParcel(parcel->get());
+ std::unique_ptr<ParcelFileDescriptor> parcelFd;
+
status_t status = parcel->get()->readParcelable(&parcelFd);
if (status != STATUS_OK) return PruneStatusT(status);
- *fd = parcelFd.release().release();
+ if (parcelFd) {
+ *fd = parcelFd->release().release();
+ } else {
+ *fd = -1;
+ }
+
return STATUS_OK;
}
@@ -248,9 +277,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()) {
@@ -279,7 +322,10 @@
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;
}
@@ -296,9 +342,10 @@
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;
}
@@ -308,19 +355,18 @@
return STATUS_OK;
}
-binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData, size_t length,
+binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData, int32_t length,
AParcel_stringArrayElementGetter getter) {
- 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);
+ // 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 (size_t i = 0; i < length; i++) {
size_t length = 0;
const char* str = getter(arrayData, i, &length);
- if (str == nullptr) return STATUS_BAD_VALUE;
+ if (str == nullptr && length != -1) return STATUS_BAD_VALUE;
binder_status_t status = AParcel_writeString(parcel, str, length);
if (status != STATUS_OK) return status;
@@ -336,10 +382,10 @@
size_t index; // index into the string array
AParcel_stringArrayElementAllocator elementAllocator;
- static char* Allocator(void* stringData, size_t length) {
+ static bool Allocator(void* stringData, int32_t length, char** buffer) {
StringArrayElementAllocationAdapter* adapter =
static_cast<StringArrayElementAllocationAdapter*>(stringData);
- return adapter->elementAllocator(adapter->arrayData, adapter->index, length);
+ return adapter->elementAllocator(adapter->arrayData, adapter->index, length, buffer);
}
};
@@ -352,10 +398,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;
if (!allocator(arrayData, length)) return STATUS_NO_MEMORY;
+ if (length == -1) return STATUS_OK; // null string array
+
StringArrayElementAllocationAdapter adapter{
.arrayData = arrayData,
.index = 0,
@@ -363,8 +411,10 @@
};
for (; adapter.index < length; adapter.index++) {
- AParcel_readString(parcel, static_cast<void*>(&adapter),
- StringArrayElementAllocationAdapter::Allocator);
+ binder_status_t status = AParcel_readString(parcel, static_cast<void*>(&adapter),
+ StringArrayElementAllocationAdapter::Allocator);
+
+ if (status != STATUS_OK) return status;
}
return STATUS_OK;
@@ -463,42 +513,42 @@
return PruneStatusT(status);
}
-binder_status_t AParcel_writeInt32Array(AParcel* parcel, const int32_t* arrayData, size_t 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* arrayData,
- size_t length) {
+ int32_t length) {
return WriteArray<uint32_t>(parcel, arrayData, length);
}
-binder_status_t AParcel_writeInt64Array(AParcel* parcel, const int64_t* arrayData, size_t 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* arrayData,
- size_t length) {
+ int32_t length) {
return WriteArray<uint64_t>(parcel, arrayData, length);
}
-binder_status_t AParcel_writeFloatArray(AParcel* parcel, const float* arrayData, size_t 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* arrayData, size_t 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, size_t length,
+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* arrayData, size_t 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* arrayData, size_t length) {
+binder_status_t AParcel_writeByteArray(AParcel* parcel, const int8_t* arrayData, int32_t length) {
return WriteArray<int8_t>(parcel, arrayData, length);
}
diff --git a/libs/binder/ndk/scripts/gen_parcel_helper.py b/libs/binder/ndk/scripts/gen_parcel_helper.py
index bb76254..8f587d2 100755
--- a/libs/binder/ndk/scripts/gen_parcel_helper.py
+++ b/libs/binder/ndk/scripts/gen_parcel_helper.py
@@ -99,8 +99,8 @@
for pretty, cpp in data_types:
nca = pretty in non_contiguously_addressable
- arg_types = "const " + cpp + "* arrayData, size_t length"
- if nca: arg_types = "const void* arrayData, size_t length, AParcel_" + pretty.lower() + "ArrayGetter getter"
+ 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
@@ -114,11 +114,11 @@
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.\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'.\n"
- header += " * \\param length the length of arrayData.\n"
+ 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"
@@ -139,16 +139,16 @@
if nca:
pre_header += "/**\n"
pre_header += " * This allocates an array of size 'length' inside of arrayData and returns whether or not there was "
- pre_header += "a success.\n"
+ 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.\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"
@@ -178,16 +178,18 @@
pre_header += " *\n"
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 a buffer of " + cpp + " of size 'length'.\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")]
@@ -232,6 +234,16 @@
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"
cpp_helper += " * Reads a 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::vector<" + cpp + ">* vec) {\n"
@@ -247,6 +259,22 @@
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/test/Android.bp b/libs/binder/ndk/test/Android.bp
index b29b6e7..67481cf 100644
--- a/libs/binder/ndk/test/Android.bp
+++ b/libs/binder/ndk/test/Android.bp
@@ -22,6 +22,7 @@
strip: {
none: true,
},
+ cpp_std: "c++17",
cflags: [
"-O0",
"-g",
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 7bcfffd..22c1bad 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -953,7 +953,7 @@
{
status_t ret;
Parcel data, reply;
- uid_t previousWorkSource = IPCThreadState::self()->setWorkSource(100);
+ int64_t previousWorkSource = IPCThreadState::self()->setCallingWorkSourceUid(100);
data.writeInterfaceToken(binderLibTestServiceName);
ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply);
EXPECT_EQ(100, reply.readInt32());
@@ -966,8 +966,8 @@
status_t ret;
Parcel data, reply;
- IPCThreadState::self()->setWorkSource(100);
- uid_t previousWorkSource = IPCThreadState::self()->clearWorkSource();
+ IPCThreadState::self()->setCallingWorkSourceUid(100);
+ int64_t previousWorkSource = IPCThreadState::self()->clearCallingWorkSource();
data.writeInterfaceToken(binderLibTestServiceName);
ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply);
@@ -976,6 +976,22 @@
EXPECT_EQ(NO_ERROR, ret);
}
+TEST_F(BinderLibTest, WorkSourceRestored)
+{
+ status_t ret;
+ Parcel data, reply;
+
+ IPCThreadState::self()->setCallingWorkSourceUid(100);
+ int64_t token = IPCThreadState::self()->clearCallingWorkSource();
+ IPCThreadState::self()->restoreCallingWorkSource(token);
+
+ data.writeInterfaceToken(binderLibTestServiceName);
+ ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply);
+
+ EXPECT_EQ(100, reply.readInt32());
+ EXPECT_EQ(NO_ERROR, ret);
+}
+
class BinderLibTestService : public BBinder
{
public:
@@ -1276,7 +1292,7 @@
}
case BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION: {
data.enforceInterface(binderLibTestServiceName);
- reply->writeInt32(IPCThreadState::self()->getWorkSource());
+ reply->writeInt32(IPCThreadState::self()->getCallingWorkSourceUid());
return NO_ERROR;
}
default:
diff --git a/libs/binder/tests/binderValueTypeTest.cpp b/libs/binder/tests/binderValueTypeTest.cpp
index c8f4697..15949d4 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>
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 7677c3a..127fcd6 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -135,6 +135,7 @@
"libutils",
"libnativewindow",
"liblog",
+ "libinput",
"libhidlbase",
"libhidltransport",
"android.hidl.token@1.0-utils",
@@ -146,7 +147,7 @@
// bufferhub is not used when building libgui for vendors
target: {
vendor: {
- cflags: ["-DNO_BUFFERHUB"],
+ cflags: ["-DNO_BUFFERHUB", "-DNO_INPUT"],
exclude_srcs: [
"BufferHubConsumer.cpp",
"BufferHubProducer.cpp",
@@ -155,6 +156,7 @@
"libbufferhub",
"libbufferhubqueue",
"libpdx_default_transport",
+ "libinput"
],
},
},
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 7b71b39..9f30060 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -50,6 +50,9 @@
output.writeFloat(color.r);
output.writeFloat(color.g);
output.writeFloat(color.b);
+#ifndef NO_INPUT
+ inputInfo.write(output);
+#endif
output.write(transparentRegion);
output.writeUint32(transform);
output.writeBool(transformToDisplayInverse);
@@ -120,6 +123,11 @@
color.r = input.readFloat();
color.g = input.readFloat();
color.b = input.readFloat();
+
+#ifndef NO_INPUT
+ inputInfo = InputWindowInfo::read(input);
+#endif
+
input.read(transparentRegion);
transform = input.readUint32();
transformToDisplayInverse = input.readBool();
@@ -343,6 +351,13 @@
listenerCallbacks = other.listenerCallbacks;
}
+#ifndef NO_INPUT
+ if (other.what & eInputInfoChanged) {
+ what |= eInputInfoChanged;
+ inputInfo = other.inputInfo;
+ }
+#endif
+
if ((other.what & what) != other.what) {
ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? "
"other.what=0x%X what=0x%X",
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index e10bda4..87c6f27 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -42,6 +42,10 @@
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
+#ifndef NO_INPUT
+#include <input/InputWindow.h>
+#endif
+
#include <private/gui/ComposerService.h>
namespace android {
@@ -759,6 +763,21 @@
return *this;
}
+#ifndef NO_INPUT
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInputWindowInfo(
+ const sp<SurfaceControl>& sc,
+ const InputWindowInfo& info) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+ s->inputInfo = info;
+ s->what |= layer_state_t::eInputInfoChanged;
+ return *this;
+}
+#endif
+
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::destroySurface(
const sp<SurfaceControl>& sc) {
layer_state_t* s = getLayerState(sc);
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index ddbac7b..cdb2309 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -25,6 +25,11 @@
#include <gui/IGraphicBufferProducer.h>
#include <gui/ITransactionCompletedListener.h>
#include <math/mat4.h>
+
+#ifndef NO_INPUT
+#include <input/InputWindow.h>
+#endif
+
#include <math/vec3.h>
#include <ui/GraphicTypes.h>
#include <ui/Rect.h>
@@ -76,6 +81,7 @@
eSidebandStreamChanged = 0x08000000,
eColorTransformChanged = 0x10000000,
eListenerCallbacksChanged = 0x20000000,
+ eInputInfoChanged = 0x40000000,
};
layer_state_t()
@@ -158,6 +164,9 @@
mat4 colorTransform;
std::vector<ListenerCallbacks> listenerCallbacks;
+#ifndef NO_INPUT
+ InputWindowInfo inputInfo;
+#endif
};
struct ComposerState {
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 1cafb77..10c27b1 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -330,6 +330,10 @@
// freezing the total geometry of a surface until a resize is completed.
Transaction& setGeometryAppliesWithResize(const sp<SurfaceControl>& sc);
+#ifndef NO_INPUT
+ Transaction& setInputWindowInfo(const sp<SurfaceControl>& sc, const InputWindowInfo& info);
+#endif
+
Transaction& destroySurface(const sp<SurfaceControl>& sc);
// Set a color transform matrix on the given layer on the built-in display.
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 72558a6..8cb8649 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -43,12 +43,12 @@
target: {
android: {
srcs: [
- "IInputFlinger.cpp",
"InputTransport.cpp",
"VelocityControl.cpp",
"VelocityTracker.cpp",
"InputApplication.cpp",
- "InputWindow.cpp"
+ "InputWindow.cpp",
+ "IInputFlinger.cpp"
],
shared_libs: [
diff --git a/libs/input/IInputFlinger.cpp b/libs/input/IInputFlinger.cpp
index 003e73d..47a2c0c 100644
--- a/libs/input/IInputFlinger.cpp
+++ b/libs/input/IInputFlinger.cpp
@@ -23,7 +23,6 @@
#include <input/IInputFlinger.h>
-
namespace android {
class BpInputFlinger : public BpInterface<IInputFlinger> {
@@ -31,23 +30,35 @@
explicit BpInputFlinger(const sp<IBinder>& impl) :
BpInterface<IInputFlinger>(impl) { }
- virtual status_t doSomething() {
+ virtual void setInputWindows(const Vector<InputWindowInfo>& inputInfo) {
Parcel data, reply;
data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor());
- remote()->transact(BnInputFlinger::DO_SOMETHING_TRANSACTION, data, &reply);
- return reply.readInt32();
+
+ data.writeUint32(static_cast<uint32_t>(inputInfo.size()));
+ for (const auto& info : inputInfo) {
+ info.write(data);
+ }
+ remote()->transact(BnInputFlinger::SET_INPUT_WINDOWS_TRANSACTION, data, &reply);
}
};
IMPLEMENT_META_INTERFACE(InputFlinger, "android.input.IInputFlinger");
-
status_t BnInputFlinger::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
switch(code) {
- case DO_SOMETHING_TRANSACTION: {
+ case SET_INPUT_WINDOWS_TRANSACTION: {
CHECK_INTERFACE(IInputFlinger, data, reply);
- reply->writeInt32(0);
+ size_t count = data.readUint32();
+ if (count > data.dataSize()) {
+ return BAD_VALUE;
+ }
+ Vector<InputWindowInfo> handles;
+ handles.setCapacity(count);
+ for (size_t i = 0; i < count; i++) {
+ handles.add(InputWindowInfo(data));
+ }
+ setInputWindows(handles);
break;
}
default:
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 32444f9..e93f3a4 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -247,6 +247,10 @@
if (s != OK) {
return s;
}
+ s = out.writeStrongBinder(mToken);
+ if (s != OK) {
+ return s;
+ }
s = out.writeDupFileDescriptor(getFd());
@@ -255,6 +259,7 @@
status_t InputChannel::read(const Parcel& from) {
mName = from.readString8();
+ mToken = from.readStrongBinder();
int rawFd = from.readFileDescriptor();
setFd(::dup(rawFd));
@@ -266,6 +271,17 @@
return OK;
}
+sp<IBinder> InputChannel::getToken() const {
+ return mToken;
+}
+
+void InputChannel::setToken(const sp<IBinder>& token) {
+ if (mToken != nullptr) {
+ ALOGE("Assigning InputChannel (%s) a second handle?", mName.c_str());
+ }
+ mToken = token;
+}
+
// --- InputPublisher ---
InputPublisher::InputPublisher(const sp<InputChannel>& channel) :
diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp
index 6968661..f82437e 100644
--- a/libs/input/InputWindow.cpp
+++ b/libs/input/InputWindow.cpp
@@ -135,6 +135,10 @@
return ret;
}
+InputWindowInfo::InputWindowInfo(const Parcel& from) {
+ *this = read(from);
+}
+
// --- InputWindowHandle ---
InputWindowHandle::InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle) :
diff --git a/opengl/include/EGL/Platform.h b/opengl/include/EGL/Platform.h
index 624d31f..f2b501c 100644
--- a/opengl/include/EGL/Platform.h
+++ b/opengl/include/EGL/Platform.h
@@ -36,6 +36,7 @@
namespace angle
{
struct WorkaroundsD3D;
+struct FeaturesVk;
using TraceEventHandle = uint64_t;
using EGLDisplayType = void *;
struct PlatformMethods;
@@ -233,6 +234,13 @@
{
}
+using OverrideFeaturesVkFunc = void (*)(PlatformMethods *platform,
+ angle::FeaturesVk *workaroundsVulkan);
+inline void DefaultOverrideFeaturesVk(PlatformMethods *platform,
+ angle::FeaturesVk *workaroundsVulkan)
+{
+}
+
// Callback on a successful program link with the program binary. Can be used to store
// shaders to disk. Keys are a 160-bit SHA-1 hash.
using ProgramKeyType = std::array<uint8_t, 20>;
@@ -262,6 +270,7 @@
OP(histogramSparse, HistogramSparse) \
OP(histogramBoolean, HistogramBoolean) \
OP(overrideWorkaroundsD3D, OverrideWorkaroundsD3D) \
+ OP(overrideFeaturesVk, OverrideFeaturesVk) \
OP(cacheProgram, CacheProgram)
#define ANGLE_PLATFORM_METHOD_DEF(Name, CapsName) CapsName##Func Name = Default##CapsName;
diff --git a/services/bufferhub/Android.bp b/services/bufferhub/Android.bp
index 8b43333..28a7501 100644
--- a/services/bufferhub/Android.bp
+++ b/services/bufferhub/Android.bp
@@ -25,6 +25,7 @@
"BufferClient.cpp",
"BufferHubService.cpp",
"BufferNode.cpp",
+ "UniqueIdGenerator.cpp",
],
header_libs: [
"libbufferhub_headers",
diff --git a/services/bufferhub/BufferHubService.cpp b/services/bufferhub/BufferHubService.cpp
index 3bfd9cb..fc5ad1d 100644
--- a/services/bufferhub/BufferHubService.cpp
+++ b/services/bufferhub/BufferHubService.cpp
@@ -35,7 +35,7 @@
std::shared_ptr<BufferNode> node =
std::make_shared<BufferNode>(desc.width, desc.height, desc.layers, desc.format,
- desc.usage, userMetadataSize);
+ desc.usage, userMetadataSize, nodeIdGenerator.getId());
if (node == nullptr || !node->IsValid()) {
ALOGE("%s: creating BufferNode failed.", __FUNCTION__);
_hidl_cb(/*bufferClient=*/nullptr, /*status=*/BufferHubStatus::ALLOCATION_FAILED);
diff --git a/services/bufferhub/BufferNode.cpp b/services/bufferhub/BufferNode.cpp
index 53dd702..715d0a1 100644
--- a/services/bufferhub/BufferNode.cpp
+++ b/services/bufferhub/BufferNode.cpp
@@ -1,5 +1,6 @@
#include <errno.h>
+#include <bufferhub/BufferHubService.h>
#include <bufferhub/BufferNode.h>
#include <private/dvr/buffer_hub_defs.h>
#include <ui/GraphicBufferAllocator.h>
@@ -22,7 +23,8 @@
// Allocates a new BufferNode.
BufferNode::BufferNode(uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
- uint64_t usage, size_t user_metadata_size) {
+ uint64_t usage, size_t user_metadata_size, uint32_t id)
+ : mId(id) {
uint32_t out_stride = 0;
// graphicBufferId is not used in GraphicBufferAllocator::allocate
// TODO(b/112338294) After move to the service folder, stop using the
@@ -54,14 +56,23 @@
InitializeMetadata();
}
-// Free the handle
BufferNode::~BufferNode() {
+ // Free the handle
if (buffer_handle_ != nullptr) {
status_t ret = GraphicBufferAllocator::get().free(buffer_handle_);
if (ret != OK) {
ALOGE("%s: Failed to free handle; Got error: %d", __FUNCTION__, ret);
}
}
+
+ // Free the id, if valid
+ if (id() != UniqueIdGenerator::kInvalidId) {
+ if (nodeIdGenerator.freeId(id())) {
+ ALOGI("%s: id #%u is freed.", __FUNCTION__, id());
+ } else {
+ ALOGE("%s: Cannot free nonexistent id #%u", __FUNCTION__, id());
+ }
+ }
}
uint64_t BufferNode::GetActiveClientsBitMask() const {
diff --git a/services/bufferhub/UniqueIdGenerator.cpp b/services/bufferhub/UniqueIdGenerator.cpp
new file mode 100644
index 0000000..362a026
--- /dev/null
+++ b/services/bufferhub/UniqueIdGenerator.cpp
@@ -0,0 +1,55 @@
+/*
+ * 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 <bufferhub/UniqueIdGenerator.h>
+
+namespace android {
+namespace frameworks {
+namespace bufferhub {
+namespace V1_0 {
+namespace implementation {
+
+constexpr uint32_t UniqueIdGenerator::kInvalidId;
+
+uint32_t UniqueIdGenerator::getId() {
+ std::lock_guard<std::mutex> lock(mIdsInUseMutex);
+
+ do {
+ if (++mLastId >= std::numeric_limits<uint32_t>::max()) {
+ mLastId = kInvalidId + 1;
+ }
+ } while (mIdsInUse.find(mLastId) != mIdsInUse.end());
+
+ mIdsInUse.insert(mLastId);
+ return mLastId;
+}
+
+bool UniqueIdGenerator::freeId(uint32_t id) {
+ std::lock_guard<std::mutex> lock(mIdsInUseMutex);
+ auto iter = mIdsInUse.find(id);
+ if (iter != mIdsInUse.end()) {
+ mIdsInUse.erase(iter);
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace bufferhub
+} // namespace frameworks
+} // namespace android
diff --git a/services/bufferhub/include/bufferhub/BufferHubService.h b/services/bufferhub/include/bufferhub/BufferHubService.h
index dbbee8f..5441750 100644
--- a/services/bufferhub/include/bufferhub/BufferHubService.h
+++ b/services/bufferhub/include/bufferhub/BufferHubService.h
@@ -22,6 +22,7 @@
#include <android/frameworks/bufferhub/1.0/IBufferHub.h>
#include <bufferhub/BufferClient.h>
+#include <bufferhub/UniqueIdGenerator.h>
#include <utils/Mutex.h>
namespace android {
@@ -34,6 +35,8 @@
using hardware::Return;
using hardware::graphics::common::V1_2::HardwareBufferDescription;
+static UniqueIdGenerator nodeIdGenerator;
+
class BufferHubService : public IBufferHub {
public:
Return<void> allocateBuffer(const HardwareBufferDescription& description,
diff --git a/services/bufferhub/include/bufferhub/BufferNode.h b/services/bufferhub/include/bufferhub/BufferNode.h
index ffeacac..c490e7c 100644
--- a/services/bufferhub/include/bufferhub/BufferNode.h
+++ b/services/bufferhub/include/bufferhub/BufferNode.h
@@ -2,6 +2,7 @@
#define ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_NODE_H_
#include <android/hardware_buffer.h>
+#include <bufferhub/UniqueIdGenerator.h>
#include <ui/BufferHubMetadata.h>
namespace android {
@@ -14,13 +15,16 @@
public:
// Allocates a new BufferNode.
BufferNode(uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
- uint64_t usage, size_t user_metadata_size);
+ uint64_t usage, size_t user_metadata_size,
+ uint32_t id = UniqueIdGenerator::kInvalidId);
~BufferNode();
// Returns whether the object holds a valid metadata.
bool IsValid() const { return metadata_.IsValid(); }
+ uint32_t id() const { return mId; }
+
size_t user_metadata_size() const { return metadata_.user_metadata_size(); }
// Accessors of the buffer description and handle
@@ -59,6 +63,11 @@
// Metadata in shared memory.
BufferHubMetadata metadata_;
+ // A system-unique id generated by bufferhub from 1 to std::numeric_limits<uint32_t>::max().
+ // BufferNodes not created by bufferhub will have id = 0, meaning "not specified".
+ // TODO(b/118891412): remove default id = 0 and update comments after pdx is no longer in use
+ const uint32_t mId = 0;
+
// The following variables are atomic variables in metadata_ that are visible
// to Bn object and Bp objects. Please find more info in
// BufferHubDefs::MetadataHeader.
diff --git a/services/bufferhub/include/bufferhub/UniqueIdGenerator.h b/services/bufferhub/include/bufferhub/UniqueIdGenerator.h
new file mode 100644
index 0000000..d2e702f
--- /dev/null
+++ b/services/bufferhub/include/bufferhub/UniqueIdGenerator.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_ID_GENERATOR_H
+#define ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_ID_GENERATOR_H
+
+#include <mutex>
+#include <set>
+
+#include <utils/Mutex.h>
+
+namespace android {
+namespace frameworks {
+namespace bufferhub {
+namespace V1_0 {
+namespace implementation {
+
+// A thread-safe incremental uint32_t id generator.
+class UniqueIdGenerator {
+public:
+ // 0 is considered invalid
+ static constexpr uint32_t kInvalidId = 0UL;
+
+ // Gets next available id. If next id is greater than std::numeric_limits<uint32_t>::max() (2 ^
+ // 32 - 1), it will try to get an id start from 1 again.
+ uint32_t getId();
+
+ // Free a specific id. Return true on freed, false on not found.
+ bool freeId(uint32_t id);
+
+private:
+ std::mutex mIdsInUseMutex;
+ // Start from kInvalidID to avoid generating it.
+ uint32_t mLastId = kInvalidId;
+ std::set<uint32_t> mIdsInUse GUARDED_BY(mIdsInUseMutex);
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace bufferhub
+} // namespace frameworks
+} // namespace android
+
+#endif // ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_ID_GENERATOR_H
diff --git a/services/bufferhub/tests/Android.bp b/services/bufferhub/tests/Android.bp
index cef31f6..8a30ef5 100644
--- a/services/bufferhub/tests/Android.bp
+++ b/services/bufferhub/tests/Android.bp
@@ -21,4 +21,20 @@
],
// TODO(b/117568153): Temporarily opt out using libcrt.
no_libcrt: true,
+}
+
+cc_test {
+ name: "UniqueIdGenerator_test",
+ srcs: ["UniqueIdGenerator_test.cpp"],
+ cflags: [
+ "-DLOG_TAG=\"UniqueIdGenerator_test\"",
+ "-DTRACE=0",
+ "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
+ ],
+ shared_libs: [
+ "libbufferhubservice",
+ ],
+ static_libs: [
+ "libgmock",
+ ],
}
\ No newline at end of file
diff --git a/services/bufferhub/tests/UniqueIdGenerator_test.cpp b/services/bufferhub/tests/UniqueIdGenerator_test.cpp
new file mode 100644
index 0000000..c4d83e0
--- /dev/null
+++ b/services/bufferhub/tests/UniqueIdGenerator_test.cpp
@@ -0,0 +1,45 @@
+#include <bufferhub/UniqueIdGenerator.h>
+#include <gtest/gtest.h>
+
+namespace android {
+namespace frameworks {
+namespace bufferhub {
+namespace V1_0 {
+namespace implementation {
+
+namespace {
+
+class UniqueIdGeneratorTest : public testing::Test {
+protected:
+ UniqueIdGenerator mIdGenerator;
+};
+
+TEST_F(UniqueIdGeneratorTest, TestGenerateAndFreeID) {
+ uint32_t id = mIdGenerator.getId();
+ EXPECT_NE(id, UniqueIdGenerator::kInvalidId);
+
+ EXPECT_TRUE(mIdGenerator.freeId(id));
+ EXPECT_FALSE(mIdGenerator.freeId(id));
+}
+
+TEST_F(UniqueIdGeneratorTest, TestGenerateUniqueIncrementalID) {
+ // 10 IDs should not overflow the UniqueIdGenerator to cause a roll back to start, so the
+ // resulting IDs should still keep incresing.
+ const size_t kTestSize = 10U;
+ uint32_t ids[kTestSize];
+ for (int i = 0; i < kTestSize; ++i) {
+ ids[i] = mIdGenerator.getId();
+ EXPECT_NE(ids[i], UniqueIdGenerator::kInvalidId);
+ if (i >= 1) {
+ EXPECT_GT(ids[i], ids[i - 1]);
+ }
+ }
+}
+
+} // namespace
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace bufferhub
+} // namespace frameworks
+} // namespace android
\ No newline at end of file
diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp
index e4ca6bc..150896c 100644
--- a/services/gpuservice/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -62,7 +62,7 @@
status_t cmd_vkjson(int out, int err);
}
-const char* const GpuService::SERVICE_NAME = "gpuservice";
+const char* const GpuService::SERVICE_NAME = "gpu";
GpuService::GpuService() = default;
diff --git a/services/gpuservice/gpuservice.rc b/services/gpuservice/gpuservice.rc
index d23cf46..65a5c27 100644
--- a/services/gpuservice/gpuservice.rc
+++ b/services/gpuservice/gpuservice.rc
@@ -1,4 +1,4 @@
-service gpuservice /system/bin/gpuservice
+service gpu /system/bin/gpuservice
class core
user gpu_service
group graphics
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 9a65452..7812cb2 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -35,6 +35,7 @@
"libutils",
"libui",
"libhardware_legacy",
+ "libutils"
],
cflags: [
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 177f832..0c9e04b 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -58,6 +58,7 @@
#include <utils/Trace.h>
#include <powermanager/PowerManager.h>
#include <ui/Region.h>
+#include <binder/Binder.h>
#define INDENT " "
#define INDENT2 " "
@@ -818,7 +819,7 @@
sp<InputWindowHandle> focusedWindowHandle =
getValueByKey(mFocusedWindowHandlesByDisplay, getTargetDisplayId(entry));
if (focusedWindowHandle != nullptr) {
- commandEntry->inputWindowHandle = focusedWindowHandle;
+ commandEntry->inputChannel = focusedWindowHandle->getInputChannel();
}
commandEntry->keyEntry = entry;
entry->refCount += 1;
@@ -1064,6 +1065,13 @@
}
}
+void InputDispatcher::removeWindowByTokenLocked(const sp<IBinder>& token) {
+ for (size_t d = 0; d < mTouchStatesByDisplay.size(); d++) {
+ TouchState& state = mTouchStatesByDisplay.editValueAt(d);
+ state.removeWindowByToken(token);
+ }
+}
+
void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
const sp<InputChannel>& inputChannel) {
if (newTimeout > 0) {
@@ -1078,17 +1086,10 @@
ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
if (connectionIndex >= 0) {
sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
- sp<InputWindowHandle> windowHandle = connection->inputWindowHandle;
+ sp<IBinder> token = connection->inputChannel->getToken();
- if (windowHandle != nullptr) {
- const InputWindowInfo* info = windowHandle->getInfo();
- if (info) {
- ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(info->displayId);
- if (stateIndex >= 0) {
- mTouchStatesByDisplay.editValueAt(stateIndex).removeWindow(
- windowHandle);
- }
- }
+ if (token != nullptr) {
+ removeWindowByTokenLocked(token);
}
if (connection->status == Connection::STATUS_NORMAL) {
@@ -3017,7 +3018,8 @@
const Vector<sp<InputWindowHandle>> windowHandles = it.second;
size_t numWindows = windowHandles.size();
for (size_t i = 0; i < numWindows; i++) {
- if (windowHandles.itemAt(i) == windowHandle) {
+ if (windowHandles.itemAt(i)->getInputChannel()->getToken()
+ == windowHandle->getInputChannel()->getToken()) {
if (windowHandle->getInfo()->displayId != it.first) {
ALOGE("Found window %s in display %" PRId32
", but it should belong to display %" PRId32,
@@ -3639,8 +3641,7 @@
mConfig.keyRepeatTimeout * 0.000001f);
}
-status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
- const sp<InputWindowHandle>& inputWindowHandle, int32_t displayId) {
+status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel, int32_t displayId) {
#if DEBUG_REGISTRATION
ALOGD("channel '%s' ~ registerInputChannel - displayId=%" PRId32,
inputChannel->getName().c_str(), displayId);
@@ -3649,17 +3650,20 @@
{ // acquire lock
AutoMutex _l(mLock);
+ // If InputWindowHandle is null and displayId is not ADISPLAY_ID_NONE,
+ // treat inputChannel as monitor channel for displayId.
+ bool monitor = inputChannel->getToken() == nullptr && displayId != ADISPLAY_ID_NONE;
+ if (monitor) {
+ inputChannel->setToken(new BBinder());
+ }
+
if (getConnectionIndexLocked(inputChannel) >= 0) {
ALOGW("Attempted to register already registered input channel '%s'",
inputChannel->getName().c_str());
return BAD_VALUE;
}
- // If InputWindowHandle is null and displayId is not ADISPLAY_ID_NONE,
- // treat inputChannel as monitor channel for displayId.
- bool monitor = inputWindowHandle == nullptr && displayId != ADISPLAY_ID_NONE;
-
- sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor);
+ sp<Connection> connection = new Connection(inputChannel, monitor);
int fd = inputChannel->getFd();
mConnectionsByFd.add(fd, connection);
@@ -3744,17 +3748,17 @@
}
ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputChannel) {
- if (!inputChannel) {
+ if (inputChannel == nullptr) {
return -1;
}
- ssize_t connectionIndex = mConnectionsByFd.indexOfKey(inputChannel->getFd());
- if (connectionIndex >= 0) {
- sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
- if (connection->inputChannel.get() == inputChannel.get()) {
- return connectionIndex;
+ for (size_t i = 0; i < mConnectionsByFd.size(); i++) {
+ sp<Connection> connection = mConnectionsByFd.valueAt(i);
+ if (connection->inputChannel->getToken() == inputChannel->getToken()) {
+ return i;
}
}
+
return -1;
}
@@ -3808,7 +3812,7 @@
CommandEntry* commandEntry = postCommandLocked(
& InputDispatcher::doNotifyANRLockedInterruptible);
commandEntry->inputApplicationHandle = applicationHandle;
- commandEntry->inputWindowHandle = windowHandle;
+ commandEntry->inputChannel = windowHandle != nullptr ? windowHandle->getInputChannel() : nullptr;
commandEntry->reason = reason;
}
@@ -3828,7 +3832,7 @@
if (connection->status != Connection::STATUS_ZOMBIE) {
mLock.unlock();
- mPolicy->notifyInputChannelBroken(connection->inputWindowHandle);
+ mPolicy->notifyInputChannelBroken(connection->inputChannel->getToken());
mLock.lock();
}
@@ -3839,14 +3843,14 @@
mLock.unlock();
nsecs_t newTimeout = mPolicy->notifyANR(
- commandEntry->inputApplicationHandle, commandEntry->inputWindowHandle,
+ commandEntry->inputApplicationHandle,
+ commandEntry->inputChannel ? commandEntry->inputChannel->getToken() : nullptr,
commandEntry->reason);
mLock.lock();
resumeAfterTargetsNotReadyTimeoutLocked(newTimeout,
- commandEntry->inputWindowHandle != nullptr
- ? commandEntry->inputWindowHandle->getInputChannel() : nullptr);
+ commandEntry->inputChannel);
}
void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
@@ -3859,7 +3863,9 @@
mLock.unlock();
android::base::Timer t;
- nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
+ sp<IBinder> token = commandEntry->inputChannel != nullptr ?
+ commandEntry->inputChannel->getToken() : nullptr;
+ nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(token,
&event, entry->policyFlags);
if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
ALOGW("Excessive delay in interceptKeyBeforeDispatching; took %s ms",
@@ -3960,7 +3966,7 @@
mLock.unlock();
- mPolicy->dispatchUnhandledKey(connection->inputWindowHandle,
+ mPolicy->dispatchUnhandledKey(connection->inputChannel->getToken(),
&event, keyEntry->policyFlags, &event);
mLock.lock();
@@ -4005,7 +4011,7 @@
mLock.unlock();
- bool fallback = mPolicy->dispatchUnhandledKey(connection->inputWindowHandle,
+ bool fallback = mPolicy->dispatchUnhandledKey(connection->inputChannel->getToken(),
&event, keyEntry->policyFlags, &event);
mLock.lock();
@@ -4721,9 +4727,8 @@
// --- InputDispatcher::Connection ---
-InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel,
- const sp<InputWindowHandle>& inputWindowHandle, bool monitor) :
- status(STATUS_NORMAL), inputChannel(inputChannel), inputWindowHandle(inputWindowHandle),
+InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel, bool monitor) :
+ status(STATUS_NORMAL), inputChannel(inputChannel),
monitor(monitor),
inputPublisher(inputChannel), inputPublisherBlocked(false) {
}
@@ -4732,8 +4737,8 @@
}
const std::string InputDispatcher::Connection::getWindowName() const {
- if (inputWindowHandle != nullptr) {
- return inputWindowHandle->getName();
+ if (inputChannel != nullptr) {
+ return inputChannel->getName();
}
if (monitor) {
return "monitor";
@@ -4840,6 +4845,15 @@
}
}
+void InputDispatcher::TouchState::removeWindowByToken(const sp<IBinder>& token) {
+ for (size_t i = 0; i < windows.size(); i++) {
+ if (windows.itemAt(i).windowHandle->getInputChannel()->getToken() == token) {
+ windows.removeAt(i);
+ return;
+ }
+ }
+}
+
void InputDispatcher::TouchState::filterNonAsIsTouchWindows() {
for (size_t i = 0 ; i < windows.size(); ) {
TouchedWindow& window = windows.editItemAt(i);
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index 5efb2fa..5016082 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -208,11 +208,11 @@
/* Notifies the system that an application is not responding.
* Returns a new timeout to continue waiting, or 0 to abort dispatch. */
virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
- const sp<InputWindowHandle>& inputWindowHandle,
+ const sp<IBinder>& token,
const std::string& reason) = 0;
/* Notifies the system that an input channel is unrecoverably broken. */
- virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) = 0;
+ virtual void notifyInputChannelBroken(const sp<IBinder>& token) = 0;
/* Gets the input dispatcher configuration. */
virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) = 0;
@@ -243,12 +243,12 @@
virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0;
/* Allows the policy a chance to intercept a key before dispatching. */
- virtual nsecs_t interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
+ virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>& token,
const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
/* Allows the policy a chance to perform default processing for an unhandled key.
* Returns an alternate keycode to redispatch as a fallback, or 0 to give up. */
- virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
+ virtual bool dispatchUnhandledKey(const sp<IBinder>& token,
const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) = 0;
/* Notifies the policy about switch events.
@@ -352,8 +352,8 @@
*
* This method may be called on any thread (usually by the input manager).
*/
- virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
- const sp<InputWindowHandle>& inputWindowHandle, int32_t displayId) = 0;
+ virtual status_t registerInputChannel(
+ const sp<InputChannel>& inputChannel, int32_t displayId) = 0;
/* Unregister input channels that will no longer receive input events.
*
@@ -413,7 +413,7 @@
const sp<InputChannel>& toChannel);
virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
- const sp<InputWindowHandle>& inputWindowHandle, int32_t displayId);
+ int32_t displayId);
virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
private:
@@ -617,11 +617,11 @@
nsecs_t eventTime;
KeyEntry* keyEntry;
sp<InputApplicationHandle> inputApplicationHandle;
- sp<InputWindowHandle> inputWindowHandle;
std::string reason;
int32_t userActivityEventType;
uint32_t seq;
bool handled;
+ sp<InputChannel> inputChannel;
};
// Generic queue implementation.
@@ -834,7 +834,6 @@
Status status;
sp<InputChannel> inputChannel; // never null
- sp<InputWindowHandle> inputWindowHandle; // may be null
bool monitor;
InputPublisher inputPublisher;
InputState inputState;
@@ -850,8 +849,7 @@
// yet received a "finished" response from the application.
Queue<DispatchEntry> waitQueue;
- explicit Connection(const sp<InputChannel>& inputChannel,
- const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
+ explicit Connection(const sp<InputChannel>& inputChannel, bool monitor);
inline const std::string getInputChannelName() const { return inputChannel->getName(); }
@@ -1007,6 +1005,7 @@
void addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle,
int32_t targetFlags, BitSet32 pointerIds);
void removeWindow(const sp<InputWindowHandle>& windowHandle);
+ void removeWindowByToken(const sp<IBinder>& token);
void filterNonAsIsTouchWindows();
sp<InputWindowHandle> getFirstForegroundWindowHandle() const;
bool isSlippery() const;
@@ -1062,6 +1061,9 @@
const sp<InputApplicationHandle>& applicationHandle,
const sp<InputWindowHandle>& windowHandle,
nsecs_t* nextWakeupTime, const char* reason);
+
+ void removeWindowByTokenLocked(const sp<IBinder>& token);
+
void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
const sp<InputChannel>& inputChannel);
nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime);
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index 519faa6..40ca6a7 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -21,6 +21,7 @@
#include "InputManager.h"
#include <log/log.h>
+#include <unordered_map>
namespace android {
@@ -90,4 +91,39 @@
return mDispatcher;
}
+class BinderApplicationHandle : public InputApplicationHandle {
+public:
+ BinderApplicationHandle() = default;
+
+ bool updateInfo() override {
+ return true;
+ }
+};
+
+class BinderWindowHandle : public InputWindowHandle {
+public:
+ BinderWindowHandle(const InputWindowInfo& info) :
+ InputWindowHandle(new BinderApplicationHandle()) {
+
+ mInfo = info;
+ }
+
+ bool updateInfo() override {
+ return true;
+ }
+};
+
+void InputManager::setInputWindows(const Vector<InputWindowInfo>& infos) {
+ std::unordered_map<int32_t, Vector<sp<InputWindowHandle>>> handlesPerDisplay;
+
+ Vector<sp<InputWindowHandle>> handles;
+ for (const auto& info : infos) {
+ handlesPerDisplay.emplace(info.displayId, Vector<sp<InputWindowHandle>>());
+ handlesPerDisplay[info.displayId].add(new BinderWindowHandle(info));
+ }
+ for (auto const& i : handlesPerDisplay) {
+ mDispatcher->setInputWindows(i.second, i.first);
+ }
+}
+
} // namespace android
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index 92e0af2..d0e4cb0 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -27,6 +27,8 @@
#include <input/Input.h>
#include <input/InputTransport.h>
+
+#include <input/IInputFlinger.h>
#include <utils/Errors.h>
#include <utils/Vector.h>
#include <utils/Timers.h>
@@ -72,7 +74,7 @@
virtual sp<InputDispatcherInterface> getDispatcher() = 0;
};
-class InputManager : public InputManagerInterface {
+class InputManager : public InputManagerInterface, public BnInputFlinger {
protected:
virtual ~InputManager();
@@ -93,6 +95,8 @@
virtual sp<InputReaderInterface> getReader();
virtual sp<InputDispatcherInterface> getDispatcher();
+ virtual void setInputWindows(const Vector<InputWindowInfo>& handles);
+
private:
sp<InputReaderInterface> mReader;
sp<InputReaderThread> mReaderThread;
diff --git a/services/inputflinger/host/Android.bp b/services/inputflinger/host/Android.bp
index 775dbdc..0e48f24 100644
--- a/services/inputflinger/host/Android.bp
+++ b/services/inputflinger/host/Android.bp
@@ -30,6 +30,9 @@
"libutils",
"libhardware",
],
+ static_libs: [
+ "libarect",
+ ],
cflags: [
"-Wall",
@@ -54,7 +57,10 @@
shared_libs: [
"libbinder",
"libinputflingerhost",
- "libutils",
+ "libutils"
+ ],
+ static_libs: [
+ "libarect",
],
init_rc: ["inputflinger.rc"],
diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h
index 39e69e5..15ca7b3 100644
--- a/services/inputflinger/host/InputFlinger.h
+++ b/services/inputflinger/host/InputFlinger.h
@@ -39,6 +39,7 @@
InputFlinger() ANDROID_API;
virtual status_t dump(int fd, const Vector<String16>& args);
+ void setInputWindows(const Vector<InputWindowInfo>&) {}
private:
virtual ~InputFlinger();
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index a1cd71c..ea42855 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -15,6 +15,7 @@
],
shared_libs: [
"libbase",
+ "libbinder",
"libcutils",
"liblog",
"libutils",
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 066c143..e860db5 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -16,6 +16,8 @@
#include "../InputDispatcher.h"
+#include <binder/Binder.h>
+
#include <gtest/gtest.h>
#include <linux/input.h>
@@ -53,12 +55,12 @@
}
virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&,
- const sp<InputWindowHandle>&,
+ const sp<IBinder>&,
const std::string&) {
return 0;
}
- virtual void notifyInputChannelBroken(const sp<InputWindowHandle>&) {
+ virtual void notifyInputChannelBroken(const sp<IBinder>&) {
}
virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
@@ -75,12 +77,12 @@
virtual void interceptMotionBeforeQueueing(nsecs_t, uint32_t&) {
}
- virtual nsecs_t interceptKeyBeforeDispatching(const sp<InputWindowHandle>&,
+ virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&,
const KeyEvent*, uint32_t) {
return 0;
}
- virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>&,
+ virtual bool dispatchUnhandledKey(const sp<IBinder>&,
const KeyEvent*, uint32_t, KeyEvent*) {
return false;
}
@@ -336,6 +338,7 @@
const std::string name, int32_t displayId) :
mDispatcher(dispatcher), mName(name), mDisplayId(displayId) {
InputChannel::openInputChannelPair(name, mServerChannel, mClientChannel);
+
mConsumer = new InputConsumer(mClientChannel);
}
@@ -366,7 +369,8 @@
InputWindowHandle(inputApplicationHandle),
FakeInputReceiver(dispatcher, name, displayId),
mFocused(false) {
- mDispatcher->registerInputChannel(mServerChannel, this, displayId);
+ mServerChannel->setToken(new BBinder());
+ mDispatcher->registerInputChannel(mServerChannel, displayId);
}
virtual bool updateInfo() {
@@ -649,7 +653,7 @@
public:
FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
int32_t displayId) : FakeInputReceiver(dispatcher, name, displayId) {
- mDispatcher->registerInputChannel(mServerChannel, nullptr, displayId);
+ mDispatcher->registerInputChannel(mServerChannel, displayId);
}
};
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 038bc58..1e910ce 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1344,7 +1344,10 @@
void Layer::updateTransformHint(const sp<const DisplayDevice>& display) const {
uint32_t orientation = 0;
- if (!mFlinger->mDebugDisableTransformHint) {
+ // Disable setting transform hint if the debug flag is set or if the
+ // getTransformToDisplayInverse flag is set and the client wants to submit buffers
+ // in one orientation.
+ if (!mFlinger->mDebugDisableTransformHint && !getTransformToDisplayInverse()) {
// The transform hint is used to improve performance, but we can
// only have a single transform hint, it cannot
// apply to all displays.
@@ -1976,6 +1979,7 @@
layerInfo->set_window_type(state.type);
layerInfo->set_app_id(state.appId);
layerInfo->set_curr_frame(mCurrentFrameNumber);
+ layerInfo->set_effective_scaling_mode(getEffectiveScalingMode());
for (const auto& pendingState : mPendingStates) {
auto barrierLayer = pendingState.barrierLayer_legacy.promote();
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 25c60fe..35ba391 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3193,19 +3193,15 @@
return NO_ERROR;
}
-status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer, bool topLevelOnly) {
+status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer) {
Mutex::Autolock _l(mStateLock);
- return removeLayerLocked(mStateLock, layer, topLevelOnly);
+ return removeLayerLocked(mStateLock, layer);
}
-status_t SurfaceFlinger::removeLayerLocked(const Mutex& lock, const sp<Layer>& layer,
- bool topLevelOnly) {
+status_t SurfaceFlinger::removeLayerLocked(const Mutex& lock, const sp<Layer>& layer) {
const auto& p = layer->getParent();
ssize_t index;
if (p != nullptr) {
- if (topLevelOnly) {
- return NO_ERROR;
- }
index = p->removeChild(layer);
} else {
index = mCurrentState.layersSortedByZ.remove(layer);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 6ffe025..8b389bc 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -592,8 +592,8 @@
void onHandleDestroyed(const sp<Layer>& layer);
// remove a layer from SurfaceFlinger immediately
- status_t removeLayer(const sp<Layer>& layer, bool topLevelOnly = false);
- status_t removeLayerLocked(const Mutex&, const sp<Layer>& layer, bool topLevelOnly = false);
+ status_t removeLayer(const sp<Layer>& layer);
+ status_t removeLayerLocked(const Mutex&, const sp<Layer>& layer);
// add a layer to SurfaceFlinger
status_t addClientLayer(const sp<Client>& client,
diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
index 2a09634..c141ee3 100644
--- a/services/surfaceflinger/layerproto/layers.proto
+++ b/services/surfaceflinger/layerproto/layers.proto
@@ -86,6 +86,7 @@
repeated BarrierLayerProto barrier_layer = 38;
// If active_buffer is not null, record its transform.
optional TransformProto buffer_transform = 39;
+ optional int32 effective_scaling_mode = 40;
}
message PositionProto {
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/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index 8f76606..e4c50d5 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 91
+define VERSION_PATCH 93
// API limits
define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256
@@ -615,6 +615,10 @@
@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"
+// 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_EXTENSION_NAME "VK_GOOGLE_hlsl_functionality1"
@@ -623,6 +627,10 @@
@extension("VK_GOOGLE_decorate_string") define VK_GOOGLE_DECORATE_STRING_SPEC_VERSION 0
@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 //
/////////////
@@ -1848,10 +1856,16 @@
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_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 {
@@ -2382,6 +2396,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,
}
/////////////////
@@ -7656,6 +7671,20 @@
platform.zx_handle_t imagePipeHandle
}
+@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 //
diff --git a/vulkan/include/vulkan/vulkan_core.h b/vulkan/include/vulkan/vulkan_core.h
index 4cd8ed5..35c0664 100644
--- a/vulkan/include/vulkan/vulkan_core.h
+++ b/vulkan/include/vulkan/vulkan_core.h
@@ -43,7 +43,7 @@
#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
// Version of this file
-#define VK_HEADER_VERSION 91
+#define VK_HEADER_VERSION 93
#define VK_NULL_HANDLE 0
@@ -454,6 +454,8 @@
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_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,
@@ -6101,9 +6103,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;
@@ -7791,8 +7794,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"
@@ -8806,6 +8807,18 @@
+#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_EXTENSION_NAME "VK_GOOGLE_hlsl_functionality1"
@@ -8816,6 +8829,18 @@
#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