Merge "gralloc: add mapper 3.0 to composer makefiles"
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 53b3a00..bd3d2d8 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -99,30 +99,31 @@
/* Tracing categories */
static const TracingCategory k_categories[] = {
- { "gfx", "Graphics", ATRACE_TAG_GRAPHICS, { } },
- { "input", "Input", ATRACE_TAG_INPUT, { } },
- { "view", "View System", ATRACE_TAG_VIEW, { } },
- { "webview", "WebView", ATRACE_TAG_WEBVIEW, { } },
- { "wm", "Window Manager", ATRACE_TAG_WINDOW_MANAGER, { } },
- { "am", "Activity Manager", ATRACE_TAG_ACTIVITY_MANAGER, { } },
- { "sm", "Sync Manager", ATRACE_TAG_SYNC_MANAGER, { } },
- { "audio", "Audio", ATRACE_TAG_AUDIO, { } },
- { "video", "Video", ATRACE_TAG_VIDEO, { } },
- { "camera", "Camera", ATRACE_TAG_CAMERA, { } },
- { "hal", "Hardware Modules", ATRACE_TAG_HAL, { } },
- { "res", "Resource Loading", ATRACE_TAG_RESOURCES, { } },
- { "dalvik", "Dalvik VM", ATRACE_TAG_DALVIK, { } },
- { "rs", "RenderScript", ATRACE_TAG_RS, { } },
- { "bionic", "Bionic C Library", ATRACE_TAG_BIONIC, { } },
- { "power", "Power Management", ATRACE_TAG_POWER, { } },
- { "pm", "Package Manager", ATRACE_TAG_PACKAGE_MANAGER, { } },
- { "ss", "System Server", ATRACE_TAG_SYSTEM_SERVER, { } },
- { "database", "Database", ATRACE_TAG_DATABASE, { } },
- { "network", "Network", ATRACE_TAG_NETWORK, { } },
- { "adb", "ADB", ATRACE_TAG_ADB, { } },
- { "vibrator", "Vibrator", ATRACE_TAG_VIBRATOR, { } },
- { "aidl", "AIDL calls", ATRACE_TAG_AIDL, { } },
- { "nnapi", "NNAPI", ATRACE_TAG_NNAPI, { } },
+ { "gfx", "Graphics", ATRACE_TAG_GRAPHICS, { } },
+ { "input", "Input", ATRACE_TAG_INPUT, { } },
+ { "view", "View System", ATRACE_TAG_VIEW, { } },
+ { "webview", "WebView", ATRACE_TAG_WEBVIEW, { } },
+ { "wm", "Window Manager", ATRACE_TAG_WINDOW_MANAGER, { } },
+ { "am", "Activity Manager", ATRACE_TAG_ACTIVITY_MANAGER, { } },
+ { "sm", "Sync Manager", ATRACE_TAG_SYNC_MANAGER, { } },
+ { "audio", "Audio", ATRACE_TAG_AUDIO, { } },
+ { "video", "Video", ATRACE_TAG_VIDEO, { } },
+ { "camera", "Camera", ATRACE_TAG_CAMERA, { } },
+ { "hal", "Hardware Modules", ATRACE_TAG_HAL, { } },
+ { "res", "Resource Loading", ATRACE_TAG_RESOURCES, { } },
+ { "dalvik", "Dalvik VM", ATRACE_TAG_DALVIK, { } },
+ { "rs", "RenderScript", ATRACE_TAG_RS, { } },
+ { "bionic", "Bionic C Library", ATRACE_TAG_BIONIC, { } },
+ { "power", "Power Management", ATRACE_TAG_POWER, { } },
+ { "pm", "Package Manager", ATRACE_TAG_PACKAGE_MANAGER, { } },
+ { "ss", "System Server", ATRACE_TAG_SYSTEM_SERVER, { } },
+ { "database", "Database", ATRACE_TAG_DATABASE, { } },
+ { "network", "Network", ATRACE_TAG_NETWORK, { } },
+ { "adb", "ADB", ATRACE_TAG_ADB, { } },
+ { "vibrator", "Vibrator", ATRACE_TAG_VIBRATOR, { } },
+ { "aidl", "AIDL calls", ATRACE_TAG_AIDL, { } },
+ { "nnapi", "NNAPI", ATRACE_TAG_NNAPI, { } },
+ { "rro", "Runtime Resource Overlay", ATRACE_TAG_RRO, { } },
{ k_coreServiceCategory, "Core services", 0, { } },
{ k_pdxServiceCategory, "PDX services", 0, { } },
{ "sched", "CPU Scheduling", 0, {
diff --git a/cmds/atrace/atrace_userdebug.rc b/cmds/atrace/atrace_userdebug.rc
index 5c28c9d..6c86c21 100644
--- a/cmds/atrace/atrace_userdebug.rc
+++ b/cmds/atrace/atrace_userdebug.rc
@@ -5,6 +5,12 @@
# Access control to these files is now entirely in selinux policy.
on post-fs
+ # On userdebug allow to enable any event via the generic
+ # set_event interface:
+ # echo sched/foo > set_event == echo 1 > events/sched/foo/enable.
+ chmod 0666 /sys/kernel/tracing/set_event
+ chmod 0666 /sys/kernel/debug/tracing/set_event
+
chmod 0666 /sys/kernel/tracing/events/workqueue/enable
chmod 0666 /sys/kernel/debug/tracing/events/workqueue/enable
chmod 0666 /sys/kernel/tracing/events/regulator/enable
diff --git a/cmds/cmd/Android.bp b/cmds/cmd/Android.bp
index d91184a..8ea71cd 100644
--- a/cmds/cmd/Android.bp
+++ b/cmds/cmd/Android.bp
@@ -1,7 +1,31 @@
+cc_library_static {
+ name: "libcmd",
+
+ srcs: ["cmd.cpp"],
+ export_include_dirs: ["."],
+
+ shared_libs: [
+ "libutils",
+ "liblog",
+ "libselinux",
+ "libbinder",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-DXP_UNIX",
+ ],
+}
+
cc_binary {
name: "cmd",
- srcs: ["cmd.cpp"],
+ srcs: ["main.cpp"],
+
+ static_libs: [
+ "libcmd",
+ ],
shared_libs: [
"libutils",
diff --git a/cmds/cmd/cmd.cpp b/cmds/cmd/cmd.cpp
index 0616add..7b4aeb2 100644
--- a/cmds/cmd/cmd.cpp
+++ b/cmds/cmd/cmd.cpp
@@ -40,6 +40,8 @@
#include "selinux/selinux.h"
#include "selinux/android.h"
+#include "cmd.h"
+
#define DEBUG 0
using namespace android;
@@ -59,8 +61,11 @@
class MyShellCallback : public BnShellCallback
{
public:
+ TextOutput& mErrorLog;
bool mActive = true;
+ MyShellCallback(TextOutput& errorLog) : mErrorLog(errorLog) {}
+
virtual int openFile(const String16& path, const String16& seLinuxContext,
const String16& mode) {
String8 path8(path);
@@ -69,7 +74,7 @@
String8 fullPath(cwd);
fullPath.appendPath(path8);
if (!mActive) {
- aerr << "Open attempt after active for: " << fullPath << endl;
+ mErrorLog << "Open attempt after active for: " << fullPath << endl;
return -EPERM;
}
#if DEBUG
@@ -78,20 +83,20 @@
int flags = 0;
bool checkRead = false;
bool checkWrite = false;
- if (mode == String16("w")) {
+ if (mode == u"w") {
flags = O_WRONLY|O_CREAT|O_TRUNC;
checkWrite = true;
- } else if (mode == String16("w+")) {
+ } else if (mode == u"w+") {
flags = O_RDWR|O_CREAT|O_TRUNC;
checkRead = checkWrite = true;
- } else if (mode == String16("r")) {
+ } else if (mode == u"r") {
flags = O_RDONLY;
checkRead = true;
- } else if (mode == String16("r+")) {
+ } else if (mode == u"r+") {
flags = O_RDWR;
checkRead = checkWrite = true;
} else {
- aerr << "Invalid mode requested: " << mode.string() << endl;
+ mErrorLog << "Invalid mode requested: " << mode.string() << endl;
return -EINVAL;
}
int fd = open(fullPath.string(), flags, S_IRWXU|S_IRWXG);
@@ -114,9 +119,7 @@
ALOGD("openFile: failed selinux write check!");
#endif
close(fd);
- aerr << "System server has no access to write file context " << context.get()
- << " (from path " << fullPath.string() << ", context "
- << seLinuxContext8.string() << ")" << endl;
+ mErrorLog << "System server has no access to write file context " << context.get() << " (from path " << fullPath.string() << ", context " << seLinuxContext8.string() << ")" << endl;
return -EPERM;
}
}
@@ -128,9 +131,7 @@
ALOGD("openFile: failed selinux read check!");
#endif
close(fd);
- aerr << "System server has no access to read file context " << context.get()
- << " (from path " << fullPath.string() << ", context "
- << seLinuxContext8.string() << ")" << endl;
+ mErrorLog << "System server has no access to read file context " << context.get() << " (from path " << fullPath.string() << ", context " << seLinuxContext8.string() << ")" << endl;
return -EPERM;
}
}
@@ -163,9 +164,8 @@
}
};
-int main(int argc, char* const argv[])
-{
- signal(SIGPIPE, SIG_IGN);
+int cmdMain(const std::vector<std::string_view>& argv, TextOutput& outputLog, TextOutput& errorLog,
+ int in, int out, int err, RunMode runMode) {
sp<ProcessState> proc = ProcessState::self();
proc->startThreadPool();
@@ -173,68 +173,77 @@
ALOGD("cmd: starting");
#endif
sp<IServiceManager> sm = defaultServiceManager();
- fflush(stdout);
+ if (runMode == RunMode::kStandalone) {
+ fflush(stdout);
+ }
if (sm == nullptr) {
ALOGW("Unable to get default service manager!");
- aerr << "cmd: Unable to get default service manager!" << endl;
+ errorLog << "cmd: Unable to get default service manager!" << endl;
return 20;
}
- if (argc == 1) {
- aerr << "cmd: No service specified; use -l to list all services" << endl;
+ int argc = argv.size();
+
+ if (argc == 0) {
+ errorLog << "cmd: No service specified; use -l to list all services" << endl;
return 20;
}
- if ((argc == 2) && (strcmp(argv[1], "-l") == 0)) {
+ if ((argc == 1) && (argv[0] == "-l")) {
Vector<String16> services = sm->listServices();
services.sort(sort_func);
- aout << "Currently running services:" << endl;
+ outputLog << "Currently running services:" << endl;
for (size_t i=0; i<services.size(); i++) {
sp<IBinder> service = sm->checkService(services[i]);
if (service != nullptr) {
- aout << " " << services[i] << endl;
+ outputLog << " " << services[i] << endl;
}
}
return 0;
}
+ const auto cmd = argv[0];
+
Vector<String16> args;
- for (int i=2; i<argc; i++) {
- args.add(String16(argv[i]));
+ String16 serviceName = String16(cmd.data(), cmd.size());
+ for (int i = 1; i < argc; i++) {
+ args.add(String16(argv[i].data(), argv[i].size()));
}
- String16 cmd = String16(argv[1]);
- sp<IBinder> service = sm->checkService(cmd);
+ sp<IBinder> service = sm->checkService(serviceName);
if (service == nullptr) {
- ALOGW("Can't find service %s", argv[1]);
- aerr << "cmd: Can't find service: " << argv[1] << endl;
+ if (runMode == RunMode::kStandalone) {
+ ALOGW("Can't find service %.*s", static_cast<int>(cmd.size()), cmd.data());
+ }
+ errorLog << "cmd: Can't find service: " << cmd << endl;
return 20;
}
- sp<MyShellCallback> cb = new MyShellCallback();
+ sp<MyShellCallback> cb = new MyShellCallback(errorLog);
sp<MyResultReceiver> result = new MyResultReceiver();
#if DEBUG
- ALOGD("cmd: Invoking %s in=%d, out=%d, err=%d", argv[1], STDIN_FILENO, STDOUT_FILENO,
- STDERR_FILENO);
+ ALOGD("cmd: Invoking %s in=%d, out=%d, err=%d", cmd, in, out, err);
#endif
// TODO: block until a result is returned to MyResultReceiver.
- status_t err = IBinder::shellCommand(service, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, args,
- cb, result);
- if (err < 0) {
+ status_t error = IBinder::shellCommand(service, in, out, err, args, cb, result);
+ if (error < 0) {
const char* errstr;
- switch (err) {
+ switch (error) {
case BAD_TYPE: errstr = "Bad type"; break;
case FAILED_TRANSACTION: errstr = "Failed transaction"; break;
case FDS_NOT_ALLOWED: errstr = "File descriptors not allowed"; break;
case UNEXPECTED_NULL: errstr = "Unexpected null"; break;
- default: errstr = strerror(-err); break;
+ default: errstr = strerror(-error); break;
}
- ALOGW("Failure calling service %s: %s (%d)", argv[1], errstr, -err);
- aout << "cmd: Failure calling service " << argv[1] << ": " << errstr << " ("
- << (-err) << ")" << endl;
- return err;
+ if (runMode == RunMode::kStandalone) {
+ ALOGW("Failure calling service %.*s: %s (%d)", static_cast<int>(cmd.size()), cmd.data(),
+ errstr, -error);
+ }
+ outputLog << "cmd: Failure calling service " << cmd << ": " << errstr << " (" << (-error)
+ << ")" << endl;
+ return error;
}
cb->mActive = false;
diff --git a/cmds/cmd/cmd.h b/cmds/cmd/cmd.h
new file mode 100644
index 0000000..a91e009
--- /dev/null
+++ b/cmds/cmd/cmd.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <binder/TextOutput.h>
+
+#include <string_view>
+#include <vector>
+
+enum class RunMode {
+ kStandalone,
+ kLibrary,
+};
+
+int cmdMain(const std::vector<std::string_view>& argv, android::TextOutput& outputLog,
+ android::TextOutput& errorLog, int in, int out, int err, RunMode runMode);
diff --git a/cmds/cmd/main.cpp b/cmds/cmd/main.cpp
new file mode 100644
index 0000000..2256e2a
--- /dev/null
+++ b/cmds/cmd/main.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <unistd.h>
+
+#include "cmd.h"
+
+int main(int argc, char* const argv[]) {
+ signal(SIGPIPE, SIG_IGN);
+
+ std::vector<std::string_view> arguments;
+ arguments.reserve(argc - 1);
+ // 0th argument is a program name, skipping.
+ for (int i = 1; i < argc; ++i) {
+ arguments.emplace_back(argv[i]);
+ }
+
+ return cmdMain(arguments, android::aout, android::aerr, STDIN_FILENO, STDOUT_FILENO,
+ STDERR_FILENO, RunMode::kStandalone);
+}
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index 849eb44..6596fa2 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -98,9 +98,10 @@
return binder::Status::ok();
}
-binder::Status DumpstateService::startBugreport(int, int bugreport_mode, int32_t* returned_id) {
- // TODO(111441001): return a request id here.
- *returned_id = -1;
+binder::Status DumpstateService::startBugreport(const android::base::unique_fd& bugreport_fd,
+ const android::base::unique_fd& screenshot_fd,
+ int bugreport_mode,
+ const sp<IDumpstateListener>& listener) {
MYLOGI("startBugreport() with mode: %d\n", bugreport_mode);
if (bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_FULL &&
@@ -114,9 +115,20 @@
StringPrintf("Invalid bugreport mode: %d", bugreport_mode));
}
+ if (bugreport_fd.get() == -1 || screenshot_fd.get() == -1) {
+ return exception(binder::Status::EX_ILLEGAL_ARGUMENT, "Invalid file descriptor");
+ }
+
std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
- options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode));
+ options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode), bugreport_fd,
+ screenshot_fd);
+
+ std::lock_guard<std::mutex> lock(lock_);
+ // TODO(b/111441001): Disallow multiple simultaneous bugreports.
ds_.SetOptions(std::move(options));
+ if (listener != nullptr) {
+ ds_.listener_ = listener;
+ }
pthread_t thread;
status_t err = pthread_create(&thread, nullptr, callAndNotify, &ds_);
diff --git a/cmds/dumpstate/DumpstateService.h b/cmds/dumpstate/DumpstateService.h
index 58095b3..1705317 100644
--- a/cmds/dumpstate/DumpstateService.h
+++ b/cmds/dumpstate/DumpstateService.h
@@ -20,6 +20,7 @@
#include <mutex>
#include <vector>
+#include <android-base/unique_fd.h>
#include <binder/BinderService.h>
#include "android/os/BnDumpstate.h"
@@ -41,7 +42,9 @@
bool getSectionDetails,
sp<IDumpstateToken>* returned_token) override;
- binder::Status startBugreport(int fd, int bugreport_mode, int32_t* returned_id) override;
+ binder::Status startBugreport(const android::base::unique_fd& bugreport_fd,
+ const android::base::unique_fd& screenshot_fd, int bugreport_mode,
+ const sp<IDumpstateListener>& listener) override;
private:
Dumpstate& ds_;
diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
index 617eab3..d24c953 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
@@ -25,8 +25,6 @@
* {@hide}
*/
interface IDumpstate {
-
-
// TODO: remove method once startBugReport is used by Shell.
/*
* Sets the listener for this dumpstate progress.
@@ -63,6 +61,12 @@
/*
* Starts a bugreport in the background.
+ *
+ * @param bugreportFd the file to which the zipped bugreport should be written
+ * @param screenshotFd the file to which screenshot should be written; optional
+ * @param bugreportMode the mode that specifies other run time options; must be one of above
+ * @param listener callback for updates; optional
*/
- int startBugreport(int fd, int bugreportMode);
+ void startBugreport(FileDescriptor bugreportFd, FileDescriptor screenshotFd, int bugreportMode,
+ IDumpstateListener listener);
}
diff --git a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
index 030d69d..2966c86 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
@@ -22,18 +22,48 @@
* {@hide}
*/
interface IDumpstateListener {
+ /**
+ * Called when there is a progress update.
+ *
+ * @param progress the progress in [0, 100]
+ */
+ oneway void onProgress(int progress);
+
+ /* Options specified are invalid or incompatible */
+ const int BUGREPORT_ERROR_INVALID_INPUT = 1;
+
+ /* Bugreport encountered a runtime error */
+ const int BUGREPORT_ERROR_RUNTIME_ERROR = 2;
+
+ /**
+ * Called on an error condition with one of the error codes listed above.
+ */
+ oneway void onError(int errorCode);
+
+ /**
+ * Called when taking bugreport finishes successfully
+ *
+ * @param durationMs time capturing bugreport took in milliseconds
+ * @param title title for the bugreport; helpful in reminding the user why they took it
+ * @param description detailed description for the bugreport
+ */
+ oneway void onFinished(long durationMs, @utf8InCpp String title,
+ @utf8InCpp String description);
+
+ // TODO(b/111441001): Remove old methods when not used anymore.
void onProgressUpdated(int progress);
void onMaxProgressUpdated(int maxProgress);
/**
- * Called after every section is complete.
- * @param name section name
- * @param status values from status_t
- * {@code OK} section completed successfully
- * {@code TIMEOUT} dump timed out
- * {@code != OK} error
- * @param size size in bytes, may be invalid if status != OK
- * @param durationMs duration in ms
- */
+ * Called after every section is complete.
+ *
+ * @param name section name
+ * @param status values from status_t
+ * {@code OK} section completed successfully
+ * {@code TIMEOUT} dump timed out
+ * {@code != OK} error
+ * @param size size in bytes, may be invalid if status != OK
+ * @param durationMs duration in ms
+ */
void onSectionComplete(@utf8InCpp String name, int status, int size, int durationMs);
}
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 516e3d8..4e5d68d 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1572,6 +1572,15 @@
RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
SEC_TO_MSEC(10));
+ if (ds.IsZipping()) {
+ RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z"},
+ CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
+ DumpHals();
+ } else {
+ RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z", "--debug"},
+ CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
+ }
+
printf("========================================================\n");
printf("== dumpstate: done (id %d)\n", ds.id_);
printf("========================================================\n");
@@ -1692,7 +1701,7 @@
printf("*** See dumpstate-board.txt entry ***\n");
}
-static void ShowUsageAndExit(int exit_code = 1) {
+static void ShowUsage() {
fprintf(stderr,
"usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
"[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
@@ -1712,12 +1721,6 @@
" -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
"shouldn't be used with -P)\n"
" -v: prints the dumpstate header and exit\n");
- exit(exit_code);
-}
-
-static void ExitOnInvalidArgs() {
- fprintf(stderr, "invalid combination of args\n");
- ShowUsageAndExit();
}
static void register_sig_handler() {
@@ -1878,8 +1881,9 @@
ds.tmp_path_ = ds.GetPath(".tmp");
ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
- std::string destination = ds.options_->fd != -1 ? StringPrintf("[fd:%d]", ds.options_->fd)
- : ds.bugreport_dir_.c_str();
+ std::string destination = ds.options_->bugreport_fd.get() != -1
+ ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
+ : ds.bugreport_dir_.c_str();
MYLOGD(
"Bugreport dir: %s\n"
"Internal Bugreport dir: %s\n"
@@ -1957,8 +1961,8 @@
}
// The zip file lives in an internal directory. Copy it over to output.
bool copy_succeeded = false;
- if (ds.options_->fd != -1) {
- copy_succeeded = android::os::CopyFileToFd(ds.path_, ds.options_->fd);
+ if (ds.options_->bugreport_fd.get() != -1) {
+ copy_succeeded = android::os::CopyFileToFd(ds.path_, ds.options_->bugreport_fd.get());
} else {
ds.final_path_ = ds.GetPath(ds.bugreport_dir_, ".zip");
copy_succeeded = android::os::CopyFileToFile(ds.path_, ds.final_path_);
@@ -2161,7 +2165,7 @@
MYLOGI("telephony_only: %d\n", options.telephony_only);
MYLOGI("wifi_only: %d\n", options.wifi_only);
MYLOGI("do_progress_updates: %d\n", options.do_progress_updates);
- MYLOGI("fd: %d\n", options.fd);
+ MYLOGI("fd: %d\n", options.bugreport_fd.get());
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());
@@ -2169,14 +2173,17 @@
MYLOGI("notification_description: %s\n", options.notification_description.c_str());
}
-void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode) {
+void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
+ const android::base::unique_fd& bugreport_fd_in,
+ const android::base::unique_fd& screenshot_fd_in) {
// In the new API world, date is always added; output is always a zip file.
// TODO(111441001): remove these options once they are obsolete.
do_add_date = true;
do_zip_file = true;
- // STOPSHIP b/111441001: Remove hardcoded output file path; accept fd.
- use_outfile = "/data/user_de/0/com.android.shell/files/bugreports/bugreport";
+ // Duplicate the fds because the passed in fds don't outlive the binder transaction.
+ bugreport_fd.reset(dup(bugreport_fd_in.get()));
+ screenshot_fd.reset(dup(screenshot_fd_in.get()));
extra_options = ModeToString(bugreport_mode);
SetOptionsFromMode(bugreport_mode, this);
@@ -2227,11 +2234,11 @@
}
bool Dumpstate::DumpOptions::ValidateOptions() const {
- if (fd != -1 && !do_zip_file) {
+ if (bugreport_fd.get() != -1 && !do_zip_file) {
return false;
}
- bool has_out_file_options = !use_outfile.empty() || fd != -1;
+ bool has_out_file_options = !use_outfile.empty() || bugreport_fd.get() != -1;
if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast) &&
!has_out_file_options) {
return false;
@@ -2514,17 +2521,18 @@
switch (status) {
case Dumpstate::RunStatus::OK:
- return 0;
- // TODO(b/111441001): Exit directly in the following cases.
+ exit(0);
case Dumpstate::RunStatus::HELP:
- ShowUsageAndExit(0 /* exit code */);
- break;
+ ShowUsage();
+ exit(0);
case Dumpstate::RunStatus::INVALID_INPUT:
- ExitOnInvalidArgs();
- break;
+ fprintf(stderr, "Invalid combination of args\n");
+ ShowUsage();
+ exit(1);
case Dumpstate::RunStatus::ERROR:
- exit(-1);
- break;
+ exit(2);
+ default:
+ fprintf(stderr, "Unknown status: %d\n", status);
+ exit(2);
}
- return 0;
}
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 7ac25e4..529111e 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -342,9 +342,11 @@
bool wifi_only = false;
// Whether progress updates should be published.
bool do_progress_updates = false;
- // File descriptor to output zip file. -1 indicates not set. Takes precedence over
- // use_outfile.
- int fd = -1;
+ // File descriptor to output zip file. Takes precedence over use_outfile.
+ android::base::unique_fd bugreport_fd;
+ // File descriptor to screenshot file.
+ // TODO(b/111441001): Use this fd.
+ android::base::unique_fd screenshot_fd;
// Partial path to output file.
std::string use_outfile;
// TODO: rename to MODE.
@@ -360,7 +362,8 @@
RunStatus Initialize(int argc, char* argv[]);
/* Initializes options from the requested mode. */
- void Initialize(BugreportMode bugreport_mode);
+ void Initialize(BugreportMode bugreport_mode, const android::base::unique_fd& bugreport_fd,
+ const android::base::unique_fd& screenshot_fd);
/* Returns true if the options set so far are consistent. */
bool ValidateOptions() const;
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
index 61a5ef5..c57775f 100644
--- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -53,6 +53,19 @@
DumpstateListener(int fd, std::shared_ptr<std::vector<SectionInfo>> sections)
: outFd_(fd), max_progress_(5000), sections_(sections) {
}
+ binder::Status onProgress(int32_t progress) override {
+ dprintf(outFd_, "\rIn progress %d", progress);
+ return binder::Status::ok();
+ }
+ binder::Status onError(int32_t error_code) override {
+ dprintf(outFd_, "\rError %d", error_code);
+ return binder::Status::ok();
+ }
+ binder::Status onFinished(int64_t duration_ms, const ::std::string&,
+ const ::std::string&) override {
+ dprintf(outFd_, "\rFinished in %lld", (long long) duration_ms);
+ return binder::Status::ok();
+ }
binder::Status onProgressUpdated(int32_t progress) override {
dprintf(outFd_, "\rIn progress %d/%d", progress, max_progress_);
return binder::Status::ok();
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index fcf9371..98ee1b0 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -59,6 +59,10 @@
class DumpstateListenerMock : public IDumpstateListener {
public:
+ MOCK_METHOD1(onProgress, binder::Status(int32_t progress));
+ MOCK_METHOD1(onError, binder::Status(int32_t error_code));
+ MOCK_METHOD3(onFinished, binder::Status(int64_t duration_ms, const ::std::string& title,
+ const ::std::string& description));
MOCK_METHOD1(onProgressUpdated, binder::Status(int32_t progress));
MOCK_METHOD1(onMaxProgressUpdated, binder::Status(int32_t max_progress));
MOCK_METHOD4(onSectionComplete, binder::Status(const ::std::string& name, int32_t status,
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index d97ffbf..990fd43 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -871,7 +871,11 @@
is_java_process ? 5 : 20, fd);
if (ret == -1) {
- dprintf(fd, "dumping failed, likely due to a timeout\n");
+ // For consistency, the header and footer to this message match those
+ // dumped by debuggerd in the success case.
+ dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
+ dprintf(fd, "Dump failed, likely due to a timeout.\n");
+ dprintf(fd, "---- end %d ----", pid);
timeout_failures++;
continue;
}
diff --git a/cmds/lshal/Command.h b/cmds/lshal/Command.h
index 4f128ab..e19e3f7 100644
--- a/cmds/lshal/Command.h
+++ b/cmds/lshal/Command.h
@@ -27,7 +27,7 @@
// Base class for all *Commands
class Command {
public:
- Command(Lshal& lshal) : mLshal(lshal) {}
+ explicit Command(Lshal& lshal) : mLshal(lshal) {}
virtual ~Command() = default;
// Expect optind to be set by Lshal::main and points to the next argument
// to process.
diff --git a/cmds/lshal/DebugCommand.h b/cmds/lshal/DebugCommand.h
index 6e12008..3c3f56f 100644
--- a/cmds/lshal/DebugCommand.h
+++ b/cmds/lshal/DebugCommand.h
@@ -31,7 +31,7 @@
class DebugCommand : public Command {
public:
- DebugCommand(Lshal &lshal) : Command(lshal) {}
+ explicit DebugCommand(Lshal &lshal) : Command(lshal) {}
~DebugCommand() = default;
Status main(const Arg &arg) override;
void usage() const override;
diff --git a/cmds/lshal/HelpCommand.h b/cmds/lshal/HelpCommand.h
index cc709f8..da0cba6 100644
--- a/cmds/lshal/HelpCommand.h
+++ b/cmds/lshal/HelpCommand.h
@@ -31,7 +31,7 @@
class HelpCommand : public Command {
public:
- HelpCommand(Lshal &lshal) : Command(lshal) {}
+ explicit HelpCommand(Lshal &lshal) : Command(lshal) {}
~HelpCommand() = default;
Status main(const Arg &arg) override;
void usage() const override;
diff --git a/cmds/lshal/ListCommand.h b/cmds/lshal/ListCommand.h
index 3f7321d..85195fc 100644
--- a/cmds/lshal/ListCommand.h
+++ b/cmds/lshal/ListCommand.h
@@ -57,7 +57,7 @@
class ListCommand : public Command {
public:
- ListCommand(Lshal &lshal) : Command(lshal) {}
+ explicit ListCommand(Lshal &lshal) : Command(lshal) {}
virtual ~ListCommand() = default;
Status main(const Arg &arg) override;
void usage() const override;
diff --git a/cmds/lshal/NullableOStream.h b/cmds/lshal/NullableOStream.h
index ab37a04..737d3a2 100644
--- a/cmds/lshal/NullableOStream.h
+++ b/cmds/lshal/NullableOStream.h
@@ -25,8 +25,8 @@
template<typename S>
class NullableOStream {
public:
- NullableOStream(S &os) : mOs(&os) {}
- NullableOStream(S *os) : mOs(os) {}
+ explicit NullableOStream(S &os) : mOs(&os) {}
+ explicit NullableOStream(S *os) : mOs(os) {}
NullableOStream &operator=(S &os) {
mOs = &os;
return *this;
@@ -57,7 +57,7 @@
S& buf() const {
return *mOs;
}
- operator bool() const {
+ operator bool() const { // NOLINT(google-explicit-constructor)
return mOs != nullptr;
}
private:
diff --git a/cmds/lshal/TableEntry.h b/cmds/lshal/TableEntry.h
index 7294b0a..601b7e2 100644
--- a/cmds/lshal/TableEntry.h
+++ b/cmds/lshal/TableEntry.h
@@ -149,7 +149,7 @@
class MergedTable {
public:
- MergedTable(std::vector<const Table*>&& tables) : mTables(std::move(tables)) {}
+ explicit MergedTable(std::vector<const Table*>&& tables) : mTables(std::move(tables)) {}
TextTable createTextTable();
private:
std::vector<const Table*> mTables;
diff --git a/cmds/lshal/TextTable.h b/cmds/lshal/TextTable.h
index 91d522a..301b4bd 100644
--- a/cmds/lshal/TextTable.h
+++ b/cmds/lshal/TextTable.h
@@ -33,11 +33,11 @@
TextTableRow() {}
// A row of cells.
- TextTableRow(std::vector<std::string>&& v) : mFields(std::move(v)) {}
+ explicit TextTableRow(std::vector<std::string>&& v) : mFields(std::move(v)) {}
// A single comment string.
- TextTableRow(std::string&& s) : mLine(std::move(s)) {}
- TextTableRow(const std::string& s) : mLine(s) {}
+ explicit TextTableRow(std::string&& s) : mLine(std::move(s)) {}
+ explicit TextTableRow(const std::string& s) : mLine(s) {}
// Whether this row is an actual row of cells.
bool isRow() const { return !fields().empty(); }
diff --git a/cmds/lshal/Timeout.h b/cmds/lshal/Timeout.h
index 58119a6..46d8177 100644
--- a/cmds/lshal/Timeout.h
+++ b/cmds/lshal/Timeout.h
@@ -29,7 +29,7 @@
class BackgroundTaskState {
public:
- BackgroundTaskState(std::function<void(void)> &&func)
+ explicit BackgroundTaskState(std::function<void(void)> &&func)
: mFunc(std::forward<decltype(func)>(func)) {}
void notify() {
std::unique_lock<std::mutex> lock(mMutex);
diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp
index 8d7405b..fc8d58b 100644
--- a/cmds/lshal/test.cpp
+++ b/cmds/lshal/test.cpp
@@ -191,7 +191,7 @@
// expose protected fields and methods for ListCommand
class MockListCommand : public ListCommand {
public:
- MockListCommand(Lshal* lshal) : ListCommand(*lshal) {}
+ explicit MockListCommand(Lshal* lshal) : ListCommand(*lshal) {}
Status parseArgs(const Arg& arg) { return ListCommand::parseArgs(arg); }
Status main(const Arg& arg) { return ListCommand::main(arg); }
@@ -308,7 +308,7 @@
// Fake service returned by mocked IServiceManager::get.
class TestService : public IBase {
public:
- TestService(pid_t id) : mId(id) {}
+ explicit TestService(pid_t id) : mId(id) {}
hardware::Return<void> getDebugInfo(getDebugInfo_cb cb) override {
cb({ mId /* pid */, getPtr(mId), DebugInfo::Architecture::IS_64BIT });
return hardware::Void();
diff --git a/cmds/servicemanager/binder.c b/cmds/servicemanager/binder.c
index fade8cf..cf3b172 100644
--- a/cmds/servicemanager/binder.c
+++ b/cmds/servicemanager/binder.c
@@ -146,7 +146,19 @@
int binder_become_context_manager(struct binder_state *bs)
{
- return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
+ struct flat_binder_object obj;
+ memset(&obj, 0, sizeof(obj));
+ obj.flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX;
+
+ int result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR_EXT, &obj);
+
+ // fallback to original method
+ if (result != 0) {
+ android_errorWriteLog(0x534e4554, "121035042");
+
+ result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
+ }
+ return result;
}
int binder_write(struct binder_state *bs, void *data, size_t len)
@@ -240,13 +252,28 @@
#endif
ptr += sizeof(struct binder_ptr_cookie);
break;
+ case BR_TRANSACTION_SEC_CTX:
case BR_TRANSACTION: {
- struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
- if ((end - ptr) < sizeof(*txn)) {
- ALOGE("parse: txn too small!\n");
- return -1;
+ struct binder_transaction_data_secctx txn;
+ if (cmd == BR_TRANSACTION_SEC_CTX) {
+ if ((end - ptr) < sizeof(struct binder_transaction_data_secctx)) {
+ ALOGE("parse: txn too small (binder_transaction_data_secctx)!\n");
+ return -1;
+ }
+ memcpy(&txn, (void*) ptr, sizeof(struct binder_transaction_data_secctx));
+ ptr += sizeof(struct binder_transaction_data_secctx);
+ } else /* BR_TRANSACTION */ {
+ if ((end - ptr) < sizeof(struct binder_transaction_data)) {
+ ALOGE("parse: txn too small (binder_transaction_data)!\n");
+ return -1;
+ }
+ memcpy(&txn.transaction_data, (void*) ptr, sizeof(struct binder_transaction_data));
+ ptr += sizeof(struct binder_transaction_data);
+
+ txn.secctx = 0;
}
- binder_dump_txn(txn);
+
+ binder_dump_txn(&txn.transaction_data);
if (func) {
unsigned rdata[256/4];
struct binder_io msg;
@@ -254,15 +281,14 @@
int res;
bio_init(&reply, rdata, sizeof(rdata), 4);
- bio_init_from_txn(&msg, txn);
- res = func(bs, txn, &msg, &reply);
- if (txn->flags & TF_ONE_WAY) {
- binder_free_buffer(bs, txn->data.ptr.buffer);
+ bio_init_from_txn(&msg, &txn.transaction_data);
+ res = func(bs, &txn, &msg, &reply);
+ if (txn.transaction_data.flags & TF_ONE_WAY) {
+ binder_free_buffer(bs, txn.transaction_data.data.ptr.buffer);
} else {
- binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
+ binder_send_reply(bs, &reply, txn.transaction_data.data.ptr.buffer, res);
}
}
- ptr += sizeof(*txn);
break;
}
case BR_REPLY: {
diff --git a/cmds/servicemanager/binder.h b/cmds/servicemanager/binder.h
index c95b33f..70be3b4 100644
--- a/cmds/servicemanager/binder.h
+++ b/cmds/servicemanager/binder.h
@@ -5,7 +5,8 @@
#define _BINDER_H_
#include <sys/ioctl.h>
-#include <linux/android/binder.h>
+
+#include "binder_kernel.h"
struct binder_state;
@@ -42,7 +43,7 @@
};
typedef int (*binder_handler)(struct binder_state *bs,
- struct binder_transaction_data *txn,
+ struct binder_transaction_data_secctx *txn,
struct binder_io *msg,
struct binder_io *reply);
diff --git a/cmds/servicemanager/binder_kernel.h b/cmds/servicemanager/binder_kernel.h
new file mode 100644
index 0000000..19fd773
--- /dev/null
+++ b/cmds/servicemanager/binder_kernel.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_BINDER_KERNEL_H
+#define ANDROID_BINDER_KERNEL_H
+
+#include <linux/android/binder.h>
+
+/**
+ * This file exists because the uapi kernel headers in bionic are built
+ * from upstream kernel headers only, and not all of the hwbinder kernel changes
+ * have made it upstream yet. Therefore, the modifications to the
+ * binder header are added locally in this file.
+ */
+
+enum {
+ FLAT_BINDER_FLAG_TXN_SECURITY_CTX = 0x1000,
+};
+
+#define BINDER_SET_CONTEXT_MGR_EXT _IOW('b', 13, struct flat_binder_object)
+
+struct binder_transaction_data_secctx {
+ struct binder_transaction_data transaction_data;
+ binder_uintptr_t secctx;
+};
+
+enum {
+ BR_TRANSACTION_SEC_CTX = _IOR('r', 2,
+ struct binder_transaction_data_secctx),
+};
+
+
+#endif // ANDROID_BINDER_KERNEL_H
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index 79cd6b5..ec3fac5 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -61,14 +61,14 @@
static char *service_manager_context;
static struct selabel_handle* sehandle;
-static bool check_mac_perms(pid_t spid, uid_t uid, const char *tctx, const char *perm, const char *name)
+static bool check_mac_perms(pid_t spid, const char* sid, uid_t uid, const char *tctx, const char *perm, const char *name)
{
- char *sctx = NULL;
+ char *lookup_sid = NULL;
const char *class = "service_manager";
bool allowed;
struct audit_data ad;
- if (getpidcon(spid, &sctx) < 0) {
+ if (sid == NULL && getpidcon(spid, &lookup_sid) < 0) {
ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid);
return false;
}
@@ -77,19 +77,23 @@
ad.uid = uid;
ad.name = name;
- int result = selinux_check_access(sctx, tctx, class, perm, (void *) &ad);
+ if (sid == NULL) {
+ android_errorWriteLog(0x534e4554, "121035042");
+ }
+
+ int result = selinux_check_access(sid ? sid : lookup_sid, tctx, class, perm, (void *) &ad);
allowed = (result == 0);
- freecon(sctx);
+ freecon(lookup_sid);
return allowed;
}
-static bool check_mac_perms_from_getcon(pid_t spid, uid_t uid, const char *perm)
+static bool check_mac_perms_from_getcon(pid_t spid, const char* sid, uid_t uid, const char *perm)
{
- return check_mac_perms(spid, uid, service_manager_context, perm, NULL);
+ return check_mac_perms(spid, sid, uid, service_manager_context, perm, NULL);
}
-static bool check_mac_perms_from_lookup(pid_t spid, uid_t uid, const char *perm, const char *name)
+static bool check_mac_perms_from_lookup(pid_t spid, const char* sid, uid_t uid, const char *perm, const char *name)
{
bool allowed;
char *tctx = NULL;
@@ -104,12 +108,12 @@
return false;
}
- allowed = check_mac_perms(spid, uid, tctx, perm, name);
+ allowed = check_mac_perms(spid, sid, uid, tctx, perm, name);
freecon(tctx);
return allowed;
}
-static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)
+static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid)
{
const char *perm = "add";
@@ -117,19 +121,19 @@
return 0; /* Don't allow apps to register services */
}
- return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0;
+ return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0;
}
-static int svc_can_list(pid_t spid, uid_t uid)
+static int svc_can_list(pid_t spid, const char* sid, uid_t uid)
{
const char *perm = "list";
- return check_mac_perms_from_getcon(spid, uid, perm) ? 1 : 0;
+ return check_mac_perms_from_getcon(spid, sid, uid, perm) ? 1 : 0;
}
-static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)
+static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid)
{
const char *perm = "find";
- return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0;
+ return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0;
}
struct svcinfo
@@ -175,7 +179,7 @@
};
-uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid)
+uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid, const char* sid)
{
struct svcinfo *si = find_svc(s, len);
@@ -192,7 +196,7 @@
}
}
- if (!svc_can_find(s, len, spid, uid)) {
+ if (!svc_can_find(s, len, spid, sid, uid)) {
return 0;
}
@@ -200,7 +204,7 @@
}
int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint32_t handle,
- uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid) {
+ uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid, const char* sid) {
struct svcinfo *si;
//ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle,
@@ -209,7 +213,7 @@
if (!handle || (len == 0) || (len > 127))
return -1;
- if (!svc_can_register(s, len, spid, uid)) {
+ if (!svc_can_register(s, len, spid, sid, uid)) {
ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
str8(s, len), handle, uid);
return -1;
@@ -248,7 +252,7 @@
}
int svcmgr_handler(struct binder_state *bs,
- struct binder_transaction_data *txn,
+ struct binder_transaction_data_secctx *txn_secctx,
struct binder_io *msg,
struct binder_io *reply)
{
@@ -260,6 +264,8 @@
int allow_isolated;
uint32_t dumpsys_priority;
+ struct binder_transaction_data *txn = &txn_secctx->transaction_data;
+
//ALOGI("target=%p code=%d pid=%d uid=%d\n",
// (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid);
@@ -305,7 +311,8 @@
if (s == NULL) {
return -1;
}
- handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid);
+ handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid,
+ (const char*) txn_secctx->secctx);
if (!handle)
break;
bio_put_ref(reply, handle);
@@ -320,7 +327,7 @@
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
dumpsys_priority = bio_get_uint32(msg);
if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority,
- txn->sender_pid))
+ txn->sender_pid, (const char*) txn_secctx->secctx))
return -1;
break;
@@ -328,7 +335,7 @@
uint32_t n = bio_get_uint32(msg);
uint32_t req_dumpsys_priority = bio_get_uint32(msg);
- if (!svc_can_list(txn->sender_pid, txn->sender_euid)) {
+ if (!svc_can_list(txn->sender_pid, (const char*) txn_secctx->secctx, txn->sender_euid)) {
ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
txn->sender_euid);
return -1;
diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp
index 384f21f..34886a9 100644
--- a/cmds/surfacereplayer/replayer/Replayer.cpp
+++ b/cmds/surfacereplayer/replayer/Replayer.cpp
@@ -286,10 +286,6 @@
std::thread(&Replayer::createSurfaceControl, this, increment.surface_creation(), event)
.detach();
} break;
- case increment.kSurfaceDeletion: {
- std::thread(&Replayer::deleteSurfaceControl, this, increment.surface_deletion(), event)
- .detach();
- } break;
case increment.kBufferUpdate: {
std::lock_guard<std::mutex> lock1(mLayerLock);
std::lock_guard<std::mutex> lock2(mBufferQueueSchedulerLock);
@@ -628,47 +624,10 @@
return NO_ERROR;
}
-status_t Replayer::deleteSurfaceControl(
- const SurfaceDeletion& delete_, const std::shared_ptr<Event>& event) {
- ALOGV("Deleting %d Surface Control", delete_.id());
- event->readyToExecute();
-
- std::lock_guard<std::mutex> lock1(mPendingLayersLock);
-
- mLayersPendingRemoval.push_back(delete_.id());
-
- const auto& iterator = mBufferQueueSchedulers.find(delete_.id());
- if (iterator != mBufferQueueSchedulers.end()) {
- (*iterator).second->stopScheduling();
- }
-
- std::lock_guard<std::mutex> lock2(mLayerLock);
- if (mLayers[delete_.id()] != nullptr) {
- mComposerClient->destroySurface(mLayers[delete_.id()]->getHandle());
- }
-
- return NO_ERROR;
-}
-
-void Replayer::doDeleteSurfaceControls() {
- std::lock_guard<std::mutex> lock1(mPendingLayersLock);
- std::lock_guard<std::mutex> lock2(mLayerLock);
- if (!mLayersPendingRemoval.empty()) {
- for (int id : mLayersPendingRemoval) {
- mLayers.erase(id);
- mColors.erase(id);
- mBufferQueueSchedulers.erase(id);
- }
- mLayersPendingRemoval.clear();
- }
-}
-
status_t Replayer::injectVSyncEvent(
const VSyncEvent& vSyncEvent, const std::shared_ptr<Event>& event) {
ALOGV("Injecting VSync Event");
- doDeleteSurfaceControls();
-
event->readyToExecute();
SurfaceComposerClient::injectVSync(vSyncEvent.when());
diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h
index 120dd9b..ad807ee 100644
--- a/cmds/surfacereplayer/replayer/Replayer.h
+++ b/cmds/surfacereplayer/replayer/Replayer.h
@@ -70,8 +70,6 @@
status_t doTransaction(const Transaction& transaction, const std::shared_ptr<Event>& event);
status_t createSurfaceControl(const SurfaceCreation& create,
const std::shared_ptr<Event>& event);
- status_t deleteSurfaceControl(const SurfaceDeletion& delete_,
- const std::shared_ptr<Event>& event);
status_t injectVSyncEvent(const VSyncEvent& vsyncEvent, const std::shared_ptr<Event>& event);
void createDisplay(const DisplayCreation& create, const std::shared_ptr<Event>& event);
void deleteDisplay(const DisplayDeletion& delete_, const std::shared_ptr<Event>& event);
@@ -120,7 +118,6 @@
void setDisplayProjection(SurfaceComposerClient::Transaction& t,
display_id id, const ProjectionChange& pc);
- void doDeleteSurfaceControls();
void waitUntilTimestamp(int64_t timestamp);
void waitUntilDeferredTransactionLayerExists(
const DeferredTransactionChange& dtc, std::unique_lock<std::mutex>& lock);
diff --git a/headers/media_plugin/media/drm/DrmAPI.h b/headers/media_plugin/media/drm/DrmAPI.h
index aa8bd3d..2ed1cca 100644
--- a/headers/media_plugin/media/drm/DrmAPI.h
+++ b/headers/media_plugin/media/drm/DrmAPI.h
@@ -84,6 +84,7 @@
kDrmPluginEventSessionReclaimed,
kDrmPluginEventExpirationUpdate,
kDrmPluginEventKeysChange,
+ kDrmPluginEventSessionLostState,
};
// Drm keys can be for offline content or for online streaming.
diff --git a/include/OWNERS b/include/OWNERS
new file mode 100644
index 0000000..22be776
--- /dev/null
+++ b/include/OWNERS
@@ -0,0 +1,14 @@
+alexeykuzmin@google.com
+dangittik@google.com
+lajos@google.com
+mathias@google.com
+michaelwr@google.com
+racarr@google.com
+romainguy@android.com
+santoscordon@google.com
+stoza@google.com
+svv@google.com
+
+# For multinetwork.h only.
+lorenzo@google.com
+
diff --git a/include/android/multinetwork.h b/include/android/multinetwork.h
index fa7d908..05d96ff 100644
--- a/include/android/multinetwork.h
+++ b/include/android/multinetwork.h
@@ -112,26 +112,43 @@
#if __ANDROID_API__ >= 29
+enum ResNsendFlags : uint32_t {
+ // Send a single request to a single resolver and fail on timeout or network errors
+ ANDROID_RESOLV_NO_RETRY = 1 << 0,
+
+ // Do not cache the result of the lookup. The lookup may return a result that is already
+ // in the cache, unless the ANDROID_RESOLV_NO_CACHE_LOOKUP flag is also specified.
+ ANDROID_RESOLV_NO_CACHE_STORE = 1 << 1,
+
+ // Don't lookup the request in cache, do not write back the response into the cache
+ ANDROID_RESOLV_NO_CACHE_LOOKUP = 1 << 2,
+};
+
/**
* Look up the {|ns_class|, |ns_type|} Resource Record (RR) associated
* with Domain Name |dname| on the given |network|.
* The typical value for |ns_class| is ns_c_in, while |type| can be any
* record type (for instance, ns_t_aaaa or ns_t_txt).
+ * |flags| is a additional config to control actual querying behavior, see
+ * ResNsendFlags for detail.
*
* Returns a file descriptor to watch for read events, or a negative
* POSIX error code (see errno.h) if an immediate error occurs.
*/
int android_res_nquery(net_handle_t network,
- const char *dname, int ns_class, int ns_type) __INTRODUCED_IN(29);
+ const char *dname, int ns_class, int ns_type,
+ enum ResNsendFlags flags) __INTRODUCED_IN(29);
/**
* Issue the query |msg| on the given |network|.
+ * |flags| is a additional config to control actual querying behavior, see
+ * ResNsendFlags for detail.
*
* Returns a file descriptor to watch for read events, or a negative
* POSIX error code (see errno.h) if an immediate error occurs.
*/
int android_res_nsend(net_handle_t network,
- const uint8_t *msg, size_t msglen) __INTRODUCED_IN(29);
+ const uint8_t *msg, size_t msglen, enum ResNsendFlags flags) __INTRODUCED_IN(29);
/**
* Read a result for the query associated with the |fd| descriptor.
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
new file mode 100644
index 0000000..13b630b
--- /dev/null
+++ b/include/android/surface_control.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @addtogroup NativeActivity Native Activity
+ * @{
+ */
+
+/**
+ * @file surface_control.h
+ */
+
+#ifndef ANDROID_SURFACE_CONTROL_H
+#define ANDROID_SURFACE_CONTROL_H
+
+#include <sys/cdefs.h>
+
+#include <android/hardware_buffer.h>
+#include <android/native_window.h>
+
+__BEGIN_DECLS
+
+#if __ANDROID_API__ >= 29
+
+struct ASurfaceControl;
+
+/**
+ * The SurfaceControl API can be used to provide a heirarchy of surfaces for
+ * composition to the system compositor. ASurfaceControl represents a content node in
+ * this heirarchy.
+ */
+typedef struct ASurfaceControl ASurfaceControl;
+
+/*
+ * Creates an ASurfaceControl with either ANativeWindow or an ASurfaceControl as its parent.
+ * |debug_name| is a debug name associated with this surface. It can be used to
+ * identify this surface in the SurfaceFlinger's layer tree. It must not be
+ * null.
+ *
+ * The caller takes ownership of the ASurfaceControl returned and must release it
+ * using ASurfaceControl_release below.
+ */
+ASurfaceControl* ASurfaceControl_createFromWindow(ANativeWindow* parent, const char* debug_name)
+ __INTRODUCED_IN(29);
+
+ASurfaceControl* ASurfaceControl_create(ASurfaceControl* parent, const char* debug_name)
+ __INTRODUCED_IN(29);
+
+/**
+ * Destroys the |surface_control| object. After releasing the ASurfaceControl the caller no longer
+ * has ownership of the AsurfaceControl.
+ */
+void ASurfaceControl_destroy(ASurfaceControl* surface_control) __INTRODUCED_IN(29);
+
+struct ASurfaceTransaction;
+
+/**
+ * ASurfaceTransaction is a collection of updates to the surface tree that must
+ * be applied atomically.
+ */
+typedef struct ASurfaceTransaction ASurfaceTransaction;
+
+/**
+ * The caller takes ownership of the transaction and must release it using
+ * ASurfaceControl_delete below.
+ */
+ASurfaceTransaction* ASurfaceTransaction_create() __INTRODUCED_IN(29);
+
+/**
+ * Destroys the |transaction| object.
+ */
+void ASurfaceTransaction_delete(ASurfaceTransaction* transaction) __INTRODUCED_IN(29);
+
+/**
+ * Applies the updates accumulated in |transaction|.
+ *
+ * Note that the transaction is guaranteed to be applied atomically. The
+ * transactions which are applied on the same thread are also guaranteed to be
+ * applied in order.
+ */
+void ASurfaceTransaction_apply(ASurfaceTransaction* transaction) __INTRODUCED_IN(29);
+
+/**
+ * Since the transactions are applied asynchronously, the
+ * ASurfaceTransaction_OnComplete callback can be used to be notified when a frame
+ * including the updates in a transaction was presented.
+ *
+ * |context| is the optional context provided by the client that is passed into
+ * the callback.
+ * |present_fence| is the sync fence that signals when the transaction has been presented.
+ * The recipient of the callback takes ownership of the present_fence and is responsible for closing
+ * it.
+ *
+ * It is safe to assume that once the present fence singals, that reads for all buffers,
+ * submitted in previous transactions, which are not in the surface tree after a transaction is
+ * applied, are finished and the buffers may be reused.
+ *
+ * THREADING
+ * The transaction completed callback can be invoked on any thread.
+ */
+typedef void (*ASurfaceTransaction_OnComplete)(void* context, int32_t present_fence);
+
+/**
+ * Sets the callback that will be invoked when the updates from this transaction
+ * are presented. For details on the callback semantics and data, see the
+ * comments on the ASurfaceTransaction_OnComplete declaration above.
+ */
+void ASurfaceTransaction_setOnComplete(ASurfaceTransaction* transaction, void* context,
+ ASurfaceTransaction_OnComplete func) __INTRODUCED_IN(29);
+
+/* Parameter for ASurfaceTransaction_setVisibility */
+enum {
+ ASURFACE_TRANSACTION_VISIBILITY_HIDE = 0,
+ ASURFACE_TRANSACTION_VISIBILITY_SHOW = 1,
+};
+/**
+ * Updates the visibility of |surface_control|. If show is set to
+ * ASURFACE_TRANSACTION_VISIBILITY_HIDE, the |surface_control| and all surfaces in its subtree will
+ * be hidden.
+ */
+void ASurfaceTransaction_setVisibility(ASurfaceTransaction* transaction,
+ ASurfaceControl* surface_control, int8_t visibility)
+ __INTRODUCED_IN(29);
+
+/**
+ * Updates the z order index for |surface_control|. Note that the z order for a surface
+ * is relative to other surfaces which are siblings of this surface. The behavior of sibilings with
+ * the same z order is undefined.
+ *
+ * Z orders may be from MIN_INT32 to MAX_INT32. A layer's default z order index is 0.
+ */
+void ASurfaceTransaction_setZOrder(ASurfaceTransaction* transaction,
+ ASurfaceControl* surface_control, int32_t z_order)
+ __INTRODUCED_IN(29);
+
+/**
+ * Updates the AHardwareBuffer displayed for |surface_control|. If not -1, the
+ * fence_fd should be a file descriptor that is signaled when all pending work
+ * for the buffer is complete and the buffer can be safely read.
+ *
+ * The frameworks takes ownership of the |fence_fd| passed and is responsible
+ * for closing it.
+ */
+void ASurfaceTransaction_setBuffer(ASurfaceTransaction* transaction,
+ ASurfaceControl* surface_control, AHardwareBuffer* buffer,
+ int fence_fd = -1) __INTRODUCED_IN(29);
+
+/**
+ * |source| the sub-rect within the buffer's content to be rendered inside the surface's area
+ * The surface's source rect is clipped by the bounds of its current buffer. The source rect's width
+ * and height must be > 0.
+ *
+ * |destination| specifies the rect in the parent's space where this surface will be drawn. The post
+ * source rect bounds are scaled to fit the destination rect. The surface's destination rect is
+ * clipped by the bounds of its parent. The destination rect's width and height must be > 0.
+ *
+ * |transform| the transform applied after the source rect is applied to the buffer. This parameter
+ * should be set to 0 for no transform. To specify a transfrom use the NATIVE_WINDOW_TRANSFORM_*
+ * enum.
+ */
+void ASurfaceTransaction_setGeometry(ASurfaceTransaction* transaction,
+ ASurfaceControl* surface_control, const ARect& source,
+ const ARect& destination, int32_t transform)
+ __INTRODUCED_IN(29);
+
+
+/* Parameter for ASurfaceTransaction_setBufferTransparency */
+enum {
+ ASURFACE_TRANSACTION_TRANSPARENCY_TRANSPARENT = 0,
+ ASURFACE_TRANSACTION_TRANSPARENCY_TRANSLUCENT = 1,
+ ASURFACE_TRANSACTION_TRANSPARENCY_OPAQUE = 2,
+};
+/**
+ * Updates whether the content for the buffer associated with this surface is
+ * completely opaque. If true, every pixel of content inside the buffer must be
+ * opaque or visual errors can occur.
+ */
+void ASurfaceTransaction_setBufferTransparency(ASurfaceTransaction* transaction,
+ ASurfaceControl* surface_control, int8_t transparency)
+ __INTRODUCED_IN(29);
+
+/**
+ * Updates the region for the content on this surface updated in this
+ * transaction. If unspecified, the complete surface is assumed to be damaged.
+ */
+void ASurfaceTransaction_setDamageRegion(ASurfaceTransaction* transaction,
+ ASurfaceControl* surface_control, const ARect rects[],
+ uint32_t count) __INTRODUCED_IN(29);
+
+#endif // __ANDROID_API__ >= 29
+
+__END_DECLS
+
+#endif // ANDROID_SURFACE_CONTROL_H
diff --git a/include/input/IInputFlinger.h b/include/input/IInputFlinger.h
index 610834d..ff443c6 100644
--- a/include/input/IInputFlinger.h
+++ b/include/input/IInputFlinger.h
@@ -36,7 +36,7 @@
DECLARE_META_INTERFACE(InputFlinger)
virtual void setInputWindows(const Vector<InputWindowInfo>& inputHandles) = 0;
-
+ virtual void transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) = 0;
virtual void registerInputChannel(const sp<InputChannel>& channel) = 0;
virtual void unregisterInputChannel(const sp<InputChannel>& channel) = 0;
};
@@ -50,7 +50,8 @@
enum {
SET_INPUT_WINDOWS_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
REGISTER_INPUT_CHANNEL_TRANSACTION,
- UNREGISTER_INPUT_CHANNEL_TRANSACTION
+ UNREGISTER_INPUT_CHANNEL_TRANSACTION,
+ TRANSFER_TOUCH_FOCUS
};
virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/include/input/Input.h b/include/input/Input.h
index 037270c..2c4a511 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -220,6 +220,27 @@
POLICY_FLAG_PASS_TO_USER = 0x40000000,
};
+/**
+ * Classifications of the current gesture, if available.
+ *
+ * The following values must be kept in sync with MotionEvent.java
+ */
+enum class MotionClassification : uint8_t {
+ /**
+ * No classification is available.
+ */
+ NONE = 0,
+ /**
+ * Too early to classify the current gesture. Need more events. Look for changes in the
+ * upcoming motion events.
+ */
+ AMBIGUOUS_GESTURE = 1,
+ /**
+ * The current gesture likely represents a user intentionally exerting force on the touchscreen.
+ */
+ DEEP_PRESS = 2,
+};
+
/*
* Pointer coordinate data.
*/
@@ -419,6 +440,8 @@
inline void setButtonState(int32_t buttonState) { mButtonState = buttonState; }
+ inline MotionClassification getClassification() const { return mClassification; }
+
inline int32_t getActionButton() const { return mActionButton; }
inline void setActionButton(int32_t button) { mActionButton = button; }
@@ -582,6 +605,7 @@
int32_t edgeFlags,
int32_t metaState,
int32_t buttonState,
+ MotionClassification classification,
float xOffset,
float yOffset,
float xPrecision,
@@ -635,6 +659,7 @@
int32_t mEdgeFlags;
int32_t mMetaState;
int32_t mButtonState;
+ MotionClassification mClassification;
float mXOffset;
float mYOffset;
float mXPrecision;
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 8df83f1..1d4e234 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -23,7 +23,9 @@
#include <binder/BpBinder.h>
#include <binder/TextOutput.h>
+#include <android-base/macros.h>
#include <cutils/sched_policy.h>
+#include <utils/CallStack.h>
#include <utils/Log.h>
#include <utils/SystemClock.h>
#include <utils/threads.h>
@@ -661,6 +663,16 @@
}
if ((flags & TF_ONE_WAY) == 0) {
+ if (UNLIKELY(mCallRestriction != ProcessState::CallRestriction::NONE)) {
+ if (mCallRestriction == ProcessState::CallRestriction::ERROR_IF_NOT_ONEWAY) {
+ ALOGE("Process making non-oneway call but is restricted.");
+ CallStack::logStack("non-oneway call", CallStack::getCurrent(10).get(),
+ ANDROID_LOG_ERROR);
+ } else /* FATAL_IF_NOT_ONEWAY */ {
+ LOG_ALWAYS_FATAL("Process may not make oneway calls.");
+ }
+ }
+
#if 0
if (code == 4) { // relayout
ALOGI(">>>>>> CALLING transaction 4");
@@ -783,7 +795,8 @@
mWorkSource(kUnsetWorkSource),
mPropagateWorkSource(false),
mStrictModePolicy(0),
- mLastTransactionBinderFlags(0)
+ mLastTransactionBinderFlags(0),
+ mCallRestriction(mProcess->mCallRestriction)
{
pthread_setspecific(gTLS, this);
clearCaller();
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 53f8ddd..3798b61 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -234,6 +234,12 @@
return count;
}
+void ProcessState::setCallRestriction(CallRestriction restriction) {
+ LOG_ALWAYS_FATAL_IF(IPCThreadState::selfOrNull(), "Call restrictions must be set before the threadpool is started.");
+
+ mCallRestriction = restriction;
+}
+
ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
{
const size_t N=mHandleToObject.size();
@@ -426,6 +432,7 @@
, mBinderContextUserData(nullptr)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
+ , mCallRestriction(CallRestriction::NONE)
{
if (mDriverFD >= 0) {
// mmap the binder, providing a chunk of virtual address space to receive transactions.
diff --git a/libs/binder/Value.cpp b/libs/binder/Value.cpp
index a28a618..19c57ba 100644
--- a/libs/binder/Value.cpp
+++ b/libs/binder/Value.cpp
@@ -97,7 +97,7 @@
template<typename T> class Value::Content : public Value::ContentBase {
public:
Content() = default;
- Content(const T & value) : mValue(value) { }
+ explicit Content(const T & value) : mValue(value) { }
virtual ~Content() = default;
diff --git a/libs/binder/include/binder/BufferedTextOutput.h b/libs/binder/include/binder/BufferedTextOutput.h
index 9a7c43b..feae93d 100644
--- a/libs/binder/include/binder/BufferedTextOutput.h
+++ b/libs/binder/include/binder/BufferedTextOutput.h
@@ -32,7 +32,7 @@
MULTITHREADED = 0x0001
};
- BufferedTextOutput(uint32_t flags = 0);
+ explicit BufferedTextOutput(uint32_t flags = 0);
virtual ~BufferedTextOutput();
virtual status_t print(const char* txt, size_t len);
diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h
index 5ec02b1..f6381f7 100644
--- a/libs/binder/include/binder/IInterface.h
+++ b/libs/binder/include/binder/IInterface.h
@@ -124,7 +124,9 @@
#define CHECK_INTERFACE(interface, data, reply) \
- if (!(data).checkInterface(this)) { return PERMISSION_DENIED; } \
+ do { \
+ if (!(data).checkInterface(this)) { return PERMISSION_DENIED; } \
+ } while (false) \
// ----------------------------------------------------------------------
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 26e8c0b..a6b0f7e 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -183,6 +183,8 @@
int32_t mStrictModePolicy;
int32_t mLastTransactionBinderFlags;
IPCThreadStateBase *mIPCThreadStateBase;
+
+ ProcessState::CallRestriction mCallRestriction;
};
}; // namespace android
diff --git a/libs/binder/include/binder/IpPrefix.h b/libs/binder/include/binder/IpPrefix.h
index dd5bc3a..c7e7a50 100644
--- a/libs/binder/include/binder/IpPrefix.h
+++ b/libs/binder/include/binder/IpPrefix.h
@@ -74,8 +74,8 @@
private:
union InternalUnion {
InternalUnion() = default;
- InternalUnion(const struct in6_addr &addr):mIn6Addr(addr) { };
- InternalUnion(const struct in_addr &addr):mInAddr(addr) { };
+ explicit InternalUnion(const struct in6_addr &addr):mIn6Addr(addr) { };
+ explicit InternalUnion(const struct in_addr &addr):mInAddr(addr) { };
struct in6_addr mIn6Addr;
struct in_addr mInAddr;
} mUnion;
diff --git a/libs/binder/include/binder/MemoryDealer.h b/libs/binder/include/binder/MemoryDealer.h
index fe5a31d..b483be0 100644
--- a/libs/binder/include/binder/MemoryDealer.h
+++ b/libs/binder/include/binder/MemoryDealer.h
@@ -34,7 +34,7 @@
class MemoryDealer : public RefBase
{
public:
- MemoryDealer(size_t size, const char* name = nullptr,
+ explicit MemoryDealer(size_t size, const char* name = nullptr,
uint32_t flags = 0 /* or bits such as MemoryHeapBase::READ_ONLY */ );
virtual sp<IMemory> allocate(size_t size);
diff --git a/libs/binder/include/binder/MemoryHeapBase.h b/libs/binder/include/binder/MemoryHeapBase.h
index 2f5039d..100d784 100644
--- a/libs/binder/include/binder/MemoryHeapBase.h
+++ b/libs/binder/include/binder/MemoryHeapBase.h
@@ -47,12 +47,12 @@
/*
* maps memory from the given device
*/
- MemoryHeapBase(const char* device, size_t size = 0, uint32_t flags = 0);
+ explicit MemoryHeapBase(const char* device, size_t size = 0, uint32_t flags = 0);
/*
* maps memory from ashmem, with the given name for debugging
*/
- MemoryHeapBase(size_t size, uint32_t flags = 0, char const* name = nullptr);
+ explicit MemoryHeapBase(size_t size, uint32_t flags = 0, char const* name = nullptr);
virtual ~MemoryHeapBase();
diff --git a/libs/binder/include/binder/ParcelFileDescriptor.h b/libs/binder/include/binder/ParcelFileDescriptor.h
index ad950af..662e56e 100644
--- a/libs/binder/include/binder/ParcelFileDescriptor.h
+++ b/libs/binder/include/binder/ParcelFileDescriptor.h
@@ -31,7 +31,7 @@
public:
ParcelFileDescriptor();
explicit ParcelFileDescriptor(android::base::unique_fd fd);
- explicit ParcelFileDescriptor(ParcelFileDescriptor&& other) : mFd(std::move(other.mFd)) { }
+ ParcelFileDescriptor(ParcelFileDescriptor&& other) : mFd(std::move(other.mFd)) { }
~ParcelFileDescriptor() override;
int get() const { return mFd.get(); }
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index 13f67ba..224cb36 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -77,10 +77,22 @@
ssize_t getKernelReferences(size_t count, uintptr_t* buf);
+ enum class CallRestriction {
+ // all calls okay
+ NONE,
+ // log when calls are blocking
+ ERROR_IF_NOT_ONEWAY,
+ // abort process on blocking calls
+ FATAL_IF_NOT_ONEWAY,
+ };
+ // Sets calling restrictions for all transactions in this process. This must be called
+ // before any threads are spawned.
+ void setCallRestriction(CallRestriction restriction);
+
private:
friend class IPCThreadState;
- ProcessState(const char* driver);
+ explicit ProcessState(const char* driver);
~ProcessState();
ProcessState(const ProcessState& o);
@@ -123,6 +135,8 @@
String8 mRootDir;
bool mThreadPoolStarted;
volatile int32_t mThreadPoolSeq;
+
+ CallRestriction mCallRestriction;
};
}; // namespace android
diff --git a/libs/binder/include/binder/TextOutput.h b/libs/binder/include/binder/TextOutput.h
index 851e01f..5b5f766 100644
--- a/libs/binder/include/binder/TextOutput.h
+++ b/libs/binder/include/binder/TextOutput.h
@@ -38,7 +38,7 @@
class Bundle {
public:
- inline Bundle(TextOutput& to) : mTO(to) { to.pushBundle(); }
+ inline explicit Bundle(TextOutput& to) : mTO(to) { to.pushBundle(); }
inline ~Bundle() { mTO.popBundle(); }
private:
TextOutput& mTO;
@@ -80,7 +80,7 @@
class TypeCode
{
public:
- inline TypeCode(uint32_t code);
+ inline explicit TypeCode(uint32_t code);
inline ~TypeCode();
inline uint32_t typeCode() const;
diff --git a/libs/binder/include/binder/Value.h b/libs/binder/include/binder/Value.h
index 4dee3d8..735f40e 100644
--- a/libs/binder/include/binder/Value.h
+++ b/libs/binder/include/binder/Value.h
@@ -74,20 +74,20 @@
bool operator!=(const Value& rhs) const { return !this->operator==(rhs); }
Value(const Value& value);
- Value(const bool& value);
- Value(const int8_t& value);
- Value(const int32_t& value);
- Value(const int64_t& value);
- Value(const double& value);
- Value(const String16& value);
- Value(const std::vector<bool>& value);
- Value(const std::vector<uint8_t>& value);
- Value(const std::vector<int32_t>& value);
- Value(const std::vector<int64_t>& value);
- Value(const std::vector<double>& value);
- Value(const std::vector<String16>& value);
- Value(const os::PersistableBundle& value);
- Value(const binder::Map& value);
+ Value(const bool& value); // NOLINT(google-explicit-constructor)
+ Value(const int8_t& value); // NOLINT(google-explicit-constructor)
+ Value(const int32_t& value); // NOLINT(google-explicit-constructor)
+ Value(const int64_t& value); // NOLINT(google-explicit-constructor)
+ Value(const double& value); // NOLINT(google-explicit-constructor)
+ Value(const String16& value); // NOLINT(google-explicit-constructor)
+ Value(const std::vector<bool>& value); // NOLINT(google-explicit-constructor)
+ Value(const std::vector<uint8_t>& value); // NOLINT(google-explicit-constructor)
+ Value(const std::vector<int32_t>& value); // NOLINT(google-explicit-constructor)
+ Value(const std::vector<int64_t>& value); // NOLINT(google-explicit-constructor)
+ Value(const std::vector<double>& value); // NOLINT(google-explicit-constructor)
+ Value(const std::vector<String16>& value); // NOLINT(google-explicit-constructor)
+ Value(const os::PersistableBundle& value); // NOLINT(google-explicit-constructor)
+ Value(const binder::Map& value); // NOLINT(google-explicit-constructor)
Value& operator=(const Value& rhs);
Value& operator=(const int8_t& rhs);
@@ -153,8 +153,8 @@
// String Convenience Adapters
// ---------------------------
- Value(const String8& value): Value(String16(value)) { }
- Value(const ::std::string& value): Value(String8(value.c_str())) { }
+ explicit Value(const String8& value): Value(String16(value)) { }
+ explicit Value(const ::std::string& value): Value(String8(value.c_str())) { }
void putString(const String8& value) { return putString(String16(value)); }
void putString(const ::std::string& value) { return putString(String8(value.c_str())); }
Value& operator=(const String8& rhs) { return *this = String16(rhs); }
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 1b69dfd..05655c1 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -23,7 +23,11 @@
"include_apex",
],
- cflags: ["-Wall", "-Wextra", "-Werror"],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
srcs: [
"ibinder.cpp",
diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h
index ac592ea..7852298 100644
--- a/libs/binder/ndk/ibinder_internal.h
+++ b/libs/binder/ndk/ibinder_internal.h
@@ -34,7 +34,7 @@
struct ABpBinder;
struct AIBinder : public virtual ::android::RefBase {
- AIBinder(const AIBinder_Class* clazz);
+ explicit AIBinder(const AIBinder_Class* clazz);
virtual ~AIBinder();
bool associateClass(const AIBinder_Class* clazz);
@@ -97,7 +97,7 @@
ABpBinder* asABpBinder() override { return this; }
private:
- ABpBinder(const ::android::sp<::android::IBinder>& binder);
+ explicit ABpBinder(const ::android::sp<::android::IBinder>& binder);
};
struct AIBinder_Class {
@@ -141,7 +141,7 @@
const AIBinder_DeathRecipient_onBinderDied& mOnDied;
};
- AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinderDied onDied);
+ explicit AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinderDied onDied);
binder_status_t linkToDeath(AIBinder* binder, void* cookie);
binder_status_t unlinkToDeath(AIBinder* binder, void* cookie);
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 ff1860e..80773f3 100644
--- a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
@@ -51,7 +51,7 @@
* Convenience operator for implicitly constructing an SpAIBinder from nullptr. This is not
* explicit because it is not taking ownership of anything.
*/
- SpAIBinder(std::nullptr_t) : SpAIBinder() {}
+ SpAIBinder(std::nullptr_t) : SpAIBinder() {} // NOLINT(google-explicit-constructor)
/**
* This will delete the underlying object if it exists. See operator=.
diff --git a/libs/binder/ndk/include_ndk/android/binder_interface_utils.h b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
index 1532725..a42c60b 100644
--- a/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
@@ -137,7 +137,7 @@
template <typename INTERFACE>
class BpCInterface : public INTERFACE {
public:
- BpCInterface(const SpAIBinder& binder) : mBinder(binder) {}
+ explicit BpCInterface(const SpAIBinder& binder) : mBinder(binder) {}
virtual ~BpCInterface() {}
SpAIBinder asBinder() override;
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index ee7132f..f0d25f7 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -87,6 +87,11 @@
AStatus_getStatus;
AStatus_isOk;
AStatus_newOk;
+ ABinderProcess_joinThreadPool; # apex
+ ABinderProcess_setThreadPoolMaxThreadCount; # apex
+ ABinderProcess_startThreadPool; # apex
+ AServiceManager_addService; # apex
+ AServiceManager_getService; # apex
local:
*;
};
diff --git a/libs/binder/ndk/parcel_internal.h b/libs/binder/ndk/parcel_internal.h
index f292309..6b7295e 100644
--- a/libs/binder/ndk/parcel_internal.h
+++ b/libs/binder/ndk/parcel_internal.h
@@ -27,7 +27,8 @@
const ::android::Parcel* get() const { return mParcel; }
::android::Parcel* get() { return mParcel; }
- AParcel(const AIBinder* binder) : AParcel(binder, new ::android::Parcel, true /*owns*/) {}
+ explicit AParcel(const AIBinder* binder)
+ : AParcel(binder, new ::android::Parcel, true /*owns*/) {}
AParcel(const AIBinder* binder, ::android::Parcel* parcel, bool owns)
: mBinder(binder), mParcel(parcel), mOwns(owns) {}
diff --git a/libs/binder/ndk/scripts/init_map.sh b/libs/binder/ndk/scripts/init_map.sh
index 1f74e43..3529b72 100755
--- a/libs/binder/ndk/scripts/init_map.sh
+++ b/libs/binder/ndk/scripts/init_map.sh
@@ -10,6 +10,10 @@
grep -oP "AParcel_[a-zA-Z0-9_]+(?=\()" include_ndk/android/binder_parcel.h;
grep -oP "AStatus_[a-zA-Z0-9_]+(?=\()" include_ndk/android/binder_status.h;
} | sort | uniq | awk '{ print " " $0 ";"; }'
+{
+ grep -oP "AServiceManager_[a-zA-Z0-9_]+(?=\()" include_apex/android/binder_manager.h;
+ grep -oP "ABinderProcess_[a-zA-Z0-9_]+(?=\()" include_apex/android/binder_process.h;
+} | sort | uniq | awk '{ print " " $0 "; # apex"; }'
echo " local:"
echo " *;"
echo "};"
diff --git a/libs/binder/ndk/status_internal.h b/libs/binder/ndk/status_internal.h
index d39f0d8..f6227f7 100644
--- a/libs/binder/ndk/status_internal.h
+++ b/libs/binder/ndk/status_internal.h
@@ -23,7 +23,7 @@
struct AStatus {
AStatus() {} // ok
- AStatus(::android::binder::Status&& status) : mStatus(std::move(status)) {}
+ explicit AStatus(::android::binder::Status&& status) : mStatus(std::move(status)) {}
::android::binder::Status* get() { return &mStatus; }
const ::android::binder::Status* get() const { return &mStatus; }
diff --git a/libs/binder/ndk/test/iface.cpp b/libs/binder/ndk/test/iface.cpp
index 6ef964e..64832f3 100644
--- a/libs/binder/ndk/test/iface.cpp
+++ b/libs/binder/ndk/test/iface.cpp
@@ -74,7 +74,7 @@
class BpFoo : public IFoo {
public:
- BpFoo(AIBinder* binder) : mBinder(binder) {}
+ explicit BpFoo(AIBinder* binder) : mBinder(binder) {}
virtual ~BpFoo() { AIBinder_decStrong(mBinder); }
virtual binder_status_t doubleNumber(int32_t in, int32_t* out) {
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index ae04b0f..78f1159 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -233,7 +233,7 @@
{
public:
BinderLibTestBundle(void) {}
- BinderLibTestBundle(const Parcel *source) : m_isValid(false) {
+ explicit BinderLibTestBundle(const Parcel *source) : m_isValid(false) {
int32_t mark;
int32_t bundleLen;
size_t pos;
@@ -1079,7 +1079,7 @@
class BinderLibTestService : public BBinder
{
public:
- BinderLibTestService(int32_t id)
+ explicit BinderLibTestService(int32_t id)
: m_id(id)
, m_nextServerId(id + 1)
, m_serverStartRequested(false)
diff --git a/libs/binder/tests/schd-dbg.cpp b/libs/binder/tests/schd-dbg.cpp
index 6cf7f36..ec9534a 100644
--- a/libs/binder/tests/schd-dbg.cpp
+++ b/libs/binder/tests/schd-dbg.cpp
@@ -218,7 +218,7 @@
uint64_t m_total_time = 0;
uint64_t m_miss = 0;
bool tracing;
- Results(bool _tracing) : tracing(_tracing) {
+ explicit Results(bool _tracing) : tracing(_tracing) {
}
inline bool miss_deadline(uint64_t nano) {
return nano > deadline_us * 1000;
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index d1c732b..3521e89 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -121,6 +121,7 @@
],
shared_libs: [
+ "android.frameworks.bufferhub@1.0",
"android.hardware.graphics.common@1.1",
"libbase",
"libsync",
@@ -153,6 +154,7 @@
"BufferHubProducer.cpp",
],
exclude_shared_libs: [
+ "android.frameworks.bufferhub@1.0",
"libbufferhub",
"libbufferhubqueue",
"libpdx_default_transport",
diff --git a/libs/gui/BufferHubProducer.cpp b/libs/gui/BufferHubProducer.cpp
index 16952a6..4be014f 100644
--- a/libs/gui/BufferHubProducer.cpp
+++ b/libs/gui/BufferHubProducer.cpp
@@ -64,13 +64,13 @@
} else if (buffers_[slot].mGraphicBuffer != nullptr) {
ALOGE("requestBuffer: slot %d is not empty.", slot);
return BAD_VALUE;
- } else if (buffers_[slot].mBufferProducer == nullptr) {
+ } else if (buffers_[slot].mProducerBuffer == nullptr) {
ALOGE("requestBuffer: slot %d is not dequeued.", slot);
return BAD_VALUE;
}
- const auto& buffer_producer = buffers_[slot].mBufferProducer;
- sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
+ const auto& producer_buffer = buffers_[slot].mProducerBuffer;
+ sp<GraphicBuffer> graphic_buffer = producer_buffer->buffer()->buffer();
buffers_[slot].mGraphicBuffer = graphic_buffer;
buffers_[slot].mRequestBufferCalled = true;
@@ -158,19 +158,19 @@
}
size_t slot = 0;
- std::shared_ptr<BufferProducer> buffer_producer;
+ std::shared_ptr<ProducerBuffer> producer_buffer;
for (size_t retry = 0; retry < BufferHubQueue::kMaxQueueCapacity; retry++) {
LocalHandle fence;
auto buffer_status = queue_->Dequeue(dequeue_timeout_ms_, &slot, &fence);
if (!buffer_status) return NO_MEMORY;
- buffer_producer = buffer_status.take();
- if (!buffer_producer) return NO_MEMORY;
+ producer_buffer = buffer_status.take();
+ if (!producer_buffer) return NO_MEMORY;
- if (width == buffer_producer->width() && height == buffer_producer->height() &&
- uint32_t(format) == buffer_producer->format()) {
- // The producer queue returns a buffer producer matches the request.
+ if (width == producer_buffer->width() && height == producer_buffer->height() &&
+ uint32_t(format) == producer_buffer->format()) {
+ // The producer queue returns a producer buffer matches the request.
break;
}
@@ -179,8 +179,8 @@
ALOGI("dequeueBuffer: requested buffer (w=%u, h=%u, format=%u) is different "
"from the buffer returned at slot: %zu (w=%u, h=%u, format=%u). Need "
"re-allocattion.",
- width, height, format, slot, buffer_producer->width(), buffer_producer->height(),
- buffer_producer->format());
+ width, height, format, slot, producer_buffer->width(), producer_buffer->height(),
+ producer_buffer->format());
// Mark the slot as reallocating, so that later we can set
// BUFFER_NEEDS_REALLOCATION when the buffer actually get dequeued.
buffers_[slot].mIsReallocating = true;
@@ -249,18 +249,18 @@
ALOGE("detachBuffer: buffer in slot %zu has not been requested", slot);
return BAD_VALUE;
}
- std::shared_ptr<BufferProducer> buffer_producer = queue_->GetBuffer(slot);
- if (buffer_producer == nullptr || buffer_producer->buffer() == nullptr) {
- ALOGE("detachBuffer: Invalid BufferProducer at slot %zu.", slot);
+ std::shared_ptr<ProducerBuffer> producer_buffer = queue_->GetBuffer(slot);
+ if (producer_buffer == nullptr || producer_buffer->buffer() == nullptr) {
+ ALOGE("detachBuffer: Invalid ProducerBuffer at slot %zu.", slot);
return BAD_VALUE;
}
- sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
+ sp<GraphicBuffer> graphic_buffer = producer_buffer->buffer()->buffer();
if (graphic_buffer == nullptr) {
ALOGE("detachBuffer: Invalid GraphicBuffer at slot %zu.", slot);
return BAD_VALUE;
}
- // Remove the BufferProducer from the ProducerQueue.
+ // Remove the ProducerBuffer from the ProducerQueue.
status_t error = RemoveBuffer(slot);
if (error != NO_ERROR) {
ALOGE("detachBuffer: Failed to remove buffer, slot=%zu, error=%d.", slot, error);
@@ -269,9 +269,9 @@
// Here we need to convert the existing ProducerBuffer into a DetachedBufferHandle and inject
// the handle into the GraphicBuffer object at the requested slot.
- auto status_or_handle = buffer_producer->Detach();
+ auto status_or_handle = producer_buffer->Detach();
if (!status_or_handle.ok()) {
- ALOGE("detachBuffer: Failed to detach from a BufferProducer at slot %zu, error=%d.", slot,
+ ALOGE("detachBuffer: Failed to detach from a ProducerBuffer at slot %zu, error=%d.", slot,
status_or_handle.error());
return BAD_VALUE;
}
@@ -301,14 +301,14 @@
// sequence, except for two things:
//
// 1) It is unnecessary to know the dimensions, format, or usage of the next buffer, i.e. the
- // function just returns whatever BufferProducer is available from the ProducerQueue and no
+ // function just returns whatever ProducerBuffer is available from the ProducerQueue and no
// buffer allocation or re-allocation will happen.
// 2) It will not block, since if it cannot find an appropriate buffer to return, it will return
// an error instead.
size_t slot = 0;
LocalHandle fence;
- // First, dequeue a BufferProducer from the ProducerQueue with no timeout. Report error
+ // First, dequeue a ProducerBuffer from the ProducerQueue with no timeout. Report error
// immediately if ProducerQueue::Dequeue() fails.
auto status_or_buffer = queue_->Dequeue(/*timeout=*/0, &slot, &fence);
if (!status_or_buffer.ok()) {
@@ -316,8 +316,8 @@
return NO_MEMORY;
}
- std::shared_ptr<BufferProducer> buffer_producer = status_or_buffer.take();
- if (buffer_producer == nullptr) {
+ std::shared_ptr<ProducerBuffer> producer_buffer = status_or_buffer.take();
+ if (producer_buffer == nullptr) {
ALOGE("detachNextBuffer: Dequeued buffer is null.");
return NO_MEMORY;
}
@@ -331,14 +331,14 @@
buffers_[slot].mBufferState.string());
return BAD_VALUE;
}
- if (buffers_[slot].mBufferProducer == nullptr) {
- ALOGE("detachNextBuffer: BufferProducer at slot %zu is null.", slot);
+ if (buffers_[slot].mProducerBuffer == nullptr) {
+ ALOGE("detachNextBuffer: ProducerBuffer at slot %zu is null.", slot);
return BAD_VALUE;
}
- if (buffers_[slot].mBufferProducer->id() != buffer_producer->id()) {
- ALOGE("detachNextBuffer: BufferProducer at slot %zu has mismatched id, actual: "
+ if (buffers_[slot].mProducerBuffer->id() != producer_buffer->id()) {
+ ALOGE("detachNextBuffer: ProducerBuffer at slot %zu has mismatched id, actual: "
"%d, expected: %d.",
- slot, buffers_[slot].mBufferProducer->id(), buffer_producer->id());
+ slot, buffers_[slot].mProducerBuffer->id(), producer_buffer->id());
return BAD_VALUE;
}
@@ -347,8 +347,8 @@
buffers_[slot].mBufferState.dequeue();
// Second, request the buffer.
- sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
- buffers_[slot].mGraphicBuffer = buffer_producer->buffer()->buffer();
+ sp<GraphicBuffer> graphic_buffer = producer_buffer->buffer()->buffer();
+ buffers_[slot].mGraphicBuffer = producer_buffer->buffer()->buffer();
// Finally, detach the buffer and then return.
status_t error = DetachBufferLocked(slot);
@@ -452,11 +452,11 @@
return BAD_VALUE;
}
- // Post the buffer producer with timestamp in the metadata.
- const auto& buffer_producer = buffers_[slot].mBufferProducer;
+ // Post the producer buffer with timestamp in the metadata.
+ const auto& producer_buffer = buffers_[slot].mProducerBuffer;
// Check input crop is not out of boundary of current buffer.
- Rect buffer_rect(buffer_producer->width(), buffer_producer->height());
+ Rect buffer_rect(producer_buffer->width(), producer_buffer->height());
Rect cropped_rect(Rect::EMPTY_RECT);
crop.intersect(buffer_rect, &cropped_rect);
if (cropped_rect != crop) {
@@ -477,11 +477,11 @@
meta_data.scaling_mode = int32_t(scaling_mode);
meta_data.transform = int32_t(transform);
- buffer_producer->PostAsync(&meta_data, fence_fd);
+ producer_buffer->PostAsync(&meta_data, fence_fd);
buffers_[slot].mBufferState.queue();
- output->width = buffer_producer->width();
- output->height = buffer_producer->height();
+ output->width = producer_buffer->width();
+ output->height = producer_buffer->height();
output->transformHint = 0; // default value, we don't use it yet.
// |numPendingBuffers| counts of the number of buffers that has been enqueued
@@ -519,8 +519,8 @@
return BAD_VALUE;
}
- auto buffer_producer = buffers_[slot].mBufferProducer;
- queue_->Enqueue(buffer_producer, size_t(slot), 0U);
+ auto producer_buffer = buffers_[slot].mProducerBuffer;
+ queue_->Enqueue(producer_buffer, size_t(slot), 0U);
buffers_[slot].mBufferState.cancel();
buffers_[slot].mFence = fence;
ALOGV("cancelBuffer: slot %d", slot);
@@ -791,12 +791,12 @@
}
size_t slot = status.get();
- auto buffer_producer = queue_->GetBuffer(slot);
+ auto producer_buffer = queue_->GetBuffer(slot);
- LOG_ALWAYS_FATAL_IF(buffer_producer == nullptr, "Failed to get buffer producer at slot: %zu",
- slot);
+ LOG_ALWAYS_FATAL_IF(producer_buffer == nullptr,
+ "Failed to get the producer buffer at slot: %zu", slot);
- buffers_[slot].mBufferProducer = buffer_producer;
+ buffers_[slot].mProducerBuffer = producer_buffer;
return NO_ERROR;
}
@@ -810,7 +810,7 @@
}
// Reset in memory objects related the the buffer.
- buffers_[slot].mBufferProducer = nullptr;
+ buffers_[slot].mProducerBuffer = nullptr;
buffers_[slot].mBufferState.detachProducer();
buffers_[slot].mFence = Fence::NO_FENCE;
buffers_[slot].mGraphicBuffer = nullptr;
@@ -821,7 +821,7 @@
status_t BufferHubProducer::FreeAllBuffers() {
for (size_t slot = 0; slot < BufferHubQueue::kMaxQueueCapacity; slot++) {
// Reset in memory objects related the the buffer.
- buffers_[slot].mBufferProducer = nullptr;
+ buffers_[slot].mProducerBuffer = nullptr;
buffers_[slot].mBufferState.reset();
buffers_[slot].mFence = Fence::NO_FENCE;
buffers_[slot].mGraphicBuffer = nullptr;
diff --git a/libs/gui/FrameTimestamps.cpp b/libs/gui/FrameTimestamps.cpp
index 96e9a85..c04d907 100644
--- a/libs/gui/FrameTimestamps.cpp
+++ b/libs/gui/FrameTimestamps.cpp
@@ -158,7 +158,7 @@
namespace {
struct FrameNumberEqual {
- FrameNumberEqual(uint64_t frameNumber) : mFrameNumber(frameNumber) {}
+ explicit FrameNumberEqual(uint64_t frameNumber) : mFrameNumber(frameNumber) {}
bool operator()(const FrameEvents& frame) {
return frame.valid && mFrameNumber == frame.frameNumber;
}
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 68a6b1f..d997674 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -536,7 +536,7 @@
class HpGraphicBufferProducer : public HpInterface<
BpGraphicBufferProducer, H2BGraphicBufferProducer> {
public:
- HpGraphicBufferProducer(const sp<IBinder>& base) : PBase(base) {}
+ explicit HpGraphicBufferProducer(const sp<IBinder>& base) : PBase(base) {}
status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override {
return mBase->requestBuffer(slot, buf);
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 2d6be26..a481e81 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -63,21 +63,10 @@
return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
}
- virtual sp<ISurfaceComposerClient> createScopedConnection(
- const sp<IGraphicBufferProducer>& parent)
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- data.writeStrongBinder(IInterface::asBinder(parent));
- remote()->transact(BnSurfaceComposer::CREATE_SCOPED_CONNECTION, data, &reply);
- return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
- }
-
- virtual void setTransactionState(
- const Vector<ComposerState>& state,
- const Vector<DisplayState>& displays,
- uint32_t flags)
- {
+ virtual void setTransactionState(const Vector<ComposerState>& state,
+ const Vector<DisplayState>& displays, uint32_t flags,
+ const sp<IBinder>& applyToken,
+ const InputWindowCommands& commands) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
@@ -92,6 +81,8 @@
}
data.writeUint32(flags);
+ data.writeStrongBinder(applyToken);
+ commands.write(data);
remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply);
}
@@ -710,14 +701,6 @@
reply->writeStrongBinder(b);
return NO_ERROR;
}
- case CREATE_SCOPED_CONNECTION: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IGraphicBufferProducer> bufferProducer =
- interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
- sp<IBinder> b = IInterface::asBinder(createScopedConnection(bufferProducer));
- reply->writeStrongBinder(b);
- return NO_ERROR;
- }
case SET_TRANSACTION_STATE: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
@@ -750,7 +733,10 @@
}
uint32_t stateFlags = data.readUint32();
- setTransactionState(state, displays, stateFlags);
+ sp<IBinder> applyToken = data.readStrongBinder();
+ InputWindowCommands inputWindowCommands;
+ inputWindowCommands.read(data);
+ setTransactionState(state, displays, stateFlags, applyToken, inputWindowCommands);
return NO_ERROR;
}
case BOOT_FINISHED: {
diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp
index a6890ee..928ef95 100644
--- a/libs/gui/ISurfaceComposerClient.cpp
+++ b/libs/gui/ISurfaceComposerClient.cpp
@@ -31,7 +31,7 @@
enum class Tag : uint32_t {
CREATE_SURFACE = IBinder::FIRST_CALL_TRANSACTION,
- DESTROY_SURFACE,
+ CREATE_WITH_SURFACE_PARENT,
CLEAR_LAYER_FRAME_STATS,
GET_LAYER_FRAME_STATS,
LAST = GET_LAYER_FRAME_STATS,
@@ -57,9 +57,16 @@
handle, gbp);
}
- status_t destroySurface(const sp<IBinder>& handle) override {
- return callRemote<decltype(&ISurfaceComposerClient::destroySurface)>(Tag::DESTROY_SURFACE,
- handle);
+ status_t createWithSurfaceParent(const String8& name, uint32_t width, uint32_t height,
+ PixelFormat format, uint32_t flags,
+ const sp<IGraphicBufferProducer>& parent, int32_t windowType,
+ int32_t ownerUid, sp<IBinder>* handle,
+ sp<IGraphicBufferProducer>* gbp) override {
+ return callRemote<decltype(
+ &ISurfaceComposerClient::createWithSurfaceParent)>(Tag::CREATE_WITH_SURFACE_PARENT,
+ name, width, height, format,
+ flags, parent, windowType,
+ ownerUid, handle, gbp);
}
status_t clearLayerFrameStats(const sp<IBinder>& handle) const override {
@@ -92,8 +99,8 @@
switch (tag) {
case Tag::CREATE_SURFACE:
return callLocal(data, reply, &ISurfaceComposerClient::createSurface);
- case Tag::DESTROY_SURFACE:
- return callLocal(data, reply, &ISurfaceComposerClient::destroySurface);
+ case Tag::CREATE_WITH_SURFACE_PARENT:
+ return callLocal(data, reply, &ISurfaceComposerClient::createWithSurfaceParent);
case Tag::CLEAR_LAYER_FRAME_STATS:
return callLocal(data, reply, &ISurfaceComposerClient::clearLayerFrameStats);
case Tag::GET_LAYER_FRAME_STATS:
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 35ce6e3..e5170ab 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -379,4 +379,36 @@
}
}
+// ------------------------------- InputWindowCommands ----------------------------------------
+
+void InputWindowCommands::merge(const InputWindowCommands& other) {
+ transferTouchFocusCommands
+ .insert(transferTouchFocusCommands.end(),
+ std::make_move_iterator(other.transferTouchFocusCommands.begin()),
+ std::make_move_iterator(other.transferTouchFocusCommands.end()));
+}
+
+void InputWindowCommands::clear() {
+ transferTouchFocusCommands.clear();
+}
+
+void InputWindowCommands::write(Parcel& output) const {
+ output.writeUint32(static_cast<uint32_t>(transferTouchFocusCommands.size()));
+ for (const auto& transferTouchFocusCommand : transferTouchFocusCommands) {
+ output.writeStrongBinder(transferTouchFocusCommand.fromToken);
+ output.writeStrongBinder(transferTouchFocusCommand.toToken);
+ }
+}
+
+void InputWindowCommands::read(const Parcel& input) {
+ size_t count = input.readUint32();
+ transferTouchFocusCommands.clear();
+ for (size_t i = 0; i < count; i++) {
+ TransferTouchFocusCommand transferTouchFocusCommand;
+ transferTouchFocusCommand.fromToken = input.readStrongBinder();
+ transferTouchFocusCommand.toToken = input.readStrongBinder();
+ transferTouchFocusCommands.emplace_back(transferTouchFocusCommand);
+ }
+}
+
}; // namespace android
diff --git a/libs/gui/OWNERS b/libs/gui/OWNERS
new file mode 100644
index 0000000..a7c7e79
--- /dev/null
+++ b/libs/gui/OWNERS
@@ -0,0 +1,8 @@
+brianderson@google.com
+jessehall@google.com
+jwcai@google.com
+mathias@google.com
+olv@google.com
+pceballos@google.com
+racarr@google.com
+stoza@google.com
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 9586219..8b9e4d7 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -166,6 +166,7 @@
mEarlyWakeup(other.mEarlyWakeup) {
mDisplayStates = other.mDisplayStates;
mComposerStates = other.mComposerStates;
+ mInputWindowCommands = other.mInputWindowCommands;
}
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Transaction&& other) {
@@ -199,9 +200,27 @@
}
other.mListenerCallbacks.clear();
+ mInputWindowCommands.merge(other.mInputWindowCommands);
+
return *this;
}
+void SurfaceComposerClient::doDropReferenceTransaction(const sp<IBinder>& handle,
+ const sp<ISurfaceComposerClient>& client) {
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ Vector<ComposerState> composerStates;
+ Vector<DisplayState> displayStates;
+
+ ComposerState s;
+ s.client = client;
+ s.state.surface = handle;
+ s.state.what |= layer_state_t::eReparent;
+ s.state.parentHandleForChild = nullptr;
+
+ composerStates.add(s);
+ sf->setTransactionState(composerStates, displayStates, 0, nullptr, {});
+}
+
status_t SurfaceComposerClient::Transaction::apply(bool synchronous) {
if (mStatus != NO_ERROR) {
return mStatus;
@@ -264,7 +283,9 @@
mAnimation = false;
mEarlyWakeup = false;
- sf->setTransactionState(composerStates, displayStates, flags);
+ sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ sf->setTransactionState(composerStates, displayStates, flags, applyToken, mInputWindowCommands);
+ mInputWindowCommands.clear();
mStatus = NO_ERROR;
return NO_ERROR;
}
@@ -802,19 +823,18 @@
s->what |= layer_state_t::eInputInfoChanged;
return *this;
}
-#endif
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::destroySurface(
- const sp<SurfaceControl>& sc) {
- layer_state_t* s = getLayerState(sc);
- if (!s) {
- mStatus = BAD_INDEX;
- return *this;
- }
- s->what |= layer_state_t::eDestroySurface;
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::transferTouchFocus(
+ const sp<IBinder>& fromToken, const sp<IBinder>& toToken) {
+ InputWindowCommands::TransferTouchFocusCommand transferTouchFocusCommand;
+ transferTouchFocusCommand.fromToken = fromToken;
+ transferTouchFocusCommand.toToken = toToken;
+ mInputWindowCommands.transferTouchFocusCommands.emplace_back(transferTouchFocusCommand);
return *this;
}
+#endif
+
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColorTransform(
const sp<SurfaceControl>& sc, const mat3& matrix, const vec3& translation) {
layer_state_t* s = getLayerState(sc);
@@ -895,11 +915,6 @@
{
}
-SurfaceComposerClient::SurfaceComposerClient(const sp<IGraphicBufferProducer>& root)
- : mStatus(NO_INIT), mParent(root)
-{
-}
-
SurfaceComposerClient::SurfaceComposerClient(const sp<ISurfaceComposerClient>& client)
: mStatus(NO_ERROR), mClient(client)
{
@@ -908,10 +923,8 @@
void SurfaceComposerClient::onFirstRef() {
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
if (sf != nullptr && mStatus == NO_INIT) {
- auto rootProducer = mParent.promote();
sp<ISurfaceComposerClient> conn;
- conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
- sf->createConnection();
+ conn = sf->createConnection();
if (conn != nullptr) {
mClient = conn;
mStatus = NO_ERROR;
@@ -964,6 +977,29 @@
return s;
}
+sp<SurfaceControl> SurfaceComposerClient::createWithSurfaceParent(const String8& name, uint32_t w,
+ uint32_t h, PixelFormat format,
+ uint32_t flags, Surface* parent,
+ int32_t windowType,
+ int32_t ownerUid) {
+ sp<SurfaceControl> sur;
+ status_t err = mStatus;
+
+ if (mStatus == NO_ERROR) {
+ sp<IBinder> handle;
+ sp<IGraphicBufferProducer> parentGbp = parent->getIGraphicBufferProducer();
+ sp<IGraphicBufferProducer> gbp;
+
+ err = mClient->createWithSurfaceParent(name, w, h, format, flags, parentGbp, windowType,
+ ownerUid, &handle, &gbp);
+ ALOGE_IF(err, "SurfaceComposerClient::createWithSurfaceParent error %s", strerror(-err));
+ if (err == NO_ERROR) {
+ return new SurfaceControl(this, handle, gbp, true /* owned */);
+ }
+ }
+ return nullptr;
+}
+
status_t SurfaceComposerClient::createSurfaceChecked(
const String8& name,
uint32_t w,
@@ -996,13 +1032,6 @@
return err;
}
-status_t SurfaceComposerClient::destroySurface(const sp<IBinder>& sid) {
- if (mStatus != NO_ERROR)
- return mStatus;
- status_t err = mClient->destroySurface(sid);
- return err;
-}
-
status_t SurfaceComposerClient::clearLayerFrameStats(const sp<IBinder>& token) const {
if (mStatus != NO_ERROR) {
return mStatus;
@@ -1126,6 +1155,7 @@
return ComposerService::getComposerService()->getDisplayedContentSample(display, maxFrames,
timestamp, outStats);
}
+
// ----------------------------------------------------------------------------
status_t ScreenshotClient::capture(const sp<IBinder>& display, const ui::Dataspace reqDataSpace,
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 3a6dfda..8e500a4 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -54,9 +54,22 @@
{
}
+SurfaceControl::SurfaceControl(const sp<SurfaceControl>& other) {
+ mClient = other->mClient;
+ mHandle = other->mHandle;
+ mGraphicBufferProducer = other->mGraphicBufferProducer;
+ mOwned = false;
+}
+
SurfaceControl::~SurfaceControl()
{
- destroy();
+ if (mClient != nullptr && mHandle != nullptr && mOwned) {
+ SurfaceComposerClient::doDropReferenceTransaction(mHandle, mClient->getClient());
+ }
+ mClient.clear();
+ mHandle.clear();
+ mGraphicBufferProducer.clear();
+ IPCThreadState::self()->flushCommands();
}
void SurfaceControl::destroy()
@@ -64,7 +77,7 @@
// Avoid destroying the server-side surface if we are not the owner of it, meaning that we
// retrieved it from another process.
if (isValid() && mOwned) {
- mClient->destroySurface(mHandle);
+ SurfaceComposerClient::Transaction().reparent(this, nullptr).apply();
}
// clear all references and trigger an IPC now, to make sure things
// happen without delay, since these resources are quite heavy.
diff --git a/libs/gui/include/gui/BufferHubProducer.h b/libs/gui/include/gui/BufferHubProducer.h
index f7af19b..0e925ce 100644
--- a/libs/gui/include/gui/BufferHubProducer.h
+++ b/libs/gui/include/gui/BufferHubProducer.h
@@ -203,10 +203,10 @@
// requested buffer usage or geometry differs from that of the buffer
// allocated to a slot.
struct BufferHubSlot : public BufferSlot {
- BufferHubSlot() : mBufferProducer(nullptr), mIsReallocating(false) {}
+ BufferHubSlot() : mProducerBuffer(nullptr), mIsReallocating(false) {}
// BufferSlot comes from android framework, using m prefix to comply with
// the name convention with the reset of data fields from BufferSlot.
- std::shared_ptr<dvr::BufferProducer> mBufferProducer;
+ std::shared_ptr<dvr::ProducerBuffer> mProducerBuffer;
bool mIsReallocating;
};
BufferHubSlot buffers_[dvr::BufferHubQueue::kMaxQueueCapacity];
diff --git a/libs/gui/include/gui/BufferQueueConsumer.h b/libs/gui/include/gui/BufferQueueConsumer.h
index d108120..aa13c0c 100644
--- a/libs/gui/include/gui/BufferQueueConsumer.h
+++ b/libs/gui/include/gui/BufferQueueConsumer.h
@@ -31,7 +31,7 @@
class BufferQueueConsumer : public BnGraphicBufferConsumer {
public:
- BufferQueueConsumer(const sp<BufferQueueCore>& core);
+ explicit BufferQueueConsumer(const sp<BufferQueueCore>& core);
~BufferQueueConsumer() override;
// acquireBuffer attempts to acquire ownership of the next pending buffer in
diff --git a/libs/gui/include/gui/BufferQueueProducer.h b/libs/gui/include/gui/BufferQueueProducer.h
index 5c7ffb4..73bc5dd 100644
--- a/libs/gui/include/gui/BufferQueueProducer.h
+++ b/libs/gui/include/gui/BufferQueueProducer.h
@@ -29,7 +29,8 @@
public:
friend class BufferQueue; // Needed to access binderDied
- BufferQueueProducer(const sp<BufferQueueCore>& core, bool consumerIsSurfaceFlinger = false);
+ explicit BufferQueueProducer(const sp<BufferQueueCore>& core,
+ bool consumerIsSurfaceFlinger = false);
~BufferQueueProducer() override;
// requestBuffer returns the GraphicBuffer for slot N.
diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h
index 32ce59a..a4102df 100644
--- a/libs/gui/include/gui/DisplayEventReceiver.h
+++ b/libs/gui/include/gui/DisplayEventReceiver.h
@@ -84,7 +84,7 @@
* or requestNextVsync to receive them.
* Other events start being delivered immediately.
*/
- DisplayEventReceiver(
+ explicit DisplayEventReceiver(
ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp);
/*
diff --git a/libs/gui/include/gui/GLConsumer.h b/libs/gui/include/gui/GLConsumer.h
index 46a99e1..ddd868d 100644
--- a/libs/gui/include/gui/GLConsumer.h
+++ b/libs/gui/include/gui/GLConsumer.h
@@ -301,7 +301,7 @@
// also only creating new EGLImages from buffers when required.
class EglImage : public LightRefBase<EglImage> {
public:
- EglImage(sp<GraphicBuffer> graphicBuffer);
+ explicit EglImage(sp<GraphicBuffer> graphicBuffer);
// createIfNeeded creates an EGLImage if required (we haven't created
// one yet, or the EGLDisplay or crop-rect has changed).
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 3052c0b..1534fca 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -42,6 +42,7 @@
struct DisplayState;
struct DisplayInfo;
struct DisplayStatInfo;
+struct InputWindowCommands;
class LayerDebugInfo;
class HdrCapabilities;
class IDisplayEventConnection;
@@ -86,22 +87,11 @@
eVsyncSourceSurfaceFlinger = 1
};
- /* create connection with surface flinger, requires
- * ACCESS_SURFACE_FLINGER permission
+ /*
+ * Create a connection with SurfaceFlinger.
*/
virtual sp<ISurfaceComposerClient> createConnection() = 0;
- /** create a scoped connection with surface flinger.
- * Surfaces produced with this connection will act
- * as children of the passed in GBP. That is to say
- * SurfaceFlinger will draw them relative and confined to
- * drawing of buffers from the layer associated with parent.
- * As this is graphically equivalent in reach to just drawing
- * pixels into the parent buffers, it requires no special permission.
- */
- virtual sp<ISurfaceComposerClient> createScopedConnection(
- const sp<IGraphicBufferProducer>& parent) = 0;
-
/* return an IDisplayEventConnection */
virtual sp<IDisplayEventConnection> createDisplayEventConnection(
VsyncSource vsyncSource = eVsyncSourceApp) = 0;
@@ -124,7 +114,9 @@
/* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */
virtual void setTransactionState(const Vector<ComposerState>& state,
- const Vector<DisplayState>& displays, uint32_t flags) = 0;
+ const Vector<DisplayState>& displays, uint32_t flags,
+ const sp<IBinder>& applyToken,
+ const InputWindowCommands& inputWindowCommands) = 0;
/* signal that we're done booting.
* Requires ACCESS_SURFACE_FLINGER permission
@@ -353,7 +345,6 @@
ENABLE_VSYNC_INJECTIONS,
INJECT_VSYNC,
GET_LAYER_DEBUG_INFO,
- CREATE_SCOPED_CONNECTION,
GET_COMPOSITION_PREFERENCE,
GET_COLOR_MANAGEMENT,
GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES,
diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h
index 82b01b8..f443df8 100644
--- a/libs/gui/include/gui/ISurfaceComposerClient.h
+++ b/libs/gui/include/gui/ISurfaceComposerClient.h
@@ -58,7 +58,12 @@
/*
* Requires ACCESS_SURFACE_FLINGER permission
*/
- virtual status_t destroySurface(const sp<IBinder>& handle) = 0;
+ virtual status_t createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h,
+ PixelFormat format, uint32_t flags,
+ const sp<IGraphicBufferProducer>& parent,
+ int32_t windowType, int32_t ownerUid,
+ sp<IBinder>* handle,
+ sp<IGraphicBufferProducer>* gbp) = 0;
/*
* Requires ACCESS_SURFACE_FLINGER permission
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 02c6be2..e7564f5 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -228,6 +228,20 @@
status_t read(const Parcel& input);
};
+struct InputWindowCommands {
+ struct TransferTouchFocusCommand {
+ sp<IBinder> fromToken;
+ sp<IBinder> toToken;
+ };
+
+ std::vector<TransferTouchFocusCommand> transferTouchFocusCommands;
+
+ void merge(const InputWindowCommands& other);
+ void clear();
+ void write(Parcel& output) const;
+ void read(const Parcel& input);
+};
+
static inline int compare_type(const ComposerState& lhs, const ComposerState& rhs) {
if (lhs.client < rhs.client) return -1;
if (lhs.client > rhs.client) return 1;
diff --git a/libs/gui/include/gui/StreamSplitter.h b/libs/gui/include/gui/StreamSplitter.h
index 8f47eb4..b4eef29 100644
--- a/libs/gui/include/gui/StreamSplitter.h
+++ b/libs/gui/include/gui/StreamSplitter.h
@@ -128,7 +128,7 @@
class BufferTracker : public LightRefBase<BufferTracker> {
public:
- BufferTracker(const sp<GraphicBuffer>& buffer);
+ explicit BufferTracker(const sp<GraphicBuffer>& buffer);
const sp<GraphicBuffer>& getBuffer() const { return mBuffer; }
const sp<Fence>& getMergedFence() const { return mMergedFence; }
@@ -154,7 +154,7 @@
};
// Only called from createSplitter
- StreamSplitter(const sp<IGraphicBufferConsumer>& inputQueue);
+ explicit StreamSplitter(const sp<IGraphicBufferConsumer>& inputQueue);
// Must be accessed through RefBase
virtual ~StreamSplitter();
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 8e3ba78..f16f781 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -90,7 +90,6 @@
public:
SurfaceComposerClient();
SurfaceComposerClient(const sp<ISurfaceComposerClient>& client);
- SurfaceComposerClient(const sp<IGraphicBufferProducer>& parent);
virtual ~SurfaceComposerClient();
// Always make sure we could initialize
@@ -146,6 +145,13 @@
ui::Dataspace* wideColorGamutDataspace,
ui::PixelFormat* wideColorGamutPixelFormat);
+ /**
+ * Called from SurfaceControl d'tor to 'destroy' the surface (or rather, reparent it
+ * to null), but without needing an sp<SurfaceControl> to avoid infinite ressurection.
+ */
+ static void doDropReferenceTransaction(const sp<IBinder>& handle,
+ const sp<ISurfaceComposerClient>& client);
+
// ------------------------------------------------------------------------
// surface creation / destruction
@@ -162,15 +168,27 @@
);
status_t createSurfaceChecked(
- const String8& name,// name of the surface
- uint32_t w, // width in pixel
- uint32_t h, // height in pixel
- PixelFormat format, // pixel-format desired
+ const String8& name, // name of the surface
+ uint32_t w, // width in pixel
+ uint32_t h, // height in pixel
+ PixelFormat format, // pixel-format desired
sp<SurfaceControl>* outSurface,
- uint32_t flags = 0, // usage flags
+ uint32_t flags = 0, // usage flags
SurfaceControl* parent = nullptr, // parent
int32_t windowType = -1, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.)
- int32_t ownerUid = -1 // UID of the task
+ int32_t ownerUid = -1 // UID of the task
+ );
+
+ //! Create a surface
+ sp<SurfaceControl> createWithSurfaceParent(
+ const String8& name, // name of the surface
+ uint32_t w, // width in pixel
+ uint32_t h, // height in pixel
+ PixelFormat format, // pixel-format desired
+ uint32_t flags = 0, // usage flags
+ Surface* parent = nullptr, // parent
+ int32_t windowType = -1, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.)
+ int32_t ownerUid = -1 // UID of the task
);
//! Create a virtual display
@@ -219,6 +237,7 @@
bool mAnimation = false;
bool mEarlyWakeup = false;
+ InputWindowCommands mInputWindowCommands;
int mStatus = NO_ERROR;
layer_state_t* getLayerState(const sp<SurfaceControl>& sc);
@@ -335,10 +354,9 @@
#ifndef NO_INPUT
Transaction& setInputWindowInfo(const sp<SurfaceControl>& sc, const InputWindowInfo& info);
+ Transaction& transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken);
#endif
- Transaction& destroySurface(const sp<SurfaceControl>& sc);
-
// Set a color transform matrix on the given layer on the built-in display.
Transaction& setColorTransform(const sp<SurfaceControl>& sc, const mat3& matrix,
const vec3& translation);
@@ -367,8 +385,6 @@
void setEarlyWakeup();
};
- status_t destroySurface(const sp<IBinder>& id);
-
status_t clearLayerFrameStats(const sp<IBinder>& token) const;
status_t getLayerFrameStats(const sp<IBinder>& token, FrameStats* outStats) const;
static status_t clearAnimationFrameStats();
@@ -400,7 +416,6 @@
mutable Mutex mLock;
status_t mStatus;
sp<ISurfaceComposerClient> mClient;
- wp<IGraphicBufferProducer> mParent;
};
// ---------------------------------------------------------------------------
diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h
index ccb30fa..9bba766 100644
--- a/libs/gui/include/gui/SurfaceControl.h
+++ b/libs/gui/include/gui/SurfaceControl.h
@@ -75,6 +75,8 @@
status_t getLayerFrameStats(FrameStats* outStats) const;
sp<SurfaceComposerClient> getClient() const;
+
+ explicit SurfaceControl(const sp<SurfaceControl>& other);
private:
// can't be copied
diff --git a/libs/gui/include/gui/bufferqueue/1.0/B2HProducerListener.h b/libs/gui/include/gui/bufferqueue/1.0/B2HProducerListener.h
index fa6c2d9..0f6fb45 100644
--- a/libs/gui/include/gui/bufferqueue/1.0/B2HProducerListener.h
+++ b/libs/gui/include/gui/bufferqueue/1.0/B2HProducerListener.h
@@ -50,7 +50,7 @@
struct B2HProducerListener : public HProducerListener {
sp<BProducerListener> mBase;
- B2HProducerListener(sp<BProducerListener> const& base);
+ explicit B2HProducerListener(sp<BProducerListener> const& base);
Return<void> onBufferReleased() override;
Return<bool> needsReleaseNotify() override;
};
diff --git a/libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h b/libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
index 74850b4..c92fa9d 100644
--- a/libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
+++ b/libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
@@ -59,7 +59,7 @@
HGraphicBufferProducer,
BGraphicBufferProducer,
BnGraphicBufferProducer> {
- H2BGraphicBufferProducer(sp<HGraphicBufferProducer> const& base) : CBase(base) {}
+ explicit H2BGraphicBufferProducer(sp<HGraphicBufferProducer> const& base) : CBase(base) {}
status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override;
status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) override;
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 60542bd..7fc69ff 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -133,6 +133,27 @@
EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction());
}
+ void expectMotionEvent(int motionEventType, int x, int y) {
+ InputEvent *ev = consumeEvent();
+ ASSERT_NE(ev, nullptr);
+ ASSERT_EQ(ev->getType(), AINPUT_EVENT_TYPE_MOTION);
+ MotionEvent *mev = static_cast<MotionEvent *>(ev);
+ EXPECT_EQ(motionEventType, mev->getAction());
+ EXPECT_EQ(x, mev->getX(0));
+ EXPECT_EQ(y, mev->getY(0));
+ }
+
+ void expectNoMotionEvent(int motionEventType) {
+ InputEvent *ev = consumeEvent();
+ if (ev == nullptr || ev->getType() != AINPUT_EVENT_TYPE_MOTION) {
+ // Didn't find an event or a motion event so assume action didn't occur.
+ return;
+ }
+
+ MotionEvent *mev = static_cast<MotionEvent *>(ev);
+ EXPECT_NE(motionEventType, mev->getAction());
+ }
+
~InputSurface() {
mInputFlinger->unregisterInputChannel(mServerChannel);
}
@@ -255,6 +276,15 @@
}
}
+void injectMotionEvent(std::string event, int x, int y) {
+ char *buf1, *buf2;
+ asprintf(&buf1, "%d", x);
+ asprintf(&buf2, "%d", y);
+ if (fork() == 0) {
+ execlp("input", "input", "motionevent", event.c_str(), buf1, buf2, NULL);
+ }
+}
+
TEST_F(InputSurfacesTest, can_receive_input) {
std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
surface->showAt(100, 100);
@@ -439,5 +469,25 @@
injectTap(11, 11);
bgSurface->expectTap(1, 1);
}
+
+TEST_F(InputSurfacesTest, transfer_touch_focus) {
+ std::unique_ptr<InputSurface> fromSurface = makeSurface(100, 100);
+
+ fromSurface->showAt(10, 10);
+ injectMotionEvent("DOWN", 11, 11);
+ fromSurface->expectMotionEvent(AMOTION_EVENT_ACTION_DOWN, 1, 1);
+
+ std::unique_ptr<InputSurface> toSurface = makeSurface(100, 100);
+ toSurface->showAt(10, 10);
+
+ sp<IBinder> fromToken = fromSurface->mServerChannel->getToken();
+ sp<IBinder> toToken = toSurface->mServerChannel->getToken();
+ SurfaceComposerClient::Transaction t;
+ t.transferTouchFocus(fromToken, toToken).apply(true);
+
+ injectMotionEvent("UP", 11, 11);
+ toSurface->expectMotionEvent(AMOTION_EVENT_ACTION_UP, 1, 1);
+ fromSurface->expectNoMotionEvent(AMOTION_EVENT_ACTION_UP);
+}
}
}
diff --git a/libs/gui/tests/Malicious.cpp b/libs/gui/tests/Malicious.cpp
index bb6b8a5..acd4297 100644
--- a/libs/gui/tests/Malicious.cpp
+++ b/libs/gui/tests/Malicious.cpp
@@ -27,7 +27,7 @@
class ProxyBQP : public BnGraphicBufferProducer {
public:
- ProxyBQP(const sp<IGraphicBufferProducer>& producer) : mProducer(producer) {}
+ explicit ProxyBQP(const sp<IGraphicBufferProducer>& producer) : mProducer(producer) {}
// Pass through calls to mProducer
status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override {
@@ -102,7 +102,7 @@
class MaliciousBQP : public ProxyBQP {
public:
- MaliciousBQP(const sp<IGraphicBufferProducer>& producer) : ProxyBQP(producer) {}
+ explicit MaliciousBQP(const sp<IGraphicBufferProducer>& producer) : ProxyBQP(producer) {}
void beMalicious(int32_t value) { mMaliciousValue = value; }
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 67afbd6..60173dc 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -545,10 +545,6 @@
}
sp<ISurfaceComposerClient> createConnection() override { return nullptr; }
- sp<ISurfaceComposerClient> createScopedConnection(
- const sp<IGraphicBufferProducer>& /* parent */) override {
- return nullptr;
- }
sp<IDisplayEventConnection> createDisplayEventConnection(ISurfaceComposer::VsyncSource)
override {
return nullptr;
@@ -558,8 +554,9 @@
void destroyDisplay(const sp<IBinder>& /*display */) override {}
sp<IBinder> getBuiltInDisplay(int32_t /*id*/) override { return nullptr; }
void setTransactionState(const Vector<ComposerState>& /*state*/,
- const Vector<DisplayState>& /*displays*/, uint32_t /*flags*/)
- override {}
+ const Vector<DisplayState>& /*displays*/, uint32_t /*flags*/,
+ const sp<IBinder>& /*applyToken*/,
+ const InputWindowCommands& /*inputWindowCommands*/) override {}
void bootFinished() override {}
bool authenticateSurfaceTexture(
const sp<IGraphicBufferProducer>& /*surface*/) const override {
@@ -669,8 +666,7 @@
class FakeProducerFrameEventHistory : public ProducerFrameEventHistory {
public:
- FakeProducerFrameEventHistory(FenceToFenceTimeMap* fenceMap)
- : mFenceMap(fenceMap) {}
+ explicit FakeProducerFrameEventHistory(FenceToFenceTimeMap* fenceMap) : mFenceMap(fenceMap) {}
~FakeProducerFrameEventHistory() {}
diff --git a/libs/input/IInputFlinger.cpp b/libs/input/IInputFlinger.cpp
index 139570a..acf40bc 100644
--- a/libs/input/IInputFlinger.cpp
+++ b/libs/input/IInputFlinger.cpp
@@ -42,6 +42,16 @@
IBinder::FLAG_ONEWAY);
}
+ virtual void transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor());
+
+ data.writeStrongBinder(fromToken);
+ data.writeStrongBinder(toToken);
+ remote()->transact(BnInputFlinger::TRANSFER_TOUCH_FOCUS, data, &reply,
+ IBinder::FLAG_ONEWAY);
+ }
+
virtual void registerInputChannel(const sp<InputChannel>& channel) {
Parcel data, reply;
data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor());
@@ -90,6 +100,13 @@
unregisterInputChannel(channel);
break;
}
+ case TRANSFER_TOUCH_FOCUS: {
+ CHECK_INTERFACE(IInputFlinger, data, reply);
+ sp<IBinder> fromToken = data.readStrongBinder();
+ sp<IBinder> toToken = data.readStrongBinder();
+ transferTouchFocus(fromToken, toToken);
+ break;
+ }
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index a558970..db86c8e 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -234,6 +234,7 @@
int32_t edgeFlags,
int32_t metaState,
int32_t buttonState,
+ MotionClassification classification,
float xOffset,
float yOffset,
float xPrecision,
@@ -250,6 +251,7 @@
mEdgeFlags = edgeFlags;
mMetaState = metaState;
mButtonState = buttonState;
+ mClassification = classification;
mXOffset = xOffset;
mYOffset = yOffset;
mXPrecision = xPrecision;
@@ -270,6 +272,7 @@
mEdgeFlags = other->mEdgeFlags;
mMetaState = other->mMetaState;
mButtonState = other->mButtonState;
+ mClassification = other->mClassification;
mXOffset = other->mXOffset;
mYOffset = other->mYOffset;
mXPrecision = other->mXPrecision;
@@ -451,6 +454,7 @@
mEdgeFlags = parcel->readInt32();
mMetaState = parcel->readInt32();
mButtonState = parcel->readInt32();
+ mClassification = static_cast<MotionClassification>(parcel->readByte());
mXOffset = parcel->readFloat();
mYOffset = parcel->readFloat();
mXPrecision = parcel->readFloat();
@@ -501,6 +505,7 @@
parcel->writeInt32(mEdgeFlags);
parcel->writeInt32(mMetaState);
parcel->writeInt32(mButtonState);
+ parcel->writeByte(static_cast<int8_t>(mClassification));
parcel->writeFloat(mXOffset);
parcel->writeFloat(mYOffset);
parcel->writeFloat(mXPrecision);
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index f33b210..0ddee44 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -1112,6 +1112,7 @@
msg->body.motion.edgeFlags,
msg->body.motion.metaState,
msg->body.motion.buttonState,
+ MotionClassification::NONE,
msg->body.motion.xOffset,
msg->body.motion.yOffset,
msg->body.motion.xPrecision,
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index 99f83ba..e4c1514 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -260,7 +260,7 @@
event->initialize(2, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, AMOTION_EVENT_ACTION_MOVE, 0,
AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED,
AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY,
- X_OFFSET, Y_OFFSET, 2.0f, 2.1f,
+ MotionClassification::NONE, X_OFFSET, Y_OFFSET, 2.0f, 2.1f,
ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME,
2, pointerProperties, pointerCoords);
@@ -572,8 +572,11 @@
pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, angle);
}
MotionEvent event;
- event.initialize(0, 0, DISPLAY_ID, AMOTION_EVENT_ACTION_MOVE, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, pointerCount, pointerProperties, pointerCoords);
+ event.initialize(0 /*deviceId*/, AINPUT_SOURCE_UNKNOWN, DISPLAY_ID, AMOTION_EVENT_ACTION_MOVE,
+ 0 /*actionButton*/, 0 /*flags*/, AMOTION_EVENT_EDGE_FLAG_NONE,
+ AMETA_NONE, 0 /*buttonState*/, MotionClassification::NONE,
+ 0 /*xOffset*/, 0 /*yOffset*/, 0 /*xPrecision*/, 0 /*yPrecision*/,
+ 0 /*downTime*/, 0 /*eventTime*/, pointerCount, pointerProperties, pointerCoords);
float originalRawX = 0 + 3;
float originalRawY = -RADIUS + 2;
diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp
index af97c34..3c67542 100644
--- a/libs/input/tests/VelocityTracker_test.cpp
+++ b/libs/input/tests/VelocityTracker_test.cpp
@@ -90,7 +90,8 @@
MotionEvent* event = new MotionEvent();
PointerCoords coords;
- PointerProperties properties[1];
+ constexpr size_t pointerCount = 1;
+ PointerProperties properties[pointerCount];
properties[0].id = DEFAULT_POINTER_ID;
properties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
@@ -98,8 +99,11 @@
// First sample added separately with initialize
coords.setAxisValue(AMOTION_EVENT_AXIS_X, positions[0].x);
coords.setAxisValue(AMOTION_EVENT_AXIS_Y, positions[0].y);
- event->initialize(0, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, AMOTION_EVENT_ACTION_MOVE,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, positions[0].time, 1, properties, &coords);
+ event->initialize(0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
+ AMOTION_EVENT_ACTION_MOVE, 0 /*actionButton*/, 0 /*flags*/,
+ AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0 /*buttonState*/, MotionClassification::NONE,
+ 0 /*xOffset*/, 0 /*yOffset*/, 0 /*xPrecision*/, 0 /*yPrecision*/,
+ 0 /*downTime*/, positions[0].time, pointerCount, properties, &coords);
for (size_t i = 1; i < numSamples; i++) {
coords.setAxisValue(AMOTION_EVENT_AXIS_X, positions[i].x);
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index a19fe17..6ea1270 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -268,7 +268,11 @@
AHardwareBuffer_Desc trialDesc = *desc;
trialDesc.width = 4;
trialDesc.height = desc->format == AHARDWAREBUFFER_FORMAT_BLOB ? 1 : 4;
- trialDesc.layers = desc->layers == 1 ? 1 : 2;
+ if (desc->usage & AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP) {
+ trialDesc.layers = desc->layers == 6 ? 6 : 12;
+ } else {
+ trialDesc.layers = desc->layers == 1 ? 1 : 2;
+ }
AHardwareBuffer* trialBuffer = nullptr;
int result = AHardwareBuffer_allocate(&trialDesc, &trialBuffer);
if (result == NO_ERROR) {
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index 03545a6..2796c75 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -208,6 +208,17 @@
*/
AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT = AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER,
/**
+ * The buffer will be used as a composer HAL overlay layer.
+ *
+ * This flag is currently only needed when using ASurfaceTransaction_setBuffer
+ * to set a buffer. In all other cases, the framework adds this flag
+ * internally to buffers that could be presented in a composer overlay.
+ * ASurfaceTransaction_setBuffer is special because it uses buffers allocated
+ * directly through AHardwareBuffer_allocate instead of buffers allocated
+ * by the framework.
+ */
+ AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY = 1ULL << 11,
+ /**
* The buffer is protected from direct CPU access or being read by
* non-secure hardware, such as video encoders.
*
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index d872f02..36211ca 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -26,6 +26,7 @@
"libgui",
"liblog",
"libnativewindow",
+ "libsync",
"libui",
"libutils",
],
@@ -79,3 +80,19 @@
thin: true,
},
}
+
+cc_library_static {
+ name: "librenderengine_mocks",
+ defaults: ["librenderengine_defaults"],
+ srcs: [
+ "mock/Framebuffer.cpp",
+ "mock/Image.cpp",
+ "mock/RenderEngine.cpp",
+ ],
+ static_libs: [
+ "libgtest",
+ "libgmock",
+ ],
+ local_include_dirs: ["include"],
+ export_include_dirs: ["include"],
+}
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 51cf188..2915bb8 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -24,14 +24,17 @@
#include <math.h>
#include <fstream>
#include <sstream>
+#include <unordered_set>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <android-base/stringprintf.h>
#include <cutils/compiler.h>
+#include <cutils/properties.h>
#include <renderengine/Mesh.h>
#include <renderengine/Texture.h>
#include <renderengine/private/Description.h>
+#include <sync/sync.h>
#include <ui/ColorSpace.h>
#include <ui/DebugUtils.h>
#include <ui/Rect.h>
@@ -414,6 +417,13 @@
mBt2020ToSrgb = mXyzToSrgb * mBt2020ToXyz;
mBt2020ToDisplayP3 = mXyzToDisplayP3 * mBt2020ToXyz;
}
+
+ char value[PROPERTY_VALUE_MAX];
+ property_get("debug.egl.traceGpuCompletion", value, "0");
+ if (atoi(value)) {
+ mTraceGpuCompletion = true;
+ mFlushTracer = std::make_unique<FlushTracer>(this);
+ }
}
GLESRenderEngine::~GLESRenderEngine() {
@@ -459,6 +469,12 @@
ALOGW("failed to dup EGL native fence sync: %#x", eglGetError());
}
+ // Only trace if we have a valid fence, as current usage falls back to
+ // calling finish() if the fence fd is invalid.
+ if (CC_UNLIKELY(mTraceGpuCompletion && mFlushTracer) && fenceFd.get() >= 0) {
+ mFlushTracer->queueSync(eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, nullptr));
+ }
+
return fenceFd;
}
@@ -474,8 +490,15 @@
return false;
}
- EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
- 2000000000 /*2 sec*/);
+ if (CC_UNLIKELY(mTraceGpuCompletion && mFlushTracer)) {
+ mFlushTracer->queueSync(eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, nullptr));
+ }
+
+ return waitSync(sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR);
+}
+
+bool GLESRenderEngine::waitSync(EGLSyncKHR sync, EGLint flags) {
+ EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync, flags, 2000000000 /*2 sec*/);
EGLint error = eglGetError();
eglDestroySyncKHR(mEGLDisplay, sync);
if (result != EGL_CONDITION_SATISFIED_KHR) {
@@ -584,6 +607,65 @@
}
}
+status_t GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName, sp<GraphicBuffer> buffer,
+ sp<Fence> bufferFence) {
+ std::unique_ptr<Image> newImage = createImage();
+
+ bool created = newImage->setNativeWindowBuffer(buffer->getNativeBuffer(),
+ buffer->getUsage() & GRALLOC_USAGE_PROTECTED);
+ if (!created) {
+ ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
+ buffer->getWidth(), buffer->getHeight(), buffer->getStride(), buffer->getUsage(),
+ buffer->getPixelFormat());
+ bindExternalTextureImage(texName, *createImage());
+ return NO_INIT;
+ }
+
+ bindExternalTextureImage(texName, *newImage);
+
+ // Wait for the new buffer to be ready.
+ if (bufferFence != nullptr && bufferFence->isValid()) {
+ if (GLExtensions::getInstance().hasWaitSync()) {
+ base::unique_fd fenceFd(bufferFence->dup());
+ if (fenceFd == -1) {
+ ALOGE("error dup'ing fence fd: %d", errno);
+ return -errno;
+ }
+ if (!waitFence(std::move(fenceFd))) {
+ ALOGE("failed to wait on fence fd");
+ return UNKNOWN_ERROR;
+ }
+ } else {
+ status_t err = bufferFence->waitForever("RenderEngine::bindExternalTextureBuffer");
+ if (err != NO_ERROR) {
+ ALOGE("error waiting for fence: %d", err);
+ return err;
+ }
+ }
+ }
+
+ return NO_ERROR;
+}
+
+FloatRect GLESRenderEngine::setupLayerCropping(const LayerSettings& layer, Mesh& mesh) {
+ // Translate win by the rounded corners rect coordinates, to have all values in
+ // layer coordinate space.
+ FloatRect cropWin = layer.geometry.boundaries;
+ const FloatRect& roundedCornersCrop = layer.geometry.roundedCornersCrop;
+ cropWin.left -= roundedCornersCrop.left;
+ cropWin.right -= roundedCornersCrop.left;
+ cropWin.top -= roundedCornersCrop.top;
+ cropWin.bottom -= roundedCornersCrop.top;
+ Mesh::VertexArray<vec2> cropCoords(mesh.getCropCoordArray<vec2>());
+ cropCoords[0] = vec2(cropWin.left, cropWin.top);
+ cropCoords[1] = vec2(cropWin.left, cropWin.top + cropWin.getHeight());
+ cropCoords[2] = vec2(cropWin.right, cropWin.top + cropWin.getHeight());
+ cropCoords[3] = vec2(cropWin.right, cropWin.top);
+
+ setupCornerRadiusCropSize(roundedCornersCrop.getWidth(), roundedCornersCrop.getHeight());
+ return cropWin;
+}
+
status_t GLESRenderEngine::bindFrameBuffer(Framebuffer* framebuffer) {
GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(framebuffer);
EGLImageKHR eglImage = glFramebuffer->getEGLImage();
@@ -672,33 +754,68 @@
setDisplayMaxLuminance(display.maxLuminance);
mat4 projectionMatrix = mState.projectionMatrix * display.globalTransform;
+ mState.projectionMatrix = projectionMatrix;
+ if (!display.clearRegion.isEmpty()) {
+ fillRegionWithColor(display.clearRegion, 0.0, 0.0, 0.0, 1.0);
+ }
- Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2);
+ Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2, 2);
for (auto layer : layers) {
- // for now, assume that all pixel sources are solid colors.
- // TODO(alecmouri): support buffer sources
- if (layer.source.buffer.buffer != nullptr) {
- continue;
- }
-
- setColorTransform(display.colorTransform * layer.colorTransform);
-
mState.projectionMatrix = projectionMatrix * layer.geometry.positionTransform;
- FloatRect bounds = layer.geometry.boundaries;
+ const FloatRect bounds = layer.geometry.boundaries;
Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
position[0] = vec2(bounds.left, bounds.top);
position[1] = vec2(bounds.left, bounds.bottom);
position[2] = vec2(bounds.right, bounds.bottom);
position[3] = vec2(bounds.right, bounds.top);
- half3 solidColor = layer.source.solidColor;
- half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer.alpha);
- setupLayerBlending(/*premultipliedAlpha=*/true, /*opaque=*/false, /*disableTexture=*/true,
- color, /*cornerRadius=*/0.0);
+ setupLayerCropping(layer, mesh);
+ setColorTransform(display.colorTransform * layer.colorTransform);
+
+ bool usePremultipliedAlpha = true;
+ bool disableTexture = true;
+
+ if (layer.source.buffer.buffer != nullptr) {
+ disableTexture = false;
+
+ sp<GraphicBuffer> gBuf = layer.source.buffer.buffer;
+
+ bindExternalTextureBuffer(layer.source.buffer.textureName, gBuf,
+ layer.source.buffer.fence);
+
+ usePremultipliedAlpha = layer.source.buffer.usePremultipliedAlpha;
+ Texture texture(Texture::TEXTURE_EXTERNAL, layer.source.buffer.textureName);
+ texture.setMatrix(layer.source.buffer.textureTransform.asArray());
+ texture.setFiltering(layer.source.buffer.useTextureFiltering);
+
+ texture.setDimensions(gBuf->getWidth(), gBuf->getHeight());
+ setSourceY410BT2020(layer.source.buffer.isY410BT2020);
+
+ renderengine::Mesh::VertexArray<vec2> texCoords(mesh.getTexCoordArray<vec2>());
+ texCoords[0] = vec2(0.0, 1.0);
+ texCoords[1] = vec2(0.0, 0.0);
+ texCoords[2] = vec2(1.0, 0.0);
+ texCoords[3] = vec2(1.0, 1.0);
+ setupLayerTexturing(texture);
+ }
+
+ const half3 solidColor = layer.source.solidColor;
+ const half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer.alpha);
+ // Buffer sources will have a black solid color ignored in the shader,
+ // so in that scenario the solid color passed here is arbitrary.
+ setupLayerBlending(usePremultipliedAlpha, layer.source.buffer.isOpaque, disableTexture,
+ color, layer.geometry.roundedCornersRadius);
setSourceDataSpace(layer.sourceDataspace);
drawMesh(mesh);
+
+ // Cleanup if there's a buffer source
+ if (layer.source.buffer.buffer != nullptr) {
+ disableBlending();
+ setSourceY410BT2020(false);
+ disableTexturing();
+ }
}
*drawFence = flush();
@@ -1128,6 +1245,61 @@
return (isInputHdrDataSpace || isOutputHdrDataSpace) && inputTransfer != outputTransfer;
}
+// FlushTracer implementation
+GLESRenderEngine::FlushTracer::FlushTracer(GLESRenderEngine* engine) : mEngine(engine) {
+ mThread = std::thread(&GLESRenderEngine::FlushTracer::loop, this);
+}
+
+GLESRenderEngine::FlushTracer::~FlushTracer() {
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mRunning = false;
+ }
+ mCondition.notify_all();
+ if (mThread.joinable()) {
+ mThread.join();
+ }
+}
+
+void GLESRenderEngine::FlushTracer::queueSync(EGLSyncKHR sync) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ char name[64];
+ const uint64_t frameNum = mFramesQueued++;
+ snprintf(name, sizeof(name), "Queueing sync for frame: %lu",
+ static_cast<unsigned long>(frameNum));
+ ATRACE_NAME(name);
+ mQueue.push({sync, frameNum});
+ ATRACE_INT("GPU Frames Outstanding", mQueue.size());
+ mCondition.notify_one();
+}
+
+void GLESRenderEngine::FlushTracer::loop() {
+ while (mRunning) {
+ QueueEntry entry;
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ mCondition.wait(mMutex,
+ [&]() REQUIRES(mMutex) { return !mQueue.empty() && !mRunning; });
+
+ if (!mRunning) {
+ // if mRunning is false, then FlushTracer is being destroyed, so
+ // bail out now.
+ break;
+ }
+ entry = mQueue.front();
+ mQueue.pop();
+ }
+ {
+ char name[64];
+ snprintf(name, sizeof(name), "waiting for frame %lu",
+ static_cast<unsigned long>(entry.mFrameNum));
+ ATRACE_NAME(name);
+ mEngine->waitSync(entry.mSync, 0);
+ }
+ }
+}
+
} // namespace gl
} // namespace renderengine
} // namespace android
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index b6fff33..b596242 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -17,8 +17,13 @@
#ifndef SF_GLESRENDERENGINE_H_
#define SF_GLESRENDERENGINE_H_
+#include <android-base/thread_annotations.h>
#include <stdint.h>
#include <sys/types.h>
+#include <condition_variable>
+#include <mutex>
+#include <queue>
+#include <thread>
#include <EGL/egl.h>
#include <EGL/eglext.h>
@@ -119,6 +124,7 @@
Protection protection);
static EGLSurface createDummyEglPbufferSurface(EGLDisplay display, EGLConfig config,
int hwcFormat, Protection protection);
+ bool waitSync(EGLSyncKHR sync, EGLint flags);
// A data space is considered HDR data space if it has BT2020 color space
// with PQ or HLG transfer function.
@@ -127,6 +133,10 @@
// Defines the viewport, and sets the projection matrix to the projection
// defined by the clip.
void setViewportAndProjection(Rect viewport, Rect clip);
+ status_t bindExternalTextureBuffer(uint32_t texName, sp<GraphicBuffer> buffer, sp<Fence> fence);
+ // Computes the cropping window for the layer and sets up cropping
+ // coordinates for the mesh.
+ FloatRect setupLayerCropping(const LayerSettings& layer, Mesh& mesh);
EGLDisplay mEGLDisplay;
EGLConfig mEGLConfig;
@@ -155,6 +165,8 @@
mat4 mBt2020ToDisplayP3;
bool mInProtectedContext = false;
+ // If set to true, then enables tracing flush() and finish() to systrace.
+ bool mTraceGpuCompletion = false;
int32_t mFboHeight = 0;
// Current dataspace of layer being rendered
@@ -166,6 +178,30 @@
// Whether device supports color management, currently color management
// supports sRGB, DisplayP3 color spaces.
const bool mUseColorManagement = false;
+
+ class FlushTracer {
+ public:
+ FlushTracer(GLESRenderEngine* engine);
+ ~FlushTracer();
+ void queueSync(EGLSyncKHR sync) EXCLUDES(mMutex);
+
+ struct QueueEntry {
+ EGLSyncKHR mSync = nullptr;
+ uint64_t mFrameNum = 0;
+ };
+
+ private:
+ void loop();
+ GLESRenderEngine* const mEngine;
+ std::thread mThread;
+ std::condition_variable_any mCondition;
+ std::mutex mMutex;
+ std::queue<QueueEntry> mQueue GUARDED_BY(mMutex);
+ uint64_t mFramesQueued GUARDED_BY(mMutex) = 0;
+ bool mRunning = true;
+ };
+ friend class FlushTracer;
+ std::unique_ptr<FlushTracer> mFlushTracer;
};
} // namespace gl
diff --git a/libs/renderengine/include/renderengine/DisplaySettings.h b/libs/renderengine/include/renderengine/DisplaySettings.h
index 0c92353..af8de23 100644
--- a/libs/renderengine/include/renderengine/DisplaySettings.h
+++ b/libs/renderengine/include/renderengine/DisplaySettings.h
@@ -51,9 +51,10 @@
// to the output dataspace.
mat4 colorTransform = mat4();
- // Region that will be cleared to (0, 0, 0, 0) prior to rendering.
- // clearRegion will first be transformed by globalTransform so that it will
- // be in the same coordinate space as the rendered layers.
+ // Region that will be cleared to (0, 0, 0, 1) prior to rendering.
+ // RenderEngine will transform the clearRegion passed in here, by
+ // globalTransform, so that it will be in the same coordinate space as the
+ // rendered layers.
Region clearRegion = Region::INVALID_REGION;
};
diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h
index 93abf5c..4d53205 100644
--- a/libs/renderengine/include/renderengine/LayerSettings.h
+++ b/libs/renderengine/include/renderengine/LayerSettings.h
@@ -19,6 +19,7 @@
#include <math/mat4.h>
#include <math/vec3.h>
#include <renderengine/Texture.h>
+#include <ui/Fence.h>
#include <ui/FloatRect.h>
#include <ui/GraphicBuffer.h>
#include <ui/GraphicTypes.h>
@@ -36,6 +37,9 @@
// ignored.
sp<GraphicBuffer> buffer = nullptr;
+ // Fence that will fire when the buffer is ready to be bound.
+ sp<Fence> fence = nullptr;
+
// Texture identifier to bind the external texture to.
// TODO(alecmouri): This is GL-specific...make the type backend-agnostic.
uint32_t textureName = 0;
@@ -49,6 +53,11 @@
// Wheteher to use pre-multiplied alpha
bool usePremultipliedAlpha = true;
+ // Override flag that alpha for each pixel in the buffer *must* be 1.0.
+ // LayerSettings::alpha is still used if isOpaque==true - this flag only
+ // overrides the alpha channel of the buffer.
+ bool isOpaque = false;
+
// HDR color-space setting for Y410.
bool isY410BT2020 = false;
};
@@ -60,6 +69,20 @@
// Transform matrix to apply to mesh coordinates.
mat4 positionTransform = mat4();
+
+ // Radius of rounded corners, if greater than 0. Otherwise, this layer's
+ // corners are not rounded.
+ // Having corner radius will force GPU composition on the layer and its children, drawing it
+ // with a special shader. The shader will receive the radius and the crop rectangle as input,
+ // modifying the opacity of the destination texture, multiplying it by a number between 0 and 1.
+ // We query Layer#getRoundedCornerState() to retrieve the radius as well as the rounded crop
+ // rectangle to figure out how to apply the radius for this layer. The crop rectangle will be
+ // in local layer coordinate space, so we have to take the layer transform into account when
+ // walking up the tree.
+ float roundedCornersRadius = 0.0;
+
+ // Rectangle within which corners will be rounded.
+ FloatRect roundedCornersCrop = FloatRect();
};
// Descriptor of the source pixels for this layer.
@@ -81,15 +104,15 @@
// Source pixels for this layer.
PixelSource source = PixelSource();
- // Alpha option to apply to the source pixels
+ // Alpha option to blend with the source pixels
half alpha = half(0.0);
// Color space describing how the source pixels should be interpreted.
- ui::Dataspace sourceDataspace;
+ ui::Dataspace sourceDataspace = ui::Dataspace::UNKNOWN;
// Additional layer-specific color transform to be applied before the global
// transform.
- mat4 colorTransform;
+ mat4 colorTransform = mat4();
};
} // namespace renderengine
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp b/libs/renderengine/include/renderengine/mock/Framebuffer.h
similarity index 63%
copy from services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
copy to libs/renderengine/include/renderengine/mock/Framebuffer.h
index fbfbc3f..7695885 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
+++ b/libs/renderengine/include/renderengine/mock/Framebuffer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,23 +14,22 @@
* limitations under the License.
*/
-#include "mock/RenderEngine/MockRenderEngine.h"
+#pragma once
-#include <ui/Region.h>
+#include <gmock/gmock.h>
+#include <renderengine/Framebuffer.h>
namespace android {
namespace renderengine {
namespace mock {
-// Explicit default instantiation is recommended.
-RenderEngine::RenderEngine() = default;
-RenderEngine::~RenderEngine() = default;
+class Framebuffer : public renderengine::Framebuffer {
+public:
+ Framebuffer();
+ ~Framebuffer() override;
-Image::Image() = default;
-Image::~Image() = default;
-
-Framebuffer::Framebuffer() = default;
-Framebuffer::~Framebuffer() = default;
+ MOCK_METHOD2(setNativeWindowBuffer, bool(ANativeWindowBuffer*, bool));
+};
} // namespace mock
} // namespace renderengine
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp b/libs/renderengine/include/renderengine/mock/Image.h
similarity index 63%
copy from services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
copy to libs/renderengine/include/renderengine/mock/Image.h
index fbfbc3f..2b0eed1 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
+++ b/libs/renderengine/include/renderengine/mock/Image.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,23 +14,22 @@
* limitations under the License.
*/
-#include "mock/RenderEngine/MockRenderEngine.h"
+#pragma once
-#include <ui/Region.h>
+#include <gmock/gmock.h>
+#include <renderengine/Image.h>
namespace android {
namespace renderengine {
namespace mock {
-// Explicit default instantiation is recommended.
-RenderEngine::RenderEngine() = default;
-RenderEngine::~RenderEngine() = default;
+class Image : public renderengine::Image {
+public:
+ Image();
+ ~Image() override;
-Image::Image() = default;
-Image::~Image() = default;
-
-Framebuffer::Framebuffer() = default;
-Framebuffer::~Framebuffer() = default;
+ MOCK_METHOD2(setNativeWindowBuffer, bool(ANativeWindowBuffer* buffer, bool isProtected));
+};
} // namespace mock
} // namespace renderengine
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h
similarity index 82%
rename from services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
rename to libs/renderengine/include/renderengine/mock/RenderEngine.h
index 81a7768..b4c7c96 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
+++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,13 +18,12 @@
#include <gmock/gmock.h>
#include <renderengine/DisplaySettings.h>
-#include <renderengine/Framebuffer.h>
-#include <renderengine/Image.h>
#include <renderengine/LayerSettings.h>
#include <renderengine/Mesh.h>
#include <renderengine/RenderEngine.h>
#include <renderengine/Texture.h>
#include <ui/GraphicBuffer.h>
+#include <ui/Region.h>
namespace android {
namespace renderengine {
@@ -35,7 +34,7 @@
RenderEngine();
~RenderEngine() override;
- MOCK_METHOD0(createFramebuffer, std::unique_ptr<Framebuffer>());
+ MOCK_METHOD0(createFramebuffer, std::unique_ptr<renderengine::Framebuffer>());
MOCK_METHOD0(createImage, std::unique_ptr<renderengine::Image>());
MOCK_CONST_METHOD0(primeCache, void());
MOCK_METHOD1(dump, void(std::string&));
@@ -69,9 +68,9 @@
MOCK_METHOD1(setSourceDataSpace, void(ui::Dataspace));
MOCK_METHOD1(setOutputDataSpace, void(ui::Dataspace));
MOCK_METHOD1(setDisplayMaxLuminance, void(const float));
- MOCK_METHOD1(bindFrameBuffer, status_t(Framebuffer*));
- MOCK_METHOD1(unbindFrameBuffer, void(Framebuffer*));
- MOCK_METHOD1(drawMesh, void(const Mesh&));
+ MOCK_METHOD1(bindFrameBuffer, status_t(renderengine::Framebuffer*));
+ MOCK_METHOD1(unbindFrameBuffer, void(renderengine::Framebuffer*));
+ MOCK_METHOD1(drawMesh, void(const renderengine::Mesh&));
MOCK_CONST_METHOD0(getMaxTextureSize, size_t());
MOCK_CONST_METHOD0(getMaxViewportDims, size_t());
MOCK_CONST_METHOD0(isProtected, bool());
@@ -82,22 +81,6 @@
ANativeWindowBuffer*, base::unique_fd*));
};
-class Image : public renderengine::Image {
-public:
- Image();
- ~Image() override;
-
- MOCK_METHOD2(setNativeWindowBuffer, bool(ANativeWindowBuffer*, bool));
-};
-
-class Framebuffer : public renderengine::Framebuffer {
-public:
- Framebuffer();
- ~Framebuffer() override;
-
- MOCK_METHOD2(setNativeWindowBuffer, bool(ANativeWindowBuffer*, bool));
-};
-
} // namespace mock
} // namespace renderengine
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp b/libs/renderengine/mock/Framebuffer.cpp
similarity index 70%
copy from services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
copy to libs/renderengine/mock/Framebuffer.cpp
index fbfbc3f..fbdcaab 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
+++ b/libs/renderengine/mock/Framebuffer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,21 +14,14 @@
* limitations under the License.
*/
-#include "mock/RenderEngine/MockRenderEngine.h"
-
-#include <ui/Region.h>
+#include <renderengine/mock/Framebuffer.h>
namespace android {
namespace renderengine {
namespace mock {
-// Explicit default instantiation is recommended.
-RenderEngine::RenderEngine() = default;
-RenderEngine::~RenderEngine() = default;
-
-Image::Image() = default;
-Image::~Image() = default;
-
+// The Google Mock documentation recommends explicit non-header instantiations
+// for better compile time performance.
Framebuffer::Framebuffer() = default;
Framebuffer::~Framebuffer() = default;
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp b/libs/renderengine/mock/Image.cpp
similarity index 68%
copy from services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
copy to libs/renderengine/mock/Image.cpp
index fbfbc3f..57f4346 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
+++ b/libs/renderengine/mock/Image.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,24 +14,17 @@
* limitations under the License.
*/
-#include "mock/RenderEngine/MockRenderEngine.h"
-
-#include <ui/Region.h>
+#include <renderengine/mock/Image.h>
namespace android {
namespace renderengine {
namespace mock {
-// Explicit default instantiation is recommended.
-RenderEngine::RenderEngine() = default;
-RenderEngine::~RenderEngine() = default;
-
+// The Google Mock documentation recommends explicit non-header instantiations
+// for better compile time performance.
Image::Image() = default;
Image::~Image() = default;
-Framebuffer::Framebuffer() = default;
-Framebuffer::~Framebuffer() = default;
-
} // namespace mock
} // namespace renderengine
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp b/libs/renderengine/mock/RenderEngine.cpp
similarity index 71%
rename from services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
rename to libs/renderengine/mock/RenderEngine.cpp
index fbfbc3f..261636d 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
+++ b/libs/renderengine/mock/RenderEngine.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,24 +14,17 @@
* limitations under the License.
*/
-#include "mock/RenderEngine/MockRenderEngine.h"
-
-#include <ui/Region.h>
+#include <renderengine/mock/RenderEngine.h>
namespace android {
namespace renderengine {
namespace mock {
-// Explicit default instantiation is recommended.
+// The Google Mock documentation recommends explicit non-header instantiations
+// for better compile time performance.
RenderEngine::RenderEngine() = default;
RenderEngine::~RenderEngine() = default;
-Image::Image() = default;
-Image::~Image() = default;
-
-Framebuffer::Framebuffer() = default;
-Framebuffer::~Framebuffer() = default;
-
} // namespace mock
} // namespace renderengine
} // namespace android
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index a0542dd..bef25a8 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -27,15 +27,30 @@
namespace android {
struct RenderEngineTest : public ::testing::Test {
- sp<GraphicBuffer> allocateDefaultBuffer() {
+ static sp<GraphicBuffer> allocateDefaultBuffer() {
return new GraphicBuffer(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT,
HAL_PIXEL_FORMAT_RGBA_8888, 1,
- GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+ GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
+ GRALLOC_USAGE_HW_RENDER,
"output");
}
+ // Allocates a 1x1 buffer to fill with a solid color
+ static sp<GraphicBuffer> allocateSourceBuffer(uint32_t width, uint32_t height) {
+ return new GraphicBuffer(width, height, HAL_PIXEL_FORMAT_RGBA_8888, 1,
+ GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
+ GRALLOC_USAGE_HW_TEXTURE,
+ "input");
+ }
+
RenderEngineTest() { mBuffer = allocateDefaultBuffer(); }
+ ~RenderEngineTest() {
+ for (uint32_t texName : mTexNames) {
+ sRE->deleteTextures(1, &texName);
+ }
+ }
+
void expectBufferColor(const Rect& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a,
uint8_t tolerance = 0) {
uint8_t* pixels;
@@ -146,27 +161,112 @@
void fillBufferCheckersRotate270();
template <typename SourceVariant>
+ void fillBufferWithLayerTransform();
+
+ template <typename SourceVariant>
void fillBufferLayerTransform();
template <typename SourceVariant>
+ void fillBufferWithColorTransform();
+
+ template <typename SourceVariant>
void fillBufferColorTransform();
+ template <typename SourceVariant>
+ void fillRedBufferWithRoundedCorners();
+
+ template <typename SourceVariant>
+ void fillBufferWithRoundedCorners();
+
+ void fillRedBufferTextureTransform();
+
+ void fillBufferTextureTransform();
+
+ void fillRedBufferWithPremultiplyAlpha();
+
+ void fillBufferWithPremultiplyAlpha();
+
+ void fillRedBufferWithoutPremultiplyAlpha();
+
+ void fillBufferWithoutPremultiplyAlpha();
+
+ void fillGreenColorBufferThenClearRegion();
+
+ void clearLeftRegion();
+
+ void fillBufferThenClearRegion();
+
// Dumb hack to get aroud the fact that tear-down for renderengine isn't
// well defined right now, so we can't create multiple instances
static std::unique_ptr<renderengine::RenderEngine> sRE;
sp<GraphicBuffer> mBuffer;
+
+ std::vector<uint32_t> mTexNames;
};
std::unique_ptr<renderengine::RenderEngine> RenderEngineTest::sRE =
renderengine::RenderEngine::create(static_cast<int32_t>(ui::PixelFormat::RGBA_8888), 0);
struct ColorSourceVariant {
- static void fillColor(renderengine::LayerSettings& layer, half r, half g, half b) {
+ static void fillColor(renderengine::LayerSettings& layer, half r, half g, half b,
+ RenderEngineTest* /*fixture*/) {
layer.source.solidColor = half3(r, g, b);
}
};
+struct RelaxOpaqueBufferVariant {
+ static void setOpaqueBit(renderengine::LayerSettings& layer) {
+ layer.source.buffer.isOpaque = false;
+ }
+
+ static uint8_t getAlphaChannel() { return 255; }
+};
+
+struct ForceOpaqueBufferVariant {
+ static void setOpaqueBit(renderengine::LayerSettings& layer) {
+ layer.source.buffer.isOpaque = true;
+ }
+
+ static uint8_t getAlphaChannel() {
+ // The isOpaque bit will override the alpha channel, so this should be
+ // arbitrary.
+ return 10;
+ }
+};
+
+template <typename OpaquenessVariant>
+struct BufferSourceVariant {
+ static void fillColor(renderengine::LayerSettings& layer, half r, half g, half b,
+ RenderEngineTest* fixture) {
+ sp<GraphicBuffer> buf = RenderEngineTest::allocateSourceBuffer(1, 1);
+ uint32_t texName;
+ RenderEngineTest::sRE->genTextures(1, &texName);
+ fixture->mTexNames.push_back(texName);
+
+ uint8_t* pixels;
+ buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+ reinterpret_cast<void**>(&pixels));
+
+ for (int32_t j = 0; j < buf->getHeight(); j++) {
+ uint8_t* iter = pixels + (buf->getStride() * j) * 4;
+ for (int32_t i = 0; i < buf->getWidth(); i++) {
+ iter[0] = uint8_t(r * 255);
+ iter[1] = uint8_t(g * 255);
+ iter[2] = uint8_t(b * 255);
+ iter[3] = OpaquenessVariant::getAlphaChannel();
+ iter += 4;
+ }
+ }
+
+ buf->unlock();
+
+ layer.source.buffer.buffer = buf;
+ layer.source.buffer.textureName = texName;
+ OpaquenessVariant::setOpaqueBit(layer);
+ }
+};
+
template <typename SourceVariant>
void RenderEngineTest::fillBuffer(half r, half g, half b, half a) {
renderengine::DisplaySettings settings;
@@ -177,7 +277,7 @@
renderengine::LayerSettings layer;
layer.geometry.boundaries = fullscreenRect().toFloatRect();
- SourceVariant::fillColor(layer, r, g, b);
+ SourceVariant::fillColor(layer, r, g, b, this);
layer.alpha = a;
layers.push_back(layer);
@@ -219,7 +319,7 @@
renderengine::LayerSettings layer;
layer.geometry.boundaries = offsetRectAtZero().toFloatRect();
- SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f);
+ SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
layer.alpha = 1.0f;
layers.push_back(layer);
@@ -253,19 +353,19 @@
renderengine::LayerSettings layerOne;
Rect rectOne(0, 0, 1, 1);
layerOne.geometry.boundaries = rectOne.toFloatRect();
- SourceVariant::fillColor(layerOne, 1.0f, 0.0f, 0.0f);
+ SourceVariant::fillColor(layerOne, 1.0f, 0.0f, 0.0f, this);
layerOne.alpha = 1.0f;
renderengine::LayerSettings layerTwo;
Rect rectTwo(0, 1, 1, 2);
layerTwo.geometry.boundaries = rectTwo.toFloatRect();
- SourceVariant::fillColor(layerTwo, 0.0f, 1.0f, 0.0f);
+ SourceVariant::fillColor(layerTwo, 0.0f, 1.0f, 0.0f, this);
layerTwo.alpha = 1.0f;
renderengine::LayerSettings layerThree;
Rect rectThree(1, 0, 2, 1);
layerThree.geometry.boundaries = rectThree.toFloatRect();
- SourceVariant::fillColor(layerThree, 0.0f, 0.0f, 1.0f);
+ SourceVariant::fillColor(layerThree, 0.0f, 0.0f, 1.0f, this);
layerThree.alpha = 1.0f;
layers.push_back(layerOne);
@@ -343,7 +443,7 @@
}
template <typename SourceVariant>
-void RenderEngineTest::fillBufferLayerTransform() {
+void RenderEngineTest::fillBufferWithLayerTransform() {
renderengine::DisplaySettings settings;
settings.physicalDisplay = fullscreenRect();
// Here logical space is 2x2
@@ -355,13 +455,18 @@
layer.geometry.boundaries = Rect(1, 1).toFloatRect();
// Translate one pixel diagonally
layer.geometry.positionTransform = mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1);
+ SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
layer.source.solidColor = half3(1.0f, 0.0f, 0.0f);
layer.alpha = 1.0f;
layers.push_back(layer);
invokeDraw(settings, layers, mBuffer);
+}
+template <typename SourceVariant>
+void RenderEngineTest::fillBufferLayerTransform() {
+ fillBufferWithLayerTransform<SourceVariant>();
expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT / 2), 0, 0, 0, 0);
expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT), 0, 0, 0, 0);
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2,
@@ -370,7 +475,7 @@
}
template <typename SourceVariant>
-void RenderEngineTest::fillBufferColorTransform() {
+void RenderEngineTest::fillBufferWithColorTransform() {
renderengine::DisplaySettings settings;
settings.physicalDisplay = fullscreenRect();
settings.clip = Rect(1, 1);
@@ -379,7 +484,7 @@
renderengine::LayerSettings layer;
layer.geometry.boundaries = Rect(1, 1).toFloatRect();
- layer.source.solidColor = half3(0.5f, 0.25f, 0.125f);
+ SourceVariant::fillColor(layer, 0.5f, 0.25f, 0.125f, this);
layer.alpha = 1.0f;
// construct a fake color matrix
@@ -388,13 +493,208 @@
// set red channel to red + green
layer.colorTransform = mat4(1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
+ layer.alpha = 1.0f;
+ layer.geometry.boundaries = Rect(1, 1).toFloatRect();
+
layers.push_back(layer);
invokeDraw(settings, layers, mBuffer);
+}
+template <typename SourceVariant>
+void RenderEngineTest::fillBufferColorTransform() {
+ fillBufferWithColorTransform<SourceVariant>();
expectBufferColor(fullscreenRect(), 191, 0, 0, 255);
}
+template <typename SourceVariant>
+void RenderEngineTest::fillRedBufferWithRoundedCorners() {
+ renderengine::DisplaySettings settings;
+ settings.physicalDisplay = fullscreenRect();
+ settings.clip = fullscreenRect();
+
+ std::vector<renderengine::LayerSettings> layers;
+
+ renderengine::LayerSettings layer;
+ layer.geometry.boundaries = fullscreenRect().toFloatRect();
+ layer.geometry.roundedCornersRadius = 5.0f;
+ layer.geometry.roundedCornersCrop = fullscreenRect().toFloatRect();
+ SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
+ layer.alpha = 1.0f;
+
+ layers.push_back(layer);
+
+ invokeDraw(settings, layers, mBuffer);
+}
+
+template <typename SourceVariant>
+void RenderEngineTest::fillBufferWithRoundedCorners() {
+ fillRedBufferWithRoundedCorners<SourceVariant>();
+ // Corners should be ignored...
+ expectBufferColor(Rect(0, 0, 1, 1), 0, 0, 0, 0);
+ expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH - 1, 0, DEFAULT_DISPLAY_WIDTH, 1), 0, 0, 0, 0);
+ expectBufferColor(Rect(0, DEFAULT_DISPLAY_HEIGHT - 1, 1, DEFAULT_DISPLAY_HEIGHT), 0, 0, 0, 0);
+ expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH - 1, DEFAULT_DISPLAY_HEIGHT - 1,
+ DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+ 0, 0, 0, 0);
+ // ...And the non-rounded portion should be red.
+ // Other pixels may be anti-aliased, so let's not check those.
+ expectBufferColor(Rect(5, 5, DEFAULT_DISPLAY_WIDTH - 5, DEFAULT_DISPLAY_HEIGHT - 5), 255, 0, 0,
+ 255);
+}
+
+void RenderEngineTest::fillRedBufferTextureTransform() {
+ renderengine::DisplaySettings settings;
+ settings.physicalDisplay = fullscreenRect();
+ settings.clip = Rect(1, 1);
+
+ std::vector<renderengine::LayerSettings> layers;
+
+ renderengine::LayerSettings layer;
+ // Here will allocate a checker board texture, but transform texture
+ // coordinates so that only the upper left is applied.
+ sp<GraphicBuffer> buf = allocateSourceBuffer(2, 2);
+ uint32_t texName;
+ RenderEngineTest::sRE->genTextures(1, &texName);
+ this->mTexNames.push_back(texName);
+
+ uint8_t* pixels;
+ buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+ reinterpret_cast<void**>(&pixels));
+ // Red top left, Green top right, Blue bottom left, Black bottom right
+ pixels[0] = 255;
+ pixels[1] = 0;
+ pixels[2] = 0;
+ pixels[3] = 255;
+ pixels[4] = 0;
+ pixels[5] = 255;
+ pixels[6] = 0;
+ pixels[7] = 255;
+ pixels[8] = 0;
+ pixels[9] = 0;
+ pixels[10] = 255;
+ pixels[11] = 255;
+ buf->unlock();
+
+ layer.source.buffer.buffer = buf;
+ layer.source.buffer.textureName = texName;
+ // Transform coordinates to only be inside the red quadrant.
+ layer.source.buffer.textureTransform = mat4::scale(vec4(0.2, 0.2, 1, 1));
+ layer.alpha = 1.0f;
+ layer.geometry.boundaries = Rect(1, 1).toFloatRect();
+
+ layers.push_back(layer);
+
+ invokeDraw(settings, layers, mBuffer);
+}
+
+void RenderEngineTest::fillBufferTextureTransform() {
+ fillRedBufferTextureTransform();
+ expectBufferColor(fullscreenRect(), 255, 0, 0, 255);
+}
+
+void RenderEngineTest::fillRedBufferWithPremultiplyAlpha() {
+ renderengine::DisplaySettings settings;
+ settings.physicalDisplay = fullscreenRect();
+ // Here logical space is 1x1
+ settings.clip = Rect(1, 1);
+
+ std::vector<renderengine::LayerSettings> layers;
+
+ renderengine::LayerSettings layer;
+ sp<GraphicBuffer> buf = allocateSourceBuffer(1, 1);
+ uint32_t texName;
+ RenderEngineTest::sRE->genTextures(1, &texName);
+ this->mTexNames.push_back(texName);
+
+ uint8_t* pixels;
+ buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+ reinterpret_cast<void**>(&pixels));
+ pixels[0] = 255;
+ pixels[1] = 0;
+ pixels[2] = 0;
+ pixels[3] = 255;
+ buf->unlock();
+
+ layer.source.buffer.buffer = buf;
+ layer.source.buffer.textureName = texName;
+ layer.source.buffer.usePremultipliedAlpha = true;
+ layer.alpha = 0.5f;
+ layer.geometry.boundaries = Rect(1, 1).toFloatRect();
+
+ layers.push_back(layer);
+
+ invokeDraw(settings, layers, mBuffer);
+}
+
+void RenderEngineTest::fillBufferWithPremultiplyAlpha() {
+ fillRedBufferWithPremultiplyAlpha();
+ expectBufferColor(fullscreenRect(), 128, 0, 0, 128);
+}
+
+void RenderEngineTest::fillRedBufferWithoutPremultiplyAlpha() {
+ renderengine::DisplaySettings settings;
+ settings.physicalDisplay = fullscreenRect();
+ // Here logical space is 1x1
+ settings.clip = Rect(1, 1);
+
+ std::vector<renderengine::LayerSettings> layers;
+
+ renderengine::LayerSettings layer;
+ sp<GraphicBuffer> buf = allocateSourceBuffer(1, 1);
+ uint32_t texName;
+ RenderEngineTest::sRE->genTextures(1, &texName);
+ this->mTexNames.push_back(texName);
+
+ uint8_t* pixels;
+ buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+ reinterpret_cast<void**>(&pixels));
+ pixels[0] = 255;
+ pixels[1] = 0;
+ pixels[2] = 0;
+ pixels[3] = 255;
+ buf->unlock();
+
+ layer.source.buffer.buffer = buf;
+ layer.source.buffer.textureName = texName;
+ layer.source.buffer.usePremultipliedAlpha = false;
+ layer.alpha = 0.5f;
+ layer.geometry.boundaries = Rect(1, 1).toFloatRect();
+
+ layers.push_back(layer);
+
+ invokeDraw(settings, layers, mBuffer);
+}
+
+void RenderEngineTest::fillBufferWithoutPremultiplyAlpha() {
+ fillRedBufferWithoutPremultiplyAlpha();
+ expectBufferColor(fullscreenRect(), 128, 0, 0, 64, 1);
+}
+
+void RenderEngineTest::clearLeftRegion() {
+ renderengine::DisplaySettings settings;
+ settings.physicalDisplay = fullscreenRect();
+ // Here logical space is 4x4
+ settings.clip = Rect(4, 4);
+ settings.globalTransform = mat4::scale(vec4(2, 4, 0, 1));
+ settings.clearRegion = Region(Rect(1, 1));
+ std::vector<renderengine::LayerSettings> layers;
+ // dummy layer, without bounds should not render anything
+ renderengine::LayerSettings layer;
+ layers.push_back(layer);
+ invokeDraw(settings, layers, mBuffer);
+}
+
+void RenderEngineTest::fillBufferThenClearRegion() {
+ fillGreenBuffer<ColorSourceVariant>();
+ // Reuse mBuffer
+ clearLeftRegion();
+ expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT), 0, 0, 0, 255);
+ expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, 0, DEFAULT_DISPLAY_WIDTH,
+ DEFAULT_DISPLAY_HEIGHT),
+ 0, 255, 0, 255);
+}
+
TEST_F(RenderEngineTest, drawLayers_noLayersToDraw) {
drawEmptyLayers();
}
@@ -443,4 +743,120 @@
fillBufferLayerTransform<ColorSourceVariant>();
}
+TEST_F(RenderEngineTest, drawLayers_fillBufferRoundedCorners_colorSource) {
+ fillBufferWithRoundedCorners<ColorSourceVariant>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillRedBuffer_opaqueBufferSource) {
+ fillRedBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillGreenBuffer_opaqueBufferSource) {
+ fillGreenBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBlueBuffer_opaqueBufferSource) {
+ fillBlueBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillRedTransparentBuffer_opaqueBufferSource) {
+ fillRedTransparentBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferPhysicalOffset_opaqueBufferSource) {
+ fillBufferPhysicalOffset<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate0_opaqueBufferSource) {
+ fillBufferCheckersRotate0<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate90_opaqueBufferSource) {
+ fillBufferCheckersRotate90<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate180_opaqueBufferSource) {
+ fillBufferCheckersRotate180<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate270_opaqueBufferSource) {
+ fillBufferCheckersRotate270<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferLayerTransform_opaqueBufferSource) {
+ fillBufferLayerTransform<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferColorTransform_opaqueBufferSource) {
+ fillBufferLayerTransform<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferRoundedCorners_opaqueBufferSource) {
+ fillBufferWithRoundedCorners<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillRedBuffer_bufferSource) {
+ fillRedBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillGreenBuffer_bufferSource) {
+ fillGreenBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBlueBuffer_bufferSource) {
+ fillBlueBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillRedTransparentBuffer_bufferSource) {
+ fillRedTransparentBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferPhysicalOffset_bufferSource) {
+ fillBufferPhysicalOffset<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate0_bufferSource) {
+ fillBufferCheckersRotate0<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate90_bufferSource) {
+ fillBufferCheckersRotate90<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate180_bufferSource) {
+ fillBufferCheckersRotate180<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate270_bufferSource) {
+ fillBufferCheckersRotate270<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferLayerTransform_bufferSource) {
+ fillBufferLayerTransform<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferColorTransform_bufferSource) {
+ fillBufferLayerTransform<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferRoundedCorners_bufferSource) {
+ fillBufferWithRoundedCorners<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferTextureTransform) {
+ fillBufferTextureTransform();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBuffer_premultipliesAlpha) {
+ fillBufferWithPremultiplyAlpha();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBuffer_withoutPremultiplyingAlpha) {
+ fillBufferWithoutPremultiplyAlpha();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferThenClearRegion) {
+ fillBufferThenClearRegion();
+}
+
} // namespace android
diff --git a/libs/sensorprivacy/SensorPrivacyManager.cpp b/libs/sensorprivacy/SensorPrivacyManager.cpp
index 1da79a0..f973cba 100644
--- a/libs/sensorprivacy/SensorPrivacyManager.cpp
+++ b/libs/sensorprivacy/SensorPrivacyManager.cpp
@@ -85,4 +85,22 @@
return false;
}
+status_t SensorPrivacyManager::linkToDeath(const sp<IBinder::DeathRecipient>& recipient)
+{
+ sp<hardware::ISensorPrivacyManager> service = getService();
+ if (service != nullptr) {
+ return IInterface::asBinder(service)->linkToDeath(recipient);
+ }
+ return INVALID_OPERATION;
+}
+
+status_t SensorPrivacyManager::unlinkToDeath(const sp<IBinder::DeathRecipient>& recipient)
+{
+ sp<hardware::ISensorPrivacyManager> service = getService();
+ if (service != nullptr) {
+ return IInterface::asBinder(service)->unlinkToDeath(recipient);
+ }
+ return INVALID_OPERATION;
+}
+
}; // namespace android
diff --git a/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h b/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h
index 8826595..2546a68 100644
--- a/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h
+++ b/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h
@@ -34,6 +34,9 @@
void removeSensorPrivacyListener(const sp<hardware::ISensorPrivacyListener>& listener);
bool isSensorPrivacyEnabled();
+ status_t linkToDeath(const sp<IBinder::DeathRecipient>& recipient);
+ status_t unlinkToDeath(const sp<IBinder::DeathRecipient>& recipient);
+
private:
Mutex mLock;
sp<hardware::ISensorPrivacyManager> mService;
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 956465c..d089bf6 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -77,6 +77,7 @@
],
shared_libs: [
+ "android.frameworks.bufferhub@1.0",
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.common@1.2",
"android.hardware.graphics.mapper@2.0",
@@ -93,7 +94,6 @@
"libutils",
"libutilscallstack",
"liblog",
- "libpdx_default_transport", // TODO(b/112338294): Remove this once BufferHub moved to use Binder.
],
export_shared_lib_headers: [
@@ -121,6 +121,7 @@
"libnativewindow_headers",
],
exclude_shared_libs: [
+ "android.frameworks.bufferhub@1.0",
"libpdx_default_transport",
],
},
@@ -148,9 +149,6 @@
"libhardware_headers",
"libui_headers",
],
-
- // TODO(b/117568153): Temporarily opt out using libcrt.
- no_libcrt: true,
}
cc_library_headers {
diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp
index 0582e1a..6310f29 100644
--- a/libs/ui/BufferHubBuffer.cpp
+++ b/libs/ui/BufferHubBuffer.cpp
@@ -14,151 +14,190 @@
* limitations under the License.
*/
-// We would eliminate the clang warnings introduced by libdpx.
-// TODO(b/112338294): Remove those once BufferHub moved to use Binder
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-#pragma clang diagnostic ignored "-Wdouble-promotion"
-#pragma clang diagnostic ignored "-Wgnu-case-range"
-#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
-#pragma clang diagnostic ignored "-Winconsistent-missing-destructor-override"
-#pragma clang diagnostic ignored "-Wnested-anon-types"
-#pragma clang diagnostic ignored "-Wpacked"
-#pragma clang diagnostic ignored "-Wshadow"
-#pragma clang diagnostic ignored "-Wsign-conversion"
-#pragma clang diagnostic ignored "-Wswitch-enum"
-#pragma clang diagnostic ignored "-Wundefined-func-template"
-#pragma clang diagnostic ignored "-Wunused-template"
-#pragma clang diagnostic ignored "-Wweak-vtables"
-#include <pdx/default_transport/client_channel.h>
-#include <pdx/default_transport/client_channel_factory.h>
-#include <pdx/file_handle.h>
-#include <private/dvr/bufferhub_rpc.h>
-#pragma clang diagnostic pop
-
#include <poll.h>
#include <android-base/unique_fd.h>
+#include <android/frameworks/bufferhub/1.0/IBufferHub.h>
+#include <log/log.h>
#include <ui/BufferHubBuffer.h>
#include <ui/BufferHubDefs.h>
+#include <utils/Trace.h>
-using android::base::unique_fd;
-using android::dvr::BufferTraits;
-using android::dvr::DetachedBufferRPC;
-using android::dvr::NativeHandleWrapper;
-
-// TODO(b/112338294): Remove PDX dependencies from libui.
-using android::pdx::LocalChannelHandle;
-using android::pdx::LocalHandle;
-using android::pdx::Status;
-using android::pdx::default_transport::ClientChannel;
-using android::pdx::default_transport::ClientChannelFactory;
+using ::android::base::unique_fd;
+using ::android::BufferHubDefs::AnyClientAcquired;
+using ::android::BufferHubDefs::AnyClientGained;
+using ::android::BufferHubDefs::IsClientAcquired;
+using ::android::BufferHubDefs::IsClientGained;
+using ::android::BufferHubDefs::IsClientPosted;
+using ::android::BufferHubDefs::IsClientReleased;
+using ::android::frameworks::bufferhub::V1_0::BufferHubStatus;
+using ::android::frameworks::bufferhub::V1_0::BufferTraits;
+using ::android::frameworks::bufferhub::V1_0::IBufferClient;
+using ::android::frameworks::bufferhub::V1_0::IBufferHub;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::graphics::common::V1_2::HardwareBufferDescription;
namespace android {
-namespace {
-
-// TODO(b/112338294): Remove this string literal after refactoring BufferHub
-// to use Binder.
-static constexpr char kBufferHubClientPath[] = "system/buffer_hub/client";
-
-using BufferHubDefs::AnyClientAcquired;
-using BufferHubDefs::AnyClientGained;
-using BufferHubDefs::AnyClientPosted;
-using BufferHubDefs::IsClientAcquired;
-using BufferHubDefs::IsClientGained;
-using BufferHubDefs::IsClientPosted;
-using BufferHubDefs::IsClientReleased;
-using BufferHubDefs::kHighBitsMask;
-
-} // namespace
-
-BufferHubClient::BufferHubClient() : Client(ClientChannelFactory::Create(kBufferHubClientPath)) {}
-
-BufferHubClient::BufferHubClient(LocalChannelHandle mChannelHandle)
- : Client(ClientChannel::Create(std::move(mChannelHandle))) {}
-
-BufferHubClient::~BufferHubClient() {}
-
-bool BufferHubClient::IsValid() const {
- return IsConnected() && GetChannelHandle().valid();
+std::unique_ptr<BufferHubBuffer> BufferHubBuffer::Create(uint32_t width, uint32_t height,
+ uint32_t layerCount, uint32_t format,
+ uint64_t usage, size_t userMetadataSize) {
+ auto buffer = std::unique_ptr<BufferHubBuffer>(
+ new BufferHubBuffer(width, height, layerCount, format, usage, userMetadataSize));
+ return buffer->IsValid() ? std::move(buffer) : nullptr;
}
-LocalChannelHandle BufferHubClient::TakeChannelHandle() {
- if (IsConnected()) {
- return std::move(GetChannelHandle());
- } else {
- return {};
+std::unique_ptr<BufferHubBuffer> BufferHubBuffer::Import(const native_handle_t* token) {
+ if (token == nullptr) {
+ ALOGE("%s: token cannot be nullptr!", __FUNCTION__);
+ return nullptr;
}
+
+ auto buffer = std::unique_ptr<BufferHubBuffer>(new BufferHubBuffer(token));
+ return buffer->IsValid() ? std::move(buffer) : nullptr;
}
BufferHubBuffer::BufferHubBuffer(uint32_t width, uint32_t height, uint32_t layerCount,
- uint32_t format, uint64_t usage, size_t mUserMetadataSize) {
+ uint32_t format, uint64_t usage, size_t userMetadataSize) {
ATRACE_CALL();
- ALOGD("%s: width=%u height=%u layerCount=%u, format=%u usage=%" PRIx64 " mUserMetadataSize=%zu",
- __FUNCTION__, width, height, layerCount, format, usage, mUserMetadataSize);
+ ALOGD("%s: width=%u height=%u layerCount=%u, format=%u "
+ "usage=%" PRIx64 " mUserMetadataSize=%zu",
+ __FUNCTION__, width, height, layerCount, format, usage, userMetadataSize);
- auto status =
- mClient.InvokeRemoteMethod<DetachedBufferRPC::Create>(width, height, layerCount, format,
- usage, mUserMetadataSize);
- if (!status) {
- ALOGE("%s: Failed to create detached buffer: %s", __FUNCTION__,
- status.GetErrorMessage().c_str());
- mClient.Close(-status.error());
+ sp<IBufferHub> bufferhub = IBufferHub::getService();
+ if (bufferhub.get() == nullptr) {
+ ALOGE("%s: BufferHub service not found!", __FUNCTION__);
+ return;
}
- const int ret = ImportGraphicBuffer();
- if (ret < 0) {
- ALOGE("%s: Failed to import buffer: %s", __FUNCTION__, strerror(-ret));
- mClient.Close(ret);
+ AHardwareBuffer_Desc aDesc = {width, height, layerCount, format,
+ usage, /*stride=*/0UL, /*rfu0=*/0UL, /*rfu1=*/0ULL};
+ HardwareBufferDescription desc;
+ memcpy(&desc, &aDesc, sizeof(HardwareBufferDescription));
+
+ BufferHubStatus ret;
+ sp<IBufferClient> client;
+ BufferTraits bufferTraits;
+ IBufferHub::allocateBuffer_cb alloc_cb = [&](const auto& status, const auto& outClient,
+ const auto& traits) {
+ ret = status;
+ client = std::move(outClient);
+ bufferTraits = std::move(traits);
+ };
+
+ if (!bufferhub->allocateBuffer(desc, static_cast<uint32_t>(userMetadataSize), alloc_cb)
+ .isOk()) {
+ ALOGE("%s: allocateBuffer transaction failed!", __FUNCTION__);
+ return;
+ } else if (ret != BufferHubStatus::NO_ERROR) {
+ ALOGE("%s: allocateBuffer failed with error %u.", __FUNCTION__, ret);
+ return;
+ } else if (client == nullptr) {
+ ALOGE("%s: allocateBuffer got null BufferClient.", __FUNCTION__);
+ return;
+ }
+
+ const int importRet = initWithBufferTraits(bufferTraits);
+ if (importRet < 0) {
+ ALOGE("%s: Failed to import buffer: %s", __FUNCTION__, strerror(-importRet));
+ client->close();
+ }
+ mBufferClient = std::move(client);
+}
+
+BufferHubBuffer::BufferHubBuffer(const native_handle_t* token) {
+ sp<IBufferHub> bufferhub = IBufferHub::getService();
+ if (bufferhub.get() == nullptr) {
+ ALOGE("%s: BufferHub service not found!", __FUNCTION__);
+ return;
+ }
+
+ BufferHubStatus ret;
+ sp<IBufferClient> client;
+ BufferTraits bufferTraits;
+ IBufferHub::importBuffer_cb import_cb = [&](const auto& status, const auto& outClient,
+ const auto& traits) {
+ ret = status;
+ client = std::move(outClient);
+ bufferTraits = std::move(traits);
+ };
+
+ // hidl_handle(native_handle_t*) simply creates a raw pointer reference withouth ownership
+ // transfer.
+ if (!bufferhub->importBuffer(hidl_handle(token), import_cb).isOk()) {
+ ALOGE("%s: importBuffer transaction failed!", __FUNCTION__);
+ return;
+ } else if (ret != BufferHubStatus::NO_ERROR) {
+ ALOGE("%s: importBuffer failed with error %u.", __FUNCTION__, ret);
+ return;
+ } else if (client == nullptr) {
+ ALOGE("%s: importBuffer got null BufferClient.", __FUNCTION__);
+ return;
+ }
+
+ const int importRet = initWithBufferTraits(bufferTraits);
+ if (importRet < 0) {
+ ALOGE("%s: Failed to import buffer: %s", __FUNCTION__, strerror(-importRet));
+ client->close();
+ }
+ mBufferClient = std::move(client);
+}
+
+BufferHubBuffer::~BufferHubBuffer() {
+ // Close buffer client to avoid possible race condition: user could first duplicate and hold
+ // token with the original buffer gone, and then try to import the token. The close function
+ // will explicitly invalidate the token to avoid this.
+ if (mBufferClient != nullptr) {
+ if (!mBufferClient->close().isOk()) {
+ ALOGE("%s: close BufferClient transaction failed!", __FUNCTION__);
+ }
}
}
-BufferHubBuffer::BufferHubBuffer(LocalChannelHandle mChannelHandle)
- : mClient(std::move(mChannelHandle)) {
- const int ret = ImportGraphicBuffer();
- if (ret < 0) {
- ALOGE("%s: Failed to import buffer: %s", __FUNCTION__, strerror(-ret));
- mClient.Close(ret);
- }
-}
-
-int BufferHubBuffer::ImportGraphicBuffer() {
+int BufferHubBuffer::initWithBufferTraits(const BufferTraits& bufferTraits) {
ATRACE_CALL();
- auto status = mClient.InvokeRemoteMethod<DetachedBufferRPC::Import>();
- if (!status) {
- ALOGE("%s: Failed to import GraphicBuffer: %s", __FUNCTION__,
- status.GetErrorMessage().c_str());
- return -status.error();
+ if (bufferTraits.bufferInfo.getNativeHandle() == nullptr) {
+ ALOGE("%s: missing buffer info handle.", __FUNCTION__);
+ return -EINVAL;
}
- BufferTraits<LocalHandle> bufferTraits = status.take();
- if (bufferTraits.id() < 0) {
- ALOGE("%s: Received an invalid id!", __FUNCTION__);
- return -EIO;
+ if (bufferTraits.bufferHandle.getNativeHandle() == nullptr) {
+ ALOGE("%s: missing gralloc handle.", __FUNCTION__);
+ return -EINVAL;
}
- // Stash the buffer id to replace the value in mId.
- const int bufferId = bufferTraits.id();
+ int bufferId = bufferTraits.bufferInfo->data[1];
+ if (bufferId < 0) {
+ ALOGE("%s: Received an invalid (negative) id!", __FUNCTION__);
+ return -EINVAL;
+ }
- // Import the metadata.
- LocalHandle metadataHandle = bufferTraits.take_metadata_handle();
- unique_fd metadataFd(metadataHandle.Release());
- mMetadata = BufferHubMetadata::Import(std::move(metadataFd));
+ uint32_t clientBitMask;
+ memcpy(&clientBitMask, &bufferTraits.bufferInfo->data[2], sizeof(clientBitMask));
+ if (clientBitMask == 0U) {
+ ALOGE("%s: Received a invalid client state mask!", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ // Import the metadata. Dup since hidl_handle owns the fd
+ unique_fd ashmemFd(fcntl(bufferTraits.bufferInfo->data[0], F_DUPFD_CLOEXEC, 0));
+ mMetadata = BufferHubMetadata::Import(std::move(ashmemFd));
if (!mMetadata.IsValid()) {
ALOGE("%s: invalid metadata.", __FUNCTION__);
- return -ENOMEM;
+ return -EINVAL;
}
- if (mMetadata.metadata_size() != bufferTraits.metadata_size()) {
- ALOGE("%s: metadata buffer too small: %zu, expected: %" PRIu64 ".", __FUNCTION__,
- mMetadata.metadata_size(), bufferTraits.metadata_size());
- return -ENOMEM;
+ uint32_t userMetadataSize;
+ memcpy(&userMetadataSize, &bufferTraits.bufferInfo->data[3], sizeof(userMetadataSize));
+ if (mMetadata.user_metadata_size() != userMetadataSize) {
+ ALOGE("%s: user metadata size not match: expected %u, actual %zu.", __FUNCTION__,
+ userMetadataSize, mMetadata.user_metadata_size());
+ return -EINVAL;
}
- size_t metadataSize = static_cast<size_t>(bufferTraits.metadata_size());
+ size_t metadataSize = static_cast<size_t>(mMetadata.metadata_size());
if (metadataSize < BufferHubDefs::kMetadataHeaderSize) {
ALOGE("%s: metadata too small: %zu", __FUNCTION__, metadataSize);
return -EINVAL;
@@ -179,24 +218,14 @@
// Import the buffer: We only need to hold on the native_handle_t here so that
// GraphicBuffer instance can be created in future.
- mBufferHandle = bufferTraits.take_buffer_handle();
+ mBufferHandle = std::move(bufferTraits.bufferHandle);
+ memcpy(&mBufferDesc, &bufferTraits.bufferDesc, sizeof(AHardwareBuffer_Desc));
- // Populate buffer desc based on buffer traits.
- mBufferDesc.width = bufferTraits.width();
- mBufferDesc.height = bufferTraits.height();
- mBufferDesc.layers = bufferTraits.layer_count();
- mBufferDesc.format = bufferTraits.format();
- mBufferDesc.usage = bufferTraits.usage();
- mBufferDesc.stride = bufferTraits.stride();
- mBufferDesc.rfu0 = 0U;
- mBufferDesc.rfu1 = 0U;
-
- // If all imports succeed, replace the previous buffer and id.
mId = bufferId;
- mClientStateMask = bufferTraits.client_state_mask();
+ mClientStateMask = clientBitMask;
// TODO(b/112012161) Set up shared fences.
- ALOGD("%s: id=%d, buffer_state=%" PRIx32 ".", __FUNCTION__, id(),
+ ALOGD("%s: id=%d, buffer_state=%" PRIx32 ".", __FUNCTION__, mId,
buffer_state_->load(std::memory_order_acquire));
return 0;
}
@@ -226,8 +255,7 @@
int BufferHubBuffer::Post() {
uint32_t current_buffer_state = buffer_state_->load(std::memory_order_acquire);
- uint32_t current_active_clients_bit_mask = 0U;
- uint32_t updated_buffer_state = 0U;
+ uint32_t updated_buffer_state = (~mClientStateMask) & BufferHubDefs::kHighBitsMask;
do {
if (!IsClientGained(current_buffer_state, mClientStateMask)) {
ALOGE("%s: Cannot post a buffer that is not gained by this client. buffer_id=%d "
@@ -236,9 +264,7 @@
return -EBUSY;
}
// Set the producer client buffer state to released, other clients' buffer state to posted.
- current_active_clients_bit_mask = active_clients_bit_mask_->load(std::memory_order_acquire);
- updated_buffer_state =
- current_active_clients_bit_mask & (~mClientStateMask) & kHighBitsMask;
+ // Post to all existing and non-existing clients.
} while (!buffer_state_->compare_exchange_weak(current_buffer_state, updated_buffer_state,
std::memory_order_acq_rel,
std::memory_order_acquire));
@@ -287,24 +313,37 @@
return 0;
}
-int BufferHubBuffer::Poll(int timeoutMs) {
- ATRACE_CALL();
-
- pollfd p = {mClient.event_fd(), POLLIN, 0};
- return poll(&p, 1, timeoutMs);
+bool BufferHubBuffer::IsValid() const {
+ // TODO(b/68770788): check eventFd once implemented
+ return mBufferHandle.getNativeHandle() != nullptr && mId >= 0 && mClientStateMask != 0U &&
+ mMetadata.IsValid() && mBufferClient != nullptr;
}
-Status<LocalChannelHandle> BufferHubBuffer::Duplicate() {
- ATRACE_CALL();
- ALOGD("%s: id=%d.", __FUNCTION__, mId);
-
- auto statusOrHandle = mClient.InvokeRemoteMethod<DetachedBufferRPC::Duplicate>();
-
- if (!statusOrHandle.ok()) {
- ALOGE("%s: Failed to duplicate buffer (id=%d): %s.", __FUNCTION__, mId,
- statusOrHandle.GetErrorMessage().c_str());
+native_handle_t* BufferHubBuffer::Duplicate() {
+ if (mBufferClient == nullptr) {
+ ALOGE("%s: missing BufferClient!", __FUNCTION__);
+ return nullptr;
}
- return statusOrHandle;
+
+ hidl_handle token;
+ BufferHubStatus ret;
+ IBufferClient::duplicate_cb dup_cb = [&](const auto& outToken, const auto& status) {
+ token = std::move(outToken);
+ ret = status;
+ };
+
+ if (!mBufferClient->duplicate(dup_cb).isOk()) {
+ ALOGE("%s: duplicate transaction failed!", __FUNCTION__);
+ return nullptr;
+ } else if (ret != BufferHubStatus::NO_ERROR) {
+ ALOGE("%s: duplicate failed with error %u.", __FUNCTION__, ret);
+ return nullptr;
+ } else if (token.getNativeHandle() == nullptr) {
+ ALOGE("%s: duplicate got null token.", __FUNCTION__);
+ return nullptr;
+ }
+
+ return native_handle_clone(token.getNativeHandle());
}
} // namespace android
diff --git a/libs/ui/include/ui/BufferHubBuffer.h b/libs/ui/include/ui/BufferHubBuffer.h
index 90dd391..c6a4a23 100644
--- a/libs/ui/include/ui/BufferHubBuffer.h
+++ b/libs/ui/include/ui/BufferHubBuffer.h
@@ -17,73 +17,43 @@
#ifndef ANDROID_BUFFER_HUB_BUFFER_H_
#define ANDROID_BUFFER_HUB_BUFFER_H_
-// We would eliminate the clang warnings introduced by libdpx.
-// TODO(b/112338294): Remove those once BufferHub moved to use Binder
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-#pragma clang diagnostic ignored "-Wdouble-promotion"
-#pragma clang diagnostic ignored "-Wgnu-case-range"
-#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
-#pragma clang diagnostic ignored "-Winconsistent-missing-destructor-override"
-#pragma clang diagnostic ignored "-Wnested-anon-types"
-#pragma clang diagnostic ignored "-Wpacked"
-#pragma clang diagnostic ignored "-Wshadow"
-#pragma clang diagnostic ignored "-Wsign-conversion"
-#pragma clang diagnostic ignored "-Wswitch-enum"
-#pragma clang diagnostic ignored "-Wundefined-func-template"
-#pragma clang diagnostic ignored "-Wunused-template"
-#pragma clang diagnostic ignored "-Wweak-vtables"
-#include <pdx/client.h>
-#include <private/dvr/native_handle_wrapper.h>
-#pragma clang diagnostic pop
-
+#include <android/frameworks/bufferhub/1.0/IBufferClient.h>
#include <android/hardware_buffer.h>
+#include <cutils/native_handle.h>
#include <ui/BufferHubDefs.h>
#include <ui/BufferHubMetadata.h>
namespace android {
-class BufferHubClient : public pdx::Client {
-public:
- BufferHubClient();
- virtual ~BufferHubClient();
- explicit BufferHubClient(pdx::LocalChannelHandle mChannelHandle);
-
- bool IsValid() const;
- pdx::LocalChannelHandle TakeChannelHandle();
-
- using pdx::Client::Close;
- using pdx::Client::event_fd;
- using pdx::Client::GetChannel;
- using pdx::Client::InvokeRemoteMethod;
-};
-
class BufferHubBuffer {
public:
- // Allocates a standalone BufferHubBuffer not associated with any producer consumer set.
+ // Allocates a standalone BufferHubBuffer.
static std::unique_ptr<BufferHubBuffer> Create(uint32_t width, uint32_t height,
uint32_t layerCount, uint32_t format,
- uint64_t usage, size_t userMetadataSize) {
- return std::unique_ptr<BufferHubBuffer>(
- new BufferHubBuffer(width, height, layerCount, format, usage, userMetadataSize));
- }
+ uint64_t usage, size_t userMetadataSize);
- // Imports the given channel handle to a BufferHubBuffer, taking ownership.
- static std::unique_ptr<BufferHubBuffer> Import(pdx::LocalChannelHandle mChannelHandle) {
- return std::unique_ptr<BufferHubBuffer>(new BufferHubBuffer(std::move(mChannelHandle)));
- }
+ // Imports the given token to a BufferHubBuffer. Not taking ownership of the token. Caller
+ // should close and destroy the token after calling this function regardless of output.
+ // TODO(b/122543147): use a movable wrapper for token
+ static std::unique_ptr<BufferHubBuffer> Import(const native_handle_t* token);
BufferHubBuffer(const BufferHubBuffer&) = delete;
void operator=(const BufferHubBuffer&) = delete;
+ virtual ~BufferHubBuffer();
+
// Gets ID of the buffer client. All BufferHubBuffer clients derived from the same buffer in
- // bufferhubd share the same buffer id.
+ // BufferHub share the same buffer id.
int id() const { return mId; }
- // Returns the buffer description, which is guaranteed to be faithful values from bufferhubd.
+ // Returns the buffer description, which is guaranteed to be faithful values from BufferHub.
const AHardwareBuffer_Desc& desc() const { return mBufferDesc; }
- const native_handle_t* DuplicateHandle() { return mBufferHandle.DuplicateHandle(); }
+ // Duplicate the underlying Gralloc buffer handle. Caller is responsible to free the handle
+ // after use.
+ native_handle_t* DuplicateHandle() {
+ return native_handle_clone(mBufferHandle.getNativeHandle());
+ }
// Returns the current value of MetadataHeader::buffer_state.
uint32_t buffer_state() {
@@ -96,12 +66,12 @@
size_t user_metadata_size() const { return mMetadata.user_metadata_size(); }
- // Returns true if the buffer holds an open PDX channels towards bufferhubd.
- bool IsConnected() const { return mClient.IsValid(); }
+ // Returns true if the BufferClient is still alive.
+ bool IsConnected() const { return mBufferClient->ping().isOk(); }
- // Returns true if the buffer holds an valid native buffer handle that's availble for the client
- // to read from and/or write into.
- bool IsValid() const { return mBufferHandle.IsValid(); }
+ // Returns true if the buffer is valid: non-null buffer handle, valid id, valid client bit mask,
+ // valid metadata and valid buffer client
+ bool IsValid() const;
// Gains the buffer for exclusive write permission. Read permission is implied once a buffer is
// gained.
@@ -124,33 +94,24 @@
// current cycle of the usage of the buffer.
int Release();
- // Returns the event mask for all the events that are pending on this buffer (see sys/poll.h for
- // all possible bits).
- pdx::Status<int> GetEventMask(int events) {
- if (auto* channel = mClient.GetChannel()) {
- return channel->GetEventMask(events);
- } else {
- return pdx::ErrorStatus(EINVAL);
- }
- }
-
- // Polls the fd for |timeoutMs| milliseconds (-1 for infinity).
- int Poll(int timeoutMs);
-
- // Creates a BufferHubBuffer client from an existing one. The new client will
- // share the same underlying gralloc buffer and ashmem region for metadata.
- pdx::Status<pdx::LocalChannelHandle> Duplicate();
+ // Creates a token that stands for this BufferHubBuffer client and could be used for Import to
+ // create another BufferHubBuffer. The new BufferHubBuffer will share the same underlying
+ // gralloc buffer and ashmem region for metadata. Note that the caller owns the token and
+ // should free it after use.
+ // Returns a valid token on success, nullptr on failure.
+ // TODO(b/122543147): use a movable wrapper for token
+ native_handle_t* Duplicate();
private:
BufferHubBuffer(uint32_t width, uint32_t height, uint32_t layerCount, uint32_t format,
uint64_t usage, size_t userMetadataSize);
- BufferHubBuffer(pdx::LocalChannelHandle mChannelHandle);
+ BufferHubBuffer(const native_handle_t* token);
- int ImportGraphicBuffer();
+ int initWithBufferTraits(const frameworks::bufferhub::V1_0::BufferTraits& bufferTraits);
// Global id for the buffer that is consistent across processes.
- int mId = -1;
+ int mId = 0;
// Client state mask of this BufferHubBuffer object. It is unique amoung all
// clients/users of the buffer.
@@ -159,8 +120,8 @@
// Stores ground truth of the buffer.
AHardwareBuffer_Desc mBufferDesc;
- // Wrapps the gralloc buffer handle of this buffer.
- dvr::NativeHandleWrapper<pdx::LocalHandle> mBufferHandle;
+ // Wraps the gralloc buffer handle of this buffer.
+ hardware::hidl_handle mBufferHandle;
// An ashmem-based metadata object. The same shared memory are mapped to the
// bufferhubd daemon and all buffer clients.
@@ -170,8 +131,8 @@
std::atomic<uint32_t>* fence_state_ = nullptr;
std::atomic<uint32_t>* active_clients_bit_mask_ = nullptr;
- // PDX backend.
- BufferHubClient mClient;
+ // HwBinder backend
+ sp<frameworks::bufferhub::V1_0::IBufferClient> mBufferClient;
};
} // namespace android
diff --git a/libs/ui/include/ui/BufferHubDefs.h b/libs/ui/include/ui/BufferHubDefs.h
index d259fef..069f0dc 100644
--- a/libs/ui/include/ui/BufferHubDefs.h
+++ b/libs/ui/include/ui/BufferHubDefs.h
@@ -158,6 +158,29 @@
static_assert(sizeof(MetadataHeader) == 128, "Unexpected MetadataHeader size");
static constexpr size_t kMetadataHeaderSize = sizeof(MetadataHeader);
+/**
+ * android.frameworks.bufferhub@1.0::BufferTraits.bufferInfo is an opaque handle. See
+ * https://cs.corp.google.com/android/frameworks/hardware/interfaces/bufferhub/1.0/types.hal for
+ * more details about android.frameworks.bufferhub@1.0::BufferTraits.
+ *
+ * This definition could be changed, but implementation of BufferHubService::buildBufferInfo
+ * (frameworks/native/services/bufferhub), VtsHalBufferHubV1_0TargetTest
+ * (frameworks/hardware/interfaces/bufferhub) and BufferHubBuffer::readBufferTraits (libui) will
+ * also need to be updated.
+ *
+ * It's definition should follow the following format:
+ * {
+ * NumFds = 1,
+ * NumInts = 3,
+ * data[0] = Ashmem fd for BufferHubMetadata,
+ * data[1] = buffer id,
+ * data[2] = client state bit mask,
+ * data[3] = user metadata size,
+ * }
+ */
+static constexpr int kBufferInfoNumFds = 1;
+static constexpr int kBufferInfoNumInts = 3;
+
} // namespace BufferHubDefs
} // namespace android
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index a670b3c..665469e 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -31,12 +31,14 @@
cc_test {
name: "GraphicBuffer_test",
header_libs: [
- "libbufferhub_headers",
"libdvr_headers",
"libnativewindow_headers",
],
shared_libs: [
- "libpdx_default_transport",
+ "android.frameworks.bufferhub@1.0",
+ "libcutils",
+ "libhidlbase",
+ "libhwbinder",
"libui",
"libutils",
],
@@ -47,7 +49,6 @@
cc_test {
name: "BufferHub_test",
header_libs: [
- "libbufferhub_headers",
"libdvr_headers",
"libnativewindow_headers",
],
@@ -60,7 +61,6 @@
"libhidlbase",
"libhwbinder",
"liblog",
- "libpdx_default_transport",
"libui",
"libutils"
],
diff --git a/libs/ui/tests/BufferHubBuffer_test.cpp b/libs/ui/tests/BufferHubBuffer_test.cpp
index 1b339a0..cd744cd 100644
--- a/libs/ui/tests/BufferHubBuffer_test.cpp
+++ b/libs/ui/tests/BufferHubBuffer_test.cpp
@@ -16,10 +16,9 @@
#define LOG_TAG "BufferHubBufferTest"
-#include <android/frameworks/bufferhub/1.0/IBufferClient.h>
-#include <android/frameworks/bufferhub/1.0/IBufferHub.h>
#include <android/hardware_buffer.h>
#include <cutils/native_handle.h>
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <hidl/ServiceManagement.h>
#include <hwbinder/IPCThreadState.h>
@@ -29,36 +28,38 @@
namespace {
+using ::android::BufferHubDefs::AnyClientAcquired;
+using ::android::BufferHubDefs::AnyClientGained;
+using ::android::BufferHubDefs::AnyClientPosted;
+using ::android::BufferHubDefs::IsBufferReleased;
+using ::android::BufferHubDefs::IsClientAcquired;
+using ::android::BufferHubDefs::IsClientGained;
+using ::android::BufferHubDefs::IsClientPosted;
+using ::android::BufferHubDefs::IsClientReleased;
+using ::android::BufferHubDefs::kMetadataHeaderSize;
+using ::testing::IsNull;
+using ::testing::NotNull;
+
const int kWidth = 640;
const int kHeight = 480;
const int kLayerCount = 1;
const int kFormat = HAL_PIXEL_FORMAT_RGBA_8888;
const int kUsage = 0;
-const size_t kUserMetadataSize = 0;
-
-using BufferHubDefs::AnyClientAcquired;
-using BufferHubDefs::AnyClientGained;
-using BufferHubDefs::AnyClientPosted;
-using BufferHubDefs::IsBufferReleased;
-using BufferHubDefs::IsClientAcquired;
-using BufferHubDefs::IsClientGained;
-using BufferHubDefs::IsClientPosted;
-using BufferHubDefs::IsClientReleased;
-using BufferHubDefs::kFirstClientBitMask;
-using BufferHubDefs::kMetadataHeaderSize;
-using frameworks::bufferhub::V1_0::BufferHubStatus;
-using frameworks::bufferhub::V1_0::IBufferClient;
-using frameworks::bufferhub::V1_0::IBufferHub;
-using hardware::hidl_handle;
-using hardware::graphics::common::V1_2::HardwareBufferDescription;
-using hidl::base::V1_0::IBase;
-using pdx::LocalChannelHandle;
+const AHardwareBuffer_Desc kDesc = {kWidth, kHeight, kLayerCount, kFormat,
+ kUsage, /*stride=*/0UL, /*rfu0=*/0UL, /*rfu1=*/0ULL};
+const size_t kUserMetadataSize = 1;
class BufferHubBufferTest : public ::testing::Test {
protected:
void SetUp() override { android::hardware::ProcessState::self()->startThreadPool(); }
};
+bool cmpAHardwareBufferDesc(const AHardwareBuffer_Desc& desc, const AHardwareBuffer_Desc& other) {
+ // Not comparing stride because it's unknown before allocation
+ return desc.format == other.format && desc.height == other.height &&
+ desc.layers == other.layers && desc.usage == other.usage && desc.width == other.width;
+}
+
class BufferHubBufferStateTransitionTest : public BufferHubBufferTest {
protected:
void SetUp() override {
@@ -67,9 +68,9 @@
}
std::unique_ptr<BufferHubBuffer> b1;
- uint64_t b1ClientMask = 0U;
+ uint32_t b1ClientMask = 0U;
std::unique_ptr<BufferHubBuffer> b2;
- uint64_t b2ClientMask = 0U;
+ uint32_t b2ClientMask = 0U;
private:
// Creates b1 and b2 as the clients of the same buffer for testing.
@@ -78,91 +79,126 @@
void BufferHubBufferStateTransitionTest::CreateTwoClientsOfABuffer() {
b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize);
+ ASSERT_THAT(b1, NotNull());
b1ClientMask = b1->client_state_mask();
ASSERT_NE(b1ClientMask, 0U);
- auto statusOrHandle = b1->Duplicate();
- ASSERT_TRUE(statusOrHandle);
- LocalChannelHandle h2 = statusOrHandle.take();
- b2 = BufferHubBuffer::Import(std::move(h2));
+
+ native_handle_t* token = b1->Duplicate();
+ ASSERT_THAT(token, NotNull());
+
+ // TODO(b/122543147): use a movalbe wrapper for token
+ b2 = BufferHubBuffer::Import(token);
+ native_handle_close(token);
+ native_handle_delete(token);
+ ASSERT_THAT(b2, NotNull());
+
b2ClientMask = b2->client_state_mask();
ASSERT_NE(b2ClientMask, 0U);
ASSERT_NE(b2ClientMask, b1ClientMask);
}
-TEST_F(BufferHubBufferTest, CreateBufferHubBufferFails) {
+TEST_F(BufferHubBufferTest, CreateBufferFails) {
// Buffer Creation will fail: BLOB format requires height to be 1.
auto b1 = BufferHubBuffer::Create(kWidth, /*height=*/2, kLayerCount,
/*format=*/HAL_PIXEL_FORMAT_BLOB, kUsage, kUserMetadataSize);
- EXPECT_FALSE(b1->IsConnected());
- EXPECT_FALSE(b1->IsValid());
+ EXPECT_THAT(b1, IsNull());
// Buffer Creation will fail: user metadata size too large.
auto b2 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
/*userMetadataSize=*/std::numeric_limits<size_t>::max());
- EXPECT_FALSE(b2->IsConnected());
- EXPECT_FALSE(b2->IsValid());
+ EXPECT_THAT(b2, IsNull());
// Buffer Creation will fail: user metadata size too large.
const size_t userMetadataSize = std::numeric_limits<size_t>::max() - kMetadataHeaderSize;
auto b3 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
userMetadataSize);
- EXPECT_FALSE(b3->IsConnected());
- EXPECT_FALSE(b3->IsValid());
+ EXPECT_THAT(b3, IsNull());
}
-TEST_F(BufferHubBufferTest, CreateBufferHubBuffer) {
+TEST_F(BufferHubBufferTest, CreateBuffer) {
auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
kUserMetadataSize);
+ ASSERT_THAT(b1, NotNull());
EXPECT_TRUE(b1->IsConnected());
EXPECT_TRUE(b1->IsValid());
- EXPECT_NE(b1->id(), 0);
+ EXPECT_TRUE(cmpAHardwareBufferDesc(b1->desc(), kDesc));
+ EXPECT_EQ(b1->user_metadata_size(), kUserMetadataSize);
}
-TEST_F(BufferHubBufferTest, DuplicateBufferHubBuffer) {
+TEST_F(BufferHubBufferTest, DuplicateAndImportBuffer) {
auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
kUserMetadataSize);
- int id1 = b1->id();
- uint64_t bufferStateMask1 = b1->client_state_mask();
- EXPECT_NE(bufferStateMask1, 0U);
+ ASSERT_THAT(b1, NotNull());
EXPECT_TRUE(b1->IsValid());
- EXPECT_EQ(b1->user_metadata_size(), kUserMetadataSize);
- auto statusOrHandle = b1->Duplicate();
- EXPECT_TRUE(statusOrHandle);
+ native_handle_t* token = b1->Duplicate();
+ EXPECT_TRUE(token);
// The detached buffer should still be valid.
EXPECT_TRUE(b1->IsConnected());
EXPECT_TRUE(b1->IsValid());
- // Gets the channel handle for the duplicated buffer.
- LocalChannelHandle h2 = statusOrHandle.take();
- EXPECT_TRUE(h2.valid());
+ std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(token);
+ native_handle_close(token);
+ native_handle_delete(token);
- std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(std::move(h2));
- EXPECT_FALSE(h2.valid());
- ASSERT_TRUE(b2 != nullptr);
+ ASSERT_THAT(b2, NotNull());
EXPECT_TRUE(b2->IsValid());
- EXPECT_EQ(b2->user_metadata_size(), kUserMetadataSize);
- int id2 = b2->id();
- uint64_t bufferStateMask2 = b2->client_state_mask();
- EXPECT_NE(bufferStateMask2, 0U);
+ EXPECT_TRUE(cmpAHardwareBufferDesc(b1->desc(), b2->desc()));
+ EXPECT_EQ(b1->user_metadata_size(), b2->user_metadata_size());
// These two buffer instances are based on the same physical buffer under the
// hood, so they should share the same id.
- EXPECT_EQ(id1, id2);
+ EXPECT_EQ(b1->id(), b2->id());
// We use client_state_mask() to tell those two instances apart.
- EXPECT_NE(bufferStateMask1, bufferStateMask2);
+ EXPECT_NE(b1->client_state_mask(), b2->client_state_mask());
// Both buffer instances should be in released state currently.
EXPECT_TRUE(IsBufferReleased(b1->buffer_state()));
EXPECT_TRUE(IsBufferReleased(b2->buffer_state()));
+}
- // TODO(b/112338294): rewrite test after migration
- return;
+TEST_F(BufferHubBufferTest, ImportFreedBuffer) {
+ auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
+ kUserMetadataSize);
+ ASSERT_THAT(b1, NotNull());
+ EXPECT_TRUE(b1->IsValid());
+
+ native_handle_t* token = b1->Duplicate();
+ EXPECT_TRUE(token);
+
+ // Explicitly destroy b1. Backend buffer should be freed and token becomes invalid
+ b1.reset();
+
+ // TODO(b/122543147): use a movalbe wrapper for token
+ std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(token);
+ native_handle_close(token);
+ native_handle_delete(token);
+
+ // Import should fail with INVALID_TOKEN
+ EXPECT_THAT(b2, IsNull());
+}
+
+// nullptr must not crash the service
+TEST_F(BufferHubBufferTest, ImportNullToken) {
+ auto b1 = BufferHubBuffer::Import(nullptr);
+ EXPECT_THAT(b1, IsNull());
+}
+
+// TODO(b/118180214): remove the comment after ag/5856474 landed
+// This test has a very little chance to fail (number of existing tokens / 2 ^ 32)
+TEST_F(BufferHubBufferTest, ImportInvalidToken) {
+ native_handle_t* token = native_handle_create(/*numFds=*/0, /*numInts=*/1);
+ token->data[0] = 0;
+
+ auto b1 = BufferHubBuffer::Import(token);
+ native_handle_delete(token);
+
+ EXPECT_THAT(b1, IsNull());
}
TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromReleasedState) {
@@ -340,5 +376,67 @@
EXPECT_EQ(b2->Release(), 0);
}
+TEST_F(BufferHubBufferStateTransitionTest, BasicUsage) {
+ // 1 producer buffer and 1 consumer buffer initialised in testcase setup.
+ // Test if this set of basic operation succeed:
+ // Producer post three times to the consumer, and released by consumer.
+ for (int i = 0; i < 3; ++i) {
+ ASSERT_EQ(b1->Gain(), 0);
+ ASSERT_EQ(b1->Post(), 0);
+ ASSERT_EQ(b2->Acquire(), 0);
+ ASSERT_EQ(b2->Release(), 0);
+ }
+}
+
+TEST_F(BufferHubBufferTest, createNewConsumerAfterGain) {
+ // Create a poducer buffer and gain.
+ std::unique_ptr<BufferHubBuffer> b1 =
+ BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
+ kUserMetadataSize);
+ ASSERT_THAT(b1, NotNull());
+ ASSERT_EQ(b1->Gain(), 0);
+
+ // Create a consumer of the buffer and test if the consumer can acquire the
+ // buffer if producer posts.
+ // TODO(b/122543147): use a movalbe wrapper for token
+ native_handle_t* token = b1->Duplicate();
+ ASSERT_TRUE(token);
+
+ std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(token);
+ native_handle_close(token);
+ native_handle_delete(token);
+
+ ASSERT_THAT(b2, NotNull());
+ ASSERT_NE(b1->client_state_mask(), b2->client_state_mask());
+
+ ASSERT_EQ(b1->Post(), 0);
+ EXPECT_EQ(b2->Acquire(), 0);
+}
+
+TEST_F(BufferHubBufferTest, createNewConsumerAfterPost) {
+ // Create a poducer buffer and post.
+ std::unique_ptr<BufferHubBuffer> b1 =
+ BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
+ kUserMetadataSize);
+ ASSERT_EQ(b1->Gain(), 0);
+ ASSERT_EQ(b1->Post(), 0);
+
+ // Create a consumer of the buffer and test if the consumer can acquire the
+ // buffer if producer posts.
+ // TODO(b/122543147): use a movalbe wrapper for token
+ native_handle_t* token = b1->Duplicate();
+ ASSERT_TRUE(token);
+
+ std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(token);
+ native_handle_close(token);
+ native_handle_delete(token);
+
+ ASSERT_THAT(b2, NotNull());
+ ASSERT_NE(b1->client_state_mask(), b2->client_state_mask());
+
+ EXPECT_EQ(b2->Acquire(), 0);
+}
+
} // namespace
+
} // namespace android
diff --git a/libs/ui/tests/GraphicBuffer_test.cpp b/libs/ui/tests/GraphicBuffer_test.cpp
index 81ab3ac..5b46454 100644
--- a/libs/ui/tests/GraphicBuffer_test.cpp
+++ b/libs/ui/tests/GraphicBuffer_test.cpp
@@ -39,7 +39,7 @@
std::unique_ptr<BufferHubBuffer> b1 =
BufferHubBuffer::Create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat,
kTestUsage, /*userMetadataSize=*/0);
- EXPECT_NE(b1, nullptr);
+ ASSERT_NE(b1, nullptr);
EXPECT_TRUE(b1->IsValid());
sp<GraphicBuffer> gb(new GraphicBuffer(std::move(b1)));
diff --git a/libs/vr/OWNERS b/libs/vr/OWNERS
new file mode 100644
index 0000000..ec2d712
--- /dev/null
+++ b/libs/vr/OWNERS
@@ -0,0 +1,4 @@
+hendrikw@google.com
+jwcai@google.com
+steventhomas@google.com
+
diff --git a/libs/vr/libbufferhub/buffer_hub-test.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp
index 1359f4c..ed5a992 100644
--- a/libs/vr/libbufferhub/buffer_hub-test.cpp
+++ b/libs/vr/libbufferhub/buffer_hub-test.cpp
@@ -5,7 +5,6 @@
#include <private/dvr/producer_buffer.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
-#include <ui/BufferHubBuffer.h>
#include <ui/BufferHubDefs.h>
#include <mutex>
@@ -20,9 +19,6 @@
return result; \
})()
-using android::BufferHubBuffer;
-using android::GraphicBuffer;
-using android::sp;
using android::BufferHubDefs::AnyClientAcquired;
using android::BufferHubDefs::AnyClientGained;
using android::BufferHubDefs::AnyClientPosted;
@@ -31,19 +27,15 @@
using android::BufferHubDefs::IsClientPosted;
using android::BufferHubDefs::IsClientReleased;
using android::BufferHubDefs::kFirstClientBitMask;
-using android::BufferHubDefs::kMetadataHeaderSize;
using android::dvr::ConsumerBuffer;
using android::dvr::ProducerBuffer;
-using android::pdx::LocalChannelHandle;
using android::pdx::LocalHandle;
using android::pdx::Status;
const int kWidth = 640;
const int kHeight = 480;
-const int kLayerCount = 1;
const int kFormat = HAL_PIXEL_FORMAT_RGBA_8888;
const int kUsage = 0;
-const size_t kUserMetadataSize = 0;
// Maximum number of consumers for the buffer that only has one producer in the
// test.
const size_t kMaxConsumerCount =
@@ -361,9 +353,11 @@
ASSERT_TRUE(p.get() != nullptr);
ASSERT_EQ(0, p->GainAsync());
ASSERT_EQ(0, p->Post(LocalHandle()));
- // Producer state bit is in released state after post. The overall state of
- // the buffer is also released because there is no consumer of this buffer.
- ASSERT_TRUE(IsBufferReleased(p->buffer_state()));
+ // Producer state bit is in released state after post, other clients shall be
+ // in posted state although there is no consumer of this buffer yet.
+ ASSERT_TRUE(IsClientReleased(p->buffer_state(), p->client_state_mask()));
+ ASSERT_FALSE(IsBufferReleased(p->buffer_state()));
+ ASSERT_TRUE(AnyClientPosted(p->buffer_state()));
// Gain in released state should succeed.
LocalHandle invalid_fence;
@@ -450,27 +444,17 @@
LocalHandle invalid_fence;
// Post the gained buffer before any consumer gets created.
- // The buffer should be in released state because it is not expected to be
- // read by any clients.
EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
- EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
+ EXPECT_FALSE(IsBufferReleased(p->buffer_state()));
EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
- // Newly created consumer will not be signalled for the posted buffer before
- // its creation. It cannot acquire the buffer immediately.
+ // Newly created consumer will be signalled for the posted buffer although it
+ // is created after producer posting.
std::unique_ptr<ConsumerBuffer> c =
ConsumerBuffer::Import(p->CreateConsumer());
ASSERT_TRUE(c.get() != nullptr);
- EXPECT_FALSE(IsClientPosted(c->buffer_state(), c->client_state_mask()));
- EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
-
- // Producer should be able to gain back and post the buffer
- EXPECT_EQ(0, p->GainAsync());
- EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
-
- // Consumer should be able to pick up the buffer this time.
+ EXPECT_TRUE(IsClientPosted(c->buffer_state(), c->client_state_mask()));
EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
- EXPECT_TRUE(IsClientAcquired(c->buffer_state(), c->client_state_mask()));
}
TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferReleased) {
@@ -816,7 +800,7 @@
// TODO(b/112338294) rewrite test after migration
return;
- std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
+ /* std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
std::unique_ptr<ConsumerBuffer> c =
ConsumerBuffer::Import(p->CreateConsumer());
@@ -884,49 +868,14 @@
EXPECT_TRUE(d->IsConnected());
EXPECT_TRUE(d->IsValid());
- EXPECT_EQ(d->id(), p_id);
-}
-
-TEST_F(LibBufferHubTest, TestCreateBufferHubBufferFails) {
- // Buffer Creation will fail: BLOB format requires height to be 1.
- auto b1 = BufferHubBuffer::Create(kWidth, /*height=2*/ 2, kLayerCount,
- /*format=*/HAL_PIXEL_FORMAT_BLOB, kUsage,
- kUserMetadataSize);
-
- EXPECT_FALSE(b1->IsConnected());
- EXPECT_FALSE(b1->IsValid());
-
- // Buffer Creation will fail: user metadata size too large.
- auto b2 = BufferHubBuffer::Create(
- kWidth, kHeight, kLayerCount, kFormat, kUsage,
- /*user_metadata_size=*/std::numeric_limits<size_t>::max());
-
- EXPECT_FALSE(b2->IsConnected());
- EXPECT_FALSE(b2->IsValid());
-
- // Buffer Creation will fail: user metadata size too large.
- auto b3 = BufferHubBuffer::Create(
- kWidth, kHeight, kLayerCount, kFormat, kUsage,
- /*user_metadata_size=*/std::numeric_limits<size_t>::max() -
- kMetadataHeaderSize);
-
- EXPECT_FALSE(b3->IsConnected());
- EXPECT_FALSE(b3->IsValid());
-}
-
-TEST_F(LibBufferHubTest, TestCreateBufferHubBuffer) {
- auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat,
- kUsage, kUserMetadataSize);
- EXPECT_TRUE(b1->IsConnected());
- EXPECT_TRUE(b1->IsValid());
- EXPECT_NE(b1->id(), 0);
+ EXPECT_EQ(d->id(), p_id); */
}
TEST_F(LibBufferHubTest, TestDetach) {
// TODO(b/112338294) rewrite test after migration
return;
- std::unique_ptr<ProducerBuffer> p1 = ProducerBuffer::Create(
+ /* std::unique_ptr<ProducerBuffer> p1 = ProducerBuffer::Create(
kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
ASSERT_TRUE(p1.get() != nullptr);
int p1_id = p1->id();
@@ -944,47 +893,5 @@
EXPECT_FALSE(h1.valid());
EXPECT_TRUE(b1->IsValid());
int b1_id = b1->id();
- EXPECT_EQ(b1_id, p1_id);
-}
-
-TEST_F(LibBufferHubTest, TestDuplicateBufferHubBuffer) {
- auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat,
- kUsage, kUserMetadataSize);
- int b1_id = b1->id();
- EXPECT_TRUE(b1->IsValid());
- EXPECT_EQ(b1->user_metadata_size(), kUserMetadataSize);
- EXPECT_NE(b1->client_state_mask(), 0U);
-
- auto status_or_handle = b1->Duplicate();
- EXPECT_TRUE(status_or_handle);
-
- // The detached buffer should still be valid.
- EXPECT_TRUE(b1->IsConnected());
- EXPECT_TRUE(b1->IsValid());
-
- // Gets the channel handle for the duplicated buffer.
- LocalChannelHandle h2 = status_or_handle.take();
- EXPECT_TRUE(h2.valid());
-
- std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(std::move(h2));
- EXPECT_FALSE(h2.valid());
- ASSERT_TRUE(b2 != nullptr);
- EXPECT_TRUE(b2->IsValid());
- EXPECT_EQ(b2->user_metadata_size(), kUserMetadataSize);
- EXPECT_NE(b2->client_state_mask(), 0U);
-
- int b2_id = b2->id();
-
- // These two buffer instances are based on the same physical buffer under the
- // hood, so they should share the same id.
- EXPECT_EQ(b1_id, b2_id);
- // We use client_state_mask() to tell those two instances apart.
- EXPECT_NE(b1->client_state_mask(), b2->client_state_mask());
-
- // Both buffer instances should be in gained state.
- EXPECT_TRUE(IsBufferReleased(b1->buffer_state()));
- EXPECT_TRUE(IsBufferReleased(b2->buffer_state()));
-
- // TODO(b/112338294) rewrite test after migration
- return;
+ EXPECT_EQ(b1_id, p1_id); */
}
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
index 440a59d..889763a 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
@@ -94,6 +94,12 @@
return buffer_state_->load(std::memory_order_acquire);
};
+ // Returns whether the buffer is already released by all current clients.
+ bool is_released() {
+ return (buffer_state() &
+ active_clients_bit_mask_->load(std::memory_order_acquire)) == 0;
+ }
+
// A state mask which is unique to a buffer hub client among all its siblings
// sharing the same concrete graphic buffer.
uint32_t client_state_mask() const { return client_state_mask_; }
diff --git a/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h b/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h
index 7aa50b1..726f035 100644
--- a/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h
@@ -6,16 +6,6 @@
namespace android {
namespace dvr {
-// BufferConsumer was originally poorly named and gets easily confused with
-// IGraphicBufferConsumer. Actually, BufferConsumer is a single buffer that can
-// consume (i.e. read) data from a buffer, but it doesn't consume buffer. On
-// the other hand, IGraphicBufferConsumer is the consumer end of a BufferQueue
-// and it is used to consume buffers.
-//
-// TODO(b/116855254): Remove this typedef once rename is complete in other
-// projects and/or branches.
-typedef class ConsumerBuffer BufferConsumer;
-
// This is a connection to a producer buffer, which can be located in another
// application. When that buffer is Post()ed, this fd will be signaled and
// Acquire allows read access. The user is responsible for making sure that
diff --git a/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h b/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h
index 2761416..7ec345c 100644
--- a/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h
@@ -6,23 +6,13 @@
namespace android {
namespace dvr {
-// BufferProducer was originally poorly named and gets easily confused with
-// IGraphicBufferProducer. Actually, BufferProducer is a single buffer that can
-// produce (i.e. write) data into a buffer, but it doesn't produce buffer. On
-// the other hand, IGraphicBufferProducer is the producer end of a BufferQueue
-// and it is used to produce buffers.
-//
-// TODO(b/116855254): Remove this typedef once rename is complete in other
-// projects and/or branches.
-typedef class ProducerBuffer BufferProducer;
-
// This represents a writable buffer. Calling Post notifies all clients and
// makes the buffer read-only. Call Gain to acquire write access. A buffer
// may have many consumers.
//
// The user of ProducerBuffer is responsible with making sure that the Post() is
// done with the correct metadata type and size. The user is also responsible
-// for making sure that remote ends (BufferConsumers) are also using the correct
+// for making sure that remote ends (ConsumerBuffers) are also using the correct
// metadata when acquiring the buffer. The API guarantees that a Post() with a
// metadata of wrong size will fail. However, it currently does not do any
// type checking.
diff --git a/libs/vr/libbufferhub/producer_buffer.cpp b/libs/vr/libbufferhub/producer_buffer.cpp
index 5274bf2..edfdddf 100644
--- a/libs/vr/libbufferhub/producer_buffer.cpp
+++ b/libs/vr/libbufferhub/producer_buffer.cpp
@@ -89,13 +89,10 @@
return -EBUSY;
}
- // Set the producer client buffer state to released, other clients' buffer
- // state to posted.
- uint32_t current_active_clients_bit_mask =
- active_clients_bit_mask_->load(std::memory_order_acquire);
- uint32_t updated_buffer_state = current_active_clients_bit_mask &
- (~client_state_mask()) &
- BufferHubDefs::kHighBitsMask;
+ // Set the producer client buffer state to released, that of all other clients
+ // (both existing and non-existing clients) to posted.
+ uint32_t updated_buffer_state =
+ (~client_state_mask()) & BufferHubDefs::kHighBitsMask;
while (!buffer_state_->compare_exchange_weak(
current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
std::memory_order_acquire)) {
@@ -176,7 +173,9 @@
}
if (BufferHubDefs::AnyClientAcquired(current_buffer_state) ||
BufferHubDefs::AnyClientGained(current_buffer_state) ||
- (BufferHubDefs::AnyClientPosted(current_buffer_state) &&
+ (BufferHubDefs::AnyClientPosted(
+ current_buffer_state &
+ active_clients_bit_mask_->load(std::memory_order_acquire)) &&
!gain_posted_buffer)) {
ALOGE("%s: not released id=%d state=%" PRIx32 ".", __FUNCTION__, id(),
current_buffer_state);
@@ -198,7 +197,9 @@
if (BufferHubDefs::AnyClientAcquired(current_buffer_state) ||
BufferHubDefs::AnyClientGained(current_buffer_state) ||
- (BufferHubDefs::AnyClientPosted(current_buffer_state) &&
+ (BufferHubDefs::AnyClientPosted(
+ current_buffer_state &
+ active_clients_bit_mask_->load(std::memory_order_acquire)) &&
!gain_posted_buffer)) {
ALOGE(
"%s: Failed to gain the buffer. The buffer is no longer released. "
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index 9c4f73f..d7833f3 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -480,7 +480,7 @@
// Note that import might (though very unlikely) fail. If so, buffer_handle
// will be closed and included in returned buffer_slots.
- if (AddBuffer(BufferProducer::Import(std::move(buffer_handle)),
+ if (AddBuffer(ProducerBuffer::Import(std::move(buffer_handle)),
buffer_slot)) {
ALOGD_IF(TRACE, "ProducerQueue::AllocateBuffers: new buffer at slot: %zu",
buffer_slot);
@@ -517,7 +517,7 @@
}
Status<void> ProducerQueue::AddBuffer(
- const std::shared_ptr<BufferProducer>& buffer, size_t slot) {
+ const std::shared_ptr<ProducerBuffer>& buffer, size_t slot) {
ALOGD_IF(TRACE, "ProducerQueue::AddBuffer: queue_id=%d buffer_id=%d slot=%zu",
id(), buffer->id(), slot);
// For producer buffer, we need to enqueue the newly added buffer
@@ -530,7 +530,7 @@
}
Status<size_t> ProducerQueue::InsertBuffer(
- const std::shared_ptr<BufferProducer>& buffer) {
+ const std::shared_ptr<ProducerBuffer>& buffer) {
if (buffer == nullptr ||
!BufferHubDefs::IsClientGained(buffer->buffer_state(),
buffer->client_state_mask())) {
@@ -554,7 +554,7 @@
size_t slot = status_or_slot.get();
// Note that we are calling AddBuffer() from the base class to explicitly
- // avoid Enqueue() the BufferProducer.
+ // avoid Enqueue() the ProducerBuffer.
auto status = BufferHubQueue::AddBuffer(buffer, slot);
if (!status) {
ALOGE("ProducerQueue::InsertBuffer: Failed to add buffer: %s.",
@@ -576,13 +576,13 @@
return BufferHubQueue::RemoveBuffer(slot);
}
-Status<std::shared_ptr<BufferProducer>> ProducerQueue::Dequeue(
+Status<std::shared_ptr<ProducerBuffer>> ProducerQueue::Dequeue(
int timeout, size_t* slot, LocalHandle* release_fence) {
DvrNativeBufferMetadata canonical_meta;
return Dequeue(timeout, slot, &canonical_meta, release_fence);
}
-pdx::Status<std::shared_ptr<BufferProducer>> ProducerQueue::Dequeue(
+pdx::Status<std::shared_ptr<ProducerBuffer>> ProducerQueue::Dequeue(
int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
pdx::LocalHandle* release_fence, bool gain_posted_buffer) {
ATRACE_NAME("ProducerQueue::Dequeue");
@@ -591,14 +591,14 @@
return ErrorStatus(EINVAL);
}
- std::shared_ptr<BufferProducer> buffer;
+ std::shared_ptr<ProducerBuffer> buffer;
Status<std::shared_ptr<BufferHubBase>> dequeue_status =
BufferHubQueue::Dequeue(timeout, slot);
if (dequeue_status.ok()) {
- buffer = std::static_pointer_cast<BufferProducer>(dequeue_status.take());
+ buffer = std::static_pointer_cast<ProducerBuffer>(dequeue_status.take());
} else {
if (gain_posted_buffer) {
- Status<std::shared_ptr<BufferProducer>> dequeue_unacquired_status =
+ Status<std::shared_ptr<ProducerBuffer>> dequeue_unacquired_status =
ProducerQueue::DequeueUnacquiredBuffer(slot);
if (!dequeue_unacquired_status.ok()) {
ALOGE("%s: DequeueUnacquiredBuffer returned error: %d", __FUNCTION__,
@@ -618,7 +618,7 @@
return {std::move(buffer)};
}
-Status<std::shared_ptr<BufferProducer>> ProducerQueue::DequeueUnacquiredBuffer(
+Status<std::shared_ptr<ProducerBuffer>> ProducerQueue::DequeueUnacquiredBuffer(
size_t* slot) {
if (unavailable_buffers_slot_.size() < 1) {
ALOGE(
@@ -632,7 +632,7 @@
// unavailable_buffers_slot_.
for (auto iter = unavailable_buffers_slot_.begin();
iter != unavailable_buffers_slot_.end(); iter++) {
- std::shared_ptr<BufferProducer> buffer = ProducerQueue::GetBuffer(*iter);
+ std::shared_ptr<ProducerBuffer> buffer = ProducerQueue::GetBuffer(*iter);
if (buffer == nullptr) {
ALOGE("%s failed. Buffer slot %d is null.", __FUNCTION__,
static_cast<int>(*slot));
@@ -718,9 +718,9 @@
ALOGD_IF(TRACE, ": buffer_handle=%d", __FUNCTION__,
buffer_handle_slot.first.value());
- std::unique_ptr<BufferConsumer> buffer_consumer =
- BufferConsumer::Import(std::move(buffer_handle_slot.first));
- if (!buffer_consumer) {
+ std::unique_ptr<ConsumerBuffer> consumer_buffer =
+ ConsumerBuffer::Import(std::move(buffer_handle_slot.first));
+ if (!consumer_buffer) {
ALOGE("%s: Failed to import buffer: slot=%zu", __FUNCTION__,
buffer_handle_slot.second);
last_error = ErrorStatus(EPIPE);
@@ -728,7 +728,7 @@
}
auto add_status =
- AddBuffer(std::move(buffer_consumer), buffer_handle_slot.second);
+ AddBuffer(std::move(consumer_buffer), buffer_handle_slot.second);
if (!add_status) {
ALOGE("%s: Failed to add buffer: %s", __FUNCTION__,
add_status.GetErrorMessage().c_str());
@@ -745,13 +745,13 @@
}
Status<void> ConsumerQueue::AddBuffer(
- const std::shared_ptr<BufferConsumer>& buffer, size_t slot) {
+ const std::shared_ptr<ConsumerBuffer>& buffer, size_t slot) {
ALOGD_IF(TRACE, "%s: queue_id=%d buffer_id=%d slot=%zu", __FUNCTION__, id(),
buffer->id(), slot);
return BufferHubQueue::AddBuffer(buffer, slot);
}
-Status<std::shared_ptr<BufferConsumer>> ConsumerQueue::Dequeue(
+Status<std::shared_ptr<ConsumerBuffer>> ConsumerQueue::Dequeue(
int timeout, size_t* slot, void* meta, size_t user_metadata_size,
LocalHandle* acquire_fence) {
if (user_metadata_size != user_metadata_size_) {
@@ -780,7 +780,7 @@
return status;
}
-Status<std::shared_ptr<BufferConsumer>> ConsumerQueue::Dequeue(
+Status<std::shared_ptr<ConsumerBuffer>> ConsumerQueue::Dequeue(
int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
pdx::LocalHandle* acquire_fence) {
ATRACE_NAME("ConsumerQueue::Dequeue");
@@ -793,7 +793,7 @@
if (!status)
return status.error_status();
- auto buffer = std::static_pointer_cast<BufferConsumer>(status.take());
+ auto buffer = std::static_pointer_cast<ConsumerBuffer>(status.take());
const int ret = buffer->AcquireAsync(out_meta, acquire_fence);
if (ret < 0)
return ErrorStatus(-ret);
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
index 53ab2b2..74b4b3d 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
@@ -131,8 +131,8 @@
bool hung_up() const { return hung_up_; }
protected:
- BufferHubQueue(pdx::LocalChannelHandle channel);
- BufferHubQueue(const std::string& endpoint_path);
+ explicit BufferHubQueue(pdx::LocalChannelHandle channel);
+ explicit BufferHubQueue(const std::string& endpoint_path);
// Imports the queue parameters by querying BufferHub for the parameters for
// this channel.
@@ -307,12 +307,12 @@
return BASE::Create(std::move(handle));
}
- // Get a buffer producer. Note that the method doesn't check whether the
+ // Get a producer buffer. Note that the method doesn't check whether the
// buffer slot has a valid buffer that has been allocated already. When no
// buffer has been imported before it returns nullptr; otherwise it returns
- // a shared pointer to a BufferProducer.
- std::shared_ptr<BufferProducer> GetBuffer(size_t slot) const {
- return std::static_pointer_cast<BufferProducer>(
+ // a shared pointer to a ProducerBuffer.
+ std::shared_ptr<ProducerBuffer> GetBuffer(size_t slot) const {
+ return std::static_pointer_cast<ProducerBuffer>(
BufferHubQueue::GetBuffer(slot));
}
@@ -333,7 +333,7 @@
// Add a producer buffer to populate the queue. Once added, a producer buffer
// is available to use (i.e. in GAINED state).
- pdx::Status<void> AddBuffer(const std::shared_ptr<BufferProducer>& buffer,
+ pdx::Status<void> AddBuffer(const std::shared_ptr<ProducerBuffer>& buffer,
size_t slot);
// Inserts a ProducerBuffer into the queue. On success, the method returns the
@@ -341,7 +341,7 @@
// being inserted should be in Gain'ed state prior to the call and it's
// considered as already Dequeued when the function returns.
pdx::Status<size_t> InsertBuffer(
- const std::shared_ptr<BufferProducer>& buffer);
+ const std::shared_ptr<ProducerBuffer>& buffer);
// Remove producer buffer from the queue.
pdx::Status<void> RemoveBuffer(size_t slot) override;
@@ -355,7 +355,7 @@
// and caller should call Post() once it's done writing to release the buffer
// to the consumer side.
// @return a buffer in gained state, which was originally in released state.
- pdx::Status<std::shared_ptr<BufferProducer>> Dequeue(
+ pdx::Status<std::shared_ptr<ProducerBuffer>> Dequeue(
int timeout, size_t* slot, pdx::LocalHandle* release_fence);
// Dequeue a producer buffer to write. The returned buffer in |Gain|'ed mode,
@@ -363,7 +363,7 @@
// to the consumer side.
//
// @param timeout to dequeue a buffer.
- // @param slot is the slot of the output BufferProducer.
+ // @param slot is the slot of the output ProducerBuffer.
// @param release_fence for gaining a buffer.
// @param out_meta metadata of the output buffer.
// @param gain_posted_buffer whether to gain posted buffer if no released
@@ -375,12 +375,12 @@
// libdvrtracking from starving when there are non-responding clients. This
// gain_posted_buffer param can be removed once libdvrtracking start to use
// the new AHardwareBuffer API.
- pdx::Status<std::shared_ptr<BufferProducer>> Dequeue(
+ pdx::Status<std::shared_ptr<ProducerBuffer>> Dequeue(
int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
pdx::LocalHandle* release_fence, bool gain_posted_buffer = false);
// Enqueues a producer buffer in the queue.
- pdx::Status<void> Enqueue(const std::shared_ptr<BufferProducer>& buffer,
+ pdx::Status<void> Enqueue(const std::shared_ptr<ProducerBuffer>& buffer,
size_t slot, uint64_t index) {
return BufferHubQueue::Enqueue({buffer, slot, index});
}
@@ -406,18 +406,18 @@
// @param slot the slot of the returned buffer.
// @return a buffer in gained state, which was originally in posted state or
// released state.
- pdx::Status<std::shared_ptr<BufferProducer>> DequeueUnacquiredBuffer(
+ pdx::Status<std::shared_ptr<ProducerBuffer>> DequeueUnacquiredBuffer(
size_t* slot);
};
class ConsumerQueue : public BufferHubQueue {
public:
- // Get a buffer consumer. Note that the method doesn't check whether the
+ // Get a consumer buffer. Note that the method doesn't check whether the
// buffer slot has a valid buffer that has been imported already. When no
// buffer has been imported before it returns nullptr; otherwise returns a
- // shared pointer to a BufferConsumer.
- std::shared_ptr<BufferConsumer> GetBuffer(size_t slot) const {
- return std::static_pointer_cast<BufferConsumer>(
+ // shared pointer to a ConsumerBuffer.
+ std::shared_ptr<ConsumerBuffer> GetBuffer(size_t slot) const {
+ return std::static_pointer_cast<ConsumerBuffer>(
BufferHubQueue::GetBuffer(slot));
}
@@ -435,36 +435,36 @@
// Dequeue a consumer buffer to read. The returned buffer in |Acquired|'ed
// mode, and caller should call Releasse() once it's done writing to release
// the buffer to the producer side. |meta| is passed along from BufferHub,
- // The user of BufferProducer is responsible with making sure that the
+ // The user of ProducerBuffer is responsible with making sure that the
// Dequeue() is done with the corect metadata type and size with those used
// when the buffer is orignally created.
template <typename Meta>
- pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
+ pdx::Status<std::shared_ptr<ConsumerBuffer>> Dequeue(
int timeout, size_t* slot, Meta* meta, pdx::LocalHandle* acquire_fence) {
return Dequeue(timeout, slot, meta, sizeof(*meta), acquire_fence);
}
- pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
+ pdx::Status<std::shared_ptr<ConsumerBuffer>> Dequeue(
int timeout, size_t* slot, pdx::LocalHandle* acquire_fence) {
return Dequeue(timeout, slot, nullptr, 0, acquire_fence);
}
- pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
+ pdx::Status<std::shared_ptr<ConsumerBuffer>> Dequeue(
int timeout, size_t* slot, void* meta, size_t user_metadata_size,
pdx::LocalHandle* acquire_fence);
- pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
+ pdx::Status<std::shared_ptr<ConsumerBuffer>> Dequeue(
int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
pdx::LocalHandle* acquire_fence);
private:
friend BufferHubQueue;
- ConsumerQueue(pdx::LocalChannelHandle handle);
+ explicit ConsumerQueue(pdx::LocalChannelHandle handle);
// Add a consumer buffer to populate the queue. Once added, a consumer buffer
// is NOT available to use until the producer side |Post| it. |WaitForBuffers|
// will catch the |Post| and |Acquire| the buffer to make it available for
// consumer.
- pdx::Status<void> AddBuffer(const std::shared_ptr<BufferConsumer>& buffer,
+ pdx::Status<void> AddBuffer(const std::shared_ptr<ConsumerBuffer>& buffer,
size_t slot);
pdx::Status<void> OnBufferAllocated() override;
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h
index ad3f56b..36ab5f6 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h
@@ -35,7 +35,7 @@
}
// Constructs an parcelable contains the channel parcelable.
- BufferHubQueueParcelable(
+ explicit BufferHubQueueParcelable(
std::unique_ptr<pdx::ChannelParcelable> channel_parcelable)
: channel_parcelable_(std::move(channel_parcelable)) {}
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
index 159d6dc..6ae603b 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
@@ -125,7 +125,7 @@
}
TEST_F(BufferHubQueueTest,
- TestDequeuePostedBufferIfNoAvailableReleasedBuffer_withBufferConsumer) {
+ TestDequeuePostedBufferIfNoAvailableReleasedBuffer_withConsumerBuffer) {
ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));
// Allocate 3 buffers to use.
@@ -205,7 +205,7 @@
}
TEST_F(BufferHubQueueTest,
- TestDequeuePostedBufferIfNoAvailableReleasedBuffer_noBufferConsumer) {
+ TestDequeuePostedBufferIfNoAvailableReleasedBuffer_noConsumerBuffer) {
ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));
// Allocate 4 buffers to use.
@@ -332,7 +332,7 @@
EXPECT_EQ(producer_queue_->capacity(), 0);
EXPECT_EQ(consumer_queue_->capacity(), 0);
- std::shared_ptr<BufferProducer> p1 = BufferProducer::Create(
+ std::shared_ptr<ProducerBuffer> p1 = ProducerBuffer::Create(
kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage, 0);
ASSERT_TRUE(p1 != nullptr);
ASSERT_EQ(p1->GainAsync(), 0);
@@ -345,7 +345,7 @@
EXPECT_EQ(status_or_slot.error(), EINVAL);
// Inserting a gained buffer will succeed.
- std::shared_ptr<BufferProducer> p2 = BufferProducer::Create(
+ std::shared_ptr<ProducerBuffer> p2 = ProducerBuffer::Create(
kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage);
ASSERT_EQ(p2->GainAsync(), 0);
ASSERT_TRUE(p2 != nullptr);
@@ -382,7 +382,7 @@
// Dequeue all the buffers and keep track of them in an array. This prevents
// the producer queue ring buffer ref counts from interfering with the tests.
struct Entry {
- std::shared_ptr<BufferProducer> buffer;
+ std::shared_ptr<ProducerBuffer> buffer;
LocalHandle fence;
size_t slot;
};
@@ -848,10 +848,10 @@
size_t slot;
LocalHandle fence;
pdx::Status<void> status;
- pdx::Status<std::shared_ptr<BufferConsumer>> consumer_status;
- pdx::Status<std::shared_ptr<BufferProducer>> producer_status;
- std::shared_ptr<BufferConsumer> consumer_buffer;
- std::shared_ptr<BufferProducer> producer_buffer;
+ pdx::Status<std::shared_ptr<ConsumerBuffer>> consumer_status;
+ pdx::Status<std::shared_ptr<ProducerBuffer>> producer_status;
+ std::shared_ptr<ConsumerBuffer> consumer_buffer;
+ std::shared_ptr<ProducerBuffer> producer_buffer;
DvrNativeBufferMetadata mi, mo;
ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));
@@ -994,7 +994,7 @@
auto s3 = producer_queue_->Dequeue(0, &slot, &producer_meta, &fence);
EXPECT_TRUE(s3.ok());
- std::shared_ptr<BufferProducer> p1 = s3.take();
+ std::shared_ptr<ProducerBuffer> p1 = s3.take();
ASSERT_NE(p1, nullptr);
producer_meta.timestamp = 42;
@@ -1061,7 +1061,7 @@
auto s2 = producer_queue_->Dequeue(0, &slot, &producer_meta, &fence);
EXPECT_TRUE(s2.ok());
- std::shared_ptr<BufferProducer> p1 = s2.take();
+ std::shared_ptr<ProducerBuffer> p1 = s2.take();
ASSERT_NE(p1, nullptr);
producer_meta.timestamp = 42;
diff --git a/libs/vr/libdisplay/include/private/dvr/display_protocol.h b/libs/vr/libdisplay/include/private/dvr/display_protocol.h
index eff50ba..3786d1d 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_protocol.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_protocol.h
@@ -60,11 +60,13 @@
using Base = Flags<Integer>;
using Type = Integer;
+ // NOLINTNEXTLINE(google-explicit-constructor)
Flags(const Integer& value) : value_{value} {}
Flags(const Flags&) = default;
Flags& operator=(const Flags&) = default;
Integer value() const { return value_; }
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator Integer() const { return value_; }
bool IsSet(Integer bits) const { return (value_ & bits) == bits; }
diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp
index f4c6600..1ca653c 100644
--- a/libs/vr/libdvr/dvr_buffer_queue.cpp
+++ b/libs/vr/libdvr/dvr_buffer_queue.cpp
@@ -8,10 +8,10 @@
#include "dvr_buffer_queue_internal.h"
using namespace android;
-using android::dvr::BufferConsumer;
using android::dvr::BufferHubBase;
-using android::dvr::BufferProducer;
+using android::dvr::ConsumerBuffer;
using android::dvr::ConsumerQueue;
+using android::dvr::ProducerBuffer;
using android::dvr::ProducerQueue;
using android::dvr::ProducerQueueConfigBuilder;
using android::dvr::UsagePolicy;
@@ -103,13 +103,13 @@
"DvrWriteBufferQueue::GainBuffer: Buffer slot is not empty: %zu", slot);
write_buffers_[slot]->write_buffer = std::move(buffer_status.take());
- const auto& buffer_producer = write_buffers_[slot]->write_buffer;
- if (!buffer_producer)
+ const auto& producer_buffer = write_buffers_[slot]->write_buffer;
+ if (!producer_buffer)
return -ENOMEM;
- if (width_ == buffer_producer->width() &&
- height_ == buffer_producer->height() &&
- format_ == buffer_producer->format()) {
+ if (width_ == producer_buffer->width() &&
+ height_ == producer_buffer->height() &&
+ format_ == producer_buffer->format()) {
// Producer queue returns a buffer matches the current request.
break;
}
@@ -122,14 +122,14 @@
"DvrWriteBufferQueue::Dequeue: requested buffer at slot: %zu "
"(w=%u, h=%u, fmt=%u) is different from the buffer returned "
"(w=%u, h=%u, fmt=%u). Need re-allocation.",
- slot, width_, height_, format_, buffer_producer->width(),
- buffer_producer->height(), buffer_producer->format());
+ slot, width_, height_, format_, producer_buffer->width(),
+ producer_buffer->height(), producer_buffer->format());
// Currently, we are not storing |layer_count| and |usage| in queue
// configuration. Copy those setup from the last buffer dequeued before we
// remove it.
- uint32_t old_layer_count = buffer_producer->layer_count();
- uint64_t old_usage = buffer_producer->usage();
+ uint32_t old_layer_count = producer_buffer->layer_count();
+ uint64_t old_usage = producer_buffer->usage();
// Allocate a new producer buffer with new buffer configs. Note that if
// there are already multiple available buffers in the queue, the next one
@@ -443,7 +443,7 @@
// When buffer is removed from the queue, the slot is already invalid.
auto read_buffer = std::make_unique<DvrReadBuffer>();
read_buffer->read_buffer =
- std::static_pointer_cast<BufferConsumer>(buffer);
+ std::static_pointer_cast<ConsumerBuffer>(buffer);
callback(read_buffer.release(), context);
});
}
diff --git a/libs/vr/libdvr/dvr_display_manager.cpp b/libs/vr/libdvr/dvr_display_manager.cpp
index fe91b14..7f631e3 100644
--- a/libs/vr/libdvr/dvr_display_manager.cpp
+++ b/libs/vr/libdvr/dvr_display_manager.cpp
@@ -10,10 +10,10 @@
#include "dvr_internal.h"
#include "dvr_buffer_queue_internal.h"
-using android::dvr::BufferConsumer;
+using android::dvr::ConsumerBuffer;
using android::dvr::display::DisplayManagerClient;
-using android::dvr::display::SurfaceAttributes;
using android::dvr::display::SurfaceAttribute;
+using android::dvr::display::SurfaceAttributes;
using android::dvr::display::SurfaceState;
using android::pdx::rpc::EmptyVariant;
diff --git a/libs/vr/libdvr/dvr_internal.h b/libs/vr/libdvr/dvr_internal.h
index df8125a..f845cd8 100644
--- a/libs/vr/libdvr/dvr_internal.h
+++ b/libs/vr/libdvr/dvr_internal.h
@@ -16,21 +16,11 @@
namespace android {
namespace dvr {
-// TODO(b/116855254): Remove this typedef once rename is complete in libdvr.
-// Note that the dvr::BufferProducer and dvr::BufferConsumer were poorly named,
-// they should really be named as ProducerBuffer and ConsumerBuffer.
-typedef class ProducerBuffer BufferProducer;
-typedef class ConsumerBuffer BufferConsumer;
class IonBuffer;
DvrBuffer* CreateDvrBufferFromIonBuffer(
const std::shared_ptr<IonBuffer>& ion_buffer);
-DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
- const std::shared_ptr<BufferConsumer>& buffer_consumer);
-DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
- const std::shared_ptr<BufferProducer>& buffer_producer);
-
} // namespace dvr
} // namespace android
@@ -42,7 +32,7 @@
// DvrWriteBuffer acquired from a DvrWriteBufferQueue.
int32_t slot = -1;
- std::shared_ptr<android::dvr::BufferProducer> write_buffer;
+ std::shared_ptr<android::dvr::ProducerBuffer> write_buffer;
};
struct DvrReadBuffer {
@@ -51,7 +41,7 @@
// DvrReadBuffer acquired from a DvrReadBufferQueue.
int32_t slot = -1;
- std::shared_ptr<android::dvr::BufferConsumer> read_buffer;
+ std::shared_ptr<android::dvr::ConsumerBuffer> read_buffer;
};
struct DvrBuffer {
diff --git a/libs/vr/libdvr/dvr_surface.cpp b/libs/vr/libdvr/dvr_surface.cpp
index a3a47f1..0c7ec01 100644
--- a/libs/vr/libdvr/dvr_surface.cpp
+++ b/libs/vr/libdvr/dvr_surface.cpp
@@ -14,7 +14,6 @@
using android::dvr::display::Surface;
using android::dvr::display::SurfaceAttributes;
using android::dvr::display::SurfaceAttributeValue;
-using android::dvr::CreateDvrReadBufferFromBufferConsumer;
using android::pdx::rpc::EmptyVariant;
namespace {
diff --git a/libs/vr/libpdx/private/pdx/channel_handle.h b/libs/vr/libpdx/private/pdx/channel_handle.h
index daa08f4..bd04305 100644
--- a/libs/vr/libpdx/private/pdx/channel_handle.h
+++ b/libs/vr/libpdx/private/pdx/channel_handle.h
@@ -26,7 +26,7 @@
class ChannelHandleBase {
public:
ChannelHandleBase() = default;
- ChannelHandleBase(const int32_t& value) : value_{value} {}
+ explicit ChannelHandleBase(const int32_t& value) : value_{value} {}
ChannelHandleBase(const ChannelHandleBase&) = delete;
ChannelHandleBase& operator=(const ChannelHandleBase&) = delete;
diff --git a/libs/vr/libpdx/private/pdx/client.h b/libs/vr/libpdx/private/pdx/client.h
index c35dabd..7e2d55c 100644
--- a/libs/vr/libpdx/private/pdx/client.h
+++ b/libs/vr/libpdx/private/pdx/client.h
@@ -206,7 +206,7 @@
class Transaction final : public OutputResourceMapper,
public InputResourceMapper {
public:
- Transaction(Client& client);
+ explicit Transaction(Client& client);
~Transaction();
template <typename T>
diff --git a/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h
index 0421220..43184dd 100644
--- a/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h
+++ b/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h
@@ -110,10 +110,10 @@
using const_iterator = typename BufferType::const_iterator;
BufferWrapper() {}
- BufferWrapper(const BufferType& buffer) : buffer_(buffer) {}
+ explicit BufferWrapper(const BufferType& buffer) : buffer_(buffer) {}
BufferWrapper(const BufferType& buffer, const Allocator& allocator)
: buffer_(buffer, allocator) {}
- BufferWrapper(BufferType&& buffer) : buffer_(std::move(buffer)) {}
+ explicit BufferWrapper(BufferType&& buffer) : buffer_(std::move(buffer)) {}
BufferWrapper(BufferType&& buffer, const Allocator& allocator)
: buffer_(std::move(buffer), allocator) {}
BufferWrapper(const BufferWrapper&) = default;
diff --git a/libs/vr/libpdx/private/pdx/rpc/payload.h b/libs/vr/libpdx/private/pdx/rpc/payload.h
index a48a64c..d2df14f 100644
--- a/libs/vr/libpdx/private/pdx/rpc/payload.h
+++ b/libs/vr/libpdx/private/pdx/rpc/payload.h
@@ -83,7 +83,7 @@
public MessageWriter,
public MessageReader {
public:
- ServicePayload(Message& message) : message_(message) {}
+ explicit ServicePayload(Message& message) : message_(message) {}
// MessageWriter
void* GetNextWriteBufferSection(size_t size) override {
@@ -120,7 +120,8 @@
MessageBuffer<ThreadLocalTypeSlot<ClientPayload<Slot>>, 1024u, int>;
using BufferType = typename ContainerType::BufferType;
- ClientPayload(Transaction& transaction) : transaction_{transaction} {}
+ explicit ClientPayload(Transaction& transaction)
+ : transaction_{transaction} {}
// MessageWriter
void* GetNextWriteBufferSection(size_t size) override {
diff --git a/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h
index 1cb85de..88868fe 100644
--- a/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h
+++ b/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h
@@ -13,7 +13,7 @@
public:
using BaseType = T;
- PointerWrapper(T* pointer) : pointer_(pointer) {}
+ explicit PointerWrapper(T* pointer) : pointer_(pointer) {}
PointerWrapper(const PointerWrapper&) = default;
PointerWrapper(PointerWrapper&&) noexcept = default;
PointerWrapper& operator=(const PointerWrapper&) = default;
diff --git a/libs/vr/libpdx/private/pdx/rpc/serialization.h b/libs/vr/libpdx/private/pdx/rpc/serialization.h
index f12aef1..914ea66 100644
--- a/libs/vr/libpdx/private/pdx/rpc/serialization.h
+++ b/libs/vr/libpdx/private/pdx/rpc/serialization.h
@@ -134,7 +134,7 @@
// ErrorType constructor for generic error codes. Explicitly not explicit,
// implicit conversion from ErrorCode to ErrorType is desirable behavior.
- // NOLINTNEXTLINE(runtime/explicit)
+ // NOLINTNEXTLINE(google-explicit-constructor)
ErrorType(ErrorCode error_code) : error_code_(error_code) {}
// ErrorType constructor for encoding type errors.
@@ -148,6 +148,7 @@
// Evaluates to true if the ErrorType represents an error.
explicit operator bool() const { return error_code_ != ErrorCode::NO_ERROR; }
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator ErrorCode() const { return error_code_; }
ErrorCode error_code() const { return error_code_; }
@@ -159,6 +160,7 @@
return unexpected_encoding_.encoding_type;
}
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator std::string() const {
std::ostringstream stream;
diff --git a/libs/vr/libpdx/private/pdx/service.h b/libs/vr/libpdx/private/pdx/service.h
index d38b174..f5a2d5e 100644
--- a/libs/vr/libpdx/private/pdx/service.h
+++ b/libs/vr/libpdx/private/pdx/service.h
@@ -95,7 +95,7 @@
class Message : public OutputResourceMapper, public InputResourceMapper {
public:
Message();
- Message(const MessageInfo& info);
+ explicit Message(const MessageInfo& info);
~Message();
/*
diff --git a/libs/vr/libpdx/private/pdx/status.h b/libs/vr/libpdx/private/pdx/status.h
index 7e51a52..498dd6d 100644
--- a/libs/vr/libpdx/private/pdx/status.h
+++ b/libs/vr/libpdx/private/pdx/status.h
@@ -11,6 +11,7 @@
// This is a helper class for constructing Status<T> with an error code.
struct ErrorStatus {
public:
+ // NOLINTNEXTLINE(google-explicit-constructor)
ErrorStatus(int error) : error_{error} {}
int error() const { return error_; }
@@ -31,12 +32,14 @@
// Value copy/move constructors. These are intentionally not marked as
// explicit to allow direct value returns from functions without having
// to explicitly wrap them into Status<T>().
- Status(const T& value) : value_{value} {} // NOLINT(runtime/explicit)
- Status(T&& value) : value_{std::move(value)} {} // NOLINT(runtime/explicit)
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ Status(const T& value) : value_{value} {}
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ Status(T&& value) : value_{std::move(value)} {}
// Constructor for storing an error code inside the Status object.
- Status(const ErrorStatus& error_status) // NOLINT(runtime/explicit)
- : error_{error_status.error()} {}
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ Status(const ErrorStatus& error_status) : error_{error_status.error()} {}
// Copy/move constructors. Move constructor leaves |other| object in empty
// state.
@@ -135,8 +138,8 @@
class Status<void> {
public:
Status() = default;
- Status(const ErrorStatus& error_status) // NOLINT(runtime/explicit)
- : error_{error_status.error()} {}
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ Status(const ErrorStatus& error_status) : error_{error_status.error()} {}
void SetValue() { error_ = 0; }
void SetError(int error) { error_ = error; }
diff --git a/libs/vr/libpdx/serialization_tests.cpp b/libs/vr/libpdx/serialization_tests.cpp
index 5ad1047..ee800f6 100644
--- a/libs/vr/libpdx/serialization_tests.cpp
+++ b/libs/vr/libpdx/serialization_tests.cpp
@@ -70,7 +70,7 @@
FileHandleType fd;
TestTemplateType() {}
- TestTemplateType(FileHandleType fd) : fd(std::move(fd)) {}
+ explicit TestTemplateType(FileHandleType fd) : fd(std::move(fd)) {}
bool operator==(const TestTemplateType& other) const {
return fd.Get() == other.fd.Get();
diff --git a/libs/vr/libpdx/variant_tests.cpp b/libs/vr/libpdx/variant_tests.cpp
index e3520f5..a977fd3 100644
--- a/libs/vr/libpdx/variant_tests.cpp
+++ b/libs/vr/libpdx/variant_tests.cpp
@@ -14,18 +14,22 @@
namespace {
struct BaseType {
+ // NOLINTNEXTLINE(google-explicit-constructor)
BaseType(int value) : value(value) {}
int value;
};
struct DerivedType : BaseType {
+ // NOLINTNEXTLINE(google-explicit-constructor)
DerivedType(int value) : BaseType{value} {};
};
template <typename T>
class TestType {
public:
+ // NOLINTNEXTLINE(google-explicit-constructor)
TestType(const T& value) : value_(value) {}
+ // NOLINTNEXTLINE(google-explicit-constructor)
TestType(T&& value) : value_(std::move(value)) {}
TestType(const TestType&) = default;
TestType(TestType&&) = default;
@@ -43,7 +47,9 @@
template <typename T>
class InstrumentType {
public:
+ // NOLINTNEXTLINE(google-explicit-constructor)
InstrumentType(const T& value) : value_(value) { constructor_count_++; }
+ // NOLINTNEXTLINE(google-explicit-constructor)
InstrumentType(T&& value) : value_(std::move(value)) { constructor_count_++; }
InstrumentType(const InstrumentType& other) : value_(other.value_) {
constructor_count_++;
@@ -51,9 +57,11 @@
InstrumentType(InstrumentType&& other) : value_(std::move(other.value_)) {
constructor_count_++;
}
+ // NOLINTNEXTLINE(google-explicit-constructor)
InstrumentType(const TestType<T>& other) : value_(other.get()) {
constructor_count_++;
}
+ // NOLINTNEXTLINE(google-explicit-constructor)
InstrumentType(TestType<T>&& other) : value_(other.take()) {
constructor_count_++;
}
@@ -1101,6 +1109,7 @@
TEST(Variant, IsConstructible) {
using ArrayType = const float[3];
struct ImplicitBool {
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator bool() const { return true; }
};
struct ExplicitBool {
diff --git a/libs/vr/libpdx_default_transport/pdx_benchmarks.cpp b/libs/vr/libpdx_default_transport/pdx_benchmarks.cpp
index f72dabc..5c9e74c 100644
--- a/libs/vr/libpdx_default_transport/pdx_benchmarks.cpp
+++ b/libs/vr/libpdx_default_transport/pdx_benchmarks.cpp
@@ -82,7 +82,7 @@
class SchedStats {
public:
SchedStats() : SchedStats(gettid()) {}
- SchedStats(pid_t task_id) : task_id_(task_id) {}
+ explicit SchedStats(pid_t task_id) : task_id_(task_id) {}
SchedStats(const SchedStats&) = default;
SchedStats& operator=(const SchedStats&) = default;
@@ -379,7 +379,7 @@
private:
friend BASE;
- BenchmarkService(std::unique_ptr<Endpoint> endpoint)
+ explicit BenchmarkService(std::unique_ptr<Endpoint> endpoint)
: BASE("BenchmarkService", std::move(endpoint)),
send_buffer(kMaxMessageSize),
receive_buffer(kMaxMessageSize) {}
@@ -492,7 +492,7 @@
private:
friend BASE;
- BenchmarkClient(const std::string& service_path)
+ explicit BenchmarkClient(const std::string& service_path)
: BASE(ClientChannelFactory::Create(service_path),
ProgramOptions.timeout) {}
diff --git a/libs/vr/libpdx_default_transport/private/pdx/default_transport/service_utility.h b/libs/vr/libpdx_default_transport/private/pdx/default_transport/service_utility.h
index 81bb17b..3ebab86 100644
--- a/libs/vr/libpdx_default_transport/private/pdx/default_transport/service_utility.h
+++ b/libs/vr/libpdx_default_transport/private/pdx/default_transport/service_utility.h
@@ -41,7 +41,8 @@
private:
friend BASE;
- ServiceUtility(const std::string& endpoint_path, int* error = nullptr)
+ explicit ServiceUtility(const std::string& endpoint_path,
+ int* error = nullptr)
: BASE(ClientChannelFactory::Create(endpoint_path), 0) {
if (error)
*error = Client::error();
diff --git a/libs/vr/libpdx_uds/client_channel_tests.cpp b/libs/vr/libpdx_uds/client_channel_tests.cpp
index 1560030..c9c5d15 100644
--- a/libs/vr/libpdx_uds/client_channel_tests.cpp
+++ b/libs/vr/libpdx_uds/client_channel_tests.cpp
@@ -45,7 +45,7 @@
class TestService : public ServiceBase<TestService> {
public:
- TestService(std::unique_ptr<Endpoint> endpoint)
+ explicit TestService(std::unique_ptr<Endpoint> endpoint)
: ServiceBase{"TestService", std::move(endpoint)} {}
Status<void> HandleMessage(Message& message) override {
@@ -78,7 +78,7 @@
class TestServiceRunner {
public:
- TestServiceRunner(LocalHandle channel_socket) {
+ explicit TestServiceRunner(LocalHandle channel_socket) {
auto endpoint = Endpoint::CreateFromSocketFd(LocalHandle{});
endpoint->RegisterNewChannelForTests(std::move(channel_socket));
service_ = TestService::Create(std::move(endpoint));
diff --git a/libs/vr/libpdx_uds/private/uds/ipc_helper.h b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
index 63b5b10..704a569 100644
--- a/libs/vr/libpdx_uds/private/uds/ipc_helper.h
+++ b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
@@ -57,7 +57,7 @@
class SendPayload : public MessageWriter, public OutputResourceMapper {
public:
- SendPayload(SendInterface* sender = nullptr) : sender_{sender} {}
+ explicit SendPayload(SendInterface* sender = nullptr) : sender_{sender} {}
Status<void> Send(const BorrowedHandle& socket_fd);
Status<void> Send(const BorrowedHandle& socket_fd, const ucred* cred,
const iovec* data_vec = nullptr, size_t vec_count = 0);
@@ -85,7 +85,8 @@
class ReceivePayload : public MessageReader, public InputResourceMapper {
public:
- ReceivePayload(RecvInterface* receiver = nullptr) : receiver_{receiver} {}
+ explicit ReceivePayload(RecvInterface* receiver = nullptr)
+ : receiver_{receiver} {}
Status<void> Receive(const BorrowedHandle& socket_fd);
Status<void> Receive(const BorrowedHandle& socket_fd, ucred* cred);
diff --git a/libs/vr/libpdx_uds/private/uds/service_endpoint.h b/libs/vr/libpdx_uds/private/uds/service_endpoint.h
index 01ebf65..50fc484 100644
--- a/libs/vr/libpdx_uds/private/uds/service_endpoint.h
+++ b/libs/vr/libpdx_uds/private/uds/service_endpoint.h
@@ -117,7 +117,7 @@
// This class must be instantiated using Create() static methods above.
Endpoint(const std::string& endpoint_path, bool blocking,
bool use_init_socket_fd = true);
- Endpoint(LocalHandle socket_fd);
+ explicit Endpoint(LocalHandle socket_fd);
void Init(LocalHandle socket_fd);
diff --git a/libs/vr/libpdx_uds/remote_method_tests.cpp b/libs/vr/libpdx_uds/remote_method_tests.cpp
index 3f25776..4f0670e 100644
--- a/libs/vr/libpdx_uds/remote_method_tests.cpp
+++ b/libs/vr/libpdx_uds/remote_method_tests.cpp
@@ -94,7 +94,7 @@
FileHandleType fd;
TestTemplateType() {}
- TestTemplateType(FileHandleType fd) : fd(std::move(fd)) {}
+ explicit TestTemplateType(FileHandleType fd) : fd(std::move(fd)) {}
private:
PDX_SERIALIZABLE_MEMBERS(TestTemplateType<FileHandleType>, fd);
@@ -328,7 +328,7 @@
private:
friend BASE;
- TestClient(LocalChannelHandle channel_handle)
+ explicit TestClient(LocalChannelHandle channel_handle)
: BASE{android::pdx::uds::ClientChannel::Create(
std::move(channel_handle))} {}
TestClient()
diff --git a/libs/vr/libvrflinger/acquired_buffer.cpp b/libs/vr/libvrflinger/acquired_buffer.cpp
index 5d873d1..c360dee 100644
--- a/libs/vr/libvrflinger/acquired_buffer.cpp
+++ b/libs/vr/libvrflinger/acquired_buffer.cpp
@@ -8,11 +8,11 @@
namespace android {
namespace dvr {
-AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
+AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<ConsumerBuffer>& buffer,
LocalHandle acquire_fence, std::size_t slot)
: buffer_(buffer), acquire_fence_(std::move(acquire_fence)), slot_(slot) {}
-AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
+AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<ConsumerBuffer>& buffer,
int* error) {
LocalHandle fence;
const int ret = buffer->Acquire(&fence);
@@ -75,7 +75,7 @@
return std::move(acquire_fence_);
}
-std::shared_ptr<BufferConsumer> AcquiredBuffer::ClaimBuffer() {
+std::shared_ptr<ConsumerBuffer> AcquiredBuffer::ClaimBuffer() {
return std::move(buffer_);
}
diff --git a/libs/vr/libvrflinger/acquired_buffer.h b/libs/vr/libvrflinger/acquired_buffer.h
index 9e35a39..7643e75 100644
--- a/libs/vr/libvrflinger/acquired_buffer.h
+++ b/libs/vr/libvrflinger/acquired_buffer.h
@@ -9,42 +9,42 @@
namespace android {
namespace dvr {
-// Manages the ACQUIRE/RELEASE ownership cycle of a BufferConsumer.
+// Manages the ACQUIRE/RELEASE ownership cycle of a ConsumerBuffer.
class AcquiredBuffer {
public:
static constexpr int kEmptyFence = pdx::LocalHandle::kEmptyFileHandle;
AcquiredBuffer() : buffer_(nullptr), acquire_fence_(kEmptyFence) {}
- // Constructs an AcquiredBuffer from a BufferConsumer pointer and an acquire
- // fence. The BufferConsumer MUST be in the ACQUIRED state prior to calling
+ // Constructs an AcquiredBuffer from a ConsumerBuffer pointer and an acquire
+ // fence. The ConsumerBuffer MUST be in the ACQUIRED state prior to calling
// this constructor; the constructor does not attempt to ACQUIRE the buffer
// itself.
- AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
+ AcquiredBuffer(const std::shared_ptr<ConsumerBuffer>& buffer,
pdx::LocalHandle acquire_fence, std::size_t slot = 0);
- // Constructs an AcquiredBuffer from a BufferConsumer. The BufferConsumer MUST
+ // Constructs an AcquiredBuffer from a ConsumerBuffer. The ConsumerBuffer MUST
// be in the POSTED state prior to calling this constructor, as this
// constructor attempts to ACQUIRE the buffer. If ACQUIRING the buffer fails
// this instance is left in the empty state. An optional error code is
// returned in |error|, which may be nullptr if not needed.
- AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer, int* error);
+ AcquiredBuffer(const std::shared_ptr<ConsumerBuffer>& buffer, int* error);
// Move constructor. Behaves similarly to the move assignment operator below.
AcquiredBuffer(AcquiredBuffer&& other) noexcept;
~AcquiredBuffer();
- // Move assignment operator. Moves the BufferConsumer and acquire fence from
- // |other| into this instance after RELEASING the current BufferConsumer and
+ // Move assignment operator. Moves the ConsumerBuffer and acquire fence from
+ // |other| into this instance after RELEASING the current ConsumerBuffer and
// closing the acquire fence. After the move |other| is left in the empty
// state.
AcquiredBuffer& operator=(AcquiredBuffer&& other) noexcept;
- // Accessors for the underlying BufferConsumer, the acquire fence, and the
+ // Accessors for the underlying ConsumerBuffer, the acquire fence, and the
// use-case specific sequence value from the acquisition (see
// private/dvr/consumer_buffer.h).
- std::shared_ptr<BufferConsumer> buffer() const { return buffer_; }
+ std::shared_ptr<ConsumerBuffer> buffer() const { return buffer_; }
int acquire_fence() const { return acquire_fence_.Get(); }
// When non-empty, returns true if the acquired fence was signaled (or if the
@@ -58,11 +58,11 @@
// Returns the buffer, passing ownership to the caller. Caller is responsible
// for calling Release on the returned buffer.
- std::shared_ptr<BufferConsumer> ClaimBuffer();
+ std::shared_ptr<ConsumerBuffer> ClaimBuffer();
- // Releases the BufferConsumer, passing the release fence in |release_fence|
- // to the producer. On success, the BufferConsumer and acquire fence are set
- // to empty state; if release fails, the BufferConsumer and acquire fence are
+ // Releases the ConsumerBuffer, passing the release fence in |release_fence|
+ // to the producer. On success, the ConsumerBuffer and acquire fence are set
+ // to empty state; if release fails, the ConsumerBuffer and acquire fence are
// left in place and a negative error code is returned.
int Release(pdx::LocalHandle release_fence = {});
@@ -71,7 +71,7 @@
std::size_t slot() const { return slot_; }
private:
- std::shared_ptr<BufferConsumer> buffer_;
+ std::shared_ptr<ConsumerBuffer> buffer_;
// Mutable so that the fence can be closed when it is determined to be
// signaled during IsAvailable().
mutable pdx::LocalHandle acquire_fence_;
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 6d259bd..e1240d6 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -104,7 +104,7 @@
class TraceArgs {
public:
template <typename... Args>
- TraceArgs(const char* format, Args&&... args) {
+ explicit TraceArgs(const char* format, Args&&... args) {
std::array<char, 1024> buffer;
snprintf(buffer.data(), buffer.size(), format, std::forward<Args>(args)...);
atrace_begin(ATRACE_TAG, buffer.data());
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index 6c25b3e..db0d6a7 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -195,7 +195,7 @@
AcquiredBuffer acquired_buffer;
pdx::LocalHandle release_fence;
- SourceSurface(const std::shared_ptr<DirectDisplaySurface>& surface)
+ explicit SourceSurface(const std::shared_ptr<DirectDisplaySurface>& surface)
: surface(surface) {}
// Attempts to acquire a new buffer from the surface and return a tuple with
diff --git a/libs/vr/libvrflinger/hwc_types.h b/libs/vr/libvrflinger/hwc_types.h
index cbf636c..8b5c3b3 100644
--- a/libs/vr/libvrflinger/hwc_types.h
+++ b/libs/vr/libvrflinger/hwc_types.h
@@ -116,19 +116,24 @@
Wrapper(const Wrapper&) = default;
// Implicit conversion from ValueType.
+ // NOLINTNEXTLINE(google-explicit-constructor)
Wrapper(ValueType value) : value(value) {}
// Implicit conversion from BaseType.
+ // NOLINTNEXTLINE(google-explicit-constructor)
Wrapper(BaseType value) : value(static_cast<ValueType>(value)) {}
// Implicit conversion from an enum type of the same underlying type.
template <typename T, typename = EnableIfMatchingEnum<T, ValueType>>
+ // NOLINTNEXTLINE(google-explicit-constructor)
Wrapper(const T& value) : value(static_cast<ValueType>(value)) {}
// Implicit conversion to BaseType.
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator BaseType() const { return static_cast<BaseType>(value); }
// Implicit conversion to ValueType.
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator ValueType() const { return value; }
template <typename T, typename = EnableIfMatchingEnum<T, ValueType>>
@@ -275,8 +280,10 @@
struct Color final {
Color(const Color&) = default;
Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) : r(r), g(g), b(b), a(a) {}
+ // NOLINTNEXTLINE(google-explicit-constructor)
Color(hwc_color_t color) : r(color.r), g(color.g), b(color.b), a(color.a) {}
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator hwc_color_t() const { return {r, g, b, a}; }
uint8_t r __attribute__((aligned(1)));
diff --git a/libs/vr/libvrflinger/include/dvr/vr_flinger.h b/libs/vr/libvrflinger/include/dvr/vr_flinger.h
index c740dde..ae52076 100644
--- a/libs/vr/libvrflinger/include/dvr/vr_flinger.h
+++ b/libs/vr/libvrflinger/include/dvr/vr_flinger.h
@@ -49,7 +49,8 @@
// Needs to be a separate class for binder's ref counting
class PersistentVrStateCallback : public BnPersistentVrStateCallbacks {
public:
- PersistentVrStateCallback(RequestDisplayCallback request_display_callback)
+ explicit PersistentVrStateCallback(
+ RequestDisplayCallback request_display_callback)
: request_display_callback_(request_display_callback) {}
void onPersistentVrStateChanged(bool enabled) override;
private:
diff --git a/libs/vr/libvrsensor/include/private/dvr/latency_model.h b/libs/vr/libvrsensor/include/private/dvr/latency_model.h
index 40b4638..bf0e687 100644
--- a/libs/vr/libvrsensor/include/private/dvr/latency_model.h
+++ b/libs/vr/libvrsensor/include/private/dvr/latency_model.h
@@ -10,7 +10,7 @@
// window_size measurements and return their average after that.
class LatencyModel {
public:
- LatencyModel(size_t window_size);
+ explicit LatencyModel(size_t window_size);
~LatencyModel() = default;
void AddLatency(int64_t latency_ns);
diff --git a/libs/vr/libvrsensor/pose_client.cpp b/libs/vr/libvrsensor/pose_client.cpp
index c72f75e..4ff6a09 100644
--- a/libs/vr/libvrsensor/pose_client.cpp
+++ b/libs/vr/libvrsensor/pose_client.cpp
@@ -221,7 +221,7 @@
return -status.error();
}
- auto buffer = BufferConsumer::Import(status.take());
+ auto buffer = ConsumerBuffer::Import(status.take());
if (!buffer) {
ALOGE("Pose failed to import ring buffer");
return -EIO;
@@ -290,7 +290,7 @@
const DvrVsyncPoseBuffer* mapped_vsync_pose_buffer_ = nullptr;
struct ControllerClientState {
- std::unique_ptr<BufferConsumer> pose_buffer;
+ std::unique_ptr<ConsumerBuffer> pose_buffer;
const DvrPoseAsync* mapped_pose_buffer = nullptr;
};
ControllerClientState controllers_[MAX_CONTROLLERS];
diff --git a/opengl/libs/EGL/egl_angle_platform.cpp b/opengl/libs/EGL/egl_angle_platform.cpp
index 297e0c4..00caff2 100644
--- a/opengl/libs/EGL/egl_angle_platform.cpp
+++ b/opengl/libs/EGL/egl_angle_platform.cpp
@@ -106,7 +106,7 @@
.flags = ANDROID_DLEXT_USE_NAMESPACE,
.library_namespace = ns,
};
- void* so = android_dlopen_ext("libEGL_angle.so", RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+ void* so = android_dlopen_ext("libGLESv2_angle.so", RTLD_LOCAL | RTLD_NOW, &dlextinfo);
angleGetDisplayPlatform =
reinterpret_cast<GetDisplayPlatformFunc>(dlsym(so, "ANGLEGetDisplayPlatform"));
diff --git a/opengl/tests/hwc/hwcCommit.cpp b/opengl/tests/hwc/hwcCommit.cpp
index 3686dab..0a6ff55 100644
--- a/opengl/tests/hwc/hwcCommit.cpp
+++ b/opengl/tests/hwc/hwcCommit.cpp
@@ -183,7 +183,7 @@
uint32_t lower(void) { return _l; }
uint32_t upper(void) { return _u; }
- operator string();
+ operator string(); // NOLINT(google-explicit-constructor)
private:
uint32_t _l; // lower
@@ -216,7 +216,9 @@
static void double2Rational(double f, Range nRange, Range dRange,
Rational& lower, Rational& upper);
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator string() const;
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator double() const { return (double) _n / (double) _d; }
diff --git a/opengl/tests/hwc/hwcTestLib.h b/opengl/tests/hwc/hwcTestLib.h
index 922fc19..5a49393 100644
--- a/opengl/tests/hwc/hwcTestLib.h
+++ b/opengl/tests/hwc/hwcTestLib.h
@@ -58,7 +58,7 @@
float c2(void) const { return _c2; }
float c3(void) const { return _c3; }
- operator std::string();
+ operator std::string(); // NOLINT(google-explicit-constructor)
private:
float _c1;
@@ -71,7 +71,7 @@
class ColorRGB {
public:
ColorRGB(): _r(0.0), _g(0.0), _b(0.0) {};
- ColorRGB(float f): _r(f), _g(f), _b(f) {}; // Gray, NOLINT(implicit)
+ ColorRGB(float f): _r(f), _g(f), _b(f) {}; // Gray, NOLINT(google-explicit-constructor)
ColorRGB(float r, float g, float b): _r(r), _g(g), _b(b) {};
float r(void) const { return _r; }
float g(void) const { return _g; }
@@ -93,8 +93,8 @@
void setWidth(uint32_t w) { _w = w; }
void setHeight(uint32_t h) { _h = h; }
- operator std::string();
- operator hwc_rect() const;
+ operator std::string(); // NOLINT(google-explicit-constructor)
+ operator hwc_rect() const; // NOLINT(google-explicit-constructor)
private:
uint32_t _w;
diff --git a/services/bufferhub/Android.bp b/services/bufferhub/Android.bp
index 72d210c..a4b81fe 100644
--- a/services/bufferhub/Android.bp
+++ b/services/bufferhub/Android.bp
@@ -34,6 +34,7 @@
],
shared_libs: [
"android.frameworks.bufferhub@1.0",
+ "libcrypto",
"libcutils",
"libhidlbase",
"libhidltransport",
@@ -60,6 +61,7 @@
shared_libs: [
"android.frameworks.bufferhub@1.0",
"libbufferhubservice",
+ "libcrypto",
"libcutils",
"libhidltransport",
"libhwbinder",
diff --git a/services/bufferhub/BufferHubIdGenerator.cpp b/services/bufferhub/BufferHubIdGenerator.cpp
index 6444a03..2c12f0e 100644
--- a/services/bufferhub/BufferHubIdGenerator.cpp
+++ b/services/bufferhub/BufferHubIdGenerator.cpp
@@ -15,6 +15,7 @@
*/
#include <bufferhub/BufferHubIdGenerator.h>
+#include <log/log.h>
namespace android {
namespace frameworks {
@@ -22,20 +23,18 @@
namespace V1_0 {
namespace implementation {
-constexpr uint32_t BufferHubIdGenerator::kInvalidId;
-
BufferHubIdGenerator& BufferHubIdGenerator::getInstance() {
static BufferHubIdGenerator generator;
return generator;
}
-uint32_t BufferHubIdGenerator::getId() {
+int BufferHubIdGenerator::getId() {
std::lock_guard<std::mutex> lock(mIdsInUseMutex);
do {
- if (++mLastId >= std::numeric_limits<uint32_t>::max()) {
- mLastId = kInvalidId + 1;
+ if (++mLastId >= std::numeric_limits<int>::max()) {
+ mLastId = 0;
}
} while (mIdsInUse.find(mLastId) != mIdsInUse.end());
@@ -43,15 +42,14 @@
return mLastId;
}
-bool BufferHubIdGenerator::freeId(uint32_t id) {
+void BufferHubIdGenerator::freeId(int id) {
std::lock_guard<std::mutex> lock(mIdsInUseMutex);
auto iter = mIdsInUse.find(id);
if (iter != mIdsInUse.end()) {
mIdsInUse.erase(iter);
- return true;
+ } else {
+ ALOGW("%s: Cannot free nonexistent id #%d", __FUNCTION__, id);
}
-
- return false;
}
} // namespace implementation
diff --git a/services/bufferhub/BufferHubService.cpp b/services/bufferhub/BufferHubService.cpp
index 2663812..a40443d 100644
--- a/services/bufferhub/BufferHubService.cpp
+++ b/services/bufferhub/BufferHubService.cpp
@@ -14,10 +14,21 @@
* limitations under the License.
*/
+#include <array>
+#include <iomanip>
+#include <random>
+#include <sstream>
+
#include <android/hardware_buffer.h>
#include <bufferhub/BufferHubService.h>
#include <cutils/native_handle.h>
#include <log/log.h>
+#include <openssl/hmac.h>
+#include <system/graphics-base.h>
+#include <ui/BufferHubDefs.h>
+
+using ::android::BufferHubDefs::MetadataHeader;
+using ::android::hardware::Void;
namespace android {
namespace frameworks {
@@ -25,7 +36,12 @@
namespace V1_0 {
namespace implementation {
-using hardware::Void;
+BufferHubService::BufferHubService() {
+ std::mt19937_64 randomEngine;
+ randomEngine.seed(time(nullptr));
+
+ mKey = randomEngine();
+}
Return<void> BufferHubService::allocateBuffer(const HardwareBufferDescription& description,
const uint32_t userMetadataSize,
@@ -49,10 +65,12 @@
std::lock_guard<std::mutex> lock(mClientSetMutex);
mClientSet.emplace(client);
+ hidl_handle bufferInfo =
+ buildBufferInfo(node->id(), node->AddNewActiveClientsBitToMask(),
+ node->user_metadata_size(), node->metadata().ashmem_fd());
BufferTraits bufferTraits = {/*bufferDesc=*/description,
/*bufferHandle=*/hidl_handle(node->buffer_handle()),
- // TODO(b/116681016): return real data to client
- /*bufferInfo=*/hidl_handle()};
+ /*bufferInfo=*/bufferInfo};
_hidl_cb(/*status=*/BufferHubStatus::NO_ERROR, /*bufferClient=*/client,
/*bufferTraits=*/bufferTraits);
@@ -61,27 +79,49 @@
Return<void> BufferHubService::importBuffer(const hidl_handle& tokenHandle,
importBuffer_cb _hidl_cb) {
- if (!tokenHandle.getNativeHandle() || tokenHandle->numFds != 0 || tokenHandle->numInts != 1) {
+ if (!tokenHandle.getNativeHandle() || tokenHandle->numFds != 0 || tokenHandle->numInts <= 1) {
// nullptr handle or wrong format
_hidl_cb(/*status=*/BufferHubStatus::INVALID_TOKEN, /*bufferClient=*/nullptr,
/*bufferTraits=*/{});
return Void();
}
- uint32_t token = tokenHandle->data[0];
+ int tokenId = tokenHandle->data[0];
wp<BufferClient> originClientWp;
{
- std::lock_guard<std::mutex> lock(mTokenMapMutex);
- auto iter = mTokenMap.find(token);
+ std::lock_guard<std::mutex> lock(mTokenMutex);
+ auto iter = mTokenMap.find(tokenId);
if (iter == mTokenMap.end()) {
- // Invalid token
+ // Token Id not exist
+ ALOGD("%s: token #%d not found.", __FUNCTION__, tokenId);
_hidl_cb(/*status=*/BufferHubStatus::INVALID_TOKEN, /*bufferClient=*/nullptr,
/*bufferTraits=*/{});
return Void();
}
- originClientWp = iter->second;
+ const std::vector<uint8_t>& tokenHMAC = iter->second.first;
+
+ int numIntsForHMAC = (int)ceil(tokenHMAC.size() * sizeof(uint8_t) / (double)sizeof(int));
+ if (tokenHandle->numInts - 1 != numIntsForHMAC) {
+ // HMAC size not match
+ ALOGD("%s: token #%d HMAC size not match. Expected: %d Actual: %d", __FUNCTION__,
+ tokenId, numIntsForHMAC, tokenHandle->numInts - 1);
+ _hidl_cb(/*status=*/BufferHubStatus::INVALID_TOKEN, /*bufferClient=*/nullptr,
+ /*bufferTraits=*/{});
+ return Void();
+ }
+
+ size_t hmacSize = tokenHMAC.size() * sizeof(uint8_t);
+ if (memcmp(tokenHMAC.data(), &tokenHandle->data[1], hmacSize) != 0) {
+ // HMAC not match
+ ALOGD("%s: token #%d HMAC not match.", __FUNCTION__, tokenId);
+ _hidl_cb(/*status=*/BufferHubStatus::INVALID_TOKEN, /*bufferClient=*/nullptr,
+ /*bufferTraits=*/{});
+ return Void();
+ }
+
+ originClientWp = iter->second.second;
mTokenMap.erase(iter);
}
@@ -114,32 +154,181 @@
HardwareBufferDescription bufferDesc;
memcpy(&bufferDesc, &node->buffer_desc(), sizeof(HardwareBufferDescription));
+ hidl_handle bufferInfo =
+ buildBufferInfo(node->id(), clientStateMask, node->user_metadata_size(),
+ node->metadata().ashmem_fd());
BufferTraits bufferTraits = {/*bufferDesc=*/bufferDesc,
/*bufferHandle=*/hidl_handle(node->buffer_handle()),
- // TODO(b/116681016): return real data to client
- /*bufferInfo=*/hidl_handle()};
+ /*bufferInfo=*/bufferInfo};
_hidl_cb(/*status=*/BufferHubStatus::NO_ERROR, /*bufferClient=*/client,
/*bufferTraits=*/bufferTraits);
return Void();
}
-hidl_handle BufferHubService::registerToken(const wp<BufferClient>& client) {
- uint32_t token;
- std::lock_guard<std::mutex> lock(mTokenMapMutex);
- do {
- token = mTokenEngine();
- } while (mTokenMap.find(token) != mTokenMap.end());
+Return<void> BufferHubService::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) {
+ if (fd.getNativeHandle() == nullptr || fd->numFds < 1) {
+ ALOGE("%s: missing fd for writing.", __FUNCTION__);
+ return Void();
+ }
- // native_handle_t use int[], so here need one slots to fit in uint32_t
- native_handle_t* handle = native_handle_create(/*numFds=*/0, /*numInts=*/1);
- handle->data[0] = token;
+ FILE* out = fdopen(dup(fd->data[0]), "w");
+
+ if (args.size() != 0) {
+ fprintf(out,
+ "Note: lshal bufferhub currently does not support args. Input arguments are "
+ "ignored.\n");
+ }
+
+ std::ostringstream stream;
+
+ // Get the number of clients of each buffer.
+ // Map from bufferId to bufferNode_clientCount pair.
+ std::map<int, std::pair<const std::shared_ptr<BufferNode>, uint32_t>> clientCount;
+ {
+ std::lock_guard<std::mutex> lock(mClientSetMutex);
+ for (auto iter = mClientSet.begin(); iter != mClientSet.end(); ++iter) {
+ sp<BufferClient> client = iter->promote();
+ if (client != nullptr) {
+ const std::shared_ptr<BufferNode> node = client->getBufferNode();
+ auto mapIter = clientCount.find(node->id());
+ if (mapIter != clientCount.end()) {
+ ++mapIter->second.second;
+ } else {
+ clientCount.emplace(node->id(),
+ std::pair<std::shared_ptr<BufferNode>, uint32_t>(node, 1U));
+ }
+ }
+ }
+ }
+
+ stream << "Active Buffers:\n";
+ stream << std::right;
+ stream << std::setw(6) << "Id";
+ stream << " ";
+ stream << std::setw(9) << "Clients";
+ stream << " ";
+ stream << std::setw(14) << "Geometry";
+ stream << " ";
+ stream << std::setw(6) << "Format";
+ stream << " ";
+ stream << std::setw(10) << "Usage";
+ stream << " ";
+ stream << std::setw(10) << "State";
+ stream << " ";
+ stream << std::setw(8) << "Index";
+ stream << std::endl;
+
+ for (auto iter = clientCount.begin(); iter != clientCount.end(); ++iter) {
+ const std::shared_ptr<BufferNode> node = std::move(iter->second.first);
+ const uint32_t clientCount = iter->second.second;
+ AHardwareBuffer_Desc desc = node->buffer_desc();
+
+ MetadataHeader* metadataHeader =
+ const_cast<BufferHubMetadata*>(&node->metadata())->metadata_header();
+ const uint32_t state = metadataHeader->buffer_state.load(std::memory_order_acquire);
+ const uint64_t index = metadataHeader->queue_index;
+
+ stream << std::right;
+ stream << std::setw(6) << /*Id=*/node->id();
+ stream << " ";
+ stream << std::setw(9) << /*Clients=*/clientCount;
+ stream << " ";
+ if (desc.format == HAL_PIXEL_FORMAT_BLOB) {
+ std::string size = std::to_string(desc.width) + " B";
+ stream << std::setw(14) << /*Geometry=*/size;
+ } else {
+ std::string dimensions = std::to_string(desc.width) + "x" +
+ std::to_string(desc.height) + "x" + std::to_string(desc.layers);
+ stream << std::setw(14) << /*Geometry=*/dimensions;
+ }
+ stream << " ";
+ stream << std::setw(6) << /*Format=*/desc.format;
+ stream << " ";
+ stream << "0x" << std::hex << std::setfill('0');
+ stream << std::setw(8) << /*Usage=*/desc.usage;
+ stream << std::dec << std::setfill(' ');
+ stream << " ";
+ stream << "0x" << std::hex << std::setfill('0');
+ stream << std::setw(8) << /*State=*/state;
+ stream << std::dec << std::setfill(' ');
+ stream << " ";
+ stream << std::setw(8) << /*Index=*/index;
+ stream << std::endl;
+ }
+
+ stream << std::endl;
+
+ // Get the number of tokens of each buffer.
+ // Map from bufferId to tokenCount
+ std::map<int, uint32_t> tokenCount;
+ {
+ std::lock_guard<std::mutex> lock(mTokenMutex);
+ for (auto iter = mTokenMap.begin(); iter != mTokenMap.end(); ++iter) {
+ sp<BufferClient> client = iter->second.second.promote();
+ if (client != nullptr) {
+ const std::shared_ptr<BufferNode> node = client->getBufferNode();
+ auto mapIter = tokenCount.find(node->id());
+ if (mapIter != tokenCount.end()) {
+ ++mapIter->second;
+ } else {
+ tokenCount.emplace(node->id(), 1U);
+ }
+ }
+ }
+ }
+
+ stream << "Unused Tokens:\n";
+ stream << std::right;
+ stream << std::setw(8) << "Buffer Id";
+ stream << " ";
+ stream << std::setw(6) << "Tokens";
+ stream << std::endl;
+
+ for (auto iter = tokenCount.begin(); iter != tokenCount.end(); ++iter) {
+ stream << std::right;
+ stream << std::setw(8) << /*Buffer Id=*/iter->first;
+ stream << " ";
+ stream << std::setw(6) << /*Tokens=*/iter->second;
+ stream << std::endl;
+ }
+
+ fprintf(out, "%s", stream.str().c_str());
+
+ fclose(out);
+ return Void();
+}
+
+hidl_handle BufferHubService::registerToken(const wp<BufferClient>& client) {
+ // Find next available token id
+ std::lock_guard<std::mutex> lock(mTokenMutex);
+ do {
+ ++mLastTokenId;
+ } while (mTokenMap.find(mLastTokenId) != mTokenMap.end());
+
+ std::array<uint8_t, EVP_MAX_MD_SIZE> hmac;
+ uint32_t hmacSize = 0U;
+
+ HMAC(/*evp_md=*/EVP_sha256(), /*key=*/&mKey, /*key_len=*/kKeyLen,
+ /*data=*/(uint8_t*)&mLastTokenId, /*data_len=*/mTokenIdSize,
+ /*out=*/hmac.data(), /*out_len=*/&hmacSize);
+
+ int numIntsForHMAC = (int)ceil(hmacSize / (double)sizeof(int));
+ native_handle_t* handle = native_handle_create(/*numFds=*/0, /*numInts=*/1 + numIntsForHMAC);
+ handle->data[0] = mLastTokenId;
+ // Set all the the bits of last int to 0 since it might not be fully overwritten
+ handle->data[numIntsForHMAC] = 0;
+ memcpy(&handle->data[1], hmac.data(), hmacSize);
// returnToken owns the native_handle_t* thus doing lifecycle management
hidl_handle returnToken;
returnToken.setTo(handle, /*shoudOwn=*/true);
- mTokenMap.emplace(token, client);
+ std::vector<uint8_t> hmacVec;
+ hmacVec.resize(hmacSize);
+ memcpy(hmacVec.data(), hmac.data(), hmacSize);
+ mTokenMap.emplace(mLastTokenId, std::pair(hmacVec, client));
+
return returnToken;
}
@@ -153,11 +342,31 @@
}
}
+// Implementation of this function should be consistent with the definition of bufferInfo handle in
+// ui/BufferHubDefs.h.
+hidl_handle BufferHubService::buildBufferInfo(int bufferId, uint32_t clientBitMask,
+ uint32_t userMetadataSize, const int metadataFd) {
+ native_handle_t* infoHandle = native_handle_create(BufferHubDefs::kBufferInfoNumFds,
+ BufferHubDefs::kBufferInfoNumInts);
+
+ infoHandle->data[0] = dup(metadataFd);
+ infoHandle->data[1] = bufferId;
+ // Use memcpy to convert to int without missing digit.
+ // TOOD(b/121345852): use bit_cast to unpack bufferInfo when C++20 becomes available.
+ memcpy(&infoHandle->data[2], &clientBitMask, sizeof(clientBitMask));
+ memcpy(&infoHandle->data[3], &userMetadataSize, sizeof(userMetadataSize));
+
+ hidl_handle bufferInfo;
+ bufferInfo.setTo(infoHandle, /*shouldOwn=*/true);
+
+ return bufferInfo;
+}
+
void BufferHubService::removeTokenByClient(const BufferClient* client) {
- std::lock_guard<std::mutex> lock(mTokenMapMutex);
+ std::lock_guard<std::mutex> lock(mTokenMutex);
auto iter = mTokenMap.begin();
while (iter != mTokenMap.end()) {
- if (iter->second == client) {
+ if (iter->second.second == client) {
auto oldIter = iter;
++iter;
mTokenMap.erase(oldIter);
diff --git a/services/bufferhub/BufferNode.cpp b/services/bufferhub/BufferNode.cpp
index da19a6f..5106390 100644
--- a/services/bufferhub/BufferNode.cpp
+++ b/services/bufferhub/BufferNode.cpp
@@ -30,7 +30,7 @@
// 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, uint32_t id)
+ uint64_t usage, size_t user_metadata_size, int id)
: mId(id) {
uint32_t out_stride = 0;
// graphicBufferId is not used in GraphicBufferAllocator::allocate
@@ -73,12 +73,8 @@
}
// Free the id, if valid
- if (id() != BufferHubIdGenerator::kInvalidId) {
- if (BufferHubIdGenerator::getInstance().freeId(id())) {
- ALOGI("%s: id #%u is freed.", __FUNCTION__, id());
- } else {
- ALOGE("%s: Cannot free nonexistent id #%u", __FUNCTION__, id());
- }
+ if (mId >= 0) {
+ BufferHubIdGenerator::getInstance().freeId(mId);
}
}
diff --git a/services/bufferhub/include/bufferhub/BufferHubIdGenerator.h b/services/bufferhub/include/bufferhub/BufferHubIdGenerator.h
index b51fcda..ef7c077 100644
--- a/services/bufferhub/include/bufferhub/BufferHubIdGenerator.h
+++ b/services/bufferhub/include/bufferhub/BufferHubIdGenerator.h
@@ -28,30 +28,28 @@
namespace V1_0 {
namespace implementation {
-// A thread-safe incremental uint32_t id generator.
+// A thread-safe, non-negative, incremental, int id generator.
class BufferHubIdGenerator {
public:
- // 0 is considered invalid
- static constexpr uint32_t kInvalidId = 0U;
-
// Get the singleton instance of this class
static BufferHubIdGenerator& getInstance();
- // 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();
+ // Gets next available id. If next id is greater than std::numeric_limits<int32_t>::max(), it
+ // will try to get an id start from 0 again.
+ int getId();
- // Free a specific id. Return true on freed, false on not found.
- bool freeId(uint32_t id);
+ // Free a specific id.
+ void freeId(int id);
private:
BufferHubIdGenerator() = default;
~BufferHubIdGenerator() = default;
+ // Start from -1 so all valid ids will be >= 0
+ int mLastId = -1;
+
std::mutex mIdsInUseMutex;
- // Start from kInvalidID to avoid generating it.
- uint32_t mLastId = kInvalidId;
- std::set<uint32_t> mIdsInUse GUARDED_BY(mIdsInUseMutex);
+ std::set<int> mIdsInUse GUARDED_BY(mIdsInUseMutex);
};
} // namespace implementation
diff --git a/services/bufferhub/include/bufferhub/BufferHubService.h b/services/bufferhub/include/bufferhub/BufferHubService.h
index f2c8ef8..23e664e 100644
--- a/services/bufferhub/include/bufferhub/BufferHubService.h
+++ b/services/bufferhub/include/bufferhub/BufferHubService.h
@@ -17,8 +17,10 @@
#ifndef ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_HUB_SERVICE_H
#define ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_HUB_SERVICE_H
+#include <map>
#include <mutex>
-#include <random>
+#include <set>
+#include <vector>
#include <android/frameworks/bufferhub/1.0/IBufferHub.h>
#include <bufferhub/BufferClient.h>
@@ -32,16 +34,22 @@
namespace implementation {
using hardware::hidl_handle;
+using hardware::hidl_string;
+using hardware::hidl_vec;
using hardware::Return;
using hardware::graphics::common::V1_2::HardwareBufferDescription;
class BufferHubService : public IBufferHub {
public:
+ BufferHubService();
+
Return<void> allocateBuffer(const HardwareBufferDescription& description,
const uint32_t userMetadataSize,
allocateBuffer_cb _hidl_cb) override;
Return<void> importBuffer(const hidl_handle& tokenHandle, importBuffer_cb _hidl_cb) override;
+ Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) override;
+
// Non-binder functions
// Internal help function for IBufferClient::duplicate.
hidl_handle registerToken(const wp<BufferClient>& client);
@@ -49,6 +57,10 @@
void onClientClosed(const BufferClient* client);
private:
+ // Helper function to build BufferTraits.bufferInfo handle
+ hidl_handle buildBufferInfo(int bufferId, uint32_t clientBitMask, uint32_t userMetadataSize,
+ const int metadataFd);
+
// Helper function to remove all the token belongs to a specific client.
void removeTokenByClient(const BufferClient* client);
@@ -56,11 +68,19 @@
std::mutex mClientSetMutex;
std::set<wp<BufferClient>> mClientSet GUARDED_BY(mClientSetMutex);
- // TODO(b/118180214): use a more secure implementation
- std::mt19937 mTokenEngine;
- // The mapping from token to the client creates it.
- std::mutex mTokenMapMutex;
- std::map<uint32_t, const wp<BufferClient>> mTokenMap GUARDED_BY(mTokenMapMutex);
+ // Token generation related
+ // A random number used as private key for HMAC
+ uint64_t mKey;
+ static constexpr size_t kKeyLen = sizeof(uint64_t);
+
+ std::mutex mTokenMutex;
+ // The first TokenId will be 1. TokenId could be negative.
+ int mLastTokenId GUARDED_BY(mTokenMutex) = 0;
+ static constexpr size_t mTokenIdSize = sizeof(int);
+ // A map from token id to the token-buffer_client pair. Using token id as the key to reduce
+ // looking up time
+ std::map<int, std::pair<std::vector<uint8_t>, const wp<BufferClient>>> mTokenMap
+ GUARDED_BY(mTokenMutex);
};
} // namespace implementation
diff --git a/services/bufferhub/include/bufferhub/BufferNode.h b/services/bufferhub/include/bufferhub/BufferNode.h
index cf56c33..b7a195b 100644
--- a/services/bufferhub/include/bufferhub/BufferNode.h
+++ b/services/bufferhub/include/bufferhub/BufferNode.h
@@ -16,15 +16,14 @@
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,
- uint32_t id = BufferHubIdGenerator::kInvalidId);
+ uint64_t usage, size_t user_metadata_size, int id = -1);
~BufferNode();
// Returns whether the object holds a valid metadata.
bool IsValid() const { return metadata_.IsValid(); }
- uint32_t id() const { return mId; }
+ int id() const { return mId; }
size_t user_metadata_size() const { return metadata_.user_metadata_size(); }
@@ -64,10 +63,10 @@
// 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;
+ // A system-unique id generated by bufferhub from 0 to std::numeric_limits<int>::max().
+ // BufferNodes not created by bufferhub will have id < 0, meaning "not specified".
+ // TODO(b/118891412): remove default id = -1 and update comments after pdx is no longer in use
+ const int mId = -1;
// The following variables are atomic variables in metadata_ that are visible
// to Bn object and Bp objects. Please find more info in
diff --git a/services/bufferhub/tests/BufferHubIdGenerator_test.cpp b/services/bufferhub/tests/BufferHubIdGenerator_test.cpp
index fe01013..fb6de0d 100644
--- a/services/bufferhub/tests/BufferHubIdGenerator_test.cpp
+++ b/services/bufferhub/tests/BufferHubIdGenerator_test.cpp
@@ -15,25 +15,28 @@
};
TEST_F(BufferHubIdGeneratorTest, TestGenerateAndFreeID) {
- uint32_t id = mIdGenerator->getId();
- EXPECT_NE(id, BufferHubIdGenerator::kInvalidId);
+ int id = mIdGenerator->getId();
+ EXPECT_GE(id, 0);
- EXPECT_TRUE(mIdGenerator->freeId(id));
- EXPECT_FALSE(mIdGenerator->freeId(id));
+ mIdGenerator->freeId(id);
}
TEST_F(BufferHubIdGeneratorTest, 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 (size_t i = 0UL; i < kTestSize; ++i) {
+ const int kTestSize = 10;
+ int ids[kTestSize];
+ for (int i = 0; i < kTestSize; ++i) {
ids[i] = mIdGenerator->getId();
- EXPECT_NE(ids[i], BufferHubIdGenerator::kInvalidId);
+ EXPECT_GE(ids[i], 0);
if (i >= 1) {
EXPECT_GT(ids[i], ids[i - 1]);
}
}
+
+ for (int i = 0; i < kTestSize; ++i) {
+ mIdGenerator->freeId(ids[i]);
+ }
}
} // namespace
diff --git a/services/displayservice/include/displayservice/DisplayEventReceiver.h b/services/displayservice/include/displayservice/DisplayEventReceiver.h
index 5d569b6..042a054 100644
--- a/services/displayservice/include/displayservice/DisplayEventReceiver.h
+++ b/services/displayservice/include/displayservice/DisplayEventReceiver.h
@@ -45,7 +45,7 @@
using FwkReceiver = ::android::DisplayEventReceiver;
struct AttachedEvent : LooperCallback {
- AttachedEvent(const sp<IEventCallback> &callback);
+ explicit AttachedEvent(const sp<IEventCallback> &callback);
~AttachedEvent();
bool detach();
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 0d8d34f..843eb37 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -22,6 +22,7 @@
shared_libs: [
"libinputflinger_base",
+ "libinputreporter",
"libinputreader",
"libbase",
"libbinder",
@@ -125,6 +126,35 @@
],
}
+cc_library_shared {
+ name: "libinputreporter",
+
+ srcs: [
+ "InputReporter.cpp",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libutils",
+ ],
+
+ header_libs: [
+ "libinputflinger_headers",
+ ],
+
+ export_header_lib_headers: [
+ "libinputflinger_headers",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-Wno-unused-parameter",
+ ],
+}
+
subdirs = [
"host",
"tests",
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index b2d2f14..cf9d3c7 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -40,6 +40,7 @@
#include <hardware_legacy/power.h>
#include <android-base/stringprintf.h>
+#include <cutils/properties.h>
#include <openssl/sha.h>
#include <utils/Log.h>
#include <utils/Timers.h>
@@ -108,6 +109,19 @@
return strstr(name, "v4l-touch") == name;
}
+/**
+ * Returns true if V4L devices should be scanned.
+ *
+ * The system property ro.input.video_enabled can be used to control whether
+ * EventHub scans and opens V4L devices. As V4L does not support multiple
+ * clients, EventHub effectively blocks access to these devices when it opens
+ * them. This property enables other clients to read these devices for testing
+ * and development.
+ */
+static bool isV4lScanningEnabled() {
+ return property_get_bool("ro.input.video_enabled", true /* default_value */);
+}
+
static nsecs_t processEventTimestamp(const struct input_event& event) {
// Use the time specified in the event instead of the current time
// so that downstream code can get more accurate estimates of
@@ -220,7 +234,6 @@
// --- EventHub ---
-const int EventHub::EPOLL_SIZE_HINT;
const int EventHub::EPOLL_MAX_EVENTS;
EventHub::EventHub(void) :
@@ -238,9 +251,14 @@
mInputWd = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
LOG_ALWAYS_FATAL_IF(mInputWd < 0, "Could not register INotify for %s: %s",
DEVICE_PATH, strerror(errno));
- mVideoWd = inotify_add_watch(mINotifyFd, VIDEO_DEVICE_PATH, IN_DELETE | IN_CREATE);
- LOG_ALWAYS_FATAL_IF(mVideoWd < 0, "Could not register INotify for %s: %s",
- VIDEO_DEVICE_PATH, strerror(errno));
+ if (isV4lScanningEnabled()) {
+ mVideoWd = inotify_add_watch(mINotifyFd, VIDEO_DEVICE_PATH, IN_DELETE | IN_CREATE);
+ LOG_ALWAYS_FATAL_IF(mVideoWd < 0, "Could not register INotify for %s: %s",
+ VIDEO_DEVICE_PATH, strerror(errno));
+ } else {
+ mVideoWd = -1;
+ ALOGI("Video device scanning disabled");
+ }
struct epoll_event eventItem;
memset(&eventItem, 0, sizeof(eventItem));
@@ -762,13 +780,27 @@
return nullptr;
}
+/**
+ * The file descriptor could be either input device, or a video device (associated with a
+ * specific input device). Check both cases here, and return the device that this event
+ * belongs to. Caller can compare the fd's once more to determine event type.
+ * Looks through all input devices, and only attached video devices. Unattached video
+ * devices are ignored.
+ */
EventHub::Device* EventHub::getDeviceByFdLocked(int fd) const {
for (size_t i = 0; i < mDevices.size(); i++) {
Device* device = mDevices.valueAt(i);
if (device->fd == fd) {
+ // This is an input device event
+ return device;
+ }
+ if (device->videoDevice && device->videoDevice->getFd() == fd) {
+ // This is a video device event
return device;
}
}
+ // We do not check mUnattachedVideoDevices here because they should not participate in epoll,
+ // and therefore should never be looked up by fd.
return nullptr;
}
@@ -874,12 +906,33 @@
}
Device* device = getDeviceByFdLocked(eventItem.data.fd);
- if (device == nullptr) {
- ALOGW("Received unexpected epoll event 0x%08x for unknown device fd %d.",
+ if (!device) {
+ ALOGE("Received unexpected epoll event 0x%08x for unknown fd %d.",
eventItem.events, eventItem.data.fd);
+ ALOG_ASSERT(!DEBUG);
continue;
}
-
+ if (device->videoDevice && eventItem.data.fd == device->videoDevice->getFd()) {
+ if (eventItem.events & EPOLLIN) {
+ size_t numFrames = device->videoDevice->readAndQueueFrames();
+ if (numFrames == 0) {
+ ALOGE("Received epoll event for video device %s, but could not read frame",
+ device->videoDevice->getName().c_str());
+ }
+ } else if (eventItem.events & EPOLLHUP) {
+ // TODO(b/121395353) - consider adding EPOLLRDHUP
+ ALOGI("Removing video device %s due to epoll hang-up event.",
+ device->videoDevice->getName().c_str());
+ unregisterVideoDeviceFromEpollLocked(*device->videoDevice);
+ device->videoDevice = nullptr;
+ } else {
+ ALOGW("Received unexpected epoll event 0x%08x for device %s.",
+ eventItem.events, device->videoDevice->getName().c_str());
+ ALOG_ASSERT(!DEBUG);
+ }
+ continue;
+ }
+ // This must be an input event
if (eventItem.events & EPOLLIN) {
int32_t readSize = read(device->fd, readBuffer,
sizeof(struct input_event) * capacity);
@@ -994,6 +1047,16 @@
return event - buffer;
}
+std::vector<TouchVideoFrame> EventHub::getVideoFrames(int32_t deviceId) {
+ AutoMutex _l(mLock);
+
+ Device* device = getDeviceLocked(deviceId);
+ if (!device || !device->videoDevice) {
+ return {};
+ }
+ return device->videoDevice->consumeFrames();
+}
+
void EventHub::wake() {
ALOGV("wake() called");
@@ -1012,9 +1075,11 @@
if(result < 0) {
ALOGE("scan dir failed for %s", DEVICE_PATH);
}
- result = scanVideoDirLocked(VIDEO_DEVICE_PATH);
- if (result != OK) {
- ALOGE("scan video dir failed for %s", VIDEO_DEVICE_PATH);
+ if (isV4lScanningEnabled()) {
+ result = scanVideoDirLocked(VIDEO_DEVICE_PATH);
+ if (result != OK) {
+ ALOGE("scan video dir failed for %s", VIDEO_DEVICE_PATH);
+ }
}
if (mDevices.indexOfKey(VIRTUAL_KEYBOARD_ID) < 0) {
createVirtualKeyboardLocked();
@@ -1044,6 +1109,7 @@
};
status_t EventHub::registerFdForEpoll(int fd) {
+ // TODO(b/121395353) - consider adding EPOLLRDHUP
struct epoll_event eventItem = {};
eventItem.events = EPOLLIN | EPOLLWAKEUP;
eventItem.data.fd = fd;
@@ -1072,10 +1138,21 @@
status_t result = registerFdForEpoll(device->fd);
if (result != OK) {
ALOGE("Could not add input device fd to epoll for device %" PRId32, device->id);
+ return result;
+ }
+ if (device->videoDevice) {
+ registerVideoDeviceForEpollLocked(*device->videoDevice);
}
return result;
}
+void EventHub::registerVideoDeviceForEpollLocked(const TouchVideoDevice& videoDevice) {
+ status_t result = registerFdForEpoll(videoDevice.getFd());
+ if (result != OK) {
+ ALOGE("Could not add video device %s to epoll", videoDevice.getName().c_str());
+ }
+}
+
status_t EventHub::unregisterDeviceFromEpollLocked(Device* device) {
if (device->hasValidFd()) {
status_t result = unregisterFdFromEpoll(device->fd);
@@ -1084,10 +1161,23 @@
return result;
}
}
+ if (device->videoDevice) {
+ unregisterVideoDeviceFromEpollLocked(*device->videoDevice);
+ }
return OK;
}
-status_t EventHub::openDeviceLocked(const char *devicePath) {
+void EventHub::unregisterVideoDeviceFromEpollLocked(const TouchVideoDevice& videoDevice) {
+ if (videoDevice.hasValidFd()) {
+ status_t result = unregisterFdFromEpoll(videoDevice.getFd());
+ if (result != OK) {
+ ALOGW("Could not remove video device fd from epoll for device: %s",
+ videoDevice.getName().c_str());
+ }
+ }
+}
+
+status_t EventHub::openDeviceLocked(const char* devicePath) {
char buffer[80];
ALOGV("Opening device: %s", devicePath);
@@ -1345,6 +1435,7 @@
}
// Find a matching video device by comparing device names
+ // This should be done before registerDeviceForEpollLocked, so that both fds are added to epoll
for (std::unique_ptr<TouchVideoDevice>& videoDevice : mUnattachedVideoDevices) {
if (device->identifier.name == videoDevice->getName()) {
device->videoDevice = std::move(videoDevice);
@@ -1422,6 +1513,9 @@
Device* device = mDevices.valueAt(i);
if (videoDevice->getName() == device->identifier.name) {
device->videoDevice = std::move(videoDevice);
+ if (device->enabled) {
+ registerVideoDeviceForEpollLocked(*device->videoDevice);
+ }
return;
}
}
@@ -1632,6 +1726,7 @@
for (size_t i = 0; i < mDevices.size(); i++) {
Device* device = mDevices.valueAt(i);
if (device->videoDevice && device->videoDevice->getPath() == devicePath) {
+ unregisterVideoDeviceFromEpollLocked(*device->videoDevice);
device->videoDevice = nullptr;
return;
}
@@ -1662,6 +1757,7 @@
unregisterDeviceFromEpollLocked(device);
if (device->videoDevice) {
+ // This must be done after the video device is removed from epoll
mUnattachedVideoDevices.push_back(std::move(device->videoDevice));
}
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 7fa9cb6..9af189a 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -257,6 +257,7 @@
mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
mLooper = new Looper(false);
+ mReporter = createInputReporter();
mKeyRepeatState.lastKeyEntry = nullptr;
@@ -841,6 +842,7 @@
if (*dropReason != DROP_REASON_NOT_DROPPED) {
setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
+ mReporter->reportDroppedKey(entry->sequenceNum);
return true;
}
@@ -2384,7 +2386,8 @@
}
InputTarget target;
- sp<InputWindowHandle> windowHandle = getWindowHandleLocked(connection->inputChannel);
+ sp<InputWindowHandle> windowHandle = getWindowHandleLocked(
+ connection->inputChannel->getToken());
if (windowHandle != nullptr) {
const InputWindowInfo* windowInfo = windowHandle->getInfo();
target.xOffset = -windowInfo->frameLeft;
@@ -2688,7 +2691,7 @@
event.initialize(args->deviceId, args->source, args->displayId,
args->action, args->actionButton,
args->flags, args->edgeFlags, args->metaState, args->buttonState,
- 0, 0, args->xPrecision, args->yPrecision,
+ args->classification, 0, 0, args->xPrecision, args->yPrecision,
args->downTime, args->eventTime,
args->pointerCount, args->pointerProperties, args->pointerCoords);
@@ -3022,13 +3025,13 @@
}
sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(
- const sp<InputChannel>& inputChannel) const {
+ const sp<IBinder>& windowHandleToken) const {
for (auto& it : mWindowHandlesByDisplay) {
const Vector<sp<InputWindowHandle>> windowHandles = it.second;
size_t numWindows = windowHandles.size();
for (size_t i = 0; i < numWindows; i++) {
const sp<InputWindowHandle>& windowHandle = windowHandles.itemAt(i);
- if (windowHandle->getToken() == inputChannel->getToken()) {
+ if (windowHandle->getToken() == windowHandleToken) {
return windowHandle;
}
}
@@ -3128,7 +3131,9 @@
for (size_t i = 0; i < newHandles.size(); i++) {
const sp<InputWindowHandle>& windowHandle = newHandles.itemAt(i);
- if (windowHandle->getInfo()->hasFocus && windowHandle->getInfo()->visible) {
+ // Set newFocusedWindowHandle to the top most focused window instead of the last one
+ if (!newFocusedWindowHandle && windowHandle->getInfo()->hasFocus
+ && windowHandle->getInfo()->visible) {
newFocusedWindowHandle = windowHandle;
}
if (windowHandle == mLastHoverWindowHandle) {
@@ -3172,7 +3177,7 @@
}
if (mFocusedDisplayId == displayId) {
- onFocusChangedLocked(newFocusedWindowHandle);
+ onFocusChangedLocked(oldFocusedWindowHandle, newFocusedWindowHandle);
}
}
@@ -3290,7 +3295,7 @@
// Sanity check
sp<InputWindowHandle> newFocusedWindowHandle =
getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
- onFocusChangedLocked(newFocusedWindowHandle);
+ onFocusChangedLocked(oldFocusedWindowHandle, newFocusedWindowHandle);
if (newFocusedWindowHandle == nullptr) {
ALOGW("Focused display #%" PRId32 " does not have a focused window.", displayId);
@@ -3371,29 +3376,27 @@
mLooper->wake();
}
-bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel,
- const sp<InputChannel>& toChannel) {
+bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) {
+ if (fromToken == toToken) {
#if DEBUG_FOCUS
- ALOGD("transferTouchFocus: fromChannel=%s, toChannel=%s",
- fromChannel->getName().c_str(), toChannel->getName().c_str());
+ ALOGD("Trivial transfer to same window.");
#endif
+ return true;
+ }
+
{ // acquire lock
AutoMutex _l(mLock);
- sp<InputWindowHandle> fromWindowHandle = getWindowHandleLocked(fromChannel);
- sp<InputWindowHandle> toWindowHandle = getWindowHandleLocked(toChannel);
+ sp<InputWindowHandle> fromWindowHandle = getWindowHandleLocked(fromToken);
+ sp<InputWindowHandle> toWindowHandle = getWindowHandleLocked(toToken);
if (fromWindowHandle == nullptr || toWindowHandle == nullptr) {
-#if DEBUG_FOCUS
- ALOGD("Cannot transfer focus because from or to window not found.");
-#endif
+ ALOGW("Cannot transfer focus because from or to window not found.");
return false;
}
- if (fromWindowHandle == toWindowHandle) {
#if DEBUG_FOCUS
- ALOGD("Trivial transfer to same window.");
+ ALOGD("transferTouchFocus: fromWindowHandle=%s, toWindowHandle=%s",
+ fromWindowHandle->getName().c_str(), toWindowHandle->getName().c_str());
#endif
- return true;
- }
if (fromWindowHandle->getInfo()->displayId != toWindowHandle->getInfo()->displayId) {
#if DEBUG_FOCUS
ALOGD("Cannot transfer focus because windows are on different displays.");
@@ -3431,6 +3434,9 @@
return false;
}
+
+ sp<InputChannel> fromChannel = getInputChannelLocked(fromToken);
+ sp<InputChannel> toChannel = getInputChannelLocked(toToken);
ssize_t fromConnectionIndex = getConnectionIndexLocked(fromChannel);
ssize_t toConnectionIndex = getConnectionIndexLocked(toChannel);
if (fromConnectionIndex >= 0 && toConnectionIndex >= 0) {
@@ -3851,11 +3857,14 @@
commandEntry->connection = connection;
}
-void InputDispatcher::onFocusChangedLocked(const sp<InputWindowHandle>& newFocus) {
- sp<IBinder> token = newFocus != nullptr ? newFocus->getToken() : nullptr;
+void InputDispatcher::onFocusChangedLocked(const sp<InputWindowHandle>& oldFocus,
+ const sp<InputWindowHandle>& newFocus) {
+ sp<IBinder> oldToken = oldFocus != nullptr ? oldFocus->getToken() : nullptr;
+ sp<IBinder> newToken = newFocus != nullptr ? newFocus->getToken() : nullptr;
CommandEntry* commandEntry = postCommandLocked(
& InputDispatcher::doNotifyFocusChangedLockedInterruptible);
- commandEntry->token = token;
+ commandEntry->oldToken = oldToken;
+ commandEntry->newToken = newToken;
}
void InputDispatcher::onANRLocked(
@@ -3917,9 +3926,10 @@
void InputDispatcher::doNotifyFocusChangedLockedInterruptible(
CommandEntry* commandEntry) {
- sp<IBinder> token = commandEntry->token;
+ sp<IBinder> oldToken = commandEntry->oldToken;
+ sp<IBinder> newToken = commandEntry->newToken;
mLock.unlock();
- mPolicy->notifyFocusChanged(token);
+ mPolicy->notifyFocusChanged(oldToken, newToken);
mLock.lock();
}
@@ -4025,6 +4035,10 @@
bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& connection,
DispatchEntry* dispatchEntry, KeyEntry* keyEntry, bool handled) {
if (keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK) {
+ if (!handled) {
+ // Report the key as unhandled, since the fallback was not handled.
+ mReporter->reportUnhandledKey(keyEntry->sequenceNum);
+ }
return false;
}
@@ -4192,6 +4206,9 @@
#if DEBUG_OUTBOUND_EVENT_DETAILS
ALOGD("Unhandled key event: No fallback key.");
#endif
+
+ // Report the key as unhandled, since there is no fallback key.
+ mReporter->reportUnhandledKey(keyEntry->sequenceNum);
}
}
return false;
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index 05b5dad..49de6f3 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -37,6 +37,7 @@
#include <unordered_map>
#include "InputListener.h"
+#include "InputReporterInterface.h"
namespace android {
@@ -216,7 +217,7 @@
/* Notifies the system that an input channel is unrecoverably broken. */
virtual void notifyInputChannelBroken(const sp<IBinder>& token) = 0;
- virtual void notifyFocusChanged(const sp<IBinder>& token) = 0;
+ virtual void notifyFocusChanged(const sp<IBinder>& oldToken, const sp<IBinder>& newToken) = 0;
/* Gets the input dispatcher configuration. */
virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) = 0;
@@ -342,13 +343,11 @@
*/
virtual void setInputFilterEnabled(bool enabled) = 0;
- /* Transfers touch focus from the window associated with one channel to the
- * window associated with the other channel.
+ /* Transfers touch focus from one window to another window.
*
* Returns true on success. False if the window did not actually have touch focus.
*/
- virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
- const sp<InputChannel>& toChannel) = 0;
+ virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) = 0;
/* Registers input channels that may be used as targets for input events.
* If inputWindowHandle is null, and displayId is not ADISPLAY_ID_NONE,
@@ -413,8 +412,7 @@
virtual void setInputDispatchMode(bool enabled, bool frozen);
virtual void setInputFilterEnabled(bool enabled);
- virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
- const sp<InputChannel>& toChannel);
+ virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken);
virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
int32_t displayId);
@@ -630,7 +628,8 @@
uint32_t seq;
bool handled;
sp<InputChannel> inputChannel;
- sp<IBinder> token;
+ sp<IBinder> oldToken;
+ sp<IBinder> newToken;
};
// Generic queue implementation.
@@ -994,7 +993,7 @@
std::unordered_map<int32_t, Vector<sp<InputWindowHandle>>> mWindowHandlesByDisplay;
// Get window handles by display, return an empty vector if not found.
Vector<sp<InputWindowHandle>> getWindowHandlesLocked(int32_t displayId) const;
- sp<InputWindowHandle> getWindowHandleLocked(const sp<InputChannel>& inputChannel) const;
+ sp<InputWindowHandle> getWindowHandleLocked(const sp<IBinder>& windowHandleToken) const;
sp<InputChannel> getInputChannelLocked(const sp<IBinder>& windowToken) const;
bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const;
@@ -1160,7 +1159,8 @@
nsecs_t currentTime, const sp<Connection>& connection, uint32_t seq, bool handled);
void onDispatchCycleBrokenLocked(
nsecs_t currentTime, const sp<Connection>& connection);
- void onFocusChangedLocked(const sp<InputWindowHandle>& newFocus);
+ void onFocusChangedLocked(const sp<InputWindowHandle>& oldFocus,
+ const sp<InputWindowHandle>& newFocus);
void onANRLocked(
nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
const sp<InputWindowHandle>& windowHandle,
@@ -1186,6 +1186,8 @@
void traceInboundQueueLengthLocked();
void traceOutboundQueueLengthLocked(const sp<Connection>& connection);
void traceWaitQueueLengthLocked(const sp<Connection>& connection);
+
+ sp<InputReporterInterface> mReporter;
};
/* Enqueues and dispatches input events, endlessly. */
diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp
index b4eb370..b349c73 100644
--- a/services/inputflinger/InputListener.cpp
+++ b/services/inputflinger/InputListener.cpp
@@ -71,8 +71,8 @@
NotifyMotionArgs::NotifyMotionArgs(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId,
uint32_t source, int32_t displayId, uint32_t policyFlags,
int32_t action, int32_t actionButton, int32_t flags, int32_t metaState,
- int32_t buttonState, int32_t edgeFlags, uint32_t deviceTimestamp,
- uint32_t pointerCount,
+ int32_t buttonState, MotionClassification classification,
+ int32_t edgeFlags, uint32_t deviceTimestamp, uint32_t pointerCount,
const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime,
const std::vector<TouchVideoFrame>& videoFrames) :
@@ -80,7 +80,7 @@
displayId(displayId), policyFlags(policyFlags),
action(action), actionButton(actionButton),
flags(flags), metaState(metaState), buttonState(buttonState),
- edgeFlags(edgeFlags), deviceTimestamp(deviceTimestamp),
+ classification(classification), edgeFlags(edgeFlags), deviceTimestamp(deviceTimestamp),
pointerCount(pointerCount),
xPrecision(xPrecision), yPrecision(yPrecision), downTime(downTime),
videoFrames(videoFrames) {
@@ -95,7 +95,7 @@
source(other.source), displayId(other.displayId), policyFlags(other.policyFlags),
action(other.action), actionButton(other.actionButton), flags(other.flags),
metaState(other.metaState), buttonState(other.buttonState),
- edgeFlags(other.edgeFlags),
+ classification(other.classification), edgeFlags(other.edgeFlags),
deviceTimestamp(other.deviceTimestamp), pointerCount(other.pointerCount),
xPrecision(other.xPrecision), yPrecision(other.yPrecision), downTime(other.downTime),
videoFrames(other.videoFrames) {
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index 15d8070..1d7ea00 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -111,6 +111,10 @@
}
}
+void InputManager::transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) {
+ mDispatcher->transferTouchFocus(fromToken, toToken);
+}
+
// Used by tests only.
void InputManager::registerInputChannel(const sp<InputChannel>& channel) {
IPCThreadState* ipc = IPCThreadState::self();
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index 8f7551e..ab309b1 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -91,6 +91,7 @@
virtual sp<InputDispatcherInterface> getDispatcher();
virtual void setInputWindows(const Vector<InputWindowInfo>& handles);
+ virtual void transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken);
virtual void registerInputChannel(const sp<InputChannel>& channel);
virtual void unregisterInputChannel(const sp<InputChannel>& channel);
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 73fcb11..2b31f6e 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -2641,6 +2641,11 @@
mOrientation = internalViewport->orientation;
}
}
+
+ // Update the PointerController if viewports changed.
+ if (mParameters.hasAssociatedDisplay) {
+ getPolicy()->obtainPointerController(getDeviceId());
+ }
bumpGeneration();
}
}
@@ -2786,7 +2791,7 @@
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
- displayId = ADISPLAY_ID_DEFAULT;
+ displayId = mPointerController->getDisplayId();
} else {
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
@@ -2829,7 +2834,8 @@
NotifyMotionArgs releaseArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
mSource, displayId, policyFlags,
AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
- metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ metaState, buttonState,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
/* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
getListener()->notifyMotion(&releaseArgs);
@@ -2838,7 +2844,7 @@
NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
displayId, policyFlags, motionEventAction, 0, 0, metaState, currentButtonState,
- AMOTION_EVENT_EDGE_FLAG_NONE,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
/* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
getListener()->notifyMotion(&args);
@@ -2850,7 +2856,8 @@
buttonState |= actionButton;
NotifyMotionArgs pressArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_BUTTON_PRESS,
- actionButton, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ actionButton, 0, metaState, buttonState,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
/* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
getListener()->notifyMotion(&pressArgs);
@@ -2864,7 +2871,8 @@
&& (mSource == AINPUT_SOURCE_MOUSE)) {
NotifyMotionArgs hoverArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
- metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ metaState, currentButtonState,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
/* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
getListener()->notifyMotion(&hoverArgs);
@@ -2878,7 +2886,7 @@
NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
mSource, displayId, policyFlags,
AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, currentButtonState,
- AMOTION_EVENT_EDGE_FLAG_NONE,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
/* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
getListener()->notifyMotion(&scrollArgs);
@@ -3009,8 +3017,8 @@
NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
mSource, displayId, policyFlags,
- AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, 0,
- AMOTION_EVENT_EDGE_FLAG_NONE,
+ AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, /* buttonState */ 0,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
/* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
0, 0, 0, /* videoFrames */ {});
getListener()->notifyMotion(&scrollArgs);
@@ -3612,10 +3620,10 @@
mOrientedRanges.clear();
}
- // Create pointer controller if needed.
+ // Create or update pointer controller if needed.
if (mDeviceMode == DEVICE_MODE_POINTER ||
(mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
- if (mPointerController == nullptr) {
+ if (mPointerController == nullptr || viewportChanged) {
mPointerController = getPolicy()->obtainPointerController(getDeviceId());
}
} else {
@@ -5404,10 +5412,11 @@
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+ const int32_t displayId = mPointerController->getDisplayId();
NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
- mSource, mViewport.displayId, policyFlags,
+ mSource, displayId, policyFlags,
AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
- metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ metaState, buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
/* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
0, 0, mPointerGesture.downTime, /* videoFrames */ {});
getListener()->notifyMotion(&args);
@@ -6312,6 +6321,7 @@
void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags,
bool down, bool hovering) {
int32_t metaState = getContext()->getGlobalMetaState();
+ int32_t displayId = mViewport.displayId;
if (mPointerController != nullptr) {
if (down || hovering) {
@@ -6322,6 +6332,7 @@
} else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
}
+ displayId = mPointerController->getDisplayId();
}
if (mPointerSimple.down && !down) {
@@ -6329,9 +6340,9 @@
// Send up.
NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
- mSource, mViewport.displayId, policyFlags,
- AMOTION_EVENT_ACTION_UP, 0, 0, metaState, mLastRawState.buttonState, 0,
- /* deviceTimestamp */ 0,
+ mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_UP, 0, 0, metaState, mLastRawState.buttonState,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
mOrientedXPrecision, mOrientedYPrecision,
mPointerSimple.downTime, /* videoFrames */ {});
@@ -6342,10 +6353,10 @@
mPointerSimple.hovering = false;
// Send hover exit.
- NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
- mSource, mViewport.displayId, policyFlags,
- AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, mLastRawState.buttonState, 0,
- /* deviceTimestamp */ 0,
+ NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+ mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, mLastRawState.buttonState,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
mOrientedXPrecision, mOrientedYPrecision,
mPointerSimple.downTime, /* videoFrames */ {});
@@ -6358,9 +6369,10 @@
mPointerSimple.downTime = when;
// Send down.
- NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
- mSource, mViewport.displayId, policyFlags,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, metaState, mCurrentRawState.buttonState, 0,
+ NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+ mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, metaState, mCurrentRawState.buttonState,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
/* deviceTimestamp */ 0,
1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
mOrientedXPrecision, mOrientedYPrecision,
@@ -6369,10 +6381,10 @@
}
// Send move.
- NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
- mSource, mViewport.displayId, policyFlags,
- AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, mCurrentRawState.buttonState, 0,
- /* deviceTimestamp */ 0,
+ NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+ mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, mCurrentRawState.buttonState,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
mOrientedXPrecision, mOrientedYPrecision,
mPointerSimple.downTime, /* videoFrames */ {});
@@ -6384,11 +6396,11 @@
mPointerSimple.hovering = true;
// Send hover enter.
- NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
- mSource, mViewport.displayId, policyFlags,
+ NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+ mSource, displayId, policyFlags,
AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0, metaState,
- mCurrentRawState.buttonState, 0,
- /* deviceTimestamp */ 0,
+ mCurrentRawState.buttonState, MotionClassification::NONE,
+ AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
mOrientedXPrecision, mOrientedYPrecision,
mPointerSimple.downTime, /* videoFrames */ {});
@@ -6396,11 +6408,11 @@
}
// Send hover move.
- NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
- mSource, mViewport.displayId, policyFlags,
+ NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+ mSource, displayId, policyFlags,
AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
- mCurrentRawState.buttonState, 0,
- /* deviceTimestamp */ 0,
+ mCurrentRawState.buttonState, MotionClassification::NONE,
+ AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
mOrientedXPrecision, mOrientedYPrecision,
mPointerSimple.downTime, /* videoFrames */ {});
@@ -6419,10 +6431,10 @@
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
- NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
- mSource, mViewport.displayId, policyFlags,
- AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, mCurrentRawState.buttonState, 0,
- /* deviceTimestamp */ 0,
+ NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+ mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, mCurrentRawState.buttonState,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
1, &mPointerSimple.currentProperties, &pointerCoords,
mOrientedXPrecision, mOrientedYPrecision,
mPointerSimple.downTime, /* videoFrames */ {});
@@ -6482,12 +6494,16 @@
ALOG_ASSERT(false);
}
}
+ const int32_t displayId = mPointerController != nullptr ?
+ mPointerController->getDisplayId() : mViewport.displayId;
- NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
- source, mViewport.displayId, policyFlags,
- action, actionButton, flags, metaState, buttonState, edgeFlags,
- deviceTimestamp, pointerCount, pointerProperties, pointerCoords,
- xPrecision, yPrecision, downTime, /* videoFrames */ {});
+ const int32_t deviceId = getDeviceId();
+ std::vector<TouchVideoFrame> frames = mDevice->getEventHub()->getVideoFrames(deviceId);
+ NotifyMotionArgs args(mContext->getNextSequenceNum(), when, deviceId,
+ source, displayId, policyFlags,
+ action, actionButton, flags, metaState, buttonState, MotionClassification::NONE,
+ edgeFlags, deviceTimestamp, pointerCount, pointerProperties, pointerCoords,
+ xPrecision, yPrecision, downTime, std::move(frames));
getListener()->notifyMotion(&args);
}
@@ -7410,9 +7426,9 @@
NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
AINPUT_SOURCE_JOYSTICK, ADISPLAY_ID_NONE, policyFlags,
- AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
- 0, 0, 0, /* videoFrames */ {});
+ AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, MotionClassification::NONE,
+ AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0, 1,
+ &pointerProperties, &pointerCoords, 0, 0, 0, /* videoFrames */ {});
getListener()->notifyMotion(&args);
}
diff --git a/services/inputflinger/InputReporter.cpp b/services/inputflinger/InputReporter.cpp
new file mode 100644
index 0000000..8d3153c
--- /dev/null
+++ b/services/inputflinger/InputReporter.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "InputReporterInterface.h"
+
+namespace android {
+
+// --- InputReporter ---
+
+class InputReporter : public InputReporterInterface {
+public:
+ void reportUnhandledKey(uint32_t sequenceNum) override;
+ void reportDroppedKey(uint32_t sequenceNum) override;
+};
+
+void InputReporter::reportUnhandledKey(uint32_t sequenceNum) {
+ // do nothing
+}
+
+void InputReporter::reportDroppedKey(uint32_t sequenceNum) {
+ // do nothing
+}
+
+sp<InputReporterInterface> createInputReporter() {
+ return new InputReporter();
+}
+
+} // namespace android
diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h
index 82ff089..9d0be95 100644
--- a/services/inputflinger/host/InputFlinger.h
+++ b/services/inputflinger/host/InputFlinger.h
@@ -40,6 +40,7 @@
virtual status_t dump(int fd, const Vector<String16>& args);
void setInputWindows(const Vector<InputWindowInfo>&) {}
+ void transferTouchFocus(const sp<IBinder>&, const sp<IBinder>&) {}
void registerInputChannel(const sp<InputChannel>&) {}
void unregisterInputChannel(const sp<InputChannel>&) {}
diff --git a/services/inputflinger/include/EventHub.h b/services/inputflinger/include/EventHub.h
index ae70169..295aca8 100644
--- a/services/inputflinger/include/EventHub.h
+++ b/services/inputflinger/include/EventHub.h
@@ -211,6 +211,7 @@
* Returns the number of events obtained, or 0 if the timeout expired.
*/
virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) = 0;
+ virtual std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) = 0;
/*
* Query current input state.
@@ -303,6 +304,7 @@
const int32_t* keyCodes, uint8_t* outFlags) const;
virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize);
+ virtual std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId);
virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const;
virtual bool hasLed(int32_t deviceId, int32_t led) const;
@@ -381,7 +383,7 @@
}
};
- status_t openDeviceLocked(const char *devicePath);
+ status_t openDeviceLocked(const char* devicePath);
void openVideoDeviceLocked(const std::string& devicePath);
void createVirtualKeyboardLocked();
void addDeviceLocked(Device* device);
@@ -400,7 +402,9 @@
status_t registerFdForEpoll(int fd);
status_t unregisterFdFromEpoll(int fd);
status_t registerDeviceForEpollLocked(Device* device);
+ void registerVideoDeviceForEpollLocked(const TouchVideoDevice& videoDevice);
status_t unregisterDeviceFromEpollLocked(Device* device);
+ void unregisterVideoDeviceFromEpollLocked(const TouchVideoDevice& videoDevice);
status_t scanDirLocked(const char *dirname);
status_t scanVideoDirLocked(const std::string& dirname);
@@ -410,6 +414,10 @@
Device* getDeviceByDescriptorLocked(const std::string& descriptor) const;
Device* getDeviceLocked(int32_t deviceId) const;
Device* getDeviceByPathLocked(const char* devicePath) const;
+ /**
+ * Look through all available fd's (both for input devices and for video devices),
+ * and return the device pointer.
+ */
Device* getDeviceByFdLocked(int fd) const;
bool hasKeycodeLocked(Device* device, int keycode) const;
@@ -470,9 +478,6 @@
int mInputWd;
int mVideoWd;
- // Epoll FD list size hint.
- static const int EPOLL_SIZE_HINT = 8;
-
// Maximum number of signalled FDs to handle at a time.
static const int EPOLL_MAX_EVENTS = 16;
diff --git a/services/inputflinger/include/InputListener.h b/services/inputflinger/include/InputListener.h
index 2442cc0..53247a0 100644
--- a/services/inputflinger/include/InputListener.h
+++ b/services/inputflinger/include/InputListener.h
@@ -99,6 +99,10 @@
int32_t flags;
int32_t metaState;
int32_t buttonState;
+ /**
+ * Classification of the current touch gesture
+ */
+ MotionClassification classification;
int32_t edgeFlags;
/**
* A timestamp in the input device's time base, not the platform's.
@@ -120,7 +124,7 @@
NotifyMotionArgs(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
int32_t displayId, uint32_t policyFlags,
int32_t action, int32_t actionButton, int32_t flags,
- int32_t metaState, int32_t buttonState,
+ int32_t metaState, int32_t buttonState, MotionClassification classification,
int32_t edgeFlags, uint32_t deviceTimestamp, uint32_t pointerCount,
const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime,
diff --git a/services/inputflinger/include/InputReporterInterface.h b/services/inputflinger/include/InputReporterInterface.h
new file mode 100644
index 0000000..906d7f2
--- /dev/null
+++ b/services/inputflinger/include/InputReporterInterface.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _UI_INPUT_REPORTER_INTERFACE_H
+#define _UI_INPUT_REPORTER_INTERFACE_H
+
+#include <utils/RefBase.h>
+
+namespace android {
+
+/*
+ * The interface used by the InputDispatcher to report information about input events after
+ * it is sent to the application, such as if a key is unhandled or dropped.
+ */
+class InputReporterInterface : public virtual RefBase {
+protected:
+ virtual ~InputReporterInterface() { }
+
+public:
+ // Report a key that was not handled by the system or apps.
+ // A key event is unhandled if:
+ // - The event was not handled and there is no fallback key; or
+ // - The event was not handled and it has a fallback key,
+ // but the fallback key was not handled.
+ virtual void reportUnhandledKey(uint32_t sequenceNum) = 0;
+
+ // Report a key that was dropped by InputDispatcher.
+ // A key can be dropped for several reasons. See the enum
+ // InputDispatcher::DropReason for details.
+ virtual void reportDroppedKey(uint32_t sequenceNum) = 0;
+};
+
+/*
+ * Factory method for InputReporter.
+ */
+sp<InputReporterInterface> createInputReporter();
+
+} // namespace android
+
+#endif // _UI_INPUT_REPORTER_INTERFACE_H
diff --git a/services/inputflinger/include/PointerControllerInterface.h b/services/inputflinger/include/PointerControllerInterface.h
index e94dd94..bc0f1f9 100644
--- a/services/inputflinger/include/PointerControllerInterface.h
+++ b/services/inputflinger/include/PointerControllerInterface.h
@@ -98,6 +98,9 @@
/* Removes all spots. */
virtual void clearSpots() = 0;
+
+ /* Gets the id of the display where the pointer should be shown. */
+ virtual int32_t getDisplayId() const = 0;
};
} // namespace android
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 26f01b7..3edec40 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -63,7 +63,7 @@
virtual void notifyInputChannelBroken(const sp<IBinder>&) {
}
- virtual void notifyFocusChanged(const sp<IBinder>&) {
+ virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) {
}
virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
@@ -160,70 +160,70 @@
pointerCoords[i].clear();
}
+ // Some constants commonly used below
+ constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
+ constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
+ constexpr int32_t metaState = AMETA_NONE;
+ constexpr MotionClassification classification = MotionClassification::NONE;
+
// Rejects undefined motion actions.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
- /*action*/ -1, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerProperties, pointerCoords);
+ event.initialize(DEVICE_ID, source, DISPLAY_ID,
+ /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+ ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with undefined action.";
// Rejects pointer down with invalid index.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
+ event.initialize(DEVICE_ID, source, DISPLAY_ID,
AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerProperties, pointerCoords);
+ 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+ ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer down index too large.";
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
+ event.initialize(DEVICE_ID, source, DISPLAY_ID,
AMOTION_EVENT_ACTION_POINTER_DOWN | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerProperties, pointerCoords);
+ 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+ ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer down index too small.";
// Rejects pointer up with invalid index.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
+ event.initialize(DEVICE_ID, source, DISPLAY_ID,
AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerProperties, pointerCoords);
+ 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+ ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer up index too large.";
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
+ event.initialize(DEVICE_ID, source, DISPLAY_ID,
AMOTION_EVENT_ACTION_POINTER_UP | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerProperties, pointerCoords);
+ 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+ ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer up index too small.";
// Rejects motion events with invalid number of pointers.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 0, pointerProperties, pointerCoords);
+ event.initialize(DEVICE_ID, source, DISPLAY_ID,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+ ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 0, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with 0 pointers.";
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
+ event.initialize(DEVICE_ID, source, DISPLAY_ID,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
@@ -233,20 +233,18 @@
// Rejects motion events with invalid pointer ids.
pointerProperties[0].id = -1;
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerProperties, pointerCoords);
+ event.initialize(DEVICE_ID, source, DISPLAY_ID,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+ ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer ids less than 0.";
pointerProperties[0].id = MAX_POINTER_ID + 1;
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerProperties, pointerCoords);
+ event.initialize(DEVICE_ID, source, DISPLAY_ID,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+ ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
@@ -255,10 +253,9 @@
// Rejects motion events with duplicate pointer ids.
pointerProperties[0].id = 1;
pointerProperties[1].id = 1;
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 2, pointerProperties, pointerCoords);
+ event.initialize(DEVICE_ID, source, DISPLAY_ID,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+ ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 2, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
@@ -460,7 +457,8 @@
// Define a valid motion down event.
event.initialize(DEVICE_ID, source, displayId,
AMOTION_EVENT_ACTION_DOWN, /* actionButton */0, /* flags */ 0, /* edgeFlags */ 0,
- AMETA_NONE, /* buttonState */ 0, /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
+ AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
+ /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
/* yPrecision */ 0, currentTime, currentTime, /*pointerCount*/ 1, pointerProperties,
pointerCoords);
@@ -517,7 +515,7 @@
sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
ADISPLAY_ID_DEFAULT);
- // Set focus application.
+ // Set focused application.
mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
// Expect one focus window exist in display.
@@ -535,6 +533,32 @@
windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
}
+TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) {
+ sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
+ ADISPLAY_ID_DEFAULT);
+ sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
+ ADISPLAY_ID_DEFAULT);
+
+ // Set focused application.
+ mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+
+ // Display has two focused windows. Add them to inputWindowsHandles in z-order (top most first)
+ windowTop->setFocus();
+ windowSecond->setFocus();
+ Vector<sp<InputWindowHandle>> inputWindowHandles;
+ inputWindowHandles.add(windowTop);
+ inputWindowHandles.add(windowSecond);
+
+ mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
+ << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+
+ // Top focused window should receive event.
+ windowTop->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
+ windowSecond->assertNoEvents();
+}
+
TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
sp<FakeApplicationHandle> application = new FakeApplicationHandle();
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index b5d2090..de87e7f 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -57,6 +57,7 @@
float mMinX, mMinY, mMaxX, mMaxY;
float mX, mY;
int32_t mButtonState;
+ int32_t mDisplayId;
protected:
virtual ~FakePointerController() { }
@@ -64,7 +65,7 @@
public:
FakePointerController() :
mHaveBounds(false), mMinX(0), mMinY(0), mMaxX(0), mMaxY(0), mX(0), mY(0),
- mButtonState(0) {
+ mButtonState(0), mDisplayId(ADISPLAY_ID_DEFAULT) {
}
void setBounds(float minX, float minY, float maxX, float maxY) {
@@ -75,6 +76,10 @@
mMaxY = maxY;
}
+ void setDisplayId(int32_t displayId) {
+ mDisplayId = displayId;
+ }
+
virtual void setPosition(float x, float y) {
mX = x;
mY = y;
@@ -93,6 +98,10 @@
*outY = mY;
}
+ virtual int32_t getDisplayId() const {
+ return mDisplayId;
+ }
+
private:
virtual bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const {
*outMinX = mMinX;
@@ -692,6 +701,10 @@
return 1;
}
+ virtual std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) {
+ return {};
+ }
+
virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const {
Device* device = getDevice(deviceId);
if (device) {
@@ -3165,6 +3178,30 @@
ASSERT_NO_FATAL_FAILURE(assertPosition(mFakePointerController, 110.0f, 220.0f));
}
+TEST_F(CursorInputMapperTest, Process_ShouldHandleDisplayId) {
+ CursorInputMapper* mapper = new CursorInputMapper(mDevice);
+ addMapperAndConfigure(mapper);
+
+ // Setup PointerController for second display.
+ constexpr int32_t SECOND_DISPLAY_ID = 1;
+ mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
+ mFakePointerController->setPosition(100, 200);
+ mFakePointerController->setButtonState(0);
+ mFakePointerController->setDisplayId(SECOND_DISPLAY_ID);
+
+ NotifyMotionArgs args;
+ process(mapper, ARBITRARY_TIME, EV_REL, REL_X, 10);
+ process(mapper, ARBITRARY_TIME, EV_REL, REL_Y, 20);
+ process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AINPUT_SOURCE_MOUSE, args.source);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+ 110.0f, 220.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+ ASSERT_NO_FATAL_FAILURE(assertPosition(mFakePointerController, 110.0f, 220.0f));
+ ASSERT_EQ(SECOND_DISPLAY_ID, args.displayId);
+}
+
// --- TouchInputMapperTest ---
@@ -6314,4 +6351,30 @@
ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
}
+TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShouldHandleDisplayId) {
+ // Setup PointerController for second display.
+ sp<FakePointerController> fakePointerController = new FakePointerController();
+ fakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
+ fakePointerController->setPosition(100, 200);
+ fakePointerController->setButtonState(0);
+ fakePointerController->setDisplayId(SECONDARY_DISPLAY_ID);
+ mFakePolicy->setPointerController(mDevice->getId(), fakePointerController);
+
+ MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
+ prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareAxes(POSITION);
+ addMapperAndConfigure(mapper);
+
+ // Check source is mouse that would obtain the PointerController.
+ ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper->getSources());
+
+ NotifyMotionArgs motionArgs;
+ processPosition(mapper, 100, 100);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
+ ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
+}
+
} // namespace android
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 9b2cd50..189ae36 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -35,6 +35,7 @@
using namespace android::hardware::sensors::V1_0::implementation;
using android::hardware::sensors::V2_0::ISensorsCallback;
using android::hardware::sensors::V2_0::EventQueueFlagBits;
+using android::hardware::sensors::V2_0::WakeLockQueueFlagBits;
using android::hardware::hidl_vec;
using android::hardware::Return;
using android::SensorDeviceUtils::HidlServiceRegistrationWaiter;
@@ -94,6 +95,8 @@
SensorDevice::SensorDevice()
: mHidlTransportErrors(20),
mRestartWaiter(new HidlServiceRegistrationWaiter()),
+ mEventQueueFlag(nullptr),
+ mWakeLockQueueFlag(nullptr),
mReconnecting(false) {
if (!connectHidlService()) {
return;
@@ -137,6 +140,11 @@
hardware::EventFlag::deleteEventFlag(&mEventQueueFlag);
mEventQueueFlag = nullptr;
}
+
+ if (mWakeLockQueueFlag != nullptr) {
+ hardware::EventFlag::deleteEventFlag(&mWakeLockQueueFlag);
+ mWakeLockQueueFlag = nullptr;
+ }
}
bool SensorDevice::connectHidlService() {
@@ -198,10 +206,16 @@
SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT,
true /* configureEventFlagWord */);
+ hardware::EventFlag::deleteEventFlag(&mEventQueueFlag);
hardware::EventFlag::createEventFlag(mEventQueue->getEventFlagWord(), &mEventQueueFlag);
+ hardware::EventFlag::deleteEventFlag(&mWakeLockQueueFlag);
+ hardware::EventFlag::createEventFlag(mWakeLockQueue->getEventFlagWord(),
+ &mWakeLockQueueFlag);
+
CHECK(mSensors != nullptr && mEventQueue != nullptr &&
- mWakeLockQueue != nullptr && mEventQueueFlag != nullptr);
+ mWakeLockQueue != nullptr && mEventQueueFlag != nullptr &&
+ mWakeLockQueueFlag != nullptr);
status_t status = StatusFromResult(checkReturn(mSensors->initialize(
*mEventQueue->getDesc(),
@@ -512,9 +526,12 @@
}
void SensorDevice::writeWakeLockHandled(uint32_t count) {
- if (mSensors != nullptr && mSensors->supportsMessageQueues() &&
- !mWakeLockQueue->write(&count)) {
- ALOGW("Failed to write wake lock handled");
+ if (mSensors != nullptr && mSensors->supportsMessageQueues()) {
+ if (mWakeLockQueue->write(&count)) {
+ mWakeLockQueueFlag->wake(asBaseType(WakeLockQueueFlagBits::DATA_WRITTEN));
+ } else {
+ ALOGW("Failed to write wake lock handled");
+ }
}
}
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index e1024ac..2a69654 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -238,6 +238,7 @@
std::unique_ptr<WakeLockQueue> mWakeLockQueue;
hardware::EventFlag* mEventQueueFlag;
+ hardware::EventFlag* mWakeLockQueueFlag;
std::array<Event, SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT> mEventBuffer;
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 0c1ea44..5b3bbca 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -1,7 +1,6 @@
cc_defaults {
name: "surfaceflinger_defaults",
cflags: [
- "-DLOG_TAG=\"SurfaceFlinger\"",
"-Wall",
"-Werror",
"-Wformat",
@@ -15,6 +14,7 @@
name: "libsurfaceflinger_defaults",
defaults: ["surfaceflinger_defaults"],
cflags: [
+ "-DLOG_TAG=\"SurfaceFlinger\"",
"-DGL_GLEXT_PROTOTYPES",
"-DEGL_EGLEXT_PROTOTYPES",
],
@@ -55,8 +55,10 @@
"libui",
"libinput",
"libutils",
+ "libutilscallstack",
],
static_libs: [
+ "libcompositionengine",
"librenderengine",
"libserviceutils",
"libtrace_proto",
@@ -69,6 +71,7 @@
"android.hardware.graphics.composer@2.3-command-buffer",
],
export_static_lib_headers: [
+ "libcompositionengine",
"librenderengine",
"libserviceutils",
],
@@ -171,6 +174,9 @@
cc_defaults {
name: "libsurfaceflinger_binary",
defaults: ["surfaceflinger_defaults"],
+ cflags: [
+ "-DLOG_TAG=\"SurfaceFlinger\"",
+ ],
whole_static_libs: [
"libsigchain",
],
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 0a3be71..164a3a6 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -176,7 +176,7 @@
if (!blackOutLayer) {
// TODO: we could be more subtle with isFixedSize()
- const bool useFiltering = needsFiltering(renderArea) || isFixedSize();
+ const bool useFiltering = needsFiltering() || renderArea.needsFiltering() || isFixedSize();
// Query the texture matrix given our current filtering mode.
float textureMatrix[16];
@@ -396,7 +396,6 @@
}
// Capture the old state of the layer for comparisons later
- Mutex::Autolock lock(mStateMutex);
const State& s(getDrawingState());
const bool oldOpacity = isOpaque(s);
sp<GraphicBuffer> oldBuffer = mActiveBuffer;
@@ -503,7 +502,7 @@
// FIXME: postedRegion should be dirty & bounds
// transform the dirty region to window-manager space
- return getTransformLocked().transform(Region(getBufferSize(s)));
+ return getTransform().transform(Region(getBufferSize(s)));
}
// transaction
@@ -551,7 +550,7 @@
// h/w composer set-up
bool BufferLayer::allTransactionsSignaled() {
- auto headFrameNumber = getHeadFrameNumberLocked();
+ auto headFrameNumber = getHeadFrameNumber();
bool matchingFramesFound = false;
bool allTransactionsApplied = true;
Mutex::Autolock lock(mLocalSyncPointMutex);
@@ -598,13 +597,15 @@
return true;
}
-bool BufferLayer::needsFiltering(const RenderArea& renderArea) const {
- return mNeedsFiltering || renderArea.needsFiltering();
+bool BufferLayer::needsFiltering() const {
+ const auto displayFrame = getBE().compositionInfo.hwc.displayFrame;
+ const auto sourceCrop = getBE().compositionInfo.hwc.sourceCrop;
+ return mNeedsFiltering || sourceCrop.getHeight() != displayFrame.getHeight() ||
+ sourceCrop.getWidth() != displayFrame.getWidth();
}
void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const {
ATRACE_CALL();
- Mutex::Autolock lock(mStateMutex);
const State& s(getDrawingState());
computeGeometry(renderArea, getBE().mMesh, useIdentityTransform);
@@ -623,17 +624,19 @@
* minimal value)? Or, we could make GL behave like HWC -- but this feel
* like more of a hack.
*/
- const Rect bounds{computeBoundsLocked()}; // Rounds from FloatRect
- ui::Transform t = getTransformLocked();
- Rect win = bounds;
- const int bufferWidth = getBufferSize(s).getWidth();
- const int bufferHeight = getBufferSize(s).getHeight();
+ // Convert to Rect so that bounds are clipped to integers.
+ const Rect win{computeCrop(Rect::INVALID_RECT)};
+ // computeCrop() returns the cropping rectangle in buffer space, so we
+ // shouldn't use getBufferSize() since that may return a rectangle specified
+ // in layer space. Otherwise we may compute incorrect texture coordinates.
+ const float bufWidth = float(mActiveBuffer->getWidth());
+ const float bufHeight = float(mActiveBuffer->getHeight());
- const float left = float(win.left) / float(bufferWidth);
- const float top = float(win.top) / float(bufferHeight);
- const float right = float(win.right) / float(bufferWidth);
- const float bottom = float(win.bottom) / float(bufferHeight);
+ const float left = win.left / bufWidth;
+ const float top = win.top / bufHeight;
+ const float right = win.right / bufWidth;
+ const float bottom = win.bottom / bufHeight;
// TODO: we probably want to generate the texture coords with the mesh
// here we assume that we only have 4 vertices
@@ -644,7 +647,7 @@
texCoords[2] = vec2(right, 1.0f - bottom);
texCoords[3] = vec2(right, 1.0f - top);
- const auto roundedCornerState = getRoundedCornerStateLocked();
+ const auto roundedCornerState = getRoundedCornerState();
const auto cropRect = roundedCornerState.cropRect;
setupRoundedCornersCropCoordinates(win, cropRect);
@@ -666,12 +669,7 @@
}
uint64_t BufferLayer::getHeadFrameNumber() const {
- Mutex::Autolock lock(mStateMutex);
- return getHeadFrameNumberLocked();
-}
-
-uint64_t BufferLayer::getHeadFrameNumberLocked() const {
- if (hasFrameUpdateLocked()) {
+ if (hasFrameUpdate()) {
return getFrameNumber();
} else {
return mCurrentFrameNumber;
@@ -698,7 +696,7 @@
std::swap(bufWidth, bufHeight);
}
- if (getTransformToDisplayInverseLocked()) {
+ if (getTransformToDisplayInverse()) {
uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform();
if (invTransform & ui::Transform::ROT_90) {
std::swap(bufWidth, bufHeight);
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index 98ae286..e3b7f2f 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -69,7 +69,7 @@
bool isOpaque(const Layer::State& s) const override;
// isVisible - true if this layer is visible, false otherwise
- bool isVisible() const override EXCLUDES(mStateMutex);
+ bool isVisible() const override;
// isProtected - true if the layer may contain protected content in the
// GRALLOC_USAGE_PROTECTED sense.
@@ -91,7 +91,7 @@
bool onPostComposition(const std::optional<DisplayId>& displayId,
const std::shared_ptr<FenceTime>& glDoneFence,
const std::shared_ptr<FenceTime>& presentFence,
- const CompositorTiming& compositorTiming) override EXCLUDES(mStateMutex);
+ const CompositorTiming& compositorTiming) override;
// latchBuffer - called each time the screen is redrawn and returns whether
// the visible regions need to be recomputed (this is a fairly heavy
@@ -101,13 +101,13 @@
// releaseFence will be populated with a native fence that fires when
// composition has completed.
Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
- const sp<Fence>& releaseFence) override EXCLUDES(mStateMutex);
+ const sp<Fence>& releaseFence) override;
bool isBufferLatched() const override { return mRefreshPending; }
void notifyAvailableFrames() override;
- bool hasReadyFrame() const override EXCLUDES(mStateMutex);
+ bool hasReadyFrame() const override;
// Returns the current scaling mode, unless mOverrideScalingMode
// is set, in which case, it returns mOverrideScalingMode
@@ -118,24 +118,19 @@
// Functions that must be implemented by derived classes
// -----------------------------------------------------------------------
private:
- virtual bool fenceHasSignaled() const EXCLUDES(mStateMutex) = 0;
+ virtual bool fenceHasSignaled() const = 0;
virtual nsecs_t getDesiredPresentTime() = 0;
- std::shared_ptr<FenceTime> getCurrentFenceTime() const EXCLUDES(mStateMutex) {
- Mutex::Autolock lock(mStateMutex);
- return getCurrentFenceTimeLocked();
- }
-
- virtual std::shared_ptr<FenceTime> getCurrentFenceTimeLocked() const REQUIRES(mStateMutex) = 0;
+ virtual std::shared_ptr<FenceTime> getCurrentFenceTime() const = 0;
virtual void getDrawingTransformMatrix(float *matrix) = 0;
- virtual uint32_t getDrawingTransform() const REQUIRES(mStateMutex) = 0;
- virtual ui::Dataspace getDrawingDataSpace() const REQUIRES(mStateMutex) = 0;
- virtual Rect getDrawingCrop() const REQUIRES(mStateMutex) = 0;
+ virtual uint32_t getDrawingTransform() const = 0;
+ virtual ui::Dataspace getDrawingDataSpace() const = 0;
+ virtual Rect getDrawingCrop() const = 0;
virtual uint32_t getDrawingScalingMode() const = 0;
- virtual Region getDrawingSurfaceDamage() const EXCLUDES(mStateMutex) = 0;
- virtual const HdrMetadata& getDrawingHdrMetadata() const EXCLUDES(mStateMutex) = 0;
- virtual int getDrawingApi() const EXCLUDES(mStateMutex) = 0;
+ virtual Region getDrawingSurfaceDamage() const = 0;
+ virtual const HdrMetadata& getDrawingHdrMetadata() const = 0;
+ virtual int getDrawingApi() const = 0;
virtual PixelFormat getPixelFormat() const = 0;
virtual uint64_t getFrameNumber() const = 0;
@@ -143,21 +138,20 @@
virtual bool getAutoRefresh() const = 0;
virtual bool getSidebandStreamChanged() const = 0;
- virtual std::optional<Region> latchSidebandStream(bool& recomputeVisibleRegions)
- EXCLUDES(mStateMutex) = 0;
+ virtual std::optional<Region> latchSidebandStream(bool& recomputeVisibleRegions) = 0;
- virtual bool hasFrameUpdateLocked() const REQUIRES(mStateMutex) = 0;
+ virtual bool hasFrameUpdate() const = 0;
virtual void setFilteringEnabled(bool enabled) = 0;
- virtual status_t bindTextureImage() EXCLUDES(mStateMutex) = 0;
+ virtual status_t bindTextureImage() = 0;
virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
- const sp<Fence>& flushFence) REQUIRES(mStateMutex) = 0;
+ const sp<Fence>& flushFence) = 0;
- virtual status_t updateActiveBuffer() REQUIRES(mStateMutex) = 0;
+ virtual status_t updateActiveBuffer() = 0;
virtual status_t updateFrameNumber(nsecs_t latchTime) = 0;
- virtual void setHwcLayerBuffer(DisplayId displayId) EXCLUDES(mStateMutex) = 0;
+ virtual void setHwcLayerBuffer(DisplayId displayId) = 0;
protected:
// Loads the corresponding system property once per process
@@ -166,29 +160,23 @@
// Check all of the local sync points to ensure that all transactions
// which need to have been applied prior to the frame which is about to
// be latched have signaled
- bool allTransactionsSignaled() REQUIRES(mStateMutex);
+ bool allTransactionsSignaled();
static bool getOpacityForFormat(uint32_t format);
- bool hasFrameUpdate() const EXCLUDES(mStateMutex) {
- Mutex::Autolock lock(mStateMutex);
- return hasFrameUpdateLocked();
- }
-
// from GLES
const uint32_t mTextureName;
+ bool mRefreshPending{false};
+
private:
- // needsLinearFiltering - true if this surface's state requires filtering
- bool needsFiltering(const RenderArea& renderArea) const;
+ // Returns true if this layer requires filtering
+ bool needsFiltering() const;
// drawing
- void drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const
- EXCLUDES(mStateMutex);
+ void drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const;
- uint64_t getHeadFrameNumber() const EXCLUDES(mStateMutex);
-
- uint64_t getHeadFrameNumberLocked() const REQUIRES(mStateMutex);
+ uint64_t getHeadFrameNumber() const;
uint32_t mCurrentScalingMode{NATIVE_WINDOW_SCALING_MODE_FREEZE};
@@ -198,9 +186,7 @@
// The texture used to draw the layer in GLES composition mode
mutable renderengine::Texture mTexture;
- bool mRefreshPending{false};
-
- Rect getBufferSize(const State& s) const override REQUIRES(mStateMutex);
+ Rect getBufferSize(const State& s) const override;
};
} // namespace android
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 3341b98..42021d1 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -51,7 +51,7 @@
return history;
}
-bool BufferQueueLayer::getTransformToDisplayInverseLocked() const {
+bool BufferQueueLayer::getTransformToDisplayInverse() const {
return mConsumer->getTransformToDisplayInverse();
}
@@ -131,7 +131,7 @@
return mConsumer->getTimestamp();
}
-std::shared_ptr<FenceTime> BufferQueueLayer::getCurrentFenceTimeLocked() const {
+std::shared_ptr<FenceTime> BufferQueueLayer::getCurrentFenceTime() const {
return mConsumer->getCurrentFenceTime();
}
@@ -192,7 +192,6 @@
std::optional<Region> BufferQueueLayer::latchSidebandStream(bool& recomputeVisibleRegions) {
bool sidebandStreamChanged = true;
- Mutex::Autolock lock(mStateMutex);
if (mSidebandStreamChanged.compare_exchange_strong(sidebandStreamChanged, false)) {
// mSidebandStreamChanged was changed to false
// replicated in LayerBE until FE/BE is ready to be synchronized
@@ -201,15 +200,15 @@
setTransactionFlags(eTransactionNeeded);
mFlinger->setTransactionFlags(eTraversalNeeded);
}
-
recomputeVisibleRegions = true;
+
const State& s(getDrawingState());
- return getTransformLocked().transform(Region(Rect(s.active_legacy.w, s.active_legacy.h)));
+ return getTransform().transform(Region(Rect(s.active_legacy.w, s.active_legacy.h)));
}
return {};
}
-bool BufferQueueLayer::hasFrameUpdateLocked() const {
+bool BufferQueueLayer::hasFrameUpdate() const {
return mQueuedFrames > 0;
}
@@ -229,18 +228,16 @@
// buffer mode.
bool queuedBuffer = false;
const int32_t layerID = getSequence();
- status_t updateResult;
- LayerRejecter r(mState.drawing, getCurrentState(), recomputeVisibleRegions,
+ LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode,
- getTransformToDisplayInverseLocked(), mFreezeGeometryUpdates);
+ getTransformToDisplayInverse(), mFreezeGeometryUpdates);
const nsecs_t expectedPresentTime = mFlinger->mUseScheduler
? mFlinger->mScheduler->mPrimaryDispSync->expectedPresentTime()
: mFlinger->mPrimaryDispSync->expectedPresentTime();
-
- updateResult = mConsumer->updateTexImage(&r, expectedPresentTime, &mAutoRefresh, &queuedBuffer,
- mLastFrameNumberReceived, releaseFence);
-
+ status_t updateResult =
+ mConsumer->updateTexImage(&r, expectedPresentTime, &mAutoRefresh, &queuedBuffer,
+ mLastFrameNumberReceived, releaseFence);
if (updateResult == BufferQueue::PRESENT_LATER) {
// Producer doesn't want buffer to be displayed yet. Signal a
// layer update so we check again at the next opportunity.
@@ -355,6 +352,14 @@
// Interface implementation for BufferLayerConsumer::ContentsChangedListener
// -----------------------------------------------------------------------
+void BufferQueueLayer::fakeVsync() {
+ mRefreshPending = false;
+ bool ignored = false;
+ latchBuffer(ignored, systemTime(), Fence::NO_FENCE);
+ usleep(16000);
+ releasePendingBuffer(systemTime());
+}
+
void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
// Add this buffer from our internal queue tracker
{ // Autolock scope
@@ -393,10 +398,7 @@
// If this layer is orphaned, then we run a fake vsync pulse so that
// dequeueBuffer doesn't block indefinitely.
if (isRemovedFromCurrentState()) {
- bool ignored = false;
- latchBuffer(ignored, systemTime(), Fence::NO_FENCE);
- usleep(16000);
- releasePendingBuffer(systemTime());
+ fakeVsync();
} else {
mFlinger->signalLayerUpdate();
}
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index f9da044..d7c3f6a 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -44,7 +44,7 @@
std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool forceFlush) override;
- bool getTransformToDisplayInverseLocked() const override REQUIRES(mStateMutex);
+ bool getTransformToDisplayInverse() const override;
// If a buffer was replaced this frame, release the former buffer
void releasePendingBuffer(nsecs_t dequeueReadyTime) override;
@@ -64,12 +64,12 @@
private:
nsecs_t getDesiredPresentTime() override;
- std::shared_ptr<FenceTime> getCurrentFenceTimeLocked() const override REQUIRES(mStateMutex);
+ std::shared_ptr<FenceTime> getCurrentFenceTime() const override;
void getDrawingTransformMatrix(float *matrix) override;
- uint32_t getDrawingTransform() const override REQUIRES(mStateMutex);
- ui::Dataspace getDrawingDataSpace() const override REQUIRES(mStateMutex);
- Rect getDrawingCrop() const override REQUIRES(mStateMutex);
+ uint32_t getDrawingTransform() const override;
+ ui::Dataspace getDrawingDataSpace() const override;
+ Rect getDrawingCrop() const override;
uint32_t getDrawingScalingMode() const override;
Region getDrawingSurfaceDamage() const override;
const HdrMetadata& getDrawingHdrMetadata() const override;
@@ -81,18 +81,17 @@
bool getAutoRefresh() const override;
bool getSidebandStreamChanged() const override;
- std::optional<Region> latchSidebandStream(bool& recomputeVisibleRegions) override
- EXCLUDES(mStateMutex);
+ std::optional<Region> latchSidebandStream(bool& recomputeVisibleRegions) override;
- bool hasFrameUpdateLocked() const override REQUIRES(mStateMutex);
+ bool hasFrameUpdate() const override;
void setFilteringEnabled(bool enabled) override;
status_t bindTextureImage() override;
status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
- const sp<Fence>& releaseFence) override REQUIRES(mStateMutex);
+ const sp<Fence>& releaseFence) override;
- status_t updateActiveBuffer() override REQUIRES(mStateMutex);
+ status_t updateActiveBuffer() override;
status_t updateFrameNumber(nsecs_t latchTime) override;
void setHwcLayerBuffer(DisplayId displayId) override;
@@ -138,6 +137,8 @@
// thread-safe
std::atomic<int32_t> mQueuedFrames{0};
std::atomic<bool> mSidebandStreamChanged{false};
+
+ void fakeVsync();
};
} // namespace android
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 0e46928..e0d9d23 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -72,31 +72,30 @@
}
bool BufferStateLayer::willPresentCurrentTransaction() const {
- Mutex::Autolock lock(mStateMutex);
// Returns true if the most recent Transaction applied to CurrentState will be presented.
return getSidebandStreamChanged() || getAutoRefresh() ||
- (mState.current.modified && mState.current.buffer != nullptr);
+ (mCurrentState.modified && mCurrentState.buffer != nullptr);
}
-bool BufferStateLayer::getTransformToDisplayInverseLocked() const {
- return mState.current.transformToDisplayInverse;
+bool BufferStateLayer::getTransformToDisplayInverse() const {
+ return mCurrentState.transformToDisplayInverse;
}
-void BufferStateLayer::pushPendingStateLocked() {
- if (!mState.current.modified) {
+void BufferStateLayer::pushPendingState() {
+ if (!mCurrentState.modified) {
return;
}
- mState.pending.push_back(mState.current);
- ATRACE_INT(mTransactionName.string(), mState.pending.size());
+ mPendingStates.push_back(mCurrentState);
+ ATRACE_INT(mTransactionName.string(), mPendingStates.size());
}
bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) {
- const bool stateUpdateAvailable = !mState.pending.empty();
- while (!mState.pending.empty()) {
+ const bool stateUpdateAvailable = !mPendingStates.empty();
+ while (!mPendingStates.empty()) {
popPendingState(stateToCommit);
}
- mCurrentStateModified = stateUpdateAvailable && mState.current.modified;
- mState.current.modified = false;
+ mCurrentStateModified = stateUpdateAvailable && mCurrentState.modified;
+ mCurrentState.modified = false;
return stateUpdateAvailable;
}
@@ -106,31 +105,28 @@
}
bool BufferStateLayer::setTransform(uint32_t transform) {
- Mutex::Autolock lock(mStateMutex);
- if (mState.current.transform == transform) return false;
- mState.current.sequence++;
- mState.current.transform = transform;
- mState.current.modified = true;
+ if (mCurrentState.transform == transform) return false;
+ mCurrentState.sequence++;
+ mCurrentState.transform = transform;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
bool BufferStateLayer::setTransformToDisplayInverse(bool transformToDisplayInverse) {
- Mutex::Autolock lock(mStateMutex);
- if (mState.current.transformToDisplayInverse == transformToDisplayInverse) return false;
- mState.current.sequence++;
- mState.current.transformToDisplayInverse = transformToDisplayInverse;
- mState.current.modified = true;
+ if (mCurrentState.transformToDisplayInverse == transformToDisplayInverse) return false;
+ mCurrentState.sequence++;
+ mCurrentState.transformToDisplayInverse = transformToDisplayInverse;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
bool BufferStateLayer::setCrop(const Rect& crop) {
- Mutex::Autolock lock(mStateMutex);
- if (mState.current.crop == crop) return false;
- mState.current.sequence++;
- mState.current.crop = crop;
- mState.current.modified = true;
+ if (mCurrentState.crop == crop) return false;
+ mCurrentState.sequence++;
+ mCurrentState.crop = crop;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
@@ -141,94 +137,96 @@
int w = frame.getWidth();
int h = frame.getHeight();
- Mutex::Autolock lock(mStateMutex);
- if (mState.current.active.transform.tx() == x && mState.current.active.transform.ty() == y &&
- mState.current.active.w == w && mState.current.active.h == h) {
+ if (x < 0) {
+ x = 0;
+ w = frame.right;
+ }
+
+ if (y < 0) {
+ y = 0;
+ h = frame.bottom;
+ }
+
+ if (mCurrentState.active.transform.tx() == x && mCurrentState.active.transform.ty() == y &&
+ mCurrentState.active.w == w && mCurrentState.active.h == h) {
return false;
}
if (!frame.isValid()) {
x = y = w = h = 0;
}
- mState.current.active.transform.set(x, y);
- mState.current.active.w = w;
- mState.current.active.h = h;
+ mCurrentState.active.transform.set(x, y);
+ mCurrentState.active.w = w;
+ mCurrentState.active.h = h;
- mState.current.sequence++;
- mState.current.modified = true;
+ mCurrentState.sequence++;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
bool BufferStateLayer::setBuffer(const sp<GraphicBuffer>& buffer) {
- Mutex::Autolock lock(mStateMutex);
- if (mState.current.buffer) {
+ if (mCurrentState.buffer) {
mReleasePreviousBuffer = true;
}
- mState.current.sequence++;
- mState.current.buffer = buffer;
- mState.current.modified = true;
+ mCurrentState.sequence++;
+ mCurrentState.buffer = buffer;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
bool BufferStateLayer::setAcquireFence(const sp<Fence>& fence) {
- Mutex::Autolock lock(mStateMutex);
// The acquire fences of BufferStateLayers have already signaled before they are set
mCallbackHandleAcquireTime = fence->getSignalTime();
- mState.current.acquireFence = fence;
- mState.current.modified = true;
+ mCurrentState.acquireFence = fence;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
bool BufferStateLayer::setDataspace(ui::Dataspace dataspace) {
- Mutex::Autolock lock(mStateMutex);
- if (mState.current.dataspace == dataspace) return false;
- mState.current.sequence++;
- mState.current.dataspace = dataspace;
- mState.current.modified = true;
+ if (mCurrentState.dataspace == dataspace) return false;
+ mCurrentState.sequence++;
+ mCurrentState.dataspace = dataspace;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
bool BufferStateLayer::setHdrMetadata(const HdrMetadata& hdrMetadata) {
- Mutex::Autolock lock(mStateMutex);
- if (mState.current.hdrMetadata == hdrMetadata) return false;
- mState.current.sequence++;
- mState.current.hdrMetadata = hdrMetadata;
- mState.current.modified = true;
+ if (mCurrentState.hdrMetadata == hdrMetadata) return false;
+ mCurrentState.sequence++;
+ mCurrentState.hdrMetadata = hdrMetadata;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
bool BufferStateLayer::setSurfaceDamageRegion(const Region& surfaceDamage) {
- Mutex::Autolock lock(mStateMutex);
- mState.current.sequence++;
- mState.current.surfaceDamageRegion = surfaceDamage;
- mState.current.modified = true;
+ mCurrentState.sequence++;
+ mCurrentState.surfaceDamageRegion = surfaceDamage;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
bool BufferStateLayer::setApi(int32_t api) {
- Mutex::Autolock lock(mStateMutex);
- if (mState.current.api == api) return false;
- mState.current.sequence++;
- mState.current.api = api;
- mState.current.modified = true;
+ if (mCurrentState.api == api) return false;
+ mCurrentState.sequence++;
+ mCurrentState.api = api;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
bool BufferStateLayer::setSidebandStream(const sp<NativeHandle>& sidebandStream) {
- Mutex::Autolock lock(mStateMutex);
- if (mState.current.sidebandStream == sidebandStream) return false;
- mState.current.sequence++;
- mState.current.sidebandStream = sidebandStream;
- mState.current.modified = true;
+ if (mCurrentState.sidebandStream == sidebandStream) return false;
+ mCurrentState.sequence++;
+ mCurrentState.sidebandStream = sidebandStream;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
if (!mSidebandStreamChanged.exchange(true)) {
@@ -262,10 +260,7 @@
mFlinger->getTransactionCompletedThread().registerPendingLatchedCallbackHandle(handle);
// Store so latched time and release fence can be set
- {
- Mutex::Autolock lock(mStateMutex);
- mState.current.callbackHandles.push_back(handle);
- }
+ mCurrentState.callbackHandles.push_back(handle);
} else { // If this layer will NOT need to be relatched and presented this frame
// Notify the transaction completed thread this handle is done
@@ -280,9 +275,8 @@
}
bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) {
- Mutex::Autolock lock(mStateMutex);
- mState.current.transparentRegionHint = transparent;
- mState.current.modified = true;
+ mCurrentState.transparentRegionHint = transparent;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
@@ -318,7 +312,6 @@
return true;
}
- Mutex::Autolock lock(mStateMutex);
return getDrawingState().acquireFence->getStatus() == Fence::Status::Signaled;
}
@@ -327,7 +320,7 @@
return 0;
}
-std::shared_ptr<FenceTime> BufferStateLayer::getCurrentFenceTimeLocked() const {
+std::shared_ptr<FenceTime> BufferStateLayer::getCurrentFenceTime() const {
return std::make_shared<FenceTime>(getDrawingState().acquireFence);
}
@@ -374,17 +367,14 @@
}
Region BufferStateLayer::getDrawingSurfaceDamage() const {
- Mutex::Autolock lock(mStateMutex);
return getDrawingState().surfaceDamageRegion;
}
const HdrMetadata& BufferStateLayer::getDrawingHdrMetadata() const {
- Mutex::Autolock lock(mStateMutex);
return getDrawingState().hdrMetadata;
}
int BufferStateLayer::getDrawingApi() const {
- Mutex::Autolock lock(mStateMutex);
return getDrawingState().api;
}
@@ -409,7 +399,6 @@
}
std::optional<Region> BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) {
- Mutex::Autolock lock(mStateMutex);
if (mSidebandStreamChanged.exchange(false)) {
const State& s(getDrawingState());
// mSidebandStreamChanged was true
@@ -421,12 +410,12 @@
}
recomputeVisibleRegions = true;
- return getTransformLocked().transform(Region(Rect(s.active.w, s.active.h)));
+ return getTransform().transform(Region(Rect(s.active.w, s.active.h)));
}
return {};
}
-bool BufferStateLayer::hasFrameUpdateLocked() const {
+bool BufferStateLayer::hasFrameUpdate() const {
return mCurrentStateModified && getCurrentState().buffer != nullptr;
}
@@ -436,10 +425,6 @@
}
status_t BufferStateLayer::bindTextureImage() {
- Mutex::Autolock lock(mStateMutex);
- return bindTextureImageLocked();
-}
-status_t BufferStateLayer::bindTextureImageLocked() {
const State& s(getDrawingState());
auto& engine(mFlinger->getRenderEngine());
@@ -544,7 +529,7 @@
auto incomingStatus = releaseFence->getStatus();
if (incomingStatus == Fence::Status::Invalid) {
ALOGE("New fence has invalid state");
- mState.drawing.acquireFence = releaseFence;
+ mDrawingState.acquireFence = releaseFence;
mFlinger->mTimeStats->onDestroy(layerID);
return BAD_VALUE;
}
@@ -555,16 +540,16 @@
char fenceName[32] = {};
snprintf(fenceName, 32, "%.28s:%d", mName.string(), mFrameNumber);
sp<Fence> mergedFence =
- Fence::merge(fenceName, mState.drawing.acquireFence, releaseFence);
+ Fence::merge(fenceName, mDrawingState.acquireFence, releaseFence);
if (!mergedFence.get()) {
ALOGE("failed to merge release fences");
// synchronization is broken, the best we can do is hope fences
// signal in order so the new fence will act like a union
- mState.drawing.acquireFence = releaseFence;
+ mDrawingState.acquireFence = releaseFence;
mFlinger->mTimeStats->onDestroy(layerID);
return BAD_VALUE;
}
- mState.drawing.acquireFence = mergedFence;
+ mDrawingState.acquireFence = mergedFence;
} else if (incomingStatus == Fence::Status::Unsignaled) {
// If one fence has signaled and the other hasn't, the unsignaled
// fence will approximately correspond with the correct timestamp.
@@ -573,7 +558,7 @@
// by this point, they will have both signaled and only the timestamp
// will be slightly off; any dependencies after this point will
// already have been met.
- mState.drawing.acquireFence = releaseFence;
+ mDrawingState.acquireFence = releaseFence;
}
} else {
// Bind the new buffer to the GL texture.
@@ -582,7 +567,7 @@
// by glEGLImageTargetTexture2DOES, which this method calls. Newer
// devices will either call this in Layer::onDraw, or (if it's not
// a GL-composited layer) not at all.
- status_t err = bindTextureImageLocked();
+ status_t err = bindTextureImage();
if (err != NO_ERROR) {
mFlinger->mTimeStats->onDestroy(layerID);
return BAD_VALUE;
@@ -591,7 +576,7 @@
// TODO(marissaw): properly support mTimeStats
mFlinger->mTimeStats->setPostTime(layerID, getFrameNumber(), getName().c_str(), latchTime);
- mFlinger->mTimeStats->setAcquireFence(layerID, getFrameNumber(), getCurrentFenceTimeLocked());
+ mFlinger->mTimeStats->setAcquireFence(layerID, getFrameNumber(), getCurrentFenceTime());
mFlinger->mTimeStats->setLatchTime(layerID, getFrameNumber(), latchTime);
return NO_ERROR;
@@ -618,7 +603,6 @@
}
void BufferStateLayer::setHwcLayerBuffer(DisplayId displayId) {
- Mutex::Autolock lock(mStateMutex);
auto& hwcInfo = getBE().mHwcLayers[displayId];
auto& hwcLayer = hwcInfo.layer;
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 655353c..3f891d3 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -41,14 +41,13 @@
bool shouldPresentNow(nsecs_t expectedPresentTime) const override;
- bool getTransformToDisplayInverseLocked() const override REQUIRES(mStateMutex);
+ bool getTransformToDisplayInverse() const override;
uint32_t doTransactionResize(uint32_t flags, Layer::State* /*stateToCommit*/) override {
return flags;
}
-
- void pushPendingStateLocked() override REQUIRES(mStateMutex);
- bool applyPendingStates(Layer::State* stateToCommit) override REQUIRES(mStateMutex);
+ void pushPendingState() override;
+ bool applyPendingStates(Layer::State* stateToCommit) override;
uint32_t getActiveWidth(const Layer::State& s) const override { return s.active.w; }
uint32_t getActiveHeight(const Layer::State& s) const override { return s.active.h; }
@@ -60,20 +59,18 @@
}
Rect getCrop(const Layer::State& s) const;
- bool setTransform(uint32_t transform) override EXCLUDES(mStateMutex);
- bool setTransformToDisplayInverse(bool transformToDisplayInverse) override
- EXCLUDES(mStateMutex);
- bool setCrop(const Rect& crop) override EXCLUDES(mStateMutex);
- bool setFrame(const Rect& frame) override EXCLUDES(mStateMutex);
- bool setBuffer(const sp<GraphicBuffer>& buffer) override EXCLUDES(mStateMutex);
- bool setAcquireFence(const sp<Fence>& fence) override EXCLUDES(mStateMutex);
- bool setDataspace(ui::Dataspace dataspace) override EXCLUDES(mStateMutex);
- bool setHdrMetadata(const HdrMetadata& hdrMetadata) override EXCLUDES(mStateMutex);
- bool setSurfaceDamageRegion(const Region& surfaceDamage) override EXCLUDES(mStateMutex);
- bool setApi(int32_t api) override EXCLUDES(mStateMutex);
- bool setSidebandStream(const sp<NativeHandle>& sidebandStream) override EXCLUDES(mStateMutex);
- bool setTransactionCompletedListeners(const std::vector<sp<CallbackHandle>>& handles) override
- EXCLUDES(mStateMutex);
+ bool setTransform(uint32_t transform) override;
+ bool setTransformToDisplayInverse(bool transformToDisplayInverse) override;
+ bool setCrop(const Rect& crop) override;
+ bool setFrame(const Rect& frame) override;
+ bool setBuffer(const sp<GraphicBuffer>& buffer) override;
+ bool setAcquireFence(const sp<Fence>& fence) override;
+ bool setDataspace(ui::Dataspace dataspace) override;
+ bool setHdrMetadata(const HdrMetadata& hdrMetadata) override;
+ bool setSurfaceDamageRegion(const Region& surfaceDamage) override;
+ bool setApi(int32_t api) override;
+ bool setSidebandStream(const sp<NativeHandle>& sidebandStream) override;
+ bool setTransactionCompletedListeners(const std::vector<sp<CallbackHandle>>& handles) override;
// Override to ignore legacy layer state properties that are not used by BufferStateLayer
bool setSize(uint32_t /*w*/, uint32_t /*h*/) override { return false; }
@@ -90,26 +87,26 @@
void deferTransactionUntil_legacy(const sp<Layer>& /*barrierLayer*/,
uint64_t /*frameNumber*/) override {}
- Rect getBufferSize(const State& s) const override REQUIRES(mStateMutex);
+ Rect getBufferSize(const State& s) const override;
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
// Interface implementation for BufferLayer
// -----------------------------------------------------------------------
- bool fenceHasSignaled() const override EXCLUDES(mStateMutex);
+ bool fenceHasSignaled() const override;
private:
nsecs_t getDesiredPresentTime() override;
- std::shared_ptr<FenceTime> getCurrentFenceTimeLocked() const override REQUIRES(mStateMutex);
+ std::shared_ptr<FenceTime> getCurrentFenceTime() const override;
void getDrawingTransformMatrix(float *matrix) override;
- uint32_t getDrawingTransform() const override REQUIRES(mStateMutex);
- ui::Dataspace getDrawingDataSpace() const override REQUIRES(mStateMutex);
- Rect getDrawingCrop() const override REQUIRES(mStateMutex);
+ uint32_t getDrawingTransform() const override;
+ ui::Dataspace getDrawingDataSpace() const override;
+ Rect getDrawingCrop() const override;
uint32_t getDrawingScalingMode() const override;
- Region getDrawingSurfaceDamage() const override EXCLUDES(mStateMutex);
- const HdrMetadata& getDrawingHdrMetadata() const override EXCLUDES(mStateMutex);
- int getDrawingApi() const override EXCLUDES(mStateMutex);
+ Region getDrawingSurfaceDamage() const override;
+ const HdrMetadata& getDrawingHdrMetadata() const override;
+ int getDrawingApi() const override;
PixelFormat getPixelFormat() const override;
uint64_t getFrameNumber() const override;
@@ -117,26 +114,24 @@
bool getAutoRefresh() const override;
bool getSidebandStreamChanged() const override;
- std::optional<Region> latchSidebandStream(bool& recomputeVisibleRegions) override
- EXCLUDES(mStateMutex);
+ std::optional<Region> latchSidebandStream(bool& recomputeVisibleRegions) override;
- bool hasFrameUpdateLocked() const override REQUIRES(mStateMutex);
+ bool hasFrameUpdate() const override;
void setFilteringEnabled(bool enabled) override;
- status_t bindTextureImage() override EXCLUDES(mStateMutex);
+ status_t bindTextureImage() override;
status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
- const sp<Fence>& releaseFence) override REQUIRES(mStateMutex);
+ const sp<Fence>& releaseFence) override;
- status_t updateActiveBuffer() override REQUIRES(mStateMutex);
+ status_t updateActiveBuffer() override;
status_t updateFrameNumber(nsecs_t latchTime) override;
- void setHwcLayerBuffer(DisplayId displayId) override EXCLUDES(mStateMutex);
+ void setHwcLayerBuffer(DisplayId displayId) override;
private:
void onFirstRef() override;
bool willPresentCurrentTransaction() const;
- status_t bindTextureImageLocked() REQUIRES(mStateMutex);
static const std::array<float, 16> IDENTITY_MATRIX;
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index 0b59147..0e447d8 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -35,55 +35,10 @@
// ---------------------------------------------------------------------------
Client::Client(const sp<SurfaceFlinger>& flinger)
- : Client(flinger, nullptr)
+ : mFlinger(flinger)
{
}
-Client::Client(const sp<SurfaceFlinger>& flinger, const sp<Layer>& parentLayer)
- : mFlinger(flinger),
- mParentLayer(parentLayer)
-{
-}
-
-Client::~Client()
-{
- // We need to post a message to remove our remaining layers rather than
- // do so directly by acquiring the SurfaceFlinger lock. If we were to
- // attempt to directly call the lock it becomes effectively impossible
- // to use sp<Client> while holding the SF lock as descoping it could
- // then trigger a dead-lock.
-
- const size_t count = mLayers.size();
- for (size_t i=0 ; i<count ; i++) {
- sp<Layer> l = mLayers.valueAt(i).promote();
- if (l == nullptr) {
- continue;
- }
- mFlinger->postMessageAsync(new LambdaMessage([flinger = mFlinger, l]() {
- flinger->removeLayer(l);
- }));
- }
-}
-
-void Client::updateParent(const sp<Layer>& parentLayer) {
- Mutex::Autolock _l(mLock);
-
- // If we didn't ever have a parent, then we must instead be
- // relying on permissions and we never need a parent.
- if (mParentLayer != nullptr) {
- mParentLayer = parentLayer;
- }
-}
-
-sp<Layer> Client::getParentLayer(bool* outParentDied) const {
- Mutex::Autolock _l(mLock);
- sp<Layer> parent = mParentLayer.promote();
- if (outParentDied != nullptr) {
- *outParentDied = (mParentLayer != nullptr && parent == nullptr);
- }
- return parent;
-}
-
status_t Client::initCheck() const {
return NO_ERROR;
}
@@ -119,32 +74,6 @@
}
-status_t Client::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- // these must be checked
- IPCThreadState* ipc = IPCThreadState::self();
- const int pid = ipc->getCallingPid();
- const int uid = ipc->getCallingUid();
- const int self_pid = getpid();
- // If we are called from another non root process without the GRAPHICS, SYSTEM, or ROOT
- // uid we require the sAccessSurfaceFlinger permission.
- // We grant an exception in the case that the Client has a "parent layer", as its
- // effects will be scoped to that layer.
- if (CC_UNLIKELY(pid != self_pid && uid != AID_GRAPHICS && uid != AID_SYSTEM && uid != 0)
- && (getParentLayer() == nullptr)) {
- // we're called from a different process, do the real check
- if (!PermissionCache::checkCallingPermission(sAccessSurfaceFlinger))
- {
- ALOGE("Permission Denial: "
- "can't openGlobalTransaction pid=%d, uid<=%d", pid, uid);
- return PERMISSION_DENIED;
- }
- }
- return BnSurfaceComposerClient::onTransact(code, data, reply, flags);
-}
-
-
status_t Client::createSurface(
const String8& name,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
@@ -160,22 +89,30 @@
return NAME_NOT_FOUND;
}
}
- if (parent == nullptr) {
- bool parentDied;
- parent = getParentLayer(&parentDied);
- // If we had a parent, but it died, we've lost all
- // our capabilities.
- if (parentDied) {
- return NAME_NOT_FOUND;
- }
- }
+ // We rely on createLayer to check permissions.
return mFlinger->createLayer(name, this, w, h, format, flags, windowType,
ownerUid, handle, gbp, &parent);
}
-status_t Client::destroySurface(const sp<IBinder>& handle) {
- return mFlinger->onLayerRemoved(this, handle);
+status_t Client::createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h,
+ PixelFormat format, uint32_t flags,
+ const sp<IGraphicBufferProducer>& parent,
+ int32_t windowType, int32_t ownerUid, sp<IBinder>* handle,
+ sp<IGraphicBufferProducer>* gbp) {
+ if (mFlinger->authenticateSurfaceTexture(parent) == false) {
+ return BAD_VALUE;
+ }
+
+ const auto& layer = (static_cast<MonitoredProducer*>(parent.get()))->getLayer();
+ if (layer == nullptr) {
+ return BAD_VALUE;
+ }
+
+ sp<IBinder> parentHandle = layer->getHandle();
+
+ return createSurface(name, w, h, format, flags, parentHandle, windowType, ownerUid, handle,
+ gbp);
}
status_t Client::clearLayerFrameStats(const sp<IBinder>& handle) const {
diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h
index 49437ed..0f5ee4c 100644
--- a/services/surfaceflinger/Client.h
+++ b/services/surfaceflinger/Client.h
@@ -39,20 +39,16 @@
{
public:
explicit Client(const sp<SurfaceFlinger>& flinger);
- Client(const sp<SurfaceFlinger>& flinger, const sp<Layer>& parentLayer);
- ~Client();
+ ~Client() = default;
status_t initCheck() const;
// protected by SurfaceFlinger::mStateLock
void attachLayer(const sp<IBinder>& handle, const sp<Layer>& layer);
-
void detachLayer(const Layer* layer);
sp<Layer> getLayerUser(const sp<IBinder>& handle) const;
- void updateParent(const sp<Layer>& parentLayer);
-
private:
// ISurfaceComposerClient interface
virtual status_t createSurface(
@@ -62,23 +58,21 @@
sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp);
- virtual status_t destroySurface(const sp<IBinder>& handle);
+ virtual status_t createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h,
+ PixelFormat format, uint32_t flags,
+ const sp<IGraphicBufferProducer>& parent,
+ int32_t windowType, int32_t ownerUid,
+ sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp);
virtual status_t clearLayerFrameStats(const sp<IBinder>& handle) const;
virtual status_t getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const;
- virtual status_t onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
-
- sp<Layer> getParentLayer(bool* outParentDied = nullptr) const;
-
// constant
sp<SurfaceFlinger> mFlinger;
// protected by mLock
DefaultKeyedVector< wp<IBinder>, wp<Layer> > mLayers;
- wp<Layer> mParentLayer;
// thread-safe
mutable Mutex mLock;
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index cb7642e..f27f6aa 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -40,16 +40,15 @@
void ColorLayer::onDraw(const RenderArea& renderArea, const Region& /* clip */,
bool useIdentityTransform) {
- Mutex::Autolock lock(mStateMutex);
half4 color = getColor();
if (color.a > 0) {
renderengine::Mesh mesh(renderengine::Mesh::TRIANGLE_FAN, 4, 2);
computeGeometry(renderArea, mesh, useIdentityTransform);
auto& engine(mFlinger->getRenderEngine());
- Rect win{computeBoundsLocked()};
+ Rect win{computeBounds()};
- const auto roundedCornerState = getRoundedCornerStateLocked();
+ const auto roundedCornerState = getRoundedCornerState();
const auto cropRect = roundedCornerState.cropRect;
setupRoundedCornersCropCoordinates(win, cropRect);
@@ -92,7 +91,6 @@
}
getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace;
- Mutex::Autolock lock(mStateMutex);
half4 color = getColor();
error = hwcLayer->setColor({static_cast<uint8_t>(std::round(255.0f * color.r)),
static_cast<uint8_t>(std::round(255.0f * color.g)),
@@ -113,12 +111,12 @@
}
getBE().compositionInfo.hwc.transform = HWC2::Transform::None;
- error = hwcLayer->setColorTransform(getColorTransformLocked());
+ error = hwcLayer->setColorTransform(getColorTransform());
if (error != HWC2::Error::None) {
ALOGE("[%s] Failed to setColorTransform: %s (%d)", mName.string(),
to_string(error).c_str(), static_cast<int32_t>(error));
}
- getBE().compositionInfo.hwc.colorTransform = getColorTransformLocked();
+ getBE().compositionInfo.hwc.colorTransform = getColorTransform();
error = hwcLayer->setSurfaceDamage(surfaceDamageRegion);
if (error != HWC2::Error::None) {
diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h
index 5850a2e..aecde9f 100644
--- a/services/surfaceflinger/ColorLayer.h
+++ b/services/surfaceflinger/ColorLayer.h
@@ -29,17 +29,17 @@
~ColorLayer() override;
virtual const char* getTypeId() const { return "ColorLayer"; }
- virtual void onDraw(const RenderArea& renderArea, const Region& clip, bool useIdentityTransform)
- EXCLUDES(mStateMutex);
- bool isVisible() const override EXCLUDES(mStateMutex);
+ virtual void onDraw(const RenderArea& renderArea, const Region& clip,
+ bool useIdentityTransform);
+ bool isVisible() const override;
void setPerFrameData(DisplayId displayId, const ui::Transform& transform, const Rect& viewport,
- int32_t supportedPerFrameMetadata) override EXCLUDES(mStateMutex);
+ int32_t supportedPerFrameMetadata) override;
bool onPreComposition(nsecs_t /*refreshStartTime*/) override { return false; }
protected:
- FloatRect computeCrop(const sp<const DisplayDevice>& /*display*/) const override { return {}; }
+ FloatRect computeCrop(const Rect& /*windowbounds*/) const override { return {}; }
};
} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
new file mode 100644
index 0000000..ec5e131
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -0,0 +1,88 @@
+cc_defaults {
+ name: "libcompositionengine_defaults",
+ defaults: ["surfaceflinger_defaults"],
+ cflags: [
+ "-DLOG_TAG=\"CompositionEngine\"",
+ ],
+ shared_libs: [
+ "android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.composer@2.2",
+ "android.hardware.graphics.composer@2.3",
+ "android.hardware.power@1.0",
+ "android.hardware.power@1.3",
+ "libbase",
+ "libcutils",
+ "libgui",
+ "liblayers_proto",
+ "liblog",
+ "libtimestats_proto",
+ "libui",
+ "libutils",
+ ],
+ static_libs: [
+ "libmath",
+ "librenderengine",
+ "libtrace_proto",
+ ],
+ header_libs: [
+ "libsurfaceflinger_headers",
+ ],
+}
+
+cc_library {
+ name: "libcompositionengine",
+ defaults: ["libcompositionengine_defaults"],
+ srcs: [
+ "src/CompositionEngine.cpp",
+ ],
+ local_include_dirs: ["include"],
+ export_include_dirs: ["include"],
+}
+
+cc_library {
+ name: "libcompositionengine_mocks",
+ defaults: ["libcompositionengine_defaults"],
+ srcs: [
+ "mock/CompositionEngine.cpp",
+ ],
+ static_libs: [
+ "libgtest",
+ "libgmock",
+ "libcompositionengine",
+ ],
+ local_include_dirs: ["include"],
+ export_include_dirs: ["include"],
+}
+
+cc_test {
+ name: "libcompositionengine_test",
+ test_suites: ["device-tests"],
+ defaults: ["libcompositionengine_defaults"],
+ srcs: [
+ "tests/CompositionEngineTest.cpp",
+ "tests/MockHWComposer.cpp",
+ ],
+ static_libs: [
+ "libcompositionengine",
+ "libcompositionengine_mocks",
+ "librenderengine_mocks",
+ "libgmock",
+ "libgtest",
+ ],
+ sanitize: {
+ // By using the address sanitizer, we not only uncover any issues
+ // with the test, but also any issues with the code under test.
+ //
+ // Note: If you get an runtime link error like:
+ //
+ // CANNOT LINK EXECUTABLE "/data/local/tmp/libcompositionengine_test": library "libclang_rt.asan-aarch64-android.so" not found
+ //
+ // it is because the address sanitizer shared objects are not installed
+ // by default in the system image.
+ //
+ // You can either "make dist tests" before flashing, or set this
+ // option to false temporarily.
+ address: true,
+ },
+}
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h
new file mode 100644
index 0000000..af8515f
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+
+namespace android {
+
+class HWComposer;
+
+namespace renderengine {
+class RenderEngine;
+} // namespace renderengine
+
+namespace compositionengine {
+
+/**
+ * Encapsulates all the interfaces and implementation details for performing
+ * display output composition.
+ */
+class CompositionEngine {
+public:
+ virtual ~CompositionEngine();
+
+ virtual HWComposer& getHwComposer() const = 0;
+ virtual void setHwComposer(std::unique_ptr<HWComposer>) = 0;
+
+ virtual renderengine::RenderEngine& getRenderEngine() const = 0;
+ virtual void setRenderEngine(std::unique_ptr<renderengine::RenderEngine>) = 0;
+};
+
+} // namespace compositionengine
+} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h
new file mode 100644
index 0000000..86d1774
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <compositionengine/CompositionEngine.h>
+
+namespace android::compositionengine::impl {
+
+class CompositionEngine : public compositionengine::CompositionEngine {
+public:
+ CompositionEngine();
+ ~CompositionEngine() override;
+
+ HWComposer& getHwComposer() const override;
+ void setHwComposer(std::unique_ptr<HWComposer>) override;
+
+ renderengine::RenderEngine& getRenderEngine() const override;
+ void setRenderEngine(std::unique_ptr<renderengine::RenderEngine>) override;
+
+private:
+ std::unique_ptr<HWComposer> mHwComposer;
+ std::unique_ptr<renderengine::RenderEngine> mRenderEngine;
+};
+
+std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine();
+
+} // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h
new file mode 100644
index 0000000..9ba213e
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <compositionengine/CompositionEngine.h>
+#include <gmock/gmock.h>
+#include <renderengine/RenderEngine.h>
+
+#include "DisplayHardware/HWComposer.h"
+
+namespace android::compositionengine::mock {
+
+class CompositionEngine : public compositionengine::CompositionEngine {
+public:
+ CompositionEngine();
+ ~CompositionEngine() override;
+
+ MOCK_CONST_METHOD0(getHwComposer, HWComposer&());
+ MOCK_METHOD1(setHwComposer, void(std::unique_ptr<HWComposer>));
+
+ MOCK_CONST_METHOD0(getRenderEngine, renderengine::RenderEngine&());
+ MOCK_METHOD1(setRenderEngine, void(std::unique_ptr<renderengine::RenderEngine>));
+};
+
+} // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/mock/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/mock/CompositionEngine.cpp
new file mode 100644
index 0000000..778a09e
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/mock/CompositionEngine.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <compositionengine/mock/CompositionEngine.h>
+
+namespace android::compositionengine::mock {
+
+// The Google Mock documentation recommends explicit non-header instantiations
+// for better compile time performance.
+CompositionEngine::CompositionEngine() = default;
+CompositionEngine::~CompositionEngine() = default;
+
+} // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
new file mode 100644
index 0000000..fbf71b5
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <compositionengine/impl/CompositionEngine.h>
+#include <renderengine/RenderEngine.h>
+
+#include "DisplayHardware/HWComposer.h"
+
+namespace android::compositionengine {
+
+CompositionEngine::~CompositionEngine() = default;
+
+namespace impl {
+
+std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine() {
+ return std::make_unique<CompositionEngine>();
+}
+
+CompositionEngine::CompositionEngine() = default;
+CompositionEngine::~CompositionEngine() = default;
+
+HWComposer& CompositionEngine::getHwComposer() const {
+ return *mHwComposer.get();
+}
+
+void CompositionEngine::setHwComposer(std::unique_ptr<HWComposer> hwComposer) {
+ mHwComposer = std::move(hwComposer);
+}
+
+renderengine::RenderEngine& CompositionEngine::getRenderEngine() const {
+ return *mRenderEngine.get();
+}
+
+void CompositionEngine::setRenderEngine(std::unique_ptr<renderengine::RenderEngine> renderEngine) {
+ mRenderEngine = std::move(renderEngine);
+}
+
+} // namespace impl
+} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
new file mode 100644
index 0000000..3766f27
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <compositionengine/impl/CompositionEngine.h>
+#include <gtest/gtest.h>
+#include <renderengine/mock/RenderEngine.h>
+
+#include "MockHWComposer.h"
+
+namespace android::compositionengine {
+namespace {
+
+using ::testing::StrictMock;
+
+class CompositionEngineTest : public testing::Test {
+public:
+ ~CompositionEngineTest() override;
+ mock::HWComposer* mHwc = new StrictMock<mock::HWComposer>();
+ renderengine::mock::RenderEngine* mRenderEngine =
+ new StrictMock<renderengine::mock::RenderEngine>();
+ impl::CompositionEngine mEngine;
+};
+
+CompositionEngineTest::~CompositionEngineTest() = default;
+
+TEST_F(CompositionEngineTest, canInstantiateCompositionEngine) {
+ auto engine = impl::createCompositionEngine();
+ EXPECT_TRUE(engine.get() != nullptr);
+}
+
+TEST_F(CompositionEngineTest, canSetHWComposer) {
+ mEngine.setHwComposer(std::unique_ptr<android::HWComposer>(mHwc));
+
+ EXPECT_EQ(mHwc, &mEngine.getHwComposer());
+}
+
+TEST_F(CompositionEngineTest, canSetRenderEngine) {
+ mEngine.setRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine));
+
+ EXPECT_EQ(mRenderEngine, &mEngine.getRenderEngine());
+}
+
+} // namespace
+} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.cpp b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.cpp
new file mode 100644
index 0000000..ae52670
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MockHWComposer.h"
+
+namespace android {
+
+// This will go away once HWComposer is moved into the "backend" library
+HWComposer::~HWComposer() = default;
+
+namespace mock {
+
+// The Google Mock documentation recommends explicit non-header instantiations
+// for better compile time performance.
+HWComposer::HWComposer() = default;
+HWComposer::~HWComposer() = default;
+
+} // namespace mock
+} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
new file mode 100644
index 0000000..ece412f
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <gmock/gmock.h>
+
+#include "LayerBE.h"
+
+#include "DisplayHardware/HWComposer.h"
+
+namespace android {
+namespace mock {
+
+class HWComposer : public android::HWComposer {
+public:
+ HWComposer();
+ ~HWComposer() override;
+
+ MOCK_METHOD2(registerCallback, void(HWC2::ComposerCallback*, int32_t));
+ MOCK_CONST_METHOD3(getDisplayIdentificationData,
+ bool(hwc2_display_t, uint8_t*, DisplayIdentificationData*));
+ MOCK_CONST_METHOD1(hasCapability, bool(HWC2::Capability));
+ MOCK_CONST_METHOD2(hasDisplayCapability,
+ bool(const std::optional<DisplayId>&, HWC2::DisplayCapability));
+
+ MOCK_METHOD3(allocateVirtualDisplay,
+ std::optional<DisplayId>(uint32_t, uint32_t, ui::PixelFormat*));
+ MOCK_METHOD1(createLayer, HWC2::Layer*(DisplayId));
+ MOCK_METHOD2(destroyLayer, void(DisplayId, HWC2::Layer*));
+ MOCK_METHOD2(prepare, status_t(DisplayId, std::vector<CompositionInfo>&));
+ MOCK_METHOD5(setClientTarget,
+ status_t(DisplayId, uint32_t, const sp<Fence>&, const sp<GraphicBuffer>&,
+ ui::Dataspace));
+ MOCK_METHOD1(presentAndGetReleaseFences, status_t(DisplayId));
+ MOCK_METHOD2(setPowerMode, status_t(DisplayId, int));
+ MOCK_METHOD2(setActiveConfig, status_t(DisplayId, size_t));
+ MOCK_METHOD2(setColorTransform, status_t(DisplayId, const mat4&));
+ MOCK_METHOD1(disconnectDisplay, void(DisplayId));
+ MOCK_CONST_METHOD1(hasDeviceComposition, bool(const std::optional<DisplayId>&));
+ MOCK_CONST_METHOD1(hasFlipClientTargetRequest, bool(const std::optional<DisplayId>&));
+ MOCK_CONST_METHOD1(hasClientComposition, bool(const std::optional<DisplayId>&));
+ MOCK_CONST_METHOD1(getPresentFence, sp<Fence>(DisplayId));
+ MOCK_CONST_METHOD2(getLayerReleaseFence, sp<Fence>(DisplayId, HWC2::Layer*));
+ MOCK_METHOD3(setOutputBuffer, status_t(DisplayId, const sp<Fence>&, const sp<GraphicBuffer>&));
+ MOCK_METHOD1(clearReleaseFences, void(DisplayId));
+ MOCK_METHOD2(getHdrCapabilities, status_t(DisplayId, HdrCapabilities*));
+ MOCK_CONST_METHOD1(getSupportedPerFrameMetadata, int32_t(DisplayId));
+ MOCK_CONST_METHOD2(getRenderIntents, std::vector<ui::RenderIntent>(DisplayId, ui::ColorMode));
+ MOCK_METHOD2(getDataspaceSaturationMatrix, mat4(DisplayId, ui::Dataspace));
+ MOCK_METHOD4(getDisplayedContentSamplingAttributes,
+ status_t(DisplayId, ui::PixelFormat*, ui::Dataspace*, uint8_t*));
+ MOCK_METHOD4(setDisplayContentSamplingEnabled, status_t(DisplayId, bool, uint8_t, uint64_t));
+ MOCK_METHOD4(getDisplayedContentSample,
+ status_t(DisplayId, uint64_t, uint64_t, DisplayedFrameStats*));
+
+ MOCK_METHOD2(onHotplug,
+ std::optional<DisplayIdentificationInfo>(hwc2_display_t, HWC2::Connection));
+ MOCK_METHOD2(onVsync, bool(hwc2_display_t, int64_t));
+ MOCK_METHOD2(setVsyncEnabled, void(DisplayId, HWC2::Vsync));
+ MOCK_CONST_METHOD1(getRefreshTimestamp, nsecs_t(DisplayId));
+ MOCK_CONST_METHOD1(isConnected, bool(DisplayId));
+ MOCK_CONST_METHOD1(getConfigs,
+ std::vector<std::shared_ptr<const HWC2::Display::Config>>(DisplayId));
+ MOCK_CONST_METHOD1(getActiveConfig, std::shared_ptr<const HWC2::Display::Config>(DisplayId));
+ MOCK_CONST_METHOD1(getActiveConfigIndex, int(DisplayId));
+ MOCK_CONST_METHOD1(getColorModes, std::vector<ui::ColorMode>(DisplayId));
+ MOCK_METHOD3(setActiveColorMode, status_t(DisplayId, ui::ColorMode, ui::RenderIntent));
+ MOCK_CONST_METHOD0(isUsingVrComposer, bool());
+
+ MOCK_CONST_METHOD1(dump, void(std::string&));
+ MOCK_CONST_METHOD0(getComposer, android::Hwc2::Composer*());
+ MOCK_CONST_METHOD1(getHwcDisplayId, std::optional<hwc2_display_t>(int32_t));
+ MOCK_CONST_METHOD0(getInternalHwcDisplayId, std::optional<hwc2_display_t>());
+ MOCK_CONST_METHOD0(getExternalHwcDisplayId, std::optional<hwc2_display_t>());
+ MOCK_CONST_METHOD1(toPhysicalDisplayId, std::optional<DisplayId>(hwc2_display_t));
+ MOCK_CONST_METHOD1(fromPhysicalDisplayId, std::optional<hwc2_display_t>(DisplayId));
+};
+
+} // namespace mock
+} // namespace android
diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h
index 6c4f7c8..413844b 100644
--- a/services/surfaceflinger/ContainerLayer.h
+++ b/services/surfaceflinger/ContainerLayer.h
@@ -31,7 +31,7 @@
const char* getTypeId() const override { return "ContainerLayer"; }
void onDraw(const RenderArea& renderArea, const Region& clip,
bool useIdentityTransform) override;
- bool isVisible() const override EXCLUDES(mStateMutex);
+ bool isVisible() const override;
void setPerFrameData(DisplayId displayId, const ui::Transform& transform, const Rect& viewport,
int32_t supportedPerFrameMetadata) override;
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 2d91c68..03eafd5 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -40,13 +40,12 @@
class BufferHandle {
public:
- BufferHandle(const native_handle_t* buffer)
- {
+ explicit BufferHandle(const native_handle_t* buffer) {
// nullptr is not a valid handle to HIDL
mHandle = (buffer) ? buffer : native_handle_init(mStorage, 0, 0);
}
- operator const hidl_handle&() const
+ operator const hidl_handle&() const // NOLINT(google-explicit-constructor)
{
return mHandle;
}
@@ -80,7 +79,7 @@
}
}
- operator const hidl_handle&() const
+ operator const hidl_handle&() const // NOLINT(google-explicit-constructor)
{
return mHandle;
}
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 9d0d8d9..ba3d2a6 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -285,7 +285,7 @@
// Composer is a wrapper to IComposer, a proxy to server-side composer.
class Composer final : public Hwc2::Composer {
public:
- Composer(const std::string& serviceName);
+ explicit Composer(const std::string& serviceName);
~Composer() override;
std::vector<IComposer::Capability> getCapabilities() override;
@@ -418,7 +418,7 @@
private:
class CommandWriter : public CommandWriterBase {
public:
- CommandWriter(uint32_t initialMaxSize);
+ explicit CommandWriter(uint32_t initialMaxSize);
~CommandWriter() override;
void setLayerInfo(uint32_t type, uint32_t appId);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 0497571..5b4d347 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -66,6 +66,10 @@
namespace android {
+HWComposer::~HWComposer() = default;
+
+namespace impl {
+
HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer)
: mHwcDevice(std::make_unique<HWC2::Device>(std::move(composer))) {}
@@ -98,6 +102,10 @@
bool HWComposer::hasDisplayCapability(const std::optional<DisplayId>& displayId,
HWC2::DisplayCapability capability) const {
if (!displayId) {
+ // Checkout global capabilities for displays without a corresponding HWC display.
+ if (capability == HWC2::DisplayCapability::SkipClientColorTransform) {
+ return hasCapability(HWC2::Capability::SkipClientColorTransform);
+ }
return false;
}
RETURN_IF_INVALID_DISPLAY(*displayId, false);
@@ -854,4 +862,5 @@
: "External display"};
}
+} // namespace impl
} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index d9a0916..f42f860 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -45,134 +45,273 @@
class Composer;
} // namespace Hwc2
-class HWComposer
-{
+class HWComposer {
+public:
+ virtual ~HWComposer();
+
+ virtual void registerCallback(HWC2::ComposerCallback* callback, int32_t sequenceId) = 0;
+
+ virtual bool getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort,
+ DisplayIdentificationData* outData) const = 0;
+
+ virtual bool hasCapability(HWC2::Capability capability) const = 0;
+ virtual bool hasDisplayCapability(const std::optional<DisplayId>& displayId,
+ HWC2::DisplayCapability capability) const = 0;
+
+ // Attempts to allocate a virtual display and returns its ID if created on the HWC device.
+ virtual std::optional<DisplayId> allocateVirtualDisplay(uint32_t width, uint32_t height,
+ ui::PixelFormat* format) = 0;
+
+ // Attempts to create a new layer on this display
+ virtual HWC2::Layer* createLayer(DisplayId displayId) = 0;
+ // Destroy a previously created layer
+ virtual void destroyLayer(DisplayId displayId, HWC2::Layer* layer) = 0;
+
+ // Asks the HAL what it can do
+ virtual status_t prepare(DisplayId displayId,
+ std::vector<CompositionInfo>& compositionData) = 0;
+
+ virtual status_t setClientTarget(DisplayId displayId, uint32_t slot,
+ const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target,
+ ui::Dataspace dataspace) = 0;
+
+ // Present layers to the display and read releaseFences.
+ virtual status_t presentAndGetReleaseFences(DisplayId displayId) = 0;
+
+ // set power mode
+ virtual status_t setPowerMode(DisplayId displayId, int mode) = 0;
+
+ // set active config
+ virtual status_t setActiveConfig(DisplayId displayId, size_t configId) = 0;
+
+ // Sets a color transform to be applied to the result of composition
+ virtual status_t setColorTransform(DisplayId displayId, const mat4& transform) = 0;
+
+ // reset state when an external, non-virtual display is disconnected
+ virtual void disconnectDisplay(DisplayId displayId) = 0;
+
+ // does this display have layers handled by HWC
+ virtual bool hasDeviceComposition(const std::optional<DisplayId>& displayId) const = 0;
+
+ // does this display have pending request to flip client target
+ virtual bool hasFlipClientTargetRequest(const std::optional<DisplayId>& displayId) const = 0;
+
+ // does this display have layers handled by GLES
+ virtual bool hasClientComposition(const std::optional<DisplayId>& displayId) const = 0;
+
+ // get the present fence received from the last call to present.
+ virtual sp<Fence> getPresentFence(DisplayId displayId) const = 0;
+
+ // Get last release fence for the given layer
+ virtual sp<Fence> getLayerReleaseFence(DisplayId displayId, HWC2::Layer* layer) const = 0;
+
+ // Set the output buffer and acquire fence for a virtual display.
+ // Returns INVALID_OPERATION if displayId is not a virtual display.
+ virtual status_t setOutputBuffer(DisplayId displayId, const sp<Fence>& acquireFence,
+ const sp<GraphicBuffer>& buffer) = 0;
+
+ // After SurfaceFlinger has retrieved the release fences for all the frames,
+ // it can call this to clear the shared pointers in the release fence map
+ virtual void clearReleaseFences(DisplayId displayId) = 0;
+
+ // Fetches the HDR capabilities of the given display
+ virtual status_t getHdrCapabilities(DisplayId displayId, HdrCapabilities* outCapabilities) = 0;
+
+ virtual int32_t getSupportedPerFrameMetadata(DisplayId displayId) const = 0;
+
+ // Returns the available RenderIntent of the given display.
+ virtual std::vector<ui::RenderIntent> getRenderIntents(DisplayId displayId,
+ ui::ColorMode colorMode) const = 0;
+
+ virtual mat4 getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace) = 0;
+
+ // Returns the attributes of the color sampling engine.
+ virtual status_t getDisplayedContentSamplingAttributes(DisplayId displayId,
+ ui::PixelFormat* outFormat,
+ ui::Dataspace* outDataspace,
+ uint8_t* outComponentMask) = 0;
+ virtual status_t setDisplayContentSamplingEnabled(DisplayId displayId, bool enabled,
+ uint8_t componentMask,
+ uint64_t maxFrames) = 0;
+ virtual status_t getDisplayedContentSample(DisplayId displayId, uint64_t maxFrames,
+ uint64_t timestamp,
+ DisplayedFrameStats* outStats) = 0;
+
+ // Events handling ---------------------------------------------------------
+
+ // Returns stable display ID (and display name on connection of new or previously disconnected
+ // display), or std::nullopt if hotplug event was ignored.
+ virtual std::optional<DisplayIdentificationInfo> onHotplug(hwc2_display_t hwcDisplayId,
+ HWC2::Connection connection) = 0;
+
+ virtual bool onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp) = 0;
+ virtual void setVsyncEnabled(DisplayId displayId, HWC2::Vsync enabled) = 0;
+
+ virtual nsecs_t getRefreshTimestamp(DisplayId displayId) const = 0;
+ virtual bool isConnected(DisplayId displayId) const = 0;
+
+ // Non-const because it can update configMap inside of mDisplayData
+ virtual std::vector<std::shared_ptr<const HWC2::Display::Config>> getConfigs(
+ DisplayId displayId) const = 0;
+
+ virtual std::shared_ptr<const HWC2::Display::Config> getActiveConfig(
+ DisplayId displayId) const = 0;
+ virtual int getActiveConfigIndex(DisplayId displayId) const = 0;
+
+ virtual std::vector<ui::ColorMode> getColorModes(DisplayId displayId) const = 0;
+
+ virtual status_t setActiveColorMode(DisplayId displayId, ui::ColorMode mode,
+ ui::RenderIntent renderIntent) = 0;
+
+ virtual bool isUsingVrComposer() const = 0;
+
+ // for debugging ----------------------------------------------------------
+ virtual void dump(std::string& out) const = 0;
+
+ virtual Hwc2::Composer* getComposer() const = 0;
+
+ // TODO(b/74619554): Remove special cases for internal/external display.
+ virtual std::optional<hwc2_display_t> getInternalHwcDisplayId() const = 0;
+ virtual std::optional<hwc2_display_t> getExternalHwcDisplayId() const = 0;
+
+ virtual std::optional<DisplayId> toPhysicalDisplayId(hwc2_display_t hwcDisplayId) const = 0;
+ virtual std::optional<hwc2_display_t> fromPhysicalDisplayId(DisplayId displayId) const = 0;
+};
+
+namespace impl {
+
+class HWComposer final : public android::HWComposer {
public:
explicit HWComposer(std::unique_ptr<Hwc2::Composer> composer);
- ~HWComposer();
+ ~HWComposer() override;
- void registerCallback(HWC2::ComposerCallback* callback,
- int32_t sequenceId);
+ void registerCallback(HWC2::ComposerCallback* callback, int32_t sequenceId) override;
bool getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort,
- DisplayIdentificationData* outData) const;
+ DisplayIdentificationData* outData) const override;
- bool hasCapability(HWC2::Capability capability) const;
+ bool hasCapability(HWC2::Capability capability) const override;
bool hasDisplayCapability(const std::optional<DisplayId>& displayId,
- HWC2::DisplayCapability capability) const;
+ HWC2::DisplayCapability capability) const override;
// Attempts to allocate a virtual display and returns its ID if created on the HWC device.
std::optional<DisplayId> allocateVirtualDisplay(uint32_t width, uint32_t height,
- ui::PixelFormat* format);
+ ui::PixelFormat* format) override;
// Attempts to create a new layer on this display
- HWC2::Layer* createLayer(DisplayId displayId);
+ HWC2::Layer* createLayer(DisplayId displayId) override;
// Destroy a previously created layer
- void destroyLayer(DisplayId displayId, HWC2::Layer* layer);
+ void destroyLayer(DisplayId displayId, HWC2::Layer* layer) override;
// Asks the HAL what it can do
- status_t prepare(DisplayId displayId, std::vector<CompositionInfo>& compositionData);
+ status_t prepare(DisplayId displayId, std::vector<CompositionInfo>& compositionData) override;
status_t setClientTarget(DisplayId displayId, uint32_t slot, const sp<Fence>& acquireFence,
- const sp<GraphicBuffer>& target, ui::Dataspace dataspace);
+ const sp<GraphicBuffer>& target, ui::Dataspace dataspace) override;
// Present layers to the display and read releaseFences.
- status_t presentAndGetReleaseFences(DisplayId displayId);
+ status_t presentAndGetReleaseFences(DisplayId displayId) override;
// set power mode
- status_t setPowerMode(DisplayId displayId, int mode);
+ status_t setPowerMode(DisplayId displayId, int mode) override;
// set active config
- status_t setActiveConfig(DisplayId displayId, size_t configId);
+ status_t setActiveConfig(DisplayId displayId, size_t configId) override;
// Sets a color transform to be applied to the result of composition
- status_t setColorTransform(DisplayId displayId, const mat4& transform);
+ status_t setColorTransform(DisplayId displayId, const mat4& transform) override;
// reset state when an external, non-virtual display is disconnected
- void disconnectDisplay(DisplayId displayId);
+ void disconnectDisplay(DisplayId displayId) override;
// does this display have layers handled by HWC
- bool hasDeviceComposition(const std::optional<DisplayId>& displayId) const;
+ bool hasDeviceComposition(const std::optional<DisplayId>& displayId) const override;
// does this display have pending request to flip client target
- bool hasFlipClientTargetRequest(const std::optional<DisplayId>& displayId) const;
+ bool hasFlipClientTargetRequest(const std::optional<DisplayId>& displayId) const override;
// does this display have layers handled by GLES
- bool hasClientComposition(const std::optional<DisplayId>& displayId) const;
+ bool hasClientComposition(const std::optional<DisplayId>& displayId) const override;
// get the present fence received from the last call to present.
- sp<Fence> getPresentFence(DisplayId displayId) const;
+ sp<Fence> getPresentFence(DisplayId displayId) const override;
// Get last release fence for the given layer
- sp<Fence> getLayerReleaseFence(DisplayId displayId, HWC2::Layer* layer) const;
+ sp<Fence> getLayerReleaseFence(DisplayId displayId, HWC2::Layer* layer) const override;
// Set the output buffer and acquire fence for a virtual display.
// Returns INVALID_OPERATION if displayId is not a virtual display.
status_t setOutputBuffer(DisplayId displayId, const sp<Fence>& acquireFence,
- const sp<GraphicBuffer>& buffer);
+ const sp<GraphicBuffer>& buffer) override;
// After SurfaceFlinger has retrieved the release fences for all the frames,
// it can call this to clear the shared pointers in the release fence map
- void clearReleaseFences(DisplayId displayId);
+ void clearReleaseFences(DisplayId displayId) override;
// Fetches the HDR capabilities of the given display
- status_t getHdrCapabilities(DisplayId displayId, HdrCapabilities* outCapabilities);
+ status_t getHdrCapabilities(DisplayId displayId, HdrCapabilities* outCapabilities) override;
- int32_t getSupportedPerFrameMetadata(DisplayId displayId) const;
+ int32_t getSupportedPerFrameMetadata(DisplayId displayId) const override;
// Returns the available RenderIntent of the given display.
std::vector<ui::RenderIntent> getRenderIntents(DisplayId displayId,
- ui::ColorMode colorMode) const;
+ ui::ColorMode colorMode) const override;
- mat4 getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace);
+ mat4 getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace) override;
// Returns the attributes of the color sampling engine.
status_t getDisplayedContentSamplingAttributes(DisplayId displayId, ui::PixelFormat* outFormat,
ui::Dataspace* outDataspace,
- uint8_t* outComponentMask);
+ uint8_t* outComponentMask) override;
status_t setDisplayContentSamplingEnabled(DisplayId displayId, bool enabled,
- uint8_t componentMask, uint64_t maxFrames);
+ uint8_t componentMask, uint64_t maxFrames) override;
status_t getDisplayedContentSample(DisplayId displayId, uint64_t maxFrames, uint64_t timestamp,
- DisplayedFrameStats* outStats);
+ DisplayedFrameStats* outStats) override;
// Events handling ---------------------------------------------------------
// Returns stable display ID (and display name on connection of new or previously disconnected
// display), or std::nullopt if hotplug event was ignored.
std::optional<DisplayIdentificationInfo> onHotplug(hwc2_display_t hwcDisplayId,
- HWC2::Connection connection);
+ HWC2::Connection connection) override;
- bool onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp);
- void setVsyncEnabled(DisplayId displayId, HWC2::Vsync enabled);
+ bool onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp) override;
+ void setVsyncEnabled(DisplayId displayId, HWC2::Vsync enabled) override;
- nsecs_t getRefreshTimestamp(DisplayId displayId) const;
- bool isConnected(DisplayId displayId) const;
+ nsecs_t getRefreshTimestamp(DisplayId displayId) const override;
+ bool isConnected(DisplayId displayId) const override;
// Non-const because it can update configMap inside of mDisplayData
- std::vector<std::shared_ptr<const HWC2::Display::Config>> getConfigs(DisplayId displayId) const;
+ std::vector<std::shared_ptr<const HWC2::Display::Config>> getConfigs(
+ DisplayId displayId) const override;
- std::shared_ptr<const HWC2::Display::Config> getActiveConfig(DisplayId displayId) const;
- int getActiveConfigIndex(DisplayId displayId) const;
+ std::shared_ptr<const HWC2::Display::Config> getActiveConfig(
+ DisplayId displayId) const override;
+ int getActiveConfigIndex(DisplayId displayId) const override;
- std::vector<ui::ColorMode> getColorModes(DisplayId displayId) const;
+ std::vector<ui::ColorMode> getColorModes(DisplayId displayId) const override;
status_t setActiveColorMode(DisplayId displayId, ui::ColorMode mode,
- ui::RenderIntent renderIntent);
+ ui::RenderIntent renderIntent) override;
- bool isUsingVrComposer() const;
+ bool isUsingVrComposer() const override;
// for debugging ----------------------------------------------------------
- void dump(std::string& out) const;
+ void dump(std::string& out) const override;
- Hwc2::Composer* getComposer() const { return mHwcDevice->getComposer(); }
+ Hwc2::Composer* getComposer() const override { return mHwcDevice->getComposer(); }
// TODO(b/74619554): Remove special cases for internal/external display.
- std::optional<hwc2_display_t> getInternalHwcDisplayId() const { return mInternalHwcDisplayId; }
- std::optional<hwc2_display_t> getExternalHwcDisplayId() const { return mExternalHwcDisplayId; }
+ std::optional<hwc2_display_t> getInternalHwcDisplayId() const override {
+ return mInternalHwcDisplayId;
+ }
+ std::optional<hwc2_display_t> getExternalHwcDisplayId() const override {
+ return mExternalHwcDisplayId;
+ }
- std::optional<DisplayId> toPhysicalDisplayId(hwc2_display_t hwcDisplayId) const;
- std::optional<hwc2_display_t> fromPhysicalDisplayId(DisplayId displayId) const;
+ std::optional<DisplayId> toPhysicalDisplayId(hwc2_display_t hwcDisplayId) const override;
+ std::optional<hwc2_display_t> fromPhysicalDisplayId(DisplayId displayId) const override;
private:
// For unit tests
@@ -223,6 +362,7 @@
uint32_t mRemainingHwcVirtualDisplays{mHwcDevice->getMaxVirtualDisplayCount()};
};
+} // namespace impl
} // namespace android
#endif // ANDROID_SF_HWCOMPOSER_H
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index f4b3cdd..ee49610 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -83,35 +83,35 @@
mTransactionName = String8("TX - ") + mName;
- mState.current.active_legacy.w = args.w;
- mState.current.active_legacy.h = args.h;
- mState.current.flags = layerFlags;
- mState.current.active_legacy.transform.set(0, 0);
- mState.current.crop_legacy.makeInvalid();
- mState.current.requestedCrop_legacy = mState.current.crop_legacy;
- mState.current.z = 0;
- mState.current.color.a = 1.0f;
- mState.current.layerStack = 0;
- mState.current.sequence = 0;
- mState.current.requested_legacy = mState.current.active_legacy;
- mState.current.appId = 0;
- mState.current.type = 0;
- mState.current.active.w = UINT32_MAX;
- mState.current.active.h = UINT32_MAX;
- mState.current.active.transform.set(0, 0);
- mState.current.transform = 0;
- mState.current.transformToDisplayInverse = false;
- mState.current.crop.makeInvalid();
- mState.current.acquireFence = new Fence(-1);
- mState.current.dataspace = ui::Dataspace::UNKNOWN;
- mState.current.hdrMetadata.validTypes = 0;
- mState.current.surfaceDamageRegion.clear();
- mState.current.cornerRadius = 0.0f;
- mState.current.api = -1;
- mState.current.hasColorTransform = false;
+ mCurrentState.active_legacy.w = args.w;
+ mCurrentState.active_legacy.h = args.h;
+ mCurrentState.flags = layerFlags;
+ mCurrentState.active_legacy.transform.set(0, 0);
+ mCurrentState.crop_legacy.makeInvalid();
+ mCurrentState.requestedCrop_legacy = mCurrentState.crop_legacy;
+ mCurrentState.z = 0;
+ mCurrentState.color.a = 1.0f;
+ mCurrentState.layerStack = 0;
+ mCurrentState.sequence = 0;
+ mCurrentState.requested_legacy = mCurrentState.active_legacy;
+ mCurrentState.appId = 0;
+ mCurrentState.type = 0;
+ mCurrentState.active.w = UINT32_MAX;
+ mCurrentState.active.h = UINT32_MAX;
+ mCurrentState.active.transform.set(0, 0);
+ mCurrentState.transform = 0;
+ mCurrentState.transformToDisplayInverse = false;
+ mCurrentState.crop.makeInvalid();
+ mCurrentState.acquireFence = new Fence(-1);
+ mCurrentState.dataspace = ui::Dataspace::UNKNOWN;
+ mCurrentState.hdrMetadata.validTypes = 0;
+ mCurrentState.surfaceDamageRegion.clear();
+ mCurrentState.cornerRadius = 0.0f;
+ mCurrentState.api = -1;
+ mCurrentState.hasColorTransform = false;
// drawing state & current state are identical
- mState.drawing = mState.current;
+ mDrawingState = mCurrentState;
CompositorTiming compositorTiming;
args.flinger->getCompositorTiming(&compositorTiming);
@@ -148,17 +148,14 @@
void Layer::onRemovedFromCurrentState() {
mRemovedFromCurrentState = true;
- {
- Mutex::Autolock lock(mStateMutex);
- // the layer is removed from SF mState.current to mLayersPendingRemoval
- if (mState.current.zOrderRelativeOf != nullptr) {
- sp<Layer> strongRelative = mState.current.zOrderRelativeOf.promote();
- if (strongRelative != nullptr) {
- strongRelative->removeZOrderRelative(this);
- mFlinger->setTransactionFlags(eTraversalNeeded);
- }
- mState.current.zOrderRelativeOf = nullptr;
+ // the layer is removed from SF mCurrentState to mLayersPendingRemoval
+ if (mCurrentState.zOrderRelativeOf != nullptr) {
+ sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
+ if (strongRelative != nullptr) {
+ strongRelative->removeZOrderRelative(this);
+ mFlinger->setTransactionFlags(eTraversalNeeded);
}
+ mCurrentState.zOrderRelativeOf = nullptr;
}
// Since we are no longer reachable from CurrentState SurfaceFlinger
@@ -182,6 +179,8 @@
for (const auto& child : mCurrentChildren) {
child->onRemovedFromCurrentState();
}
+
+ mFlinger->markLayerPendingRemovalLocked(this);
}
void Layer::addToCurrentState() {
@@ -297,32 +296,21 @@
}
Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const {
- Mutex::Autolock lock(mStateMutex);
const State& s(getDrawingState());
Region transparentRegion = reduceTransparentRegion ? getActiveTransparentRegion(s) : Region();
- FloatRect bounds = computeBoundsLocked(transparentRegion);
- ui::Transform t = getTransformLocked();
+ FloatRect bounds = computeBounds(transparentRegion);
+ ui::Transform t = getTransform();
// Transform to screen space.
bounds = t.transform(bounds);
return Rect{bounds};
}
FloatRect Layer::computeBounds() const {
- Mutex::Autolock lock(mStateMutex);
- return computeBoundsLocked();
-}
-
-FloatRect Layer::computeBoundsLocked() const {
const State& s(getDrawingState());
- return computeBoundsLocked(getActiveTransparentRegion(s));
+ return computeBounds(getActiveTransparentRegion(s));
}
FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const {
- Mutex::Autolock lock(mStateMutex);
- return computeBoundsLocked(activeTransparentRegion);
-}
-
-FloatRect Layer::computeBoundsLocked(const Region& activeTransparentRegion) const {
const State& s(getDrawingState());
Rect bounds = getCroppedBufferSize(s);
FloatRect floatBounds = bounds.toFloatRect();
@@ -375,7 +363,6 @@
// child bounds as well.
ui::Transform t = s.active_legacy.transform;
croppedBounds = t.transform(croppedBounds);
- Mutex::Autolock lock(p->mStateMutex);
croppedBounds = p->cropChildBounds(croppedBounds);
croppedBounds = t.inverse().transform(croppedBounds);
}
@@ -393,7 +380,7 @@
return size;
}
-Rect Layer::computeInitialCrop(const sp<const DisplayDevice>& display) const {
+Rect Layer::computeInitialCrop(const Rect& windowBounds) const {
// the crop is the area of the window that gets cropped, but not
// scaled in any ways.
const State& s(getDrawingState());
@@ -403,13 +390,18 @@
// if there are no window scaling involved, this operation will map to full
// pixels in the buffer.
- FloatRect activeCropFloat = computeBoundsLocked();
- ui::Transform t = getTransformLocked();
- // Transform to screen space.
- activeCropFloat = t.transform(activeCropFloat);
- activeCropFloat = activeCropFloat.intersect(display->getViewport().toFloatRect());
- // Back to layer space to work with the content crop.
- activeCropFloat = t.inverse().transform(activeCropFloat);
+ FloatRect activeCropFloat = computeBounds();
+
+ // If we have valid window boundaries then we need to crop to the window
+ // boundaries in layer space.
+ if (windowBounds.isValid()) {
+ const ui::Transform t = getTransform();
+ // Transform to screen space.
+ activeCropFloat = t.transform(activeCropFloat);
+ activeCropFloat = activeCropFloat.intersect(windowBounds.toFloatRect());
+ // Back to layer space to work with the content crop.
+ activeCropFloat = t.inverse().transform(activeCropFloat);
+ }
// This needs to be here as transform.transform(Rect) computes the
// transformed rect and then takes the bounding box of the result before
// returning. This means
@@ -439,7 +431,7 @@
cropCoords[3] = vec2(win.right, win.top);
}
-FloatRect Layer::computeCrop(const sp<const DisplayDevice>& display) const {
+FloatRect Layer::computeCrop(const Rect& windowBounds) const {
// the content crop is the area of the content that gets scaled to the
// layer's size. This is in buffer space.
FloatRect crop = getContentCrop().toFloatRect();
@@ -447,14 +439,14 @@
// In addition there is a WM-specified crop we pull from our drawing state.
const State& s(getDrawingState());
- Rect activeCrop = computeInitialCrop(display);
+ Rect activeCrop = computeInitialCrop(windowBounds);
Rect bufferSize = getBufferSize(s);
// Transform the window crop to match the buffer coordinate system,
// which means using the inverse of the current transform set on the
// SurfaceFlingerConsumer.
uint32_t invTransform = mCurrentTransform;
- if (getTransformToDisplayInverseLocked()) {
+ if (getTransformToDisplayInverse()) {
/*
* the code below applies the primary display's inverse transform to the
* buffer
@@ -505,7 +497,6 @@
}
void Layer::setGeometry(const sp<const DisplayDevice>& display, uint32_t z) {
- Mutex::Autolock lock(mStateMutex);
const auto displayId = display->getId();
LOG_ALWAYS_FATAL_IF(!displayId);
RETURN_IF_NO_HWC_LAYER(*displayId);
@@ -514,7 +505,7 @@
// enable this layer
hwcInfo.forceClientComposition = false;
- if (isSecureLocked() && !display->isSecure()) {
+ if (isSecure() && !display->isSecure()) {
hwcInfo.forceClientComposition = true;
}
@@ -524,7 +515,7 @@
const State& s(getDrawingState());
const Rect bufferSize = getBufferSize(s);
auto blendMode = HWC2::BlendMode::None;
- if (!isOpaque(s) || getAlphaLocked() != 1.0f) {
+ if (!isOpaque(s) || getAlpha() != 1.0f) {
blendMode =
mPremultipliedAlpha ? HWC2::BlendMode::Premultiplied : HWC2::BlendMode::Coverage;
}
@@ -539,7 +530,7 @@
// apply the layer's transform, followed by the display's global transform
// here we're guaranteed that the layer's transform preserves rects
Region activeTransparentRegion(getActiveTransparentRegion(s));
- ui::Transform t = getTransformLocked();
+ ui::Transform t = getTransform();
Rect activeCrop = getCrop(s);
if (!activeCrop.isEmpty() && bufferSize.isValid()) {
activeCrop = t.transform(activeCrop);
@@ -567,7 +558,7 @@
// computeBounds returns a FloatRect to provide more accuracy during the
// transformation. We then round upon constructing 'frame'.
- Rect frame{t.transform(computeBoundsLocked(activeTransparentRegion))};
+ Rect frame{t.transform(computeBounds(activeTransparentRegion))};
if (!frame.intersect(display->getViewport(), &frame)) {
frame.clear();
}
@@ -595,7 +586,7 @@
}
getBE().compositionInfo.hwc.sourceCrop = sourceCrop;
- float alpha = static_cast<float>(getAlphaLocked());
+ float alpha = static_cast<float>(getAlpha());
error = hwcLayer->setPlaneAlpha(alpha);
ALOGE_IF(error != HWC2::Error::None,
"[%s] Failed to set plane alpha %.3f: "
@@ -612,7 +603,6 @@
int appId = s.appId;
sp<Layer> parent = mDrawingParent.promote();
if (parent.get()) {
- Mutex::Autolock lock(parent->mStateMutex);
auto& parentState = parent->getDrawingState();
if (parentState.type >= 0 || parentState.appId >= 0) {
type = parentState.type;
@@ -638,7 +628,7 @@
const ui::Transform bufferOrientation(mCurrentTransform);
ui::Transform transform(tr * t * bufferOrientation);
- if (getTransformToDisplayInverseLocked()) {
+ if (getTransformToDisplayInverse()) {
/*
* the code below applies the primary display's inverse transform to the
* buffer
@@ -688,7 +678,6 @@
}
void Layer::updateCursorPosition(const sp<const DisplayDevice>& display) {
- Mutex::Autolock lock(mStateMutex);
const auto displayId = display->getId();
LOG_ALWAYS_FATAL_IF(!displayId);
if (!hasHwcLayer(*displayId) || getCompositionType(displayId) != HWC2::Composition::Cursor) {
@@ -703,7 +692,7 @@
Rect win = getCroppedBufferSize(s);
// Subtract the transparent region and snap to the bounds
Rect bounds = reduce(win, getActiveTransparentRegion(s));
- Rect frame(getTransformLocked().transform(bounds));
+ Rect frame(getTransform().transform(bounds));
frame.intersect(display->getViewport(), &frame);
auto& displayTransform = display->getTransform();
auto position = displayTransform.transform(frame);
@@ -733,7 +722,6 @@
void Layer::clearWithOpenGL(const RenderArea& renderArea, float red, float green, float blue,
float alpha) const {
auto& engine(mFlinger->getRenderEngine());
- Mutex::Autolock lock(mStateMutex);
computeGeometry(renderArea, getBE().mMesh, false);
engine.setupFillWithColor(red, green, blue, alpha);
engine.drawMesh(getBE().mMesh);
@@ -818,14 +806,14 @@
renderengine::Mesh& mesh,
bool useIdentityTransform) const {
const ui::Transform renderAreaTransform(renderArea.getTransform());
- FloatRect win = computeBoundsLocked();
+ FloatRect win = computeBounds();
vec2 lt = vec2(win.left, win.top);
vec2 lb = vec2(win.left, win.bottom);
vec2 rb = vec2(win.right, win.bottom);
vec2 rt = vec2(win.right, win.top);
- ui::Transform layerTransform = getTransformLocked();
+ ui::Transform layerTransform = getTransform();
if (!useIdentityTransform) {
lt = layerTransform.transform(lt);
lb = layerTransform.transform(lb);
@@ -841,12 +829,7 @@
}
bool Layer::isSecure() const {
- Mutex::Autolock lock(mStateMutex);
- return isSecureLocked();
-}
-
-bool Layer::isSecureLocked() const {
- const State& s(mState.drawing);
+ const State& s(mDrawingState);
return (s.flags & layer_state_t::eLayerSecure);
}
@@ -874,13 +857,9 @@
// ----------------------------------------------------------------------------
// transaction
// ----------------------------------------------------------------------------
-void Layer::pushPendingState() {
- Mutex::Autolock lock(mStateMutex);
- pushPendingStateLocked();
-}
-void Layer::pushPendingStateLocked() {
- if (!mState.current.modified) {
+void Layer::pushPendingState() {
+ if (!mCurrentState.modified) {
return;
}
@@ -888,22 +867,22 @@
// point and send it to the remote layer.
// We don't allow installing sync points after we are removed from the current state
// as we won't be able to signal our end.
- if (mState.current.barrierLayer_legacy != nullptr && !isRemovedFromCurrentState()) {
- sp<Layer> barrierLayer = mState.current.barrierLayer_legacy.promote();
+ if (mCurrentState.barrierLayer_legacy != nullptr && !isRemovedFromCurrentState()) {
+ sp<Layer> barrierLayer = mCurrentState.barrierLayer_legacy.promote();
if (barrierLayer == nullptr) {
ALOGE("[%s] Unable to promote barrier Layer.", mName.string());
// If we can't promote the layer we are intended to wait on,
// then it is expired or otherwise invalid. Allow this transaction
// to be applied as per normal (no synchronization).
- mState.current.barrierLayer_legacy = nullptr;
+ mCurrentState.barrierLayer_legacy = nullptr;
} else {
- auto syncPoint = std::make_shared<SyncPoint>(mState.current.frameNumber_legacy);
+ auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.frameNumber_legacy);
if (barrierLayer->addSyncPoint(syncPoint)) {
mRemoteSyncPoints.push_back(std::move(syncPoint));
} else {
// We already missed the frame we're supposed to synchronize
// on, so go ahead and apply the state update
- mState.current.barrierLayer_legacy = nullptr;
+ mCurrentState.barrierLayer_legacy = nullptr;
}
}
@@ -911,21 +890,21 @@
setTransactionFlags(eTransactionNeeded);
mFlinger->setTransactionFlags(eTraversalNeeded);
}
- mState.pending.push_back(mState.current);
- ATRACE_INT(mTransactionName.string(), mState.pending.size());
+ mPendingStates.push_back(mCurrentState);
+ ATRACE_INT(mTransactionName.string(), mPendingStates.size());
}
void Layer::popPendingState(State* stateToCommit) {
- *stateToCommit = mState.pending[0];
+ *stateToCommit = mPendingStates[0];
- mState.pending.removeAt(0);
- ATRACE_INT(mTransactionName.string(), mState.pending.size());
+ mPendingStates.removeAt(0);
+ ATRACE_INT(mTransactionName.string(), mPendingStates.size());
}
bool Layer::applyPendingStates(State* stateToCommit) {
bool stateUpdateAvailable = false;
- while (!mState.pending.empty()) {
- if (mState.pending[0].barrierLayer_legacy != nullptr) {
+ while (!mPendingStates.empty()) {
+ if (mPendingStates[0].barrierLayer_legacy != nullptr) {
if (mRemoteSyncPoints.empty()) {
// If we don't have a sync point for this, apply it anyway. It
// will be visually wrong, but it should keep us from getting
@@ -937,7 +916,7 @@
}
if (mRemoteSyncPoints.front()->getFrameNumber() !=
- mState.pending[0].frameNumber_legacy) {
+ mPendingStates[0].frameNumber_legacy) {
ALOGE("[%s] Unexpected sync point frame number found", mName.string());
// Signal our end of the sync point and then dispose of it
@@ -965,12 +944,12 @@
// If we still have pending updates, wake SurfaceFlinger back up and point
// it at this layer so we can process them
- if (!mState.pending.empty()) {
+ if (!mPendingStates.empty()) {
setTransactionFlags(eTransactionNeeded);
mFlinger->setTransactionFlags(eTraversalNeeded);
}
- mState.current.modified = false;
+ mCurrentState.modified = false;
return stateUpdateAvailable;
}
@@ -1067,8 +1046,7 @@
return 0;
}
- Mutex::Autolock lock(mStateMutex);
- pushPendingStateLocked();
+ pushPendingState();
State c = getCurrentState();
if (!applyPendingStates(&c)) {
return 0;
@@ -1100,60 +1078,49 @@
clearSyncPoints();
}
- if (mState.current.inputInfoChanged) {
+ if (mCurrentState.inputInfoChanged) {
flags |= eInputInfoChanged;
- mState.current.inputInfoChanged = false;
+ mCurrentState.inputInfoChanged = false;
}
// Commit the transaction
commitTransaction(c);
- mState.current.callbackHandles = {};
+ mCurrentState.callbackHandles = {};
return flags;
}
void Layer::commitTransaction(const State& stateToCommit) {
- mState.drawing = stateToCommit;
-}
-
-uint32_t Layer::getTransactionFlags() const {
- Mutex::Autolock lock(mStateMutex);
- return mState.transactionFlags;
+ mDrawingState = stateToCommit;
}
uint32_t Layer::getTransactionFlags(uint32_t flags) {
- Mutex::Autolock lock(mStateMutex);
- uint32_t and_flags = mState.transactionFlags & flags;
- mState.transactionFlags &= ~flags;
- return and_flags;
+ return mTransactionFlags.fetch_and(~flags) & flags;
}
uint32_t Layer::setTransactionFlags(uint32_t flags) {
- uint32_t old_flags = mState.transactionFlags;
- mState.transactionFlags |= flags;
- return old_flags;
+ return mTransactionFlags.fetch_or(flags);
}
bool Layer::setPosition(float x, float y, bool immediate) {
- Mutex::Autolock lock(mStateMutex);
- if (mState.current.requested_legacy.transform.tx() == x &&
- mState.current.requested_legacy.transform.ty() == y)
+ if (mCurrentState.requested_legacy.transform.tx() == x &&
+ mCurrentState.requested_legacy.transform.ty() == y)
return false;
- mState.current.sequence++;
+ mCurrentState.sequence++;
// We update the requested and active position simultaneously because
// we want to apply the position portion of the transform matrix immediately,
// but still delay scaling when resizing a SCALING_MODE_FREEZE layer.
- mState.current.requested_legacy.transform.set(x, y);
+ mCurrentState.requested_legacy.transform.set(x, y);
if (immediate && !mFreezeGeometryUpdates) {
// Here we directly update the active state
// unlike other setters, because we store it within
// the transform, but use different latching rules.
// b/38182305
- mState.current.active_legacy.transform.set(x, y);
+ mCurrentState.active_legacy.transform.set(x, y);
}
mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate;
- mState.current.modified = true;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
@@ -1186,44 +1153,38 @@
}
bool Layer::setLayer(int32_t z) {
- Mutex::Autolock lock(mStateMutex);
- if (mState.current.z == z && !usingRelativeZLocked(LayerVector::StateSet::Current))
- return false;
-
- mState.current.sequence++;
- mState.current.z = z;
- mState.current.modified = true;
+ if (mCurrentState.z == z && !usingRelativeZ(LayerVector::StateSet::Current)) return false;
+ mCurrentState.sequence++;
+ mCurrentState.z = z;
+ mCurrentState.modified = true;
// Discard all relative layering.
- if (mState.current.zOrderRelativeOf != nullptr) {
- sp<Layer> strongRelative = mState.current.zOrderRelativeOf.promote();
+ if (mCurrentState.zOrderRelativeOf != nullptr) {
+ sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
if (strongRelative != nullptr) {
strongRelative->removeZOrderRelative(this);
}
- mState.current.zOrderRelativeOf = nullptr;
+ mCurrentState.zOrderRelativeOf = nullptr;
}
setTransactionFlags(eTransactionNeeded);
return true;
}
void Layer::removeZOrderRelative(const wp<Layer>& relative) {
- Mutex::Autolock lock(mStateMutex);
- mState.current.zOrderRelatives.remove(relative);
- mState.current.sequence++;
- mState.current.modified = true;
+ mCurrentState.zOrderRelatives.remove(relative);
+ mCurrentState.sequence++;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
}
void Layer::addZOrderRelative(const wp<Layer>& relative) {
- Mutex::Autolock lock(mStateMutex);
- mState.current.zOrderRelatives.add(relative);
- mState.current.modified = true;
- mState.current.sequence++;
+ mCurrentState.zOrderRelatives.add(relative);
+ mCurrentState.modified = true;
+ mCurrentState.sequence++;
setTransactionFlags(eTransactionNeeded);
}
bool Layer::setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ) {
- Mutex::Autolock lock(mStateMutex);
sp<Handle> handle = static_cast<Handle*>(relativeToHandle.get());
if (handle == nullptr) {
return false;
@@ -1233,20 +1194,20 @@
return false;
}
- if (mState.current.z == relativeZ && usingRelativeZLocked(LayerVector::StateSet::Current) &&
- mState.current.zOrderRelativeOf == relative) {
+ if (mCurrentState.z == relativeZ && usingRelativeZ(LayerVector::StateSet::Current) &&
+ mCurrentState.zOrderRelativeOf == relative) {
return false;
}
- mState.current.sequence++;
- mState.current.modified = true;
- mState.current.z = relativeZ;
+ mCurrentState.sequence++;
+ mCurrentState.modified = true;
+ mCurrentState.z = relativeZ;
- auto oldZOrderRelativeOf = mState.current.zOrderRelativeOf.promote();
+ auto oldZOrderRelativeOf = mCurrentState.zOrderRelativeOf.promote();
if (oldZOrderRelativeOf != nullptr) {
oldZOrderRelativeOf->removeZOrderRelative(this);
}
- mState.current.zOrderRelativeOf = relative;
+ mCurrentState.zOrderRelativeOf = relative;
relative->addZOrderRelative(this);
setTransactionFlags(eTransactionNeeded);
@@ -1255,51 +1216,47 @@
}
bool Layer::setSize(uint32_t w, uint32_t h) {
- Mutex::Autolock lock(mStateMutex);
- if (mState.current.requested_legacy.w == w && mState.current.requested_legacy.h == h)
+ if (mCurrentState.requested_legacy.w == w && mCurrentState.requested_legacy.h == h)
return false;
- mState.current.requested_legacy.w = w;
- mState.current.requested_legacy.h = h;
- mState.current.modified = true;
+ mCurrentState.requested_legacy.w = w;
+ mCurrentState.requested_legacy.h = h;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
// record the new size, from this point on, when the client request
// a buffer, it'll get the new size.
- setDefaultBufferSize(mState.current.requested_legacy.w, mState.current.requested_legacy.h);
+ setDefaultBufferSize(mCurrentState.requested_legacy.w, mCurrentState.requested_legacy.h);
return true;
}
bool Layer::setAlpha(float alpha) {
- Mutex::Autolock lock(mStateMutex);
- if (mState.current.color.a == alpha) return false;
- mState.current.sequence++;
- mState.current.color.a = alpha;
- mState.current.modified = true;
+ if (mCurrentState.color.a == alpha) return false;
+ mCurrentState.sequence++;
+ mCurrentState.color.a = alpha;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
bool Layer::setColor(const half3& color) {
- Mutex::Autolock lock(mStateMutex);
- if (color.r == mState.current.color.r && color.g == mState.current.color.g &&
- color.b == mState.current.color.b)
+ if (color.r == mCurrentState.color.r && color.g == mCurrentState.color.g &&
+ color.b == mCurrentState.color.b)
return false;
- mState.current.sequence++;
- mState.current.color.r = color.r;
- mState.current.color.g = color.g;
- mState.current.color.b = color.b;
- mState.current.modified = true;
+ mCurrentState.sequence++;
+ mCurrentState.color.r = color.r;
+ mCurrentState.color.g = color.g;
+ mCurrentState.color.b = color.b;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
bool Layer::setCornerRadius(float cornerRadius) {
- Mutex::Autolock lock(mStateMutex);
- if (mState.current.cornerRadius == cornerRadius) return false;
+ if (mCurrentState.cornerRadius == cornerRadius) return false;
- mState.current.sequence++;
- mState.current.cornerRadius = cornerRadius;
- mState.current.modified = true;
+ mCurrentState.sequence++;
+ mCurrentState.cornerRadius = cornerRadius;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
@@ -1313,50 +1270,45 @@
ALOGW("Attempt to set rotation matrix without permission ACCESS_SURFACE_FLINGER ignored");
return false;
}
- Mutex::Autolock lock(mStateMutex);
- mState.current.sequence++;
- mState.current.requested_legacy.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx,
- matrix.dsdy);
- mState.current.modified = true;
+ mCurrentState.sequence++;
+ mCurrentState.requested_legacy.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx,
+ matrix.dsdy);
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
bool Layer::setTransparentRegionHint(const Region& transparent) {
- Mutex::Autolock lock(mStateMutex);
- mState.current.requestedTransparentRegion_legacy = transparent;
- mState.current.modified = true;
+ mCurrentState.requestedTransparentRegion_legacy = transparent;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
bool Layer::setFlags(uint8_t flags, uint8_t mask) {
- Mutex::Autolock lock(mStateMutex);
- const uint32_t newFlags = (mState.current.flags & ~mask) | (flags & mask);
- if (mState.current.flags == newFlags) return false;
- mState.current.sequence++;
- mState.current.flags = newFlags;
- mState.current.modified = true;
+ const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask);
+ if (mCurrentState.flags == newFlags) return false;
+ mCurrentState.sequence++;
+ mCurrentState.flags = newFlags;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
bool Layer::setCrop_legacy(const Rect& crop, bool immediate) {
- Mutex::Autolock lock(mStateMutex);
- if (mState.current.requestedCrop_legacy == crop) return false;
- mState.current.sequence++;
- mState.current.requestedCrop_legacy = crop;
+ if (mCurrentState.requestedCrop_legacy == crop) return false;
+ mCurrentState.sequence++;
+ mCurrentState.requestedCrop_legacy = crop;
if (immediate && !mFreezeGeometryUpdates) {
- mState.current.crop_legacy = crop;
+ mCurrentState.crop_legacy = crop;
}
mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate;
- mState.current.modified = true;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
bool Layer::setOverrideScalingMode(int32_t scalingMode) {
- Mutex::Autolock lock(mStateMutex);
if (scalingMode == mOverrideScalingMode) return false;
mOverrideScalingMode = scalingMode;
setTransactionFlags(eTransactionNeeded);
@@ -1364,29 +1316,22 @@
}
void Layer::setInfo(int32_t type, int32_t appId) {
- Mutex::Autolock lock(mStateMutex);
- mState.current.appId = appId;
- mState.current.type = type;
- mState.current.modified = true;
+ mCurrentState.appId = appId;
+ mCurrentState.type = type;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
}
bool Layer::setLayerStack(uint32_t layerStack) {
- Mutex::Autolock lock(mStateMutex);
- if (mState.current.layerStack == layerStack) return false;
- mState.current.sequence++;
- mState.current.layerStack = layerStack;
- mState.current.modified = true;
+ if (mCurrentState.layerStack == layerStack) return false;
+ mCurrentState.sequence++;
+ mCurrentState.layerStack = layerStack;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
uint32_t Layer::getLayerStack() const {
- Mutex::Autolock lock(mStateMutex);
- return getLayerStackLocked();
-}
-
-uint32_t Layer::getLayerStackLocked() const {
auto p = mDrawingParent.promote();
if (p == nullptr) {
return getDrawingState().layerStack;
@@ -1395,16 +1340,15 @@
}
void Layer::deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber) {
- Mutex::Autolock lock(mStateMutex);
- mState.current.barrierLayer_legacy = barrierLayer;
- mState.current.frameNumber_legacy = frameNumber;
+ mCurrentState.barrierLayer_legacy = barrierLayer;
+ mCurrentState.frameNumber_legacy = frameNumber;
// We don't set eTransactionNeeded, because just receiving a deferral
// request without any other state updates shouldn't actually induce a delay
- mState.current.modified = true;
- pushPendingStateLocked();
- mState.current.barrierLayer_legacy = nullptr;
- mState.current.frameNumber_legacy = 0;
- mState.current.modified = false;
+ mCurrentState.modified = true;
+ pushPendingState();
+ mCurrentState.barrierLayer_legacy = nullptr;
+ mCurrentState.frameNumber_legacy = 0;
+ mCurrentState.modified = false;
}
void Layer::deferTransactionUntil_legacy(const sp<IBinder>& barrierHandle, uint64_t frameNumber) {
@@ -1417,8 +1361,7 @@
// ----------------------------------------------------------------------------
bool Layer::isHiddenByPolicy() const {
- Mutex::Autolock lock(mStateMutex);
- const State& s(mState.drawing);
+ const State& s(mDrawingState);
const auto& parent = mDrawingParent.promote();
if (parent != nullptr && parent->isHiddenByPolicy()) {
return true;
@@ -1463,7 +1406,6 @@
// TODO(marissaw): add new layer state info to layer debugging
LayerDebugInfo Layer::getLayerDebugInfo() const {
- Mutex::Autolock lock(mStateMutex);
LayerDebugInfo info;
const State& ds = getDrawingState();
info.mName = getName();
@@ -1473,7 +1415,7 @@
info.mTransparentRegion = ds.activeTransparentRegion_legacy;
info.mVisibleRegion = visibleRegion;
info.mSurfaceDamageRegion = surfaceDamageRegion;
- info.mLayerStack = getLayerStackLocked();
+ info.mLayerStack = getLayerStack();
info.mX = ds.active_legacy.transform.tx();
info.mY = ds.active_legacy.transform.ty();
info.mZ = ds.z;
@@ -1509,13 +1451,6 @@
return info;
}
-std::tuple<uint32_t, int32_t> Layer::getLayerStackAndZ(StateSet stateSet) {
- Mutex::Autolock lock(mStateMutex);
- const State& state = (stateSet == StateSet::Current) ? mState.current : mState.drawing;
-
- return {state.layerStack, state.z};
-}
-
void Layer::miniDumpHeader(std::string& result) {
result.append("-------------------------------");
result.append("-------------------------------");
@@ -1532,7 +1467,6 @@
}
void Layer::miniDump(std::string& result, DisplayId displayId) const {
- Mutex::Autolock lock(mStateMutex);
if (!hasHwcLayer(displayId)) {
return;
}
@@ -1644,6 +1578,7 @@
ssize_t Layer::removeChild(const sp<Layer>& layer) {
layer->setParent(nullptr);
+
return mCurrentChildren.remove(layer);
}
@@ -1661,16 +1596,10 @@
}
if (attachChildren()) {
- Mutex::Autolock lock(mStateMutex);
setTransactionFlags(eTransactionNeeded);
}
for (const sp<Layer>& child : mCurrentChildren) {
newParent->addChild(child);
-
- sp<Client> client(child->mClientRef.promote());
- if (client != nullptr) {
- client->updateParent(newParent);
- }
}
mCurrentChildren.clear();
@@ -1684,14 +1613,14 @@
}
bool Layer::reparent(const sp<IBinder>& newParentHandle) {
- if (newParentHandle == nullptr) {
- return false;
- }
+ bool callSetTransactionFlags = false;
- auto handle = static_cast<Handle*>(newParentHandle.get());
- sp<Layer> newParent = handle->owner.promote();
- if (newParent == nullptr) {
- ALOGE("Unable to promote Layer handle");
+ // While layers are detached, we allow most operations
+ // and simply halt performing the actual transaction. However
+ // for reparent != null we would enter the mRemovedFromCurrentState
+ // state, regardless of whether doTransaction was called, and
+ // so we need to prevent the update here.
+ if (mLayerDetached && newParentHandle == nullptr) {
return false;
}
@@ -1699,25 +1628,31 @@
if (parent != nullptr) {
parent->removeChild(this);
}
- newParent->addChild(this);
- if (!newParent->isRemovedFromCurrentState()) {
- addToCurrentState();
+ if (newParentHandle != nullptr) {
+ auto handle = static_cast<Handle*>(newParentHandle.get());
+ sp<Layer> newParent = handle->owner.promote();
+ if (newParent == nullptr) {
+ ALOGE("Unable to promote Layer handle");
+ return false;
+ }
+
+ newParent->addChild(this);
+ if (!newParent->isRemovedFromCurrentState()) {
+ addToCurrentState();
+ } else {
+ onRemovedFromCurrentState();
+ }
+
+ if (mLayerDetached) {
+ mLayerDetached = false;
+ callSetTransactionFlags = true;
+ }
+ } else {
+ onRemovedFromCurrentState();
}
- sp<Client> client(mClientRef.promote());
- sp<Client> newParentClient(newParent->mClientRef.promote());
-
- if (client != newParentClient) {
- client->updateParent(newParent);
- }
-
- Mutex::Autolock lock(mStateMutex);
- if (mLayerDetached) {
- mLayerDetached = false;
- setTransactionFlags(eTransactionNeeded);
- }
- if (attachChildren()) {
+ if (callSetTransactionFlags || attachChildren()) {
setTransactionFlags(eTransactionNeeded);
}
return true;
@@ -1756,24 +1691,18 @@
bool Layer::setColorTransform(const mat4& matrix) {
static const mat4 identityMatrix = mat4();
- Mutex::Autolock lock(mStateMutex);
- if (mState.current.colorTransform == matrix) {
+ if (mCurrentState.colorTransform == matrix) {
return false;
}
- ++mState.current.sequence;
- mState.current.colorTransform = matrix;
- mState.current.hasColorTransform = matrix != identityMatrix;
- mState.current.modified = true;
+ ++mCurrentState.sequence;
+ mCurrentState.colorTransform = matrix;
+ mCurrentState.hasColorTransform = matrix != identityMatrix;
+ mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
mat4 Layer::getColorTransform() const {
- Mutex::Autolock lock(mStateMutex);
- return getColorTransformLocked();
-}
-
-mat4 Layer::getColorTransformLocked() const {
mat4 colorTransform = mat4(getDrawingState().colorTransform);
if (sp<Layer> parent = mDrawingParent.promote(); parent != nullptr) {
colorTransform = parent->getColorTransform() * colorTransform;
@@ -1782,7 +1711,6 @@
}
bool Layer::hasColorTransform() const {
- Mutex::Autolock lock(mStateMutex);
bool hasColorTransform = getDrawingState().hasColorTransform;
if (sp<Layer> parent = mDrawingParent.promote(); parent != nullptr) {
hasColorTransform = hasColorTransform || parent->hasColorTransform();
@@ -1813,18 +1741,12 @@
}
int32_t Layer::getZ() const {
- Mutex::Autolock lock(mStateMutex);
- return mState.drawing.z;
+ return mDrawingState.z;
}
bool Layer::usingRelativeZ(LayerVector::StateSet stateSet) {
- Mutex::Autolock lock(mStateMutex);
- return usingRelativeZLocked(stateSet);
-}
-
-bool Layer::usingRelativeZLocked(LayerVector::StateSet stateSet) {
const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
- const State& state = useDrawing ? mState.drawing : mState.current;
+ const State& state = useDrawing ? mDrawingState : mCurrentState;
return state.zOrderRelativeOf != nullptr;
}
@@ -1834,7 +1756,7 @@
"makeTraversalList received invalid stateSet");
const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
- const State& state = useDrawing ? mState.drawing : mState.current;
+ const State& state = useDrawing ? mDrawingState : mCurrentState;
if (state.zOrderRelatives.size() == 0) {
*outSkipRelativeZUsers = true;
@@ -1850,7 +1772,7 @@
}
for (const sp<Layer>& child : children) {
- const State& childState = useDrawing ? child->mState.drawing : child->mState.current;
+ const State& childState = useDrawing ? child->mDrawingState : child->mCurrentState;
if (childState.zOrderRelativeOf != nullptr) {
continue;
}
@@ -1889,6 +1811,7 @@
visitor(this);
for (; i < list.size(); i++) {
const auto& relative = list[i];
+
if (skipRelativeZUsers && relative->usingRelativeZ(stateSet)) {
continue;
}
@@ -1936,7 +1859,7 @@
"makeTraversalList received invalid stateSet");
const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
- const State& state = useDrawing ? mState.drawing : mState.current;
+ const State& state = useDrawing ? mDrawingState : mCurrentState;
LayerVector traverse(stateSet);
for (const wp<Layer>& weakRelative : state.zOrderRelatives) {
@@ -1949,7 +1872,7 @@
}
for (const sp<Layer>& child : children) {
- const State& childState = useDrawing ? child->mState.drawing : child->mState.current;
+ const State& childState = useDrawing ? child->mDrawingState : child->mCurrentState;
// If a layer has a relativeOf layer, only ignore if the layer it's relative to is a
// descendent of the top most parent of the tree. If it's not a descendent, then just add
// the child here since it won't be added later as a relative.
@@ -2006,16 +1929,10 @@
}
ui::Transform Layer::getTransform() const {
- Mutex::Autolock lock(mStateMutex);
- return getTransformLocked();
-}
-
-ui::Transform Layer::getTransformLocked() const {
ui::Transform t;
const auto& p = mDrawingParent.promote();
if (p != nullptr) {
- Mutex::Autolock lock(p->mStateMutex);
- t = p->getTransformLocked();
+ t = p->getTransform();
// If the parent is not using NATIVE_WINDOW_SCALING_MODE_FREEZE (e.g.
// it isFixedSize) then there may be additional scaling not accounted
@@ -2043,27 +1960,18 @@
}
half Layer::getAlpha() const {
- Mutex::Autolock lock(mStateMutex);
- return getAlphaLocked();
-}
-
-half Layer::getAlphaLocked() const {
const auto& p = mDrawingParent.promote();
+
half parentAlpha = (p != nullptr) ? p->getAlpha() : 1.0_hf;
return parentAlpha * getDrawingState().color.a;
}
half4 Layer::getColor() const {
const half4 color(getDrawingState().color);
- return half4(color.r, color.g, color.b, getAlphaLocked());
+ return half4(color.r, color.g, color.b, getAlpha());
}
Layer::RoundedCornerState Layer::getRoundedCornerState() const {
- Mutex::Autolock lock(mStateMutex);
- return getRoundedCornerStateLocked();
-}
-
-Layer::RoundedCornerState Layer::getRoundedCornerStateLocked() const {
const auto& p = mDrawingParent.promote();
if (p != nullptr) {
RoundedCornerState parentState = p->getRoundedCornerState();
@@ -2080,7 +1988,7 @@
}
}
const float radius = getDrawingState().cornerRadius;
- return radius > 0 ? RoundedCornerState(computeBoundsLocked(), radius) : RoundedCornerState();
+ return radius > 0 ? RoundedCornerState(computeBounds(), radius) : RoundedCornerState();
}
void Layer::commitChildList() {
@@ -2093,21 +2001,19 @@
}
void Layer::setInputInfo(const InputWindowInfo& info) {
- Mutex::Autolock lock(mStateMutex);
- mState.current.inputInfo = info;
- mState.current.modified = true;
- mState.current.inputInfoChanged = true;
+ mCurrentState.inputInfo = info;
+ mCurrentState.modified = true;
+ mCurrentState.inputInfoChanged = true;
setTransactionFlags(eTransactionNeeded);
}
void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) {
- Mutex::Autolock lock(mStateMutex);
const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
- const State& state = useDrawing ? mState.drawing : mState.current;
+ const State& state = useDrawing ? mDrawingState : mCurrentState;
ui::Transform requestedTransform = state.active_legacy.transform;
- ui::Transform transform = getTransformLocked();
+ ui::Transform transform = getTransform();
layerInfo->set_id(sequence);
layerInfo->set_name(getName().c_str());
@@ -2129,7 +2035,7 @@
LayerProtoHelper::writeToProto(visibleRegion, layerInfo->mutable_visible_region());
LayerProtoHelper::writeToProto(surfaceDamageRegion, layerInfo->mutable_damage_region());
- layerInfo->set_layer_stack(getLayerStackLocked());
+ layerInfo->set_layer_stack(getLayerStack());
layerInfo->set_z(state.z);
PositionProto* position = layerInfo->mutable_position();
@@ -2145,7 +2051,7 @@
size->set_h(state.active_legacy.h);
LayerProtoHelper::writeToProto(state.crop_legacy, layerInfo->mutable_crop());
- layerInfo->set_corner_radius(getRoundedCornerStateLocked().radius);
+ layerInfo->set_corner_radius(getRoundedCornerState().radius);
layerInfo->set_is_opaque(isOpaque(state));
layerInfo->set_invalidate(contentDirty);
@@ -2186,7 +2092,7 @@
layerInfo->set_curr_frame(mCurrentFrameNumber);
layerInfo->set_effective_scaling_mode(getEffectiveScalingMode());
- for (const auto& pendingState : mState.pending) {
+ for (const auto& pendingState : mPendingStates) {
auto barrierLayer = pendingState.barrierLayer_legacy.promote();
if (barrierLayer != nullptr) {
BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer();
@@ -2230,25 +2136,19 @@
}
InputWindowInfo Layer::fillInputInfo(const Rect& screenBounds) {
- InputWindowInfo info;
- ui::Transform t;
- Rect layerBounds;
- {
- Mutex::Autolock lock(mStateMutex);
- info = mState.drawing.inputInfo;
- t = getTransformLocked();
- const float xScale = t.sx();
- const float yScale = t.sy();
- if (xScale != 1.0f || yScale != 1.0f) {
- info.windowXScale *= 1.0f / xScale;
- info.windowYScale *= 1.0f / yScale;
- info.touchableRegion.scaleSelf(xScale, yScale);
- }
+ InputWindowInfo info = mDrawingState.inputInfo;
- // Transform layer size to screen space and inset it by surface insets.
- layerBounds = getCroppedBufferSize(getDrawingState());
+ ui::Transform t = getTransform();
+ const float xScale = t.sx();
+ const float yScale = t.sy();
+ if (xScale != 1.0f || yScale != 1.0f) {
+ info.windowXScale *= 1.0f / xScale;
+ info.windowYScale *= 1.0f / yScale;
+ info.touchableRegion.scaleSelf(xScale, yScale);
}
+ // Transform layer size to screen space and inset it by surface insets.
+ Rect layerBounds = getCroppedBufferSize(getDrawingState());
layerBounds = t.transform(layerBounds);
layerBounds.inset(info.surfaceInset, info.surfaceInset, info.surfaceInset, info.surfaceInset);
@@ -2271,8 +2171,7 @@
}
bool Layer::hasInput() const {
- Mutex::Autolock lock(mStateMutex);
- return mState.drawing.inputInfo.token != nullptr;
+ return mDrawingState.inputInfo.token != nullptr;
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index fb75e4c..7bc7a82 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -55,7 +55,6 @@
#include "RenderArea.h"
using namespace android::surfaceflinger;
-using StateSet = android::LayerVector::StateSet;
namespace android {
@@ -240,7 +239,7 @@
// also the rendered size of the layer prior to any transformations. Parent
// or local matrix transformations will not affect the size of the buffer,
// but may affect it's on-screen size or clipping.
- virtual bool setSize(uint32_t w, uint32_t h) EXCLUDES(mStateMutex);
+ virtual bool setSize(uint32_t w, uint32_t h);
// Set a 2x2 transformation matrix on the layer. This transform
// will be applied after parent transforms, but before any final
// producer specified transform.
@@ -255,76 +254,58 @@
// setPosition operates in parent buffer space (pre parent-transform) or display
// space for top-level layers.
- virtual bool setPosition(float x, float y, bool immediate) EXCLUDES(mStateMutex);
+ virtual bool setPosition(float x, float y, bool immediate);
// Buffer space
- virtual bool setCrop_legacy(const Rect& crop, bool immediate) EXCLUDES(mStateMutex);
+ virtual bool setCrop_legacy(const Rect& crop, bool immediate);
// TODO(b/38182121): Could we eliminate the various latching modes by
// using the layer hierarchy?
// -----------------------------------------------------------------------
- virtual bool setLayer(int32_t z) EXCLUDES(mStateMutex);
- virtual bool setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ)
- EXCLUDES(mStateMutex);
+ virtual bool setLayer(int32_t z);
+ virtual bool setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ);
- virtual bool setAlpha(float alpha) EXCLUDES(mStateMutex);
- virtual bool setColor(const half3& color) EXCLUDES(mStateMutex);
+ virtual bool setAlpha(float alpha);
+ virtual bool setColor(const half3& color);
// Set rounded corner radius for this layer and its children.
//
// We only support 1 radius per layer in the hierarchy, where parent layers have precedence.
// The shape of the rounded corner rectangle is specified by the crop rectangle of the layer
// from which we inferred the rounded corner radius.
- virtual bool setCornerRadius(float cornerRadius) EXCLUDES(mStateMutex);
- virtual bool setTransparentRegionHint(const Region& transparent) EXCLUDES(mStateMutex);
- virtual bool setFlags(uint8_t flags, uint8_t mask) EXCLUDES(mStateMutex);
- virtual bool setLayerStack(uint32_t layerStack) EXCLUDES(mStateMutex);
- virtual uint32_t getLayerStack() const EXCLUDES(mStateMutex);
+ virtual bool setCornerRadius(float cornerRadius);
+ virtual bool setTransparentRegionHint(const Region& transparent);
+ virtual bool setFlags(uint8_t flags, uint8_t mask);
+ virtual bool setLayerStack(uint32_t layerStack);
+ virtual uint32_t getLayerStack() const;
virtual void deferTransactionUntil_legacy(const sp<IBinder>& barrierHandle,
uint64_t frameNumber);
- virtual void deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber)
- EXCLUDES(mStateMutex);
- virtual bool setOverrideScalingMode(int32_t overrideScalingMode) EXCLUDES(mStateMutex);
- virtual void setInfo(int32_t type, int32_t appId) EXCLUDES(mStateMutex);
- virtual bool reparentChildren(const sp<IBinder>& layer) EXCLUDES(mStateMutex);
+ virtual void deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber);
+ virtual bool setOverrideScalingMode(int32_t overrideScalingMode);
+ virtual void setInfo(int32_t type, int32_t appId);
+ virtual bool reparentChildren(const sp<IBinder>& layer);
virtual void setChildrenDrawingParent(const sp<Layer>& layer);
- virtual bool reparent(const sp<IBinder>& newParentHandle) EXCLUDES(mStateMutex);
+ virtual bool reparent(const sp<IBinder>& newParentHandle);
virtual bool detachChildren();
bool attachChildren();
bool isLayerDetached() const { return mLayerDetached; }
- virtual bool setColorTransform(const mat4& matrix) EXCLUDES(mStateMutex);
- mat4 getColorTransform() const EXCLUDES(mStateMutex);
- virtual mat4 getColorTransformLocked() const REQUIRES(mStateMutex);
- virtual bool hasColorTransform() const EXCLUDES(mStateMutex);
- ;
+ virtual bool setColorTransform(const mat4& matrix);
+ virtual mat4 getColorTransform() const;
+ virtual bool hasColorTransform() const;
// Used only to set BufferStateLayer state
- virtual bool setTransform(uint32_t /*transform*/) EXCLUDES(mStateMutex) { return false; };
- virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/)
- EXCLUDES(mStateMutex) {
- return false;
- };
- virtual bool setCrop(const Rect& /*crop*/) EXCLUDES(mStateMutex) { return false; };
- virtual bool setFrame(const Rect& /*frame*/) EXCLUDES(mStateMutex) { return false; };
- virtual bool setBuffer(const sp<GraphicBuffer>& /*buffer*/) EXCLUDES(mStateMutex) {
- return false;
- };
- virtual bool setAcquireFence(const sp<Fence>& /*fence*/) EXCLUDES(mStateMutex) {
- return false;
- };
- virtual bool setDataspace(ui::Dataspace /*dataspace*/) EXCLUDES(mStateMutex) { return false; };
- virtual bool setHdrMetadata(const HdrMetadata& /*hdrMetadata*/) EXCLUDES(mStateMutex) {
- return false;
- };
- virtual bool setSurfaceDamageRegion(const Region& /*surfaceDamage*/) EXCLUDES(mStateMutex) {
- return false;
- };
- virtual bool setApi(int32_t /*api*/) EXCLUDES(mStateMutex) { return false; };
- virtual bool setSidebandStream(const sp<NativeHandle>& /*sidebandStream*/)
- EXCLUDES(mStateMutex) {
- return false;
- };
+ virtual bool setTransform(uint32_t /*transform*/) { return false; };
+ virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; };
+ virtual bool setCrop(const Rect& /*crop*/) { return false; };
+ virtual bool setFrame(const Rect& /*frame*/) { return false; };
+ virtual bool setBuffer(const sp<GraphicBuffer>& /*buffer*/) { return false; };
+ virtual bool setAcquireFence(const sp<Fence>& /*fence*/) { return false; };
+ virtual bool setDataspace(ui::Dataspace /*dataspace*/) { return false; };
+ virtual bool setHdrMetadata(const HdrMetadata& /*hdrMetadata*/) { return false; };
+ virtual bool setSurfaceDamageRegion(const Region& /*surfaceDamage*/) { return false; };
+ virtual bool setApi(int32_t /*api*/) { return false; };
+ virtual bool setSidebandStream(const sp<NativeHandle>& /*sidebandStream*/) { return false; };
virtual bool setTransactionCompletedListeners(
- const std::vector<sp<CallbackHandle>>& /*handles*/) EXCLUDES(mStateMutex) {
+ const std::vector<sp<CallbackHandle>>& /*handles*/) {
return false;
};
@@ -343,21 +324,18 @@
virtual void useSurfaceDamage() {}
virtual void useEmptyDamage() {}
- uint32_t getTransactionFlags() const EXCLUDES(mStateMutex);
- uint32_t getTransactionFlags(uint32_t flags) EXCLUDES(mStateMutex);
- uint32_t setTransactionFlags(uint32_t flags) REQUIRES(mStateMutex);
+ uint32_t getTransactionFlags() const { return mTransactionFlags; }
+ uint32_t getTransactionFlags(uint32_t flags);
+ uint32_t setTransactionFlags(uint32_t flags);
- bool belongsToDisplay(uint32_t layerStack, bool isPrimaryDisplay) const EXCLUDES(mStateMutex) {
+ bool belongsToDisplay(uint32_t layerStack, bool isPrimaryDisplay) const {
return getLayerStack() == layerStack && (!mPrimaryDisplayOnly || isPrimaryDisplay);
}
void computeGeometry(const RenderArea& renderArea, renderengine::Mesh& mesh,
- bool useIdentityTransform) const REQUIRES(mStateMutex);
- FloatRect computeBounds(const Region& activeTransparentRegion) const EXCLUDES(mStateMutex);
- FloatRect computeBoundsLocked(const Region& activeTransparentRegion) const
- REQUIRES(mStateMutex);
- FloatRect computeBounds() const EXCLUDES(mStateMutex);
- FloatRect computeBoundsLocked() const REQUIRES(mStateMutex);
+ bool useIdentityTransform) const;
+ FloatRect computeBounds(const Region& activeTransparentRegion) const;
+ FloatRect computeBounds() const;
int32_t getSequence() const { return sequence; }
@@ -374,21 +352,16 @@
*/
virtual bool isOpaque(const Layer::State&) const { return false; }
- virtual bool isDrawingOpaque() const EXCLUDES(mStateMutex) {
- Mutex::Autolock lock(mStateMutex);
- return isOpaque(mState.drawing);
- }
-
/*
* isSecure - true if this surface is secure, that is if it prevents
* screenshots or VNC servers.
*/
- bool isSecure() const EXCLUDES(mStateMutex);
+ bool isSecure() const;
/*
* isVisible - true if this layer is visible, false otherwise
*/
- virtual bool isVisible() const EXCLUDES(mStateMutex) = 0;
+ virtual bool isVisible() const = 0;
/*
* isHiddenByPolicy - true if this layer has been forced invisible.
@@ -396,7 +369,7 @@
* For example if this layer has no active buffer, it may not be hidden by
* policy, but it still can not be visible.
*/
- bool isHiddenByPolicy() const EXCLUDES(mStateMutex);
+ bool isHiddenByPolicy() const;
/*
* isProtected - true if the layer may contain protected content in the
@@ -417,8 +390,7 @@
bool isRemovedFromCurrentState() const;
void writeToProto(LayerProto* layerInfo,
- LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing)
- EXCLUDES(mStateMutex);
+ LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing);
void writeToProto(LayerProto* layerInfo, DisplayId displayId);
@@ -431,32 +403,25 @@
virtual Region getActiveTransparentRegion(const Layer::State& s) const {
return s.activeTransparentRegion_legacy;
}
-
- virtual Region getDrawingActiveTransparentRegion() const EXCLUDES(mStateMutex) {
- Mutex::Autolock lock(mStateMutex);
- return getActiveTransparentRegion(mState.drawing);
- }
-
virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; }
protected:
/*
* onDraw - draws the surface.
*/
- virtual void onDraw(const RenderArea& renderArea, const Region& clip, bool useIdentityTransform)
- EXCLUDES(mStateMutex) = 0;
+ virtual void onDraw(const RenderArea& renderArea, const Region& clip,
+ bool useIdentityTransform) = 0;
public:
virtual void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) {}
virtual bool isHdrY410() const { return false; }
- void setGeometry(const sp<const DisplayDevice>& display, uint32_t z) EXCLUDES(mStateMutex);
+ void setGeometry(const sp<const DisplayDevice>& display, uint32_t z);
void forceClientComposition(DisplayId displayId);
bool getForceClientComposition(DisplayId displayId);
virtual void setPerFrameData(DisplayId displayId, const ui::Transform& transform,
- const Rect& viewport, int32_t supportedPerFrameMetadata)
- EXCLUDES(mStateMutex) = 0;
+ const Rect& viewport, int32_t supportedPerFrameMetadata) = 0;
// callIntoHwc exists so we can update our local state and call
// acceptDisplayChanges without unnecessarily updating the device's state
@@ -464,7 +429,7 @@
HWC2::Composition getCompositionType(const std::optional<DisplayId>& displayId) const;
void setClearClientTarget(DisplayId displayId, bool clear);
bool getClearClientTarget(DisplayId displayId) const;
- void updateCursorPosition(const sp<const DisplayDevice>& display) EXCLUDES(mStateMutex);
+ void updateCursorPosition(const sp<const DisplayDevice>& display);
/*
* called after page-flip
@@ -487,8 +452,7 @@
virtual bool onPostComposition(const std::optional<DisplayId>& /*displayId*/,
const std::shared_ptr<FenceTime>& /*glDoneFence*/,
const std::shared_ptr<FenceTime>& /*presentFence*/,
- const CompositorTiming& /*compositorTiming*/)
- EXCLUDES(mStateMutex) {
+ const CompositorTiming& /*compositorTiming*/) {
return false;
}
@@ -500,14 +464,14 @@
* draw - performs some global clipping optimizations
* and calls onDraw().
*/
- void draw(const RenderArea& renderArea, const Region& clip) EXCLUDES(mStateMutex);
- void draw(const RenderArea& renderArea, bool useIdentityTransform) EXCLUDES(mStateMutex);
+ void draw(const RenderArea& renderArea, const Region& clip);
+ void draw(const RenderArea& renderArea, bool useIdentityTransform);
/*
* doTransaction - process the transaction. This is a good place to figure
* out which attributes of the surface have changed.
*/
- uint32_t doTransaction(uint32_t transactionFlags) EXCLUDES(mStateMutex);
+ uint32_t doTransaction(uint32_t transactionFlags);
/*
* setVisibleRegion - called to set the new visible region. This gives
@@ -540,17 +504,17 @@
* to figure out if the content or size of a surface has changed.
*/
virtual Region latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/,
- const sp<Fence>& /*releaseFence*/) EXCLUDES(mStateMutex) {
+ const sp<Fence>& /*releaseFence*/) {
return {};
}
virtual bool isBufferLatched() const { return false; }
/*
- * called with SurfaceFlinger mStateLock a binder thread when the layer is
+ * called with the state lock from a binder thread when the layer is
* removed from the current list to the pending removal list
*/
- void onRemovedFromCurrentState() EXCLUDES(mStateMutex);
+ void onRemovedFromCurrentState();
/*
* Called when the layer is added back to the current state list.
@@ -570,7 +534,7 @@
/*
* Returns if a frame is ready
*/
- virtual bool hasReadyFrame() const EXCLUDES(mStateMutex) { return false; }
+ virtual bool hasReadyFrame() const { return false; }
virtual int32_t getQueuedFrameCount() const { return 0; }
@@ -599,32 +563,17 @@
}
// -----------------------------------------------------------------------
- void clearWithOpenGL(const RenderArea& renderArea) const EXCLUDES(mStateMutex);
+ void clearWithOpenGL(const RenderArea& renderArea) const;
- inline const State& getDrawingState() const REQUIRES(mStateMutex) { return mState.drawing; }
+ inline const State& getDrawingState() const { return mDrawingState; }
+ inline const State& getCurrentState() const { return mCurrentState; }
+ inline State& getCurrentState() { return mCurrentState; }
- inline const State& getCurrentState() const REQUIRES(mStateMutex) { return mState.current; }
-
- inline State& getCurrentState() REQUIRES(mStateMutex) { return mState.current; }
-
- std::tuple<uint32_t, int32_t> getLayerStackAndZ(StateSet stateSet) EXCLUDES(mStateMutex);
- wp<Layer> getZOrderRelativeOf(StateSet stateSet) EXCLUDES(mStateMutex) {
- Mutex::Autolock lock(mStateMutex);
- const State& state = (stateSet == StateSet::Current) ? mState.current : mState.drawing;
-
- return state.zOrderRelativeOf;
- }
-
- uint8_t getCurrentFlags() EXCLUDES(mStateMutex) {
- Mutex::Autolock lock(mStateMutex);
- return mState.current.flags;
- }
-
- LayerDebugInfo getLayerDebugInfo() const EXCLUDES(mStateMutex);
+ LayerDebugInfo getLayerDebugInfo() const;
/* always call base class first */
static void miniDumpHeader(std::string& result);
- void miniDump(std::string& result, DisplayId displayId) const EXCLUDES(mStateMutex);
+ void miniDump(std::string& result, DisplayId displayId) const;
void dumpFrameStats(std::string& result) const;
void dumpFrameEvents(std::string& result);
void clearFrameStats();
@@ -639,29 +588,22 @@
void addAndGetFrameTimestamps(const NewFrameEventsEntry* newEntry,
FrameEventHistoryDelta* outDelta);
- bool getTransformToDisplayInverse() const EXCLUDES(mStateMutex) {
- Mutex::Autolock lock(mStateMutex);
- return getTransformToDisplayInverseLocked();
- }
+ virtual bool getTransformToDisplayInverse() const { return false; }
- virtual bool getTransformToDisplayInverseLocked() const REQUIRES(mStateMutex) { return false; }
-
- ui::Transform getTransform() const EXCLUDES(mStateMutex);
- ui::Transform getTransformLocked() const REQUIRES(mStateMutex);
+ ui::Transform getTransform() const;
// Returns the Alpha of the Surface, accounting for the Alpha
// of parent Surfaces in the hierarchy (alpha's will be multiplied
// down the hierarchy).
- half getAlpha() const EXCLUDES(mStateMutex);
- half4 getColor() const REQUIRES(mStateMutex);
+ half getAlpha() const;
+ half4 getColor() const;
// Returns how rounded corners should be drawn for this layer.
// This will traverse the hierarchy until it reaches its root, finding topmost rounded
// corner definition and converting it into current layer's coordinates.
// As of now, only 1 corner radius per display list is supported. Subsequent ones will be
// ignored.
- RoundedCornerState getRoundedCornerState() const EXCLUDES(mStateMutex);
- RoundedCornerState getRoundedCornerStateLocked() const REQUIRES(mStateMutex);
+ RoundedCornerState getRoundedCornerState() const;
void traverseInReverseZOrder(LayerVector::StateSet stateSet,
const LayerVector::Visitor& visitor);
@@ -681,7 +623,7 @@
ssize_t removeChild(const sp<Layer>& layer);
sp<Layer> getParent() const { return mCurrentParent.promote(); }
bool hasParent() const { return getParent() != nullptr; }
- Rect computeScreenBounds(bool reduceTransparentRegion = true) const EXCLUDES(mStateMutex);
+ Rect computeScreenBounds(bool reduceTransparentRegion = true) const;
bool setChildLayer(const sp<Layer>& childLayer, int32_t z);
bool setChildRelativeLayer(const sp<Layer>& childLayer,
const sp<IBinder>& relativeToHandle, int32_t relativeZ);
@@ -689,23 +631,14 @@
// Copy the current list of children to the drawing state. Called by
// SurfaceFlinger to complete a transaction.
void commitChildList();
- int32_t getZ() const EXCLUDES(mStateMutex);
- void pushPendingState() EXCLUDES(mStateMutex);
- virtual void pushPendingStateLocked() REQUIRES(mStateMutex);
+ int32_t getZ() const;
+ virtual void pushPendingState();
/**
* Returns active buffer size in the correct orientation. Buffer size is determined by undoing
* any buffer transformations. If the layer has no buffer then return INVALID_RECT.
*/
- virtual Rect getBufferSize(const Layer::State&) const REQUIRES(mStateMutex) {
- return Rect::INVALID_RECT;
- }
-
- virtual Rect getBufferSize(StateSet stateSet) const EXCLUDES(mStateMutex) {
- Mutex::Autolock lock(mStateMutex);
- const State& state = (stateSet == StateSet::Current) ? mState.current : mState.drawing;
- return getBufferSize(state);
- }
+ virtual Rect getBufferSize(const Layer::State&) const { return Rect::INVALID_RECT; }
protected:
// constant
@@ -734,17 +667,26 @@
// For unit tests
friend class TestableSurfaceFlinger;
- void commitTransaction(const State& stateToCommit) REQUIRES(mStateMutex);
+ void commitTransaction(const State& stateToCommit);
uint32_t getEffectiveUsage(uint32_t usage) const;
- virtual FloatRect computeCrop(const sp<const DisplayDevice>& display) const
- REQUIRES(mStateMutex);
+ // Computes the crop applied to this layer. windowBounds is the boundary of
+ // layer-stack space, so the cropping rectangle will be clipped to those
+ // bounds in that space. The crop rectangle is returned in buffer space. If
+ // windowBounds is invalid, then it is ignored.
+ virtual FloatRect computeCrop(const Rect& windowBounds) const;
+
+ // See the above method, but pulls the window boundaries from the display.
+ FloatRect computeCrop(const sp<const DisplayDevice>& display) const {
+ return computeCrop(display->getViewport());
+ }
// Compute the initial crop as specified by parent layers and the
// SurfaceControl for this layer. Does not include buffer crop from the
// IGraphicBufferProducer client, as that should not affect child clipping.
// Returns in screen space.
- Rect computeInitialCrop(const sp<const DisplayDevice>& display) const REQUIRES(mStateMutex);
+ Rect computeInitialCrop(const Rect& windowBounds) const;
+
/**
* Setup rounded corners coordinates of this layer, taking into account the layer bounds and
* crop coordinates, transforming them into layer space.
@@ -752,13 +694,13 @@
void setupRoundedCornersCropCoordinates(Rect win, const FloatRect& roundedCornersCrop) const;
// drawing
- void clearWithOpenGL(const RenderArea& renderArea, float r, float g, float b, float alpha) const
- EXCLUDES(mStateMutex);
+ void clearWithOpenGL(const RenderArea& renderArea, float r, float g, float b,
+ float alpha) const;
void setParent(const sp<Layer>& layer);
LayerVector makeTraversalList(LayerVector::StateSet stateSet, bool* outSkipRelativeZUsers);
- void addZOrderRelative(const wp<Layer>& relative) EXCLUDES(mStateMutex);
- void removeZOrderRelative(const wp<Layer>& relative) EXCLUDES(mStateMutex);
+ void addZOrderRelative(const wp<Layer>& relative);
+ void removeZOrderRelative(const wp<Layer>& relative);
class SyncPoint {
public:
@@ -794,10 +736,9 @@
// Returns false if the relevant frame has already been latched
bool addSyncPoint(const std::shared_ptr<SyncPoint>& point);
- void popPendingState(State* stateToCommit) REQUIRES(mStateMutex);
- virtual bool applyPendingStates(State* stateToCommit) REQUIRES(mStateMutex);
- virtual uint32_t doTransactionResize(uint32_t flags, Layer::State* stateToCommit)
- REQUIRES(mStateMutex);
+ void popPendingState(State* stateToCommit);
+ virtual bool applyPendingStates(State* stateToCommit);
+ virtual uint32_t doTransactionResize(uint32_t flags, Layer::State* stateToCommit);
void clearSyncPoints();
@@ -830,15 +771,14 @@
bool getPremultipledAlpha() const;
bool mPendingHWCDestroy{false};
- void setInputInfo(const InputWindowInfo& info) EXCLUDES(mStateMutex);
+ void setInputInfo(const InputWindowInfo& info);
- InputWindowInfo fillInputInfo(const Rect& screenBounds) EXCLUDES(mStateMutex);
- bool hasInput() const EXCLUDES(mStateMutex);
+ InputWindowInfo fillInputInfo(const Rect& screenBounds);
+ bool hasInput() const;
protected:
// -----------------------------------------------------------------------
- bool usingRelativeZ(LayerVector::StateSet stateSet) EXCLUDES(mStateMutex);
- bool usingRelativeZLocked(LayerVector::StateSet stateSet) REQUIRES(mStateMutex);
+ bool usingRelativeZ(LayerVector::StateSet stateSet);
bool mPremultipliedAlpha{true};
String8 mName;
@@ -846,14 +786,14 @@
bool mPrimaryDisplayOnly = false;
+ // these are protected by an external lock
+ State mCurrentState;
+ State mDrawingState;
+ std::atomic<uint32_t> mTransactionFlags{0};
+
// Accessed from main thread and binder threads
- mutable Mutex mStateMutex;
- struct {
- State current;
- State drawing;
- uint32_t transactionFlags{0};
- Vector<State> pending;
- } mState GUARDED_BY(mStateMutex);
+ Mutex mPendingStateMutex;
+ Vector<State> mPendingStates;
// Timestamp history for UIAutomation. Thread safe.
FrameTracker mFrameTracker;
@@ -926,7 +866,7 @@
* The cropped bounds must be transformed back from parent layer space to child layer space by
* applying the inverse of the child's transformation.
*/
- FloatRect cropChildBounds(const FloatRect& childBounds) const REQUIRES(mStateMutex);
+ FloatRect cropChildBounds(const FloatRect& childBounds) const;
/**
* Returns the cropped buffer size or the layer crop if the layer has no buffer. Return
@@ -934,12 +874,7 @@
* A layer with an invalid buffer size and no crop is considered to be boundless. The layer
* bounds are constrained by its parent bounds.
*/
- Rect getCroppedBufferSize(const Layer::State& s) const REQUIRES(mStateMutex);
-
- // locked version of public methods
- bool isSecureLocked() const REQUIRES(mStateMutex);
- virtual uint32_t getLayerStackLocked() const REQUIRES(mStateMutex);
- half getAlphaLocked() const REQUIRES(mStateMutex);
+ Rect getCroppedBufferSize(const Layer::State& s) const;
};
} // namespace android
diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp
index a7db23e..8494524 100644
--- a/services/surfaceflinger/LayerVector.cpp
+++ b/services/surfaceflinger/LayerVector.cpp
@@ -38,12 +38,18 @@
const auto& l = *reinterpret_cast<const sp<Layer>*>(lhs);
const auto& r = *reinterpret_cast<const sp<Layer>*>(rhs);
- const auto& [ls, lz] = l->getLayerStackAndZ(mStateSet);
- const auto& [rs, rz] = r->getLayerStackAndZ(mStateSet);
+ const auto& lState =
+ (mStateSet == StateSet::Current) ? l->getCurrentState() : l->getDrawingState();
+ const auto& rState =
+ (mStateSet == StateSet::Current) ? r->getCurrentState() : r->getDrawingState();
+ uint32_t ls = lState.layerStack;
+ uint32_t rs = rState.layerStack;
if (ls != rs)
return (ls > rs) ? 1 : -1;
+ int32_t lz = lState.z;
+ int32_t rz = rState.z;
if (lz != rz)
return (lz > rz) ? 1 : -1;
@@ -56,8 +62,9 @@
void LayerVector::traverseInZOrder(StateSet stateSet, const Visitor& visitor) const {
for (size_t i = 0; i < size(); i++) {
const auto& layer = (*this)[i];
- auto zOrderRelativeOf = layer->getZOrderRelativeOf(stateSet);
- if (zOrderRelativeOf != nullptr) {
+ auto& state = (stateSet == StateSet::Current) ? layer->getCurrentState()
+ : layer->getDrawingState();
+ if (state.zOrderRelativeOf != nullptr) {
continue;
}
layer->traverseInZOrder(stateSet, visitor);
@@ -67,8 +74,9 @@
void LayerVector::traverseInReverseZOrder(StateSet stateSet, const Visitor& visitor) const {
for (auto i = static_cast<int64_t>(size()) - 1; i >= 0; i--) {
const auto& layer = (*this)[i];
- auto zOrderRelativeOf = layer->getZOrderRelativeOf(stateSet);
- if (zOrderRelativeOf != nullptr) {
+ auto& state = (stateSet == StateSet::Current) ? layer->getCurrentState()
+ : layer->getDrawingState();
+ if (state.zOrderRelativeOf != nullptr) {
continue;
}
layer->traverseInReverseZOrder(stateSet, visitor);
diff --git a/services/surfaceflinger/OWNERS b/services/surfaceflinger/OWNERS
new file mode 100644
index 0000000..dc2b300
--- /dev/null
+++ b/services/surfaceflinger/OWNERS
@@ -0,0 +1,5 @@
+chaviw@google.com
+lpy@google.com
+marissaw@google.com
+racarr@google.com
+stoza@google.com
\ No newline at end of file
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index 1683982..bf925b2 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -67,7 +67,13 @@
}
void EventThreadConnection::requestNextVsync() {
- mEventThread->requestNextVsync(this);
+ ATRACE_NAME("requestNextVsync");
+ mEventThread->requestNextVsync(this, true);
+}
+
+void EventThreadConnection::requestNextVsyncForHWC() {
+ ATRACE_NAME("requestNextVsyncForHWC");
+ mEventThread->requestNextVsync(this, false);
}
status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
@@ -184,16 +190,17 @@
}
}
-void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) {
- std::lock_guard<std::mutex> lock(mMutex);
- if (mResetIdleTimer) {
+void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection, bool reset) {
+ if (mResetIdleTimer && reset) {
+ ATRACE_NAME("resetIdleTimer");
mResetIdleTimer();
}
-
if (mResyncWithRateLimitCallback) {
mResyncWithRateLimitCallback();
}
+ std::lock_guard<std::mutex> lock(mMutex);
+
if (connection->count < 0) {
connection->count = 0;
mCondition.notify_all();
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index 66f54bd..e110488 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -68,6 +68,9 @@
status_t stealReceiveChannel(gui::BitTube* outChannel) override;
status_t setVsyncRate(uint32_t count) override;
void requestNextVsync() override; // asynchronous
+ // Requesting Vsync for HWC does not reset the idle timer, since HWC requires a refresh
+ // in order to update the configs.
+ void requestNextVsyncForHWC();
// count >= 1 : continuous event. count is the vsync rate
// count == 0 : one-shot event that has not fired
@@ -105,7 +108,9 @@
virtual status_t registerDisplayEventConnection(
const sp<EventThreadConnection>& connection) = 0;
virtual void setVsyncRate(uint32_t count, const sp<EventThreadConnection>& connection) = 0;
- virtual void requestNextVsync(const sp<EventThreadConnection>& connection) = 0;
+ // Requests the next vsync. If resetIdleTimer is set to true, it resets the idle timer.
+ virtual void requestNextVsync(const sp<EventThreadConnection>& connection,
+ bool resetIdleTimer) = 0;
};
namespace impl {
@@ -129,7 +134,8 @@
status_t registerDisplayEventConnection(const sp<EventThreadConnection>& connection) override;
void setVsyncRate(uint32_t count, const sp<EventThreadConnection>& connection) override;
- void requestNextVsync(const sp<EventThreadConnection>& connection) override;
+ void requestNextVsync(const sp<EventThreadConnection>& connection,
+ bool resetIdleTimer) override;
// called before the screen is turned off from main thread
void onScreenReleased() override;
@@ -166,6 +172,9 @@
// Implements VSyncSource::Callback
void onVSyncEvent(nsecs_t timestamp) override;
+ // Acquires mutex and requests next vsync.
+ void requestNextVsyncInternal(const sp<EventThreadConnection>& connection) EXCLUDES(mMutex);
+
// TODO(b/113612090): Once the Scheduler is complete this pointer will become obsolete.
VSyncSource* mVSyncSource GUARDED_BY(mMutex) = nullptr;
std::unique_ptr<VSyncSource> mVSyncSourceUnique GUARDED_BY(mMutex) = nullptr;
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp
index 36403cc..66f42bb 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.cpp
+++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp
@@ -148,6 +148,10 @@
mEvents->requestNextVsync();
}
+void MessageQueue::invalidateForHWC() {
+ mEvents->requestNextVsyncForHWC();
+}
+
void MessageQueue::refresh() {
mHandler->dispatchRefresh();
}
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.h b/services/surfaceflinger/Scheduler/MessageQueue.h
index 24a3834..0bf00b0 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.h
+++ b/services/surfaceflinger/Scheduler/MessageQueue.h
@@ -91,6 +91,7 @@
virtual void waitMessage() = 0;
virtual status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime = 0) = 0;
virtual void invalidate() = 0;
+ virtual void invalidateForHWC() = 0;
virtual void refresh() = 0;
};
@@ -134,6 +135,9 @@
// sends INVALIDATE message at next VSYNC
void invalidate() override;
+
+ // sends INVALIDATE message at next VSYNC, without resetting the idle timer in the Scheduler
+ void invalidateForHWC();
// sends REFRESH message at next VSYNC
void refresh() override;
};
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index c363ba5..fec53af 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -238,6 +238,16 @@
mLayerHistory.incrementCounter();
}
+void Scheduler::setExpiredIdleTimerCallback(const ExpiredIdleTimerCallback& expiredTimerCallback) {
+ std::lock_guard<std::mutex> lock(mCallbackLock);
+ mExpiredTimerCallback = expiredTimerCallback;
+}
+
+void Scheduler::setResetIdleTimerCallback(const ResetIdleTimerCallback& resetTimerCallback) {
+ std::lock_guard<std::mutex> lock(mCallbackLock);
+ mResetTimerCallback = resetTimerCallback;
+}
+
void Scheduler::updateFrameSkipping(const int64_t skipCount) {
ATRACE_INT("FrameSkipCount", skipCount);
if (mSkipCount != skipCount) {
@@ -314,12 +324,12 @@
// TODO(b/113612090): This are current numbers from trial and error while running videos
// from YouTube at 24, 30, and 60 fps.
if (mean > 14 && mean < 18) {
- ATRACE_INT("FPS", 60);
+ ATRACE_INT("MediaFPS", 60);
} else if (mean > 31 && mean < 34) {
- ATRACE_INT("FPS", 30);
+ ATRACE_INT("MediaFPS", 30);
return;
} else if (mean > 39 && mean < 42) {
- ATRACE_INT("FPS", 24);
+ ATRACE_INT("MediaFPS", 24);
}
}
@@ -328,13 +338,19 @@
mIdleTimer->reset();
ATRACE_INT("ExpiredIdleTimer", 0);
}
+
+ std::lock_guard<std::mutex> lock(mCallbackLock);
+ if (mResetTimerCallback) {
+ mResetTimerCallback();
+ }
}
void Scheduler::expiredTimerCallback() {
- // TODO(b/113612090): Each time a timer expired, we should record the information into
- // a circular buffer. Once this has happened a given amount (TBD) of times, we can comfortably
- // say that the device is sitting in idle.
- ATRACE_INT("ExpiredIdleTimer", 1);
+ std::lock_guard<std::mutex> lock(mCallbackLock);
+ if (mExpiredTimerCallback) {
+ mExpiredTimerCallback();
+ ATRACE_INT("ExpiredIdleTimer", 1);
+ }
}
} // namespace android
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 9d7dd4d..3538f31 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -36,6 +36,9 @@
class Scheduler {
public:
+ using ExpiredIdleTimerCallback = std::function<void()>;
+ using ResetIdleTimerCallback = std::function<void()>;
+
// Enum to indicate whether to start the transaction early, or at vsync time.
enum class TransactionStart { EARLY, NORMAL };
@@ -111,6 +114,10 @@
const std::string layerName);
// Increments counter in the layer history to indicate that SF has started a new frame.
void incrementFrameCounter();
+ // Callback that gets invoked once the idle timer expires.
+ void setExpiredIdleTimerCallback(const ExpiredIdleTimerCallback& expiredTimerCallback);
+ // Callback that gets invoked once the idle timer is reset.
+ void setResetIdleTimerCallback(const ResetIdleTimerCallback& resetTimerCallback);
protected:
virtual std::unique_ptr<EventThread> makeEventThread(
@@ -173,6 +180,10 @@
// interval, a callback is fired. Set this variable to >0 to use this feature.
int64_t mSetIdleTimerMs = 0;
std::unique_ptr<scheduler::IdleTimer> mIdleTimer;
+
+ std::mutex mCallbackLock;
+ ExpiredIdleTimerCallback mExpiredTimerCallback GUARDED_BY(mCallbackLock);
+ ResetIdleTimerCallback mResetTimerCallback GUARDED_BY(mCallbackLock);
};
} // namespace android
diff --git a/services/surfaceflinger/StartPropertySetThread.h b/services/surfaceflinger/StartPropertySetThread.h
index a64c21b..bbdcde2 100644
--- a/services/surfaceflinger/StartPropertySetThread.h
+++ b/services/surfaceflinger/StartPropertySetThread.h
@@ -33,7 +33,7 @@
// Any property_set() will block during init stage so need to be offloaded
// to this thread. see b/63844978.
public:
- StartPropertySetThread(bool timestampPropertyValue);
+ explicit StartPropertySetThread(bool timestampPropertyValue);
status_t Start();
private:
virtual bool threadLoop();
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 4a93be6..9eff3c6 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -35,32 +35,30 @@
#include <binder/IServiceManager.h>
#include <binder/PermissionCache.h>
+#include <compositionengine/CompositionEngine.h>
#include <dvr/vr_flinger.h>
-
-#include <input/IInputFlinger.h>
-
-#include <ui/ColorSpace.h>
-#include <ui/DebugUtils.h>
-#include <ui/DisplayInfo.h>
-#include <ui/DisplayStatInfo.h>
-
#include <gui/BufferQueue.h>
#include <gui/GuiConfig.h>
#include <gui/IDisplayEventConnection.h>
#include <gui/IProducerListener.h>
#include <gui/LayerDebugInfo.h>
#include <gui/Surface.h>
+#include <input/IInputFlinger.h>
#include <renderengine/RenderEngine.h>
+#include <ui/ColorSpace.h>
+#include <ui/DebugUtils.h>
+#include <ui/DisplayInfo.h>
+#include <ui/DisplayStatInfo.h>
#include <ui/GraphicBufferAllocator.h>
#include <ui/PixelFormat.h>
#include <ui/UiConfig.h>
-
-#include <utils/misc.h>
-#include <utils/String8.h>
-#include <utils/String16.h>
+#include <utils/CallStack.h>
#include <utils/StopWatch.h>
+#include <utils/String16.h>
+#include <utils/String8.h>
#include <utils/Timers.h>
#include <utils/Trace.h>
+#include <utils/misc.h>
#include <private/android_filesystem_config.h>
#include <private/gui/SyncFeatures.h>
@@ -238,7 +236,6 @@
SurfaceFlingerBE::SurfaceFlingerBE()
: mHwcServiceName(getHwcServiceName()),
- mRenderEngine(nullptr),
mFrameBuckets(),
mTotalTime(0),
mLastSwapTime(0),
@@ -272,7 +269,8 @@
mHasPoweredOff(false),
mNumLayers(0),
mVrFlingerRequestsDisplay(false),
- mMainThreadId(std::this_thread::get_id()) {}
+ mMainThreadId(std::this_thread::get_id()),
+ mCompositionEngine{getFactory().createCompositionEngine()} {}
SurfaceFlinger::SurfaceFlinger(surfaceflinger::Factory& factory)
: SurfaceFlinger(factory, SkipInitialization) {
@@ -458,19 +456,6 @@
return initClient(new Client(this));
}
-sp<ISurfaceComposerClient> SurfaceFlinger::createScopedConnection(
- const sp<IGraphicBufferProducer>& gbp) {
- if (authenticateSurfaceTexture(gbp) == false) {
- return nullptr;
- }
- const auto& layer = (static_cast<MonitoredProducer*>(gbp.get()))->getLayer();
- if (layer == nullptr) {
- return nullptr;
- }
-
- return initClient(new Client(this, layer));
-}
-
sp<IBinder> SurfaceFlinger::createDisplay(const String8& displayName,
bool secure)
{
@@ -544,6 +529,18 @@
return NO_ERROR;
}
+HWComposer& SurfaceFlinger::getHwComposer() const {
+ return mCompositionEngine->getHwComposer();
+}
+
+renderengine::RenderEngine& SurfaceFlinger::getRenderEngine() const {
+ return mCompositionEngine->getRenderEngine();
+}
+
+compositionengine::CompositionEngine& SurfaceFlinger::getCompositionEngine() const {
+ return *mCompositionEngine.get();
+}
+
void SurfaceFlinger::bootFinished()
{
if (mStartPropertySetThread->join() != NO_ERROR) {
@@ -673,15 +670,14 @@
renderengine::RenderEngine::USE_HIGH_PRIORITY_CONTEXT : 0);
// TODO(b/77156734): We need to stop casting and use HAL types when possible.
- getBE().mRenderEngine =
+ mCompositionEngine->setRenderEngine(
renderengine::RenderEngine::create(static_cast<int32_t>(defaultCompositionPixelFormat),
- renderEngineFeature);
- LOG_ALWAYS_FATAL_IF(getBE().mRenderEngine == nullptr, "couldn't create RenderEngine");
+ renderEngineFeature));
LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
"Starting with vr flinger active is not currently supported.");
- getBE().mHwc = getFactory().createHWComposer(getBE().mHwcServiceName);
- getBE().mHwc->registerCallback(this, getBE().mComposerSequenceId);
+ mCompositionEngine->setHwComposer(getFactory().createHWComposer(getBE().mHwcServiceName));
+ mCompositionEngine->getHwComposer().registerCallback(this, getBE().mComposerSequenceId);
// Process any initial hotplug and resulting display changes.
processDisplayHotplugEventsLocked();
const auto display = getDefaultDisplayDeviceLocked();
@@ -722,7 +718,7 @@
// set initial conditions (e.g. unblank default device)
initializeDisplays();
- getBE().mRenderEngine->primeCache();
+ getRenderEngine().primeCache();
// Inform native graphics APIs whether the present timestamp is supported:
@@ -734,6 +730,11 @@
ALOGE("Run StartPropertySetThread failed!");
}
+ if (mUseScheduler) {
+ mScheduler->setExpiredIdleTimerCallback([this]() { setRefreshRateTo(60.f /* fps */); });
+ mScheduler->setResetIdleTimerCallback([this]() { setRefreshRateTo(90.f /* fps */); });
+ }
+
ALOGV("Done initializing");
}
@@ -762,11 +763,11 @@
}
size_t SurfaceFlinger::getMaxTextureSize() const {
- return getBE().mRenderEngine->getMaxTextureSize();
+ return getRenderEngine().getMaxTextureSize();
}
size_t SurfaceFlinger::getMaxViewportDims() const {
- return getBE().mRenderEngine->getMaxViewportDims();
+ return getRenderEngine().getMaxViewportDims();
}
// ----------------------------------------------------------------------------
@@ -939,14 +940,45 @@
return display->getActiveConfig();
}
-void SurfaceFlinger::setActiveConfigInternal(const sp<DisplayDevice>& display, int mode) {
+status_t SurfaceFlinger::setActiveConfigAsync(const sp<IBinder>& displayToken, int mode) {
+ ATRACE_NAME("setActiveConfigAsync");
+ postMessageAsync(new LambdaMessage([=] { setActiveConfigInternal(displayToken, mode); }));
+ return NO_ERROR;
+}
+
+status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mode) {
+ ATRACE_NAME("setActiveConfigSync");
+ postMessageSync(new LambdaMessage([&] { setActiveConfigInternal(displayToken, mode); }));
+ return NO_ERROR;
+}
+
+void SurfaceFlinger::setActiveConfigInternal(const sp<IBinder>& displayToken, int mode) {
+ Vector<DisplayInfo> configs;
+ getDisplayConfigs(displayToken, &configs);
+ if (mode < 0 || mode >= static_cast<int>(configs.size())) {
+ ALOGE("Attempt to set active config %d for display with %zu configs", mode, configs.size());
+ return;
+ }
+
+ const auto display = getDisplayDevice(displayToken);
+ if (!display) {
+ ALOGE("Attempt to set active config %d for invalid display token %p", mode,
+ displayToken.get());
+ return;
+ }
if (display->isVirtual()) {
- ALOGE("%s: Invalid operation on virtual display", __FUNCTION__);
+ ALOGW("Attempt to set active config %d for virtual display", mode);
+ return;
+ }
+ int currentDisplayPowerMode = display->getPowerMode();
+ if (currentDisplayPowerMode != HWC_POWER_MODE_NORMAL) {
+ // Don't change active config when in AoD.
return;
}
int currentMode = display->getActiveConfig();
if (mode == currentMode) {
+ // Don't update config if we are already running in the desired mode.
return;
}
@@ -955,29 +987,9 @@
display->setActiveConfig(mode);
getHwComposer().setActiveConfig(*displayId, mode);
-}
-status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mode) {
- postMessageSync(new LambdaMessage([&] {
- Vector<DisplayInfo> configs;
- getDisplayConfigs(displayToken, &configs);
- if (mode < 0 || mode >= static_cast<int>(configs.size())) {
- ALOGE("Attempt to set active config %d for display with %zu configs", mode,
- configs.size());
- return;
- }
- const auto display = getDisplayDevice(displayToken);
- if (!display) {
- ALOGE("Attempt to set active config %d for invalid display token %p", mode,
- displayToken.get());
- } else if (display->isVirtual()) {
- ALOGW("Attempt to set active config %d for virtual display", mode);
- } else {
- setActiveConfigInternal(display, mode);
- }
- }));
-
- return NO_ERROR;
+ ATRACE_INT("ActiveConfigMode", mode);
+ resyncToHardwareVsync(true);
}
status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& displayToken,
@@ -1387,6 +1399,49 @@
*compositorTiming = getBE().mCompositorTiming;
}
+void SurfaceFlinger::setRefreshRateTo(float newFps) {
+ const auto displayId = getInternalDisplayId();
+ if (!displayId || mBootStage != BootStage::FINISHED) {
+ return;
+ }
+ // TODO(b/113612090): There should be a message queue flush here. Because this esentially
+ // runs on a mainthread, we cannot call postMessageSync. This can be resolved in a better
+ // manner, once the setActiveConfig is synchronous, and is executed at a known time in a
+ // refresh cycle.
+
+ // Don't do any updating if the current fps is the same as the new one.
+ const auto activeConfig = getHwComposer().getActiveConfig(*displayId);
+ const nsecs_t currentVsyncPeriod = activeConfig->getVsyncPeriod();
+ if (currentVsyncPeriod == 0) {
+ return;
+ }
+ // TODO(b/113612090): Consider having an enum value for correct refresh rates, rather than
+ // floating numbers.
+ const float currentFps = 1e9 / currentVsyncPeriod;
+ if (std::abs(currentFps - newFps) <= 1) {
+ return;
+ }
+
+ auto configs = getHwComposer().getConfigs(*displayId);
+ for (int i = 0; i < configs.size(); i++) {
+ const nsecs_t vsyncPeriod = configs.at(i)->getVsyncPeriod();
+ if (vsyncPeriod == 0) {
+ continue;
+ }
+ const float fps = 1e9 / vsyncPeriod;
+ // TODO(b/113612090): There should be a better way at determining which config
+ // has the right refresh rate.
+ if (std::abs(fps - newFps) <= 1) {
+ const auto display = getBuiltInDisplay(HWC_DISPLAY_PRIMARY);
+ if (!display) return;
+ // This is posted in async function to avoid deadlock when getDisplayDevice
+ // requires mStateLock.
+ setActiveConfigAsync(display, i);
+ ATRACE_INT("FPS", newFps);
+ }
+ }
+}
+
void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,
HWC2::Connection connection) {
ALOGV("%s(%d, %" PRIu64 ", %s)", __FUNCTION__, sequenceId, hwcDisplayId,
@@ -1418,7 +1473,7 @@
if (sequenceId != getBE().mComposerSequenceId) {
return;
}
- repaintEverything();
+ repaintEverythingForHWC();
}
void SurfaceFlinger::setVsyncEnabled(EventThread::DisplayType /*displayType*/, bool enabled) {
@@ -1449,11 +1504,11 @@
if (!mVrFlinger)
return;
bool vrFlingerRequestsDisplay = mVrFlingerRequestsDisplay;
- if (vrFlingerRequestsDisplay == getBE().mHwc->isUsingVrComposer()) {
+ if (vrFlingerRequestsDisplay == getHwComposer().isUsingVrComposer()) {
return;
}
- if (vrFlingerRequestsDisplay && !getBE().mHwc->getComposer()->isRemote()) {
+ if (vrFlingerRequestsDisplay && !getHwComposer().getComposer()->isRemote()) {
ALOGE("Vr flinger is only supported for remote hardware composer"
" service connections. Ignoring request to transition to vr"
" flinger.");
@@ -1476,12 +1531,13 @@
}
resetDisplayState();
- getBE().mHwc.reset(); // Delete the current instance before creating the new one
- getBE().mHwc = getFactory().createHWComposer(
- vrFlingerRequestsDisplay ? "vr" : getBE().mHwcServiceName);
- getBE().mHwc->registerCallback(this, ++getBE().mComposerSequenceId);
+ // Delete the current instance before creating the new one
+ mCompositionEngine->setHwComposer(std::unique_ptr<HWComposer>());
+ mCompositionEngine->setHwComposer(getFactory().createHWComposer(
+ vrFlingerRequestsDisplay ? "vr" : getBE().mHwcServiceName));
+ getHwComposer().registerCallback(this, ++getBE().mComposerSequenceId);
- LOG_ALWAYS_FATAL_IF(!getBE().mHwc->getComposer()->isRemote(),
+ LOG_ALWAYS_FATAL_IF(!getHwComposer().getComposer()->isRemote(),
"Switched to non-remote hardware composer");
if (vrFlingerRequestsDisplay) {
@@ -1504,9 +1560,10 @@
// The present fences returned from vr_hwc are not an accurate
// representation of vsync times.
if (mUseScheduler) {
- mScheduler->setIgnorePresentFences(getBE().mHwc->isUsingVrComposer() || !hasSyncFramework);
+ mScheduler->setIgnorePresentFences(getHwComposer().isUsingVrComposer() ||
+ !hasSyncFramework);
} else {
- mPrimaryDispSync->setIgnorePresentFences(getBE().mHwc->isUsingVrComposer() ||
+ mPrimaryDispSync->setIgnorePresentFences(getHwComposer().isUsingVrComposer() ||
!hasSyncFramework);
}
@@ -1568,11 +1625,23 @@
bool SurfaceFlinger::handleMessageTransaction() {
uint32_t transactionFlags = peekTransactionFlags();
+
+ // Apply any ready transactions in the queues if there are still transactions that have not been
+ // applied, wake up during the next vsync period and check again
+ bool transactionNeeded = false;
+ if (!flushTransactionQueues()) {
+ transactionNeeded = true;
+ }
+
if (transactionFlags) {
handleTransaction(transactionFlags);
- return true;
}
- return false;
+
+ if (transactionNeeded) {
+ setTransactionFlags(eTransactionNeeded);
+ }
+
+ return transactionFlags;
}
void SurfaceFlinger::handleMessageRefresh() {
@@ -1599,12 +1668,12 @@
mHadClientComposition = false;
for (const auto& [token, display] : mDisplays) {
- mHadClientComposition = mHadClientComposition ||
- getBE().mHwc->hasClientComposition(display->getId());
+ mHadClientComposition =
+ mHadClientComposition || getHwComposer().hasClientComposition(display->getId());
}
// Setup RenderEngine sync fences if native sync is supported.
- if (getBE().mRenderEngine->useNativeFenceSync()) {
+ if (getRenderEngine().useNativeFenceSync()) {
if (mHadClientComposition) {
base::unique_fd flushFence(getRenderEngine().flush());
ALOGE_IF(flushFence < 0, "Failed to flush RenderEngine!");
@@ -1867,22 +1936,78 @@
getBE().mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
}
+// debug patch for b/119477596 - add stack guards to catch stack
+// corruptions and disable clang optimizations.
+// The code below is temporary and planned to be removed once stack
+// corruptions are found.
+#pragma clang optimize off
+class StackGuard {
+public:
+ StackGuard(const char* name, const char* func, int line) {
+ guarders.reserve(MIN_CAPACITY);
+ guarders.push_back({this, name, func, line});
+ validate();
+ }
+ ~StackGuard() {
+ for (auto i = guarders.end() - 1; i >= guarders.begin(); --i) {
+ if (i->guard == this) {
+ guarders.erase(i);
+ break;
+ }
+ }
+ }
+
+ static void validate() {
+ for (const auto& guard : guarders) {
+ if (guard.guard->cookie != COOKIE_VALUE) {
+ ALOGE("%s:%d: Stack corruption detected at %s", guard.func, guard.line, guard.name);
+ CallStack stack(LOG_TAG);
+ abort();
+ }
+ }
+ }
+
+private:
+ uint64_t cookie = COOKIE_VALUE;
+ static constexpr uint64_t COOKIE_VALUE = 0xc0febebedeadbeef;
+ static constexpr size_t MIN_CAPACITY = 16;
+
+ struct GuarderElement {
+ StackGuard* guard;
+ const char* name;
+ const char* func;
+ int line;
+ };
+
+ static std::vector<GuarderElement> guarders;
+};
+std::vector<StackGuard::GuarderElement> StackGuard::guarders;
+
+#define DEFINE_STACK_GUARD(__n) StackGuard __n##StackGuard(#__n, __FUNCTION__, __LINE__);
+
+#define ASSERT_ON_STACK_GUARD() StackGuard::validate();
void SurfaceFlinger::postComposition()
{
+ DEFINE_STACK_GUARD(begin);
ATRACE_CALL();
ALOGV("postComposition");
// Release any buffers which were replaced this frame
nsecs_t dequeueReadyTime = systemTime();
+ DEFINE_STACK_GUARD(dequeueReadyTime);
for (auto& layer : mLayersWithQueuedFrames) {
layer->releasePendingBuffer(dequeueReadyTime);
}
+ ASSERT_ON_STACK_GUARD();
// |mStateLock| not needed as we are on the main thread
const auto display = getDefaultDisplayDeviceLocked();
+ DEFINE_STACK_GUARD(display);
getBE().mGlCompositionDoneTimeline.updateSignalTimes();
std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
+ DEFINE_STACK_GUARD(glCompositionDoneFenceTime);
+
if (display && getHwComposer().hasClientComposition(display->getId())) {
glCompositionDoneFenceTime =
std::make_shared<FenceTime>(display->getClientTargetAcquireFence());
@@ -1891,13 +2016,17 @@
glCompositionDoneFenceTime = FenceTime::NO_FENCE;
}
+ ASSERT_ON_STACK_GUARD();
+
getBE().mDisplayTimeline.updateSignalTimes();
mPreviousPresentFence =
display ? getHwComposer().getPresentFence(*display->getId()) : Fence::NO_FENCE;
auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFence);
+ DEFINE_STACK_GUARD(presentFenceTime);
getBE().mDisplayTimeline.push(presentFenceTime);
DisplayStatInfo stats;
+ DEFINE_STACK_GUARD(stats);
if (mUseScheduler) {
mScheduler->getDisplayStatInfo(&stats);
} else {
@@ -1905,34 +2034,46 @@
stats.vsyncPeriod = mPrimaryDispSync->getPeriod();
}
+ ASSERT_ON_STACK_GUARD();
+
// We use the mRefreshStartTime which might be sampled a little later than
// when we started doing work for this frame, but that should be okay
// since updateCompositorTiming has snapping logic.
updateCompositorTiming(stats, mRefreshStartTime, presentFenceTime);
CompositorTiming compositorTiming;
+ DEFINE_STACK_GUARD(compositorTiming);
+
{
std::lock_guard<std::mutex> lock(getBE().mCompositorTimingLock);
+ DEFINE_STACK_GUARD(lock);
compositorTiming = getBE().mCompositorTiming;
+
+ ASSERT_ON_STACK_GUARD();
}
mDrawingState.traverseInZOrder([&](Layer* layer) {
bool frameLatched = layer->onPostComposition(display->getId(), glCompositionDoneFenceTime,
presentFenceTime, compositorTiming);
+ DEFINE_STACK_GUARD(frameLatched);
if (frameLatched) {
recordBufferingStats(layer->getName().string(),
layer->getOccupancyHistory(false));
}
+ ASSERT_ON_STACK_GUARD();
});
if (presentFenceTime->isValid()) {
+ ASSERT_ON_STACK_GUARD();
if (mUseScheduler) {
mScheduler->addPresentFence(presentFenceTime);
+ ASSERT_ON_STACK_GUARD();
} else {
if (mPrimaryDispSync->addPresentFence(presentFenceTime)) {
enableHardwareVsync();
} else {
disableHardwareVsync(false);
}
+ ASSERT_ON_STACK_GUARD();
}
}
@@ -1946,61 +2087,86 @@
}
}
+ ASSERT_ON_STACK_GUARD();
+
if (mAnimCompositionPending) {
mAnimCompositionPending = false;
if (presentFenceTime->isValid()) {
mAnimFrameTracker.setActualPresentFence(
std::move(presentFenceTime));
+
+ ASSERT_ON_STACK_GUARD();
} else if (display && getHwComposer().isConnected(*display->getId())) {
// The HWC doesn't support present fences, so use the refresh
// timestamp instead.
const nsecs_t presentTime = getHwComposer().getRefreshTimestamp(*display->getId());
+ DEFINE_STACK_GUARD(presentTime);
+
mAnimFrameTracker.setActualPresentTime(presentTime);
+ ASSERT_ON_STACK_GUARD();
}
mAnimFrameTracker.advanceFrame();
}
+ ASSERT_ON_STACK_GUARD();
+
mTimeStats->incrementTotalFrames();
if (mHadClientComposition) {
mTimeStats->incrementClientCompositionFrames();
}
+ ASSERT_ON_STACK_GUARD();
+
mTimeStats->setPresentFenceGlobal(presentFenceTime);
+ ASSERT_ON_STACK_GUARD();
+
if (display && getHwComposer().isConnected(*display->getId()) && !display->isPoweredOn()) {
return;
}
nsecs_t currentTime = systemTime();
+ DEFINE_STACK_GUARD(currentTime);
if (mHasPoweredOff) {
mHasPoweredOff = false;
} else {
nsecs_t elapsedTime = currentTime - getBE().mLastSwapTime;
+ DEFINE_STACK_GUARD(elapsedTime);
size_t numPeriods = static_cast<size_t>(elapsedTime / stats.vsyncPeriod);
+ DEFINE_STACK_GUARD(numPeriods);
if (numPeriods < SurfaceFlingerBE::NUM_BUCKETS - 1) {
getBE().mFrameBuckets[numPeriods] += elapsedTime;
} else {
getBE().mFrameBuckets[SurfaceFlingerBE::NUM_BUCKETS - 1] += elapsedTime;
}
getBE().mTotalTime += elapsedTime;
+
+ ASSERT_ON_STACK_GUARD();
}
getBE().mLastSwapTime = currentTime;
+ ASSERT_ON_STACK_GUARD();
{
std::lock_guard lock(mTexturePoolMutex);
+ DEFINE_STACK_GUARD(lock);
const size_t refillCount = mTexturePoolSize - mTexturePool.size();
+ DEFINE_STACK_GUARD(refillCount);
if (refillCount > 0) {
const size_t offset = mTexturePool.size();
mTexturePool.resize(mTexturePoolSize);
getRenderEngine().genTextures(refillCount, mTexturePool.data() + offset);
ATRACE_INT("TexturePoolSize", mTexturePool.size());
}
+ ASSERT_ON_STACK_GUARD();
}
mTransactionCompletedThread.addPresentFence(mPreviousPresentFence);
mTransactionCompletedThread.sendCallbacks();
+
+ ASSERT_ON_STACK_GUARD();
}
+#pragma clang optimize on // b/119477596
void SurfaceFlinger::rebuildLayerStacks() {
ATRACE_CALL();
@@ -2273,7 +2439,7 @@
// supply them with the present fence.
if (!display->getLayersNeedingFences().isEmpty()) {
sp<Fence> presentFence =
- displayId ? getBE().mHwc->getPresentFence(*displayId) : Fence::NO_FENCE;
+ displayId ? getHwComposer().getPresentFence(*displayId) : Fence::NO_FENCE;
for (auto& layer : display->getLayersNeedingFences()) {
layer->getBE().onLayerDisplayed(presentFence);
}
@@ -2739,6 +2905,7 @@
if (inputChanged || mVisibleRegionsDirty) {
updateInputWindows();
}
+ executeInputWindowCommands();
updateCursorAsync();
}
@@ -2763,6 +2930,23 @@
mInputFlinger->setInputWindows(inputHandles);
}
+void SurfaceFlinger::executeInputWindowCommands() {
+ if (!mInputFlinger) {
+ return;
+ }
+
+ for (const auto& transferTouchFocusCommand : mInputWindowCommands.transferTouchFocusCommands) {
+ if (transferTouchFocusCommand.fromToken != nullptr &&
+ transferTouchFocusCommand.toToken != nullptr &&
+ transferTouchFocusCommand.fromToken != transferTouchFocusCommand.toToken) {
+ mInputFlinger->transferTouchFocus(transferTouchFocusCommand.fromToken,
+ transferTouchFocusCommand.toToken);
+ }
+ }
+
+ mInputWindowCommands.clear();
+}
+
void SurfaceFlinger::updateCursorAsync()
{
for (const auto& [token, display] : mDisplays) {
@@ -2800,10 +2984,8 @@
// showing at its last configured state until we eventually
// abandon the buffer queue.
if (l->isRemovedFromCurrentState()) {
- l->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* child) {
- child->destroyHwcLayersForAllDisplays();
- latchAndReleaseBuffer(child);
- });
+ l->destroyHwcLayersForAllDisplays();
+ latchAndReleaseBuffer(l);
}
}
mLayersPendingRemoval.clear();
@@ -2837,6 +3019,9 @@
outDirtyRegion.clear();
mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
+ // start with the whole surface at its current location
+ const Layer::State& s(layer->getDrawingState());
+
// only consider the layers on the given layer stack
if (!layer->belongsToDisplay(display->getLayerStack(), display->isPrimary())) {
return;
@@ -2874,7 +3059,7 @@
// handle hidden surfaces by setting the visible region to empty
if (CC_LIKELY(layer->isVisible())) {
- const bool translucent = !layer->isDrawingOpaque();
+ const bool translucent = !layer->isOpaque(s);
Rect bounds(layer->computeScreenBounds());
visibleRegion.set(bounds);
@@ -2884,8 +3069,7 @@
if (translucent) {
if (tr.preserveRects()) {
// transform the transparent region
- transparentRegion =
- tr.transform(layer->getDrawingActiveTransparentRegion());
+ transparentRegion = tr.transform(layer->getActiveTransparentRegion(s));
} else {
// transformation too complex, can't do the
// transparent region optimization.
@@ -3003,12 +3187,18 @@
}
});
- for (auto& layer : mLayersWithQueuedFrames) {
- const Region dirty(layer->latchBuffer(visibleRegions, latchTime, getBE().flushFence));
- layer->useSurfaceDamage();
- invalidateLayerStack(layer, dirty);
- if (layer->isBufferLatched()) {
- newDataLatched = true;
+ if (!mLayersWithQueuedFrames.empty()) {
+ // mStateLock is needed for latchBuffer as LayerRejecter::reject()
+ // writes to Layer current state. See also b/119481871
+ Mutex::Autolock lock(mStateLock);
+
+ for (auto& layer : mLayersWithQueuedFrames) {
+ const Region dirty(layer->latchBuffer(visibleRegions, latchTime, getBE().flushFence));
+ layer->useSurfaceDamage();
+ invalidateLayerStack(layer, dirty);
+ if (layer->isBufferLatched()) {
+ newDataLatched = true;
+ }
}
}
@@ -3070,7 +3260,7 @@
const Region bounds(display->bounds());
const DisplayRenderArea renderArea(display);
const auto displayId = display->getId();
- const bool hasClientComposition = getBE().mHwc->hasClientComposition(displayId);
+ const bool hasClientComposition = getHwComposer().hasClientComposition(displayId);
ATRACE_INT("hasClientComposition", hasClientComposition);
mat4 colorMatrix;
@@ -3105,15 +3295,15 @@
if (display->hasWideColorGamut()) {
outputDataspace = display->getCompositionDataSpace();
}
- getBE().mRenderEngine->setOutputDataSpace(outputDataspace);
- getBE().mRenderEngine->setDisplayMaxLuminance(
+ getRenderEngine().setOutputDataSpace(outputDataspace);
+ getRenderEngine().setDisplayMaxLuminance(
display->getHdrCapabilities().getDesiredMaxLuminance());
- const bool hasDeviceComposition = getBE().mHwc->hasDeviceComposition(displayId);
+ const bool hasDeviceComposition = getHwComposer().hasDeviceComposition(displayId);
const bool skipClientColorTransform =
- getBE().mHwc
- ->hasDisplayCapability(displayId,
- HWC2::DisplayCapability::SkipClientColorTransform);
+ getHwComposer()
+ .hasDisplayCapability(displayId,
+ HWC2::DisplayCapability::SkipClientColorTransform);
// Compute the global color transform matrix.
applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform;
@@ -3130,7 +3320,7 @@
// remove where there are opaque FB layers. however, on some
// GPUs doing a "clean slate" clear might be more efficient.
// We'll revisit later if needed.
- getBE().mRenderEngine->clearWithColor(0, 0, 0, 0);
+ getRenderEngine().clearWithColor(0, 0, 0, 0);
} else {
// we start with the whole screen area and remove the scissor part
// we're left with the letterbox region
@@ -3155,7 +3345,7 @@
// the GL scissor so we don't draw anything where we shouldn't
// enable scissor for this frame
- getBE().mRenderEngine->setScissor(scissor);
+ getRenderEngine().setScissor(scissor);
}
}
@@ -3178,8 +3368,9 @@
case HWC2::Composition::Sideband:
case HWC2::Composition::SolidColor: {
LOG_ALWAYS_FATAL_IF(!displayId);
+ const Layer::State& state(layer->getDrawingState());
if (layer->getClearClientTarget(*displayId) && !firstLayer &&
- layer->isDrawingOpaque() && (layer->getAlpha() == 1.0f) &&
+ layer->isOpaque(state) && (layer->getAlpha() == 1.0f) &&
layer->getRoundedCornerState().radius == 0.0f && hasClientComposition) {
// never clear the very first layer since we're
// guaranteed the FB is already cleared
@@ -3213,7 +3404,7 @@
// Perform some cleanup steps if we used client composition.
if (hasClientComposition) {
getRenderEngine().setColorTransform(mat4());
- getBE().mRenderEngine->disableScissor();
+ getRenderEngine().disableScissor();
display->finishBuffer();
// Clear out error flags here so that we don't wait until next
// composition to log.
@@ -3231,7 +3422,8 @@
const sp<IBinder>& handle,
const sp<IGraphicBufferProducer>& gbc,
const sp<Layer>& lbc,
- const sp<Layer>& parent)
+ const sp<Layer>& parent,
+ bool addToCurrentState)
{
// add this layer to the current state list
{
@@ -3241,13 +3433,12 @@
MAX_LAYERS);
return NO_MEMORY;
}
- if (parent == nullptr) {
+ if (parent == nullptr && addToCurrentState) {
mCurrentState.layersSortedByZ.add(lbc);
- } else {
- if (parent->isRemovedFromCurrentState()) {
+ } else if (parent == nullptr || parent->isRemovedFromCurrentState()) {
ALOGE("addClientLayer called with a removed parent");
lbc->onRemovedFromCurrentState();
- }
+ } else {
parent->addChild(lbc);
}
@@ -3268,30 +3459,6 @@
return NO_ERROR;
}
-status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer) {
- Mutex::Autolock _l(mStateLock);
- return removeLayerLocked(mStateLock, layer);
-}
-
-status_t SurfaceFlinger::removeLayerLocked(const Mutex& lock, const sp<Layer>& layer) {
- if (layer->isLayerDetached()) {
- return NO_ERROR;
- }
-
- const auto& p = layer->getParent();
- ssize_t index;
- if (p != nullptr) {
- index = p->removeChild(layer);
- } else {
- index = mCurrentState.layersSortedByZ.remove(layer);
- }
-
- layer->onRemovedFromCurrentState();
-
- markLayerPendingRemovalLocked(lock, layer);
- return NO_ERROR;
-}
-
uint32_t SurfaceFlinger::peekTransactionFlags() {
return mTransactionFlags;
}
@@ -3314,6 +3481,26 @@
return old;
}
+bool SurfaceFlinger::flushTransactionQueues() {
+ Mutex::Autolock _l(mStateLock);
+ auto it = mTransactionQueues.begin();
+ while (it != mTransactionQueues.end()) {
+ auto& [applyToken, transactionQueue] = *it;
+
+ while (!transactionQueue.empty()) {
+ const auto& [states, displays, flags] = transactionQueue.front();
+ if (composerStateContainsUnsignaledFences(states)) {
+ break;
+ }
+ applyTransactionState(states, displays, flags, mInputWindowCommands);
+ transactionQueue.pop();
+ }
+
+ it = (transactionQueue.empty()) ? mTransactionQueues.erase(it) : std::next(it, 1);
+ }
+ return mTransactionQueues.empty();
+}
+
bool SurfaceFlinger::containsAnyInvalidClientState(const Vector<ComposerState>& states) {
for (const ComposerState& state : states) {
// Here we need to check that the interface we're given is indeed
@@ -3336,19 +3523,46 @@
return false;
}
-void SurfaceFlinger::setTransactionState(
- const Vector<ComposerState>& states,
- const Vector<DisplayState>& displays,
- uint32_t flags)
-{
+bool SurfaceFlinger::composerStateContainsUnsignaledFences(const Vector<ComposerState>& states) {
+ for (const ComposerState& state : states) {
+ const layer_state_t& s = state.state;
+ if (!(s.what & layer_state_t::eAcquireFenceChanged)) {
+ continue;
+ }
+ if (s.acquireFence && s.acquireFence->getStatus() == Fence::Status::Unsignaled) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void SurfaceFlinger::setTransactionState(const Vector<ComposerState>& states,
+ const Vector<DisplayState>& displays, uint32_t flags,
+ const sp<IBinder>& applyToken,
+ const InputWindowCommands& inputWindowCommands) {
ATRACE_CALL();
Mutex::Autolock _l(mStateLock);
- uint32_t transactionFlags = 0;
if (containsAnyInvalidClientState(states)) {
return;
}
+ // If its TransactionQueue already has a pending TransactionState or if it is pending
+ if (mTransactionQueues.find(applyToken) != mTransactionQueues.end() ||
+ composerStateContainsUnsignaledFences(states)) {
+ mTransactionQueues[applyToken].emplace(states, displays, flags);
+ setTransactionFlags(eTransactionNeeded);
+ return;
+ }
+
+ applyTransactionState(states, displays, flags, inputWindowCommands);
+}
+
+void SurfaceFlinger::applyTransactionState(const Vector<ComposerState>& states,
+ const Vector<DisplayState>& displays, uint32_t flags,
+ const InputWindowCommands& inputWindowCommands) {
+ uint32_t transactionFlags = 0;
+
if (flags & eAnimation) {
// For window updates that are part of an animation we must wait for
// previous animation "frames" to be handled.
@@ -3379,13 +3593,7 @@
}
transactionFlags |= clientStateFlags;
- // Iterate through all layers again to determine if any need to be destroyed. Marking layers
- // as destroyed should only occur after setting all other states. This is to allow for a
- // child re-parent to happen before marking its original parent as destroyed (which would
- // then mark the child as destroyed).
- for (const ComposerState& state : states) {
- setDestroyStateLocked(state);
- }
+ transactionFlags |= addInputWindowCommands(inputWindowCommands);
// If a synchronous transaction is explicitly requested without any changes, force a transaction
// anyway. This can be used as a flush mechanism for previous async transactions.
@@ -3710,18 +3918,14 @@
return flags;
}
-void SurfaceFlinger::setDestroyStateLocked(const ComposerState& composerState) {
- const layer_state_t& state = composerState.state;
- sp<Client> client(static_cast<Client*>(composerState.client.get()));
-
- sp<Layer> layer(client->getLayerUser(state.surface));
- if (layer == nullptr) {
- return;
+uint32_t SurfaceFlinger::addInputWindowCommands(const InputWindowCommands& inputWindowCommands) {
+ uint32_t flags = 0;
+ if (!inputWindowCommands.transferTouchFocusCommands.empty()) {
+ flags |= eTraversalNeeded;
}
- if (state.what & layer_state_t::eDestroySurface) {
- removeLayerLocked(mStateLock, layer);
- }
+ mInputWindowCommands.merge(inputWindowCommands);
+ return flags;
}
status_t SurfaceFlinger::createLayer(
@@ -3793,7 +3997,9 @@
layer->setInfo(windowType, ownerUid);
- result = addClientLayer(client, *handle, *gbp, layer, *parent);
+ bool addToCurrentState = callingThreadHasUnscopedSurfaceFlingerAccess();
+ result = addClientLayer(client, *handle, *gbp, layer, *parent,
+ addToCurrentState);
if (result != NO_ERROR) {
return result;
}
@@ -3891,21 +4097,7 @@
}
-status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle)
-{
- // called by a client when it wants to remove a Layer
- status_t err = NO_ERROR;
- sp<Layer> l(client->getLayerUser(handle));
- if (l != nullptr) {
- mInterceptor->saveSurfaceDeletion(l);
- err = removeLayer(l);
- ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
- "error removing layer=%p (%s)", l.get(), strerror(-err));
- }
- return err;
-}
-
-void SurfaceFlinger::markLayerPendingRemovalLocked(const Mutex&, const sp<Layer>& layer) {
+void SurfaceFlinger::markLayerPendingRemovalLocked(const sp<Layer>& layer) {
mLayersPendingRemoval.add(layer);
mLayersRemoved = true;
setTransactionFlags(eTransactionNeeded);
@@ -3914,7 +4106,14 @@
void SurfaceFlinger::onHandleDestroyed(sp<Layer>& layer)
{
Mutex::Autolock lock(mStateLock);
- markLayerPendingRemovalLocked(mStateLock, layer);
+ // If a layer has a parent, we allow it to out-live it's handle
+ // with the idea that the parent holds a reference and will eventually
+ // be cleaned up. However no one cleans up the top-level so we do so
+ // here.
+ if (layer->getParent() == nullptr) {
+ mCurrentState.layersSortedByZ.remove(layer);
+ }
+ markLayerPendingRemovalLocked(layer);
layer.clear();
}
@@ -3938,7 +4137,7 @@
d.width = 0;
d.height = 0;
displays.add(d);
- setTransactionState(state, displays, 0);
+ setTransactionState(state, displays, 0, nullptr, mInputWindowCommands);
const auto display = getDisplayDevice(displayToken);
if (!display) return;
@@ -4611,7 +4810,7 @@
result.append("SurfaceFlinger global state:\n");
colorizer.reset(result);
- getBE().mRenderEngine->dump(result);
+ getRenderEngine().dump(result);
if (const auto display = getDefaultDisplayDeviceLocked()) {
display->undefinedRegion.dump(result, "undefinedRegion");
@@ -4757,7 +4956,6 @@
// access to SF.
case BOOT_FINISHED:
case CLEAR_ANIMATION_FRAME_STATS:
- case CREATE_CONNECTION:
case CREATE_DISPLAY:
case DESTROY_DISPLAY:
case ENABLE_VSYNC_INJECTIONS:
@@ -4804,8 +5002,7 @@
// Calling setTransactionState is safe, because you need to have been
// granted a reference to Client* and Handle* to do anything with it.
case SET_TRANSACTION_STATE:
- // Creating a scoped connection is safe, as per discussion in ISurfaceComposer.h
- case CREATE_SCOPED_CONNECTION:
+ case CREATE_CONNECTION:
case GET_COLOR_MANAGEMENT:
case GET_COMPOSITION_PREFERENCE: {
return OK;
@@ -5087,7 +5284,7 @@
// Is VrFlinger active?
case 1028: {
Mutex::Autolock _l(mStateLock);
- reply->writeBool(getBE().mHwc->isUsingVrComposer());
+ reply->writeBool(getHwComposer().isUsingVrComposer());
return NO_ERROR;
}
// Is device color managed?
@@ -5137,6 +5334,11 @@
signalTransaction();
}
+void SurfaceFlinger::repaintEverythingForHWC() {
+ mRepaintEverything = true;
+ mEventQueue->invalidateForHWC();
+}
+
// A simple RAII class to disconnect from an ANativeWindow* when it goes out of scope
class WindowDisconnector {
public:
@@ -5204,12 +5406,15 @@
mFlinger(flinger),
mChildrenOnly(childrenOnly) {}
const ui::Transform& getTransform() const override { return mTransform; }
- Rect getBounds() const override { return mLayer->getBufferSize(StateSet::Drawing); }
+ Rect getBounds() const override {
+ const Layer::State& layerState(mLayer->getDrawingState());
+ return mLayer->getBufferSize(layerState);
+ }
int getHeight() const override {
- return mLayer->getBufferSize(StateSet::Drawing).getHeight();
+ return mLayer->getBufferSize(mLayer->getDrawingState()).getHeight();
}
int getWidth() const override {
- return mLayer->getBufferSize(StateSet::Drawing).getWidth();
+ return mLayer->getBufferSize(mLayer->getDrawingState()).getWidth();
}
bool isSecure() const override { return false; }
bool needsFiltering() const override { return mNeedsFiltering; }
@@ -5276,7 +5481,7 @@
const int uid = IPCThreadState::self()->getCallingUid();
const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM;
- if (!forSystem && parent->getCurrentFlags() & layer_state_t::eLayerSecure) {
+ if (!forSystem && parent->getCurrentState().flags & layer_state_t::eLayerSecure) {
ALOGW("Attempting to capture secure layer: PERMISSION_DENIED");
return PERMISSION_DENIED;
}
@@ -5284,12 +5489,12 @@
Rect crop(sourceCrop);
if (sourceCrop.width() <= 0) {
crop.left = 0;
- crop.right = parent->getBufferSize(StateSet::Current).getWidth();
+ crop.right = parent->getBufferSize(parent->getCurrentState()).getWidth();
}
if (sourceCrop.height() <= 0) {
crop.top = 0;
- crop.bottom = parent->getBufferSize(StateSet::Current).getHeight();
+ crop.bottom = parent->getBufferSize(parent->getCurrentState()).getHeight();
}
int32_t reqWidth = crop.width() * frameScale;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index b1bfb3a..134f9c2 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -25,53 +25,46 @@
* NOTE: Make sure this file doesn't include anything from <gl/ > or <gl2/ >
*/
-#include <cutils/compiler.h>
#include <cutils/atomic.h>
-
-#include <utils/Errors.h>
-#include <utils/KeyedVector.h>
-#include <utils/RefBase.h>
-#include <utils/SortedVector.h>
-#include <utils/threads.h>
-#include <utils/Trace.h>
-
-#include <ui/FenceTime.h>
-#include <ui/PixelFormat.h>
-#include <math/mat4.h>
-
+#include <cutils/compiler.h>
+#include <gui/BufferQueue.h>
#include <gui/FrameTimestamps.h>
#include <gui/ISurfaceComposer.h>
#include <gui/ISurfaceComposerClient.h>
#include <gui/LayerState.h>
-
#include <gui/OccupancyTracker.h>
-#include <gui/BufferQueue.h>
-
#include <hardware/hwcomposer_defs.h>
-
+#include <layerproto/LayerProtoHeader.h>
+#include <math/mat4.h>
#include <serviceutils/PriorityDumper.h>
-
#include <system/graphics.h>
+#include <ui/FenceTime.h>
+#include <ui/PixelFormat.h>
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+#include <utils/SortedVector.h>
+#include <utils/Trace.h>
+#include <utils/threads.h>
#include "Barrier.h"
#include "DisplayDevice.h"
+#include "DisplayHardware/HWC2.h"
+#include "DisplayHardware/HWComposer.h"
+#include "Effects/Daltonizer.h"
#include "FrameTracker.h"
#include "LayerBE.h"
#include "LayerStats.h"
#include "LayerVector.h"
-#include "SurfaceFlingerFactory.h"
-#include "SurfaceInterceptor.h"
-#include "SurfaceTracing.h"
-#include "TransactionCompletedThread.h"
-
-#include "DisplayHardware/HWC2.h"
-#include "DisplayHardware/HWComposer.h"
-#include "Effects/Daltonizer.h"
#include "Scheduler/DispSync.h"
#include "Scheduler/EventThread.h"
#include "Scheduler/MessageQueue.h"
#include "Scheduler/Scheduler.h"
#include "Scheduler/VSyncModulator.h"
+#include "SurfaceFlingerFactory.h"
+#include "SurfaceInterceptor.h"
+#include "SurfaceTracing.h"
+#include "TransactionCompletedThread.h"
#include <map>
#include <mutex>
@@ -82,8 +75,6 @@
#include <unordered_map>
#include <utility>
-#include <layerproto/LayerProtoHeader.h>
-
using namespace android::surfaceflinger;
namespace android {
@@ -146,35 +137,8 @@
public:
SurfaceFlingerBE();
- // The current hardware composer interface.
- //
- // The following thread safety rules apply when accessing mHwc, either
- // directly or via getHwComposer():
- //
- // 1. When recreating mHwc, acquire mStateLock. We currently recreate mHwc
- // only when switching into and out of vr. Recreating mHwc must only be
- // done on the main thread.
- //
- // 2. When accessing mHwc on the main thread, it's not necessary to acquire
- // mStateLock.
- //
- // 3. When accessing mHwc on a thread other than the main thread, we always
- // need to acquire mStateLock. This is because the main thread could be
- // in the process of destroying the current mHwc instance.
- //
- // The above thread safety rules only apply to SurfaceFlinger.cpp. In
- // SurfaceFlinger_hwc1.cpp we create mHwc at surface flinger init and never
- // destroy it, so it's always safe to access mHwc from any thread without
- // acquiring mStateLock.
- std::unique_ptr<HWComposer> mHwc;
-
const std::string mHwcServiceName; // "default" for real use, something else for testing.
- // constant members (no synchronization needed for access)
- std::unique_ptr<renderengine::RenderEngine> mRenderEngine;
- EGLContext mEGLContext;
- EGLDisplay mEGLDisplay;
-
FenceTimeline mGlCompositionDoneTimeline;
FenceTimeline mDisplayTimeline;
@@ -334,8 +298,14 @@
// force full composition on all displays
void repaintEverything();
+ // force full composition on all displays without resetting the scheduler idle timer.
+ void repaintEverythingForHWC();
+
surfaceflinger::Factory& getFactory() { return mFactory; }
+ // The CompositionEngine encapsulates all composition related interfaces and actions.
+ compositionengine::CompositionEngine& getCompositionEngine() const;
+
// returns the default Display
sp<const DisplayDevice> getDefaultDisplayDevice() const {
Mutex::Autolock _l(mStateLock);
@@ -362,7 +332,7 @@
// TODO: this should be made accessible only to HWComposer
const Vector<sp<Layer>>& getLayerSortedByZForHwcDisplay(DisplayId displayId);
- renderengine::RenderEngine& getRenderEngine() const { return *getBE().mRenderEngine; }
+ renderengine::RenderEngine& getRenderEngine() const;
bool authenticateSurfaceTextureLocked(
const sp<IGraphicBufferProducer>& bufferProducer) const;
@@ -429,76 +399,74 @@
/* ------------------------------------------------------------------------
* IBinder interface
*/
- virtual status_t onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags);
- virtual status_t dump(int fd, const Vector<String16>& args) { return priorityDump(fd, args); }
+ status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override;
+ status_t dump(int fd, const Vector<String16>& args) override { return priorityDump(fd, args); }
/* ------------------------------------------------------------------------
* ISurfaceComposer interface
*/
- virtual sp<ISurfaceComposerClient> createConnection();
- virtual sp<ISurfaceComposerClient> createScopedConnection(const sp<IGraphicBufferProducer>& gbp);
- virtual sp<IBinder> createDisplay(const String8& displayName, bool secure);
- virtual void destroyDisplay(const sp<IBinder>& displayToken);
- virtual sp<IBinder> getBuiltInDisplay(int32_t id);
- virtual void setTransactionState(const Vector<ComposerState>& state,
- const Vector<DisplayState>& displays, uint32_t flags);
- virtual void bootFinished();
- virtual bool authenticateSurfaceTexture(
- const sp<IGraphicBufferProducer>& bufferProducer) const;
- virtual status_t getSupportedFrameTimestamps(
- std::vector<FrameEvent>* outSupported) const;
- virtual sp<IDisplayEventConnection> createDisplayEventConnection(
- ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp);
- virtual status_t captureScreen(const sp<IBinder>& displayToken, sp<GraphicBuffer>* outBuffer,
- const ui::Dataspace reqDataspace,
- const ui::PixelFormat reqPixelFormat, Rect sourceCrop,
- uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform,
- ISurfaceComposer::Rotation rotation);
- virtual status_t captureLayers(const sp<IBinder>& parentHandle, sp<GraphicBuffer>* outBuffer,
- const ui::Dataspace reqDataspace,
- const ui::PixelFormat reqPixelFormat, const Rect& sourceCrop,
- float frameScale, bool childrenOnly);
- virtual status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats);
- virtual status_t getDisplayConfigs(const sp<IBinder>& displayToken,
- Vector<DisplayInfo>* configs);
- virtual int getActiveConfig(const sp<IBinder>& displayToken);
- virtual status_t getDisplayColorModes(const sp<IBinder>& displayToken,
- Vector<ui::ColorMode>* configs);
- virtual ui::ColorMode getActiveColorMode(const sp<IBinder>& displayToken);
- virtual status_t setActiveColorMode(const sp<IBinder>& displayToken, ui::ColorMode colorMode);
- virtual void setPowerMode(const sp<IBinder>& displayToken, int mode);
- virtual status_t setActiveConfig(const sp<IBinder>& displayToken, int id);
- virtual status_t clearAnimationFrameStats();
- virtual status_t getAnimationFrameStats(FrameStats* outStats) const;
- virtual status_t getHdrCapabilities(const sp<IBinder>& displayToken,
- HdrCapabilities* outCapabilities) const;
- virtual status_t enableVSyncInjections(bool enable);
- virtual status_t injectVSync(nsecs_t when);
- virtual status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const;
- virtual status_t getColorManagement(bool* outGetColorManagement) const;
+ sp<ISurfaceComposerClient> createConnection() override;
+ sp<IBinder> createDisplay(const String8& displayName, bool secure) override;
+ void destroyDisplay(const sp<IBinder>& displayToken) override;
+ sp<IBinder> getBuiltInDisplay(int32_t id) override;
+ void setTransactionState(const Vector<ComposerState>& state,
+ const Vector<DisplayState>& displays, uint32_t flags,
+ const sp<IBinder>& applyToken,
+ const InputWindowCommands& inputWindowCommands) override;
+ void bootFinished() override;
+ bool authenticateSurfaceTexture(
+ const sp<IGraphicBufferProducer>& bufferProducer) const override;
+ status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported) const override;
+ sp<IDisplayEventConnection> createDisplayEventConnection(
+ ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp) override;
+ status_t captureScreen(const sp<IBinder>& displayToken, sp<GraphicBuffer>* outBuffer,
+ const ui::Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat,
+ Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+ bool useIdentityTransform, ISurfaceComposer::Rotation rotation) override;
+ status_t captureLayers(const sp<IBinder>& parentHandle, sp<GraphicBuffer>* outBuffer,
+ const ui::Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat,
+ const Rect& sourceCrop, float frameScale, bool childrenOnly) override;
+ status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats) override;
+ status_t getDisplayConfigs(const sp<IBinder>& displayToken,
+ Vector<DisplayInfo>* configs) override;
+ int getActiveConfig(const sp<IBinder>& displayToken) override;
+ status_t getDisplayColorModes(const sp<IBinder>& displayToken,
+ Vector<ui::ColorMode>* configs) override;
+ ui::ColorMode getActiveColorMode(const sp<IBinder>& displayToken) override;
+ status_t setActiveColorMode(const sp<IBinder>& displayToken, ui::ColorMode colorMode) override;
+ void setPowerMode(const sp<IBinder>& displayToken, int mode) override;
+ status_t setActiveConfig(const sp<IBinder>& displayToken, int id) override;
+ status_t clearAnimationFrameStats() override;
+ status_t getAnimationFrameStats(FrameStats* outStats) const override;
+ status_t getHdrCapabilities(const sp<IBinder>& displayToken,
+ HdrCapabilities* outCapabilities) const override;
+ status_t enableVSyncInjections(bool enable) override;
+ status_t injectVSync(nsecs_t when) override;
+ status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const override;
+ status_t getColorManagement(bool* outGetColorManagement) const override;
status_t getCompositionPreference(ui::Dataspace* outDataspace, ui::PixelFormat* outPixelFormat,
ui::Dataspace* outWideColorGamutDataspace,
ui::PixelFormat* outWideColorGamutPixelFormat) const override;
- virtual status_t getDisplayedContentSamplingAttributes(
- const sp<IBinder>& display, ui::PixelFormat* outFormat, ui::Dataspace* outDataspace,
- uint8_t* outComponentMask) const override;
- virtual status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
- uint8_t componentMask,
- uint64_t maxFrames) const override;
- virtual status_t getDisplayedContentSample(const sp<IBinder>& display, uint64_t maxFrames,
- uint64_t timestamp,
- DisplayedFrameStats* outStats) const override;
+ status_t getDisplayedContentSamplingAttributes(const sp<IBinder>& display,
+ ui::PixelFormat* outFormat,
+ ui::Dataspace* outDataspace,
+ uint8_t* outComponentMask) const override;
+ status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
+ uint8_t componentMask,
+ uint64_t maxFrames) const override;
+ status_t getDisplayedContentSample(const sp<IBinder>& display, uint64_t maxFrames,
+ uint64_t timestamp,
+ DisplayedFrameStats* outStats) const override;
/* ------------------------------------------------------------------------
* DeathRecipient interface
*/
- virtual void binderDied(const wp<IBinder>& who);
+ void binderDied(const wp<IBinder>& who) override;
/* ------------------------------------------------------------------------
* RefBase interface
*/
- virtual void onFirstRef();
+ void onFirstRef() override;
/* ------------------------------------------------------------------------
* HWC2::ComposerCallback / HWComposer::EventHandler interface
@@ -521,8 +489,10 @@
// called on the main thread in response to initializeDisplays()
void onInitializeDisplays();
+ // setActiveConfigInternal() posted on a main thread for async execution
+ status_t setActiveConfigAsync(const sp<IBinder>& displayToken, int mode);
// called on the main thread in response to setActiveConfig()
- void setActiveConfigInternal(const sp<DisplayDevice>& display, int mode);
+ void setActiveConfigInternal(const sp<IBinder>& displayToken, int mode);
// called on the main thread in response to setPowerMode()
void setPowerModeInternal(const sp<DisplayDevice>& display, int mode);
@@ -542,6 +512,7 @@
void handleTransactionLocked(uint32_t transactionFlags);
void updateInputWindows();
+ void executeInputWindowCommands();
void updateCursorAsync();
/* handlePageFlip - latch a new buffer if available and compute the dirty
@@ -553,6 +524,10 @@
/* ------------------------------------------------------------------------
* Transactions
*/
+ void applyTransactionState(const Vector<ComposerState>& state,
+ const Vector<DisplayState>& displays, uint32_t flags,
+ const InputWindowCommands& inputWindowCommands) REQUIRES(mStateLock);
+ bool flushTransactionQueues();
uint32_t getTransactionFlags(uint32_t flags);
uint32_t peekTransactionFlags();
// Can only be called from the main thread or with mStateLock held
@@ -561,9 +536,10 @@
void latchAndReleaseBuffer(const sp<Layer>& layer);
void commitTransaction();
bool containsAnyInvalidClientState(const Vector<ComposerState>& states);
+ bool composerStateContainsUnsignaledFences(const Vector<ComposerState>& states);
uint32_t setClientStateLocked(const ComposerState& composerState);
uint32_t setDisplayStateLocked(const DisplayState& s);
- void setDestroyStateLocked(const ComposerState& composerState);
+ uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands);
/* ------------------------------------------------------------------------
* Layer management
@@ -592,27 +568,19 @@
String8 getUniqueLayerName(const String8& name);
- // called in response to the window-manager calling
- // ISurfaceComposerClient::destroySurface()
- status_t onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle);
-
- void markLayerPendingRemovalLocked(const Mutex& /* mStateLock */, const sp<Layer>& layer);
-
// called when all clients have released all their references to
// this layer meaning it is entirely safe to destroy all
// resources associated to this layer.
void onHandleDestroyed(sp<Layer>& layer);
-
- // remove a layer from SurfaceFlinger immediately
- status_t removeLayer(const sp<Layer>& layer);
- status_t removeLayerLocked(const Mutex&, const sp<Layer>& layer);
+ void markLayerPendingRemovalLocked(const sp<Layer>& layer);
// add a layer to SurfaceFlinger
status_t addClientLayer(const sp<Client>& client,
const sp<IBinder>& handle,
const sp<IGraphicBufferProducer>& gbc,
const sp<Layer>& lbc,
- const sp<Layer>& parent);
+ const sp<Layer>& parent,
+ bool addToCurrentState);
/* ------------------------------------------------------------------------
* Boot animation, on/off animations and screen capture
@@ -691,7 +659,27 @@
* H/W composer
*/
- HWComposer& getHwComposer() const { return *getBE().mHwc; }
+ // The current hardware composer interface.
+ //
+ // The following thread safety rules apply when accessing mHwc, either
+ // directly or via getHwComposer():
+ //
+ // 1. When recreating mHwc, acquire mStateLock. We currently recreate mHwc
+ // only when switching into and out of vr. Recreating mHwc must only be
+ // done on the main thread.
+ //
+ // 2. When accessing mHwc on the main thread, it's not necessary to acquire
+ // mStateLock.
+ //
+ // 3. When accessing mHwc on a thread other than the main thread, we always
+ // need to acquire mStateLock. This is because the main thread could be
+ // in the process of destroying the current mHwc instance.
+ //
+ // The above thread safety rules only apply to SurfaceFlinger.cpp. In
+ // SurfaceFlinger_hwc1.cpp we create mHwc at surface flinger init and never
+ // destroy it, so it's always safe to access mHwc from any thread without
+ // acquiring mStateLock.
+ HWComposer& getHwComposer() const;
/* ------------------------------------------------------------------------
* Compositing
@@ -764,6 +752,9 @@
void resyncWithRateLimit();
void getCompositorTiming(CompositorTiming* compositorTiming);
private:
+ // Sets the refresh rate to newFps by switching active configs, if they are available for
+ // the desired refresh rate.
+ void setRefreshRateTo(float newFps);
/* ------------------------------------------------------------------------
* Debugging & dumpsys
@@ -965,6 +956,22 @@
uint32_t mTexturePoolSize = 0;
std::vector<uint32_t> mTexturePool;
+ struct IBinderHash {
+ std::size_t operator()(const sp<IBinder>& strongPointer) const {
+ return std::hash<IBinder*>{}(strongPointer.get());
+ }
+ };
+ struct TransactionState {
+ TransactionState(const Vector<ComposerState>& composerStates,
+ const Vector<DisplayState>& displayStates, uint32_t transactionFlags)
+ : states(composerStates), displays(displayStates), flags(transactionFlags) {}
+
+ Vector<ComposerState> states;
+ Vector<DisplayState> displays;
+ uint32_t flags;
+ };
+ std::unordered_map<sp<IBinder>, std::queue<TransactionState>, IBinderHash> mTransactionQueues;
+
/* ------------------------------------------------------------------------
* Feature prototyping
*/
@@ -991,6 +998,7 @@
ui::Dataspace mWideColorGamutCompositionDataspace;
SurfaceFlingerBE mBE;
+ std::unique_ptr<compositionengine::CompositionEngine> mCompositionEngine;
bool mUseScheduler = false;
std::unique_ptr<Scheduler> mScheduler;
@@ -998,6 +1006,8 @@
sp<Scheduler::ConnectionHandle> mSfConnectionHandle;
sp<IInputFlinger> mInputFlinger;
+
+ InputWindowCommands mInputWindowCommands;
};
}; // namespace android
diff --git a/services/surfaceflinger/SurfaceFlingerFactory.cpp b/services/surfaceflinger/SurfaceFlingerFactory.cpp
index 88649e3..77679e3 100644
--- a/services/surfaceflinger/SurfaceFlingerFactory.cpp
+++ b/services/surfaceflinger/SurfaceFlingerFactory.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <compositionengine/impl/CompositionEngine.h>
#include <ui/GraphicBuffer.h>
#include "BufferQueueLayer.h"
@@ -59,7 +60,7 @@
}
std::unique_ptr<HWComposer> createHWComposer(const std::string& serviceName) override {
- return std::make_unique<HWComposer>(
+ return std::make_unique<android::impl::HWComposer>(
std::make_unique<Hwc2::impl::Composer>(serviceName));
}
@@ -102,6 +103,10 @@
return surfaceflinger::impl::createNativeWindowSurface(producer);
}
+ std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine() override {
+ return compositionengine::impl::createCompositionEngine();
+ }
+
sp<ContainerLayer> createContainerLayer(const LayerCreationArgs& args) override {
return new ContainerLayer(args);
}
diff --git a/services/surfaceflinger/SurfaceFlingerFactory.h b/services/surfaceflinger/SurfaceFlingerFactory.h
index 1c27cc7..f747684 100644
--- a/services/surfaceflinger/SurfaceFlingerFactory.h
+++ b/services/surfaceflinger/SurfaceFlingerFactory.h
@@ -49,6 +49,9 @@
struct DisplayDeviceCreationArgs;
struct LayerCreationArgs;
+namespace compositionengine {
+class CompositionEngine;
+} // namespace compositionengine
namespace surfaceflinger {
class NativeWindowSurface;
@@ -78,6 +81,8 @@
virtual std::unique_ptr<surfaceflinger::NativeWindowSurface> createNativeWindowSurface(
const sp<IGraphicBufferProducer>&) = 0;
+ virtual std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine() = 0;
+
virtual sp<BufferQueueLayer> createBufferQueueLayer(const LayerCreationArgs& args) = 0;
virtual sp<BufferStateLayer> createBufferStateLayer(const LayerCreationArgs& args) = 0;
virtual sp<ColorLayer> createColorLayer(const LayerCreationArgs& args) = 0;
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index a6dcb7e..7bfe033 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -101,23 +101,22 @@
transaction->set_animation(layerFlags & BnSurfaceComposer::eAnimation);
const int32_t layerId(getLayerId(layer));
- Mutex::Autolock lock(layer->mStateMutex);
- addPositionLocked(transaction, layerId, layer->mState.current.active_legacy.transform.tx(),
- layer->mState.current.active_legacy.transform.ty());
- addDepthLocked(transaction, layerId, layer->mState.current.z);
- addAlphaLocked(transaction, layerId, layer->mState.current.color.a);
+ addPositionLocked(transaction, layerId, layer->mCurrentState.active_legacy.transform.tx(),
+ layer->mCurrentState.active_legacy.transform.ty());
+ addDepthLocked(transaction, layerId, layer->mCurrentState.z);
+ addAlphaLocked(transaction, layerId, layer->mCurrentState.color.a);
addTransparentRegionLocked(transaction, layerId,
- layer->mState.current.activeTransparentRegion_legacy);
- addLayerStackLocked(transaction, layerId, layer->mState.current.layerStack);
- addCropLocked(transaction, layerId, layer->mState.current.crop_legacy);
- addCornerRadiusLocked(transaction, layerId, layer->mState.current.cornerRadius);
- if (layer->mState.current.barrierLayer_legacy != nullptr) {
+ layer->mCurrentState.activeTransparentRegion_legacy);
+ addLayerStackLocked(transaction, layerId, layer->mCurrentState.layerStack);
+ addCropLocked(transaction, layerId, layer->mCurrentState.crop_legacy);
+ addCornerRadiusLocked(transaction, layerId, layer->mCurrentState.cornerRadius);
+ if (layer->mCurrentState.barrierLayer_legacy != nullptr) {
addDeferTransactionLocked(transaction, layerId,
- layer->mState.current.barrierLayer_legacy.promote(),
- layer->mState.current.frameNumber_legacy);
+ layer->mCurrentState.barrierLayer_legacy.promote(),
+ layer->mCurrentState.frameNumber_legacy);
}
addOverrideScalingModeLocked(transaction, layerId, layer->getEffectiveScalingMode());
- addFlagsLocked(transaction, layerId, layer->mState.current.flags);
+ addFlagsLocked(transaction, layerId, layer->mCurrentState.flags);
}
void SurfaceInterceptor::addInitialDisplayStateLocked(Increment* increment,
@@ -427,9 +426,8 @@
SurfaceCreation* creation(increment->mutable_surface_creation());
creation->set_id(getLayerId(layer));
creation->set_name(getLayerName(layer));
- Mutex::Autolock lock(layer->mStateMutex);
- creation->set_w(layer->mState.current.active_legacy.w);
- creation->set_h(layer->mState.current.active_legacy.h);
+ creation->set_w(layer->mCurrentState.active_legacy.w);
+ creation->set_h(layer->mCurrentState.active_legacy.h);
}
void SurfaceInterceptor::addSurfaceDeletionLocked(Increment* increment,
diff --git a/services/surfaceflinger/TEST_MAPPING b/services/surfaceflinger/TEST_MAPPING
new file mode 100644
index 0000000..cab33ae
--- /dev/null
+++ b/services/surfaceflinger/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+ "presubmit": [
+ {
+ "name": "libsurfaceflinger_unittest"
+ },
+ {
+ "name": "libcompositionengine_test"
+ }
+ ]
+}
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index 604aa7d..f121a95 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -17,6 +17,7 @@
defaults: ["surfaceflinger_defaults"],
test_suites: ["device-tests"],
srcs: [
+ "BufferGenerator.cpp",
"Credentials_test.cpp",
"Stress_test.cpp",
"SurfaceInterceptor_test.cpp",
diff --git a/services/surfaceflinger/tests/BufferGenerator.cpp b/services/surfaceflinger/tests/BufferGenerator.cpp
new file mode 100644
index 0000000..8ddda60
--- /dev/null
+++ b/services/surfaceflinger/tests/BufferGenerator.cpp
@@ -0,0 +1,381 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gui/BufferItemConsumer.h>
+#include <gui/Surface.h>
+
+#include <GLES3/gl3.h>
+#include <math/vec2.h>
+#include <math/vec3.h>
+#include <math/vec4.h>
+
+#include "BufferGenerator.h"
+#include "BufferGeneratorShader.h"
+
+namespace android {
+
+/* Used to receive the surfaces and fences from egl. The egl buffers are thrown
+ * away. The fences are sent to the requester via a callback */
+class SurfaceManager {
+public:
+ /* Returns a fence from egl */
+ using BufferCallback = std::function<void(const sp<GraphicBuffer>& buffer, int32_t fence)>;
+
+ /* Listens for a new frame, detaches the buffer and returns the fence
+ * through saved callback. */
+ class BufferListener : public ConsumerBase::FrameAvailableListener {
+ public:
+ BufferListener(sp<IGraphicBufferConsumer> consumer, BufferCallback callback)
+ : mConsumer(consumer), mCallback(callback) {}
+
+ void onFrameAvailable(const BufferItem& /*item*/) {
+ BufferItem item;
+
+ if (mConsumer->acquireBuffer(&item, 0)) return;
+ if (mConsumer->detachBuffer(item.mSlot)) return;
+
+ mCallback(item.mGraphicBuffer, item.mFence->dup());
+ }
+
+ private:
+ sp<IGraphicBufferConsumer> mConsumer;
+ BufferCallback mCallback;
+ };
+
+ /* Creates a buffer listener that waits on a new frame from the buffer
+ * queue. */
+ void initialize(uint32_t width, uint32_t height, android_pixel_format_t format,
+ BufferCallback callback) {
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+
+ consumer->setDefaultBufferSize(width, height);
+ consumer->setDefaultBufferFormat(format);
+
+ mBufferItemConsumer = new BufferItemConsumer(consumer, 0);
+
+ mListener = new BufferListener(consumer, callback);
+ mBufferItemConsumer->setFrameAvailableListener(mListener);
+
+ mSurface = new Surface(producer, true);
+ }
+
+ /* Used by Egl manager. The surface is never displayed. */
+ sp<Surface> getSurface() const { return mSurface; }
+
+private:
+ sp<BufferItemConsumer> mBufferItemConsumer;
+ sp<BufferListener> mListener;
+ /* Used by Egl manager. The surface is never displayed */
+ sp<Surface> mSurface;
+};
+
+/* Used to generate valid fences. It is not possible to create a dummy sync
+ * fence for testing. Egl can generate buffers along with a valid fence.
+ * The buffer cannot be guaranteed to be the same format across all devices so
+ * a CPU filled buffer is used instead. The Egl fence is used along with the
+ * CPU filled buffer. */
+class EglManager {
+public:
+ EglManager()
+ : mEglDisplay(EGL_NO_DISPLAY), mEglSurface(EGL_NO_SURFACE), mEglContext(EGL_NO_CONTEXT) {}
+
+ ~EglManager() { cleanup(); }
+
+ int initialize(sp<Surface> surface) {
+ mSurface = surface;
+
+ mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (mEglDisplay == EGL_NO_DISPLAY) return false;
+
+ EGLint major;
+ EGLint minor;
+ if (!eglInitialize(mEglDisplay, &major, &minor)) {
+ ALOGW("Could not initialize EGL");
+ return false;
+ }
+
+ /* We're going to use a 1x1 pbuffer surface later on
+ * The configuration distance doesn't really matter for what we're
+ * trying to do */
+ EGLint configAttrs[] = {EGL_RENDERABLE_TYPE,
+ EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE,
+ 8,
+ EGL_GREEN_SIZE,
+ 8,
+ EGL_BLUE_SIZE,
+ 8,
+ EGL_ALPHA_SIZE,
+ 0,
+ EGL_DEPTH_SIZE,
+ 24,
+ EGL_STENCIL_SIZE,
+ 0,
+ EGL_NONE};
+
+ EGLConfig configs[1];
+ EGLint configCnt;
+ if (!eglChooseConfig(mEglDisplay, configAttrs, configs, 1, &configCnt)) {
+ ALOGW("Could not select EGL configuration");
+ eglReleaseThread();
+ eglTerminate(mEglDisplay);
+ return false;
+ }
+
+ if (configCnt <= 0) {
+ ALOGW("Could not find EGL configuration");
+ eglReleaseThread();
+ eglTerminate(mEglDisplay);
+ return false;
+ }
+
+ /* These objects are initialized below but the default "null" values are
+ * used to cleanup properly at any point in the initialization sequence */
+ EGLint attrs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
+ mEglContext = eglCreateContext(mEglDisplay, configs[0], EGL_NO_CONTEXT, attrs);
+ if (mEglContext == EGL_NO_CONTEXT) {
+ ALOGW("Could not create EGL context");
+ cleanup();
+ return false;
+ }
+
+ EGLint majorVersion;
+ if (!eglQueryContext(mEglDisplay, mEglContext, EGL_CONTEXT_CLIENT_VERSION, &majorVersion)) {
+ ALOGW("Could not query EGL version");
+ cleanup();
+ return false;
+ }
+
+ if (majorVersion != 3) {
+ ALOGW("Unsupported EGL version");
+ cleanup();
+ return false;
+ }
+
+ EGLint surfaceAttrs[] = {EGL_NONE};
+ mEglSurface = eglCreateWindowSurface(mEglDisplay, configs[0], mSurface.get(), surfaceAttrs);
+ if (mEglSurface == EGL_NO_SURFACE) {
+ ALOGW("Could not create EGL surface");
+ cleanup();
+ return false;
+ }
+
+ if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
+ ALOGW("Could not change current EGL context");
+ cleanup();
+ return false;
+ }
+
+ return true;
+ }
+
+ void makeCurrent() const { eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext); }
+
+ void present() const { eglSwapBuffers(mEglDisplay, mEglSurface); }
+
+private:
+ void cleanup() {
+ if (mEglDisplay == EGL_NO_DISPLAY) return;
+ if (mEglSurface != EGL_NO_SURFACE) eglDestroySurface(mEglDisplay, mEglSurface);
+ if (mEglContext != EGL_NO_CONTEXT) eglDestroyContext(mEglDisplay, mEglContext);
+
+ eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglReleaseThread();
+ eglTerminate(mEglDisplay);
+ }
+
+ sp<Surface> mSurface;
+ EGLDisplay mEglDisplay;
+ EGLSurface mEglSurface;
+ EGLContext mEglContext;
+};
+
+class Program {
+public:
+ ~Program() {
+ if (mInitialized) {
+ glDetachShader(mProgram, mVertexShader);
+ glDetachShader(mProgram, mFragmentShader);
+
+ glDeleteShader(mVertexShader);
+ glDeleteShader(mFragmentShader);
+
+ glDeleteProgram(mProgram);
+ }
+ }
+
+ bool initialize(const char* vertex, const char* fragment) {
+ mVertexShader = buildShader(vertex, GL_VERTEX_SHADER);
+ if (!mVertexShader) {
+ return false;
+ }
+
+ mFragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
+ if (!mFragmentShader) {
+ return false;
+ }
+
+ mProgram = glCreateProgram();
+ glAttachShader(mProgram, mVertexShader);
+ glAttachShader(mProgram, mFragmentShader);
+
+ glLinkProgram(mProgram);
+
+ GLint status;
+ glGetProgramiv(mProgram, GL_LINK_STATUS, &status);
+ if (status != GL_TRUE) {
+ GLint length = 0;
+ glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, &length);
+ if (length > 1) {
+ GLchar log[length];
+ glGetProgramInfoLog(mProgram, length, nullptr, &log[0]);
+ ALOGE("%s", log);
+ }
+ ALOGE("Error while linking shaders");
+ return false;
+ }
+ mInitialized = true;
+ return true;
+ }
+
+ void use() const { glUseProgram(mProgram); }
+
+ void bindVec4(GLint location, vec4 v) const { glUniform4f(location, v.x, v.y, v.z, v.w); }
+
+ void bindVec3(GLint location, const vec3* v, uint32_t count) const {
+ glUniform3fv(location, count, &(v->x));
+ }
+
+ void bindFloat(GLint location, float v) { glUniform1f(location, v); }
+
+private:
+ GLuint buildShader(const char* source, GLenum type) const {
+ GLuint shader = glCreateShader(type);
+ glShaderSource(shader, 1, &source, nullptr);
+ glCompileShader(shader);
+
+ GLint status;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
+ if (status != GL_TRUE) {
+ ALOGE("Error while compiling shader of type 0x%x:\n===\n%s\n===", type, source);
+ // Some drivers return wrong values for GL_INFO_LOG_LENGTH
+ // use a fixed size instead
+ GLchar log[512];
+ glGetShaderInfoLog(shader, sizeof(log), nullptr, &log[0]);
+ ALOGE("Shader info log: %s", log);
+ return 0;
+ }
+
+ return shader;
+ }
+
+ GLuint mProgram = 0;
+ GLuint mVertexShader = 0;
+ GLuint mFragmentShader = 0;
+ bool mInitialized = false;
+};
+
+BufferGenerator::BufferGenerator()
+ : mSurfaceManager(new SurfaceManager), mEglManager(new EglManager), mProgram(new Program) {
+ const float width = 1000.0;
+ const float height = 1000.0;
+
+ auto setBufferWithContext =
+ std::bind(setBuffer, std::placeholders::_1, std::placeholders::_2, this);
+ mSurfaceManager->initialize(width, height, HAL_PIXEL_FORMAT_RGBA_8888, setBufferWithContext);
+
+ if (!mEglManager->initialize(mSurfaceManager->getSurface())) return;
+
+ mEglManager->makeCurrent();
+
+ if (!mProgram->initialize(VERTEX_SHADER, FRAGMENT_SHADER)) return;
+ mProgram->use();
+ mProgram->bindVec4(0, vec4{width, height, 1.0f / width, 1.0f / height});
+ mProgram->bindVec3(2, &SPHERICAL_HARMONICS[0], 4);
+
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, &TRIANGLE[0]);
+
+ mInitialized = true;
+}
+
+BufferGenerator::~BufferGenerator() {
+ mEglManager->makeCurrent();
+}
+
+status_t BufferGenerator::get(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) {
+ // mMutex is used to protect get() from getting called by multiple threads at the same time
+ static std::mutex mMutex;
+ std::lock_guard lock(mMutex);
+
+ if (!mInitialized) {
+ if (outBuffer) {
+ *outBuffer = nullptr;
+ }
+ if (*outFence) {
+ *outFence = nullptr;
+ }
+ return -EINVAL;
+ }
+
+ // Generate a buffer and fence. They will be returned through the setBuffer callback
+ mEglManager->makeCurrent();
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ const std::chrono::duration<float> time = std::chrono::steady_clock::now() - mEpoch;
+ mProgram->bindFloat(1, time.count());
+
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+
+ mPending = true;
+ mEglManager->present();
+
+ // Wait for the setBuffer callback
+ if (!mConditionVariable.wait_for(mMutex, std::chrono::seconds(2),
+ [this] { return !mPending; })) {
+ ALOGE("failed to set buffer and fence");
+ return -ETIME;
+ }
+
+ // Return buffer and fence
+ if (outBuffer) {
+ *outBuffer = mGraphicBuffer;
+ }
+ if (outFence) {
+ *outFence = new Fence(mFence);
+ } else {
+ close(mFence);
+ }
+ mGraphicBuffer = nullptr;
+ mFence = -1;
+
+ return NO_ERROR;
+}
+
+// static
+void BufferGenerator::setBuffer(const sp<GraphicBuffer>& buffer, int32_t fence,
+ void* bufferGenerator) {
+ BufferGenerator* generator = static_cast<BufferGenerator*>(bufferGenerator);
+ generator->mGraphicBuffer = buffer;
+ generator->mFence = fence;
+ generator->mPending = false;
+ generator->mConditionVariable.notify_all();
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/tests/BufferGenerator.h b/services/surfaceflinger/tests/BufferGenerator.h
new file mode 100644
index 0000000..a3ffe86
--- /dev/null
+++ b/services/surfaceflinger/tests/BufferGenerator.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <condition_variable>
+#include <mutex>
+
+#include <ui/GraphicBuffer.h>
+
+namespace android {
+
+class SurfaceManager;
+class EglManager;
+class Program;
+
+class BufferGenerator {
+public:
+ BufferGenerator();
+ ~BufferGenerator();
+
+ /* Get a new fence */
+ status_t get(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence);
+
+ /* Static callback that sets the fence on a particular instance */
+ static void setBuffer(const sp<GraphicBuffer>& buffer, int32_t fence, void* fenceGenerator);
+
+private:
+ bool mInitialized = false;
+
+ std::unique_ptr<SurfaceManager> mSurfaceManager;
+ std::unique_ptr<EglManager> mEglManager;
+ std::unique_ptr<Program> mProgram;
+
+ std::condition_variable_any mConditionVariable;
+
+ sp<GraphicBuffer> mGraphicBuffer;
+ int32_t mFence = -1;
+ bool mPending = false;
+
+ using Epoch = std::chrono::time_point<std::chrono::steady_clock>;
+ Epoch mEpoch = std::chrono::steady_clock::now();
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/tests/BufferGeneratorShader.h b/services/surfaceflinger/tests/BufferGeneratorShader.h
new file mode 100644
index 0000000..564cda3
--- /dev/null
+++ b/services/surfaceflinger/tests/BufferGeneratorShader.h
@@ -0,0 +1,355 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <GLES3/gl3.h>
+#include <math/vec2.h>
+#include <math/vec3.h>
+#include <math/vec4.h>
+
+static const char* VERTEX_SHADER = R"SHADER__(#version 300 es
+precision highp float;
+
+layout(location = 0) in vec4 mesh_position;
+
+void main() {
+ gl_Position = mesh_position;
+}
+)SHADER__";
+
+static const char* FRAGMENT_SHADER = R"SHADER__(#version 300 es
+precision highp float;
+
+layout(location = 0) uniform vec4 resolution;
+layout(location = 1) uniform float time;
+layout(location = 2) uniform vec3[4] SPHERICAL_HARMONICS;
+
+layout(location = 0) out vec4 fragColor;
+
+#define saturate(x) clamp(x, 0.0, 1.0)
+#define PI 3.14159265359
+
+//------------------------------------------------------------------------------
+// Distance field functions
+//------------------------------------------------------------------------------
+
+float sdPlane(in vec3 p) {
+ return p.y;
+}
+
+float sdSphere(in vec3 p, float s) {
+ return length(p) - s;
+}
+
+float sdTorus(in vec3 p, in vec2 t) {
+ return length(vec2(length(p.xz) - t.x, p.y)) - t.y;
+}
+
+vec2 opUnion(vec2 d1, vec2 d2) {
+ return d1.x < d2.x ? d1 : d2;
+}
+
+vec2 scene(in vec3 position) {
+ vec2 scene = opUnion(
+ vec2(sdPlane(position), 1.0),
+ vec2(sdSphere(position - vec3(0.0, 0.4, 0.0), 0.4), 12.0)
+ );
+ return scene;
+}
+
+//------------------------------------------------------------------------------
+// Ray casting
+//------------------------------------------------------------------------------
+
+float shadow(in vec3 origin, in vec3 direction, in float tmin, in float tmax) {
+ float hit = 1.0;
+
+ for (float t = tmin; t < tmax; ) {
+ float h = scene(origin + direction * t).x;
+ if (h < 0.001) return 0.0;
+ t += h;
+ hit = min(hit, 10.0 * h / t);
+ }
+
+ return clamp(hit, 0.0, 1.0);
+}
+
+vec2 traceRay(in vec3 origin, in vec3 direction) {
+ float tmin = 0.02;
+ float tmax = 20.0;
+
+ float material = -1.0;
+ float t = tmin;
+
+ for ( ; t < tmax; ) {
+ vec2 hit = scene(origin + direction * t);
+ if (hit.x < 0.002 || t > tmax) break;
+ t += hit.x;
+ material = hit.y;
+ }
+
+ if (t > tmax) {
+ material = -1.0;
+ }
+
+ return vec2(t, material);
+}
+
+vec3 normal(in vec3 position) {
+ vec3 epsilon = vec3(0.001, 0.0, 0.0);
+ vec3 n = vec3(
+ scene(position + epsilon.xyy).x - scene(position - epsilon.xyy).x,
+ scene(position + epsilon.yxy).x - scene(position - epsilon.yxy).x,
+ scene(position + epsilon.yyx).x - scene(position - epsilon.yyx).x);
+ return normalize(n);
+}
+
+//------------------------------------------------------------------------------
+// BRDF
+//------------------------------------------------------------------------------
+
+float pow5(float x) {
+ float x2 = x * x;
+ return x2 * x2 * x;
+}
+
+float D_GGX(float linearRoughness, float NoH, const vec3 h) {
+ // Walter et al. 2007, "Microfacet Models for Refraction through Rough Surfaces"
+ float oneMinusNoHSquared = 1.0 - NoH * NoH;
+ float a = NoH * linearRoughness;
+ float k = linearRoughness / (oneMinusNoHSquared + a * a);
+ float d = k * k * (1.0 / PI);
+ return d;
+}
+
+float V_SmithGGXCorrelated(float linearRoughness, float NoV, float NoL) {
+ // Heitz 2014, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs"
+ float a2 = linearRoughness * linearRoughness;
+ float GGXV = NoL * sqrt((NoV - a2 * NoV) * NoV + a2);
+ float GGXL = NoV * sqrt((NoL - a2 * NoL) * NoL + a2);
+ return 0.5 / (GGXV + GGXL);
+}
+
+vec3 F_Schlick(const vec3 f0, float VoH) {
+ // Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"
+ return f0 + (vec3(1.0) - f0) * pow5(1.0 - VoH);
+}
+
+float F_Schlick(float f0, float f90, float VoH) {
+ return f0 + (f90 - f0) * pow5(1.0 - VoH);
+}
+
+float Fd_Burley(float linearRoughness, float NoV, float NoL, float LoH) {
+ // Burley 2012, "Physically-Based Shading at Disney"
+ float f90 = 0.5 + 2.0 * linearRoughness * LoH * LoH;
+ float lightScatter = F_Schlick(1.0, f90, NoL);
+ float viewScatter = F_Schlick(1.0, f90, NoV);
+ return lightScatter * viewScatter * (1.0 / PI);
+}
+
+float Fd_Lambert() {
+ return 1.0 / PI;
+}
+
+//------------------------------------------------------------------------------
+// Indirect lighting
+//------------------------------------------------------------------------------
+
+vec3 Irradiance_SphericalHarmonics(const vec3 n) {
+ return max(
+ SPHERICAL_HARMONICS[0]
+ + SPHERICAL_HARMONICS[1] * (n.y)
+ + SPHERICAL_HARMONICS[2] * (n.z)
+ + SPHERICAL_HARMONICS[3] * (n.x)
+ , 0.0);
+}
+
+vec2 PrefilteredDFG_Karis(float roughness, float NoV) {
+ // Karis 2014, "Physically Based Material on Mobile"
+ const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022);
+ const vec4 c1 = vec4( 1.0, 0.0425, 1.040, -0.040);
+
+ vec4 r = roughness * c0 + c1;
+ float a004 = min(r.x * r.x, exp2(-9.28 * NoV)) * r.x + r.y;
+
+ return vec2(-1.04, 1.04) * a004 + r.zw;
+}
+
+//------------------------------------------------------------------------------
+// Tone mapping and transfer functions
+//------------------------------------------------------------------------------
+
+vec3 Tonemap_ACES(const vec3 x) {
+ // Narkowicz 2015, "ACES Filmic Tone Mapping Curve"
+ const float a = 2.51;
+ const float b = 0.03;
+ const float c = 2.43;
+ const float d = 0.59;
+ const float e = 0.14;
+ return (x * (a * x + b)) / (x * (c * x + d) + e);
+}
+
+vec3 OECF_sRGBFast(const vec3 linear) {
+ return pow(linear, vec3(1.0 / 2.2));
+}
+
+//------------------------------------------------------------------------------
+// Rendering
+//------------------------------------------------------------------------------
+
+vec3 render(in vec3 origin, in vec3 direction, out float distance) {
+ // Sky gradient
+ vec3 color = vec3(0.65, 0.85, 1.0) + direction.y * 0.72;
+
+ // (distance, material)
+ vec2 hit = traceRay(origin, direction);
+ distance = hit.x;
+ float material = hit.y;
+
+ // We've hit something in the scene
+ if (material > 0.0) {
+ vec3 position = origin + distance * direction;
+
+ vec3 v = normalize(-direction);
+ vec3 n = normal(position);
+ vec3 l = normalize(vec3(0.6, 0.7, -0.7));
+ vec3 h = normalize(v + l);
+ vec3 r = normalize(reflect(direction, n));
+
+ float NoV = abs(dot(n, v)) + 1e-5;
+ float NoL = saturate(dot(n, l));
+ float NoH = saturate(dot(n, h));
+ float LoH = saturate(dot(l, h));
+
+ vec3 baseColor = vec3(0.0);
+ float roughness = 0.0;
+ float metallic = 0.0;
+
+ float intensity = 2.0;
+ float indirectIntensity = 0.64;
+
+ if (material < 4.0) {
+ // Checkerboard floor
+ float f = mod(floor(6.0 * position.z) + floor(6.0 * position.x), 2.0);
+ baseColor = 0.4 + f * vec3(0.6);
+ roughness = 0.1;
+ } else if (material < 16.0) {
+ // Metallic objects
+ baseColor = vec3(0.3, 0.0, 0.0);
+ roughness = 0.2;
+ }
+
+ float linearRoughness = roughness * roughness;
+ vec3 diffuseColor = (1.0 - metallic) * baseColor.rgb;
+ vec3 f0 = 0.04 * (1.0 - metallic) + baseColor.rgb * metallic;
+
+ float attenuation = shadow(position, l, 0.02, 2.5);
+
+ // specular BRDF
+ float D = D_GGX(linearRoughness, NoH, h);
+ float V = V_SmithGGXCorrelated(linearRoughness, NoV, NoL);
+ vec3 F = F_Schlick(f0, LoH);
+ vec3 Fr = (D * V) * F;
+
+ // diffuse BRDF
+ vec3 Fd = diffuseColor * Fd_Burley(linearRoughness, NoV, NoL, LoH);
+
+ color = Fd + Fr;
+ color *= (intensity * attenuation * NoL) * vec3(0.98, 0.92, 0.89);
+
+ // diffuse indirect
+ vec3 indirectDiffuse = Irradiance_SphericalHarmonics(n) * Fd_Lambert();
+
+ vec2 indirectHit = traceRay(position, r);
+ vec3 indirectSpecular = vec3(0.65, 0.85, 1.0) + r.y * 0.72;
+ if (indirectHit.y > 0.0) {
+ if (indirectHit.y < 4.0) {
+ vec3 indirectPosition = position + indirectHit.x * r;
+ // Checkerboard floor
+ float f = mod(floor(6.0 * indirectPosition.z) + floor(6.0 * indirectPosition.x), 2.0);
+ indirectSpecular = 0.4 + f * vec3(0.6);
+ } else if (indirectHit.y < 16.0) {
+ // Metallic objects
+ indirectSpecular = vec3(0.3, 0.0, 0.0);
+ }
+ }
+
+ // indirect contribution
+ vec2 dfg = PrefilteredDFG_Karis(roughness, NoV);
+ vec3 specularColor = f0 * dfg.x + dfg.y;
+ vec3 ibl = diffuseColor * indirectDiffuse + indirectSpecular * specularColor;
+
+ color += ibl * indirectIntensity;
+ }
+
+ return color;
+}
+
+//------------------------------------------------------------------------------
+// Setup and execution
+//------------------------------------------------------------------------------
+
+mat3 setCamera(in vec3 origin, in vec3 target, float rotation) {
+ vec3 forward = normalize(target - origin);
+ vec3 orientation = vec3(sin(rotation), cos(rotation), 0.0);
+ vec3 left = normalize(cross(forward, orientation));
+ vec3 up = normalize(cross(left, forward));
+ return mat3(left, up, forward);
+}
+
+void main() {
+ // Normalized coordinates
+ vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;
+ // Aspect ratio
+ p.x *= resolution.x / resolution.y;
+
+ // Camera position and "look at"
+ vec3 origin = vec3(0.0, 1.0, 0.0);
+ vec3 target = vec3(0.0);
+
+ origin.x += 2.0 * cos(time * 0.2);
+ origin.z += 2.0 * sin(time * 0.2);
+
+ mat3 toWorld = setCamera(origin, target, 0.0);
+ vec3 direction = toWorld * normalize(vec3(p.xy, 2.0));
+
+ // Render scene
+ float distance;
+ vec3 color = render(origin, direction, distance);
+
+ // Tone mapping
+ color = Tonemap_ACES(color);
+
+ // Exponential distance fog
+ color = mix(color, 0.8 * vec3(0.7, 0.8, 1.0), 1.0 - exp2(-0.011 * distance * distance));
+
+ // Gamma compression
+ color = OECF_sRGBFast(color);
+
+ fragColor = vec4(color, 1.0);
+}
+)SHADER__";
+
+static const android::vec3 SPHERICAL_HARMONICS[4] =
+ {{0.754554516862612, 0.748542953903366, 0.790921515418539},
+ {-0.083856548007422, 0.092533500963210, 0.322764661032516},
+ {0.308152705331738, 0.366796330467391, 0.466698181299906},
+ {-0.188884931542396, -0.277402551592231, -0.377844212327557}};
+
+static const android::vec4 TRIANGLE[3] = {{-1.0f, -1.0f, 1.0f, 1.0f},
+ {3.0f, -1.0f, 1.0f, 1.0f},
+ {-1.0f, 3.0f, 1.0f, 1.0f}};
diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp
index a73ec6c..8560f5e 100644
--- a/services/surfaceflinger/tests/Credentials_test.cpp
+++ b/services/surfaceflinger/tests/Credentials_test.cpp
@@ -162,10 +162,10 @@
setSystemUID();
ASSERT_NO_FATAL_FAILURE(initClient());
- // No one else can init the client.
+ // Anyone else can init the client.
setBinUID();
mComposerClient = new SurfaceComposerClient;
- ASSERT_EQ(NO_INIT, mComposerClient->initCheck());
+ ASSERT_NO_FATAL_FAILURE(initClient());
}
TEST_F(CredentialsTest, GetBuiltInDisplayAccessTest) {
@@ -222,22 +222,6 @@
ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
}
-TEST_F(CredentialsTest, CreateSurfaceTest) {
- sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
- DisplayInfo info;
- SurfaceComposerClient::getDisplayInfo(display, &info);
- const ssize_t displayWidth = info.w;
- const ssize_t displayHeight = info.h;
-
- std::function<bool()> condition = [=]() {
- mBGSurfaceControl =
- mComposerClient->createSurface(SURFACE_NAME, displayWidth, displayHeight,
- PIXEL_FORMAT_RGBA_8888, 0);
- return mBGSurfaceControl != nullptr && mBGSurfaceControl->isValid();
- };
- ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
-}
-
TEST_F(CredentialsTest, CreateDisplayTest) {
std::function<bool()> condition = [=]() {
sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
diff --git a/services/surfaceflinger/tests/Stress_test.cpp b/services/surfaceflinger/tests/Stress_test.cpp
index 3e1be8e..89c26f4 100644
--- a/services/surfaceflinger/tests/Stress_test.cpp
+++ b/services/surfaceflinger/tests/Stress_test.cpp
@@ -34,7 +34,7 @@
auto surf = client->createSurface(String8("t"), 100, 100,
PIXEL_FORMAT_RGBA_8888, 0);
ASSERT_TRUE(surf != nullptr);
- client->destroySurface(surf->getHandle());
+ surf->clear();
}
};
diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
index e506757..8ec3e15 100644
--- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
+++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
@@ -806,18 +806,6 @@
Increment::IncrementCase::kSurfaceCreation);
}
-TEST_F(SurfaceInterceptorTest, InterceptSurfaceDeletionWorks) {
- enableInterceptor();
- sp<SurfaceControl> layerToDelete = mComposerClient->createSurface(String8(LAYER_NAME),
- SIZE_UPDATE, SIZE_UPDATE, PIXEL_FORMAT_RGBA_8888, 0);
- mComposerClient->destroySurface(layerToDelete->getHandle());
- disableInterceptor();
-
- Trace capturedTrace;
- ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace));
- ASSERT_TRUE(singleIncrementFound(capturedTrace, Increment::IncrementCase::kSurfaceDeletion));
-}
-
TEST_F(SurfaceInterceptorTest, InterceptDisplayCreationWorks) {
captureTest(&SurfaceInterceptorTest::displayCreation,
Increment::IncrementCase::kDisplayCreation);
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 037d32f..ef6999d 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -28,7 +28,6 @@
#include <gui/ISurfaceComposer.h>
#include <gui/LayerState.h>
-
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <private/gui/ComposerService.h>
@@ -41,6 +40,8 @@
#include <math.h>
#include <math/vec3.h>
+#include "BufferGenerator.h"
+
namespace android {
namespace {
@@ -301,7 +302,7 @@
void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); }
- ScreenCapture(const sp<GraphicBuffer>& outBuffer) : mOutBuffer(outBuffer) {
+ explicit ScreenCapture(const sp<GraphicBuffer>& outBuffer) : mOutBuffer(outBuffer) {
mOutBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&mPixels));
}
@@ -478,6 +479,11 @@
return screenshot;
}
+ static status_t getBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) {
+ static BufferGenerator bufferGenerator;
+ return bufferGenerator.get(outBuffer, outFence);
+ }
+
sp<SurfaceComposerClient> mClient;
sp<IBinder> mDisplay;
@@ -1017,7 +1023,7 @@
.setRelativeLayer(layerG, layerR->getHandle(), 1)
.apply();
- mClient->destroySurface(layerG->getHandle());
+ layerG->clear();
// layerG should have been removed
screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
}
@@ -2164,6 +2170,36 @@
TEST_F(LayerTransactionTest, SetFenceBasic_BufferState) {
sp<SurfaceControl> layer;
+ Transaction transaction;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+ fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
+
+ sp<Fence> fence;
+ if (getBuffer(nullptr, &fence) != NO_ERROR) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ Transaction().setBuffer(layer, buffer).setAcquireFence(layer, fence).apply();
+
+ status_t status = fence->wait(1000);
+ ASSERT_NE(static_cast<status_t>(Fence::Status::Unsignaled), status);
+ std::this_thread::sleep_for(200ms);
+
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetFenceNull_BufferState) {
+ sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(
layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
@@ -2514,7 +2550,7 @@
}
void addSurface(ExpectedResult::Transaction transactionResult, const sp<SurfaceControl>& layer,
- ExpectedResult::Buffer bufferResult = NOT_ACQUIRED,
+ ExpectedResult::Buffer bufferResult = ACQUIRED,
ExpectedResult::PreviousBuffer previousBufferResult = NOT_RELEASED) {
mTransactionResult = transactionResult;
mExpectedSurfaceResults.emplace(std::piecewise_construct,
@@ -2524,7 +2560,7 @@
void addSurfaces(ExpectedResult::Transaction transactionResult,
const std::vector<sp<SurfaceControl>>& layers,
- ExpectedResult::Buffer bufferResult = NOT_ACQUIRED,
+ ExpectedResult::Buffer bufferResult = ACQUIRED,
ExpectedResult::PreviousBuffer previousBufferResult = NOT_RELEASED) {
for (const auto& layer : layers) {
addSurface(transactionResult, layer, bufferResult, previousBufferResult);
@@ -2631,24 +2667,22 @@
return createLayer(mClient, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState);
}
- static void fillTransaction(Transaction& transaction, CallbackHelper* callbackHelper,
- const sp<SurfaceControl>& layer = nullptr) {
+ static int fillTransaction(Transaction& transaction, CallbackHelper* callbackHelper,
+ const sp<SurfaceControl>& layer = nullptr) {
if (layer) {
- sp<GraphicBuffer> buffer =
- new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
- BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
- BufferUsage::COMPOSER_OVERLAY |
- BufferUsage::GPU_TEXTURE,
- "test");
- fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
-
- sp<Fence> fence = new Fence(-1);
+ sp<GraphicBuffer> buffer;
+ sp<Fence> fence;
+ int err = getBuffer(&buffer, &fence);
+ if (err != NO_ERROR) {
+ return err;
+ }
transaction.setBuffer(layer, buffer).setAcquireFence(layer, fence);
}
transaction.addTransactionCompletedCallback(callbackHelper->function,
callbackHelper->getContext());
+ return NO_ERROR;
}
static void waitForCallback(CallbackHelper& helper, const ExpectedResult& expectedResult,
@@ -2680,7 +2714,11 @@
Transaction transaction;
CallbackHelper callback;
- fillTransaction(transaction, &callback, layer);
+ int err = fillTransaction(transaction, &callback, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
transaction.apply();
@@ -2695,19 +2733,28 @@
Transaction transaction;
CallbackHelper callback;
- fillTransaction(transaction, &callback);
+ int err = fillTransaction(transaction, &callback);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
ExpectedResult expected;
- expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer);
+ expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer,
+ ExpectedResult::Buffer::NOT_ACQUIRED);
EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
}
TEST_F(LayerCallbackTest, NoStateChange) {
Transaction transaction;
CallbackHelper callback;
- fillTransaction(transaction, &callback);
+ int err = fillTransaction(transaction, &callback);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
transaction.apply();
@@ -2721,7 +2768,11 @@
Transaction transaction;
CallbackHelper callback;
- fillTransaction(transaction, &callback, layer);
+ int err = fillTransaction(transaction, &callback, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
transaction.setFrame(layer, Rect(-100, -100, 100, 100)).apply();
@@ -2737,8 +2788,16 @@
Transaction transaction1, transaction2;
CallbackHelper callback1, callback2;
- fillTransaction(transaction1, &callback1, layer1);
- fillTransaction(transaction2, &callback2, layer2);
+ int err = fillTransaction(transaction1, &callback1, layer1);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback2, layer2);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
@@ -2756,8 +2815,16 @@
Transaction transaction1, transaction2;
CallbackHelper callback;
- fillTransaction(transaction1, &callback, layer1);
- fillTransaction(transaction2, &callback, layer2);
+ int err = fillTransaction(transaction1, &callback, layer1);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback, layer2);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
transaction2.merge(std::move(transaction1)).apply();
@@ -2773,8 +2840,16 @@
Transaction transaction1, transaction2;
CallbackHelper callback1, callback2;
- fillTransaction(transaction1, &callback1, layer);
- fillTransaction(transaction2, &callback2, layer);
+ int err = fillTransaction(transaction1, &callback1, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback2, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
transaction2.merge(std::move(transaction1)).apply();
@@ -2784,25 +2859,6 @@
EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
}
-TEST_F(LayerCallbackTest, Merge_SingleBuffer) {
- sp<SurfaceControl> layer1, layer2;
- ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer());
- ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer());
-
- Transaction transaction1, transaction2;
- CallbackHelper callback1, callback2;
- fillTransaction(transaction1, &callback1, layer1);
- fillTransaction(transaction2, &callback2);
-
- transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
- transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
-
- ExpectedResult expected;
- expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2});
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
- EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
-}
-
TEST_F(LayerCallbackTest, Merge_DifferentClients) {
sp<SurfaceComposerClient> client1(new SurfaceComposerClient),
client2(new SurfaceComposerClient);
@@ -2818,8 +2874,16 @@
Transaction transaction1, transaction2;
CallbackHelper callback1, callback2;
- fillTransaction(transaction1, &callback1, layer1);
- fillTransaction(transaction2, &callback2, layer2);
+ int err = fillTransaction(transaction1, &callback1, layer1);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback2, layer2);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
@@ -2837,13 +2901,17 @@
Transaction transaction;
CallbackHelper callback;
for (size_t i = 0; i < 10; i++) {
- fillTransaction(transaction, &callback, layer);
+ int err = fillTransaction(transaction, &callback, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
transaction.apply();
ExpectedResult expected;
expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
- ExpectedResult::Buffer::NOT_ACQUIRED,
+ ExpectedResult::Buffer::ACQUIRED,
(i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED
: ExpectedResult::PreviousBuffer::RELEASED);
EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected));
@@ -2861,10 +2929,18 @@
ExpectedResult expected;
if (i == 0) {
- fillTransaction(transaction, &callback, layer);
+ int err = fillTransaction(transaction, &callback, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
} else {
- fillTransaction(transaction, &callback);
+ int err = fillTransaction(transaction, &callback);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
}
transaction.apply();
@@ -2882,9 +2958,17 @@
CallbackHelper callback;
for (size_t i = 0; i < 10; i++) {
if (i == 0) {
- fillTransaction(transaction, &callback, layer);
+ int err = fillTransaction(transaction, &callback, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
} else {
- fillTransaction(transaction, &callback);
+ int err = fillTransaction(transaction, &callback);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
}
transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
@@ -2892,7 +2976,9 @@
ExpectedResult expected;
expected.addSurface((i == 0) ? ExpectedResult::Transaction::PRESENTED
: ExpectedResult::Transaction::NOT_PRESENTED,
- layer);
+ layer,
+ (i == 0) ? ExpectedResult::Buffer::ACQUIRED
+ : ExpectedResult::Buffer::NOT_ACQUIRED);
EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, i == 0));
}
ASSERT_NO_FATAL_FAILURE(callback.verifyFinalState());
@@ -2906,15 +2992,23 @@
Transaction transaction1, transaction2;
CallbackHelper callback1, callback2;
for (size_t i = 0; i < 10; i++) {
- fillTransaction(transaction1, &callback1, layer1);
- fillTransaction(transaction2, &callback2, layer2);
+ int err = fillTransaction(transaction1, &callback1, layer1);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback2, layer2);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
ExpectedResult expected;
expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2},
- ExpectedResult::Buffer::NOT_ACQUIRED,
+ ExpectedResult::Buffer::ACQUIRED,
(i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED
: ExpectedResult::PreviousBuffer::RELEASED);
EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected));
@@ -2939,15 +3033,23 @@
Transaction transaction1, transaction2;
CallbackHelper callback1, callback2;
for (size_t i = 0; i < 10; i++) {
- fillTransaction(transaction1, &callback1, layer1);
- fillTransaction(transaction2, &callback2, layer2);
+ int err = fillTransaction(transaction1, &callback1, layer1);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback2, layer2);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
ExpectedResult expected;
expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2},
- ExpectedResult::Buffer::NOT_ACQUIRED,
+ ExpectedResult::Buffer::ACQUIRED,
(i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED
: ExpectedResult::PreviousBuffer::RELEASED);
EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected));
@@ -2973,8 +3075,16 @@
CallbackHelper callback1, callback2;
// Normal call to set up test
- fillTransaction(transaction1, &callback1, layer1);
- fillTransaction(transaction2, &callback2, layer2);
+ int err = fillTransaction(transaction1, &callback1, layer1);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback2, layer2);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
@@ -2986,8 +3096,16 @@
expected.reset();
// Test
- fillTransaction(transaction1, &callback1);
- fillTransaction(transaction2, &callback2);
+ err = fillTransaction(transaction1, &callback1);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback2);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
transaction2.merge(std::move(transaction1)).apply();
@@ -3012,8 +3130,16 @@
CallbackHelper callback1, callback2;
// Normal call to set up test
- fillTransaction(transaction1, &callback1, layer1);
- fillTransaction(transaction2, &callback2, layer2);
+ int err = fillTransaction(transaction1, &callback1, layer1);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback2, layer2);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
@@ -3025,12 +3151,21 @@
expected.reset();
// Test
- fillTransaction(transaction1, &callback1);
- fillTransaction(transaction2, &callback2);
+ err = fillTransaction(transaction1, &callback1);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback2);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
- expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer2);
+ expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer2,
+ ExpectedResult::Buffer::NOT_ACQUIRED);
EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
}
@@ -3047,13 +3182,16 @@
for (auto& expected : expectedResults) {
expected.reset();
expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
- ExpectedResult::Buffer::NOT_ACQUIRED, previousBufferResult);
+ ExpectedResult::Buffer::ACQUIRED, previousBufferResult);
previousBufferResult = ExpectedResult::PreviousBuffer::RELEASED;
- fillTransaction(transaction, &callback, layer);
+ int err = fillTransaction(transaction, &callback, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
transaction.apply();
- std::this_thread::sleep_for(200ms);
}
EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true));
}
@@ -3062,23 +3200,33 @@
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+ // Normal call to set up test
Transaction transaction;
CallbackHelper callback;
+ int err = fillTransaction(transaction, &callback, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction.apply();
+
+ ExpectedResult expected;
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+
+ // Test
std::vector<ExpectedResult> expectedResults(50);
- bool first = true;
for (auto& expected : expectedResults) {
expected.reset();
- if (first) {
- fillTransaction(transaction, &callback, layer);
- expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
- first = false;
- } else {
- fillTransaction(transaction, &callback);
+ err = fillTransaction(transaction, &callback);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
}
transaction.apply();
- std::this_thread::sleep_for(200ms);
}
EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true));
}
@@ -3090,7 +3238,11 @@
// Normal call to set up test
Transaction transaction;
CallbackHelper callback;
- fillTransaction(transaction, &callback, layer);
+ int err = fillTransaction(transaction, &callback, layer);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
@@ -3102,13 +3254,16 @@
std::vector<ExpectedResult> expectedResults(50);
for (auto& expected : expectedResults) {
expected.reset();
- expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer);
+ expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer,
+ ExpectedResult::Buffer::NOT_ACQUIRED);
- fillTransaction(transaction, &callback);
+ err = fillTransaction(transaction, &callback);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
-
- std::this_thread::sleep_for(200ms);
}
EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true));
}
@@ -3875,9 +4030,9 @@
asTransaction([&](Transaction& t) { t.reparent(mChild, nullptr); });
{
mCapture = screenshot();
- // Nothing should have changed.
+ // The surface should now be offscreen.
mCapture->expectFGColor(64, 64);
- mCapture->expectChildColor(74, 74);
+ mCapture->expectFGColor(74, 74);
mCapture->expectFGColor(84, 84);
}
}
@@ -4455,7 +4610,7 @@
ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60));
auto redLayerHandle = redLayer->getHandle();
- mClient->destroySurface(redLayerHandle);
+ redLayer->clear();
SurfaceComposerClient::Transaction().apply(true);
sp<GraphicBuffer> outBuffer;
diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp
index 973156a..eeb6efe 100644
--- a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp
+++ b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp
@@ -81,7 +81,7 @@
class DelayedEventGenerator {
public:
- DelayedEventGenerator(std::function<void()> onTimerExpired)
+ explicit DelayedEventGenerator(std::function<void()> onTimerExpired)
: mOnTimerExpired(onTimerExpired), mThread([this]() { loop(); }) {}
~DelayedEventGenerator() {
diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerService.h b/services/surfaceflinger/tests/fakehwc/FakeComposerService.h
index c439b7e..a3fb8a6 100644
--- a/services/surfaceflinger/tests/fakehwc/FakeComposerService.h
+++ b/services/surfaceflinger/tests/fakehwc/FakeComposerService.h
@@ -26,7 +26,7 @@
class FakeComposerService : public IComposer {
public:
- FakeComposerService(android::sp<ComposerClient>& client);
+ explicit FakeComposerService(android::sp<ComposerClient>& client);
virtual ~FakeComposerService();
Return<void> getCapabilities(getCapabilities_cb hidl_cb) override;
diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h b/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h
index 1258a97..7d20d3c 100644
--- a/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h
+++ b/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h
@@ -100,10 +100,7 @@
*/
class TransactionScope : public android::SurfaceComposerClient::Transaction {
public:
- TransactionScope(FakeComposerClient& composer) :
- Transaction(),
- mComposer(composer) {
- }
+ explicit TransactionScope(FakeComposerClient& composer) : Transaction(), mComposer(composer) {}
~TransactionScope() {
int frameCount = mComposer.getFrameCount();
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
index d7082f3..06ae314 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
@@ -171,7 +171,7 @@
class Hwc2TestBlendMode : public Hwc2TestProperty<hwc2_blend_mode_t> {
public:
- Hwc2TestBlendMode(Hwc2TestCoverage coverage);
+ explicit Hwc2TestBlendMode(Hwc2TestCoverage coverage);
std::string dump() const override;
@@ -192,8 +192,8 @@
class Hwc2TestColor : public Hwc2TestProperty<hwc_color_t> {
public:
- Hwc2TestColor(Hwc2TestCoverage coverage,
- hwc2_blend_mode_t blendMode = HWC2_BLEND_MODE_NONE);
+ explicit Hwc2TestColor(Hwc2TestCoverage coverage,
+ hwc2_blend_mode_t blendMode = HWC2_BLEND_MODE_NONE);
std::string dump() const override;
@@ -217,7 +217,7 @@
class Hwc2TestComposition : public Hwc2TestProperty<hwc2_composition_t> {
public:
- Hwc2TestComposition(Hwc2TestCoverage coverage);
+ explicit Hwc2TestComposition(Hwc2TestCoverage coverage);
std::string dump() const override;
@@ -232,7 +232,7 @@
class Hwc2TestDataspace : public Hwc2TestProperty<android::ui::Dataspace> {
public:
- Hwc2TestDataspace(Hwc2TestCoverage coverage);
+ explicit Hwc2TestDataspace(Hwc2TestCoverage coverage);
std::string dump() const override;
@@ -248,7 +248,7 @@
class Hwc2TestDisplayDimension : public Hwc2TestProperty<UnsignedArea> {
public:
- Hwc2TestDisplayDimension(Hwc2TestCoverage coverage);
+ explicit Hwc2TestDisplayDimension(Hwc2TestCoverage coverage);
std::string dump() const;
@@ -291,7 +291,7 @@
class Hwc2TestPlaneAlpha : public Hwc2TestProperty<float> {
public:
- Hwc2TestPlaneAlpha(Hwc2TestCoverage coverage);
+ explicit Hwc2TestPlaneAlpha(Hwc2TestCoverage coverage);
std::string dump() const override;
@@ -306,7 +306,7 @@
class Hwc2TestSourceCrop : public Hwc2TestProperty<hwc_frect_t> {
public:
- Hwc2TestSourceCrop(Hwc2TestCoverage coverage, const Area& bufferArea = {0, 0});
+ explicit Hwc2TestSourceCrop(Hwc2TestCoverage coverage, const Area& bufferArea = {0, 0});
std::string dump() const override;
@@ -330,7 +330,7 @@
class Hwc2TestSurfaceDamage : public Hwc2TestProperty<hwc_region_t> {
public:
- Hwc2TestSurfaceDamage(Hwc2TestCoverage coverage);
+ explicit Hwc2TestSurfaceDamage(Hwc2TestCoverage coverage);
~Hwc2TestSurfaceDamage();
std::string dump() const override;
@@ -356,7 +356,7 @@
class Hwc2TestTransform : public Hwc2TestProperty<hwc_transform_t> {
public:
- Hwc2TestTransform(Hwc2TestCoverage coverage);
+ explicit Hwc2TestTransform(Hwc2TestCoverage coverage);
std::string dump() const override;
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h
index 10c8ef0..5a74a6c 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h
@@ -29,7 +29,7 @@
class Hwc2TestVirtualDisplay {
public:
- Hwc2TestVirtualDisplay(Hwc2TestCoverage coverage);
+ explicit Hwc2TestVirtualDisplay(Hwc2TestCoverage coverage);
std::string dump() const;
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 2f35ae5..f63c911 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -20,6 +20,16 @@
// Using the address sanitizer not only helps uncover issues in the code
// covered by the tests, but also covers some of the tricky injection of
// fakes the unit tests currently do.
+ //
+ // Note: If you get an runtime link error like:
+ //
+ // CANNOT LINK EXECUTABLE "/data/local/tmp/libsurfaceflinger_unittest": library "libclang_rt.asan-aarch64-android.so" not found
+ //
+ // it is because the address sanitizer shared objects are not installed
+ // by default in the system image.
+ //
+ // You can either "make dist tests" before flashing, or set this
+ // option to false temporarily.
address: true,
},
srcs: [
@@ -46,11 +56,14 @@
"mock/MockMessageQueue.cpp",
"mock/MockNativeWindowSurface.cpp",
"mock/MockSurfaceInterceptor.cpp",
- "mock/RenderEngine/MockRenderEngine.cpp",
"mock/system/window/MockNativeWindow.cpp",
],
static_libs: [
"libgmock",
+ "libcompositionengine",
+ "libcompositionengine_mocks",
+ "librenderengine_mocks",
+
],
header_libs: [
"libsurfaceflinger_headers",
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index b7c09ed..e417350 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -19,9 +19,11 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
-
#include <gui/IProducerListener.h>
#include <log/log.h>
+#include <renderengine/mock/Framebuffer.h>
+#include <renderengine/mock/Image.h>
+#include <renderengine/mock/RenderEngine.h>
#include <system/window.h>
#include <utils/String8.h>
@@ -36,7 +38,6 @@
#include "mock/MockEventControlThread.h"
#include "mock/MockEventThread.h"
#include "mock/MockMessageQueue.h"
-#include "mock/RenderEngine/MockRenderEngine.h"
#include "mock/system/window/MockNativeWindow.h"
namespace android {
@@ -767,7 +768,7 @@
const auto displayId = test->mDisplay->getId();
ASSERT_TRUE(displayId);
- layer->createHwcLayer(test->mFlinger.mFlinger->getBE().mHwc.get(), *displayId);
+ layer->createHwcLayer(&test->mFlinger.getHwComposer(), *displayId);
Mock::VerifyAndClear(test->mComposer);
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index bd9b140..ff84a62 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -21,9 +21,8 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
-
#include <log/log.h>
-
+#include <renderengine/mock/RenderEngine.h>
#include <ui/DebugUtils.h>
#include "DisplayIdentificationTest.h"
@@ -36,7 +35,6 @@
#include "mock/MockMessageQueue.h"
#include "mock/MockNativeWindowSurface.h"
#include "mock/MockSurfaceInterceptor.h"
-#include "mock/RenderEngine/MockRenderEngine.h"
#include "mock/gui/MockGraphicBufferConsumer.h"
#include "mock/gui/MockGraphicBufferProducer.h"
#include "mock/system/window/MockNativeWindow.h"
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index acbed51..2d26bb3 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -200,7 +200,7 @@
TEST_F(EventThreadTest, requestNextVsyncPostsASingleVSyncEventToTheConnection) {
// Signal that we want the next vsync event to be posted to the connection
- mThread->requestNextVsync(mConnection);
+ mThread->requestNextVsync(mConnection, false);
// EventThread should immediately request a resync.
EXPECT_TRUE(mResyncCallRecorder.waitForCall().has_value());
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 4da08b8..9ff5e8d 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -16,6 +16,8 @@
#pragma once
+#include <compositionengine/impl/CompositionEngine.h>
+
#include "BufferQueueLayer.h"
#include "BufferStateLayer.h"
#include "ColorLayer.h"
@@ -113,6 +115,10 @@
return mCreateNativeWindowSurface(producer);
}
+ std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine() override {
+ return compositionengine::impl::createCompositionEngine();
+ }
+
sp<BufferQueueLayer> createBufferQueueLayer(const LayerCreationArgs&) override {
// TODO: Use test-fixture controlled factory
return nullptr;
@@ -148,6 +154,10 @@
std::function<std::unique_ptr<surfaceflinger::NativeWindowSurface>(
const sp<IGraphicBufferProducer>&)>;
CreateNativeWindowSurfaceFunction mCreateNativeWindowSurface;
+
+ using CreateCompositionEngineFunction =
+ std::function<std::unique_ptr<compositionengine::CompositionEngine>()>;
+ CreateCompositionEngineFunction mCreateCompositionEngine;
};
} // namespace surfaceflinger::test
@@ -158,11 +168,12 @@
// functions.
void setupRenderEngine(std::unique_ptr<renderengine::RenderEngine> renderEngine) {
- mFlinger->getBE().mRenderEngine = std::move(renderEngine);
+ mFlinger->mCompositionEngine->setRenderEngine(std::move(renderEngine));
}
void setupComposer(std::unique_ptr<Hwc2::Composer> composer) {
- mFlinger->getBE().mHwc.reset(new HWComposer(std::move(composer)));
+ mFlinger->mCompositionEngine->setHwComposer(
+ std::make_unique<impl::HWComposer>(std::move(composer)));
}
using CreateBufferQueueFunction = surfaceflinger::test::Factory::CreateBufferQueueFunction;
@@ -178,12 +189,11 @@
using HotplugEvent = SurfaceFlinger::HotplugEvent;
- auto& mutableLayerCurrentState(sp<Layer> layer) { return layer->mState.current; }
- auto& mutableLayerDrawingState(sp<Layer> layer) { return layer->mState.drawing; }
+ auto& mutableLayerCurrentState(sp<Layer> layer) { return layer->mCurrentState; }
+ auto& mutableLayerDrawingState(sp<Layer> layer) { return layer->mDrawingState; }
void setLayerSidebandStream(sp<Layer> layer, sp<NativeHandle> sidebandStream) {
- Mutex::Autolock lock(layer->mStateMutex);
- layer->mState.drawing.sidebandStream = sidebandStream;
+ layer->mDrawingState.sidebandStream = sidebandStream;
layer->getBE().compositionInfo.hwc.sidebandStream = sidebandStream;
}
@@ -253,6 +263,9 @@
const auto& getHasPoweredOff() const { return mFlinger->mHasPoweredOff; }
const auto& getHWVsyncAvailable() const { return mFlinger->mHWVsyncAvailable; }
const auto& getVisibleRegionsDirty() const { return mFlinger->mVisibleRegionsDirty; }
+ auto& getHwComposer() const {
+ return static_cast<impl::HWComposer&>(mFlinger->getHwComposer());
+ }
const auto& getCompositorTiming() const { return mFlinger->getBE().mCompositorTiming; }
@@ -285,13 +298,10 @@
auto& mutableUseHwcVirtualDisplays() { return mFlinger->mUseHwcVirtualDisplays; }
auto& mutableComposerSequenceId() { return mFlinger->getBE().mComposerSequenceId; }
- auto& mutableHwcDisplayData() { return mFlinger->getHwComposer().mDisplayData; }
- auto& mutableHwcPhysicalDisplayIdMap() {
- return mFlinger->getHwComposer().mPhysicalDisplayIdMap;
- }
-
- auto& mutableInternalHwcDisplayId() { return mFlinger->getHwComposer().mInternalHwcDisplayId; }
- auto& mutableExternalHwcDisplayId() { return mFlinger->getHwComposer().mExternalHwcDisplayId; }
+ auto& mutableHwcDisplayData() { return getHwComposer().mDisplayData; }
+ auto& mutableHwcPhysicalDisplayIdMap() { return getHwComposer().mPhysicalDisplayIdMap; }
+ auto& mutableInternalHwcDisplayId() { return getHwComposer().mInternalHwcDisplayId; }
+ auto& mutableExternalHwcDisplayId() { return getHwComposer().mExternalHwcDisplayId; }
~TestableSurfaceFlinger() {
// All these pointer and container clears help ensure that GMock does
@@ -304,8 +314,9 @@
mutableEventThread().reset();
mutableInterceptor().reset();
mutablePrimaryDispSync().reset();
- mFlinger->getBE().mHwc.reset();
- mFlinger->getBE().mRenderEngine.reset();
+ mFlinger->mCompositionEngine->setHwComposer(std::unique_ptr<HWComposer>());
+ mFlinger->mCompositionEngine->setRenderEngine(
+ std::unique_ptr<renderengine::RenderEngine>());
}
/* ------------------------------------------------------------------------
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index bb6e183..48d45fa 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -37,7 +37,7 @@
MOCK_METHOD1(registerDisplayEventConnection,
status_t(const sp<android::EventThreadConnection> &));
MOCK_METHOD2(setVsyncRate, void(uint32_t, const sp<android::EventThreadConnection> &));
- MOCK_METHOD1(requestNextVsync, void(const sp<android::EventThreadConnection> &));
+ MOCK_METHOD2(requestNextVsync, void(const sp<android::EventThreadConnection> &, bool));
};
} // namespace mock
diff --git a/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h b/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
index dc8d606..8c113e2 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
@@ -35,6 +35,7 @@
MOCK_METHOD0(waitMessage, void());
MOCK_METHOD2(postMessage, status_t(const sp<MessageBase>&, nsecs_t));
MOCK_METHOD0(invalidate, void());
+ MOCK_METHOD0(invalidateForHWC, void());
MOCK_METHOD0(refresh, void());
};
diff --git a/services/vr/bufferhubd/include/private/dvr/buffer_hub.h b/services/vr/bufferhubd/include/private/dvr/buffer_hub.h
index 676617d..01520fc 100644
--- a/services/vr/bufferhubd/include/private/dvr/buffer_hub.h
+++ b/services/vr/bufferhubd/include/private/dvr/buffer_hub.h
@@ -41,12 +41,12 @@
// Captures buffer info for use by BufferHubService::DumpState().
struct BufferInfo {
- // Common data field shared by BufferProducer and ProducerQueue.
+ // Common data field shared by ProducerBuffer and ProducerQueue.
int id = -1;
int type = -1;
size_t consumer_count = 0;
- // Data field for buffer producer.
+ // Data field for producer buffer.
uint32_t width = 0;
uint32_t height = 0;
uint32_t layer_count = 0;
diff --git a/services/vr/bufferhubd/include/private/dvr/producer_queue_channel.h b/services/vr/bufferhubd/include/private/dvr/producer_queue_channel.h
index c4003da..0456ad8 100644
--- a/services/vr/bufferhubd/include/private/dvr/producer_queue_channel.h
+++ b/services/vr/bufferhubd/include/private/dvr/producer_queue_channel.h
@@ -37,11 +37,11 @@
uint32_t format, uint64_t usage,
size_t buffer_count);
- // Inserts a BufferProducer into the queue. Note that the buffer must be in
+ // Inserts a ProducerBuffer into the queue. Note that the buffer must be in
// Gain'ed state for the operation to succeed.
pdx::Status<size_t> OnProducerQueueInsertBuffer(pdx::Message& message, int buffer_cid);
- // Removes a BufferProducer indicated by |slot|. Note that the buffer must be
+ // Removes a ProducerBuffer indicated by |slot|. Note that the buffer must be
// in Gain'ed state for the operation to succeed.
pdx::Status<void> OnProducerQueueRemoveBuffer(pdx::Message& message,
size_t slot);
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index 5c484b8..409bce9 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -369,7 +369,9 @@
(consumer_state_mask & BufferHubDefs::kHighBitsMask);
}
}
- if (update_buffer_state) {
+ if (update_buffer_state || BufferHubDefs::IsClientPosted(
+ buffer_state_->load(std::memory_order_acquire),
+ consumer_state_mask)) {
consumer->OnProducerPosted();
}
@@ -455,7 +457,7 @@
uint32_t buffer_state = buffer_state_->load(std::memory_order_acquire);
if (!BufferHubDefs::IsClientGained(
buffer_state, BufferHubDefs::kFirstClientStateMask)) {
- // Can only detach a BufferProducer when it's in gained state.
+ // Can only detach a ProducerBuffer when it's in gained state.
ALOGW(
"ProducerChannel::OnProducerDetach: The buffer (id=%d, state=%"
PRIx32
@@ -537,8 +539,13 @@
uint32_t current_buffer_state =
buffer_state_->load(std::memory_order_acquire);
+ uint32_t current_active_clients_bit_mask =
+ active_clients_bit_mask_->load(std::memory_order_acquire);
+ // Signal producer if all current active consumers have released the buffer.
if (BufferHubDefs::IsBufferReleased(current_buffer_state &
- ~orphaned_consumer_bit_mask_)) {
+ ~orphaned_consumer_bit_mask_ &
+ current_active_clients_bit_mask)) {
+ buffer_state_->store(0U);
SignalAvailable();
if (orphaned_consumer_bit_mask_) {
ALOGW(
@@ -564,8 +571,13 @@
uint32_t current_buffer_state =
buffer_state_->load(std::memory_order_acquire);
+ uint32_t current_active_clients_bit_mask =
+ active_clients_bit_mask_->load(std::memory_order_acquire);
+ // Signal producer if all current active consumers have released the buffer.
if (BufferHubDefs::IsBufferReleased(current_buffer_state &
- ~orphaned_consumer_bit_mask_)) {
+ ~orphaned_consumer_bit_mask_ &
+ current_active_clients_bit_mask)) {
+ buffer_state_->store(0U);
SignalAvailable();
}
diff --git a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.h b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.h
index b478bb5..a82df7f 100644
--- a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.h
+++ b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.h
@@ -10,7 +10,7 @@
class ParcelableComposerFrame : public Parcelable {
public:
ParcelableComposerFrame();
- ParcelableComposerFrame(const ComposerView::Frame& frame);
+ explicit ParcelableComposerFrame(const ComposerView::Frame& frame);
~ParcelableComposerFrame() override;
ComposerView::Frame frame() const { return frame_; }
diff --git a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.h b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.h
index 4cf48f1..6d2ac09 100644
--- a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.h
+++ b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.h
@@ -12,7 +12,7 @@
class ParcelableComposerLayer : public Parcelable {
public:
ParcelableComposerLayer();
- ParcelableComposerLayer(const ComposerView::ComposerLayer& layer);
+ explicit ParcelableComposerLayer(const ComposerView::ComposerLayer& layer);
~ParcelableComposerLayer() override;
ComposerView::ComposerLayer layer() const { return layer_; }
diff --git a/services/vr/hardware_composer/aidl/android/dvr/parcelable_unique_fd.h b/services/vr/hardware_composer/aidl/android/dvr/parcelable_unique_fd.h
index daf9e6d..c4216f6 100644
--- a/services/vr/hardware_composer/aidl/android/dvr/parcelable_unique_fd.h
+++ b/services/vr/hardware_composer/aidl/android/dvr/parcelable_unique_fd.h
@@ -13,7 +13,7 @@
class ParcelableUniqueFd : public Parcelable {
public:
ParcelableUniqueFd();
- ParcelableUniqueFd(const base::unique_fd& fence);
+ explicit ParcelableUniqueFd(const base::unique_fd& fence);
~ParcelableUniqueFd() override;
void set_fence(const base::unique_fd& fence) {
diff --git a/services/vr/hardware_composer/impl/vr_composer_client.h b/services/vr/hardware_composer/impl/vr_composer_client.h
index de22640..0b7ce5e 100644
--- a/services/vr/hardware_composer/impl/vr_composer_client.h
+++ b/services/vr/hardware_composer/impl/vr_composer_client.h
@@ -35,13 +35,13 @@
class VrComposerClient : public ComposerClient {
public:
- VrComposerClient(android::dvr::VrHwc& hal);
+ explicit VrComposerClient(android::dvr::VrHwc& hal);
virtual ~VrComposerClient();
private:
class VrCommandEngine : public ComposerCommandEngine {
public:
- VrCommandEngine(VrComposerClient& client);
+ explicit VrCommandEngine(VrComposerClient& client);
~VrCommandEngine() override;
bool executeCommand(IComposerClient::Command command,
diff --git a/services/vr/hardware_composer/impl/vr_hwc.h b/services/vr/hardware_composer/impl/vr_hwc.h
index f9872b2..e8c0212 100644
--- a/services/vr/hardware_composer/impl/vr_hwc.h
+++ b/services/vr/hardware_composer/impl/vr_hwc.h
@@ -113,9 +113,7 @@
using Composition =
hardware::graphics::composer::V2_1::IComposerClient::Composition;
- HwcLayer(Layer new_id) {
- info.id = new_id;
- }
+ explicit HwcLayer(Layer new_id) { info.id = new_id; }
void dumpDebugInfo(std::string* result) const;
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadService.h b/services/vr/virtual_touchpad/VirtualTouchpadService.h
index 2c46209..2c88aec 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadService.h
+++ b/services/vr/virtual_touchpad/VirtualTouchpadService.h
@@ -13,7 +13,7 @@
//
class VirtualTouchpadService : public BnVirtualTouchpadService {
public:
- VirtualTouchpadService(std::unique_ptr<VirtualTouchpad> touchpad)
+ explicit VirtualTouchpadService(std::unique_ptr<VirtualTouchpad> touchpad)
: touchpad_(std::move(touchpad)), client_pid_(0) {}
~VirtualTouchpadService() override;