Merge "egl: Remove retire event."
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 1cf00f5..9434d56 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1536,7 +1536,7 @@
if (is_redirecting) {
ds.bugreport_dir_ = dirname(use_outfile);
std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
- std::string device_name = android::base::GetProperty("ro.product.device", "UNKNOWN_DEVICE");
+ std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(use_outfile),
device_name.c_str(), build_id.c_str());
if (do_add_date) {
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 4655d33..3153aa5 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -58,6 +58,8 @@
using android::os::dumpstate::DumpFileToFd;
using android::os::dumpstate::PropertiesHelper;
+// Keep in sync with
+// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
/* Most simple commands have 10 as timeout, so 5 is a good estimate */
diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk
index f567a10..be1a434 100644
--- a/cmds/installd/Android.mk
+++ b/cmds/installd/Android.mk
@@ -23,10 +23,9 @@
LOCAL_CFLAGS += -DART_BASE_ADDRESS_MIN_DELTA=$(LOCAL_LIBART_IMG_HOST_MIN_BASE_ADDRESS_DELTA)
LOCAL_CFLAGS += -DART_BASE_ADDRESS_MAX_DELTA=$(LOCAL_LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA)
-LOCAL_SRC_FILES := otapreopt.cpp InstalldNativeService.cpp globals.cpp utils.cpp dexopt.cpp binder/android/os/IInstalld.aidl
+LOCAL_SRC_FILES := otapreopt.cpp globals.cpp utils.cpp dexopt.cpp
LOCAL_SHARED_LIBRARIES := \
libbase \
- libbinder \
libcutils \
liblog \
liblogwrap \
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 754ba4c..9006330 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -359,17 +359,20 @@
}
if (property_get_bool("dalvik.vm.usejitprofiles", false)) {
- const std::string profile_path = create_data_user_profile_package_path(userId, pkgname);
+ const std::string profile_dir =
+ create_primary_current_profile_package_dir_path(userId, pkgname);
// read-write-execute only for the app user.
- if (fs_prepare_dir_strict(profile_path.c_str(), 0700, uid, uid) != 0) {
- return error("Failed to prepare " + profile_path);
+ if (fs_prepare_dir_strict(profile_dir.c_str(), 0700, uid, uid) != 0) {
+ return error("Failed to prepare " + profile_dir);
}
- std::string profile_file = create_primary_profile(profile_path);
+ const std::string profile_file = create_current_profile_path(userId, pkgname,
+ /*is_secondary_dex*/false);
// read-write only for the app user.
if (fs_prepare_file_strict(profile_file.c_str(), 0600, uid, uid) != 0) {
- return error("Failed to prepare " + profile_path);
+ return error("Failed to prepare " + profile_file);
}
- const std::string ref_profile_path = create_data_ref_profile_package_path(pkgname);
+ const std::string ref_profile_path =
+ create_primary_reference_profile_package_dir_path(pkgname);
// dex2oat/profman runs under the shared app gid and it needs to read/write reference
// profiles.
int shared_app_gid = multiuser_get_shared_gid(0, appId);
@@ -433,10 +436,10 @@
std::lock_guard<std::recursive_mutex> lock(mLock);
binder::Status res = ok();
- if (!clear_reference_profile(packageName)) {
+ if (!clear_primary_reference_profile(packageName)) {
res = error("Failed to clear reference profile for " + packageName);
}
- if (!clear_current_profiles(packageName)) {
+ if (!clear_primary_current_profiles(packageName)) {
res = error("Failed to clear current profiles for " + packageName);
}
return res;
@@ -484,7 +487,7 @@
}
}
if (!only_cache) {
- if (!clear_current_profile(packageName, userId)) {
+ if (!clear_primary_current_profile(packageName, userId)) {
res = error("Failed to clear current profile for " + packageName);
}
}
@@ -494,13 +497,13 @@
static int destroy_app_reference_profile(const std::string& pkgname) {
return delete_dir_contents_and_dir(
- create_data_ref_profile_package_path(pkgname),
+ create_primary_reference_profile_package_dir_path(pkgname),
/*ignore_if_missing*/ true);
}
static int destroy_app_current_profiles(const std::string& pkgname, userid_t userid) {
return delete_dir_contents_and_dir(
- create_data_user_profile_package_path(userid, pkgname),
+ create_primary_current_profile_package_dir_path(userid, pkgname),
/*ignore_if_missing*/ true);
}
@@ -727,7 +730,7 @@
if (delete_dir_contents_and_dir(path, true) != 0) {
res = error("Failed to delete " + path);
}
- path = create_data_user_profile_path(userId);
+ path = create_primary_cur_profile_dir_path(userId);
if (delete_dir_contents_and_dir(path, true) != 0) {
res = error("Failed to delete " + path);
}
@@ -1237,9 +1240,9 @@
ATRACE_END();
ATRACE_BEGIN("profiles");
- auto userProfilePath = create_data_user_profile_package_path(userId, pkgname);
+ auto userProfilePath = create_primary_current_profile_package_dir_path(userId, pkgname);
calculate_tree_size(userProfilePath, &stats.dataSize);
- auto refProfilePath = create_data_ref_profile_package_path(pkgname);
+ auto refProfilePath = create_primary_reference_profile_package_dir_path(pkgname);
calculate_tree_size(refProfilePath, &stats.codeSize);
ATRACE_END();
@@ -1257,7 +1260,7 @@
calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
sharedGid, -1);
}
- calculate_tree_size(create_data_user_profile_path(userId), &stats.dataSize,
+ calculate_tree_size(create_primary_cur_profile_dir_path(userId), &stats.dataSize,
multiuser_get_uid(userId, appId), -1);
ATRACE_END();
}
@@ -1332,9 +1335,9 @@
ATRACE_END();
ATRACE_BEGIN("profile");
- auto userProfilePath = create_data_user_profile_path(userId);
+ auto userProfilePath = create_primary_cur_profile_dir_path(userId);
calculate_tree_size(userProfilePath, &stats.dataSize, -1, -1, true);
- auto refProfilePath = create_data_ref_profile_path();
+ auto refProfilePath = create_primary_ref_profile_dir_path();
calculate_tree_size(refProfilePath, &stats.codeSize, -1, -1, true);
ATRACE_END();
@@ -1356,7 +1359,7 @@
ATRACE_BEGIN("dalvik");
calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
-1, -1, true);
- calculate_tree_size(create_data_user_profile_path(userId), &stats.dataSize,
+ calculate_tree_size(create_primary_cur_profile_dir_path(userId), &stats.dataSize,
-1, -1, true);
ATRACE_END();
@@ -1389,9 +1392,9 @@
ATRACE_END();
ATRACE_BEGIN("profile");
- auto userProfilePath = create_data_user_profile_path(userId);
+ auto userProfilePath = create_primary_cur_profile_dir_path(userId);
calculate_tree_size(userProfilePath, &stats.dataSize);
- auto refProfilePath = create_data_ref_profile_path();
+ auto refProfilePath = create_primary_ref_profile_dir_path();
calculate_tree_size(refProfilePath, &stats.codeSize);
ATRACE_END();
@@ -1406,7 +1409,7 @@
ATRACE_BEGIN("dalvik");
calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize);
- calculate_tree_size(create_data_user_profile_path(userId), &stats.dataSize);
+ calculate_tree_size(create_primary_cur_profile_dir_path(userId), &stats.dataSize);
ATRACE_END();
}
@@ -1577,8 +1580,7 @@
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
std::lock_guard<std::recursive_mutex> lock(mLock);
- const char* pkgname = packageName.c_str();
- *_aidl_return = analyse_profiles(uid, pkgname);
+ *_aidl_return = analyze_primary_profiles(uid, packageName);
return ok();
}
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 0d5652f..f7e8d13 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -50,6 +50,18 @@
namespace android {
namespace installd {
+// Deleter using free() for use with std::unique_ptr<>. See also UniqueCPtr<> below.
+struct FreeDelete {
+ // NOTE: Deleting a const object is valid but free() takes a non-const pointer.
+ void operator()(const void* ptr) const {
+ free(const_cast<void*>(ptr));
+ }
+};
+
+// Alias for std::unique_ptr<> that uses the C function free() to delete objects.
+template <typename T>
+using UniqueCPtr = std::unique_ptr<T, FreeDelete>;
+
static unique_fd invalid_unique_fd() {
return unique_fd(-1);
}
@@ -106,27 +118,40 @@
return truncated;
}
-bool clear_reference_profile(const std::string& pkgname) {
- std::string reference_profile_dir = create_data_ref_profile_package_path(pkgname);
- std::string reference_profile = create_primary_profile(reference_profile_dir);
- return clear_profile(reference_profile);
+// Clear the reference profile for the given location.
+// The location is the package name for primary apks or the dex path for secondary dex files.
+static bool clear_reference_profile(const std::string& location, bool is_secondary_dex) {
+ return clear_profile(create_reference_profile_path(location, is_secondary_dex));
}
-bool clear_current_profile(const std::string& pkgname, userid_t user) {
- std::string profile_dir = create_data_user_profile_package_path(user, pkgname);
- std::string profile = create_primary_profile(profile_dir);
- return clear_profile(profile);
+// Clear the reference profile for the given location.
+// The location is the package name for primary apks or the dex path for secondary dex files.
+static bool clear_current_profile(const std::string& pkgname, userid_t user,
+ bool is_secondary_dex) {
+ return clear_profile(create_current_profile_path(user, pkgname, is_secondary_dex));
}
-bool clear_current_profiles(const std::string& pkgname) {
+// Clear the reference profile for the primary apk of the given package.
+bool clear_primary_reference_profile(const std::string& pkgname) {
+ return clear_reference_profile(pkgname, /*is_secondary_dex*/false);
+}
+
+// Clear all current profile for the primary apk of the given package.
+bool clear_primary_current_profiles(const std::string& pkgname) {
bool success = true;
+ // For secondary dex files, we don't really need the user but we use it for sanity checks.
std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
for (auto user : users) {
- success &= clear_current_profile(pkgname, user);
+ success &= clear_current_profile(pkgname, user, /*is_secondary_dex*/false);
}
return success;
}
+// Clear the current profile for the primary apk of the given package and user.
+bool clear_primary_current_profile(const std::string& pkgname, userid_t user) {
+ return clear_current_profile(pkgname, user, /*is_secondary_dex*/false);
+}
+
static int split_count(const char *str)
{
char *ctx;
@@ -472,72 +497,86 @@
}
}
-static unique_fd open_profile_dir(const std::string& profile_dir) {
- unique_fd profile_dir_fd(TEMP_FAILURE_RETRY(open(profile_dir.c_str(),
- O_PATH | O_CLOEXEC | O_DIRECTORY | O_NOFOLLOW)));
- if (profile_dir_fd.get() < 0) {
- // In a multi-user environment, these directories can be created at
- // different points and it's possible we'll attempt to open a profile
- // dir before it exists.
- if (errno != ENOENT) {
- PLOG(ERROR) << "Failed to open profile_dir: " << profile_dir;
- }
- }
- return profile_dir_fd;
-}
-
-static unique_fd open_primary_profile_file_from_dir(const std::string& profile_dir,
- mode_t open_mode) {
- unique_fd profile_dir_fd = open_profile_dir(profile_dir);
- if (profile_dir_fd.get() < 0) {
- return invalid_unique_fd();
- }
-
- std::string profile_file = create_primary_profile(profile_dir);
- unique_fd profile_fd(TEMP_FAILURE_RETRY(open(profile_file.c_str(),
- open_mode | O_NOFOLLOW, 0600)));
- if (profile_fd == -1) {
- // It's not an error if the profile file does not exist.
- if (errno != ENOENT) {
- PLOG(ERROR) << "Failed to open profile : " << profile_file;
- }
- }
- return profile_fd;
-}
-
-static unique_fd open_primary_profile_file(userid_t user, const std::string& pkgname) {
- std::string profile_dir = create_data_user_profile_package_path(user, pkgname);
- return open_primary_profile_file_from_dir(profile_dir, O_RDONLY);
-}
-
-static unique_fd open_reference_profile(uid_t uid, const std::string& pkgname, bool read_write) {
- std::string reference_profile_dir = create_data_ref_profile_package_path(pkgname);
- int flags = read_write ? O_RDWR | O_CREAT : O_RDONLY;
- unique_fd fd = open_primary_profile_file_from_dir(reference_profile_dir, flags);
+static bool create_profile(int uid, const std::string& profile) {
+ unique_fd fd(TEMP_FAILURE_RETRY(open(profile.c_str(), O_CREAT | O_NOFOLLOW, 0600)));
if (fd.get() < 0) {
- return invalid_unique_fd();
+ if (errno == EEXIST) {
+ return true;
+ } else {
+ PLOG(ERROR) << "Failed to create profile " << profile;
+ return false;
+ }
}
+ // Profiles should belong to the app; make sure of that by giving ownership to
+ // the app uid. If we cannot do that, there's no point in returning the fd
+ // since dex2oat/profman will fail with SElinux denials.
+ if (fchown(fd.get(), uid, uid) < 0) {
+ PLOG(ERROR) << "Could not chwon profile " << profile;
+ return false;
+ }
+ return true;
+}
+
+static unique_fd open_profile(int uid, const std::string& profile, bool read_write) {
+ // Check if we need to open the profile for a read-write operation. If so, we
+ // might need to create the profile since the file might not be there. Reference
+ // profiles are created on the fly so they might not exist beforehand.
if (read_write) {
- // Fix the owner.
- if (fchown(fd.get(), uid, uid) < 0) {
+ if (!create_profile(uid, profile)) {
return invalid_unique_fd();
}
}
+ int flags = read_write ? O_RDWR : O_RDONLY;
+ // Do not follow symlinks when opening a profile:
+ // - primary profiles should not contain symlinks in their paths
+ // - secondary dex paths should have been already resolved and validated
+ flags |= O_NOFOLLOW;
+
+ unique_fd fd(TEMP_FAILURE_RETRY(open(profile.c_str(), flags)));
+ if (fd.get() < 0) {
+ if (errno != ENOENT) {
+ // Profiles might be missing for various reasons. For example, in a
+ // multi-user environment, the profile directory for one user can be created
+ // after we start a merge. In this case the current profile for that user
+ // will not be found.
+ // Also, the secondary dex profiles might be deleted by the app at any time,
+ // so we can't we need to prepare if they are missing.
+ PLOG(ERROR) << "Failed to open profile " << profile;
+ }
+ return invalid_unique_fd();
+ }
+
return fd;
}
-static void open_profile_files(uid_t uid, const std::string& pkgname,
+static unique_fd open_current_profile(uid_t uid, userid_t user, const std::string& location,
+ bool is_secondary_dex) {
+ std::string profile = create_current_profile_path(user, location, is_secondary_dex);
+ return open_profile(uid, profile, /*read_write*/false);
+}
+
+static unique_fd open_reference_profile(uid_t uid, const std::string& location, bool read_write,
+ bool is_secondary_dex) {
+ std::string profile = create_reference_profile_path(location, is_secondary_dex);
+ return open_profile(uid, profile, read_write);
+}
+
+static void open_profile_files(uid_t uid, const std::string& location, bool is_secondary_dex,
/*out*/ std::vector<unique_fd>* profiles_fd, /*out*/ unique_fd* reference_profile_fd) {
// Open the reference profile in read-write mode as profman might need to save the merge.
- *reference_profile_fd = open_reference_profile(uid, pkgname, /*read_write*/ true);
- if (reference_profile_fd->get() < 0) {
- // We can't access the reference profile file.
- return;
- }
+ *reference_profile_fd = open_reference_profile(uid, location, /*read_write*/ true,
+ is_secondary_dex);
- std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
+ // For secondary dex files, we don't really need the user but we use it for sanity checks.
+ // Note: the user owning the dex file should be the current user.
+ std::vector<userid_t> users;
+ if (is_secondary_dex){
+ users.push_back(multiuser_get_user_id(uid));
+ } else {
+ users = get_known_users(/*volume_uuid*/ nullptr);
+ }
for (auto user : users) {
- unique_fd profile_fd = open_primary_profile_file(user, pkgname);
+ unique_fd profile_fd = open_current_profile(uid, user, location, is_secondary_dex);
// Add to the lists only if both fds are valid.
if (profile_fd.get() >= 0) {
profiles_fd->push_back(std::move(profile_fd));
@@ -603,14 +642,15 @@
}
// Decides if profile guided compilation is needed or not based on existing profiles.
-// Returns true if there is enough information in the current profiles that worth
-// a re-compilation of the package.
+// The location is the package name for primary apks or the dex path for secondary dex files.
+// Returns true if there is enough information in the current profiles that makes it
+// worth to recompile the given location.
// If the return value is true all the current profiles would have been merged into
// the reference profiles accessible with open_reference_profile().
-bool analyse_profiles(uid_t uid, const std::string& pkgname) {
+static bool analyze_profiles(uid_t uid, const std::string& location, bool is_secondary_dex) {
std::vector<unique_fd> profiles_fd;
unique_fd reference_profile_fd;
- open_profile_files(uid, pkgname, &profiles_fd, &reference_profile_fd);
+ open_profile_files(uid, location, is_secondary_dex, &profiles_fd, &reference_profile_fd);
if (profiles_fd.empty() || (reference_profile_fd.get() < 0)) {
// Skip profile guided compilation because no profiles were found.
// Or if the reference profile info couldn't be opened.
@@ -630,7 +670,7 @@
bool should_clear_current_profiles = false;
bool should_clear_reference_profile = false;
if (!WIFEXITED(return_code)) {
- LOG(WARNING) << "profman failed for package " << pkgname << ": " << return_code;
+ LOG(WARNING) << "profman failed for location " << location << ": " << return_code;
} else {
return_code = WEXITSTATUS(return_code);
switch (return_code) {
@@ -645,7 +685,7 @@
should_clear_reference_profile = false;
break;
case PROFMAN_BIN_RETURN_CODE_BAD_PROFILES:
- LOG(WARNING) << "Bad profiles for package " << pkgname;
+ LOG(WARNING) << "Bad profiles for location " << location;
need_to_compile = false;
should_clear_current_profiles = true;
should_clear_reference_profile = true;
@@ -653,15 +693,15 @@
case PROFMAN_BIN_RETURN_CODE_ERROR_IO: // fall-through
case PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING:
// Temporary IO problem (e.g. locking). Ignore but log a warning.
- LOG(WARNING) << "IO error while reading profiles for package " << pkgname;
+ LOG(WARNING) << "IO error while reading profiles for location " << location;
need_to_compile = false;
should_clear_current_profiles = false;
should_clear_reference_profile = false;
break;
default:
// Unknown return code or error. Unlink profiles.
- LOG(WARNING) << "Unknown error code while processing profiles for package " << pkgname
- << ": " << return_code;
+ LOG(WARNING) << "Unknown error code while processing profiles for location "
+ << location << ": " << return_code;
need_to_compile = false;
should_clear_current_profiles = true;
should_clear_reference_profile = true;
@@ -670,14 +710,29 @@
}
if (should_clear_current_profiles) {
- clear_current_profiles(pkgname);
+ if (is_secondary_dex) {
+ // For secondary dex files, the owning user is the current user.
+ clear_current_profile(location, multiuser_get_user_id(uid), is_secondary_dex);
+ } else {
+ clear_primary_current_profiles(location);
+ }
}
if (should_clear_reference_profile) {
- clear_reference_profile(pkgname);
+ clear_reference_profile(location, is_secondary_dex);
}
return need_to_compile;
}
+// Decides if profile guided compilation is needed or not based on existing profiles.
+// The analysis is done for the primary apks of the given package.
+// Returns true if there is enough information in the current profiles that makes it
+// worth to recompile the package.
+// If the return value is true all the current profiles would have been merged into
+// the reference profiles accessible with open_reference_profile().
+bool analyze_primary_profiles(uid_t uid, const std::string& pkgname) {
+ return analyze_profiles(uid, pkgname, /*is_secondary_dex*/false);
+}
+
static void run_profman_dump(const std::vector<unique_fd>& profile_fds,
const unique_fd& reference_profile_fd,
const std::vector<std::string>& dex_locations,
@@ -729,7 +784,8 @@
unique_fd reference_profile_fd;
std::string out_file_name = StringPrintf("/data/misc/profman/%s.txt", pkgname.c_str());
- open_profile_files(uid, pkgname, &profile_fds, &reference_profile_fd);
+ open_profile_files(uid, pkgname, /*is_secondary_dex*/false,
+ &profile_fds, &reference_profile_fd);
const bool has_reference_profile = (reference_profile_fd.get() != -1);
const bool has_profiles = !profile_fds.empty();
@@ -739,7 +795,8 @@
return false;
}
- unique_fd output_fd(open(out_file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0644));
+ unique_fd output_fd(open(out_file_name.c_str(),
+ O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0644));
if (fchmod(output_fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
ALOGE("installd cannot chmod '%s' dump_profile\n", out_file_name.c_str());
return false;
@@ -1061,23 +1118,22 @@
// Opens the reference profiles if needed.
// Note that the reference profile might not exist so it's OK if the fd will be -1.
-Dex2oatFileWrapper maybe_open_reference_profile(const char* pkgname, bool profile_guided,
- bool is_public, int uid, bool is_secondary_dex) {
+Dex2oatFileWrapper maybe_open_reference_profile(const std::string& pkgname,
+ const std::string& dex_path, bool profile_guided, bool is_public, int uid,
+ bool is_secondary_dex) {
// Public apps should not be compiled with profile information ever. Same goes for the special
// package '*' used for the system server.
- // TODO(calin): add support for writing profiles for secondary dex files
- if (profile_guided && !is_secondary_dex && !is_public && (pkgname[0] != '*')) {
- // Open reference profile in read only mode as dex2oat does not get write permissions.
- const std::string pkgname_str(pkgname);
- unique_fd profile_fd = open_reference_profile(uid, pkgname, /*read_write*/ false);
- return Dex2oatFileWrapper(
- profile_fd.release(),
- [pkgname_str]() {
- clear_reference_profile(pkgname_str.c_str());
- });
- } else {
+ if (!profile_guided || is_public || (pkgname[0] == '*')) {
return Dex2oatFileWrapper();
}
+
+ // Open reference profile in read only mode as dex2oat does not get write permissions.
+ const std::string location = is_secondary_dex ? dex_path : pkgname;
+ unique_fd ufd = open_reference_profile(uid, location, /*read_write*/false, is_secondary_dex);
+ const auto& cleanup = [location, is_secondary_dex]() {
+ clear_reference_profile(location.c_str(), is_secondary_dex);
+ };
+ return Dex2oatFileWrapper(ufd.release(), cleanup);
}
// Opens the vdex files and assigns the input fd to in_vdex_wrapper_fd and the output fd to
@@ -1197,8 +1253,11 @@
}
// Runs (execv) dexoptanalyzer on the given arguments.
-static void exec_dexoptanalyzer(const char* dex_file, const char* instruction_set,
- const char* compiler_filter) {
+// The analyzer will check if the dex_file needs to be (re)compiled to match the compiler_filter.
+// If this is for a profile guided compilation, profile_was_updated will tell whether or not
+// the profile has changed.
+static void exec_dexoptanalyzer(const std::string& dex_file, const char* instruction_set,
+ const char* compiler_filter, bool profile_was_updated) {
static const char* DEXOPTANALYZER_BIN = "/system/bin/dexoptanalyzer";
static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
@@ -1211,18 +1270,22 @@
char dex_file_arg[strlen("--dex-file=") + PKG_PATH_MAX];
char isa_arg[strlen("--isa=") + MAX_INSTRUCTION_SET_LEN];
char compiler_filter_arg[strlen("--compiler-filter=") + kPropertyValueMax];
+ const char* assume_profile_changed = "--assume-profile-changed";
- sprintf(dex_file_arg, "--dex-file=%s", dex_file);
+ sprintf(dex_file_arg, "--dex-file=%s", dex_file.c_str());
sprintf(isa_arg, "--isa=%s", instruction_set);
sprintf(compiler_filter_arg, "--compiler-filter=%s", compiler_filter);
// program name, dex file, isa, filter, the final NULL
- const char* argv[5];
+ const char* argv[5 + (profile_was_updated ? 1 : 0)];
int i = 0;
argv[i++] = DEXOPTANALYZER_BIN;
argv[i++] = dex_file_arg;
argv[i++] = isa_arg;
argv[i++] = compiler_filter_arg;
+ if (profile_was_updated) {
+ argv[i++] = assume_profile_changed;
+ }
argv[i] = NULL;
execv(DEXOPTANALYZER_BIN, (char * const *)argv);
@@ -1230,15 +1293,14 @@
}
// Prepares the oat dir for the secondary dex files.
-static bool prepare_secondary_dex_oat_dir(const char* dex_path, int uid,
- const char* instruction_set, std::string* oat_dir_out) {
- std::string apk_path_str(dex_path);
- unsigned long dirIndex = apk_path_str.rfind('/');
+static bool prepare_secondary_dex_oat_dir(const std::string& dex_path, int uid,
+ const char* instruction_set, std::string* oat_dir_out) {
+ unsigned long dirIndex = dex_path.rfind('/');
if (dirIndex == std::string::npos) {
LOG(ERROR ) << "Unexpected dir structure for secondary dex " << dex_path;
return false;
}
- std::string apk_dir = apk_path_str.substr(0, dirIndex);
+ std::string dex_dir = dex_path.substr(0, dirIndex);
// Assign the gid to the cache gid so that the oat file storage
// is counted towards the app cache.
@@ -1250,13 +1312,13 @@
}
// Create oat file output directory.
- if (prepare_app_cache_dir(apk_dir, "oat", 02711, uid, cache_gid) != 0) {
+ if (prepare_app_cache_dir(dex_dir, "oat", 02711, uid, cache_gid) != 0) {
LOG(ERROR) << "Could not prepare oat dir for secondary dex: " << dex_path;
return false;
}
char oat_dir[PKG_PATH_MAX];
- snprintf(oat_dir, PKG_PATH_MAX, "%s/oat", apk_dir.c_str());
+ snprintf(oat_dir, PKG_PATH_MAX, "%s/oat", dex_dir.c_str());
oat_dir_out->assign(oat_dir);
// Create oat/isa output directory.
@@ -1273,7 +1335,7 @@
// Verifies the result of dexoptanalyzer executed for the apk_path.
// If the result is valid returns true and sets dexopt_needed_out to a valid value.
// Returns false for errors or unexpected result values.
-static bool process_dexoptanalyzer_result(const char* dex_path, int result,
+static bool process_dexoptanalyzer_result(const std::string& dex_path, int result,
int* dexopt_needed_out) {
// The result values are defined in dexoptanalyzer.
switch (result) {
@@ -1305,10 +1367,11 @@
// be compiled. Returns false for errors (logged) or true if the secondary dex path was process
// successfully.
// When returning true, dexopt_needed_out is assigned a valid OatFileAsssitant::DexOptNeeded
-// code and aot_dir_out is assigned the oat dir path where the oat file should be stored.
-static bool process_secondary_dex_dexopt(const char* dex_path, const char* pkgname,
+// code and oat_dir_out is assigned the oat dir path where the oat file should be stored.
+static bool process_secondary_dex_dexopt(const char* original_dex_path, const char* pkgname,
int dexopt_flags, const char* volume_uuid, int uid, const char* instruction_set,
- const char* compiler_filter, int* dexopt_needed_out, std::string* aot_dir_out) {
+ const char* compiler_filter, int* dexopt_needed_out, std::string* oat_dir_out,
+ std::string* dex_path_out) {
int storage_flag;
if ((dexopt_flags & DEXOPT_STORAGE_CE) != 0) {
@@ -1324,17 +1387,31 @@
return false;
}
+ {
+ // As opposed to the primary apk, secondary dex files might contain symlinks.
+ // Resolve the path before passing it to the validate method to
+ // make sure the verification is done on the real location.
+ UniqueCPtr<char> dex_real_path_cstr(realpath(original_dex_path, nullptr));
+ if (dex_real_path_cstr == nullptr) {
+ PLOG(ERROR) << "Could not get the real path of the secondary dex file "
+ << original_dex_path;
+ return false;
+ } else {
+ dex_path_out->assign(dex_real_path_cstr.get());
+ }
+ }
+ const std::string& dex_path = *dex_path_out;
if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid, uid, storage_flag)) {
LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
return false;
}
// Check if the path exist. If not, there's nothing to do.
- if (access(dex_path, F_OK) != 0) {
+ if (access(dex_path.c_str(), F_OK) != 0) {
if (errno == ENOENT) {
// Secondary dex files might be deleted any time by the app.
// Nothing to do if that's the case
- ALOGV("Secondary dex does not exist %s", dex_path);
+ ALOGV("Secondary dex does not exist %s", dex_path.c_str());
return NO_DEXOPT_NEEDED;
} else {
PLOG(ERROR) << "Could not access secondary dex " << dex_path;
@@ -1342,16 +1419,19 @@
}
// Prepare the oat directories.
- if (!prepare_secondary_dex_oat_dir(dex_path, uid, instruction_set, aot_dir_out)) {
+ if (!prepare_secondary_dex_oat_dir(dex_path, uid, instruction_set, oat_dir_out)) {
return false;
}
+ // Analyze profiles.
+ bool profile_was_updated = analyze_profiles(uid, dex_path, /*is_secondary_dex*/true);
+
pid_t pid = fork();
if (pid == 0) {
// child -- drop privileges before continuing.
drop_capabilities(uid);
// Run dexoptanalyzer to get dexopt_needed code.
- exec_dexoptanalyzer(dex_path, instruction_set, compiler_filter);
+ exec_dexoptanalyzer(dex_path, instruction_set, compiler_filter, profile_was_updated);
exit(DEXOPTANALYZER_BIN_EXEC_ERROR);
}
@@ -1394,10 +1474,12 @@
// Check if we're dealing with a secondary dex file and if we need to compile it.
std::string oat_dir_str;
+ std::string dex_real_path;
if (is_secondary_dex) {
if (process_secondary_dex_dexopt(dex_path, pkgname, dexopt_flags, volume_uuid, uid,
- instruction_set, compiler_filter, &dexopt_needed, &oat_dir_str)) {
+ instruction_set, compiler_filter, &dexopt_needed, &oat_dir_str, &dex_real_path)) {
oat_dir = oat_dir_str.c_str();
+ dex_path = dex_real_path.c_str();
if (dexopt_needed == NO_DEXOPT_NEEDED) {
return 0; // Nothing to do, report success.
}
@@ -1442,8 +1524,8 @@
maybe_open_app_image(out_oat_path, profile_guided, is_public, uid, is_secondary_dex);
// Open the reference profile if needed.
- Dex2oatFileWrapper reference_profile_fd =
- maybe_open_reference_profile(pkgname, profile_guided, is_public, uid, is_secondary_dex);
+ Dex2oatFileWrapper reference_profile_fd = maybe_open_reference_profile(
+ pkgname, dex_path, profile_guided, is_public, uid, is_secondary_dex);
ALOGV("DexInv: --- BEGIN '%s' ---\n", dex_path);
@@ -1482,7 +1564,7 @@
ALOGV("DexInv: --- END '%s' (success) ---\n", dex_path);
} else {
ALOGE("DexInv: --- END '%s' --- status=0x%04x, process failed\n", dex_path, res);
- return -1;
+ return res;
}
}
@@ -1541,7 +1623,7 @@
snprintf(out_oat_isa_dir, PKG_PATH_MAX, "%s/%s", out_oat_dir, isa.c_str());
if (!create_oat_out_path(dex_path.c_str(), isa.c_str(), out_oat_dir,
- /*is_secondary_dex*/ true, out_oat_path)) {
+ /*is_secondary_dex*/true, out_oat_path)) {
LOG(ERROR) << "Could not create oat path for secondary dex " << dex_path;
return false;
}
@@ -1738,7 +1820,7 @@
// Delete the oat/odex file.
char out_path[PKG_PATH_MAX];
if (!create_oat_out_path(apk_path, instruction_set, oat_dir,
- /*is_secondary_dex*/ false, out_path)) {
+ /*is_secondary_dex*/false, out_path)) {
return false;
}
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index df6d176..dbf3fae 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -32,13 +32,23 @@
static constexpr int DEX2OAT_FOR_RELOCATION = 4;
static constexpr int PATCHOAT_FOR_RELOCATION = 5;
-bool clear_reference_profile(const std::string& pkgname);
-bool clear_current_profile(const std::string& pkgname, userid_t user);
-bool clear_current_profiles(const std::string& pkgname);
+// Clear the reference profile for the primary apk of the given package.
+bool clear_primary_reference_profile(const std::string& pkgname);
+// Clear the current profile for the primary apk of the given package and user.
+bool clear_primary_current_profile(const std::string& pkgname, userid_t user);
+// Clear all current profile for the primary apk of the given package.
+bool clear_primary_current_profiles(const std::string& pkgname);
bool move_ab(const char* apk_path, const char* instruction_set, const char* output_path);
-bool analyse_profiles(uid_t uid, const std::string& pkgname);
+// Decide if profile guided compilation is needed or not based on existing profiles.
+// The analysis is done for the primary apks (base + splits) of the given package.
+// Returns true if there is enough information in the current profiles that makes it
+// worth to recompile the package.
+// If the return value is true all the current profiles would have been merged into
+// the reference profiles accessible with open_reference_profile().
+bool analyze_primary_profiles(uid_t uid, const std::string& pkgname);
+
bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths);
bool delete_odex(const char* apk_path, const char* instruction_set, const char* output_path);
diff --git a/cmds/installd/globals.h b/cmds/installd/globals.h
index 8242eec..c90beec 100644
--- a/cmds/installd/globals.h
+++ b/cmds/installd/globals.h
@@ -20,8 +20,6 @@
#include <inttypes.h>
-#include "InstalldNativeService.h"
-
namespace android {
namespace installd {
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index c74c65b..82b8cc2 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -36,7 +36,6 @@
#include <log/log.h>
#include <private/android_filesystem_config.h>
-#include "InstalldNativeService.h"
#include "dexopt.h"
#include "file_parsing.h"
#include "globals.h"
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 850d257..49605be 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -525,29 +525,50 @@
}
TEST_F(UtilsTest, CreateDataUserProfilePath) {
- EXPECT_EQ("/data/misc/profiles/cur/0", create_data_user_profile_path(0));
- EXPECT_EQ("/data/misc/profiles/cur/1", create_data_user_profile_path(1));
+ EXPECT_EQ("/data/misc/profiles/cur/0", create_primary_cur_profile_dir_path(0));
+ EXPECT_EQ("/data/misc/profiles/cur/1", create_primary_cur_profile_dir_path(1));
}
TEST_F(UtilsTest, CreateDataUserProfilePackagePath) {
EXPECT_EQ("/data/misc/profiles/cur/0/com.example",
- create_data_user_profile_package_path(0, "com.example"));
+ create_primary_current_profile_package_dir_path(0, "com.example"));
EXPECT_EQ("/data/misc/profiles/cur/1/com.example",
- create_data_user_profile_package_path(1, "com.example"));
+ create_primary_current_profile_package_dir_path(1, "com.example"));
}
TEST_F(UtilsTest, CreateDataRefProfilePath) {
- EXPECT_EQ("/data/misc/profiles/ref", create_data_ref_profile_path());
+ EXPECT_EQ("/data/misc/profiles/ref", create_primary_ref_profile_dir_path());
}
TEST_F(UtilsTest, CreateDataRefProfilePackagePath) {
EXPECT_EQ("/data/misc/profiles/ref/com.example",
- create_data_ref_profile_package_path("com.example"));
+ create_primary_reference_profile_package_dir_path("com.example"));
}
-TEST_F(UtilsTest, CreatePrimaryProfile) {
- EXPECT_EQ("/data/misc/profiles/ref/com.example/primary.prof",
- create_primary_profile("/data/misc/profiles/ref/com.example"));
+TEST_F(UtilsTest, CreatePrimaryCurrentProfile) {
+ std::string expected =
+ create_primary_current_profile_package_dir_path(1, "com.example") + "/primary.prof";
+ EXPECT_EQ(expected,
+ create_current_profile_path(/*user*/0, "com.example", /*is_secondary*/false));
+}
+
+TEST_F(UtilsTest, CreatePrimaryReferenceProfile) {
+ std::string expected =
+ create_primary_reference_profile_package_dir_path("com.example") + "/primary.prof";
+ EXPECT_EQ(expected,
+ create_reference_profile_path("com.example", /*is_secondary*/false));
+}
+
+TEST_F(UtilsTest, CreateSecondaryCurrentProfile) {
+ EXPECT_EQ("/data/user/0/com.example/secondary.dex.prof",
+ create_current_profile_path(/*user*/0,
+ "/data/user/0/com.example/secondary.dex", /*is_secondary*/true));
+}
+
+TEST_F(UtilsTest, CreateSecondaryReferenceProfile) {
+ EXPECT_EQ("/data/user/0/com.example/oat/secondary.dex.prof",
+ create_reference_profile_path(
+ "/data/user/0/com.example/secondary.dex", /*is_secondary*/true));
}
} // namespace installd
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 5a08c32..97298e5 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -217,20 +217,22 @@
return StringPrintf("%s/misc/user/%u", create_data_path(nullptr).c_str(), userid);
}
-std::string create_data_user_profile_path(userid_t userid) {
+std::string create_primary_cur_profile_dir_path(userid_t userid) {
return StringPrintf("%s/cur/%u", android_profiles_dir.path, userid);
}
-std::string create_data_user_profile_package_path(userid_t user, const std::string& package_name) {
+std::string create_primary_current_profile_package_dir_path(userid_t user,
+ const std::string& package_name) {
check_package_name(package_name.c_str());
- return StringPrintf("%s/%s",create_data_user_profile_path(user).c_str(), package_name.c_str());
+ return StringPrintf("%s/%s",
+ create_primary_cur_profile_dir_path(user).c_str(), package_name.c_str());
}
-std::string create_data_ref_profile_path() {
+std::string create_primary_ref_profile_dir_path() {
return StringPrintf("%s/ref", android_profiles_dir.path);
}
-std::string create_data_ref_profile_package_path(const std::string& package_name) {
+std::string create_primary_reference_profile_package_dir_path(const std::string& package_name) {
check_package_name(package_name.c_str());
return StringPrintf("%s/ref/%s", android_profiles_dir.path, package_name.c_str());
}
@@ -239,11 +241,38 @@
return "/data/dalvik-cache";
}
-// Keep profile paths in sync with ActivityThread.
-constexpr const char* PRIMARY_PROFILE_NAME = "primary.prof";
+// Keep profile paths in sync with ActivityThread and LoadedApk.
+const std::string PROFILE_EXT = ".prof";
+const std::string PRIMARY_PROFILE_NAME = "primary" + PROFILE_EXT;
-std::string create_primary_profile(const std::string& profile_dir) {
- return StringPrintf("%s/%s", profile_dir.c_str(), PRIMARY_PROFILE_NAME);
+std::string create_current_profile_path(userid_t user, const std::string& location,
+ bool is_secondary_dex) {
+ if (is_secondary_dex) {
+ // Secondary dex profiles are stored next to the dex files using .prof extension.
+ return StringPrintf("%s%s", location.c_str(), PROFILE_EXT.c_str());
+ } else {
+ // Profiles for primary apks are under /data/misc/profiles/cur.
+ std::string profile_dir = create_primary_current_profile_package_dir_path(user, location);
+ return StringPrintf("%s/%s", profile_dir.c_str(), PRIMARY_PROFILE_NAME.c_str());
+ }
+}
+
+std::string create_reference_profile_path(const std::string& location, bool is_secondary_dex) {
+ if (is_secondary_dex) {
+ // Secondary dex reference profiles are stored next to the dex files under the oat folder.
+ size_t dirIndex = location.rfind('/');
+ CHECK(dirIndex != std::string::npos)
+ << "Unexpected dir structure for secondary dex " << location;
+
+ std::string dex_dir = location.substr(0, dirIndex);
+ std::string dex_name = location.substr(dirIndex +1);
+ return StringPrintf("%s/oat/%s%s",
+ dex_dir.c_str(), dex_name.c_str(), PROFILE_EXT.c_str());
+ } else {
+ // Reference profiles for primary apks are stored in /data/misc/profile/ref.
+ std::string profile_dir = create_primary_reference_profile_package_dir_path(location);
+ return StringPrintf("%s/%s", profile_dir.c_str(), PRIMARY_PROFILE_NAME.c_str());
+ }
}
std::vector<userid_t> get_known_users(const char* volume_uuid) {
@@ -1182,13 +1211,15 @@
return -1;
}
-bool validate_secondary_dex_path(const char* pkgname, const char* path,
+bool validate_secondary_dex_path(const std::string& pkgname, const std::string& dex_path,
const char* volume_uuid, int uid, int storage_flag) {
CHECK(storage_flag == FLAG_STORAGE_CE || storage_flag == FLAG_STORAGE_DE);
std::string app_private_dir = storage_flag == FLAG_STORAGE_CE
- ? create_data_user_ce_package_path(volume_uuid, multiuser_get_user_id(uid), pkgname)
- : create_data_user_de_package_path(volume_uuid, multiuser_get_user_id(uid), pkgname);
+ ? create_data_user_ce_package_path(
+ volume_uuid, multiuser_get_user_id(uid), pkgname.c_str())
+ : create_data_user_de_package_path(
+ volume_uuid, multiuser_get_user_id(uid), pkgname.c_str());
dir_rec_t dir;
if (get_path_from_string(&dir, app_private_dir.c_str()) != 0) {
LOG(WARNING) << "Could not get dir rec for " << app_private_dir;
@@ -1198,7 +1229,7 @@
// Pick at most 10 subdirectories when validating (arbitrary value).
// If the secondary dex file is >10 directory nested then validation will
// fail and the file will not be compiled.
- return validate_path(&dir, path, /*max_subdirs*/ 10) == 0;
+ return validate_path(&dir, dex_path.c_str(), /*max_subdirs*/ 10) == 0;
}
/**
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 1c36a54..abe6830 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -96,15 +96,19 @@
std::string create_data_misc_legacy_path(userid_t userid);
-std::string create_data_user_profile_path(userid_t userid);
-std::string create_data_user_profile_package_path(userid_t user, const std::string& package_name);
-
-std::string create_data_ref_profile_path();
-std::string create_data_ref_profile_package_path(const std::string& package_name);
-
std::string create_data_dalvik_cache_path();
-std::string create_primary_profile(const std::string& profile_dir);
+std::string create_primary_cur_profile_dir_path(userid_t userid);
+std::string create_primary_current_profile_package_dir_path(
+ userid_t user, const std::string& package_name);
+
+std::string create_primary_ref_profile_dir_path();
+std::string create_primary_reference_profile_package_dir_path(const std::string& package_name);
+
+std::string create_current_profile_path(
+ userid_t user, const std::string& package_name, bool is_secondary_dex);
+std::string create_reference_profile_path(
+ const std::string& package_name, bool is_secondary_dex);
std::vector<userid_t> get_known_users(const char* volume_uuid);
@@ -151,7 +155,7 @@
void finish_cache_collection(cache_t* cache);
int validate_system_app_path(const char* path);
-bool validate_secondary_dex_path(const char* pkgname, const char* path,
+bool validate_secondary_dex_path(const std::string& pkgname, const std::string& dex_path,
const char* volume_uuid, int uid, int storage_flag);
int get_path_from_env(dir_rec_t* rec, const char* var);
diff --git a/cmds/vr/pose/Android.mk b/cmds/vr/pose/Android.mk
index 1657551..8be3214 100644
--- a/cmds/vr/pose/Android.mk
+++ b/cmds/vr/pose/Android.mk
@@ -19,7 +19,7 @@
staticLibraries := \
libdvrcommon \
- libsensor \
+ libvrsensor \
libpdx_default_transport \
sharedLibraries := \
@@ -33,9 +33,3 @@
LOCAL_MODULE := pose
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
-
-ifeq ($(TARGET_BUILD_VARIANT),eng)
-ALL_DEFAULT_INSTALLED_MODULES += pose
-all_modules: pose
-endif
-
diff --git a/cmds/vr/vrscreencap/Android.mk b/cmds/vr/vrscreencap/Android.mk
index 2fa9155..bd0b224 100644
--- a/cmds/vr/vrscreencap/Android.mk
+++ b/cmds/vr/vrscreencap/Android.mk
@@ -21,8 +21,3 @@
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
-
-ifeq ($(TARGET_BUILD_VARIANT),eng)
-ALL_DEFAULT_INSTALLED_MODULES += vrscreencap
-all_modules: vrscreencap
-endif
diff --git a/data/etc/android.hardware.vr.headtracking-0.xml b/data/etc/android.hardware.vr.headtracking-0.xml
new file mode 100644
index 0000000..1b53995
--- /dev/null
+++ b/data/etc/android.hardware.vr.headtracking-0.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- This is the feature indicating that the device supports VR headtracking
+ level 0 -->
+<permissions>
+ <feature name="android.hardware.vr.headtracking" version="0" />
+</permissions>
diff --git a/data/etc/android.hardware.vr.headtracking-1.xml b/data/etc/android.hardware.vr.headtracking-1.xml
new file mode 100644
index 0000000..2ad8ccc
--- /dev/null
+++ b/data/etc/android.hardware.vr.headtracking-1.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- This is the feature indicating that the device supports VR headtracking
+ level 1 -->
+<permissions>
+ <feature name="android.hardware.vr.headtracking" version="1" />
+</permissions>
diff --git a/data/etc/car_core_hardware.xml b/data/etc/car_core_hardware.xml
index ab89ef5..835504f 100644
--- a/data/etc/car_core_hardware.xml
+++ b/data/etc/car_core_hardware.xml
@@ -23,6 +23,9 @@
devices.
-->
<permissions>
+ <!-- This is Android and fully CTS compatible. Basically this is for CTS tests to use. -->
+ <feature name="android.software.cts" />
+
<feature name="android.hardware.audio.output" />
<feature name="android.hardware.location" />
<feature name="android.hardware.location.network" />
diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml
index 467e0fd..2607d58 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -23,6 +23,9 @@
devices.
-->
<permissions>
+ <!-- This is Android and fully CTS compatible. Basically this is for CTS tests to use. -->
+ <feature name="android.software.cts" />
+
<feature name="android.hardware.audio.output" />
<feature name="android.hardware.camera" />
<feature name="android.hardware.location" />
@@ -56,6 +59,9 @@
<!-- Devices with all optimizations required to be a "VR Ready" device that
pass all CTS tests for this feature must include feature
android.hardware.vr.high_performance -->
+ <!-- Devices that support VR headtracking features and pass all CDD
+ requirements may include
+ android.hardware.vr.headtracking -->
<!-- devices with GPS must include android.hardware.location.gps.xml -->
<!-- devices with an autofocus camera and/or flash must include either
diff --git a/data/etc/tablet_core_hardware.xml b/data/etc/tablet_core_hardware.xml
index 7f545e6..f0ca067 100644
--- a/data/etc/tablet_core_hardware.xml
+++ b/data/etc/tablet_core_hardware.xml
@@ -23,6 +23,9 @@
devices.
-->
<permissions>
+ <!-- This is Android and fully CTS compatible. Basically this is for CTS tests to use. -->
+ <feature name="android.software.cts" />
+
<feature name="android.hardware.audio.output" />
<feature name="android.hardware.location" />
<feature name="android.hardware.location.network" />
diff --git a/data/etc/wearable_core_hardware.xml b/data/etc/wearable_core_hardware.xml
index 84230da..a7955e9 100644
--- a/data/etc/wearable_core_hardware.xml
+++ b/data/etc/wearable_core_hardware.xml
@@ -21,6 +21,9 @@
Wearable devices include watches, glasses, backpacks, and sweaters.
-->
<permissions>
+ <!-- This is Android and fully CTS compatible. Basically this is for CTS tests to use. -->
+ <feature name="android.software.cts" />
+
<feature name="android.hardware.location" />
<!-- devices supporting compass/magnitometer sensor must include
android.hardware.sensor.compass.xml -->
diff --git a/include/gui/BufferItemConsumer.h b/include/gui/BufferItemConsumer.h
index ec77ec7..db7e944 100644
--- a/include/gui/BufferItemConsumer.h
+++ b/include/gui/BufferItemConsumer.h
@@ -37,6 +37,10 @@
public:
typedef ConsumerBase::FrameAvailableListener FrameAvailableListener;
+ struct BufferFreedListener : public virtual RefBase {
+ virtual void onBufferFreed(const wp<GraphicBuffer>& graphicBuffer) = 0;
+ };
+
enum { DEFAULT_MAX_BUFFERS = -1 };
enum { INVALID_BUFFER_SLOT = BufferQueue::INVALID_BUFFER_SLOT };
enum { NO_BUFFER_AVAILABLE = BufferQueue::NO_BUFFER_AVAILABLE };
@@ -57,6 +61,10 @@
// log messages.
void setName(const String8& name);
+ // setBufferFreedListener sets the listener object that will be notified
+ // when an old buffer is being freed.
+ void setBufferFreedListener(const wp<BufferFreedListener>& listener);
+
// Gets the next graphics buffer from the producer, filling out the
// passed-in BufferItem structure. Returns NO_BUFFER_AVAILABLE if the queue
// of buffers is empty, and INVALID_OPERATION if the maximum number of
@@ -81,6 +89,13 @@
status_t releaseBuffer(const BufferItem &item,
const sp<Fence>& releaseFence = Fence::NO_FENCE);
+ private:
+ void freeBufferLocked(int slotIndex) override;
+
+ // mBufferFreedListener is the listener object that will be called when
+ // an old buffer is being freed. If it is not NULL it will be called from
+ // freeBufferLocked.
+ wp<BufferFreedListener> mBufferFreedListener;
};
} // namespace android
diff --git a/libs/gui/BufferItemConsumer.cpp b/libs/gui/BufferItemConsumer.cpp
index 3491043..d9d50db 100644
--- a/libs/gui/BufferItemConsumer.cpp
+++ b/libs/gui/BufferItemConsumer.cpp
@@ -22,7 +22,7 @@
#include <gui/BufferItem.h>
#include <gui/BufferItemConsumer.h>
-//#define BI_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
+#define BI_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
//#define BI_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
//#define BI_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__)
//#define BI_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__)
@@ -57,6 +57,12 @@
mConsumer->setConsumerName(name);
}
+void BufferItemConsumer::setBufferFreedListener(
+ const wp<BufferFreedListener>& listener) {
+ Mutex::Autolock _l(mMutex);
+ mBufferFreedListener = listener;
+}
+
status_t BufferItemConsumer::acquireBuffer(BufferItem *item,
nsecs_t presentWhen, bool waitForFence) {
status_t err;
@@ -104,4 +110,14 @@
return err;
}
+void BufferItemConsumer::freeBufferLocked(int slotIndex) {
+ sp<BufferFreedListener> listener = mBufferFreedListener.promote();
+ if (listener != NULL && mSlots[slotIndex].mGraphicBuffer != NULL) {
+ // Fire callback if we have a listener registered and the buffer being freed is valid.
+ BI_LOGV("actually calling onBufferFreed");
+ listener->onBufferFreed(mSlots[slotIndex].mGraphicBuffer);
+ }
+ ConsumerBase::freeBufferLocked(slotIndex);
+}
+
} // namespace android
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index 4492a08..3a99147 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -8,6 +8,7 @@
clang: true,
srcs: [
+ "BufferItemConsumer_test.cpp",
"BufferQueue_test.cpp",
"CpuConsumer_test.cpp",
"FillBuffer.cpp",
diff --git a/libs/gui/tests/BufferItemConsumer_test.cpp b/libs/gui/tests/BufferItemConsumer_test.cpp
new file mode 100644
index 0000000..d64e530
--- /dev/null
+++ b/libs/gui/tests/BufferItemConsumer_test.cpp
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BufferItemConsumer_test"
+//#define LOG_NDEBUG 0
+
+#include <gtest/gtest.h>
+#include <gui/BufferItemConsumer.h>
+#include <gui/IProducerListener.h>
+#include <gui/Surface.h>
+
+namespace android {
+
+static constexpr int kWidth = 100;
+static constexpr int kHeight = 100;
+static constexpr int kMaxLockedBuffers = 3;
+static constexpr int kFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+static constexpr int kFrameSleepUs = 30 * 1000;
+
+class BufferItemConsumerTest : public ::testing::Test {
+ protected:
+ struct BufferFreedListener
+ : public BufferItemConsumer::BufferFreedListener {
+ explicit BufferFreedListener(BufferItemConsumerTest* test)
+ : mTest(test) {}
+ void onBufferFreed(const wp<GraphicBuffer>& /* gBuffer */) override {
+ mTest->HandleBufferFreed();
+ }
+ BufferItemConsumerTest* mTest;
+ };
+
+ void SetUp() override {
+ BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+ mBIC =
+ new BufferItemConsumer(mConsumer, kFormat, kMaxLockedBuffers, true);
+ String8 name("BufferItemConsumer_Under_Test");
+ mBIC->setName(name);
+ mBFL = new BufferFreedListener(this);
+ mBIC->setBufferFreedListener(mBFL);
+
+ sp<IProducerListener> producerListener = new DummyProducerListener();
+ IGraphicBufferProducer::QueueBufferOutput bufferOutput;
+ ASSERT_EQ(NO_ERROR,
+ mProducer->connect(producerListener, NATIVE_WINDOW_API_CPU,
+ true, &bufferOutput));
+ ASSERT_EQ(NO_ERROR,
+ mProducer->setMaxDequeuedBufferCount(kMaxLockedBuffers));
+ }
+
+ int GetFreedBufferCount() {
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mFreedBufferCount;
+ }
+
+ void HandleBufferFreed() {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mFreedBufferCount++;
+ ALOGV("HandleBufferFreed, mFreedBufferCount=%d", mFreedBufferCount);
+ }
+
+ void DequeueBuffer(int* outSlot) {
+ ASSERT_NE(outSlot, nullptr);
+
+ int slot;
+ sp<Fence> outFence;
+ status_t ret = mProducer->dequeueBuffer(&slot, &outFence, kWidth,
+ kHeight, 0, 0, nullptr);
+ ASSERT_GE(ret, 0);
+
+ ALOGV("dequeueBuffer: slot=%d", slot);
+ if (ret & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
+ ret = mProducer->requestBuffer(slot, &mBuffers[slot]);
+ ASSERT_EQ(NO_ERROR, ret);
+ }
+ *outSlot = slot;
+ }
+
+ void QueueBuffer(int slot) {
+ ALOGV("enqueueBuffer: slot=%d", slot);
+ IGraphicBufferProducer::QueueBufferInput bufferInput(
+ 0ULL, true, HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
+ NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
+ IGraphicBufferProducer::QueueBufferOutput bufferOutput;
+ status_t ret = mProducer->queueBuffer(slot, bufferInput, &bufferOutput);
+ ASSERT_EQ(NO_ERROR, ret);
+ }
+
+ void AcquireBuffer(int* outSlot) {
+ ASSERT_NE(outSlot, nullptr);
+ BufferItem buffer;
+ status_t ret = mBIC->acquireBuffer(&buffer, 0, false);
+ ASSERT_EQ(NO_ERROR, ret);
+
+ ALOGV("acquireBuffer: slot=%d", buffer.mSlot);
+ *outSlot = buffer.mSlot;
+ }
+
+ void ReleaseBuffer(int slot) {
+ ALOGV("releaseBuffer: slot=%d", slot);
+ BufferItem buffer;
+ buffer.mSlot = slot;
+ buffer.mGraphicBuffer = mBuffers[slot];
+ status_t ret = mBIC->releaseBuffer(buffer, Fence::NO_FENCE);
+ ASSERT_EQ(NO_ERROR, ret);
+ }
+
+
+ std::mutex mMutex;
+ int mFreedBufferCount{0};
+
+ sp<BufferItemConsumer> mBIC;
+ sp<BufferFreedListener> mBFL;
+ sp<IGraphicBufferProducer> mProducer;
+ sp<IGraphicBufferConsumer> mConsumer;
+ sp<GraphicBuffer> mBuffers[BufferQueueDefs::NUM_BUFFER_SLOTS];
+};
+
+// Test that detaching buffer from consumer side triggers onBufferFreed.
+TEST_F(BufferItemConsumerTest, TriggerBufferFreed_DetachBufferFromConsumer) {
+ int slot;
+ // Producer: generate a dummy buffer.
+ DequeueBuffer(&slot);
+ QueueBuffer(slot);
+
+ ASSERT_EQ(0, GetFreedBufferCount());
+ // Consumer: acquire the buffer and then detach it.
+ AcquireBuffer(&slot);
+ status_t ret = mBIC->detachBuffer(slot);
+ ASSERT_EQ(NO_ERROR, ret);
+
+ // Sleep to give some time for callbacks to happen.
+ usleep(kFrameSleepUs);
+ ASSERT_EQ(1, GetFreedBufferCount());
+}
+
+// Test that detaching buffer from producer side triggers onBufferFreed.
+TEST_F(BufferItemConsumerTest, TriggerBufferFreed_DetachBufferFromProducer) {
+ int slot;
+ // Let buffer go through the cycle at least once.
+ DequeueBuffer(&slot);
+ QueueBuffer(slot);
+ AcquireBuffer(&slot);
+ ReleaseBuffer(slot);
+
+ ASSERT_EQ(0, GetFreedBufferCount());
+
+ // Producer: generate the buffer again.
+ DequeueBuffer(&slot);
+
+ // Producer: detach the buffer.
+ status_t ret = mProducer->detachBuffer(slot);
+ ASSERT_EQ(NO_ERROR, ret);
+
+ // Sleep to give some time for callbacks to happen.
+ usleep(kFrameSleepUs);
+ ASSERT_EQ(1, GetFreedBufferCount());
+}
+
+// Test that abandoning BufferItemConsumer triggers onBufferFreed.
+TEST_F(BufferItemConsumerTest, TriggerBufferFreed_AbandonBufferItemConsumer) {
+ int slot;
+ // Let buffer go through the cycle at least once.
+ DequeueBuffer(&slot);
+ QueueBuffer(slot);
+ AcquireBuffer(&slot);
+ ReleaseBuffer(slot);
+
+ // Abandon the BufferItemConsumer.
+ mBIC->abandon();
+
+ // Sleep to give some time for callbacks to happen.
+ usleep(kFrameSleepUs);
+ ASSERT_EQ(1, GetFreedBufferCount());
+}
+
+// Test that delete BufferItemConsumer triggers onBufferFreed.
+TEST_F(BufferItemConsumerTest, TriggerBufferFreed_DeleteBufferItemConsumer) {
+ int slot;
+ // Let buffer go through the cycle at least once.
+ DequeueBuffer(&slot);
+ QueueBuffer(slot);
+ AcquireBuffer(&slot);
+ ReleaseBuffer(slot);
+
+ // Delete the BufferItemConsumer.
+ mBIC.clear();
+
+ // Sleep to give some time for callbacks to happen.
+ usleep(kFrameSleepUs);
+ ASSERT_EQ(1, GetFreedBufferCount());
+}
+
+} // namespace android
diff --git a/libs/hwc2on1adapter/Android.bp b/libs/hwc2on1adapter/Android.bp
index 2be3e67..438d3f5 100644
--- a/libs/hwc2on1adapter/Android.bp
+++ b/libs/hwc2on1adapter/Android.bp
@@ -48,6 +48,9 @@
"-Wno-sign-conversion",
"-Wno-switch-enum",
"-Wno-float-equal",
+ "-Wno-shorten-64-to-32",
+ "-Wno-sign-compare",
+ "-Wno-missing-prototypes",
],
srcs: [
diff --git a/libs/hwc2on1adapter/HWC2On1Adapter.cpp b/libs/hwc2on1adapter/HWC2On1Adapter.cpp
index 5ad05c7..03297ca 100644
--- a/libs/hwc2on1adapter/HWC2On1Adapter.cpp
+++ b/libs/hwc2on1adapter/HWC2On1Adapter.cpp
@@ -245,6 +245,11 @@
return asFP<HWC2_PFN_VALIDATE_DISPLAY>(
displayHook<decltype(&Display::validate),
&Display::validate, uint32_t*, uint32_t*>);
+ case FunctionDescriptor::GetClientTargetSupport:
+ return asFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(
+ displayHook<decltype(&Display::getClientTargetSupport),
+ &Display::getClientTargetSupport, uint32_t, uint32_t,
+ int32_t, int32_t>);
// Layer functions
case FunctionDescriptor::SetCursorPosition:
@@ -1009,6 +1014,22 @@
return Error::None;
}
+Error HWC2On1Adapter::Display::getClientTargetSupport(uint32_t width, uint32_t height,
+ int32_t format, int32_t dataspace){
+ if (mActiveConfig == nullptr) {
+ return Error::Unsupported;
+ }
+
+ if (width == mActiveConfig->getAttribute(Attribute::Width) &&
+ height == mActiveConfig->getAttribute(Attribute::Height) &&
+ format == HAL_PIXEL_FORMAT_RGBA_8888 &&
+ dataspace == HAL_DATASPACE_UNKNOWN) {
+ return Error::None;
+ }
+
+ return Error::Unsupported;
+}
+
static constexpr uint32_t ATTRIBUTES_WITH_COLOR[] = {
HWC_DISPLAY_VSYNC_PERIOD,
HWC_DISPLAY_WIDTH,
diff --git a/libs/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h b/libs/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h
index a1d2c88..3badfce 100644
--- a/libs/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h
+++ b/libs/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h
@@ -248,6 +248,9 @@
HWC2::Error updateLayerZ(hwc2_layer_t layerId, uint32_t z);
+ HWC2::Error getClientTargetSupport(uint32_t width, uint32_t height,
+ int32_t format, int32_t dataspace);
+
// Read configs from HWC1 device
void populateConfigs();
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index ef49995..572cb4e 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -97,8 +97,6 @@
AHARDWAREBUFFER_USAGE0_GPU_SAMPLED_IMAGE = 1ULL << 10,
/* The buffer will be written to by the GPU */
AHARDWAREBUFFER_USAGE0_GPU_COLOR_OUTPUT = 1ULL << 11,
- /* The buffer will be used as a cubemap texture */
- AHARDWAREBUFFER_USAGE0_GPU_CUBEMAP = 1ULL << 13,
/* The buffer will be used as a shader storage or uniform buffer object*/
AHARDWAREBUFFER_USAGE0_GPU_DATA_BUFFER = 1ULL << 14,
/* The buffer must not be used outside of a protected hardware path */
diff --git a/libs/sensor/SensorManager.cpp b/libs/sensor/SensorManager.cpp
index 9309275..d6d3304 100644
--- a/libs/sensor/SensorManager.cpp
+++ b/libs/sensor/SensorManager.cpp
@@ -38,14 +38,15 @@
namespace android {
// ----------------------------------------------------------------------------
-android::Mutex android::SensorManager::sLock;
-std::map<String16, SensorManager*> android::SensorManager::sPackageInstances;
+Mutex SensorManager::sLock;
+std::map<String16, SensorManager*> SensorManager::sPackageInstances;
SensorManager& SensorManager::getInstanceForPackage(const String16& packageName) {
+ waitForSensorService(nullptr);
+
Mutex::Autolock _l(sLock);
SensorManager* sensorManager;
- std::map<String16, SensorManager*>::iterator iterator =
- sPackageInstances.find(packageName);
+ auto iterator = sPackageInstances.find(packageName);
if (iterator != sPackageInstances.end()) {
sensorManager = iterator->second;
@@ -100,6 +101,28 @@
free(mSensorList);
}
+status_t SensorManager::waitForSensorService(sp<ISensorServer> *server) {
+ // try for 300 seconds (60*5(getService() tries for 5 seconds)) before giving up ...
+ sp<ISensorServer> s;
+ const String16 name("sensorservice");
+ for (int i = 0; i < 60; i++) {
+ status_t err = getService(name, &s);
+ switch (err) {
+ case NAME_NOT_FOUND:
+ sleep(1);
+ continue;
+ case NO_ERROR:
+ if (server != nullptr) {
+ *server = s;
+ }
+ return NO_ERROR;
+ default:
+ return err;
+ }
+ }
+ return TIMED_OUT;
+}
+
void SensorManager::sensorManagerDied() {
Mutex::Autolock _l(mLock);
mSensorServer.clear();
@@ -120,19 +143,8 @@
}
}
if (initSensorManager) {
- // try for 300 seconds (60*5(getService() tries for 5 seconds)) before giving up ...
- const String16 name("sensorservice");
- for (int i = 0; i < 60; i++) {
- status_t err = getService(name, &mSensorServer);
- if (err == NAME_NOT_FOUND) {
- sleep(1);
- continue;
- }
- if (err != NO_ERROR) {
- return err;
- }
- break;
- }
+ waitForSensorService(&mSensorServer);
+ LOG_ALWAYS_FATAL_IF(mSensorServer == nullptr, "getService(SensorService) NULL");
class DeathObserver : public IBinder::DeathRecipient {
SensorManager& mSensorManager;
@@ -144,8 +156,6 @@
explicit DeathObserver(SensorManager& mgr) : mSensorManager(mgr) { }
};
- LOG_ALWAYS_FATAL_IF(mSensorServer.get() == NULL, "getService(SensorService) NULL");
-
mDeathObserver = new DeathObserver(*const_cast<SensorManager *>(this));
IInterface::asBinder(mSensorServer)->linkToDeath(mDeathObserver);
diff --git a/libs/sensor/include/sensor/SensorManager.h b/libs/sensor/include/sensor/SensorManager.h
index a3d9741..92c9823 100644
--- a/libs/sensor/include/sensor/SensorManager.h
+++ b/libs/sensor/include/sensor/SensorManager.h
@@ -68,6 +68,7 @@
private:
// DeathRecipient interface
void sensorManagerDied();
+ static status_t waitForSensorService(sp<ISensorServer> *server);
SensorManager(const String16& opPackageName);
status_t assertStateLocked();
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
new file mode 100644
index 0000000..e068469
--- /dev/null
+++ b/libs/vr/libbufferhub/Android.bp
@@ -0,0 +1,59 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+sourceFiles = [
+ "buffer_hub_client.cpp",
+ "buffer_hub_rpc.cpp",
+ "dvr_buffer.cpp",
+ "ion_buffer.cpp",
+]
+
+localIncludeFiles = [
+ "include",
+]
+
+staticLibraries = [
+ "libdvrcommon",
+ "libpdx_default_transport",
+]
+
+sharedLibraries = [
+ "libbase",
+ "libcutils",
+ "libhardware",
+ "liblog",
+ "libui",
+ "libutils",
+]
+
+cc_library {
+ srcs: sourceFiles,
+ cflags: [
+ "-DLOG_TAG=\"libbufferhub\"",
+ "-DTRACE=0"
+ ],
+ export_include_dirs: localIncludeFiles,
+ static_libs: staticLibraries,
+ shared_libs: sharedLibraries,
+ name: "libbufferhub",
+}
+
+cc_test {
+ tags: ["optional"],
+ srcs: ["bufferhub_tests.cpp"],
+ static_libs: ["libbufferhub"] + staticLibraries,
+ shared_libs: sharedLibraries,
+ name: "bufferhub_tests",
+}
+
diff --git a/libs/vr/libbufferhub/Android.mk b/libs/vr/libbufferhub/Android.mk
deleted file mode 100644
index 0877b0b..0000000
--- a/libs/vr/libbufferhub/Android.mk
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-sourceFiles := \
- buffer_hub_client.cpp \
- buffer_hub_rpc.cpp \
- ion_buffer.cpp
-
-includeFiles := \
- $(LOCAL_PATH)/include
-
-staticLibraries := \
- libdvrcommon \
- libpdx_default_transport \
-
-sharedLibraries := \
- libbase \
- libcutils \
- libhardware \
- liblog \
- libui \
- libutils
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(sourceFiles)
-LOCAL_C_INCLUDES := $(includeFiles)
-LOCAL_CFLAGS := -DLOG_TAG=\"libbufferhub\"
-LOCAL_CFLAGS += -DTRACE=0
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(includeFiles)
-LOCAL_STATIC_LIBRARIES := $(staticLibraries)
-LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
-LOCAL_MODULE := libbufferhub
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := optional
-LOCAL_SRC_FILES := bufferhub_tests.cpp
-LOCAL_STATIC_LIBRARIES := libbufferhub $(staticLibraries)
-LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
-LOCAL_MODULE := bufferhub_tests
-include $(BUILD_NATIVE_TEST)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libs/vr/libbufferhub/buffer_hub_client.cpp b/libs/vr/libbufferhub/buffer_hub_client.cpp
index e2413bd..2749fd1 100644
--- a/libs/vr/libbufferhub/buffer_hub_client.cpp
+++ b/libs/vr/libbufferhub/buffer_hub_client.cpp
@@ -51,8 +51,6 @@
int BufferHubBuffer::ImportBuffer() {
ATRACE_NAME("BufferHubBuffer::ImportBuffer");
- if (!IonBuffer::GetGrallocModule())
- return -EIO;
Status<std::vector<NativeBufferHandle<LocalHandle>>> status =
InvokeRemoteMethod<BufferHubRPC::GetBuffers>();
@@ -132,6 +130,13 @@
return ret;
}
+void BufferHubBuffer::GetBlobFds(int* fds, size_t* fds_count,
+ size_t max_fds_count) const {
+ size_t numFds = static_cast<size_t>(native_handle()->numFds);
+ *fds_count = std::min(max_fds_count, numFds);
+ std::copy(native_handle()->data, native_handle()->data + *fds_count, fds);
+}
+
BufferConsumer::BufferConsumer(LocalChannelHandle channel)
: BASE(std::move(channel)) {
const int ret = ImportBuffer();
diff --git a/libs/vr/libbufferhub/dvr_buffer.cpp b/libs/vr/libbufferhub/dvr_buffer.cpp
new file mode 100644
index 0000000..3eb611f
--- /dev/null
+++ b/libs/vr/libbufferhub/dvr_buffer.cpp
@@ -0,0 +1,124 @@
+#include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/dvr_buffer.h>
+#include <ui/GraphicBuffer.h>
+
+using namespace android;
+
+struct DvrWriteBuffer {
+ std::unique_ptr<dvr::BufferProducer> write_buffer_;
+ sp<GraphicBuffer> graphic_buffer_;
+};
+
+struct DvrReadBuffer {
+ std::unique_ptr<dvr::BufferConsumer> read_buffer_;
+ sp<GraphicBuffer> graphic_buffer_;
+};
+
+namespace android {
+namespace dvr {
+
+DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
+ std::unique_ptr<dvr::BufferProducer> buffer_producer) {
+ DvrWriteBuffer* write_buffer = new DvrWriteBuffer;
+ write_buffer->write_buffer_ = std::move(buffer_producer);
+ return write_buffer;
+}
+
+DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
+ std::unique_ptr<dvr::BufferConsumer> buffer_consumer) {
+ DvrReadBuffer* read_buffer = new DvrReadBuffer;
+ read_buffer->read_buffer_ = std::move(buffer_consumer);
+ return read_buffer;
+}
+
+} // namespace dvr
+} // namespace android
+
+namespace {
+
+void InitializeGraphicBuffer(const dvr::BufferHubBuffer* buffer,
+ sp<GraphicBuffer>* graphic_buffer) {
+ *graphic_buffer = sp<GraphicBuffer>(new GraphicBuffer(
+ buffer->width(), buffer->height(), buffer->format(), 1, /* layer count */
+ buffer->usage(), buffer->stride(), buffer->native_handle(),
+ false /* keep ownership */));
+}
+
+} // anonymous namespace
+
+extern "C" {
+
+void dvrWriteBufferDestroy(DvrWriteBuffer* client) { delete client; }
+
+void dvrWriteBufferGetBlobFds(DvrWriteBuffer* client, int* fds,
+ size_t* fds_count, size_t max_fds_count) {
+ client->write_buffer_->GetBlobFds(fds, fds_count, max_fds_count);
+}
+
+int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* client,
+ AHardwareBuffer** hardware_buffer) {
+ if (!client->graphic_buffer_.get()) {
+ InitializeGraphicBuffer(client->write_buffer_.get(),
+ &client->graphic_buffer_);
+ }
+ *hardware_buffer =
+ reinterpret_cast<AHardwareBuffer*>(client->graphic_buffer_.get());
+ return 0;
+}
+
+int dvrWriteBufferPost(DvrWriteBuffer* client, int ready_fence_fd,
+ const void* meta, size_t meta_size_bytes) {
+ pdx::LocalHandle fence(ready_fence_fd);
+ int result = client->write_buffer_->Post(fence, meta, meta_size_bytes);
+ fence.Release();
+ return result;
+}
+
+int dvrWriteBufferGain(DvrWriteBuffer* client, int* release_fence_fd) {
+ pdx::LocalHandle release_fence;
+ int result = client->write_buffer_->Gain(&release_fence);
+ *release_fence_fd = release_fence.Release();
+ return result;
+}
+
+int dvrWriteBufferGainAsync(DvrWriteBuffer* client) {
+ return client->write_buffer_->GainAsync();
+}
+
+void dvrReadBufferGetBlobFds(DvrReadBuffer* client, int* fds, size_t* fds_count,
+ size_t max_fds_count) {
+ client->read_buffer_->GetBlobFds(fds, fds_count, max_fds_count);
+}
+
+int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* client,
+ AHardwareBuffer** hardware_buffer) {
+ if (!client->graphic_buffer_.get()) {
+ InitializeGraphicBuffer(client->read_buffer_.get(),
+ &client->graphic_buffer_);
+ }
+ *hardware_buffer =
+ reinterpret_cast<AHardwareBuffer*>(client->graphic_buffer_.get());
+ return 0;
+}
+
+int dvrReadBufferAcquire(DvrReadBuffer* client, int* ready_fence_fd, void* meta,
+ size_t meta_size_bytes) {
+ pdx::LocalHandle ready_fence;
+ int result =
+ client->read_buffer_->Acquire(&ready_fence, meta, meta_size_bytes);
+ *ready_fence_fd = ready_fence.Release();
+ return result;
+}
+
+int dvrReadBufferRelease(DvrReadBuffer* client, int release_fence_fd) {
+ pdx::LocalHandle fence(release_fence_fd);
+ int result = client->read_buffer_->Release(fence);
+ fence.Release();
+ return result;
+}
+
+int dvrReadBufferReleaseAsync(DvrReadBuffer* client) {
+ return client->read_buffer_->ReleaseAsync();
+}
+
+} // extern "C"
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
index cefde7b..aacc385 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
@@ -70,6 +70,10 @@
return LocalHandle(dup(native_handle()->data[0]));
}
+ // Get up to |max_fds_count| file descriptors for accessing the blob shared
+ // memory. |fds_count| will contain the actual number of file descriptors.
+ void GetBlobFds(int* fds, size_t* fds_count, size_t max_fds_count) const;
+
using Client::event_fd;
Status<int> GetEventMask(int events) {
diff --git a/libs/vr/libbufferhub/include/private/dvr/dvr_buffer.h b/libs/vr/libbufferhub/include/private/dvr/dvr_buffer.h
new file mode 100644
index 0000000..c14b1a3
--- /dev/null
+++ b/libs/vr/libbufferhub/include/private/dvr/dvr_buffer.h
@@ -0,0 +1,55 @@
+#ifndef ANDROID_DVR_BUFFER_H_
+#define ANDROID_DVR_BUFFER_H_
+
+#include <memory>
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct DvrWriteBuffer DvrWriteBuffer;
+typedef struct DvrReadBuffer DvrReadBuffer;
+typedef struct AHardwareBuffer AHardwareBuffer;
+
+// Write buffer
+void dvrWriteBufferDestroy(DvrWriteBuffer* client);
+void dvrWriteBufferGetBlobFds(DvrWriteBuffer* client, int* fds,
+ size_t* fds_count, size_t max_fds_count);
+int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* client,
+ AHardwareBuffer** hardware_buffer);
+int dvrWriteBufferPost(DvrWriteBuffer* client, int ready_fence_fd,
+ const void* meta, size_t meta_size_bytes);
+int dvrWriteBufferGain(DvrWriteBuffer* client, int* release_fence_fd);
+int dvrWriteBufferGainAsync(DvrWriteBuffer* client);
+
+// Read buffer
+void dvrReadBufferGetBlobFds(DvrReadBuffer* client, int* fds, size_t* fds_count,
+ size_t max_fds_count);
+int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* client,
+ AHardwareBuffer** hardware_buffer);
+int dvrReadBufferAcquire(DvrReadBuffer* client, int* ready_fence_fd, void* meta,
+ size_t meta_size_bytes);
+int dvrReadBufferRelease(DvrReadBuffer* client, int release_fence_fd);
+int dvrReadBufferReleaseAsync(DvrReadBuffer* client);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+namespace android {
+namespace dvr {
+
+class BufferProducer;
+class BufferConsumer;
+
+DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
+ std::unique_ptr<BufferProducer> buffer_producer);
+DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
+ std::unique_ptr<BufferConsumer> buffer_consumer);
+
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_DVR_BUFFER_H_
diff --git a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
index 8125c54..e449cbd 100644
--- a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
@@ -2,6 +2,8 @@
#define ANDROID_DVR_ION_BUFFER_H_
#include <hardware/gralloc.h>
+#include <log/log.h>
+#include <ui/GraphicBuffer.h>
namespace android {
namespace dvr {
@@ -58,45 +60,24 @@
int LockYUV(int usage, int x, int y, int width, int height,
struct android_ycbcr* yuv);
int Unlock();
-
- buffer_handle_t handle() const { return handle_; }
- int width() const { return width_; }
- int height() const { return height_; }
- int layer_count() const { return layer_count_; }
- int stride() const { return stride_; }
- int layer_stride() const { return layer_stride_; }
- int format() const { return format_; }
- int usage() const { return usage_; }
-
- static gralloc_module_t const* GetGrallocModule() {
- GrallocInit();
- return gralloc_module_;
- }
-
- static alloc_device_t* GetGrallocDevice() {
- GrallocInit();
- return gralloc_device_;
- }
+ buffer_handle_t handle() const { if (buffer_.get()) return buffer_->handle;
+ else return nullptr; }
+ int width() const { if (buffer_.get()) return buffer_->getWidth();
+ else return 0; }
+ int height() const { if (buffer_.get()) return buffer_->getHeight();
+ else return 0; }
+ int layer_count() const { if (buffer_.get()) return buffer_->getLayerCount();
+ else return 0; }
+ int stride() const { if (buffer_.get()) return buffer_->getStride();
+ else return 0; }
+ int layer_stride() const { return 0; }
+ int format() const { if (buffer_.get()) return buffer_->getPixelFormat();
+ else return 0; }
+ int usage() const { if (buffer_.get()) return buffer_->getUsage();
+ else return 0; }
private:
- buffer_handle_t handle_;
- int width_;
- int height_;
- int layer_count_;
- int stride_;
- int layer_stride_;
- int format_;
- int usage_;
- bool locked_;
- bool needs_unregister_;
-
- void Replace(buffer_handle_t handle, int width, int height, int layer_count,
- int stride, int layer_stride, int format, int usage,
- bool needs_unregister);
-
- static void GrallocInit();
- static gralloc_module_t const* gralloc_module_;
- static alloc_device_t* gralloc_device_;
+ sp<GraphicBuffer> buffer_;
IonBuffer(const IonBuffer&) = delete;
void operator=(const IonBuffer&) = delete;
diff --git a/libs/vr/libbufferhub/ion_buffer.cpp b/libs/vr/libbufferhub/ion_buffer.cpp
index 4db2164..3fb3f3c 100644
--- a/libs/vr/libbufferhub/ion_buffer.cpp
+++ b/libs/vr/libbufferhub/ion_buffer.cpp
@@ -1,4 +1,5 @@
#include <private/dvr/ion_buffer.h>
+#include <ui/GraphicBufferMapper.h>
#include <log/log.h>
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
@@ -9,9 +10,6 @@
namespace android {
namespace dvr {
-gralloc_module_t const* IonBuffer::gralloc_module_ = nullptr;
-alloc_device_t* IonBuffer::gralloc_device_ = nullptr;
-
IonBuffer::IonBuffer() : IonBuffer(nullptr, 0, 0, 0, 0, 0, 0, 0) {}
IonBuffer::IonBuffer(int width, int height, int format, int usage)
@@ -23,33 +21,26 @@
int format, int usage)
: IonBuffer(handle, width, height, 1, stride, 0, format, usage) {}
+
IonBuffer::IonBuffer(buffer_handle_t handle, int width, int height,
int layer_count, int stride, int layer_stride, int format,
int usage)
- : handle_(handle),
- width_(width),
- height_(height),
- layer_count_(layer_count),
- stride_(stride),
- layer_stride_(layer_stride),
- format_(format),
- usage_(usage),
- locked_(false),
- needs_unregister_(false) {
+ : buffer_(nullptr) {
ALOGD_IF(TRACE,
- "IonBuffer::IonBuffer: handle=%p width=%d height=%d layer_count=%d "
- "stride=%d layer stride=%d format=%d usage=%d",
- handle_, width_, height_, layer_count_, stride_, layer_stride_,
- format_, usage_);
- GrallocInit();
+ "IonBuffer::IonBuffer: handle=%p width=%d height=%d layer_count=%d "
+ "stride=%d layer stride=%d format=%d usage=%d",
+ handle, width, height, layer_count, stride, layer_stride,
+ format, usage);
+ if (handle != 0) {
+ Import(handle, width, height, stride, format, usage);
+ }
}
IonBuffer::~IonBuffer() {
ALOGD_IF(TRACE,
"IonBuffer::~IonBuffer: handle=%p width=%d height=%d stride=%d "
"format=%d usage=%d",
- handle_, width_, height_, stride_, format_, usage_);
-
+ handle() , width(), height(), stride(), format(), usage());
FreeHandle();
}
@@ -58,111 +49,42 @@
}
IonBuffer& IonBuffer::operator=(IonBuffer&& other) {
- ALOGD_IF(TRACE, "IonBuffer::operator=: handle_=%p other.handle_=%p", handle_,
- other.handle_);
+ ALOGD_IF(TRACE, "IonBuffer::operator=: handle_=%p other.handle_=%p", handle(),
+ other.handle());
if (this != &other) {
- Replace(other.handle_, other.width_, other.height_, other.layer_count_,
- other.stride_, other.layer_stride_, other.format_, other.usage_,
- other.needs_unregister_);
- locked_ = other.locked_;
- other.handle_ = nullptr;
+ buffer_ = other.buffer_;
other.FreeHandle();
}
-
return *this;
}
void IonBuffer::FreeHandle() {
- if (handle_) {
- // Lock/Unlock don't need to be balanced, but one Unlock is needed to
- // clean/unmap the buffer. Warn if this didn't happen before freeing the
- // native handle.
- ALOGW_IF(locked_,
- "IonBuffer::FreeHandle: freeing a locked handle!!! handle=%p",
- handle_);
-
- if (needs_unregister_) {
- int ret = gralloc_module_->unregisterBuffer(gralloc_module_, handle_);
- ALOGE_IF(ret < 0,
- "IonBuffer::FreeHandle: Failed to unregister handle: %s",
- strerror(-ret));
-
- native_handle_close(const_cast<native_handle_t*>(handle_));
- native_handle_delete(const_cast<native_handle_t*>(handle_));
- } else {
- int ret = gralloc_device_->free(gralloc_device_, handle_);
- if (ret < 0) {
- ALOGE("IonBuffer::FreeHandle: failed to free buffer: %s",
- strerror(-ret));
-
- // Not sure if this is the right thing to do. Attempting to prevent a
- // memory leak of the native handle.
- native_handle_close(const_cast<native_handle_t*>(handle_));
- native_handle_delete(const_cast<native_handle_t*>(handle_));
- }
- }
+ if (buffer_.get()) {
+ // GraphicBuffer unregisters and cleans up the handle if needed
+ buffer_ = nullptr;
}
-
- // Always re-initialize these members, even if handle_ was nullptr, in case
- // someone was dumb enough to pass a nullptr handle to the constructor or
- // Reset.
- handle_ = nullptr;
- width_ = 0;
- height_ = 0;
- layer_count_ = 0;
- stride_ = 0;
- layer_stride_ = 0;
- format_ = 0;
- usage_ = 0;
- locked_ = false;
- needs_unregister_ = false;
}
int IonBuffer::Alloc(int width, int height, int format, int usage) {
- ATRACE_NAME("IonBuffer::Alloc");
ALOGD_IF(TRACE, "IonBuffer::Alloc: width=%d height=%d format=%d usage=%d",
width, height, format, usage);
- int stride;
- buffer_handle_t handle;
-
- int ret = gralloc_device_->alloc(gralloc_device_, width, height, format,
- usage, &handle, &stride);
- if (ret < 0) {
- ALOGE("IonBuffer::Alloc: failed to allocate gralloc buffer: %s",
- strerror(-ret));
- return ret;
+ GraphicBufferMapper& mapper = GraphicBufferMapper::get();
+ buffer_ = new GraphicBuffer(width, height, format, usage);
+ if (mapper.registerBuffer(buffer_.get()) != OK) {
+ ALOGE("IonBuffer::Aloc: Failed to register buffer");
}
-
- Replace(handle, width, height, 1, stride, 0, format, usage, false);
return 0;
}
-void IonBuffer::Replace(buffer_handle_t handle, int width, int height,
- int layer_count, int stride, int layer_stride,
- int format, int usage, bool needs_unregister) {
- FreeHandle();
-
- handle_ = handle;
- width_ = width;
- height_ = height;
- layer_count_ = layer_count;
- stride_ = stride;
- layer_stride_ = layer_stride;
- format_ = format;
- usage_ = usage;
- needs_unregister_ = needs_unregister;
-}
-
void IonBuffer::Reset(buffer_handle_t handle, int width, int height, int stride,
int format, int usage) {
ALOGD_IF(TRACE,
"IonBuffer::Reset: handle=%p width=%d height=%d stride=%d format=%d "
"usage=%d",
handle, width, height, stride, format, usage);
-
- Replace(handle, width, height, 1, stride, 0, format, usage, false);
+ Import(handle, width, height, stride, format, usage);
}
int IonBuffer::Import(buffer_handle_t handle, int width, int height, int stride,
@@ -173,14 +95,14 @@
"IonBuffer::Import: handle=%p width=%d height=%d stride=%d format=%d "
"usage=%d",
handle, width, height, stride, format, usage);
-
- int ret = gralloc_module_->registerBuffer(gralloc_module_, handle);
- if (ret < 0) {
- ALOGE("IonBuffer::Import: failed to import handle: %s", strerror(-ret));
- return ret;
+ FreeHandle();
+ GraphicBufferMapper& mapper = GraphicBufferMapper::get();
+ buffer_ = new GraphicBuffer(width, height, format, 1, usage,
+ stride, (native_handle_t*)handle, true);
+ if (mapper.registerBuffer(buffer_.get()) != OK) {
+ ALOGE("IonBuffer::Import: Failed to register cloned buffer");
+ return -EINVAL;
}
-
- Replace(handle, width, height, 1, stride, 0, format, usage, true);
return 0;
}
@@ -262,15 +184,14 @@
ALOGD_IF(TRACE,
"IonBuffer::Lock: handle=%p usage=%d x=%d y=%d width=%d height=%d "
"address=%p",
- handle_, usage, x, y, width, height, address);
+ handle(), usage, x, y, width, height, address);
- // Lock may be called multiple times; but only one Unlock is required.
- const int err = gralloc_module_->lock(gralloc_module_, handle_, usage, x, y,
- width, height, address);
- if (!err)
- locked_ = true;
-
- return err;
+ status_t err = buffer_->lock(usage, Rect(x, y, x + width, y + height),
+ address);
+ if (err != NO_ERROR)
+ return -EINVAL;
+ else
+ return 0;
}
int IonBuffer::LockYUV(int usage, int x, int y, int width, int height,
@@ -278,45 +199,25 @@
ATRACE_NAME("IonBuffer::LockYUV");
ALOGD_IF(TRACE,
"IonBuffer::Lock: handle=%p usage=%d x=%d y=%d width=%d height=%d",
- handle_, usage, x, y, width, height);
- const int err = gralloc_module_->lock_ycbcr(gralloc_module_, handle_, usage,
- x, y, width, height, yuv);
- if (!err)
- locked_ = true;
+ handle(), usage, x, y, width, height);
- return err;
+ status_t err = buffer_->lockYCbCr(usage, Rect(x, y, x + width, y + height),
+ yuv);
+ if (err != NO_ERROR)
+ return -EINVAL;
+ else
+ return 0;
}
int IonBuffer::Unlock() {
ATRACE_NAME("IonBuffer::Unlock");
- ALOGD_IF(TRACE, "IonBuffer::Unlock: handle=%p", handle_);
+ ALOGD_IF(TRACE, "IonBuffer::Unlock: handle=%p", handle());
- // Lock may be called multiple times; but only one Unlock is required.
- const int err = gralloc_module_->unlock(gralloc_module_, handle_);
- if (!err)
- locked_ = false;
-
- return err;
+ status_t err = buffer_->unlock();
+ if (err != NO_ERROR)
+ return -EINVAL;
+ else
+ return 0;
}
-
-void IonBuffer::GrallocInit() {
- static std::once_flag gralloc_flag;
- std::call_once(gralloc_flag, []() {
- hw_module_t const* module = nullptr;
- alloc_device_t* device = nullptr;
-
- int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
- ALOGE_IF(err, "IonBuffer::GrallocInit: failed to find the %s module: %s",
- GRALLOC_HARDWARE_MODULE_ID, strerror(-err));
-
- err = gralloc_open(module, &device);
- ALOGE_IF(err, "IonBuffer::GrallocInit: failed to open gralloc device: %s",
- strerror(-err));
-
- gralloc_module_ = reinterpret_cast<gralloc_module_t const*>(module);
- gralloc_device_ = device;
- });
-}
-
-} // namespace dvr
-} // namespace android
+} // namespace dvr
+} // namespace android
diff --git a/libs/vr/libbufferhub/tests/Android.mk b/libs/vr/libbufferhub/tests/Android.mk
deleted file mode 100644
index 5053e7d..0000000
--- a/libs/vr/libbufferhub/tests/Android.mk
+++ /dev/null
@@ -1 +0,0 @@
-include $(call all-subdir-makefiles)
diff --git a/libs/vr/libbufferhub/tests/ion_buffer/Android.mk b/libs/vr/libbufferhub/tests/ion_buffer/Android.mk
deleted file mode 100644
index 3bfdb7b..0000000
--- a/libs/vr/libbufferhub/tests/ion_buffer/Android.mk
+++ /dev/null
@@ -1,74 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-COMPONENT_TOP := ${LOCAL_PATH}/../..
-
-LOCAL_SRC_FILES := \
- ion_buffer-test.cpp \
- ../../ion_buffer.cpp \
- ../../mocks/gralloc/gralloc.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libc \
- libcutils \
- libutils \
- liblog
-
-LOCAL_STATIC_LIBRARIES := \
- libgmock
-
-LOCAL_C_INCLUDES := \
- ${COMPONENT_TOP}/mocks/gralloc \
- ${COMPONENT_TOP}/include \
- $(TOP)/system/core/base/include
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := ${LOCAL_C_INCLUDES}
-
-LOCAL_NATIVE_COVERAGE := true
-
-LOCAL_CFLAGS := -DTRACE=0 -g
-
-LOCAL_MODULE := ion_buffer-test
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_NATIVE_TEST)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- ion_buffer-test.cpp \
- ../../ion_buffer.cpp \
- ../../mocks/gralloc/gralloc.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- liblog
-
-LOCAL_STATIC_LIBRARIES := \
- libgmock_host
-
-LOCAL_C_INCLUDES := \
- ${COMPONENT_TOP}/mocks/gralloc \
- ${COMPONENT_TOP}/include \
- $(TOP)/system/core/base/include
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := ${LOCAL_C_INCLUDES}
-
-LOCAL_NATIVE_COVERAGE := true
-
-LOCAL_CFLAGS := -DTRACE=0
-
-LOCAL_MODULE := ion_buffer-host_test
-LOCAL_MODULE_TAGS := tests
-include $(BUILD_HOST_NATIVE_TEST)
-
-.PHONY: dvr_host_native_unit_tests
-dvr_host_native_unit_tests: ion_buffer-host_test
-ifeq (true,$(NATIVE_COVERAGE))
- ion_buffer-host_test: llvm-cov
- ion_buffer-test: llvm-cov
- # This shouldn't be necessary, but the default build with
- # NATIVE_COVERAGE=true manages to ion_buffer-test without
- # building llvm-cov (droid is the default target).
- droid: llvm-cov
-endif
diff --git a/libs/vr/libbufferhub/tests/ion_buffer/ion_buffer-test.cpp b/libs/vr/libbufferhub/tests/ion_buffer/ion_buffer-test.cpp
deleted file mode 100644
index 68f82d7..0000000
--- a/libs/vr/libbufferhub/tests/ion_buffer/ion_buffer-test.cpp
+++ /dev/null
@@ -1,375 +0,0 @@
-#include <gmock/gmock.h>
-#include <gralloc_mock.h>
-#include <gtest/gtest.h>
-#include <private/dvr/ion_buffer.h>
-
-using ::testing::_;
-using ::testing::Invoke;
-using ::testing::Return;
-using ::testing::SetArgPointee;
-using android::dvr::IonBuffer;
-
-GrallocMock* GrallocMock::staticObject = nullptr;
-
-namespace {
-
-const int w1 = 100;
-const int h1 = 200;
-const int d1 = 2;
-const int f1 = 1;
-const int u1 = 3;
-const int stride1 = 8;
-const int layer_stride1 = 8;
-native_handle_t handle1;
-const int w2 = 150;
-const int h2 = 300;
-const int d2 = 4;
-const int f2 = 2;
-const int u2 = 5;
-const int stride2 = 4;
-const int layer_stride2 = 4;
-native_handle_t handle2;
-const int kMaxFd = 10;
-const int kMaxInt = 10;
-char handleData[sizeof(native_handle_t) + (kMaxFd + kMaxInt) * sizeof(int)];
-native_handle_t* const dataHandle =
- reinterpret_cast<native_handle_t*>(handleData);
-char refData[sizeof(native_handle_t) + (kMaxFd + kMaxInt) * sizeof(int)];
-native_handle_t* const refHandle = reinterpret_cast<native_handle_t*>(refData);
-
-class IonBufferUnitTest : public ::testing::Test {
- protected:
- // You can remove any or all of the following functions if its body
- // is empty.
-
- IonBufferUnitTest() {
- GrallocMock::staticObject = new GrallocMock;
- // You can do set-up work for each test here.
- // most ServicefsClients will use this initializer. Use as the
- // default.
- }
-
- virtual ~IonBufferUnitTest() {
- delete GrallocMock::staticObject;
- GrallocMock::staticObject = nullptr;
- // You can do clean-up work that doesn't throw exceptions here.
- }
-
- // If the constructor and destructor are not enough for setting up
- // and cleaning up each test, you can define the following methods:
-
- void SetUp() override {
- // Code here will be called immediately after the constructor (right
- // before each test).
- }
-
- void TearDown() override {
- // Code here will be called immediately after each test (right
- // before the destructor).
- }
-};
-
-void TestIonBufferState(const IonBuffer& buffer, int w, int h, int d, int f,
- int u, native_handle_t* handle, int stride,
- int layer_stride) {
- EXPECT_EQ(buffer.width(), w);
- EXPECT_EQ(buffer.height(), h);
- EXPECT_EQ(buffer.layer_count(), d);
- EXPECT_EQ(buffer.format(), f);
- EXPECT_EQ(buffer.usage(), u);
- EXPECT_EQ(buffer.handle(), handle);
- EXPECT_EQ(buffer.stride(), stride);
- EXPECT_EQ(buffer.layer_stride(), layer_stride);
-}
-
-TEST_F(IonBufferUnitTest, TestFreeOnDestruction) {
- // Set up |alloc|(|w1...|) to succeed once and fail on others calls.
- EXPECT_CALL(*GrallocMock::staticObject, alloc(w1, h1, f1, u1, _, _))
- .Times(1)
- .WillOnce(DoAll(SetArgPointee<4>(&handle1), SetArgPointee<5>(stride1),
- Return(0)));
- // Set up |free| to be called once.
- EXPECT_CALL(*GrallocMock::staticObject, free(&handle1))
- .Times(1)
- .WillRepeatedly(Return(0));
-
- IonBuffer buffer;
- // First call to |alloc| with |w1...| set up to succeed.
- int ret = buffer.Alloc(w1, h1, f1, u1);
- EXPECT_EQ(ret, 0);
- TestIonBufferState(buffer, w1, h1, 1, f1, u1, &handle1, stride1, 0);
-
- // Scoped destructor will be called, calling |free| on |handle1|.
-}
-
-TEST_F(IonBufferUnitTest, TestAlloc) {
- IonBuffer buffer;
- // Set up |alloc|(|w1...|) to succeed once and fail on others calls.
- EXPECT_CALL(*GrallocMock::staticObject, alloc(w1, h1, f1, u1, _, _))
- .Times(2)
- .WillOnce(DoAll(SetArgPointee<4>(&handle1), SetArgPointee<5>(stride1),
- Return(0)))
- .WillRepeatedly(Return(-1));
-
- // Set up |alloc|(|w2...|) to succeed once and fail on others calls.
- EXPECT_CALL(*GrallocMock::staticObject, alloc(w2, h2, f2, u2, _, _))
- .Times(2)
- .WillOnce(DoAll(SetArgPointee<4>(&handle2), SetArgPointee<5>(stride2),
- Return(0)))
- .WillRepeatedly(Return(-1));
- EXPECT_CALL(*GrallocMock::staticObject, free(&handle1))
- .Times(1)
- .WillRepeatedly(Return(0));
- EXPECT_CALL(*GrallocMock::staticObject, free(&handle2))
- .Times(1)
- .WillRepeatedly(Return(0));
-
- // First call to |alloc| with |w1...| set up to succeed.
- int ret = buffer.Alloc(w1, h1, f1, u1);
- EXPECT_EQ(ret, 0);
- TestIonBufferState(buffer, w1, h1, 1, f1, u1, &handle1, stride1, 0);
-
- // First call to |alloc| with |w2...| set up to succeed, |free| should be
- // called once on |handle1|.
- ret = buffer.Alloc(w2, h2, f2, u2);
- EXPECT_EQ(ret, 0);
- TestIonBufferState(buffer, w2, h2, 1, f2, u2, &handle2, stride2, 0);
-
- // Second call to |alloc| with |w1| is set up to fail.
- ret = buffer.Alloc(w1, h1, f1, u1);
- EXPECT_LT(ret, 0);
- TestIonBufferState(buffer, w2, h2, 1, f2, u2, &handle2, stride2, 0);
-
- // |free| on |handle2| should be called here.
- buffer.FreeHandle();
- TestIonBufferState(buffer, 0, 0, 0, 0, 0, nullptr, 0, 0);
-
- // |alloc| is set up to fail.
- ret = buffer.Alloc(w2, h2, f2, u2);
- EXPECT_LT(ret, 0);
- TestIonBufferState(buffer, 0, 0, 0, 0, 0, nullptr, 0, 0);
-}
-
-TEST_F(IonBufferUnitTest, TestReset) {
- IonBuffer buffer;
- EXPECT_CALL(*GrallocMock::staticObject, free(&handle1))
- .Times(1)
- .WillRepeatedly(Return(0));
- EXPECT_CALL(*GrallocMock::staticObject, free(&handle2))
- .Times(1)
- .WillRepeatedly(Return(0));
- buffer.Reset(&handle1, w1, h1, stride1, f1, u1);
- TestIonBufferState(buffer, w1, h1, 1, f1, u1, &handle1, stride1, 0);
- buffer.Reset(&handle2, w2, h2, stride2, f2, u2);
- TestIonBufferState(buffer, w2, h2, 1, f2, u2, &handle2, stride2, 0);
- buffer.FreeHandle();
-}
-
-TEST_F(IonBufferUnitTest, TestImport1) {
- IonBuffer buffer;
- EXPECT_CALL(*GrallocMock::staticObject, registerBuffer(&handle1))
- .Times(3)
- .WillOnce(Return(0))
- .WillRepeatedly(Return(-1));
- EXPECT_CALL(*GrallocMock::staticObject, registerBuffer(&handle2))
- .Times(3)
- .WillOnce(Return(0))
- .WillOnce(Return(-1))
- .WillOnce(Return(0));
- EXPECT_CALL(*GrallocMock::staticObject, unregisterBuffer(&handle1))
- .Times(1)
- .WillOnce(Return(0));
- EXPECT_CALL(*GrallocMock::staticObject, native_handle_close(&handle1))
- .Times(1);
- EXPECT_CALL(*GrallocMock::staticObject, native_handle_delete(&handle1))
- .Times(1);
- EXPECT_CALL(*GrallocMock::staticObject, alloc(w1, h1, f1, u1, _, _))
- .Times(1)
- .WillRepeatedly(DoAll(SetArgPointee<4>(&handle1),
- SetArgPointee<5>(stride1), Return(0)));
- EXPECT_CALL(*GrallocMock::staticObject, unregisterBuffer(&handle2))
- .Times(2)
- .WillRepeatedly(Return(0));
- EXPECT_CALL(*GrallocMock::staticObject, native_handle_close(&handle2))
- .Times(2);
- EXPECT_CALL(*GrallocMock::staticObject, native_handle_delete(&handle2))
- .Times(2);
- EXPECT_CALL(*GrallocMock::staticObject, free(&handle1))
- .Times(1)
- .WillRepeatedly(Return(0));
-
- int ret = buffer.Import(&handle1, w1, h1, stride1, f1, u1);
- EXPECT_EQ(ret, 0);
- TestIonBufferState(buffer, w1, h1, 1, f1, u1, &handle1, stride1, 0);
- ret = buffer.Import(&handle2, w2, h2, stride2, f2, u2);
- EXPECT_EQ(ret, 0);
- TestIonBufferState(buffer, w2, h2, 1, f2, u2, &handle2, stride2, 0);
- ret = buffer.Alloc(w1, h1, f1, u1);
- EXPECT_EQ(ret, 0);
- ret = buffer.Import(&handle2, w2, h2, stride2, f2, u2);
- EXPECT_LT(ret, 0);
- TestIonBufferState(buffer, w1, h1, 1, f1, u1, &handle1, stride1, 0);
- ret = buffer.Import(&handle2, w2, h2, stride2, f2, u2);
- EXPECT_EQ(ret, 0);
- TestIonBufferState(buffer, w2, h2, 1, f2, u2, &handle2, stride2, 0);
- ret = buffer.Import(&handle1, w1, h1, stride1, f1, u1);
- EXPECT_LT(ret, 0);
- TestIonBufferState(buffer, w2, h2, 1, f2, u2, &handle2, stride2, 0);
- buffer.FreeHandle();
- ret = buffer.Import(&handle1, w1, h1, stride1, f1, u1);
- EXPECT_LT(ret, 0);
- TestIonBufferState(buffer, 0, 0, 0, 0, 0, nullptr, 0, 0);
-}
-
-native_handle_t* native_handle_create_impl(int nFds, int nInts) {
- if ((nFds + nInts) > (kMaxFd + kMaxInt))
- return nullptr;
- dataHandle->version = sizeof(native_handle_t);
- dataHandle->numFds = nFds;
- dataHandle->numInts = nInts;
- for (int i = 0; i < nFds + nInts; i++)
- dataHandle->data[i] = 0;
- return dataHandle;
-}
-
-TEST_F(IonBufferUnitTest, TestImport2) {
- IonBuffer buffer;
- int ints[] = {211, 313, 444};
- int fds[] = {-1, -1};
- int ni = sizeof(ints) / sizeof(ints[0]);
- int nfd = sizeof(fds) / sizeof(fds[0]);
- EXPECT_CALL(*GrallocMock::staticObject, native_handle_create(nfd, ni))
- .Times(3)
- .WillOnce(Return(nullptr))
- .WillRepeatedly(Invoke(native_handle_create_impl));
- EXPECT_CALL(*GrallocMock::staticObject, registerBuffer(dataHandle))
- .Times(2)
- .WillOnce(Return(-1))
- .WillRepeatedly(Return(0));
- EXPECT_CALL(*GrallocMock::staticObject, native_handle_close(dataHandle))
- .Times(2);
- EXPECT_CALL(*GrallocMock::staticObject, native_handle_delete(dataHandle))
- .Times(2);
- EXPECT_CALL(*GrallocMock::staticObject, unregisterBuffer(dataHandle))
- .Times(1)
- .WillRepeatedly(Return(0));
-
- int ret = buffer.Import(fds, -1, ints, ni, w1, h1, stride1, f1, u1);
- EXPECT_LT(ret, 0);
- ret = buffer.Import(fds, nfd, ints, -1, w1, h1, stride1, f1, u1);
- EXPECT_LT(ret, 0);
- ret = buffer.Import(fds, nfd, ints, ni, w1, h1, stride1, f1, u1);
- EXPECT_LT(ret, 0);
- ret = buffer.Import(fds, nfd, ints, ni, w1, h1, stride1, f1, u1);
- EXPECT_LT(ret, 0);
- ret = buffer.Import(fds, nfd, ints, ni, w1, h1, stride1, f1, u1);
- EXPECT_EQ(ret, 0);
- TestIonBufferState(buffer, w1, h1, 1, f1, u1, dataHandle, stride1, 0);
- EXPECT_EQ(dataHandle->numFds, nfd);
- EXPECT_EQ(dataHandle->numInts, ni);
- for (int i = 0; i < nfd; i++)
- EXPECT_EQ(dataHandle->data[i], fds[i]);
- for (int i = 0; i < ni; i++)
- EXPECT_EQ(dataHandle->data[nfd + i], ints[i]);
- buffer.FreeHandle();
-}
-
-TEST_F(IonBufferUnitTest, TestDuplicate) {
- IonBuffer buffer;
- IonBuffer ref;
- int ints[] = {211, 313, 444};
- int fds[] = {-1, -1};
- int ni = sizeof(ints) / sizeof(ints[0]);
- int nfd = sizeof(fds) / sizeof(fds[0]);
-
- for (int i = 0; i < nfd; i++) {
- refHandle->data[i] = fds[i];
- }
- for (int i = 0; i < ni; i++) {
- refHandle->data[i + nfd] = ints[i];
- }
-
- EXPECT_CALL(*GrallocMock::staticObject, alloc(w1, h1, f1, u1, _, _))
- .Times(1)
- .WillRepeatedly(DoAll(SetArgPointee<4>(refHandle),
- SetArgPointee<5>(stride1), Return(0)));
- EXPECT_CALL(*GrallocMock::staticObject, native_handle_create(nfd, ni))
- .Times(3)
- .WillOnce(Return(nullptr))
- .WillRepeatedly(Invoke(native_handle_create_impl));
- EXPECT_CALL(*GrallocMock::staticObject, registerBuffer(dataHandle))
- .Times(2)
- .WillOnce(Return(-1))
- .WillRepeatedly(Return(0));
- EXPECT_CALL(*GrallocMock::staticObject, native_handle_close(dataHandle))
- .Times(2);
- EXPECT_CALL(*GrallocMock::staticObject, native_handle_delete(dataHandle))
- .Times(2);
- EXPECT_CALL(*GrallocMock::staticObject, unregisterBuffer(dataHandle))
- .Times(1)
- .WillRepeatedly(Return(0));
- EXPECT_CALL(*GrallocMock::staticObject, free(refHandle))
- .Times(1)
- .WillRepeatedly(Return(0));
-
- int ret = buffer.Duplicate(&ref);
- EXPECT_LT(ret, 0);
- ret = ref.Alloc(w1, h1, f1, u1);
- EXPECT_EQ(ret, 0);
- refHandle->numFds = -1;
- refHandle->numInts = 0;
- ret = buffer.Duplicate(&ref);
- EXPECT_LT(ret, 0);
- refHandle->numFds = nfd;
- refHandle->numInts = ni;
- ret = buffer.Duplicate(&ref);
- EXPECT_LT(ret, 0);
- ret = buffer.Duplicate(&ref);
- EXPECT_LT(ret, 0);
- ret = buffer.Duplicate(&ref);
- EXPECT_EQ(ret, 0);
- TestIonBufferState(buffer, w1, h1, 1, f1, u1, dataHandle, stride1, 0);
- EXPECT_EQ(dataHandle->numFds, nfd);
- EXPECT_EQ(dataHandle->numInts, ni);
- for (int i = 0; i < nfd; i++)
- EXPECT_LT(dataHandle->data[i], 0);
- for (int i = 0; i < ni; i++)
- EXPECT_EQ(dataHandle->data[nfd + i], ints[i]);
- buffer.FreeHandle();
- ref.FreeHandle();
-}
-
-TEST_F(IonBufferUnitTest, TestLockUnlock) {
- IonBuffer buffer;
- const int x = 12;
- const int y = 24;
- const int value1 = 17;
- const int value2 = 25;
- void* addr1;
- void** addr = &addr1;
-
- EXPECT_CALL(*GrallocMock::staticObject, alloc(w1, h1, f1, u1, _, _))
- .Times(1)
- .WillRepeatedly(DoAll(SetArgPointee<4>(&handle1),
- SetArgPointee<5>(stride1), Return(0)));
- EXPECT_CALL(*GrallocMock::staticObject,
- lock(&handle1, u2, x, y, w2, h2, addr))
- .Times(1)
- .WillRepeatedly(Return(value1));
- EXPECT_CALL(*GrallocMock::staticObject, unlock(&handle1))
- .Times(1)
- .WillRepeatedly(Return(value2));
- EXPECT_CALL(*GrallocMock::staticObject, free(&handle1))
- .Times(1)
- .WillRepeatedly(Return(0));
-
- int ret = buffer.Alloc(w1, h1, f1, u1);
- EXPECT_EQ(ret, 0);
- ret = buffer.Lock(u2, x, y, w2, h2, addr);
- EXPECT_EQ(ret, value1);
- ret = buffer.Unlock();
- EXPECT_EQ(ret, value2);
- buffer.FreeHandle();
-}
-
-} // namespace
diff --git a/libs/vr/libbufferhubqueue/Android.bp b/libs/vr/libbufferhubqueue/Android.bp
new file mode 100644
index 0000000..1c8f2c0
--- /dev/null
+++ b/libs/vr/libbufferhubqueue/Android.bp
@@ -0,0 +1,56 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+sourceFiles = [
+ "buffer_hub_queue_client.cpp",
+ "buffer_hub_queue_core.cpp",
+ "buffer_hub_queue_consumer.cpp",
+ "buffer_hub_queue_producer.cpp",
+]
+
+includeFiles = [
+ "include",
+]
+
+staticLibraries = [
+ "libbufferhub",
+ "libdvrcommon",
+ "libpdx_default_transport",
+]
+
+sharedLibraries = [
+ "libbase",
+ "libbinder",
+ "libcutils",
+ "libhardware",
+ "liblog",
+ "libui",
+ "libutils",
+ "libgui",
+]
+
+cc_library {
+ name: "libbufferhubqueue",
+ cflags = [
+ "-DLOGTAG=\"libbufferhubqueue\"",
+ "-DTRACE=0",
+ ],
+ srcs: sourceFiles,
+ export_include_dirs: includeFiles,
+ export_static_lib_headers: staticLibraries,
+ static_libs: staticLibraries,
+ shared_libs: sharedLibraries,
+}
+
+subdirs = ["tests"]
diff --git a/libs/vr/libbufferhubqueue/Android.mk b/libs/vr/libbufferhubqueue/Android.mk
deleted file mode 100644
index d53f06a..0000000
--- a/libs/vr/libbufferhubqueue/Android.mk
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-sourceFiles := \
- buffer_hub_queue_client.cpp \
- buffer_hub_queue_core.cpp \
- buffer_hub_queue_consumer.cpp \
- buffer_hub_queue_producer.cpp \
-
-includeFiles := \
- $(LOCAL_PATH)/include
-
-staticLibraries := \
- libbufferhub \
- libdvrcommon \
- libpdx_default_transport \
-
-sharedLibraries := \
- libbase \
- libbinder \
- libcutils \
- libhardware \
- liblog \
- libui \
- libutils \
- libgui \
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(sourceFiles)
-LOCAL_C_INCLUDES := $(includeFiles)
-LOCAL_CFLAGS := -DLOG_TAG=\"libbufferhubqueue\"
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(includeFiles)
-LOCAL_STATIC_LIBRARIES := $(staticLibraries)
-LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
-LOCAL_MODULE := libbufferhubqueue
-include $(BUILD_STATIC_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index bad9503..bd6511d 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -1,7 +1,5 @@
#include "include/private/dvr/buffer_hub_queue_client.h"
-//#define LOG_NDEBUG 0
-
#include <inttypes.h>
#include <log/log.h>
#include <sys/epoll.h>
@@ -13,9 +11,6 @@
#include <pdx/file_handle.h>
#include <private/dvr/bufferhub_rpc.h>
-using android::pdx::LocalHandle;
-using android::pdx::LocalChannelHandle;
-
namespace android {
namespace dvr {
@@ -28,6 +23,7 @@
buffers_(BufferHubQueue::kMaxQueueCapacity),
epollhup_pending_(BufferHubQueue::kMaxQueueCapacity, false),
available_buffers_(BufferHubQueue::kMaxQueueCapacity),
+ fences_(BufferHubQueue::kMaxQueueCapacity),
capacity_(0) {
Initialize();
}
@@ -41,6 +37,7 @@
buffers_(BufferHubQueue::kMaxQueueCapacity),
epollhup_pending_(BufferHubQueue::kMaxQueueCapacity, false),
available_buffers_(BufferHubQueue::kMaxQueueCapacity),
+ fences_(BufferHubQueue::kMaxQueueCapacity),
capacity_(0) {
Initialize();
}
@@ -74,7 +71,8 @@
auto return_value = status.take();
- ALOGD("CreateConsumerQueue: meta_size_bytes=%zu", return_value.second);
+ ALOGD_IF(TRACE, "BufferHubQueue::CreateConsumerQueue: meta_size_bytes=%zu",
+ return_value.second);
return ConsumerQueue::Create(std::move(return_value.first),
return_value.second);
}
@@ -86,7 +84,7 @@
int ret = epoll_fd_.Wait(events.data(), events.size(), timeout);
if (ret == 0) {
- ALOGD("Wait on epoll returns nothing before timeout.");
+ ALOGD_IF(TRACE, "Wait on epoll returns nothing before timeout.");
return false;
}
@@ -103,7 +101,7 @@
for (int i = 0; i < num_events; i++) {
int64_t index = static_cast<int64_t>(events[i].data.u64);
- ALOGD("New BufferHubQueue event %d: index=%" PRId64, i, index);
+ ALOGD_IF(TRACE, "New BufferHubQueue event %d: index=%" PRId64, i, index);
if (is_buffer_event_index(index)) {
HandleBufferEvent(static_cast<size_t>(index), events[i]);
@@ -134,7 +132,7 @@
int events = status.get();
if (events & EPOLLIN) {
- int ret = OnBufferReady(buffer);
+ int ret = OnBufferReady(buffer, &fences_[slot]);
if (ret < 0) {
ALOGE("Failed to set buffer ready: %s", strerror(-ret));
return;
@@ -254,8 +252,9 @@
std::shared_ptr<BufferHubBuffer> BufferHubQueue::Dequeue(int timeout,
size_t* slot,
- void* meta) {
- ALOGD("Dequeue: count=%zu, timeout=%d", count(), timeout);
+ void* meta,
+ LocalHandle* fence) {
+ ALOGD_IF(TRACE, "Dequeue: count=%zu, timeout=%d", count(), timeout);
if (count() == 0 && !WaitForBuffers(timeout))
return nullptr;
@@ -263,6 +262,8 @@
std::shared_ptr<BufferHubBuffer> buf;
BufferInfo& buffer_info = available_buffers_.Front();
+ *fence = std::move(fences_[buffer_info.slot]);
+
// Report current pos as the output slot.
std::swap(buffer_info.slot, *slot);
// Swap buffer from vector to be returned later.
@@ -339,8 +340,9 @@
// We only allocate one buffer at a time.
auto& buffer_handle = buffer_handle_slots[0].first;
size_t buffer_slot = buffer_handle_slots[0].second;
- ALOGD("ProducerQueue::AllocateBuffer, new buffer, channel_handle: %d",
- buffer_handle.value());
+ ALOGD_IF(TRACE,
+ "ProducerQueue::AllocateBuffer, new buffer, channel_handle: %d",
+ buffer_handle.value());
*out_slot = buffer_slot;
return AddBuffer(BufferProducer::Import(std::move(buffer_handle)),
@@ -373,15 +375,21 @@
return BufferHubQueue::DetachBuffer(slot);
}
-std::shared_ptr<BufferProducer> ProducerQueue::Dequeue(int timeout,
- size_t* slot) {
- auto buf = BufferHubQueue::Dequeue(timeout, slot, nullptr);
+std::shared_ptr<BufferProducer> ProducerQueue::Dequeue(
+ int timeout, size_t* slot, LocalHandle* release_fence) {
+ if (slot == nullptr || release_fence == nullptr) {
+ ALOGE("invalid parameter, slot=%p, release_fence=%p", slot, release_fence);
+ return nullptr;
+ }
+
+ auto buf = BufferHubQueue::Dequeue(timeout, slot, nullptr, release_fence);
return std::static_pointer_cast<BufferProducer>(buf);
}
-int ProducerQueue::OnBufferReady(std::shared_ptr<BufferHubBuffer> buf) {
+int ProducerQueue::OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
+ LocalHandle* release_fence) {
auto buffer = std::static_pointer_cast<BufferProducer>(buf);
- return buffer->GainAsync();
+ return buffer->Gain(release_fence);
}
ConsumerQueue::ConsumerQueue(LocalChannelHandle handle, size_t meta_size)
@@ -406,8 +414,9 @@
auto buffer_handle_slots = status.take();
for (auto& buffer_handle_slot : buffer_handle_slots) {
- ALOGD("ConsumerQueue::ImportBuffers, new buffer, buffer_handle: %d",
- buffer_handle_slot.first.value());
+ ALOGD_IF(TRACE,
+ "ConsumerQueue::ImportBuffers, new buffer, buffer_handle: %d",
+ buffer_handle_slot.first.value());
std::unique_ptr<BufferConsumer> buffer_consumer =
BufferConsumer::Import(std::move(buffer_handle_slot.first));
@@ -431,9 +440,9 @@
return BufferHubQueue::AddBuffer(buf, slot);
}
-std::shared_ptr<BufferConsumer> ConsumerQueue::Dequeue(int timeout,
- size_t* slot, void* meta,
- size_t meta_size) {
+std::shared_ptr<BufferConsumer> ConsumerQueue::Dequeue(
+ int timeout, size_t* slot, void* meta, size_t meta_size,
+ LocalHandle* acquire_fence) {
if (meta_size != meta_size_) {
ALOGE(
"metadata size (%zu) for the dequeuing buffer does not match metadata "
@@ -441,14 +450,21 @@
meta_size, meta_size_);
return nullptr;
}
- auto buf = BufferHubQueue::Dequeue(timeout, slot, meta);
+
+ if (slot == nullptr || meta == nullptr || acquire_fence == nullptr) {
+ ALOGE("invalid parameter, slot=%p, meta=%p, acquire_fence=%p", slot, meta,
+ acquire_fence);
+ return nullptr;
+ }
+
+ auto buf = BufferHubQueue::Dequeue(timeout, slot, meta, acquire_fence);
return std::static_pointer_cast<BufferConsumer>(buf);
}
-int ConsumerQueue::OnBufferReady(std::shared_ptr<BufferHubBuffer> buf) {
+int ConsumerQueue::OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
+ LocalHandle* acquire_fence) {
auto buffer = std::static_pointer_cast<BufferConsumer>(buf);
- LocalHandle fence;
- return buffer->Acquire(&fence, meta_buffer_tmp_.get(), meta_size_);
+ return buffer->Acquire(acquire_fence, meta_buffer_tmp_.get(), meta_size_);
}
int ConsumerQueue::OnBufferAllocated() {
@@ -458,7 +474,7 @@
} else if (ret < 0) {
ALOGE("Failed to import buffers on buffer allocated event.");
}
- ALOGD("Imported %d consumer buffers.", ret);
+ ALOGD_IF(TRACE, "Imported %d consumer buffers.", ret);
return ret;
}
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_consumer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_consumer.cpp
index 02bca09..1ea3994 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_consumer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_consumer.cpp
@@ -1,7 +1,5 @@
#include "include/private/dvr/buffer_hub_queue_consumer.h"
-//#define LOG_NDEBUG 0
-
namespace android {
namespace dvr {
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_core.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_core.cpp
index b013c85..a108042 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_core.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_core.cpp
@@ -1,8 +1,5 @@
#include "include/private/dvr/buffer_hub_queue_core.h"
-//#define LOG_NDEBUG 0
-#define LOG_TAG "BufferHubQueueCore"
-
#include <log/log.h>
namespace android {
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
index 7ddf49b..ddf7fd2 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
@@ -1,7 +1,5 @@
#include "include/private/dvr/buffer_hub_queue_producer.h"
-//#define LOG_NDEBUG 0
-
#include <inttypes.h>
#include <log/log.h>
@@ -14,7 +12,7 @@
status_t BufferHubQueueProducer::requestBuffer(int slot,
sp<GraphicBuffer>* buf) {
- ALOGD("requestBuffer: slot=%d", slot);
+ ALOGD_IF(TRACE, "requestBuffer: slot=%d", slot);
std::unique_lock<std::mutex> lock(core_->mutex_);
@@ -35,8 +33,8 @@
status_t BufferHubQueueProducer::setMaxDequeuedBufferCount(
int max_dequeued_buffers) {
- ALOGD("setMaxDequeuedBufferCount: max_dequeued_buffers=%d",
- max_dequeued_buffers);
+ ALOGD_IF(TRACE, "setMaxDequeuedBufferCount: max_dequeued_buffers=%d",
+ max_dequeued_buffers);
std::unique_lock<std::mutex> lock(core_->mutex_);
@@ -63,8 +61,8 @@
PixelFormat format,
uint32_t usage,
FrameEventHistoryDelta* /* outTimestamps */) {
- ALOGD("dequeueBuffer: w=%u, h=%u, format=%d, usage=%u", width, height, format,
- usage);
+ ALOGD_IF(TRACE, "dequeueBuffer: w=%u, h=%u, format=%d, usage=%u", width,
+ height, format, usage);
status_t ret;
std::unique_lock<std::mutex> lock(core_->mutex_);
@@ -83,8 +81,9 @@
std::shared_ptr<BufferProducer> buffer_producer;
for (size_t retry = 0; retry < BufferHubQueue::kMaxQueueCapacity; retry++) {
+ LocalHandle fence;
buffer_producer =
- core_->producer_->Dequeue(core_->dequeue_timeout_ms_, &slot);
+ core_->producer_->Dequeue(core_->dequeue_timeout_ms_, &slot, &fence);
if (!buffer_producer)
return NO_MEMORY;
@@ -133,7 +132,7 @@
core_->buffers_[slot].mBufferState.freeQueued();
core_->buffers_[slot].mBufferState.dequeue();
- ALOGD("dequeueBuffer: slot=%zu", slot);
+ ALOGD_IF(TRACE, "dequeueBuffer: slot=%zu", slot);
// TODO(jwcai) Handle fence properly. |BufferHub| has full fence support, we
// just need to exopose that through |BufferHubQueue| once we need fence.
@@ -172,7 +171,7 @@
status_t BufferHubQueueProducer::queueBuffer(int slot,
const QueueBufferInput& input,
QueueBufferOutput* /* output */) {
- ALOGD("queueBuffer: slot %d", slot);
+ ALOGD_IF(TRACE, "queueBuffer: slot %d", slot);
int64_t timestamp;
sp<Fence> fence;
@@ -219,7 +218,7 @@
status_t BufferHubQueueProducer::cancelBuffer(int slot,
const sp<Fence>& fence) {
- ALOGD(__FUNCTION__);
+ ALOGD_IF(TRACE, __FUNCTION__);
std::unique_lock<std::mutex> lock(core_->mutex_);
@@ -240,13 +239,13 @@
core_->producer_->Enqueue(buffer_producer, slot);
core_->buffers_[slot].mBufferState.cancel();
core_->buffers_[slot].mFence = fence;
- ALOGD("cancelBuffer: slot %d", slot);
+ ALOGD_IF(TRACE, "cancelBuffer: slot %d", slot);
return NO_ERROR;
}
status_t BufferHubQueueProducer::query(int what, int* out_value) {
- ALOGD(__FUNCTION__);
+ ALOGD_IF(TRACE, __FUNCTION__);
std::unique_lock<std::mutex> lock(core_->mutex_);
@@ -277,7 +276,7 @@
return BAD_VALUE;
}
- ALOGD("query: key=%d, v=%d", what, value);
+ ALOGD_IF(TRACE, "query: key=%d, v=%d", what, value);
*out_value = value;
return NO_ERROR;
}
@@ -287,14 +286,14 @@
bool /* producer_controlled_by_app */, QueueBufferOutput* /* output */) {
// Consumer interaction are actually handled by buffer hub, and we need
// to maintain consumer operations here. Hence |connect| is a NO-OP.
- ALOGD(__FUNCTION__);
+ ALOGD_IF(TRACE, __FUNCTION__);
return NO_ERROR;
}
status_t BufferHubQueueProducer::disconnect(int /* api */, DisconnectMode /* mode */) {
// Consumer interaction are actually handled by buffer hub, and we need
// to maintain consumer operations here. Hence |disconnect| is a NO-OP.
- ALOGD(__FUNCTION__);
+ ALOGD_IF(TRACE, __FUNCTION__);
return NO_ERROR;
}
@@ -326,7 +325,7 @@
status_t BufferHubQueueProducer::setGenerationNumber(
uint32_t generation_number) {
- ALOGD(__FUNCTION__);
+ ALOGD_IF(TRACE, __FUNCTION__);
std::unique_lock<std::mutex> lock(core_->mutex_);
core_->generation_number_ = generation_number;
@@ -353,7 +352,7 @@
}
status_t BufferHubQueueProducer::setDequeueTimeout(nsecs_t timeout) {
- ALOGD(__FUNCTION__);
+ ALOGD_IF(TRACE, __FUNCTION__);
std::unique_lock<std::mutex> lock(core_->mutex_);
core_->dequeue_timeout_ms_ = static_cast<int>(timeout / (1000 * 1000));
@@ -373,7 +372,7 @@
}
status_t BufferHubQueueProducer::getUniqueId(uint64_t* out_id) const {
- ALOGD(__FUNCTION__);
+ ALOGD_IF(TRACE, __FUNCTION__);
*out_id = core_->unique_id_;
return NO_ERROR;
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 1f2830a..feaf3d7 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
@@ -20,6 +20,7 @@
// automatically re-requeued when released by the remote side.
class BufferHubQueue : public pdx::Client {
public:
+ using LocalHandle = pdx::LocalHandle;
using LocalChannelHandle = pdx::LocalChannelHandle;
template <typename T>
using Status = pdx::Status<T>;
@@ -91,14 +92,15 @@
// while specifying a timeout equal to zero cause |Dequeue()| to return
// immediately, even if no buffers are available.
std::shared_ptr<BufferHubBuffer> Dequeue(int timeout, size_t* slot,
- void* meta);
+ void* meta, LocalHandle* fence);
// Wait for buffers to be released and re-add them to the queue.
bool WaitForBuffers(int timeout);
void HandleBufferEvent(size_t slot, const epoll_event& event);
void HandleQueueEvent(const epoll_event& event);
- virtual int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf) = 0;
+ virtual int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
+ LocalHandle* fence) = 0;
// Called when a buffer is allocated remotely.
virtual int OnBufferAllocated() = 0;
@@ -202,6 +204,10 @@
// prevent the buffer from being deleted.
RingBuffer<BufferInfo> available_buffers_;
+ // Fences (acquire fence for consumer and release fence for consumer) , one
+ // for each buffer slot.
+ std::vector<LocalHandle> fences_;
+
// Keep track with how many buffers have been added into the queue.
size_t capacity_;
@@ -274,7 +280,8 @@
// Dequeue a producer buffer to write. The returned buffer in |Gain|'ed mode,
// and caller should call Post() once it's done writing to release the buffer
// to the consumer side.
- std::shared_ptr<BufferProducer> Dequeue(int timeout, size_t* slot);
+ std::shared_ptr<BufferProducer> Dequeue(int timeout, size_t* slot,
+ LocalHandle* release_fence);
private:
friend BASE;
@@ -287,7 +294,8 @@
ProducerQueue(size_t meta_size, int usage_set_mask, int usage_clear_mask,
int usage_deny_set_mask, int usage_deny_clear_mask);
- int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf) override;
+ int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
+ LocalHandle* release_fence) override;
// Producer buffer is always allocated from the client (i.e. local) side.
int OnBufferAllocated() override { return 0; }
@@ -316,14 +324,11 @@
// Dequeue() is done with the corect metadata type and size with those used
// when the buffer is orignally created.
template <typename Meta>
- std::shared_ptr<BufferConsumer> Dequeue(int timeout, size_t* slot,
- Meta* meta) {
- return Dequeue(timeout, slot, meta, sizeof(*meta));
+ std::shared_ptr<BufferConsumer> Dequeue(int timeout, size_t* slot, Meta* meta,
+ LocalHandle* acquire_fence) {
+ return Dequeue(timeout, slot, meta, sizeof(*meta), acquire_fence);
}
- std::shared_ptr<BufferConsumer> Dequeue(int timeout, size_t* slot, void* meta,
- size_t meta_size);
-
private:
friend BASE;
@@ -335,9 +340,14 @@
// consumer.
int AddBuffer(const std::shared_ptr<BufferConsumer>& buf, size_t slot);
- int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf) override;
+ int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
+ LocalHandle* acquire_fence) override;
int OnBufferAllocated() override;
+
+ std::shared_ptr<BufferConsumer> Dequeue(int timeout, size_t* slot, void* meta,
+ size_t meta_size,
+ LocalHandle* acquire_fence);
};
} // namespace dvr
diff --git a/libs/vr/libbufferhubqueue/tests/Android.bp b/libs/vr/libbufferhubqueue/tests/Android.bp
new file mode 100644
index 0000000..b8a0da3
--- /dev/null
+++ b/libs/vr/libbufferhubqueue/tests/Android.bp
@@ -0,0 +1,46 @@
+
+
+shared_libraries = [
+ "libbase",
+ "libbinder",
+ "libcutils",
+ "libgui",
+ "liblog",
+ "libhardware",
+ "libui",
+ "libutils",
+]
+
+static_libraries = [
+ "libbufferhubqueue",
+ "libbufferhub",
+ "libchrome",
+ "libdvrcommon",
+ "libpdx_default_transport",
+]
+
+cc_test {
+ srcs: ["buffer_hub_queue-test.cpp"],
+ static_libs: static_libraries,
+ shared_libs: shared_libraries,
+ cflags: [
+ "-DTRACE=0",
+ "-O0",
+ "-g",
+ ],
+ name: "buffer_hub_queue-test",
+ tags: ["optional"],
+}
+
+cc_test {
+ srcs: ["buffer_hub_queue_producer-test.cpp"],
+ static_libs: static_libraries,
+ shared_libs: shared_libraries,
+ cflags: [
+ "-DTRACE=0",
+ "-O0",
+ "-g",
+ ],
+ name: "buffer_hub_queue_producer-test",
+ tags: ["optional"],
+}
diff --git a/libs/vr/libbufferhubqueue/tests/Android.mk b/libs/vr/libbufferhubqueue/tests/Android.mk
deleted file mode 100644
index 59061e6..0000000
--- a/libs/vr/libbufferhubqueue/tests/Android.mk
+++ /dev/null
@@ -1,38 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-shared_libraries := \
- libbase \
- libbinder \
- libcutils \
- libgui \
- liblog \
- libhardware \
- libui \
- libutils \
-
-static_libraries := \
- libbufferhubqueue \
- libbufferhub \
- libchrome \
- libdvrcommon \
- libpdx_default_transport \
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := buffer_hub_queue-test.cpp
-LOCAL_STATIC_LIBRARIES := $(static_libraries)
-LOCAL_SHARED_LIBRARIES := $(shared_libraries)
-LOCAL_EXPORT_C_INCLUDE_DIRS := ${LOCAL_C_INCLUDES}
-LOCAL_CFLAGS := -DTRACE=0 -O0 -g
-LOCAL_MODULE := buffer_hub_queue-test
-LOCAL_MODULE_TAGS := optional
-include $(BUILD_NATIVE_TEST)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := buffer_hub_queue_producer-test.cpp
-LOCAL_STATIC_LIBRARIES := $(static_libraries)
-LOCAL_SHARED_LIBRARIES := $(shared_libraries)
-LOCAL_EXPORT_C_INCLUDE_DIRS := ${LOCAL_C_INCLUDES}
-LOCAL_CFLAGS := -DTRACE=0 -O0 -g
-LOCAL_MODULE := buffer_hub_queue_producer-test
-LOCAL_MODULE_TAGS := optional
-include $(BUILD_NATIVE_TEST)
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
index 841554e..811543d 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
@@ -59,12 +59,13 @@
// But dequeue multiple times.
for (size_t i = 0; i < nb_dequeue_times; i++) {
size_t slot;
- auto p1 = producer_queue_->Dequeue(0, &slot);
+ LocalHandle fence;
+ auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
ASSERT_NE(nullptr, p1);
size_t mi = i;
ASSERT_EQ(p1->Post(LocalHandle(), &mi, sizeof(mi)), 0);
size_t mo;
- auto c1 = consumer_queue_->Dequeue(100, &slot, &mo);
+ auto c1 = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
ASSERT_NE(nullptr, c1);
ASSERT_EQ(mi, mo);
c1->Release(LocalHandle());
@@ -91,19 +92,21 @@
ASSERT_EQ(consumer_queue_->capacity(), i);
// Dequeue returns nullptr since no buffer is ready to consumer, but
// this implicitly triggers buffer import and bump up |capacity|.
- auto consumer_null = consumer_queue_->Dequeue(0, &slot, &seq);
+ LocalHandle fence;
+ auto consumer_null = consumer_queue_->Dequeue(0, &slot, &seq, &fence);
ASSERT_EQ(nullptr, consumer_null);
ASSERT_EQ(consumer_queue_->capacity(), i + 1);
}
for (size_t i = 0; i < nb_buffer; i++) {
+ LocalHandle fence;
// First time, there is no buffer available to dequeue.
- auto buffer_null = consumer_queue_->Dequeue(0, &slot, &seq);
+ auto buffer_null = consumer_queue_->Dequeue(0, &slot, &seq, &fence);
ASSERT_EQ(nullptr, buffer_null);
// Make sure Producer buffer is Post()'ed so that it's ready to Accquire
// in the consumer's Dequeue() function.
- auto producer = producer_queue_->Dequeue(0, &slot);
+ auto producer = producer_queue_->Dequeue(0, &slot, &fence);
ASSERT_NE(nullptr, producer);
uint64_t seq_in = static_cast<uint64_t>(i);
@@ -111,7 +114,7 @@
// Second time, the just |Post()|'ed buffer should be dequeued.
uint64_t seq_out = 0;
- auto consumer = consumer_queue_->Dequeue(0, &slot, &seq_out);
+ auto consumer = consumer_queue_->Dequeue(0, &slot, &seq_out, &fence);
ASSERT_NE(nullptr, consumer);
ASSERT_EQ(seq_in, seq_out);
}
@@ -132,11 +135,12 @@
for (auto mi : ms) {
size_t slot;
- auto p1 = producer_queue_->Dequeue(0, &slot);
+ LocalHandle fence;
+ auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
ASSERT_NE(nullptr, p1);
ASSERT_EQ(p1->Post(LocalHandle(-1), &mi, sizeof(mi)), 0);
TestMetadata mo;
- auto c1 = consumer_queue_->Dequeue(0, &slot, &mo);
+ auto c1 = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
ASSERT_EQ(mi.a, mo.a);
ASSERT_EQ(mi.b, mo.b);
ASSERT_EQ(mi.c, mo.c);
@@ -150,13 +154,14 @@
int64_t mi = 3;
size_t slot;
- auto p1 = producer_queue_->Dequeue(0, &slot);
+ LocalHandle fence;
+ auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
ASSERT_NE(nullptr, p1);
ASSERT_EQ(p1->Post(LocalHandle(-1), &mi, sizeof(mi)), 0);
int32_t mo;
// Acquire a buffer with mismatched metadata is not OK.
- auto c1 = consumer_queue_->Dequeue(0, &slot, &mo);
+ auto c1 = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
ASSERT_EQ(nullptr, c1);
}
@@ -165,12 +170,13 @@
AllocateBuffer();
size_t slot;
- auto p1 = producer_queue_->Dequeue(0, &slot);
+ LocalHandle fence;
+ auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
ASSERT_NE(nullptr, p1);
int64_t mo;
producer_queue_->Enqueue(p1, slot);
- auto c1 = consumer_queue_->Dequeue(0, &slot, &mo);
+ auto c1 = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
ASSERT_EQ(nullptr, c1);
}
@@ -179,12 +185,13 @@
size_t s1;
AllocateBuffer();
- auto p1 = producer_queue_->Dequeue(0, &s1);
+ LocalHandle fence;
+ auto p1 = producer_queue_->Dequeue(0, &s1, &fence);
ASSERT_NE(nullptr, p1);
// producer queue is exhausted
size_t s2;
- auto p2_null = producer_queue_->Dequeue(0, &s2);
+ auto p2_null = producer_queue_->Dequeue(0, &s2, &fence);
ASSERT_EQ(nullptr, p2_null);
// dynamically add buffer.
@@ -193,7 +200,7 @@
ASSERT_EQ(producer_queue_->capacity(), 2U);
// now we can dequeue again
- auto p2 = producer_queue_->Dequeue(0, &s2);
+ auto p2 = producer_queue_->Dequeue(0, &s2, &fence);
ASSERT_NE(nullptr, p2);
ASSERT_EQ(producer_queue_->count(), 0U);
// p1 and p2 should have different slot number
@@ -206,14 +213,14 @@
int64_t seq = 1;
ASSERT_EQ(p1->Post(LocalHandle(), seq), 0);
size_t cs1, cs2;
- auto c1 = consumer_queue_->Dequeue(0, &cs1, &seq);
+ auto c1 = consumer_queue_->Dequeue(0, &cs1, &seq, &fence);
ASSERT_NE(nullptr, c1);
ASSERT_EQ(consumer_queue_->count(), 0U);
ASSERT_EQ(consumer_queue_->capacity(), 2U);
ASSERT_EQ(cs1, s1);
ASSERT_EQ(p2->Post(LocalHandle(), seq), 0);
- auto c2 = consumer_queue_->Dequeue(0, &cs2, &seq);
+ auto c2 = consumer_queue_->Dequeue(0, &cs2, &seq, &fence);
ASSERT_NE(nullptr, c2);
ASSERT_EQ(cs2, s2);
}
@@ -229,7 +236,8 @@
kBufferSliceCount, &slot);
ASSERT_EQ(ret, 0);
- auto p1 = producer_queue_->Dequeue(0, &slot);
+ LocalHandle fence;
+ auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
ASSERT_EQ(p1->usage() & set_mask, set_mask);
}
@@ -244,7 +252,8 @@
kBufferSliceCount, &slot);
ASSERT_EQ(ret, 0);
- auto p1 = producer_queue_->Dequeue(0, &slot);
+ LocalHandle fence;
+ auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
ASSERT_EQ(p1->usage() & clear_mask, 0);
}
diff --git a/libs/vr/libdisplay/Android.bp b/libs/vr/libdisplay/Android.bp
new file mode 100644
index 0000000..f3c71b5
--- /dev/null
+++ b/libs/vr/libdisplay/Android.bp
@@ -0,0 +1,104 @@
+// 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.
+
+sourceFiles = [
+ "native_buffer_queue.cpp",
+ "display_client.cpp",
+ "display_manager_client.cpp",
+ "display_manager_client_impl.cpp",
+ "display_rpc.cpp",
+ "dummy_native_window.cpp",
+ "gl_fenced_flush.cpp",
+ "graphics.cpp",
+ "late_latch.cpp",
+ "video_mesh_surface_client.cpp",
+ "vsync_client.cpp",
+ "vsync_client_api.cpp",
+ "screenshot_client.cpp",
+ "frame_history.cpp",
+]
+
+localIncludeFiles = [
+ "include",
+]
+
+sharedLibraries = [
+ "libbase",
+ "libcutils",
+ "liblog",
+ "libutils",
+ "libEGL",
+ "libGLESv2",
+ "libvulkan",
+ "libui",
+ "libgui",
+ "libhardware",
+ "libsync",
+ "libnativewindow",
+]
+
+staticLibraries = [
+ "libbufferhub",
+ "libbufferhubqueue",
+ "libdvrcommon",
+ "libdvrgraphics",
+ "libvrsensor",
+ "libpdx_default_transport",
+]
+
+headerLibraries = [
+ "vulkan_headers",
+]
+
+cc_library {
+ tags: ["tests"],
+ srcs: sourceFiles,
+ cflags: ["-DLOG_TAG=\"libdisplay\"",
+ "-DTRACE=0",
+ "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
+ "-DGL_GLEXT_PROTOTYPES",
+ "-DEGL_EGLEXT_PROTOTYPES",
+ ], // + [ "-UNDEBUG", "-DDEBUG", "-O0", "-g" ],
+ export_include_dirs: localIncludeFiles,
+ shared_libs: sharedLibraries,
+ static_libs: staticLibraries,
+ header_libs: headerLibraries,
+ export_header_lib_headers: headerLibraries,
+
+ name: "libdisplay",
+}
+
+graphicsAppTestFiles = ["tests/graphics_app_tests.cpp"]
+
+cc_test {
+ name: "graphics_app_tests",
+ tags: ["optional"],
+
+ srcs: graphicsAppTestFiles,
+
+ shared_libs: sharedLibraries,
+
+ static_libs: ["libdisplay"] + staticLibraries,
+}
+
+dummyNativeWindowTestFiles = ["tests/dummy_native_window_tests.cpp"]
+
+cc_test {
+ name: "dummy_native_window_tests",
+ tags: [ "optional" ],
+ srcs: dummyNativeWindowTestFiles,
+ shared_libs: sharedLibraries,
+ static_libs: [ "libdisplay" ] + staticLibraries,
+}
+
diff --git a/libs/vr/libdisplay/Android.mk b/libs/vr/libdisplay/Android.mk
deleted file mode 100644
index 60f73c6..0000000
--- a/libs/vr/libdisplay/Android.mk
+++ /dev/null
@@ -1,116 +0,0 @@
-# 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.
-
-LOCAL_PATH := $(call my-dir)
-
-sourceFiles := \
- native_buffer_queue.cpp \
- display_client.cpp \
- display_manager_client.cpp \
- display_manager_client_impl.cpp \
- display_rpc.cpp \
- dummy_native_window.cpp \
- gl_fenced_flush.cpp \
- graphics.cpp \
- late_latch.cpp \
- video_mesh_surface_client.cpp \
- vsync_client.cpp \
- vsync_client_api.cpp \
- screenshot_client.cpp \
- frame_history.cpp
-
-includeFiles := \
- $(LOCAL_PATH)/include \
- frameworks/native/vulkan/include
-
-sharedLibraries := \
- libbase \
- libcutils \
- liblog \
- libutils \
- libEGL \
- libGLESv2 \
- libvulkan \
- libui \
- libgui \
- libhardware \
- libsync \
- libnativewindow \
-
-staticLibraries := \
- libbufferhub \
- libbufferhubqueue \
- libdvrcommon \
- libdvrgraphics \
- libsensor \
- libpdx_default_transport \
-
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := $(sourceFiles)
-LOCAL_C_INCLUDES := $(includeFiles)
-#LOCAL_CPPFLAGS := -UNDEBUG -DDEBUG -O0 -g
-LOCAL_CFLAGS += -DLOG_TAG=\"libdisplay\"
-LOCAL_CFLAGS += -DTRACE=0
-LOCAL_CFLAGS += -DATRACE_TAG=ATRACE_TAG_GRAPHICS
-LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(includeFiles)
-LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
-LOCAL_STATIC_LIBRARIES := $(staticLibraries)
-LOCAL_MODULE := libdisplay
-include $(BUILD_STATIC_LIBRARY)
-
-graphicsAppTestFiles := \
- tests/graphics_app_tests.cpp
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := graphics_app_tests
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := \
- $(graphicsAppTestFiles) \
-
-LOCAL_C_INCLUDES := \
- $(includeFiles) \
-
-LOCAL_SHARED_LIBRARIES := \
- $(sharedLibraries) \
-
-LOCAL_STATIC_LIBRARIES := \
- libdisplay \
- $(staticLibraries) \
-
-include $(BUILD_NATIVE_TEST)
-
-dummyNativeWindowTestFiles := \
- tests/dummy_native_window_tests.cpp \
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := dummy_native_window_tests
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := \
- $(dummyNativeWindowTestFiles) \
-
-LOCAL_C_INCLUDES := \
- $(includeFiles) \
-
-LOCAL_SHARED_LIBRARIES := \
- $(sharedLibraries) \
-
-LOCAL_STATIC_LIBRARIES := \
- libdisplay \
- $(staticLibraries) \
-include $(BUILD_NATIVE_TEST)
-
diff --git a/libs/vr/libdisplay/display_client.cpp b/libs/vr/libdisplay/display_client.cpp
index 54098e8..3a1cc72 100644
--- a/libs/vr/libdisplay/display_client.cpp
+++ b/libs/vr/libdisplay/display_client.cpp
@@ -148,18 +148,22 @@
}
}
-std::shared_ptr<BufferProducer> DisplaySurfaceClient::AllocateBuffer(
- uint32_t* buffer_index) {
- auto status = InvokeRemoteMethod<DisplayRPC::AllocateBuffer>();
- if (!status) {
- ALOGE("DisplaySurfaceClient::AllocateBuffer: Failed to allocate buffer: %s",
+std::shared_ptr<ProducerQueue> DisplaySurfaceClient::GetProducerQueue() {
+ if (producer_queue_ == nullptr) {
+ // Create producer queue through DisplayRPC
+ auto status = InvokeRemoteMethod<DisplayRPC::CreateBufferQueue>();
+ if (!status) {
+ ALOGE(
+ "DisplaySurfaceClient::GetProducerQueue: failed to create producer "
+ "queue: %s",
status.GetErrorMessage().c_str());
- return nullptr;
- }
+ return nullptr;
+ }
- if (buffer_index)
- *buffer_index = status.get().first;
- return BufferProducer::Import(status.take().second);
+ producer_queue_ =
+ ProducerQueue::Import<DisplaySurfaceMetadata>(status.take());
+ }
+ return producer_queue_;
}
volatile DisplaySurfaceMetadata* DisplaySurfaceClient::GetMetadataBufferPtr() {
@@ -272,5 +276,18 @@
return DisplaySurfaceClient::Create(width, height, format, usage, flags);
}
+std::unique_ptr<BufferConsumer> DisplayClient::GetPoseBuffer() {
+ auto status = InvokeRemoteMethod<DisplayRPC::GetPoseBuffer>();
+ if (!status) {
+ ALOGE(
+ "DisplayClient::GetPoseBuffer: Failed to get pose buffer %s",
+ status.GetErrorMessage().c_str());
+ return nullptr;
+ }
+
+ return BufferConsumer::Import(std::move(status));
+}
+
+
} // namespace dvr
} // namespace android
diff --git a/libs/vr/libdisplay/display_manager_client.cpp b/libs/vr/libdisplay/display_manager_client.cpp
index fe18619..d60d35b 100644
--- a/libs/vr/libdisplay/display_manager_client.cpp
+++ b/libs/vr/libdisplay/display_manager_client.cpp
@@ -2,6 +2,7 @@
#include <private/dvr/buffer_hub_client.h>
#include <private/dvr/display_manager_client_impl.h>
+#include <private/dvr/dvr_buffer.h>
using android::dvr::DisplaySurfaceAttributeEnum;
@@ -41,6 +42,18 @@
delete client;
}
+DvrWriteBuffer* dvrDisplayManagerSetupPoseBuffer(
+ DvrDisplayManagerClient* client, size_t extended_region_size,
+ uint64_t usage0, uint64_t usage1) {
+ // TODO(hendrikw): When we move to gralloc1, pass both usage0 and usage1 down.
+ auto buffer_producer = client->client->SetupPoseBuffer(
+ extended_region_size, static_cast<int>(usage0));
+ if (buffer_producer) {
+ return CreateDvrWriteBufferFromBufferProducer(std::move(buffer_producer));
+ }
+ return nullptr;
+}
+
int dvrDisplayManagerClientGetEventFd(DvrDisplayManagerClient* client) {
return client->client->event_fd();
}
diff --git a/libs/vr/libdisplay/display_manager_client_impl.cpp b/libs/vr/libdisplay/display_manager_client_impl.cpp
index 3fbd1e0..7993fce 100644
--- a/libs/vr/libdisplay/display_manager_client_impl.cpp
+++ b/libs/vr/libdisplay/display_manager_client_impl.cpp
@@ -31,5 +31,20 @@
return 0;
}
+std::unique_ptr<BufferProducer> DisplayManagerClient::SetupPoseBuffer(
+ size_t extended_region_size, int usage) {
+ auto status = InvokeRemoteMethod<DisplayManagerRPC::SetupPoseBuffer>(
+ extended_region_size, usage);
+ if (!status) {
+ ALOGE(
+ "DisplayManagerClient::SetupPoseBuffer: Failed to create the pose "
+ "buffer %s",
+ status.GetErrorMessage().c_str());
+ return {};
+ }
+
+ return BufferProducer::Import(std::move(status));
+}
+
} // namespace dvr
} // namespace android
diff --git a/libs/vr/libdisplay/graphics.cpp b/libs/vr/libdisplay/graphics.cpp
index 61f6fea..c2fbb8b 100644
--- a/libs/vr/libdisplay/graphics.cpp
+++ b/libs/vr/libdisplay/graphics.cpp
@@ -17,6 +17,7 @@
#include <private/dvr/clock_ns.h>
#include <private/dvr/debug.h>
#include <private/dvr/display_types.h>
+#include <private/dvr/dvr_buffer.h>
#include <private/dvr/frame_history.h>
#include <private/dvr/gl_fenced_flush.h>
#include <private/dvr/graphics/vr_gl_extensions.h>
@@ -1571,3 +1572,14 @@
};
}
}
+
+extern "C" int dvrGetPoseBuffer(DvrReadBuffer** pose_buffer) {
+ auto client = android::dvr::DisplayClient::Create();
+ if (!client) {
+ ALOGE("Failed to create display client!");
+ return -ECOMM;
+ }
+
+ *pose_buffer = CreateDvrReadBufferFromBufferConsumer(client->GetPoseBuffer());
+ return 0;
+}
diff --git a/libs/vr/libdisplay/include/dvr/graphics.h b/libs/vr/libdisplay/include/dvr/graphics.h
index 19deec3..fc51d52 100644
--- a/libs/vr/libdisplay/include/dvr/graphics.h
+++ b/libs/vr/libdisplay/include/dvr/graphics.h
@@ -160,6 +160,8 @@
int dvrGetNativeDisplayDimensions(int* native_width, int* native_height);
+typedef struct DvrReadBuffer DvrReadBuffer;
+
// Opaque struct that represents a graphics context, the texture swap chain,
// and surfaces.
typedef struct DvrGraphicsContext DvrGraphicsContext;
@@ -440,6 +442,9 @@
const int eye,
const float* transform);
+// Get a pointer to the global pose buffer.
+int dvrGetPoseBuffer(DvrReadBuffer** pose_buffer);
+
__END_DECLS
#endif // DVR_GRAPHICS_H_
diff --git a/libs/vr/libdisplay/include/private/dvr/display_client.h b/libs/vr/libdisplay/include/private/dvr/display_client.h
index 034b7b4..bfc167e 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_client.h
@@ -5,6 +5,7 @@
#include <pdx/client.h>
#include <pdx/file_handle.h>
#include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/buffer_hub_queue_client.h>
#include <private/dvr/display_rpc.h>
namespace android {
@@ -62,13 +63,9 @@
void SetBlurBehind(bool blur_behind);
void SetAttributes(const DisplaySurfaceAttributes& attributes);
- // |out_buffer_index| will receive a unique index for this buffer within the
- // surface. The first buffer gets 0, second gets 1, and so on. This index
- // can be used to deliver metadata for buffers that are queued for display.
- std::shared_ptr<BufferProducer> AllocateBuffer(uint32_t* out_buffer_index);
- std::shared_ptr<BufferProducer> AllocateBuffer() {
- return AllocateBuffer(nullptr);
- }
+ // Get the producer end of the buffer queue that transports graphics buffer
+ // from the application side to the compositor side.
+ std::shared_ptr<ProducerQueue> GetProducerQueue();
// Get the shared memory metadata buffer for this display surface. If it is
// not yet allocated, this will allocate it.
@@ -93,6 +90,9 @@
bool blur_behind_;
DisplaySurfaceMetadata* mapped_metadata_buffer_;
+ // TODO(jwcai) Add support for multiple queues.
+ std::shared_ptr<ProducerQueue> producer_queue_;
+
DisplaySurfaceClient(const DisplaySurfaceClient&) = delete;
void operator=(const DisplaySurfaceClient&) = delete;
};
@@ -111,6 +111,8 @@
std::unique_ptr<DisplaySurfaceClient> CreateDisplaySurface(
int width, int height, int format, int usage, int flags);
+ std::unique_ptr<BufferConsumer> GetPoseBuffer();
+
private:
friend BASE;
diff --git a/libs/vr/libdisplay/include/private/dvr/display_manager_client.h b/libs/vr/libdisplay/include/private/dvr/display_manager_client.h
index f515b8f..0928d43 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_manager_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_manager_client.h
@@ -14,11 +14,16 @@
DvrDisplayManagerClientSurfaceList;
typedef struct DvrDisplayManagerClientSurfaceBuffers
DvrDisplayManagerClientSurfaceBuffers;
+typedef struct DvrWriteBuffer DvrWriteBuffer;
DvrDisplayManagerClient* dvrDisplayManagerClientCreate();
void dvrDisplayManagerClientDestroy(DvrDisplayManagerClient* client);
+DvrWriteBuffer* dvrDisplayManagerSetupPoseBuffer(
+ DvrDisplayManagerClient* client, size_t extended_region_size,
+ uint64_t usage0, uint64_t usage1);
+
// Return an event fd for checking if there was an event on the server
// Note that the only event which will be flagged is POLLIN. You must use
// dvrDisplayManagerClientTranslateEpollEventMask in order to get the real
diff --git a/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h b/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h
index 0897126..144cd3b 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h
@@ -9,7 +9,7 @@
namespace android {
namespace dvr {
-class BufferConsumer;
+class BufferProducer;
class DisplayManagerClient : public pdx::ClientBase<DisplayManagerClient> {
public:
@@ -17,6 +17,9 @@
int GetSurfaceList(std::vector<DisplaySurfaceInfo>* surface_list);
+ std::unique_ptr<BufferProducer> SetupPoseBuffer(size_t extended_region_size,
+ int usage);
+
using Client::event_fd;
using Client::GetChannel;
diff --git a/libs/vr/libdisplay/include/private/dvr/display_rpc.h b/libs/vr/libdisplay/include/private/dvr/display_rpc.h
index d37aed7..e373123 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_rpc.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_rpc.h
@@ -212,14 +212,15 @@
kOpGetMetrics = 0,
kOpGetEdsCapture,
kOpCreateSurface,
- kOpAllocateBuffer,
+ kOpCreateBufferQueue,
kOpSetAttributes,
kOpGetMetadataBuffer,
kOpCreateVideoMeshSurface,
kOpVideoMeshSurfaceCreateProducerQueue,
kOpEnterVrMode,
kOpExitVrMode,
- kOpSetViewerParams
+ kOpSetViewerParams,
+ kOpGetPoseBuffer,
};
// Aliases.
@@ -233,8 +234,8 @@
PDX_REMOTE_METHOD(CreateSurface, kOpCreateSurface,
int(int width, int height, int format, int usage,
DisplaySurfaceFlags flags));
- PDX_REMOTE_METHOD(AllocateBuffer, kOpAllocateBuffer,
- std::pair<std::uint32_t, LocalChannelHandle>(Void));
+ PDX_REMOTE_METHOD(CreateBufferQueue, kOpCreateBufferQueue,
+ LocalChannelHandle(Void));
PDX_REMOTE_METHOD(SetAttributes, kOpSetAttributes,
int(const DisplaySurfaceAttributes& attributes));
PDX_REMOTE_METHOD(GetMetadataBuffer, kOpGetMetadataBuffer,
@@ -249,6 +250,8 @@
PDX_REMOTE_METHOD(ExitVrMode, kOpExitVrMode, int(Void));
PDX_REMOTE_METHOD(SetViewerParams, kOpSetViewerParams,
void(const ViewerParams& viewer_params));
+ PDX_REMOTE_METHOD(GetPoseBuffer, kOpGetPoseBuffer,
+ LocalChannelHandle(Void));
};
struct DisplayManagerRPC {
@@ -259,6 +262,7 @@
enum {
kOpGetSurfaceList = 0,
kOpUpdateSurfaces,
+ kOpSetupPoseBuffer,
};
// Aliases.
@@ -271,6 +275,8 @@
PDX_REMOTE_METHOD(
UpdateSurfaces, kOpUpdateSurfaces,
int(const std::map<int, DisplaySurfaceAttributes>& updates));
+ PDX_REMOTE_METHOD(SetupPoseBuffer, kOpSetupPoseBuffer,
+ LocalChannelHandle(size_t extended_region_size, int usage));
};
struct ScreenshotData {
diff --git a/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h b/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h
index 87e9c9f..4b1fa98 100644
--- a/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h
+++ b/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h
@@ -14,57 +14,27 @@
namespace android {
namespace dvr {
-// NativeBufferQueue manages a queue of NativeBufferProducers allocated from a
-// DisplaySurfaceClient. Buffers are automatically re-enqueued when released by
-// the consumer side.
+// A wrapper over dvr::ProducerQueue that caches EGLImage.
class NativeBufferQueue {
public:
// Create a queue with the given number of free buffers.
- NativeBufferQueue(const std::shared_ptr<DisplaySurfaceClient>& surface,
- size_t capacity);
NativeBufferQueue(EGLDisplay display,
const std::shared_ptr<DisplaySurfaceClient>& surface,
size_t capacity);
- ~NativeBufferQueue();
- std::shared_ptr<DisplaySurfaceClient> surface() const { return surface_; }
+ size_t GetQueueCapacity() const { return producer_queue_->capacity(); }
// Dequeue a buffer from the free queue, blocking until one is available.
NativeBufferProducer* Dequeue();
- // Enqueue a buffer at the end of the free queue.
- void Enqueue(NativeBufferProducer* buf);
-
- // Get the number of free buffers in the queue.
- size_t GetFreeBufferCount() const;
-
- // Get the total number of buffers managed by this queue.
- size_t GetQueueCapacity() const;
-
- // Accessors for display surface buffer attributes.
- int width() const { return surface_->width(); }
- int height() const { return surface_->height(); }
- int format() const { return surface_->format(); }
- int usage() const { return surface_->usage(); }
+ // An noop here to keep Vulkan path in GraphicsContext happy.
+ // TODO(jwcai, cort) Move Vulkan path into GVR/Google3.
+ void Enqueue(NativeBufferProducer* buffer) {}
private:
- // Wait for buffers to be released and enqueue them.
- bool WaitForBuffers();
-
- std::shared_ptr<DisplaySurfaceClient> surface_;
-
- // A list of strong pointers to the buffers, used for managing buffer
- // lifetime.
- std::vector<android::sp<NativeBufferProducer>> buffers_;
-
- // Used to implement queue semantics.
- RingBuffer<NativeBufferProducer*> buffer_queue_;
-
- // Epoll fd used to wait for BufferHub events.
- int epoll_fd_;
-
- NativeBufferQueue(const NativeBufferQueue&) = delete;
- void operator=(NativeBufferQueue&) = delete;
+ EGLDisplay display_;
+ std::shared_ptr<ProducerQueue> producer_queue_;
+ std::vector<sp<NativeBufferProducer>> buffers_;
};
} // namespace dvr
diff --git a/libs/vr/libdisplay/include/private/dvr/video_mesh_surface_client.h b/libs/vr/libdisplay/include/private/dvr/video_mesh_surface_client.h
index e52d0b9..3a7f125 100644
--- a/libs/vr/libdisplay/include/private/dvr/video_mesh_surface_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/video_mesh_surface_client.h
@@ -25,7 +25,7 @@
private:
friend BASE;
- std::shared_ptr<android::dvr::ProducerQueue> producer_queue_;
+ std::shared_ptr<ProducerQueue> producer_queue_;
VideoMeshSurfaceMetadata* mapped_metadata_buffer_;
explicit VideoMeshSurfaceClient(LocalChannelHandle handle);
diff --git a/libs/vr/libdisplay/native_buffer_queue.cpp b/libs/vr/libdisplay/native_buffer_queue.cpp
index 8dd0ee0..d516d63 100644
--- a/libs/vr/libdisplay/native_buffer_queue.cpp
+++ b/libs/vr/libdisplay/native_buffer_queue.cpp
@@ -13,138 +13,51 @@
namespace dvr {
NativeBufferQueue::NativeBufferQueue(
- const std::shared_ptr<DisplaySurfaceClient>& surface, size_t capacity)
- : NativeBufferQueue(nullptr, surface, capacity) {}
-
-NativeBufferQueue::NativeBufferQueue(
EGLDisplay display, const std::shared_ptr<DisplaySurfaceClient>& surface,
size_t capacity)
- : surface_(surface),
- buffers_(capacity),
- buffer_queue_(capacity) {
- LOG_ALWAYS_FATAL_IF(!surface);
-
- epoll_fd_ = epoll_create(64);
- if (epoll_fd_ < 0) {
- ALOGE("NativeBufferQueue::NativeBufferQueue: Failed to create epoll fd: %s",
- strerror(errno));
- return;
- }
-
- // The kSurfaceBufferMaxCount must be >= the capacity so that shader code
- // can bind surface buffer array data.
- LOG_ALWAYS_FATAL_IF(kSurfaceBufferMaxCount < capacity);
+ : display_(display), buffers_(capacity) {
+ std::shared_ptr<ProducerQueue> queue = surface->GetProducerQueue();
for (size_t i = 0; i < capacity; i++) {
- uint32_t buffer_index = 0;
- auto buffer = surface_->AllocateBuffer(&buffer_index);
- if (!buffer) {
- ALOGE("NativeBufferQueue::NativeBufferQueue: Failed to allocate buffer!");
- return;
- }
-
- // TODO(jbates): store an index associated with each buffer so that we can
- // determine which index in DisplaySurfaceMetadata it is associated
- // with.
- buffers_.push_back(new NativeBufferProducer(buffer, display, buffer_index));
- NativeBufferProducer* native_buffer = buffers_.back().get();
-
- epoll_event event = {.events = EPOLLIN | EPOLLET,
- .data = {.ptr = native_buffer}};
- if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, buffer->event_fd(), &event) <
- 0) {
+ size_t slot;
+ // TODO(jwcai) Should change to use BufferViewPort's spec to config.
+ int ret =
+ queue->AllocateBuffer(surface->width(), surface->height(),
+ surface->format(), surface->usage(), 1, &slot);
+ if (ret < 0) {
ALOGE(
- "NativeBufferQueue::NativeBufferQueue: Failed to add buffer producer "
- "to epoll set: %s",
- strerror(errno));
+ "NativeBufferQueue::NativeBufferQueue: Failed to allocate buffer, "
+ "error=%d",
+ ret);
return;
}
- Enqueue(native_buffer);
- }
-}
-
-NativeBufferQueue::~NativeBufferQueue() {
- if (epoll_fd_ >= 0)
- close(epoll_fd_);
-}
-
-bool NativeBufferQueue::WaitForBuffers() {
- ATRACE_NAME("NativeBufferQueue::WaitForBuffers");
- // Intentionally set this to one so that we don't waste time retrieving too
- // many buffers.
- constexpr size_t kMaxEvents = 1;
- std::array<epoll_event, kMaxEvents> events;
-
- while (buffer_queue_.IsEmpty()) {
- int num_events = epoll_wait(epoll_fd_, events.data(), events.size(), -1);
- if (num_events < 0 && errno != EINTR) {
- ALOGE("NativeBufferQueue:WaitForBuffers: Failed to wait for buffers: %s",
- strerror(errno));
- return false;
- }
-
- ALOGD_IF(TRACE, "NativeBufferQueue::WaitForBuffers: num_events=%d",
- num_events);
-
- for (int i = 0; i < num_events; i++) {
- NativeBufferProducer* buffer =
- static_cast<NativeBufferProducer*>(events[i].data.ptr);
- ALOGD_IF(TRACE,
- "NativeBufferQueue::WaitForBuffers: event %d: buffer_id=%d "
- "events=0x%x",
- i, buffer->buffer()->id(), events[i].events);
-
- if (events[i].events & EPOLLIN) {
- const int ret = buffer->GainAsync();
- if (ret < 0) {
- ALOGE("NativeBufferQueue::WaitForBuffers: Failed to gain buffer: %s",
- strerror(-ret));
- continue;
- }
-
- Enqueue(buffer);
- }
- }
+ ALOGD_IF(TRACE,
+ "NativeBufferQueue::NativeBufferQueue: New buffer allocated at "
+ "slot=%zu",
+ slot);
}
- return true;
-}
-
-void NativeBufferQueue::Enqueue(NativeBufferProducer* buf) {
- ATRACE_NAME("NativeBufferQueue::Enqueue");
- if (buffer_queue_.IsFull()) {
- ALOGE("NativeBufferQueue::Enqueue: Queue is full!");
- return;
- }
-
- buffer_queue_.Append(buf);
+ producer_queue_ = std::move(queue);
}
NativeBufferProducer* NativeBufferQueue::Dequeue() {
ATRACE_NAME("NativeBufferQueue::Dequeue");
- ALOGD_IF(TRACE, "NativeBufferQueue::Dequeue: count=%zd",
- buffer_queue_.GetSize());
- if (buffer_queue_.IsEmpty() && !WaitForBuffers())
- return nullptr;
+ // This never times out.
+ size_t slot;
+ pdx::LocalHandle fence;
+ std::shared_ptr<BufferProducer> buffer =
+ producer_queue_->Dequeue(-1, &slot, &fence);
- NativeBufferProducer* buf = buffer_queue_.Front();
- buffer_queue_.PopFront();
- if (buf == nullptr) {
- ALOGE("NativeBufferQueue::Dequeue: Buffer at tail was nullptr!!!");
- return nullptr;
+ if (buffers_[slot] == nullptr) {
+ buffers_[slot] = new NativeBufferProducer(buffer, display_, slot);
}
- return buf;
-}
-
-size_t NativeBufferQueue::GetFreeBufferCount() const {
- return buffer_queue_.GetSize();
-}
-
-size_t NativeBufferQueue::GetQueueCapacity() const {
- return buffer_queue_.GetCapacity();
+ ALOGD_IF(TRACE,
+ "NativeBufferQueue::Dequeue: dequeue buffer at slot=%zu, buffer=%p",
+ slot, buffers_[slot].get());
+ return buffers_[slot].get();
}
} // namespace dvr
diff --git a/libs/vr/libdvrcommon/Android.bp b/libs/vr/libdvrcommon/Android.bp
new file mode 100644
index 0000000..81404a4
--- /dev/null
+++ b/libs/vr/libdvrcommon/Android.bp
@@ -0,0 +1,81 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+sourceFiles = [
+ "frame_time_history.cpp",
+ "revision.cpp",
+ "revision_path.cpp",
+ "sync_util.cpp",
+]
+
+localIncludeFiles = [
+ "include",
+]
+
+sharedLibraries = [
+ "libbase",
+ "libcutils",
+ "liblog",
+ "libutils",
+ "libEGL",
+ "libGLESv2",
+ "libui",
+ "libgui",
+ "libhardware",
+]
+
+staticLibraries = ["libpdx_default_transport"]
+
+headerLibraries = [
+ "libeigen",
+]
+
+cc_library {
+ srcs: sourceFiles,
+ local_include_dirs: localIncludeFiles,
+
+ cflags: [
+ "-DLOG_TAG=\"libdvrcommon\"",
+ "-DTRACE=0",
+ ],
+ export_include_dirs: localIncludeFiles,
+
+ shared_libs: sharedLibraries,
+ static_libs: staticLibraries,
+ header_libs: headerLibraries,
+ export_header_lib_headers: headerLibraries,
+
+ name: "libdvrcommon",
+}
+
+testFiles = [
+ "tests/numeric_test.cpp",
+ "tests/pose_test.cpp",
+]
+
+cc_test {
+ name: "libdvrcommon_test",
+ tags: ["optional"],
+
+ srcs: testFiles,
+
+ shared_libs: sharedLibraries,
+
+ static_libs: [
+ "libgmock_main",
+ "libgmock",
+ "libgtest",
+ "libdvrcommon",
+ ] + staticLibraries,
+}
diff --git a/libs/vr/libdvrcommon/Android.mk b/libs/vr/libdvrcommon/Android.mk
deleted file mode 100644
index 80eb3a6..0000000
--- a/libs/vr/libdvrcommon/Android.mk
+++ /dev/null
@@ -1,80 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-sourceFiles := \
- frame_time_history.cpp \
- revision.cpp \
- revision_path.cpp \
- sync_util.cpp \
-
-includeFiles := \
- $(LOCAL_PATH)/include \
- external/eigen \
-
-sharedLibraries := \
- libbase \
- libcutils \
- liblog \
- libutils \
- libEGL \
- libGLESv2 \
- libui \
- libgui \
- libhardware
-
-staticLibraries := \
- libpdx_default_transport \
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(sourceFiles)
-LOCAL_C_INCLUDES := \
- $(includeFiles) \
-
-LOCAL_CFLAGS += -DLOG_TAG=\"libdvrcommon\"
-LOCAL_CFLAGS += -DTRACE=0
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
- $(includeFiles) \
-
-LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
-LOCAL_STATIC_LIBRARIES := $(staticLibraries)
-LOCAL_MODULE := libdvrcommon
-include $(BUILD_STATIC_LIBRARY)
-
-testFiles := \
- tests/numeric_test.cpp \
- tests/pose_test.cpp \
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libdvrcommon_test
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := \
- $(testFiles) \
-
-LOCAL_C_INCLUDES := \
- $(includeFiles) \
-
-LOCAL_SHARED_LIBRARIES := \
- $(sharedLibraries) \
-
-LOCAL_STATIC_LIBRARIES := \
- libgmock_main \
- libgmock \
- libgtest \
- $(staticLibraries) \
-
-include $(BUILD_NATIVE_TEST)
-
diff --git a/libs/vr/libdvrgraphics/Android.bp b/libs/vr/libdvrgraphics/Android.bp
new file mode 100644
index 0000000..73a8bf8
--- /dev/null
+++ b/libs/vr/libdvrgraphics/Android.bp
@@ -0,0 +1,45 @@
+
+
+sourceFiles = [
+ "blur.cpp",
+ "debug_text.cpp",
+ "egl_image.cpp",
+ "gpu_profiler.cpp",
+ "shader_program.cpp",
+ "timer_query.cpp",
+ "vr_gl_extensions.cpp",
+]
+
+localIncludeFiles = [
+ "include",
+]
+
+staticLibraries = [
+ "libbufferhub",
+ "libdvrcommon",
+ "libpdx_default_transport",
+]
+
+sharedLibraries = [
+ "libcutils",
+ "libbase",
+ "libEGL",
+ "libGLESv2",
+ "libpng",
+ "liblog",
+]
+
+cc_library_static {
+ srcs: sourceFiles,
+ cflags: [
+ "-DGL_GLEXT_PROTOTYPES",
+ "-DEGL_EGLEXT_PROTOTYPES",
+ ],
+ export_include_dirs: localIncludeFiles,
+ shared_libs: sharedLibraries,
+ static_libs: staticLibraries,
+ // Rather than add this header-file-only library to all users of libdvrgraphics,
+ // include it here.
+ whole_static_libs: ["libarect"],
+ name: "libdvrgraphics",
+}
diff --git a/libs/vr/libdvrgraphics/Android.mk b/libs/vr/libdvrgraphics/Android.mk
deleted file mode 100644
index b9e601c..0000000
--- a/libs/vr/libdvrgraphics/Android.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-sourceFiles := \
- blur.cpp \
- debug_text.cpp \
- egl_image.cpp \
- gpu_profiler.cpp \
- shader_program.cpp \
- timer_query.cpp \
- vr_gl_extensions.cpp \
-
-includeFiles := \
- $(LOCAL_PATH)/include
-
-staticLibraries := \
- libbufferhub \
- libdvrcommon \
- libpdx_default_transport \
-
-sharedLibraries := \
- libcutils \
- libbase \
- libpng
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(sourceFiles)
-LOCAL_C_INCLUDES := $(includeFiles)
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(includeFiles)
-LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
-LOCAL_STATIC_LIBRARIES := $(staticLibraries)
-# Rather than add this header-file-only library to all users of libdvrgraphics,
-# include it here.
-LOCAL_WHOLE_STATIC_LIBRARIES := libarect
-LOCAL_MODULE := libdvrgraphics
-include $(BUILD_STATIC_LIBRARY)
-
diff --git a/libs/vr/libeds/Android.bp b/libs/vr/libeds/Android.bp
new file mode 100644
index 0000000..187cbbf
--- /dev/null
+++ b/libs/vr/libeds/Android.bp
@@ -0,0 +1,88 @@
+// 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.
+
+sourceFiles = [
+ "eds.cpp",
+ "eds_mesh.cpp",
+ "composite_hmd.cpp",
+ "cpu_thread_pose_updater.cpp",
+ "display_metrics.cpp",
+ "distortion_renderer.cpp",
+ "lucid_metrics.cpp",
+ "lucid_pose_tracker.cpp",
+ "lookup_radial_distortion.cpp",
+ "polynomial_radial_distortion.cpp",
+]
+
+localIncludeFiles = [
+ "include",
+]
+
+sharedLibraries = [
+ "libbase",
+ "libcutils",
+ "liblog",
+ "libEGL",
+ "libGLESv1_CM",
+ "libGLESv2",
+ "libui",
+ "libutils",
+ "libvulkan",
+]
+
+staticLibraries = [
+ "libdisplay",
+ "libdvrcommon",
+ "libdvrgraphics",
+ "libvrsensor",
+ "libpdx_default_transport",
+]
+
+cc_library_static {
+ srcs: sourceFiles,
+ cflags: [
+ "-DGL_GLEXT_PROTOTYPES",
+ "-DEGL_EGLEXT_PROTOTYPES",
+ "-Wno-unused-parameter"],
+ // Enable debug options below to show GL errors and use gdb.
+ // + ["-UNDEBUG", "-DDEBUG", "-O0", "-g", ]
+ export_include_dirs: localIncludeFiles,
+ shared_libs: sharedLibraries,
+ static_libs: staticLibraries,
+ name: "libeds",
+}
+
+testFiles = ["tests/eds_app_tests.cpp"]
+
+cc_test {
+ name: "eds_app_tests",
+ tags: ["optional"],
+
+ srcs: testFiles,
+
+ shared_libs: [
+ "libhardware",
+ "libsync",
+ ] + sharedLibraries,
+
+ static_libs: [
+ "libgmock_main",
+ "libgmock",
+ "libeds",
+ ] + staticLibraries + [
+ "libbufferhub",
+ "libbufferhubqueue",
+ ],
+
+}
diff --git a/libs/vr/libeds/Android.mk b/libs/vr/libeds/Android.mk
deleted file mode 100644
index d2e6526..0000000
--- a/libs/vr/libeds/Android.mk
+++ /dev/null
@@ -1,88 +0,0 @@
-# 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.
-
-LOCAL_PATH := $(call my-dir)
-
-sourceFiles := \
- eds.cpp \
- eds_mesh.cpp \
- composite_hmd.cpp \
- cpu_thread_pose_updater.cpp \
- display_metrics.cpp \
- distortion_renderer.cpp \
- lucid_metrics.cpp \
- lucid_pose_tracker.cpp \
- lookup_radial_distortion.cpp \
- polynomial_radial_distortion.cpp
-
-includeFiles += \
- $(LOCAL_PATH)/include
-
-sharedLibraries := \
- libbase \
- libcutils \
- liblog \
- libEGL \
- libGLESv1_CM \
- libGLESv2 \
- libvulkan \
-
-staticLibraries := \
- libdisplay \
- libdvrcommon \
- libdvrgraphics \
- libsensor \
- libpdx_default_transport \
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(sourceFiles)
-LOCAL_C_INCLUDES := $(includeFiles)
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
-LOCAL_CFLAGS += -Wno-unused-parameter
-# Enable debug options below to show GL errors and use gdb.
-# LOCAL_CFLAGS += -UNDEBUG -DDEBUG -O0 -g
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(includeFiles)
-LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
-LOCAL_STATIC_LIBRARIES := $(staticLibraries)
-LOCAL_MODULE := libeds
-include $(BUILD_STATIC_LIBRARY)
-
-
-testFiles := \
- tests/eds_app_tests.cpp
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := eds_app_tests
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := \
- $(testFiles) \
-
-LOCAL_C_INCLUDES := \
- $(includeFiles) \
-
-LOCAL_SHARED_LIBRARIES := \
- libhardware \
- libsync \
- $(sharedLibraries) \
-
-LOCAL_STATIC_LIBRARIES := \
- libgmock_main \
- libgmock \
- libdisplay \
- libeds \
- libbufferhub \
- $(staticLibraries) \
-
-include $(BUILD_NATIVE_TEST)
diff --git a/libs/vr/libimageio/Android.bp b/libs/vr/libimageio/Android.bp
new file mode 100644
index 0000000..7dde075
--- /dev/null
+++ b/libs/vr/libimageio/Android.bp
@@ -0,0 +1,26 @@
+
+
+sourceFiles = [
+ "image_io.cpp",
+ "image_io_png.cpp",
+ "image_io_ppm.cpp",
+]
+
+includeFiles = ["include"]
+
+sharedLibraries = [
+ "libcutils",
+ "libpng",
+]
+
+cc_library_static {
+ srcs: sourceFiles,
+ export_include_dirs: includeFiles,
+ shared_libs: sharedLibraries,
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ ],
+ name: "libimageio",
+ tags: ["optional"],
+}
diff --git a/libs/vr/libimageio/Android.mk b/libs/vr/libimageio/Android.mk
deleted file mode 100644
index b3b88ac..0000000
--- a/libs/vr/libimageio/Android.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-sourceFiles := \
- image_io.cpp \
- image_io_png.cpp \
- image_io_ppm.cpp
-
-includeFiles := \
- $(LOCAL_PATH)/include
-
-sharedLibraries := \
- libcutils \
- libpng
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(sourceFiles)
-LOCAL_C_INCLUDES += $(includeFiles)
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(includeFiles)
-LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
-LOCAL_CFLAGS := -Wall -Wextra
-LOCAL_MODULE := libimageio
-LOCAL_MODULE_TAGS := optional
-include $(BUILD_STATIC_LIBRARY)
diff --git a/libs/vr/libpdx/private/pdx/rpc/function_traits.h b/libs/vr/libpdx/private/pdx/rpc/function_traits.h
index 5fdad72..7641b0a 100644
--- a/libs/vr/libpdx/private/pdx/rpc/function_traits.h
+++ b/libs/vr/libpdx/private/pdx/rpc/function_traits.h
@@ -43,6 +43,12 @@
SignatureType<ConditionalRewrite<Return_, ReturnType>(
ConditionalRewrite<Args_, Params>...)>;
+ template <template <typename> class Wrapper, typename ReturnType,
+ typename... Params>
+ using RewriteSignatureWrapReturn =
+ SignatureType<Wrapper<ConditionalRewrite<Return_, ReturnType>>(
+ ConditionalRewrite<Args_, Params>...)>;
+
template <typename ReturnType>
using RewriteReturn =
SignatureType<ConditionalRewrite<Return_, ReturnType>(Args_...)>;
diff --git a/libs/vr/libpdx/private/pdx/rpc/remote_method.h b/libs/vr/libpdx/private/pdx/rpc/remote_method.h
index 49bee40..e5c6616 100644
--- a/libs/vr/libpdx/private/pdx/rpc/remote_method.h
+++ b/libs/vr/libpdx/private/pdx/rpc/remote_method.h
@@ -10,6 +10,7 @@
#include <pdx/rpc/payload.h>
#include <pdx/rpc/remote_method_type.h>
#include <pdx/service.h>
+#include <pdx/status.h>
namespace android {
namespace pdx {
@@ -25,10 +26,9 @@
// Evaluates to true if the method type is <any>(Void), false otherwise.
template <typename RemoteMethodType>
using IsVoidMethod = typename std::integral_constant<
- bool,
- RemoteMethodType::Traits::Arity == 1 &&
- std::is_same<typename RemoteMethodType::Traits::template Arg<0>,
- Void>::value>;
+ bool, RemoteMethodType::Traits::Arity == 1 &&
+ std::is_same<typename RemoteMethodType::Traits::template Arg<0>,
+ Void>::value>;
// Utility to determine if a method is of type <any>(Void).
template <typename RemoteMethodType>
@@ -158,6 +158,25 @@
strerror(-ret));
}
+// Overload for Status<void> return types.
+template <typename RemoteMethodType>
+void RemoteMethodReturn(Message& message, const Status<void>& return_value) {
+ if (return_value)
+ RemoteMethodReturn<RemoteMethodType>(message, 0);
+ else
+ RemoteMethodError(message, return_value.error());
+}
+
+// Overload for Status<T> return types. This overload forwards the underlying
+// value or error within the Status<T>.
+template <typename RemoteMethodType, typename Return>
+void RemoteMethodReturn(Message& message, const Status<Return>& return_value) {
+ if (return_value)
+ RemoteMethodReturn<RemoteMethodType, Return>(message, return_value.get());
+ else
+ RemoteMethodError(message, return_value.error());
+}
+
// Dispatches a method by deserializing arguments from the given Message, with
// compile-time interface check. Overload for void return types.
template <typename RemoteMethodType, typename Class, typename... Args,
@@ -274,7 +293,9 @@
void DispatchRemoteMethod(
Class& instance, ChannelHandle<Mode> (Class::*method)(Message&, Args...),
Message& message, std::size_t max_capacity = InitialBufferCapacity) {
- using Signature = typename RemoteMethodType::template RewriteArgs<Args...>;
+ using Signature =
+ typename RemoteMethodType::template RewriteSignature<ChannelHandle<Mode>,
+ Args...>;
rpc::ServicePayload<ReceiveBuffer> payload(message);
payload.Resize(max_capacity);
@@ -339,6 +360,46 @@
RemoteMethodReturn<RemoteMethodType>(message, return_value);
}
+// Dispatches a method by deserializing arguments from the given Message, with
+// compile-time interface signature check. Overload for Status<T> return types.
+template <typename RemoteMethodType, typename Class, typename Return,
+ typename... Args, typename = EnableIfNotVoidMethod<RemoteMethodType>>
+void DispatchRemoteMethod(Class& instance,
+ Status<Return> (Class::*method)(Message&, Args...),
+ Message& message,
+ std::size_t max_capacity = InitialBufferCapacity) {
+ using Signature =
+ typename RemoteMethodType::template RewriteSignature<Return, Args...>;
+ using InvokeSignature =
+ typename RemoteMethodType::template RewriteSignatureWrapReturn<
+ Status, Return, Args...>;
+ rpc::ServicePayload<ReceiveBuffer> payload(message);
+ payload.Resize(max_capacity);
+
+ auto size = message.Read(payload.Data(), payload.Size());
+ if (size < 0) {
+ RemoteMethodError(message, -size);
+ return;
+ }
+
+ payload.Resize(size);
+
+ ErrorType error;
+ auto decoder = MakeArgumentDecoder<Signature>(&payload);
+ auto arguments = decoder.DecodeArguments(&error);
+ if (error) {
+ RemoteMethodError(message, EIO);
+ return;
+ }
+
+ auto return_value = UnpackArguments<Class, InvokeSignature>(
+ instance, method, message, arguments)
+ .Invoke();
+ // Return the value to the caller unless the message was moved.
+ if (message)
+ RemoteMethodReturn<RemoteMethodType>(message, return_value);
+}
+
#ifdef __clang__
// Overloads to handle Void argument type without exploding clang.
@@ -398,6 +459,18 @@
if (message)
RemoteMethodReturn<RemoteMethodType>(message, return_value);
}
+
+// Overload for Status<T> return type.
+template <typename RemoteMethodType, typename Class, typename Return,
+ typename = EnableIfVoidMethod<RemoteMethodType>>
+void DispatchRemoteMethod(Class& instance,
+ Status<Return> (Class::*method)(Message&),
+ Message& message) {
+ auto return_value = (instance.*method)(message);
+ // Return the value to the caller unless the message was moved.
+ if (message)
+ RemoteMethodReturn<RemoteMethodType>(message, return_value);
+}
#endif
} // namespace rpc
diff --git a/libs/vr/libpdx/private/pdx/rpc/remote_method_type.h b/libs/vr/libpdx/private/pdx/rpc/remote_method_type.h
index de9a3cc..cf9a189 100644
--- a/libs/vr/libpdx/private/pdx/rpc/remote_method_type.h
+++ b/libs/vr/libpdx/private/pdx/rpc/remote_method_type.h
@@ -31,6 +31,12 @@
using RewriteSignature =
typename Traits::template RewriteSignature<ReturnType, Params...>;
+ template <template <typename> class Wrapper, typename ReturnType,
+ typename... Params>
+ using RewriteSignatureWrapReturn =
+ typename Traits::template RewriteSignatureWrapReturn<Wrapper, ReturnType,
+ Params...>;
+
template <typename ReturnType>
using RewriteReturn = typename Traits::template RewriteReturn<ReturnType>;
};
diff --git a/libs/vr/libpdx/thread_local_buffer_tests.cpp b/libs/vr/libpdx/thread_local_buffer_tests.cpp
index c6a7b0b..1747d79 100644
--- a/libs/vr/libpdx/thread_local_buffer_tests.cpp
+++ b/libs/vr/libpdx/thread_local_buffer_tests.cpp
@@ -89,8 +89,9 @@
EXPECT_NE(id1, id2);
}
+// TODO(b/36456321): Fix this and enable it again.
// Tests that thread-local buffers are allocated at the first buffer request.
-TEST(ThreadLocalBufferTest, InitialValue) {
+TEST(ThreadLocalBufferTest, DISABLED_InitialValue) {
struct TypeTagX;
using SendSlotX = ThreadLocalSlot<TypeTagX, kSendBufferIndex>;
diff --git a/libs/vr/libpdx_uds/remote_method_tests.cpp b/libs/vr/libpdx_uds/remote_method_tests.cpp
index 299910c..9050500 100644
--- a/libs/vr/libpdx_uds/remote_method_tests.cpp
+++ b/libs/vr/libpdx_uds/remote_method_tests.cpp
@@ -23,6 +23,7 @@
using android::pdx::BorrowedHandle;
using android::pdx::Channel;
using android::pdx::ClientBase;
+using android::pdx::ErrorStatus;
using android::pdx::LocalChannelHandle;
using android::pdx::LocalHandle;
using android::pdx::Message;
@@ -36,6 +37,20 @@
namespace {
+std::string Rot13(const std::string& s) {
+ std::string text = s;
+ std::transform(std::begin(text), std::end(text), std::begin(text),
+ [](char c) -> char {
+ if (!std::isalpha(c)) {
+ return c;
+ } else {
+ const char pivot = std::isupper(c) ? 'A' : 'a';
+ return (c - pivot + 13) % 26 + pivot;
+ }
+ });
+ return text;
+}
+
// Defines a serializable user type that may be transferred between client and
// service.
struct TestType {
@@ -134,6 +149,7 @@
kOpOpenFiles,
kOpReadFile,
kOpPushChannel,
+ kOpPositive,
};
// Methods.
@@ -161,10 +177,11 @@
std::pair<int, BufferWrapper<std::uint8_t*>>(
const std::string&, int, std::size_t));
PDX_REMOTE_METHOD(PushChannel, kOpPushChannel, LocalChannelHandle(Void));
+ PDX_REMOTE_METHOD(Positive, kOpPositive, void(int));
PDX_REMOTE_API(API, Add, Foo, Concatenate, SumVector, StringLength,
SendTestType, SendVector, Rot13, NoArgs, SendFile, GetFile,
- GetTestFdType, OpenFiles, PushChannel);
+ GetTestFdType, OpenFiles, PushChannel, Positive);
};
constexpr char TestInterface::kClientPath[];
@@ -301,6 +318,11 @@
return status ? 0 : -status.error();
}
+ bool Positive(int test_value) {
+ auto status = InvokeRemoteMethod<TestInterface::Positive>(test_value);
+ return status.ok();
+ }
+
int GetFd() const { return event_fd(); }
private:
@@ -397,6 +419,11 @@
*this, &TestService::OnPushChannel, message);
return 0;
+ case TestInterface::Positive::Opcode:
+ DispatchRemoteMethod<TestInterface::Positive>(
+ *this, &TestService::OnPositive, message);
+ return 0;
+
default:
return Service::DefaultHandleMessage(message);
}
@@ -438,18 +465,8 @@
return return_value;
}
- std::string OnRot13(Message&, const std::string& s) {
- std::string text = s;
- std::transform(std::begin(text), std::end(text), std::begin(text),
- [](char c) -> char {
- if (!std::isalpha(c)) {
- return c;
- } else {
- const char pivot = std::isupper(c) ? 'A' : 'a';
- return (c - pivot + 13) % 26 + pivot;
- }
- });
- return text;
+ Status<std::string> OnRot13(Message&, const std::string& s) {
+ return {Rot13(s)};
}
int OnNoArgs(Message&) { return 1; }
@@ -514,6 +531,13 @@
return status.take();
}
+ Status<void> OnPositive(Message& /*message*/, int test_value) {
+ if (test_value >= 0)
+ return {};
+ else
+ return ErrorStatus(EINVAL);
+ }
+
TestService(const TestService&) = delete;
void operator=(const TestService&) = delete;
};
@@ -575,6 +599,10 @@
const auto cat = client->Concatenate("This is a string", ", that it is.");
EXPECT_EQ("This is a string, that it is.", cat);
+ std::string alphabet = "abcdefghijklmnopqrstuvwxyz";
+ const auto rot13_alphabet = client->Rot13(alphabet);
+ EXPECT_EQ(Rot13(alphabet), rot13_alphabet);
+
const auto length = client->Foo(10, "123");
EXPECT_EQ(13, length);
@@ -677,6 +705,21 @@
EXPECT_GE(35, sum);
}
+TEST_F(RemoteMethodTest, Positive) {
+ // Create a test service and add it to the dispatcher.
+ auto service = TestService::Create();
+ ASSERT_NE(nullptr, service);
+ ASSERT_EQ(0, dispatcher_->AddService(service));
+
+ // Create a client to service.
+ auto client = TestClient::Create();
+ ASSERT_NE(nullptr, client);
+
+ ASSERT_TRUE(client->Positive(0));
+ ASSERT_TRUE(client->Positive(1));
+ ASSERT_FALSE(client->Positive(-1));
+}
+
TEST_F(RemoteMethodTest, AggregateLocalHandle) {
// Create a test service and add it to the dispatcher.
auto service = TestService::Create();
diff --git a/libs/vr/libpdx_uds/service_framework_tests.cpp b/libs/vr/libpdx_uds/service_framework_tests.cpp
index 8891600..9e31e82 100644
--- a/libs/vr/libpdx_uds/service_framework_tests.cpp
+++ b/libs/vr/libpdx_uds/service_framework_tests.cpp
@@ -26,6 +26,7 @@
using android::pdx::Channel;
using android::pdx::ChannelReference;
using android::pdx::ClientBase;
+using android::pdx::ErrorStatus;
using android::pdx::LocalChannelHandle;
using android::pdx::LocalHandle;
using android::pdx::Message;
@@ -379,6 +380,14 @@
data_array.size() * sizeof(int), nullptr, 0));
}
+ Status<int> GetEventMask(int events) {
+ if (auto* client_channel = GetChannel()) {
+ return client_channel->GetEventMask(events);
+ } else {
+ return ErrorStatus(EINVAL);
+ }
+ }
+
using ClientBase<TestClient>::event_fd;
enum : size_t { kMaxPayload = MAX_IMPULSE_LENGTH };
@@ -634,7 +643,9 @@
count = epoll_wait(client->event_fd(), &event, 1, -1);
ASSERT_EQ(1, count);
- ASSERT_TRUE((EPOLLHUP & event.events) != 0);
+ auto event_status = client->GetEventMask(event.events);
+ ASSERT_TRUE(event_status.ok());
+ ASSERT_TRUE((EPOLLHUP & event_status.get()) != 0);
}
TEST_F(ServiceFrameworkTest, LargeDataSum) {
diff --git a/libs/vr/libperformance/Android.bp b/libs/vr/libperformance/Android.bp
new file mode 100644
index 0000000..364873d
--- /dev/null
+++ b/libs/vr/libperformance/Android.bp
@@ -0,0 +1,41 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+sourceFiles = [
+ "performance_client.cpp",
+ "performance_rpc.cpp",
+]
+
+includeFiles = [ "include" ]
+
+staticLibraries = ["libpdx_default_transport"]
+
+sharedLibraries = [
+ "libbase",
+ "libcutils",
+ "liblog",
+ "libutils",
+]
+
+cc_library {
+ srcs: sourceFiles,
+ cflags: [
+ "-DLOG_TAG=\"libperformance\"",
+ "-DTRACE=0"
+ ],
+ export_include_dirs: includeFiles,
+ static_libs: staticLibraries,
+ shared_libs: sharedLibraries,
+ name: "libperformance",
+}
diff --git a/libs/vr/libperformance/Android.mk b/libs/vr/libperformance/Android.mk
deleted file mode 100644
index aaacb1a..0000000
--- a/libs/vr/libperformance/Android.mk
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-sourceFiles := \
- performance_client.cpp \
- performance_rpc.cpp
-
-includeFiles := \
- $(LOCAL_PATH)/include
-
-staticLibraries := \
- libpdx_default_transport \
-
-sharedLibraries := \
- libbase \
- libcutils \
- liblog \
- libutils
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(sourceFiles)
-LOCAL_C_INCLUDES := $(includeFiles)
-LOCAL_CFLAGS := -DLOG_TAG=\"libperformance\"
-LOCAL_CFLAGS += -DTRACE=0
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(includeFiles)
-LOCAL_STATIC_LIBRARIES := $(staticLibraries)
-LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
-LOCAL_MODULE := libperformance
-include $(BUILD_STATIC_LIBRARY)
-
diff --git a/libs/vr/libposepredictor/Android.bp b/libs/vr/libposepredictor/Android.bp
new file mode 100644
index 0000000..2f1d2f5
--- /dev/null
+++ b/libs/vr/libposepredictor/Android.bp
@@ -0,0 +1,58 @@
+// Copyright (C) 2008 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.
+
+sourceFiles = [
+ "predictor.cpp",
+ "buffered_predictor.cpp",
+ "linear_predictor.cpp",
+ "polynomial_predictor.cpp",
+ "dvr_pose_predictor.cpp",
+]
+
+includeFiles = [
+ "include",
+]
+
+staticLibraries = ["libvrsensor"]
+
+sharedLibraries = []
+
+headerLibraries = [ "libeigen" ]
+
+cc_library {
+ srcs: sourceFiles,
+ cflags: [
+ "-DLOG_TAG=\"libposepredictor\"",
+ "-DTRACE=0",
+ ],
+ export_include_dirs: includeFiles,
+ static_libs: staticLibraries,
+ shared_libs: sharedLibraries,
+ header_libs: headerLibraries,
+ export_header_lib_headers: headerLibraries,
+ name: "libposepredictor",
+}
+
+cc_test {
+ tags: ["optional"],
+ srcs: [
+ "predictor_tests.cpp",
+ "linear_predictor_tests.cpp",
+ "polynomial_predictor_tests.cpp",
+ ],
+
+ static_libs: ["libposepredictor"] + staticLibraries,
+ shared_libs: sharedLibraries,
+ name: "pose_predictor_tests",
+}
diff --git a/libs/vr/libposepredictor/Android.mk b/libs/vr/libposepredictor/Android.mk
deleted file mode 100755
index 2217819..0000000
--- a/libs/vr/libposepredictor/Android.mk
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright (C) 2008 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-sourceFiles := \
- predictor.cpp \
- buffered_predictor.cpp \
- linear_predictor.cpp \
- polynomial_predictor.cpp \
- dvr_pose_predictor.cpp \
-
-includeFiles := \
- $(LOCAL_PATH)/include \
- external/eigen \
-
-staticLibraries := \
- libsensor \
-
-sharedLibraries := \
-
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(sourceFiles)
-LOCAL_C_INCLUDES := $(includeFiles)
-LOCAL_CFLAGS := -DLOG_TAG=\"libposepredictor\"
-LOCAL_CFLAGS += -DTRACE=0
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(includeFiles)
-LOCAL_STATIC_LIBRARIES := $(staticLibraries)
-LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
-LOCAL_MODULE := libposepredictor
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := optional
-LOCAL_SRC_FILES := \
- predictor_tests.cpp \
- linear_predictor_tests.cpp \
- polynomial_predictor_tests.cpp \
-
-LOCAL_STATIC_LIBRARIES := libposepredictor $(staticLibraries)
-LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
-LOCAL_MODULE := pose_predictor_tests
-include $(BUILD_NATIVE_TEST)
diff --git a/libs/vr/libsensor/Android.mk b/libs/vr/libsensor/Android.mk
deleted file mode 100644
index 8c7ad43..0000000
--- a/libs/vr/libsensor/Android.mk
+++ /dev/null
@@ -1,76 +0,0 @@
-# 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.
-
-LOCAL_PATH := $(call my-dir)
-
-sourceFiles := \
- pose_client.cpp \
- sensor_client.cpp
-
-includeFiles := \
- $(LOCAL_PATH)/include
-
-staticLibraries := \
- libbufferhub \
- libdvrcommon \
- libpdx_default_transport \
-
-sharedLibraries := \
- libbase \
- libcutils \
- libhardware \
- liblog \
- libutils \
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(sourceFiles)
-LOCAL_C_INCLUDES := $(includeFiles)
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(includeFiles)
-LOCAL_STATIC_LIBRARIES := $(staticLibraries)
-LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
-LOCAL_MODULE := libsensor
-include $(BUILD_STATIC_LIBRARY)
-
-
-testFiles := \
- tests/sensor_app_tests.cpp
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := sensor_app_tests
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := \
- $(testFiles) \
-
-LOCAL_C_INCLUDES := \
- $(includeFiles) \
-
-LOCAL_SHARED_LIBRARIES := \
- libEGL \
- libGLESv1_CM \
- libGLESv2 \
- libvulkan \
- libsync \
- $(sharedLibraries) \
-
-LOCAL_STATIC_LIBRARIES := \
- libgmock_main \
- libgmock \
- libdisplay \
- libeds \
- libsensor \
- libdvrgraphics \
- $(staticLibraries) \
-
-include $(BUILD_NATIVE_TEST)
diff --git a/libs/vr/libvr_manager/Android.bp b/libs/vr/libvr_manager/Android.bp
new file mode 100644
index 0000000..8784877
--- /dev/null
+++ b/libs/vr/libvr_manager/Android.bp
@@ -0,0 +1,36 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+exported_include_dirs = [ "include" ]
+
+include_dirs = ["frameworks/native/include/vr/vr_manager"]
+
+src_files = [
+ "vr_manager.cpp",
+ "trusted_uids.cpp",
+]
+
+static_libs = [
+ "libutils",
+ "libbinder",
+]
+
+cc_library_static {
+ srcs: src_files,
+ include_dirs: include_dirs,
+ export_include_dirs: exported_include_dirs,
+ cflags: ["-Wall", "-Werror", "-Wunused", "-Wunreachable-code"],
+ static_libs: static_libs,
+ name: "libvr_manager",
+}
diff --git a/libs/vr/libvr_manager/Android.mk b/libs/vr/libvr_manager/Android.mk
deleted file mode 100644
index e9987f7..0000000
--- a/libs/vr/libvr_manager/Android.mk
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-exported_include_dirs := \
- $(LOCAL_PATH)/include
-
-include_dirs := \
- frameworks/native/include/vr/vr_manager \
- $(exported_include_dirs)
-
-src_files := \
- vr_manager.cpp \
- trusted_uids.cpp
-
-static_libs := \
- libutils \
- libbinder \
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(src_files)
-LOCAL_C_INCLUDES := $(include_dirs)
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(exported_include_dirs)
-LOCAL_CFLAGS += -Wall
-LOCAL_CFLAGS += -Werror
-LOCAL_CFLAGS += -Wunused
-LOCAL_CFLAGS += -Wunreachable-code
-LOCAL_STATIC_LIBRARIES := $(static_libs)
-LOCAL_MODULE := libvr_manager
-include $(BUILD_STATIC_LIBRARY)
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
new file mode 100644
index 0000000..3f79a7b
--- /dev/null
+++ b/libs/vr/libvrflinger/Android.bp
@@ -0,0 +1,86 @@
+// Copyright (C) 2008 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.
+
+sourceFiles = [
+ "acquired_buffer.cpp",
+ "compositor.cpp",
+ "debug_hud_data.cpp",
+ "debug_hud_view.cpp",
+ "display_manager_service.cpp",
+ "display_service.cpp",
+ "display_surface.cpp",
+ "hardware_composer.cpp",
+ "screenshot_service.cpp",
+ "surface_channel.cpp",
+ "video_compositor.cpp",
+ "video_mesh_surface.cpp",
+ "vr_flinger.cpp",
+ "vsync_service.cpp",
+]
+
+includeFiles = [ "include" ]
+
+staticLibraries = [
+ "libsurfaceflingerincludes",
+ "libhwcomposer-command-buffer",
+ "libbufferhub",
+ "libbufferhubqueue",
+ "libeds",
+ "libdisplay",
+ "libdvrcommon",
+ "libdvrgraphics",
+ "libperformance",
+ "libvrsensor",
+ "libpdx_default_transport",
+ "libvr_manager",
+]
+
+sharedLibraries = [
+ "android.dvr.composer@1.0",
+ "android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.composer@2.1",
+ "libbinder",
+ "libbase",
+ "libcutils",
+ "liblog",
+ "libhardware",
+ "libnativewindow",
+ "libutils",
+ "libEGL",
+ "libGLESv1_CM",
+ "libGLESv2",
+ "libvulkan",
+ "libui",
+ "libgui",
+ "libsync",
+ "libhidlbase",
+ "libhidltransport",
+ "libfmq",
+]
+
+cc_library_static {
+ srcs: sourceFiles,
+ export_include_dirs: includeFiles,
+
+ cflags: [
+ "-DLOG_TAG=\"vr_flinger\"",
+ "-DTRACE=0",
+ "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
+ "-DGL_GLEXT_PROTOTYPES",
+ "-DEGL_EGLEXT_PROTOTYPES",
+ ],
+ shared_libs: sharedLibraries,
+ whole_static_libs: staticLibraries,
+ name: "libvrflinger",
+}
diff --git a/libs/vr/libvrflinger/Android.mk b/libs/vr/libvrflinger/Android.mk
deleted file mode 100644
index 3450788..0000000
--- a/libs/vr/libvrflinger/Android.mk
+++ /dev/null
@@ -1,84 +0,0 @@
-# Copyright (C) 2008 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-sourceFiles := \
- acquired_buffer.cpp \
- compositor.cpp \
- debug_hud_data.cpp \
- debug_hud_view.cpp \
- display_manager_service.cpp \
- display_service.cpp \
- display_surface.cpp \
- epoll_event_dispatcher.cpp \
- hardware_composer.cpp \
- screenshot_service.cpp \
- surface_channel.cpp \
- video_compositor.cpp \
- video_mesh_surface.cpp \
- vr_flinger.cpp \
- vsync_service.cpp
-
-includeFiles := $(LOCAL_PATH)/include
-
-staticLibraries := \
- libsurfaceflingerincludes \
- libhwcomposer-command-buffer \
- libbufferhub \
- libbufferhubqueue \
- libeds \
- libdisplay \
- libdvrcommon \
- libdvrgraphics \
- libperformance \
- libsensor \
- libpdx_default_transport \
- libvr_manager \
-
-sharedLibraries := \
- android.dvr.composer@1.0 \
- android.hardware.graphics.allocator@2.0 \
- android.hardware.graphics.composer@2.1 \
- libbinder \
- libbase \
- libcutils \
- liblog \
- libhardware \
- libnativewindow \
- libutils \
- libEGL \
- libGLESv1_CM \
- libGLESv2 \
- libvulkan \
- libui \
- libgui \
- libsync \
- libhidlbase \
- libhidltransport \
- libfmq \
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(sourceFiles)
-LOCAL_C_INCLUDES := $(includeFiles)
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(includeFiles)
-
-LOCAL_CFLAGS += -DLOG_TAG=\"vr_flinger\"
-LOCAL_CFLAGS += -DTRACE=0
-LOCAL_CFLAGS += -DATRACE_TAG=ATRACE_TAG_GRAPHICS
-LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
-LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
-LOCAL_WHOLE_STATIC_LIBRARIES := $(staticLibraries)
-LOCAL_MODULE := libvrflinger
-include $(BUILD_STATIC_LIBRARY)
diff --git a/libs/vr/libvrflinger/display_manager_service.cpp b/libs/vr/libvrflinger/display_manager_service.cpp
index 6df1642..e07901d 100644
--- a/libs/vr/libvrflinger/display_manager_service.cpp
+++ b/libs/vr/libvrflinger/display_manager_service.cpp
@@ -82,6 +82,11 @@
*this, &DisplayManagerService::OnUpdateSurfaces, message);
return 0;
+ case DisplayManagerRPC::SetupPoseBuffer::Opcode:
+ DispatchRemoteMethod<DisplayManagerRPC::SetupPoseBuffer>(
+ *this, &DisplayManagerService::OnSetupPoseBuffer, message);
+ return 0;
+
default:
return Service::DefaultHandleMessage(message);
}
@@ -91,30 +96,31 @@
pdx::Message& /*message*/) {
std::vector<DisplaySurfaceInfo> items;
- display_service_->ForEachDisplaySurface([&items](
- const std::shared_ptr<DisplaySurface>& surface) mutable {
- DisplaySurfaceInfo item;
+ display_service_->ForEachDisplaySurface(
+ [&items](const std::shared_ptr<DisplaySurface>& surface) mutable {
+ DisplaySurfaceInfo item;
- item.surface_id = surface->surface_id();
- item.process_id = surface->process_id();
- item.type = surface->type();
- item.flags = 0; // TODO(eieio)
- item.client_attributes = DisplaySurfaceAttributes{
- {DisplaySurfaceAttributeEnum::Visible,
- DisplaySurfaceAttributeValue{surface->client_visible()}},
- {DisplaySurfaceAttributeEnum::ZOrder,
- DisplaySurfaceAttributeValue{surface->client_z_order()}},
- {DisplaySurfaceAttributeEnum::Blur, DisplaySurfaceAttributeValue{0.f}}};
- item.manager_attributes = DisplaySurfaceAttributes{
- {DisplaySurfaceAttributeEnum::Visible,
- DisplaySurfaceAttributeValue{surface->manager_visible()}},
- {DisplaySurfaceAttributeEnum::ZOrder,
- DisplaySurfaceAttributeValue{surface->manager_z_order()}},
- {DisplaySurfaceAttributeEnum::Blur,
- DisplaySurfaceAttributeValue{surface->manager_blur()}}};
+ item.surface_id = surface->surface_id();
+ item.process_id = surface->process_id();
+ item.type = surface->type();
+ item.flags = 0; // TODO(eieio)
+ item.client_attributes = DisplaySurfaceAttributes{
+ {DisplaySurfaceAttributeEnum::Visible,
+ DisplaySurfaceAttributeValue{surface->client_visible()}},
+ {DisplaySurfaceAttributeEnum::ZOrder,
+ DisplaySurfaceAttributeValue{surface->client_z_order()}},
+ {DisplaySurfaceAttributeEnum::Blur,
+ DisplaySurfaceAttributeValue{0.f}}};
+ item.manager_attributes = DisplaySurfaceAttributes{
+ {DisplaySurfaceAttributeEnum::Visible,
+ DisplaySurfaceAttributeValue{surface->manager_visible()}},
+ {DisplaySurfaceAttributeEnum::ZOrder,
+ DisplaySurfaceAttributeValue{surface->manager_z_order()}},
+ {DisplaySurfaceAttributeEnum::Blur,
+ DisplaySurfaceAttributeValue{surface->manager_blur()}}};
- items.push_back(item);
- });
+ items.push_back(item);
+ });
// The fact that we're in the message handler implies that display_manager_ is
// not nullptr. No check required, unless this service becomes multi-threaded.
@@ -182,6 +188,11 @@
return 0;
}
+pdx::BorrowedChannelHandle DisplayManagerService::OnSetupPoseBuffer(
+ pdx::Message& message, size_t extended_region_size, int usage) {
+ return display_service_->SetupPoseBuffer(extended_region_size, usage);
+}
+
void DisplayManagerService::OnDisplaySurfaceChange() {
if (display_manager_) {
display_manager_->SetNotificationsPending(true);
diff --git a/libs/vr/libvrflinger/display_manager_service.h b/libs/vr/libvrflinger/display_manager_service.h
index 3f83c7d..19098c2 100644
--- a/libs/vr/libvrflinger/display_manager_service.h
+++ b/libs/vr/libvrflinger/display_manager_service.h
@@ -54,6 +54,10 @@
int OnUpdateSurfaces(pdx::Message& message,
const std::map<int, DisplaySurfaceAttributes>& updates);
+ pdx::BorrowedChannelHandle OnSetupPoseBuffer(pdx::Message& message,
+ size_t extended_region_size,
+ int usage);
+
// Called by the display service to indicate changes to display surfaces that
// the display manager should evaluate.
void OnDisplaySurfaceChange();
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index bb70c5c..e3d7564 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -18,6 +18,15 @@
using android::pdx::rpc::DispatchRemoteMethod;
using android::pdx::rpc::WrapBuffer;
+namespace {
+
+constexpr char kPersistentPoseBufferName[] = "DvrPersistentPoseBuffer";
+const int kPersistentPoseBufferUserId = 0;
+const int kPersistentPoseBufferGroupId = 0;
+const size_t kTimingDataSizeOffset = 128;
+
+} // anonymous namespace
+
namespace android {
namespace dvr {
@@ -89,8 +98,13 @@
*this, &DisplayService::OnSetViewerParams, message);
return 0;
+ case DisplayRPC::GetPoseBuffer::Opcode:
+ DispatchRemoteMethod<DisplayRPC::GetPoseBuffer>(
+ *this, &DisplayService::OnGetPoseBuffer, message);
+ return 0;
+
// Direct the surface specific messages to the surface instance.
- case DisplayRPC::AllocateBuffer::Opcode:
+ case DisplayRPC::CreateBufferQueue::Opcode:
case DisplayRPC::SetAttributes::Opcode:
case DisplayRPC::GetMetadataBuffer::Opcode:
case DisplayRPC::CreateVideoMeshSurface::Opcode:
@@ -254,6 +268,15 @@
compositor->UpdateHeadMountMetrics(head_mount_metrics);
}
+pdx::LocalChannelHandle DisplayService::OnGetPoseBuffer(pdx::Message& message) {
+ if (pose_buffer_) {
+ return pose_buffer_->CreateConsumer().take();
+ }
+
+ pdx::rpc::RemoteMethodError(message, EAGAIN);
+ return {};
+}
+
// Calls the message handler for the DisplaySurface associated with this
// channel.
int DisplayService::HandleSurfaceMessage(pdx::Message& message) {
@@ -324,6 +347,18 @@
return hardware_composer_.SetDisplaySurfaces(std::move(visible_surfaces));
}
+pdx::BorrowedChannelHandle DisplayService::SetupPoseBuffer(
+ size_t extended_region_size, int usage) {
+ if (!pose_buffer_) {
+ pose_buffer_ = BufferProducer::Create(
+ kPersistentPoseBufferName, kPersistentPoseBufferUserId,
+ kPersistentPoseBufferGroupId, usage,
+ extended_region_size + kTimingDataSizeOffset);
+ }
+
+ return pose_buffer_->GetChannelHandle().Borrow();
+}
+
void DisplayService::OnHardwareComposerRefresh() {
hardware_composer_.OnHardwareComposerRefresh();
}
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index b207e4d..a2b3ed5 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -14,7 +14,6 @@
#include "acquired_buffer.h"
#include "display_surface.h"
-#include "epoll_event_dispatcher.h"
#include "hardware_composer.h"
namespace android {
@@ -39,6 +38,9 @@
// any change to client/manager attributes that affect visibility or z order.
int UpdateActiveDisplaySurfaces();
+ pdx::BorrowedChannelHandle SetupPoseBuffer(size_t extended_region_size,
+ int usage);
+
template <class A>
void ForEachDisplaySurface(A action) const {
ForEachChannel([action](const ChannelIterator::value_type& pair) mutable {
@@ -81,14 +83,16 @@
DisplayService(android::Hwc2::Composer* hidl);
SystemDisplayMetrics OnGetMetrics(pdx::Message& message);
- int OnCreateSurface(pdx::Message& message, int width, int height,
- int format, int usage, DisplaySurfaceFlags flags);
+ int OnCreateSurface(pdx::Message& message, int width, int height, int format,
+ int usage, DisplaySurfaceFlags flags);
DisplayRPC::ByteBuffer OnGetEdsCapture(pdx::Message& message);
int OnEnterVrMode(pdx::Message& message);
int OnExitVrMode(pdx::Message& message);
- void OnSetViewerParams(pdx::Message& message, const ViewerParams& view_params);
+ void OnSetViewerParams(pdx::Message& message,
+ const ViewerParams& view_params);
+ pdx::LocalChannelHandle OnGetPoseBuffer(pdx::Message& message);
// Called by DisplaySurface to signal that a surface property has changed and
// the display manager should be notified.
@@ -99,9 +103,10 @@
DisplayService(const DisplayService&) = delete;
void operator=(const DisplayService&) = delete;
- EpollEventDispatcher dispatcher_;
HardwareComposer hardware_composer_;
DisplayConfigurationUpdateNotifier update_notifier_;
+
+ std::unique_ptr<BufferProducer> pose_buffer_;
};
} // namespace dvr
diff --git a/libs/vr/libvrflinger/display_surface.cpp b/libs/vr/libvrflinger/display_surface.cpp
index d427ea6..66808ca 100644
--- a/libs/vr/libvrflinger/display_surface.cpp
+++ b/libs/vr/libvrflinger/display_surface.cpp
@@ -26,7 +26,7 @@
: SurfaceChannel(service, surface_id, SurfaceTypeEnum::Normal,
sizeof(DisplaySurfaceMetadata)),
process_id_(process_id),
- posted_buffers_(kMaxPostedBuffers),
+ acquired_buffers_(kMaxPostedBuffers),
video_mesh_surfaces_updated_(false),
width_(width),
height_(height),
@@ -40,7 +40,6 @@
manager_visible_(false),
manager_z_order_(0),
manager_blur_(0.0f),
- allocated_buffer_index_(0),
layer_order_(0) {}
DisplaySurface::~DisplaySurface() {
@@ -84,71 +83,107 @@
client_blur_behind_ = blur_behind;
}
+void DisplaySurface::DequeueBuffersLocked() {
+ if (consumer_queue_ == nullptr) {
+ ALOGE(
+ "DisplaySurface::DequeueBuffersLocked: Consumer queue is not "
+ "initialized.");
+ return;
+ }
+
+ size_t slot;
+ uint64_t sequence;
+ while (true) {
+ LocalHandle acquire_fence;
+ auto buffer_consumer =
+ consumer_queue_->Dequeue(0, &slot, &sequence, &acquire_fence);
+ if (!buffer_consumer) {
+ ALOGD_IF(TRACE,
+ "DisplaySurface::DequeueBuffersLocked: We have dequeued all "
+ "available buffers.");
+ return;
+ }
+
+ if (!IsVisible()) {
+ ATRACE_NAME("DropFrameOnInvisibleSurface");
+ ALOGD_IF(TRACE,
+ "DisplaySurface::DequeueBuffersLocked: Discarding buffer_id=%d "
+ "on invisible surface.",
+ buffer_consumer->id());
+ buffer_consumer->Discard();
+ continue;
+ }
+
+ if (acquired_buffers_.IsFull()) {
+ ALOGE(
+ "DisplaySurface::DequeueBuffersLocked: Posted buffers full, "
+ "overwriting.");
+ acquired_buffers_.PopBack();
+ }
+
+ acquired_buffers_.Append(
+ AcquiredBuffer(buffer_consumer, std::move(acquire_fence), sequence));
+ }
+}
+
+AcquiredBuffer DisplaySurface::AcquireCurrentBuffer() {
+ std::lock_guard<std::mutex> autolock(lock_);
+ DequeueBuffersLocked();
+
+ if (acquired_buffers_.IsEmpty()) {
+ ALOGE(
+ "DisplaySurface::AcquireCurrentBuffer: attempt to acquire buffer when "
+ "none are posted.");
+ return AcquiredBuffer();
+ }
+ AcquiredBuffer buffer = std::move(acquired_buffers_.Front());
+ acquired_buffers_.PopFront();
+ ALOGD_IF(TRACE, "DisplaySurface::AcquireCurrentBuffer: buffer: %p",
+ buffer.buffer().get());
+ return buffer;
+}
+
AcquiredBuffer DisplaySurface::AcquireNewestAvailableBuffer(
AcquiredBuffer* skipped_buffer) {
std::lock_guard<std::mutex> autolock(lock_);
+ DequeueBuffersLocked();
+
AcquiredBuffer buffer;
int frames = 0;
// Basic latency stopgap for when the application misses a frame:
// If the application recovers on the 2nd or 3rd (etc) frame after
// missing, this code will skip frames to catch up by checking if
// the next frame is also available.
- while (!posted_buffers_.IsEmpty() && posted_buffers_.Front().IsAvailable()) {
+ while (!acquired_buffers_.IsEmpty() &&
+ acquired_buffers_.Front().IsAvailable()) {
// Capture the skipped buffer into the result parameter.
// Note that this API only supports skipping one buffer per vsync.
if (frames > 0 && skipped_buffer)
*skipped_buffer = std::move(buffer);
++frames;
- buffer = std::move(posted_buffers_.Front());
- posted_buffers_.PopFront();
+ buffer = std::move(acquired_buffers_.Front());
+ acquired_buffers_.PopFront();
if (frames == 2)
break;
}
+ ALOGD_IF(TRACE, "DisplaySurface::AcquireNewestAvailableBuffer: buffer: %p",
+ buffer.buffer().get());
return buffer;
}
-bool DisplaySurface::IsBufferAvailable() const {
+bool DisplaySurface::IsBufferAvailable() {
std::lock_guard<std::mutex> autolock(lock_);
- return !posted_buffers_.IsEmpty() && posted_buffers_.Front().IsAvailable();
+ DequeueBuffersLocked();
+
+ return !acquired_buffers_.IsEmpty() &&
+ acquired_buffers_.Front().IsAvailable();
}
-bool DisplaySurface::IsBufferPosted() const {
+bool DisplaySurface::IsBufferPosted() {
std::lock_guard<std::mutex> autolock(lock_);
- return !posted_buffers_.IsEmpty();
-}
+ DequeueBuffersLocked();
-AcquiredBuffer DisplaySurface::AcquireCurrentBuffer() {
- std::lock_guard<std::mutex> autolock(lock_);
- if (posted_buffers_.IsEmpty()) {
- ALOGE("Error: attempt to acquire buffer when none are posted.");
- return AcquiredBuffer();
- }
- AcquiredBuffer buffer = std::move(posted_buffers_.Front());
- posted_buffers_.PopFront();
- return buffer;
-}
-
-int DisplaySurface::GetConsumers(std::vector<LocalChannelHandle>* consumers) {
- std::lock_guard<std::mutex> autolock(lock_);
- std::vector<LocalChannelHandle> items;
-
- for (auto pair : buffers_) {
- const auto& buffer = pair.second;
-
- Status<LocalChannelHandle> consumer_channel = buffer->CreateConsumer();
- if (!consumer_channel) {
- ALOGE(
- "DisplaySurface::GetConsumers: Failed to get a new consumer for "
- "buffer %d: %s",
- buffer->id(), consumer_channel.GetErrorMessage().c_str());
- return -consumer_channel.error();
- }
-
- items.push_back(consumer_channel.take());
- }
-
- *consumers = std::move(items);
- return 0;
+ return !acquired_buffers_.IsEmpty();
}
int DisplaySurface::HandleMessage(pdx::Message& message) {
@@ -158,9 +193,9 @@
*this, &DisplaySurface::OnClientSetAttributes, message);
break;
- case DisplayRPC::AllocateBuffer::Opcode:
- DispatchRemoteMethod<DisplayRPC::AllocateBuffer>(
- *this, &DisplaySurface::OnAllocateBuffer, message);
+ case DisplayRPC::CreateBufferQueue::Opcode:
+ DispatchRemoteMethod<DisplayRPC::CreateBufferQueue>(
+ *this, &DisplaySurface::OnCreateBufferQueue, message);
break;
case DisplayRPC::CreateVideoMeshSurface::Opcode:
@@ -226,58 +261,20 @@
return 0;
}
-// Allocates a new buffer for the DisplaySurface associated with this channel.
-std::pair<uint32_t, LocalChannelHandle> DisplaySurface::OnAllocateBuffer(
- pdx::Message& message) {
- // Inject flag to enable framebuffer compression for the application buffers.
- // TODO(eieio,jbates): Make this configurable per hardware platform.
- const int usage = usage_ | GRALLOC_USAGE_QCOM_FRAMEBUFFER_COMPRESSION;
- const int slice_count =
- (flags_ & static_cast<int>(DisplaySurfaceFlagsEnum::SeparateGeometry))
- ? 2
- : 1;
+LocalChannelHandle DisplaySurface::OnCreateBufferQueue(Message& message) {
+ ATRACE_NAME("DisplaySurface::OnCreateBufferQueue");
- ALOGI_IF(
- TRACE,
- "DisplaySurface::OnAllocateBuffer: width=%d height=%d format=%x usage=%x "
- "slice_count=%d",
- width_, height_, format_, usage, slice_count);
-
- // Create a producer buffer to hand back to the sender.
- auto producer = BufferProducer::Create(width_, height_, format_, usage,
- sizeof(uint64_t), slice_count);
- if (!producer)
- REPLY_ERROR_RETURN(message, EINVAL, {});
-
- // Create and import a consumer attached to the producer.
- Status<LocalChannelHandle> consumer_channel = producer->CreateConsumer();
- if (!consumer_channel)
- REPLY_ERROR_RETURN(message, consumer_channel.error(), {});
-
- std::shared_ptr<BufferConsumer> consumer =
- BufferConsumer::Import(consumer_channel.take());
- if (!consumer)
- REPLY_ERROR_RETURN(message, ENOMEM, {});
-
- // Add the consumer to this surface.
- int err = AddConsumer(consumer);
- if (err < 0) {
- ALOGE("DisplaySurface::OnAllocateBuffer: failed to add consumer: buffer=%d",
- consumer->id());
- REPLY_ERROR_RETURN(message, -err, {});
+ if (consumer_queue_ != nullptr) {
+ ALOGE(
+ "DisplaySurface::OnCreateBufferQueue: A ProdcuerQueue has already been "
+ "created and transported to DisplayClient.");
+ REPLY_ERROR_RETURN(message, EALREADY, {});
}
- // Move the channel handle so that it doesn't get closed when the producer
- // goes out of scope.
- std::pair<uint32_t, LocalChannelHandle> return_value(
- allocated_buffer_index_, std::move(producer->GetChannelHandle()));
+ auto producer = ProducerQueue::Create<uint64_t>();
+ consumer_queue_ = producer->CreateConsumerQueue();
- // Save buffer index, associated with the buffer id so that it can be looked
- // up later.
- buffer_id_to_index_[consumer->id()] = allocated_buffer_index_;
- ++allocated_buffer_index_;
-
- return return_value;
+ return std::move(producer->GetChannelHandle());
}
RemoteChannelHandle DisplaySurface::OnCreateVideoMeshSurface(
@@ -319,103 +316,6 @@
return status.take();
}
-int DisplaySurface::AddConsumer(
- const std::shared_ptr<BufferConsumer>& consumer) {
- ALOGD_IF(TRACE, "DisplaySurface::AddConsumer: buffer_id=%d", consumer->id());
- // Add the consumer to the epoll dispatcher, edge-triggered.
- int err = service()->dispatcher_.AddEventHandler(
- consumer->event_fd(), EPOLLET | EPOLLIN | EPOLLHUP,
- std::bind(&DisplaySurface::HandleConsumerEvents,
- std::static_pointer_cast<DisplaySurface>(shared_from_this()),
- consumer, std::placeholders::_1));
- if (err) {
- ALOGE(
- "DisplaySurface::AddConsumer: failed to add epoll event handler for "
- "consumer: %s",
- strerror(-err));
- return err;
- }
-
- // Add the consumer to the list of buffers for this surface.
- std::lock_guard<std::mutex> autolock(lock_);
- buffers_.insert(std::make_pair(consumer->id(), consumer));
- return 0;
-}
-
-void DisplaySurface::RemoveConsumer(
- const std::shared_ptr<BufferConsumer>& consumer) {
- ALOGD_IF(TRACE, "DisplaySurface::RemoveConsumer: buffer_id=%d",
- consumer->id());
- service()->dispatcher_.RemoveEventHandler(consumer->event_fd());
-
- std::lock_guard<std::mutex> autolock(lock_);
- buffers_.erase(consumer->id());
-}
-
-void DisplaySurface::RemoveConsumerUnlocked(
- const std::shared_ptr<BufferConsumer>& consumer) {
- ALOGD_IF(TRACE, "DisplaySurface::RemoveConsumerUnlocked: buffer_id=%d",
- consumer->id());
- service()->dispatcher_.RemoveEventHandler(consumer->event_fd());
- buffers_.erase(consumer->id());
-}
-
-void DisplaySurface::OnPostConsumer(
- const std::shared_ptr<BufferConsumer>& consumer) {
- ATRACE_NAME("DisplaySurface::OnPostConsumer");
- std::lock_guard<std::mutex> autolock(lock_);
-
- if (!IsVisible()) {
- ALOGD_IF(TRACE,
- "DisplaySurface::OnPostConsumer: Discarding buffer_id=%d on "
- "invisible surface.",
- consumer->id());
- consumer->Discard();
- return;
- }
-
- if (posted_buffers_.IsFull()) {
- ALOGE("Error: posted buffers full, overwriting");
- posted_buffers_.PopBack();
- }
-
- int error;
- posted_buffers_.Append(AcquiredBuffer(consumer, &error));
-
- // Remove the consumer if the other end was closed.
- if (posted_buffers_.Back().IsEmpty() && error == -EPIPE)
- RemoveConsumerUnlocked(consumer);
-}
-
-void DisplaySurface::HandleConsumerEvents(
- const std::shared_ptr<BufferConsumer>& consumer, int events) {
- auto status = consumer->GetEventMask(events);
- if (!status) {
- ALOGW(
- "DisplaySurface::HandleConsumerEvents: Failed to get event mask for "
- "consumer: %s",
- status.GetErrorMessage().c_str());
- return;
- }
-
- events = status.get();
- if (events & EPOLLHUP) {
- ALOGD_IF(TRACE,
- "DisplaySurface::HandleConsumerEvents: removing event handler for "
- "buffer=%d",
- consumer->id());
- RemoveConsumer(consumer);
- } else if (events & EPOLLIN) {
- // BufferHub uses EPOLLIN to signal consumer ownership.
- ALOGD_IF(TRACE,
- "DisplaySurface::HandleConsumerEvents: posting buffer=%d for "
- "process=%d",
- consumer->id(), process_id_);
-
- OnPostConsumer(consumer);
- }
-}
-
std::vector<std::shared_ptr<VideoMeshSurface>>
DisplaySurface::GetVideoMeshSurfaces() {
std::lock_guard<std::mutex> autolock(lock_);
diff --git a/libs/vr/libvrflinger/display_surface.h b/libs/vr/libvrflinger/display_surface.h
index fa34057..feb173e 100644
--- a/libs/vr/libvrflinger/display_surface.h
+++ b/libs/vr/libvrflinger/display_surface.h
@@ -13,7 +13,6 @@
#include <vector>
#include "acquired_buffer.h"
-#include "epoll_event_dispatcher.h"
#include "surface_channel.h"
#include "video_mesh_surface.h"
@@ -65,19 +64,8 @@
return buffer_id_to_index_[buffer_id];
}
- // Gets a new set of consumers for all of the surface's buffers. These
- // consumers are independent from the consumers maintained internally to the
- // surface and may be passed to other processes over IPC.
- int GetConsumers(std::vector<pdx::LocalChannelHandle>* consumers);
-
- template <class A>
- void ForEachBuffer(A action) {
- std::lock_guard<std::mutex> autolock(lock_);
- std::for_each(buffers_.begin(), buffers_.end(), action);
- }
-
- bool IsBufferAvailable() const;
- bool IsBufferPosted() const;
+ bool IsBufferAvailable();
+ bool IsBufferPosted();
AcquiredBuffer AcquireCurrentBuffer();
// Get the newest buffer. Up to one buffer will be skipped. If a buffer is
@@ -119,12 +107,6 @@
// Returns whether a frame is available without locking the mutex.
bool IsFrameAvailableNoLock() const;
- // Handles epoll events for BufferHub consumers. Events are mainly generated
- // by producers posting buffers ready for display. This handler runs on the
- // epoll event thread.
- void HandleConsumerEvents(const std::shared_ptr<BufferConsumer>& consumer,
- int events);
-
// Dispatches display surface messages to the appropriate handlers. This
// handler runs on the displayd message dispatch thread.
int HandleMessage(pdx::Message& message) override;
@@ -133,33 +115,22 @@
int OnClientSetAttributes(pdx::Message& message,
const DisplaySurfaceAttributes& attributes);
- // Allocates a buffer with the display surface geometry and settings and
- // returns it to the client.
- std::pair<uint32_t, pdx::LocalChannelHandle> OnAllocateBuffer(
- pdx::Message& message);
+ // Creates a BufferHubQueue associated with this surface and returns the PDX
+ // handle of its producer side to the client.
+ pdx::LocalChannelHandle OnCreateBufferQueue(pdx::Message& message);
- // Creates a video mesh surface associated with this surface and returns it
- // to the client.
+ // Creates a video mesh surface associated with this surface and returns its
+ // PDX handle to the client.
pdx::RemoteChannelHandle OnCreateVideoMeshSurface(pdx::Message& message);
- // Sets the current buffer for the display surface, discarding the previous
- // buffer if it is not already claimed. Runs on the epoll event thread.
- void OnPostConsumer(const std::shared_ptr<BufferConsumer>& consumer);
-
// Client interface (called through IPC) to set visibility and z order.
void ClientSetVisible(bool visible);
void ClientSetZOrder(int z_order);
void ClientSetExcludeFromBlur(bool exclude_from_blur);
void ClientSetBlurBehind(bool blur_behind);
- // Runs on the displayd message dispatch thread.
- int AddConsumer(const std::shared_ptr<BufferConsumer>& consumer);
-
- // Runs on the epoll event thread.
- void RemoveConsumer(const std::shared_ptr<BufferConsumer>& consumer);
-
- // Runs on the epoll and display post thread.
- void RemoveConsumerUnlocked(const std::shared_ptr<BufferConsumer>& consumer);
+ // Dequeue all available buffers from the consumer queue.
+ void DequeueBuffersLocked();
DisplaySurface(const DisplaySurface&) = delete;
void operator=(const DisplaySurface&) = delete;
@@ -169,11 +140,16 @@
// Synchronizes access to mutable state below between message dispatch thread,
// epoll event thread, and frame post thread.
mutable std::mutex lock_;
- std::unordered_map<int, std::shared_ptr<BufferConsumer>> buffers_;
+
+ // The consumer end of a BufferHubQueue. VrFlinger allocates and controls the
+ // buffer queue and pass producer end to the app and the consumer end to
+ // compositor.
+ // TODO(jwcai) Add support for multiple buffer queues per display surface.
+ std::shared_ptr<ConsumerQueue> consumer_queue_;
// In a triple-buffered surface, up to kMaxPostedBuffers buffers may be
// posted and pending.
- RingBuffer<AcquiredBuffer> posted_buffers_;
+ RingBuffer<AcquiredBuffer> acquired_buffers_;
// Provides access to VideoMeshSurface. Here we don't want to increase
// the reference count immediately on allocation, will leave it into
@@ -194,8 +170,6 @@
bool manager_visible_;
int manager_z_order_;
float manager_blur_;
- // The monotonically increasing index for allocated buffers in this surface.
- uint32_t allocated_buffer_index_;
int layer_order_;
// Maps from the buffer id to the corresponding allocated buffer index.
diff --git a/libs/vr/libvrflinger/epoll_event_dispatcher.cpp b/libs/vr/libvrflinger/epoll_event_dispatcher.cpp
deleted file mode 100644
index b37e76e..0000000
--- a/libs/vr/libvrflinger/epoll_event_dispatcher.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-#include "epoll_event_dispatcher.h"
-
-#include <log/log.h>
-#include <sys/epoll.h>
-#include <sys/eventfd.h>
-#include <sys/prctl.h>
-
-#include <dvr/performance_client_api.h>
-
-namespace android {
-namespace dvr {
-
-EpollEventDispatcher::EpollEventDispatcher()
- : exit_thread_(false), epoll_fd_(-1), event_fd_(-1) {
- epoll_fd_ = epoll_create(64);
- if (epoll_fd_ < 0) {
- ALOGE("Failed to create epoll fd: %s", strerror(errno));
- return;
- }
-
- event_fd_ = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
- if (event_fd_ < 0) {
- ALOGE("Failed to create event for epolling: %s", strerror(errno));
- return;
- }
-
- // Add watch for eventfd. This should only watch for EPOLLIN, which gets set
- // when eventfd_write occurs. Use "this" as a unique sentinal value to
- // identify events from the event fd.
- epoll_event event = {.events = EPOLLIN, .data = {.ptr = this}};
- if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, event_fd_, &event) < 0) {
- ALOGE("Failed to add eventfd to epoll set because: %s", strerror(errno));
- return;
- }
-
- thread_ = std::thread(&EpollEventDispatcher::EventThread, this);
-}
-
-EpollEventDispatcher::~EpollEventDispatcher() {
- Stop();
-
- close(epoll_fd_);
- close(event_fd_);
-}
-
-void EpollEventDispatcher::Stop() {
- exit_thread_.store(true);
- eventfd_write(event_fd_, 1);
-}
-
-int EpollEventDispatcher::AddEventHandler(int fd, int event_mask,
- Handler handler) {
- std::lock_guard<std::mutex> lock(lock_);
-
- epoll_event event;
- event.events = event_mask;
- event.data.ptr = &(handlers_[fd] = handler);
-
- ALOGD_IF(
- TRACE,
- "EpollEventDispatcher::AddEventHandler: fd=%d event_mask=0x%x handler=%p",
- fd, event_mask, event.data.ptr);
-
- int err = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &event);
- return err < 0 ? -errno : 0;
-}
-
-int EpollEventDispatcher::RemoveEventHandler(int fd) {
- ALOGD_IF(TRACE, "EpollEventDispatcher::RemoveEventHandler: fd=%d", fd);
- std::lock_guard<std::mutex> lock(lock_);
-
- epoll_event dummy; // See BUGS in man 2 epoll_ctl.
- if (epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, &dummy) < 0) {
- ALOGE("Failed to remove fd from epoll set because: %s", strerror(errno));
- return -errno;
- }
-
- // If the fd was valid above, add it to the list of ids to remove.
- removed_handlers_.push_back(fd);
-
- // Wake up the event thread to clean up.
- eventfd_write(event_fd_, 1);
-
- return 0;
-}
-
-void EpollEventDispatcher::EventThread() {
- prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("EpollEvent"), 0, 0, 0);
-
- const int error = dvrSetSchedulerClass(0, "graphics");
- LOG_ALWAYS_FATAL_IF(
- error < 0,
- "EpollEventDispatcher::EventThread: Failed to set scheduler class: %s",
- strerror(-error));
-
- const size_t kMaxNumEvents = 128;
- epoll_event events[kMaxNumEvents];
-
- while (!exit_thread_.load()) {
- int num_events = epoll_wait(epoll_fd_, events, kMaxNumEvents, -1);
- if (num_events < 0 && errno != EINTR)
- break;
-
- ALOGD_IF(TRACE, "EpollEventDispatcher::EventThread: num_events=%d",
- num_events);
-
- for (int i = 0; i < num_events; i++) {
- ALOGD_IF(
- TRACE,
- "EpollEventDispatcher::EventThread: event %d: handler=%p events=0x%x",
- i, events[i].data.ptr, events[i].events);
-
- if (events[i].data.ptr == this) {
- // Clear pending event on event_fd_. Serialize the read with respect to
- // writes from other threads.
- std::lock_guard<std::mutex> lock(lock_);
- eventfd_t value;
- eventfd_read(event_fd_, &value);
- } else {
- auto handler = reinterpret_cast<Handler*>(events[i].data.ptr);
- if (handler)
- (*handler)(events[i].events);
- }
- }
-
- // Remove any handlers that have been posted for removal. This is done here
- // instead of in RemoveEventHandler() to prevent races between the dispatch
- // thread and the code requesting the removal. Handlers are guaranteed to
- // stay alive between exiting epoll_wait() and the dispatch loop above.
- std::lock_guard<std::mutex> lock(lock_);
- for (auto handler_fd : removed_handlers_) {
- ALOGD_IF(TRACE,
- "EpollEventDispatcher::EventThread: removing handler: fd=%d",
- handler_fd);
- handlers_.erase(handler_fd);
- }
- removed_handlers_.clear();
- }
-}
-
-} // namespace dvr
-} // namespace android
diff --git a/libs/vr/libvrflinger/epoll_event_dispatcher.h b/libs/vr/libvrflinger/epoll_event_dispatcher.h
deleted file mode 100644
index 43bca2e..0000000
--- a/libs/vr/libvrflinger/epoll_event_dispatcher.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_EPOLL_EVENT_DISPATCHER_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_EPOLL_EVENT_DISPATCHER_H_
-
-#include <sys/epoll.h>
-
-#include <atomic>
-#include <functional>
-#include <mutex>
-#include <thread>
-#include <unordered_map>
-#include <vector>
-
-namespace android {
-namespace dvr {
-
-class EpollEventDispatcher {
- public:
- // Function type for event handlers. The handler receives a bitmask of the
- // epoll events that occurred on the file descriptor associated with the
- // handler.
- using Handler = std::function<void(int)>;
-
- EpollEventDispatcher();
- ~EpollEventDispatcher();
-
- // |handler| is called on the internal dispatch thread when |fd| is signaled
- // by events in |event_mask|.
- // Return 0 on success or a negative error code on failure.
- int AddEventHandler(int fd, int event_mask, Handler handler);
- int RemoveEventHandler(int fd);
-
- void Stop();
-
- private:
- void EventThread();
-
- std::thread thread_;
- std::atomic<bool> exit_thread_;
-
- // Protects handlers_ and removed_handlers_ and serializes operations on
- // epoll_fd_ and event_fd_.
- std::mutex lock_;
-
- // Maintains a map of fds to event handlers. This is primarily to keep any
- // references alive that may be bound in the std::function instances. It is
- // not used at dispatch time to avoid performance problems with different
- // versions of std::unordered_map.
- std::unordered_map<int, Handler> handlers_;
-
- // List of fds to be removed from the map. The actual removal is performed
- // by the event dispatch thread to avoid races.
- std::vector<int> removed_handlers_;
-
- int epoll_fd_;
- int event_fd_;
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_SERVICES_DISPLAYD_EPOLL_EVENT_DISPATCHER_H_
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index f801d9b..53c2ac2 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -1485,6 +1485,8 @@
handle = acquired_buffer_.buffer()->native_handle();
acquire_fence_fd_.Reset(acquired_buffer_.ClaimAcquireFence().Release());
} else {
+ // TODO(jwcai) Note: this is the GPU compositor's layer, and we need the
+ // mechanism to accept distorted layers from VrCore.
right = direct_buffer_->width();
bottom = direct_buffer_->height();
handle = direct_buffer_->handle();
diff --git a/libs/vr/libvrflinger/video_compositor.cpp b/libs/vr/libvrflinger/video_compositor.cpp
index 6b39a3c..411e3a3 100644
--- a/libs/vr/libvrflinger/video_compositor.cpp
+++ b/libs/vr/libvrflinger/video_compositor.cpp
@@ -79,7 +79,9 @@
// queued in order from the producer side.
// TODO(jwcai) Use |metadata.timestamp_ns| to schedule video frames
// accurately.
- auto buffer_consumer = consumer_queue_->Dequeue(0, &slot, &metadata);
+ LocalHandle acquire_fence;
+ auto buffer_consumer =
+ consumer_queue_->Dequeue(0, &slot, &metadata, &acquire_fence);
if (buffer_consumer) {
// Create a new texture if it hasn't been created yet, or the same slot
diff --git a/libs/vr/libvrsensor/Android.bp b/libs/vr/libvrsensor/Android.bp
new file mode 100644
index 0000000..6d48f18
--- /dev/null
+++ b/libs/vr/libvrsensor/Android.bp
@@ -0,0 +1,73 @@
+// 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.
+
+sourceFiles = [
+ "pose_client.cpp",
+ "sensor_client.cpp",
+]
+
+includeFiles = [
+ "include",
+]
+
+staticLibraries = [
+ "libbufferhub",
+ "libbufferhubqueue",
+ "libdvrcommon",
+ "libpdx_default_transport",
+]
+
+sharedLibraries = [
+ "libbase",
+ "libcutils",
+ "libhardware",
+ "liblog",
+ "libutils",
+ "libui",
+]
+
+cc_library {
+ srcs: sourceFiles,
+ export_include_dirs: includeFiles,
+ static_libs: staticLibraries,
+ shared_libs: sharedLibraries,
+ name: "libvrsensor",
+}
+
+testFiles = ["tests/sensor_app_tests.cpp"]
+
+cc_test {
+ name: "sensor_app_tests",
+ tags: ["optional"],
+
+ srcs: testFiles,
+
+ shared_libs: [
+ "libEGL",
+ "libGLESv1_CM",
+ "libGLESv2",
+ "libvulkan",
+ "libsync",
+ ] + sharedLibraries,
+
+ static_libs: [
+ "libgmock_main",
+ "libgmock",
+ "libdisplay",
+ "libeds",
+ "libvrsensor",
+ "libdvrgraphics",
+ ] + staticLibraries,
+
+}
diff --git a/libs/vr/libsensor/include/CPPLINT.cfg b/libs/vr/libvrsensor/include/CPPLINT.cfg
similarity index 100%
rename from libs/vr/libsensor/include/CPPLINT.cfg
rename to libs/vr/libvrsensor/include/CPPLINT.cfg
diff --git a/libs/vr/libsensor/include/dvr/pose_client.h b/libs/vr/libvrsensor/include/dvr/pose_client.h
similarity index 100%
rename from libs/vr/libsensor/include/dvr/pose_client.h
rename to libs/vr/libvrsensor/include/dvr/pose_client.h
diff --git a/libs/vr/libsensor/include/private/dvr/pose-ipc.h b/libs/vr/libvrsensor/include/private/dvr/pose-ipc.h
similarity index 100%
rename from libs/vr/libsensor/include/private/dvr/pose-ipc.h
rename to libs/vr/libvrsensor/include/private/dvr/pose-ipc.h
diff --git a/libs/vr/libsensor/include/private/dvr/pose_client_internal.h b/libs/vr/libvrsensor/include/private/dvr/pose_client_internal.h
similarity index 100%
rename from libs/vr/libsensor/include/private/dvr/pose_client_internal.h
rename to libs/vr/libvrsensor/include/private/dvr/pose_client_internal.h
diff --git a/libs/vr/libsensor/include/private/dvr/sensor-ipc.h b/libs/vr/libvrsensor/include/private/dvr/sensor-ipc.h
similarity index 100%
rename from libs/vr/libsensor/include/private/dvr/sensor-ipc.h
rename to libs/vr/libvrsensor/include/private/dvr/sensor-ipc.h
diff --git a/libs/vr/libsensor/include/private/dvr/sensor_client.h b/libs/vr/libvrsensor/include/private/dvr/sensor_client.h
similarity index 100%
rename from libs/vr/libsensor/include/private/dvr/sensor_client.h
rename to libs/vr/libvrsensor/include/private/dvr/sensor_client.h
diff --git a/libs/vr/libsensor/include/private/dvr/sensor_constants.h b/libs/vr/libvrsensor/include/private/dvr/sensor_constants.h
similarity index 100%
rename from libs/vr/libsensor/include/private/dvr/sensor_constants.h
rename to libs/vr/libvrsensor/include/private/dvr/sensor_constants.h
diff --git a/libs/vr/libsensor/pose_client.cpp b/libs/vr/libvrsensor/pose_client.cpp
similarity index 100%
rename from libs/vr/libsensor/pose_client.cpp
rename to libs/vr/libvrsensor/pose_client.cpp
diff --git a/libs/vr/libsensor/sensor_client.cpp b/libs/vr/libvrsensor/sensor_client.cpp
similarity index 100%
rename from libs/vr/libsensor/sensor_client.cpp
rename to libs/vr/libvrsensor/sensor_client.cpp
diff --git a/libs/vr/libsensor/tests/sensor_app_tests.cpp b/libs/vr/libvrsensor/tests/sensor_app_tests.cpp
similarity index 100%
rename from libs/vr/libsensor/tests/sensor_app_tests.cpp
rename to libs/vr/libvrsensor/tests/sensor_app_tests.cpp
diff --git a/services/Android.bp b/services/Android.bp
new file mode 100644
index 0000000..7a8ee5d
--- /dev/null
+++ b/services/Android.bp
@@ -0,0 +1 @@
+subdirs = [ "*" ]
diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp
new file mode 100644
index 0000000..8c2300e
--- /dev/null
+++ b/services/sensorservice/Android.bp
@@ -0,0 +1,3 @@
+subdirs = [
+ "hidl"
+]
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 7bd495f..2a17a7f 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -51,7 +51,7 @@
}
}
-SensorDevice::SensorDevice() {
+SensorDevice::SensorDevice() : mHidlTransportErrors(20) {
// SensorDevice may wait upto 100ms * 10 = 1s for hidl service.
constexpr auto RETRY_DELAY = std::chrono::milliseconds(100);
size_t retry = 10;
@@ -118,7 +118,15 @@
if (mSensors == NULL) return "HAL not initialized\n";
String8 result;
- checkReturn(mSensors->getSensorsList([&](const auto &list) {
+
+ result.appendFormat("Saw %d hidlTransport Errors\n", mTotalHidlTransportErrors);
+ for (auto it = mHidlTransportErrors.begin() ; it != mHidlTransportErrors.end(); it++ ) {
+ result += "\t";
+ result += it->toString();
+ result += "\n";
+ }
+
+ checkReturn(mSensors->getSensorsList([&](const auto &list){
const size_t count = list.size();
result.appendFormat(
@@ -182,19 +190,44 @@
if (mSensors == NULL) return NO_INIT;
ssize_t err;
+ int numHidlTransportErrors = 0;
+ bool hidlTransportError = false;
- checkReturn(mSensors->poll(
- count,
- [&](auto result,
- const auto &events,
- const auto &dynamicSensorsAdded) {
- if (result == Result::OK) {
- convertToSensorEvents(events, dynamicSensorsAdded, buffer);
- err = (ssize_t)events.size();
- } else {
- err = StatusFromResult(result);
- }
- }));
+ do {
+ auto ret = mSensors->poll(
+ count,
+ [&](auto result,
+ const auto &events,
+ const auto &dynamicSensorsAdded) {
+ if (result == Result::OK) {
+ convertToSensorEvents(events, dynamicSensorsAdded, buffer);
+ err = (ssize_t)events.size();
+ } else {
+ err = StatusFromResult(result);
+ }
+ });
+
+ if (ret.isOk()) {
+ hidlTransportError = false;
+ } else {
+ hidlTransportError = true;
+ numHidlTransportErrors++;
+ if (numHidlTransportErrors > 50) {
+ // Log error and bail
+ ALOGE("Max Hidl transport errors this cycle : %d", numHidlTransportErrors);
+ handleHidlDeath(ret.description());
+ } else {
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ }
+ }
+ } while (hidlTransportError);
+
+ if(numHidlTransportErrors > 0) {
+ ALOGE("Saw %d Hidl transport failures", numHidlTransportErrors);
+ HidlTransportErrorLog errLog(time(NULL), numHidlTransportErrors);
+ mHidlTransportErrors.add(errLog);
+ mTotalHidlTransportErrors++;
+ }
return err;
}
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 03552f6..410531b 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -31,6 +31,8 @@
#include "android/hardware/sensors/1.0/ISensors.h"
+#include "RingBuffer.h"
+
// ---------------------------------------------------------------------------
namespace android {
@@ -41,6 +43,33 @@
class SensorDevice : public Singleton<SensorDevice>, public Dumpable {
public:
+
+ class HidlTransportErrorLog {
+ public:
+
+ HidlTransportErrorLog() {
+ mTs = 0;
+ mCount = 0;
+ }
+
+ HidlTransportErrorLog(time_t ts, int count) {
+ mTs = ts;
+ mCount = count;
+ }
+
+ String8 toString() const {
+ String8 result;
+ struct tm *timeInfo = localtime(&mTs);
+ result.appendFormat("%02d:%02d:%02d :: %d", timeInfo->tm_hour, timeInfo->tm_min,
+ timeInfo->tm_sec, mCount);
+ return result;
+ }
+
+ private:
+ time_t mTs; // timestamp of the error
+ int mCount; // number of transport errors observed
+ };
+
ssize_t getSensorList(sensor_t const** list);
void handleDynamicSensorConnection(int handle, bool connected);
@@ -125,6 +154,10 @@
};
DefaultKeyedVector<int, Info> mActivationCount;
+ // Keep track of any hidl transport failures
+ SensorServiceUtil::RingBuffer<HidlTransportErrorLog> mHidlTransportErrors;
+ int mTotalHidlTransportErrors;
+
// Use this vector to determine which client is activated or deactivated.
SortedVector<void *> mDisabledClients;
SensorDevice();
diff --git a/services/sensorservice/hidl/Android.bp b/services/sensorservice/hidl/Android.bp
new file mode 100644
index 0000000..f00c297
--- /dev/null
+++ b/services/sensorservice/hidl/Android.bp
@@ -0,0 +1,28 @@
+cc_library_shared {
+ name: "libsensorservicehidl",
+ srcs: [
+ "DirectReportChannel.cpp",
+ "SensorManager.cpp",
+ "utils.cpp",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ shared_libs: [
+ "libbase",
+ "libhidlbase",
+ "libhidltransport",
+ "libutils",
+ "libsensor",
+ "android.frameworks.sensorservice@1.0",
+ "android.hardware.sensors@1.0",
+ "android.hidl.base@1.0",
+ ],
+ export_include_dirs: [
+ "include/"
+ ],
+ local_include_dirs: [
+ "include/sensorservicehidl/"
+ ]
+}
diff --git a/services/sensorservice/hidl/DirectReportChannel.cpp b/services/sensorservice/hidl/DirectReportChannel.cpp
new file mode 100644
index 0000000..9caba47
--- /dev/null
+++ b/services/sensorservice/hidl/DirectReportChannel.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "DirectReportChannel.h"
+#include "utils.h"
+
+namespace android {
+namespace frameworks {
+namespace sensorservice {
+namespace V1_0 {
+namespace implementation {
+
+DirectReportChannel::DirectReportChannel(::android::SensorManager& manager, int channelId)
+ : mManager(manager), mId(channelId) {}
+
+DirectReportChannel::~DirectReportChannel() {
+ mManager.destroyDirectChannel(mId);
+}
+
+// Methods from ::android::frameworks::sensorservice::V1_0::IDirectReportChannel follow.
+Return<Result> DirectReportChannel::configure(int32_t sensorHandle, RateLevel rate) {
+ return convertResult(mManager.configureDirectChannel(mId,
+ static_cast<int>(sensorHandle), static_cast<int>(rate)));
+}
+
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace sensorservice
+} // namespace frameworks
+} // namespace android
diff --git a/services/sensorservice/hidl/DirectReportChannel.h b/services/sensorservice/hidl/DirectReportChannel.h
new file mode 100644
index 0000000..f4cd4e7
--- /dev/null
+++ b/services/sensorservice/hidl/DirectReportChannel.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_FRAMEWORKS_SENSORSERVICE_V1_0_DIRECTREPORTCHANNEL_H
+#define ANDROID_FRAMEWORKS_SENSORSERVICE_V1_0_DIRECTREPORTCHANNEL_H
+
+#include <android/frameworks/sensorservice/1.0/IDirectReportChannel.h>
+#include <android/frameworks/sensorservice/1.0/types.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <sensor/SensorManager.h>
+
+namespace android {
+namespace frameworks {
+namespace sensorservice {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::frameworks::sensorservice::V1_0::IDirectReportChannel;
+using ::android::hardware::sensors::V1_0::RateLevel;
+using ::android::hidl::base::V1_0::DebugInfo;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct DirectReportChannel : public IDirectReportChannel {
+
+ DirectReportChannel(::android::SensorManager& manager, int channelId);
+ ~DirectReportChannel();
+
+ // Methods from ::android::frameworks::sensorservice::V1_0::IDirectReportChannel follow.
+ Return<Result> configure(int32_t sensorHandle, RateLevel rate) override;
+
+private:
+ ::android::SensorManager& mManager;
+ const int mId;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace sensorservice
+} // namespace frameworks
+} // namespace android
+
+#endif // ANDROID_FRAMEWORKS_SENSORSERVICE_V1_0_DIRECTREPORTCHANNEL_H
diff --git a/services/sensorservice/hidl/SensorManager.cpp b/services/sensorservice/hidl/SensorManager.cpp
new file mode 100644
index 0000000..b55efb0
--- /dev/null
+++ b/services/sensorservice/hidl/SensorManager.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// LOG_TAG defined via build flag.
+#ifndef LOG_TAG
+#define LOG_TAG "HidlSensorManager"
+#endif
+#include <android-base/logging.h>
+
+#include "DirectReportChannel.h"
+#include "SensorManager.h"
+#include "utils.h"
+
+namespace android {
+namespace frameworks {
+namespace sensorservice {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::frameworks::sensorservice::V1_0::IDirectReportChannel;
+using ::android::hardware::sensors::V1_0::SensorInfo;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Void;
+using ::android::sp;
+
+SensorManager::SensorManager()
+ : mManager{::android::SensorManager::getInstanceForPackage(
+ String16(ISensorManager::descriptor))} {
+}
+
+// Methods from ::android::frameworks::sensorservice::V1_0::ISensorManager follow.
+Return<void> SensorManager::getSensorList(getSensorList_cb _hidl_cb) {
+ ::android::Sensor const* const* list;
+ ssize_t count = mManager.getSensorList(&list);
+ if (count < 0 || !list) {
+ LOG(ERROR) << "::android::SensorManager::getSensorList encounters " << count;
+ _hidl_cb({}, Result::UNKNOWN_ERROR);
+ return Void();
+ }
+ hidl_vec<SensorInfo> ret;
+ ret.resize(static_cast<size_t>(count));
+ for (ssize_t i = 0; i < count; ++i) {
+ ret[i] = convertSensor(*list[i]);
+ }
+ _hidl_cb(ret, Result::OK);
+ return Void();
+}
+
+Return<void> SensorManager::getDefaultSensor(SensorType type, getDefaultSensor_cb _hidl_cb) {
+ ::android::Sensor const* sensor = mManager.getDefaultSensor(static_cast<int>(type));
+ if (!sensor) {
+ _hidl_cb({}, Result::NOT_EXIST);
+ return Void();
+ }
+ _hidl_cb(convertSensor(*sensor), Result::OK);
+ return Void();
+}
+
+template<typename Callback>
+void createDirectChannel(::android::SensorManager& manager, size_t size, int type,
+ const native_handle_t* handle, const Callback& _hidl_cb) {
+
+ int channelId = manager.createDirectChannel(
+ size, type, handle);
+ if (channelId < 0) {
+ _hidl_cb(nullptr, convertResult(channelId));
+ return;
+ }
+ if (channelId == 0) {
+ _hidl_cb(nullptr, Result::UNKNOWN_ERROR);
+ return;
+ }
+
+ _hidl_cb(sp<IDirectReportChannel>(new DirectReportChannel(manager, channelId)),
+ Result::OK);
+}
+
+Return<void> SensorManager::createAshmemDirectChannel(
+ const hidl_memory& mem, uint64_t size,
+ createAshmemDirectChannel_cb _hidl_cb) {
+ if (size > mem.size()) {
+ _hidl_cb(nullptr, Result::BAD_VALUE);
+ return Void();
+ }
+
+ createDirectChannel(mManager, size, SENSOR_DIRECT_MEM_TYPE_ASHMEM,
+ mem.handle(), _hidl_cb);
+
+ return Void();
+}
+
+Return<void> SensorManager::createGrallocDirectChannel(
+ const hidl_handle& buffer, uint64_t size,
+ createGrallocDirectChannel_cb _hidl_cb) {
+
+ createDirectChannel(mManager, size, SENSOR_DIRECT_MEM_TYPE_GRALLOC,
+ buffer.getNativeHandle(), _hidl_cb);
+
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace sensorservice
+} // namespace frameworks
+} // namespace android
diff --git a/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h b/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
new file mode 100644
index 0000000..484e624
--- /dev/null
+++ b/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_FRAMEWORKS_SENSORSERVICE_V1_0_SENSORMANAGER_H
+#define ANDROID_FRAMEWORKS_SENSORSERVICE_V1_0_SENSORMANAGER_H
+
+#include <android/frameworks/sensorservice/1.0/ISensorManager.h>
+#include <android/frameworks/sensorservice/1.0/types.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <sensor/SensorManager.h>
+
+namespace android {
+namespace frameworks {
+namespace sensorservice {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::sensors::V1_0::SensorType;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::Return;
+
+struct SensorManager : public ISensorManager {
+
+ SensorManager();
+
+ // Methods from ::android::frameworks::sensorservice::V1_0::ISensorManager follow.
+ Return<void> getSensorList(getSensorList_cb _hidl_cb) override;
+ Return<void> getDefaultSensor(SensorType type, getDefaultSensor_cb _hidl_cb) override;
+ Return<void> createAshmemDirectChannel(const hidl_memory& mem, uint64_t size, createAshmemDirectChannel_cb _hidl_cb) override;
+ Return<void> createGrallocDirectChannel(const hidl_handle& buffer, uint64_t size, createGrallocDirectChannel_cb _hidl_cb) override;
+
+private:
+ ::android::SensorManager& mManager;
+
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace sensorservice
+} // namespace frameworks
+} // namespace android
+
+#endif // ANDROID_FRAMEWORKS_SENSORSERVICE_V1_0_SENSORMANAGER_H
diff --git a/services/sensorservice/hidl/utils.cpp b/services/sensorservice/hidl/utils.cpp
new file mode 100644
index 0000000..4e02741
--- /dev/null
+++ b/services/sensorservice/hidl/utils.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "utils.h"
+
+namespace android {
+namespace frameworks {
+namespace sensorservice {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::Sensor;
+using ::android::hardware::hidl_string;
+using ::android::hardware::sensors::V1_0::SensorInfo;
+
+SensorInfo convertSensor(const Sensor &src) {
+ SensorInfo dst;
+ const String8& name = src.getName();
+ const String8& vendor = src.getVendor();
+ dst.name = hidl_string{name.string(), name.size()};
+ dst.vendor = hidl_string{vendor.string(), vendor.size()};
+ dst.version = src.getVersion();
+ dst.sensorHandle = src.getHandle();
+ dst.type = static_cast<::android::hardware::sensors::V1_0::SensorType>(
+ src.getType());
+ // FIXME maxRange uses maxValue because ::android::Sensor wraps the
+ // internal sensor_t in this way.
+ dst.maxRange = src.getMaxValue();
+ dst.resolution = src.getResolution();
+ dst.power = src.getPowerUsage();
+ dst.minDelay = src.getMinDelay();
+ dst.fifoReservedEventCount = src.getFifoReservedEventCount();
+ dst.fifoMaxEventCount = src.getFifoMaxEventCount();
+ dst.typeAsString = src.getStringType();
+ dst.requiredPermission = src.getRequiredPermission();
+ dst.maxDelay = src.getMaxDelay();
+ dst.flags = src.getFlags();
+ return dst;
+}
+
+Result convertResult(status_t status) {
+ switch (status) {
+ case OK:
+ return Result::OK;
+ case NAME_NOT_FOUND:
+ return Result::NOT_EXIST;
+ case NO_MEMORY:
+ return Result::NO_MEMORY;
+ case NO_INIT:
+ return Result::NO_INIT;
+ case BAD_VALUE:
+ return Result::BAD_VALUE;
+ case INVALID_OPERATION:
+ return Result::INVALID_OPERATION;
+ default:
+ return Result::UNKNOWN_ERROR;
+ }
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace sensorservice
+} // namespace frameworks
+} // namespace android
diff --git a/services/sensorservice/hidl/utils.h b/services/sensorservice/hidl/utils.h
new file mode 100644
index 0000000..0606e69
--- /dev/null
+++ b/services/sensorservice/hidl/utils.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_FRAMEWORKS_SENSORSERVICE_V1_0_UTILS_H
+#define ANDROID_FRAMEWORKS_SENSORSERVICE_V1_0_UTILS_H
+
+#include <android/frameworks/sensorservice/1.0/types.h>
+#include <android/hardware/sensors/1.0/types.h>
+#include <hidl/HidlSupport.h>
+#include <sensor/Sensor.h>
+namespace android {
+namespace frameworks {
+namespace sensorservice {
+namespace V1_0 {
+namespace implementation {
+
+::android::hardware::sensors::V1_0::SensorInfo convertSensor(const ::android::Sensor &src);
+Result convertResult(status_t status);
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace sensorservice
+} // namespace frameworks
+} // namespace android
+
+#endif // ANDROID_FRAMEWORKS_SENSORSERVICE_V1_0_UTILS_H
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index ad5955a..a6ea750 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -65,30 +65,10 @@
DisplayHardware/HWComposer_hwc1.cpp
endif
-ifeq ($(TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS),true)
- LOCAL_CFLAGS += -DFORCE_HWC_COPY_FOR_VIRTUAL_DISPLAYS
-endif
-
ifneq ($(NUM_FRAMEBUFFER_SURFACE_BUFFERS),)
LOCAL_CFLAGS += -DNUM_FRAMEBUFFER_SURFACE_BUFFERS=$(NUM_FRAMEBUFFER_SURFACE_BUFFERS)
endif
-ifeq ($(TARGET_RUNNING_WITHOUT_SYNC_FRAMEWORK),true)
- LOCAL_CFLAGS += -DRUNNING_WITHOUT_SYNC_FRAMEWORK
-endif
-
-ifneq ($(PRESENT_TIME_OFFSET_FROM_VSYNC_NS),)
- LOCAL_CFLAGS += -DPRESENT_TIME_OFFSET_FROM_VSYNC_NS=$(PRESENT_TIME_OFFSET_FROM_VSYNC_NS)
-else
- LOCAL_CFLAGS += -DPRESENT_TIME_OFFSET_FROM_VSYNC_NS=0
-endif
-
-ifneq ($(MAX_VIRTUAL_DISPLAY_DIMENSION),)
- LOCAL_CFLAGS += -DMAX_VIRTUAL_DISPLAY_DIMENSION=$(MAX_VIRTUAL_DISPLAY_DIMENSION)
-else
- LOCAL_CFLAGS += -DMAX_VIRTUAL_DISPLAY_DIMENSION=0
-endif
-
LOCAL_CFLAGS += -fvisibility=hidden -Werror=format
LOCAL_HEADER_LIBRARIES := \
@@ -205,3 +185,5 @@
include $(BUILD_SHARED_LIBRARY)
endif # libnativehelper
+
+include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index 86cf17d..bd9b8aa 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -33,6 +33,7 @@
#include <ui/Fence.h>
#include "DispSync.h"
+#include "SurfaceFlinger.h"
#include "EventLog/EventLog.h"
using std::max;
@@ -54,10 +55,6 @@
// present time and the nearest software-predicted vsync.
static const nsecs_t kErrorThreshold = 160000000000; // 400 usec squared
-// This is the offset from the present fence timestamps to the corresponding
-// vsync event.
-static const int64_t kPresentTimeOffset = PRESENT_TIME_OFFSET_FROM_VSYNC_NS;
-
#undef LOG_TAG
#define LOG_TAG "DispSyncThread"
class DispSyncThread: public Thread {
@@ -219,7 +216,8 @@
return BAD_VALUE;
}
- // This method is only here to handle the kIgnorePresentFences case.
+ // This method is only here to handle the !SurfaceFlinger::hasSyncFramework
+ // case.
bool hasAnyEventListeners() {
if (kTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
@@ -379,8 +377,10 @@
DispSync::DispSync(const char* name) :
mName(name),
mRefreshSkipCount(0),
- mThread(new DispSyncThread(name)) {
+ mThread(new DispSyncThread(name)),
+ mIgnorePresentFences(!SurfaceFlinger::hasSyncFramework){
+ mPresentTimeOffset = SurfaceFlinger::dispSyncPresentTimeOffset;
mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
// set DispSync to SCHED_FIFO to minimize jitter
struct sched_param param = {0};
@@ -399,7 +399,7 @@
// Even if we're just ignoring the fences, the zero-phase tracing is
// not needed because any time there is an event registered we will
// turn on the HW vsync events.
- if (!kIgnorePresentFences && kEnableZeroPhaseTracer) {
+ if (!mIgnorePresentFences && kEnableZeroPhaseTracer) {
addEventListener("ZeroPhaseTracer", 0, new ZeroPhaseTracer());
}
}
@@ -433,7 +433,7 @@
nsecs_t t = f->getSignalTime();
if (t < INT64_MAX) {
mPresentFences[i].clear();
- mPresentTimes[i] = t + kPresentTimeOffset;
+ mPresentTimes[i] = t + mPresentTimeOffset;
}
}
}
@@ -478,7 +478,7 @@
resetErrorLocked();
}
- if (kIgnorePresentFences) {
+ if (mIgnorePresentFences) {
// If we don't have the sync framework we will never have
// addPresentFence called. This means we have no way to know whether
// or not we're synchronized with the HW vsyncs, so we just request
@@ -643,7 +643,7 @@
void DispSync::dump(String8& result) const {
Mutex::Autolock lock(mMutex);
result.appendFormat("present fences are %s\n",
- kIgnorePresentFences ? "ignored" : "used");
+ mIgnorePresentFences ? "ignored" : "used");
result.appendFormat("mPeriod: %" PRId64 " ns (%.3f fps; skipCount=%d)\n",
mPeriod, 1000000000.0 / mPeriod, mRefreshSkipCount);
result.appendFormat("mPhase: %" PRId64 " ns\n", mPhase);
diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h
index 2763e59..82ae795 100644
--- a/services/surfaceflinger/DispSync.h
+++ b/services/surfaceflinger/DispSync.h
@@ -25,15 +25,6 @@
namespace android {
-// Ignore present (retire) fences if the device doesn't have support for the
-// sync framework
-#if defined(RUNNING_WITHOUT_SYNC_FRAMEWORK)
-static const bool kIgnorePresentFences = true;
-#else
-static const bool kIgnorePresentFences = false;
-#endif
-
-
class String8;
class Fence;
class DispSyncThread;
@@ -182,6 +173,14 @@
// mMutex is used to protect access to all member variables.
mutable Mutex mMutex;
+
+ // This is the offset from the present fence timestamps to the corresponding
+ // vsync event.
+ int64_t mPresentTimeOffset;
+
+ // Ignore present (retire) fences if the device doesn't have support for the
+ // sync framework
+ bool mIgnorePresentFences;
};
}
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 9af4402..11df4e2 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -118,6 +118,9 @@
mNativeWindow = surface = new Surface(producer, false);
ANativeWindow* const window = mNativeWindow.get();
+#ifdef USE_HWC2
+ mActiveColorMode = static_cast<android_color_mode_t>(-1);
+#endif
/*
* Create our display's surface
*/
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 3982ba4..09434f6 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -267,12 +267,12 @@
return NO_MEMORY;
}
- if (MAX_VIRTUAL_DISPLAY_DIMENSION != 0 &&
- (width > MAX_VIRTUAL_DISPLAY_DIMENSION ||
- height > MAX_VIRTUAL_DISPLAY_DIMENSION)) {
+ if (SurfaceFlinger::maxVirtualDisplaySize != 0 &&
+ (width > SurfaceFlinger::maxVirtualDisplaySize ||
+ height > SurfaceFlinger::maxVirtualDisplaySize)) {
ALOGE("createVirtualDisplay: Can't create a virtual display with"
- " a dimension > %u (tried %u x %u)",
- MAX_VIRTUAL_DISPLAY_DIMENSION, width, height);
+ " a dimension > %" PRIu64 " (tried %u x %u)",
+ SurfaceFlinger::maxVirtualDisplaySize, width, height);
return INVALID_OPERATION;
}
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 6f253ab..8217540 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -17,6 +17,7 @@
// #define LOG_NDEBUG 0
#include "VirtualDisplaySurface.h"
#include "HWComposer.h"
+#include "SurfaceFlinger.h"
#include <gui/BufferItem.h>
#include <gui/BufferQueue.h>
@@ -26,12 +27,6 @@
namespace android {
// ---------------------------------------------------------------------------
-#if defined(FORCE_HWC_COPY_FOR_VIRTUAL_DISPLAYS)
-static const bool sForceHwcCopy = true;
-#else
-static const bool sForceHwcCopy = false;
-#endif
-
#define VDS_LOGE(msg, ...) ALOGE("[%s] " msg, \
mDisplayName.string(), ##__VA_ARGS__)
#define VDS_LOGW_IF(cond, msg, ...) ALOGW_IF(cond, "[%s] " msg, \
@@ -74,7 +69,8 @@
mOutputProducerSlot(BufferQueue::INVALID_BUFFER_SLOT),
mDbgState(DBG_STATE_IDLE),
mDbgLastCompositionType(COMPOSITION_UNKNOWN),
- mMustRecompose(false)
+ mMustRecompose(false),
+ mForceHwcCopy(SurfaceFlinger::useHwcForRgbToYuv)
{
mSource[SOURCE_SINK] = sink;
mSource[SOURCE_SCRATCH] = bqProducer;
@@ -137,7 +133,7 @@
mDbgState = DBG_STATE_PREPARED;
mCompositionType = compositionType;
- if (sForceHwcCopy && mCompositionType == COMPOSITION_GLES) {
+ if (mForceHwcCopy && mCompositionType == COMPOSITION_GLES) {
// Some hardware can do RGB->YUV conversion more efficiently in hardware
// controlled by HWC than in hardware controlled by the video encoder.
// Forcing GLES-composed frames to go through an extra copy by the HWC
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index ee2772a..5c0e084 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -255,6 +255,9 @@
#ifdef USE_HWC2
HWComposerBufferCache mHwcBufferCache;
#endif
+
+
+ bool mForceHwcCopy;
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index ccbc2d9..2755206 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -760,9 +760,7 @@
mHwcLayers[hwcId].forceClientComposition = true;
}
-#endif
-#ifdef USE_HWC2
void Layer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) {
// Apply this display's projection's viewport to the visible region
// before giving it to the HWC HAL.
@@ -865,6 +863,10 @@
static_cast<int32_t>(error));
}
}
+
+android_dataspace Layer::getDataSpace() const {
+ return mCurrentState.dataSpace;
+}
#else
void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
HWComposer::HWCLayerInterface& layer) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index a87c16f..cee9e3c 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -261,6 +261,8 @@
void forceClientComposition(int32_t hwcId);
void setPerFrameData(const sp<const DisplayDevice>& displayDevice);
+ android_dataspace getDataSpace() const;
+
// callIntoHwc exists so we can update our local state and call
// acceptDisplayChanges without unnecessarily updating the device's state
void setCompositionType(int32_t hwcId, HWC2::Composition type,
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 0f0a017..4e7e36f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -99,6 +99,7 @@
namespace android {
+
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
@@ -113,6 +114,10 @@
int64_t SurfaceFlinger::vsyncPhaseOffsetNs;
int64_t SurfaceFlinger::sfVsyncPhaseOffsetNs;
bool SurfaceFlinger::useContextPriority;
+int64_t SurfaceFlinger::dispSyncPresentTimeOffset;
+bool SurfaceFlinger::useHwcForRgbToYuv;
+uint64_t SurfaceFlinger::maxVirtualDisplaySize;
+bool SurfaceFlinger::hasSyncFramework;
SurfaceFlinger::SurfaceFlinger()
: BnSurfaceComposer(),
@@ -156,6 +161,7 @@
,mEnterVrMode(false)
#endif
{
+ ALOGI("SurfaceFlinger is starting");
vsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::vsyncEventPhaseOffsetNs>(1000000);
@@ -163,11 +169,21 @@
sfVsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::vsyncSfEventPhaseOffsetNs>(1000000);
- ALOGI("SurfaceFlinger is starting");
+ hasSyncFramework = getBool< ISurfaceFlingerConfigs,
+ &ISurfaceFlingerConfigs::hasSyncFramework>(true);
useContextPriority = getBool< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::useContextPriority>(false);
+ dispSyncPresentTimeOffset = getInt64< ISurfaceFlingerConfigs,
+ &ISurfaceFlingerConfigs::presentTimeOffsetFromVSyncNs>(0);
+
+ useHwcForRgbToYuv = getBool< ISurfaceFlingerConfigs,
+ &ISurfaceFlingerConfigs::useHwcForRGBtoYUV>(false);
+
+ maxVirtualDisplaySize = getUInt64<ISurfaceFlingerConfigs,
+ &ISurfaceFlingerConfigs::maxVirtualDisplaySize>(0);
+
// debugging stuff...
char value[PROPERTY_VALUE_MAX];
@@ -1487,7 +1503,7 @@
}
}
- if (kIgnorePresentFences) {
+ if (!hasSyncFramework) {
if (hw->isDisplayOn()) {
enableHardwareVsync();
}
@@ -3216,6 +3232,11 @@
if (isLayerTripleBufferingDisabled())
result.append(" DISABLE_TRIPLE_BUFFERING");
+
+ result.appendFormat(" PRESENT_TIME_OFFSET=%" PRId64 , dispSyncPresentTimeOffset);
+ result.appendFormat(" FORCE_HWC_FOR_RBG_TO_YUV=%d", useHwcForRgbToYuv);
+ result.appendFormat(" MAX_VIRT_DISPLAY_DIM=%" PRIu64, maxVirtualDisplaySize);
+ result.appendFormat(" RUNNING_WITHOUT_SYNC_FRAMEWORK=%d", !hasSyncFramework);
result.append("]");
}
@@ -3342,9 +3363,9 @@
result.append("DispSync configuration: ");
colorizer.reset(result);
result.appendFormat("app phase %" PRId64 " ns, sf phase %" PRId64 " ns, "
- "present offset %d ns (refresh %" PRId64 " ns)",
+ "present offset %" PRId64 " ns (refresh %" PRId64 " ns)",
vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs,
- PRESENT_TIME_OFFSET_FROM_VSYNC_NS, activeConfig->getVsyncPeriod());
+ dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod());
result.append("\n");
// Dump static screen stats
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 15e4ba2..7d7d4ff 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -105,7 +105,6 @@
{
public:
-
// This is the phase offset in nanoseconds of the software vsync event
// relative to the vsync event reported by HWComposer. The software vsync
// event is when SurfaceFlinger and Choreographer-based applications run each
@@ -129,9 +128,26 @@
static int64_t vsyncPhaseOffsetNs;
static int64_t sfVsyncPhaseOffsetNs;
+ // If fences from sync Framework are supported.
+ static bool hasSyncFramework;
+
// Instruct the Render Engine to use EGL_IMG_context_priority is available.
static bool useContextPriority;
+ // The offset in nanoseconds to use when DispSync timestamps present fence
+ // signaling time.
+ static int64_t dispSyncPresentTimeOffset;
+
+ // Some hardware can do RGB->YUV conversion more efficiently in hardware
+ // controlled by HWC than in hardware controlled by the video encoder.
+ // This instruct VirtualDisplaySurface to use HWC for such conversion on
+ // GL composition.
+ static bool useHwcForRgbToYuv;
+
+ // Maximum dimension supported by HWC for virtual display.
+ // Equal to min(max_height, max_width).
+ static uint64_t maxVirtualDisplaySize;
+
static char const* getServiceName() ANDROID_API {
return "SurfaceFlinger";
}
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index 01226e0..1d2b485 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -179,7 +179,7 @@
const nsecs_t nextRefresh = dispSync.computeNextRefresh(hwcLatency);
// The DispSync time is already adjusted for the difference between
- // vsync and reported-vsync (PRESENT_TIME_OFFSET_FROM_VSYNC_NS), so
+ // vsync and reported-vsync (SurfaceFlinger::dispSyncPresentTimeOffset), so
// we don't need to factor that in here. Pad a little to avoid
// weird effects if apps might be requesting times right on the edge.
nsecs_t extraPadding = 0;
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index c43a546..0ff9f54 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -112,6 +112,10 @@
int64_t SurfaceFlinger::vsyncPhaseOffsetNs;
int64_t SurfaceFlinger::sfVsyncPhaseOffsetNs;
bool SurfaceFlinger::useContextPriority;
+int64_t SurfaceFlinger::dispSyncPresentTimeOffset;
+bool SurfaceFlinger::useHwcForRgbToYuv;
+uint64_t SurfaceFlinger::maxVirtualDisplaySize;
+bool SurfaceFlinger::hasSyncFramework;
SurfaceFlinger::SurfaceFlinger()
: BnSurfaceComposer(),
@@ -148,17 +152,29 @@
mLastSwapTime(0),
mNumLayers(0)
{
+ ALOGI("SurfaceFlinger is starting");
+
vsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::vsyncEventPhaseOffsetNs>(1000000);
sfVsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::vsyncSfEventPhaseOffsetNs>(1000000);
- ALOGI("SurfaceFlinger is starting");
+ maxVirtualDisplaySize = getUInt64<ISurfaceFlingerConfigs,
+ &ISurfaceFlingerConfigs::maxVirtualDisplaySize>(0);
+
+ hasSyncFramework = getBool< ISurfaceFlingerConfigs,
+ &ISurfaceFlingerConfigs::hasSyncFramework>(true);
useContextPriority = getBool< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::useContextPriority>(false);
+ dispSyncPresentTimeOffset = getInt64< ISurfaceFlingerConfigs,
+ &ISurfaceFlingerConfigs::presentTimeOffsetFromVSyncNs>(0);
+
+ useHwcForRgbToYuv = getBool< ISurfaceFlingerConfigs,
+ &ISurfaceFlingerConfigs::useHwcForRGBtoYUV>(false);
+
char value[PROPERTY_VALUE_MAX];
property_get("ro.bq.gpu_to_cpu_unsupported", value, "0");
@@ -1267,7 +1283,7 @@
}
}
- if (kIgnorePresentFences) {
+ if (!hasSyncFramework) {
if (hw->isDisplayOn()) {
enableHardwareVsync();
}
@@ -1688,9 +1704,9 @@
ALOGE_IF(status != NO_ERROR,
"Unable to query height (%d)", status);
if (mUseHwcVirtualDisplays &&
- (MAX_VIRTUAL_DISPLAY_DIMENSION == 0 ||
- (width <= MAX_VIRTUAL_DISPLAY_DIMENSION &&
- height <= MAX_VIRTUAL_DISPLAY_DIMENSION))) {
+ (SurfaceFlinger::maxVirtualDisplaySize == 0 ||
+ (width <= static_cast<int>(SurfaceFlinger::maxVirtualDisplaySize) &&
+ height <= static_cast<int>(SurfaceFlinger::maxVirtualDisplaySize)))) {
hwcDisplayId = allocateHwcDisplayId(state.type);
}
@@ -3003,6 +3019,11 @@
if (isLayerTripleBufferingDisabled())
result.append(" DISABLE_TRIPLE_BUFFERING");
+
+ result.appendFormat(" PRESENT_TIME_OFFSET=%" PRId64, dispSyncPresentTimeOffset);
+ result.appendFormat(" FORCE_HWC_FOR_RBG_TO_YUV=%d", useHwcForRgbToYuv);
+ result.appendFormat(" MAX_VIRT_DISPLAY_DIM=%" PRIu64, maxVirtualDisplaySize);
+ result.appendFormat(" RUNNING_WITHOUT_SYNC_FRAMEWORK=%d", !hasSyncFramework);
result.append("]");
}
@@ -3126,8 +3147,8 @@
result.append("DispSync configuration: ");
colorizer.reset(result);
result.appendFormat("app phase %" PRId64 " ns, sf phase %" PRId64 " ns, "
- "present offset %d ns (refresh %" PRId64 " ns)",
- vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, PRESENT_TIME_OFFSET_FROM_VSYNC_NS,
+ "present offset %" PRId64 " ns (refresh %" PRId64 " ns)",
+ vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, dispSyncPresentTimeOffset,
mHwc->getRefreshPeriod(HWC_DISPLAY_PRIMARY));
result.append("\n");
diff --git a/services/surfaceflinger/tests/Android.mk b/services/surfaceflinger/tests/Android.mk
index f93d918..f46ce8a 100644
--- a/services/surfaceflinger/tests/Android.mk
+++ b/services/surfaceflinger/tests/Android.mk
@@ -8,8 +8,9 @@
LOCAL_MODULE_TAGS := tests
LOCAL_SRC_FILES := \
- Transaction_test.cpp \
- SurfaceInterceptor_test.cpp
+ Transaction_test.cpp \
+ Stress_test.cpp \
+ SurfaceInterceptor_test.cpp
LOCAL_SHARED_LIBRARIES := \
libEGL \
@@ -20,6 +21,7 @@
libprotobuf-cpp-full \
libui \
libutils \
+ libandroid \
liblog
LOCAL_STATIC_LIBRARIES := libtrace_proto
diff --git a/services/surfaceflinger/tests/Stress_test.cpp b/services/surfaceflinger/tests/Stress_test.cpp
new file mode 100644
index 0000000..33dd2f5
--- /dev/null
+++ b/services/surfaceflinger/tests/Stress_test.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <gui/SurfaceComposerClient.h>
+
+#include <utils/String8.h>
+
+#include <thread>
+#include <functional>
+
+
+namespace android {
+
+TEST(SurfaceFlingerStress, create_and_destroy) {
+ auto do_stress = []() {
+ sp<SurfaceComposerClient> client = new SurfaceComposerClient;
+ ASSERT_EQ(NO_ERROR, client->initCheck());
+ for (int j = 0; j < 1000; j++) {
+ auto surf = client->createSurface(String8("t"), 100, 100,
+ PIXEL_FORMAT_RGBA_8888, 0);
+ ASSERT_TRUE(surf != nullptr);
+ client->destroySurface(surf->getHandle());
+ }
+ };
+
+ std::vector<std::thread> threads;
+ for (int i = 0; i < 10; i++) {
+ threads.push_back(std::thread(do_stress));
+ }
+ for (auto& thread : threads) {
+ thread.join();
+ }
+}
+
+}
diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
index 1a3f89f..0cc763c 100644
--- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
+++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
@@ -15,6 +15,7 @@
*/
#include <frameworks/native/cmds/surfacereplayer/proto/src/trace.pb.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <gtest/gtest.h>
@@ -68,11 +69,18 @@
}
static status_t readProtoFile(Trace* trace) {
- std::ifstream input(DEFAULT_FILENAME, std::ios::in | std::ios::binary);
- if (input && !trace->ParseFromIstream(&input)) {
- return PERMISSION_DENIED;
+ status_t err = NO_ERROR;
+
+ int fd = open(DEFAULT_FILENAME, O_RDONLY);
+ {
+ google::protobuf::io::FileInputStream f(fd);
+ if (fd && !trace->ParseFromZeroCopyStream(&f)) {
+ err = PERMISSION_DENIED;
+ }
}
- return NO_ERROR;
+ close(fd);
+
+ return err;
}
static void enableInterceptor() {
diff --git a/services/vr/Android.bp b/services/vr/Android.bp
index af8212a..80df479 100644
--- a/services/vr/Android.bp
+++ b/services/vr/Android.bp
@@ -1,3 +1,3 @@
subdirs = [
- "*/*",
+ "*",
]
diff --git a/services/vr/bufferhubd/Android.mk b/services/vr/bufferhubd/Android.mk
index 0db909c..c1a0b6f 100644
--- a/services/vr/bufferhubd/Android.mk
+++ b/services/vr/bufferhubd/Android.mk
@@ -34,7 +34,8 @@
liblog \
libsync \
libutils \
- libgui
+ libgui \
+ libui
include $(CLEAR_VARS)
# Don't strip symbols so we see stack traces in logcat.
diff --git a/services/vr/bufferhubd/buffer_hub.cpp b/services/vr/bufferhubd/buffer_hub.cpp
index 0906476..80efcf8 100644
--- a/services/vr/bufferhubd/buffer_hub.cpp
+++ b/services/vr/bufferhubd/buffer_hub.cpp
@@ -29,7 +29,7 @@
BufferHubService::~BufferHubService() {}
bool BufferHubService::IsInitialized() const {
- return BASE::IsInitialized() && IonBuffer::GetGrallocModule();
+ return BASE::IsInitialized();
}
std::string BufferHubService::DumpState(size_t /*max_length*/) {
diff --git a/services/vr/sensord/Android.mk b/services/vr/sensord/Android.mk
index f86664e..ba0821b 100644
--- a/services/vr/sensord/Android.mk
+++ b/services/vr/sensord/Android.mk
@@ -30,7 +30,7 @@
staticLibraries := \
libdvrcommon \
- libsensor \
+ libvrsensor \
libperformance \
libbufferhub \
libpdx_default_transport \
@@ -44,6 +44,7 @@
liblog \
libhardware \
libutils \
+ libui \
$(SENSORD_EXTEND) \
cFlags := -DLOG_TAG=\"sensord\" \
diff --git a/services/vr/virtual_touchpad/Android.bp b/services/vr/virtual_touchpad/Android.bp
new file mode 100644
index 0000000..c8bc884
--- /dev/null
+++ b/services/vr/virtual_touchpad/Android.bp
@@ -0,0 +1,117 @@
+
+
+// Touchpad implementation.
+
+src = [
+ "EvdevInjector.cpp",
+ "VirtualTouchpadEvdev.cpp",
+]
+
+shared_libs = [
+ "libbase",
+ "liblog",
+ "libutils",
+]
+
+cc_library {
+ srcs: src,
+ export_include_dirs: ["include"],
+ shared_libs: shared_libs,
+ cppflags: ["-std=c++11"],
+ cflags: ["-DLOG_TAG=\"VrVirtualTouchpad\""],
+ name: "libvirtualtouchpad",
+ tags: ["optional"],
+}
+
+// Touchpad unit tests.
+
+test_static_libs = [
+ "libcutils",
+ "libvirtualtouchpad",
+]
+
+test_shared_libs = [
+ "libbase",
+ "liblog",
+ "libutils",
+]
+
+test_src_files = ["tests/VirtualTouchpad_test.cpp"]
+
+cc_test {
+ srcs: test_src_files,
+ static_libs: test_static_libs,
+ shared_libs: test_shared_libs,
+ cppflags = [
+ "-std=c++11",
+ ],
+ host_ldlibs = [
+ "-llog",
+ ],
+ name: "VirtualTouchpad_test",
+ stl: "libc++_static",
+ tags: [ "optional" ],
+}
+
+// Service.
+
+service_src = [
+ "main.cpp",
+ "VirtualTouchpadService.cpp",
+ "aidl/android/dvr/VirtualTouchpadService.aidl",
+]
+
+service_static_libs = [
+ "libcutils",
+ "libvirtualtouchpad",
+]
+
+service_shared_libs = [
+ "libbase",
+ "libbinder",
+ "liblog",
+ "libutils",
+]
+
+cc_binary {
+ srcs: service_src,
+ static_libs: service_static_libs,
+ shared_libs: service_shared_libs,
+ cppflags: ["-std=c++11"],
+ cflags: [
+ "-DLOG_TAG=\"VrVirtualTouchpad\"",
+ "-DSELINUX_ACCESS_CONTROL",
+ ],
+ host_ldlibs: ["-llog"],
+ name: "virtual_touchpad",
+ tags: ["optional"],
+ init_rc: ["virtual_touchpad.rc"],
+ compile_multilib: "64",
+ stl: "libc++_static",
+}
+
+// Touchpad client library.
+
+client_src = [
+ "VirtualTouchpadClient.cpp",
+ "DvrVirtualTouchpadClient.cpp",
+ "aidl/android/dvr/VirtualTouchpadService.aidl",
+]
+
+client_shared_libs = [
+ "libbase",
+ "libbinder",
+ "liblog",
+ "libutils",
+]
+
+cc_library {
+ srcs: client_src,
+ shared_libs: client_shared_libs,
+ cppflags: ["-std=c++11"],
+ cflags: ["-DLOG_TAG=\"VirtualTouchpadClient\""],
+ host_ldlibs: ["-llog"],
+ name: "libvirtualtouchpadclient",
+ tags: ["optional"],
+ export_include_dirs: ["include"],
+}
diff --git a/services/vr/virtual_touchpad/Android.mk b/services/vr/virtual_touchpad/Android.mk
deleted file mode 100644
index 88b2dd9..0000000
--- a/services/vr/virtual_touchpad/Android.mk
+++ /dev/null
@@ -1,107 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-
-# Touchpad implementation.
-
-src := \
- EvdevInjector.cpp \
- VirtualTouchpadEvdev.cpp
-
-shared_libs := \
- libbase \
- libutils
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(src)
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_SHARED_LIBRARIES := $(shared_libs)
-LOCAL_CPPFLAGS += -std=c++11
-LOCAL_CFLAGS += -DLOG_TAG=\"VrVirtualTouchpad\"
-LOCAL_MODULE := libvirtualtouchpad
-LOCAL_MODULE_TAGS := optional
-include $(BUILD_STATIC_LIBRARY)
-
-
-# Touchpad unit tests.
-
-test_static_libs := \
- libbase \
- libcutils \
- libvirtualtouchpad
-
-test_shared_libs := \
- libutils
-
-test_src_files := \
- tests/VirtualTouchpad_test.cpp
-
-$(foreach file,$(test_src_files), \
- $(eval include $(CLEAR_VARS)) \
- $(eval LOCAL_SRC_FILES := $(file)) \
- $(eval LOCAL_C_INCLUDES := $(LOCAL_PATH)/include) \
- $(eval LOCAL_STATIC_LIBRARIES := $(test_static_libs)) \
- $(eval LOCAL_SHARED_LIBRARIES := $(test_shared_libs)) \
- $(eval LOCAL_CPPFLAGS += -std=c++11) \
- $(eval LOCAL_LDLIBS := -llog) \
- $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
- $(eval LOCAL_MODULE_TAGS := optional) \
- $(eval LOCAL_CXX_STL := libc++_static) \
- $(eval include $(BUILD_NATIVE_TEST)) \
-)
-
-
-# Service.
-
-src := \
- main.cpp \
- VirtualTouchpadService.cpp \
- aidl/android/dvr/VirtualTouchpadService.aidl
-
-static_libs := \
- libcutils \
- libvirtualtouchpad
-
-shared_libs := \
- libbase \
- libbinder \
- libutils
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(src)
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_STATIC_LIBRARIES := $(static_libs)
-LOCAL_SHARED_LIBRARIES := $(shared_libs)
-LOCAL_CPPFLAGS += -std=c++11
-LOCAL_CFLAGS += -DLOG_TAG=\"VrVirtualTouchpad\" -DSELINUX_ACCESS_CONTROL
-LOCAL_LDLIBS := -llog
-LOCAL_MODULE := virtual_touchpad
-LOCAL_MODULE_TAGS := optional
-LOCAL_INIT_RC := virtual_touchpad.rc
-LOCAL_MULTILIB := 64
-LOCAL_CXX_STL := libc++_static
-include $(BUILD_EXECUTABLE)
-
-
-# Touchpad client library.
-
-src := \
- VirtualTouchpadClient.cpp \
- aidl/android/dvr/VirtualTouchpadService.aidl
-
-shared_libs := \
- libbase \
- libbinder \
- libutils
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(src)
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_SHARED_LIBRARIES := $(shared_libs)
-LOCAL_CPPFLAGS += -std=c++11
-LOCAL_CFLAGS += -DLOG_TAG=\"VirtualTouchpadClient\"
-LOCAL_LDLIBS := -llog
-LOCAL_MODULE := libvirtualtouchpadclient
-LOCAL_MODULE_TAGS := optional
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-include $(BUILD_STATIC_LIBRARY)
diff --git a/services/vr/virtual_touchpad/DvrVirtualTouchpadClient.cpp b/services/vr/virtual_touchpad/DvrVirtualTouchpadClient.cpp
new file mode 100644
index 0000000..eb152ed
--- /dev/null
+++ b/services/vr/virtual_touchpad/DvrVirtualTouchpadClient.cpp
@@ -0,0 +1,45 @@
+#include "VirtualTouchpadClient.h"
+#include "dvr/virtual_touchpad_client.h"
+
+struct DvrVirtualTouchpad {};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+namespace {
+android::dvr::VirtualTouchpad* FromC(DvrVirtualTouchpad* client) {
+ return reinterpret_cast<android::dvr::VirtualTouchpad*>(client);
+}
+} // namespace
+
+DvrVirtualTouchpad* dvrVirtualTouchpadCreate() {
+ return reinterpret_cast<DvrVirtualTouchpad*>(
+ android::dvr::VirtualTouchpadClient::Create().release());
+}
+
+void dvrVirtualTouchpadDestroy(DvrVirtualTouchpad* client) {
+ delete FromC(client);
+}
+
+int dvrVirtualTouchpadAttach(DvrVirtualTouchpad* client) {
+ return FromC(client)->Attach();
+}
+
+int dvrVirtualTouchpadDetach(DvrVirtualTouchpad* client) {
+ return FromC(client)->Detach();
+}
+
+int dvrVirtualTouchpadTouch(DvrVirtualTouchpad* client, int touchpad, float x,
+ float y, float pressure) {
+ return FromC(client)->Touch(touchpad, x, y, pressure);
+}
+
+int dvrVirtualTouchpadButtonState(DvrVirtualTouchpad* client, int touchpad,
+ int buttons) {
+ return FromC(client)->ButtonState(touchpad, buttons);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp b/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp
index 782b19c..c7c8184 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp
@@ -72,8 +72,8 @@
} // anonymous namespace
-sp<VirtualTouchpad> VirtualTouchpadClient::Create() {
- return new VirtualTouchpadClientImpl();
+std::unique_ptr<VirtualTouchpad> VirtualTouchpadClient::Create() {
+ return std::unique_ptr<VirtualTouchpad>(new VirtualTouchpadClientImpl());
}
} // namespace dvr
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
index 92193d3..ee09d48 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
@@ -30,10 +30,10 @@
} // anonymous namespace
-sp<VirtualTouchpad> VirtualTouchpadEvdev::Create() {
- VirtualTouchpadEvdev* const touchpad = new VirtualTouchpadEvdev();
+std::unique_ptr<VirtualTouchpad> VirtualTouchpadEvdev::Create() {
+ std::unique_ptr<VirtualTouchpadEvdev> touchpad(new VirtualTouchpadEvdev());
touchpad->Reset();
- return sp<VirtualTouchpad>(touchpad);
+ return touchpad;
}
void VirtualTouchpadEvdev::Reset() {
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h
index dbaca9a..2fb8ff3 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h
+++ b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h
@@ -1,8 +1,6 @@
#ifndef ANDROID_DVR_VIRTUAL_TOUCHPAD_EVDEV_H
#define ANDROID_DVR_VIRTUAL_TOUCHPAD_EVDEV_H
-#include <memory>
-
#include "EvdevInjector.h"
#include "VirtualTouchpad.h"
@@ -15,7 +13,8 @@
//
class VirtualTouchpadEvdev : public VirtualTouchpad {
public:
- static sp<VirtualTouchpad> Create();
+ static std::unique_ptr<VirtualTouchpad> Create();
+ ~VirtualTouchpadEvdev() override {}
// VirtualTouchpad implementation:
status_t Attach() override;
@@ -28,7 +27,6 @@
static constexpr int kTouchpads = 2;
VirtualTouchpadEvdev() {}
- ~VirtualTouchpadEvdev() override {}
void Reset();
// Must be called only between construction (or Detach()) and Attach().
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadService.h b/services/vr/virtual_touchpad/VirtualTouchpadService.h
index 194d787..cf236f9 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadService.h
+++ b/services/vr/virtual_touchpad/VirtualTouchpadService.h
@@ -13,8 +13,8 @@
//
class VirtualTouchpadService : public BnVirtualTouchpadService {
public:
- VirtualTouchpadService(sp<VirtualTouchpad> touchpad)
- : touchpad_(touchpad), client_pid_(0) {}
+ VirtualTouchpadService(std::unique_ptr<VirtualTouchpad> touchpad)
+ : touchpad_(std::move(touchpad)), client_pid_(0) {}
~VirtualTouchpadService() override;
protected:
@@ -31,7 +31,7 @@
bool CheckPermissions();
bool CheckTouchPermission(pid_t* out_pid);
- sp<VirtualTouchpad> touchpad_;
+ std::unique_ptr<VirtualTouchpad> touchpad_;
// Only one client at a time can use the virtual touchpad.
pid_t client_pid_;
diff --git a/services/vr/virtual_touchpad/include/VirtualTouchpad.h b/services/vr/virtual_touchpad/include/VirtualTouchpad.h
index b1ee700..da3a0b7 100644
--- a/services/vr/virtual_touchpad/include/VirtualTouchpad.h
+++ b/services/vr/virtual_touchpad/include/VirtualTouchpad.h
@@ -1,31 +1,34 @@
#ifndef ANDROID_DVR_VIRTUAL_TOUCHPAD_INTERFACE_H
#define ANDROID_DVR_VIRTUAL_TOUCHPAD_INTERFACE_H
+#include "dvr/virtual_touchpad_client.h"
+
+#include <memory>
#include <utils/Errors.h>
-#include <utils/RefBase.h>
#include <utils/String8.h>
-#include <utils/StrongPointer.h>
namespace android {
namespace dvr {
// Provides a virtual touchpad for injecting events into the input system.
//
-class VirtualTouchpad : public RefBase {
+class VirtualTouchpad {
public:
enum : int {
- PRIMARY = 0,
- VIRTUAL = 1,
+ PRIMARY = DVR_VIRTUAL_TOUCHPAD_PRIMARY,
+ VIRTUAL = DVR_VIRTUAL_TOUCHPAD_VIRTUAL,
};
+ virtual ~VirtualTouchpad() {}
+
// Create a virtual touchpad.
// Implementations should provide this, and hide their constructors.
// For the user, switching implementations should be as simple as changing
// the class whose |Create()| is called.
// Implementations should be minimial; major resource allocation should
// be performed in Attach().
- static sp<VirtualTouchpad> Create() {
- return sp<VirtualTouchpad>();
+ static std::unique_ptr<VirtualTouchpad> Create() {
+ return nullptr;
}
// Initialize a virtual touchpad.
@@ -63,7 +66,6 @@
protected:
VirtualTouchpad() {}
- ~VirtualTouchpad() override {}
private:
VirtualTouchpad(const VirtualTouchpad&) = delete;
diff --git a/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h b/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
index 471d9e0..23fb9f8 100644
--- a/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
+++ b/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
@@ -12,7 +12,7 @@
class VirtualTouchpadClient : public VirtualTouchpad {
public:
// VirtualTouchpad implementation:
- static sp<VirtualTouchpad> Create();
+ static std::unique_ptr<VirtualTouchpad> Create();
status_t Attach() override;
status_t Detach() override;
status_t Touch(int touchpad, float x, float y, float pressure) override;
diff --git a/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h b/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h
new file mode 100644
index 0000000..08cca1b
--- /dev/null
+++ b/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h
@@ -0,0 +1,71 @@
+#ifndef ANDROID_DVR_VIRTUAL_TOUCHPAD_C_CLIENT_H
+#define ANDROID_DVR_VIRTUAL_TOUCHPAD_C_CLIENT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct DvrVirtualTouchpad DvrVirtualTouchpad;
+
+enum {
+ DVR_VIRTUAL_TOUCHPAD_PRIMARY = 0,
+ DVR_VIRTUAL_TOUCHPAD_VIRTUAL = 1,
+};
+
+// Creates a new virtual touchpad client.
+//
+// @return Pointer to the created virtual touchpad client; nullptr on failure.
+//
+DvrVirtualTouchpad* dvrVirtualTouchpadCreate();
+
+// Destroys a virtual touchpad client.
+//
+// @param client Pointer to the virtual touchpad client to be destroyed.
+//
+void dvrVirtualTouchpadDestroy(DvrVirtualTouchpad* client);
+
+// Initialize the virtual touchpad.
+//
+// In the current server implementation, attachment creates and configures
+// the kernel virtual touchpad device(s). A single client may be attached
+// and detached repeatedly, e.g. on entering and leaving VR mode.
+//
+// @param client Pointer to the virtual touchpad client to be attached.
+// @return Zero on success, status_t-style error code on failure.
+//
+int dvrVirtualTouchpadAttach(DvrVirtualTouchpad* client);
+
+// Shut down the virtual touchpad.
+//
+// @param client Pointer to the virtual touchpad client to be detached.
+// @return Zero on success, status_t-style error code on failure.
+//
+int dvrVirtualTouchpadDetach(DvrVirtualTouchpad* client);
+
+// Generate a simulated touch event.
+//
+// @param client Pointer to the virtual touchpad client.
+// @param touchpad Selects touchpad.
+// @param x Horizontal touch position.
+// @param y Vertical touch position.
+// @param pressure Touch pressure; use 0.0 for no touch (lift or hover).
+// @return Zero on success, status_t-style error code on failure.
+//
+int dvrVirtualTouchpadTouch(DvrVirtualTouchpad* client, int touchpad, float x,
+ float y, float pressure);
+
+// Generate a simulated touchpad button state event.
+//
+// @param client Pointer to the virtual touchpad client.
+// @param touchpad Selects touchpad.
+// @param buttons A union of MotionEvent BUTTON_* values.
+// @return Zero on success, status_t-style error code on failure.
+//
+int dvrVirtualTouchpadButtonState(DvrVirtualTouchpad* client, int touchpad,
+ int buttons);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // ANDROID_DVR_VIRTUAL_TOUCHPAD_CLIENT_H
diff --git a/services/vr/virtual_touchpad/main.cpp b/services/vr/virtual_touchpad/main.cpp
index e73f8b9..68f1d70 100644
--- a/services/vr/virtual_touchpad/main.cpp
+++ b/services/vr/virtual_touchpad/main.cpp
@@ -9,7 +9,7 @@
int main() {
ALOGI("Starting");
android::dvr::VirtualTouchpadService touchpad_service(
- android::dvr::VirtualTouchpadEvdev::Create());
+ std::move(android::dvr::VirtualTouchpadEvdev::Create()));
signal(SIGPIPE, SIG_IGN);
android::sp<android::ProcessState> ps(android::ProcessState::self());
diff --git a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp b/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
index bc34850..24cfdf8 100644
--- a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
+++ b/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
@@ -95,7 +95,9 @@
class VirtualTouchpadForTesting : public VirtualTouchpadEvdev {
public:
- static sp<VirtualTouchpad> Create() { return sp<VirtualTouchpad>(New()); }
+ static std::unique_ptr<VirtualTouchpad> Create() {
+ return std::unique_ptr<VirtualTouchpad>(New());
+ }
static VirtualTouchpadForTesting* New() {
VirtualTouchpadForTesting* const touchpad = new VirtualTouchpadForTesting();
touchpad->Reset();
@@ -124,7 +126,8 @@
class VirtualTouchpadTest : public testing::Test {};
TEST_F(VirtualTouchpadTest, Goodness) {
- sp<VirtualTouchpadForTesting> touchpad(VirtualTouchpadForTesting::New());
+ std::unique_ptr<VirtualTouchpadForTesting> touchpad(
+ VirtualTouchpadForTesting::New());
UInputRecorder expect;
status_t touch_status = touchpad->Attach();
@@ -284,7 +287,8 @@
}
TEST_F(VirtualTouchpadTest, Badness) {
- sp<VirtualTouchpadForTesting> touchpad(VirtualTouchpadForTesting::New());
+ std::unique_ptr<VirtualTouchpadForTesting> touchpad(
+ VirtualTouchpadForTesting::New());
UInputRecorder expect;
UInputRecorder& record = touchpad->injector[VirtualTouchpad::PRIMARY].record;
diff --git a/services/vr/vr_window_manager/Android.bp b/services/vr/vr_window_manager/Android.bp
new file mode 100644
index 0000000..a7a341c
--- /dev/null
+++ b/services/vr/vr_window_manager/Android.bp
@@ -0,0 +1,103 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+subdirs = [ "composer", ]
+
+native_src = [
+ "application.cpp",
+ "controller_mesh.cpp",
+ "elbow_model.cpp",
+ "hwc_callback.cpp",
+ "reticle.cpp",
+ "shell_view.cpp",
+ "surface_flinger_view.cpp",
+ "texture.cpp",
+ "vr_window_manager.cpp",
+ "vr_window_manager_binder.cpp",
+ "aidl/android/service/vr/IVrWindowManager.aidl",
+ "display_view.cpp",
+]
+
+static_libs = [
+ "libdisplay",
+ "libbufferhub",
+ "libbufferhubqueue",
+ "libeds",
+ "libdvrgraphics",
+ "libdvrcommon",
+ "libhwcomposer-client",
+ "libvrsensor",
+ "libperformance",
+ "libpdx_default_transport",
+ "libcutils",
+ "libvr_manager",
+ "libvirtualtouchpadclient",
+]
+
+shared_libs = [
+ "android.dvr.composer@1.0",
+ "android.hardware.graphics.composer@2.1",
+ "libvrhwc",
+ "libbase",
+ "libbinder",
+ "libinput",
+ "libhardware",
+ "libhwbinder",
+ "libsync",
+ "libutils",
+ "libgui",
+ "libEGL",
+ "libGLESv2",
+ "libvulkan",
+ "libsync",
+ "libui",
+ "libhidlbase",
+ "libhidltransport",
+ "liblog",
+]
+
+cc_binary {
+ srcs: native_src,
+ static_libs: static_libs,
+ shared_libs: shared_libs,
+ cflags: ["-DGL_GLEXT_PROTOTYPES", "-DEGL_EGLEXT_PROTOTYPES", "-DLOG_TAG=\"VrWindowManager\""],
+ host_ldlibs: ["-llog"],
+ name: "vr_wm",
+ tags: ["optional"],
+ init_rc: ["vr_wm.rc"],
+}
+
+cmd_src = [
+ "vr_wm_ctl.cpp",
+ "aidl/android/service/vr/IVrWindowManager.aidl",
+]
+
+staticLibs = ["libcutils"]
+
+sharedLibs = [
+ "libbase",
+ "libbinder",
+ "libutils",
+]
+
+cc_binary {
+ srcs: cmd_src,
+ static_libs: staticLibs,
+ shared_libs: sharedLibs,
+ cppflags: ["-std=c++11"],
+ cflags: ["-DLOG_TAG=\"vrwmctl\""],
+ host_ldlibs: ["-llog"],
+ name: "vr_wm_ctl",
+ tags: ["optional"],
+}
diff --git a/services/vr/vr_window_manager/Android.mk b/services/vr/vr_window_manager/Android.mk
deleted file mode 100644
index 59ef63c..0000000
--- a/services/vr/vr_window_manager/Android.mk
+++ /dev/null
@@ -1,100 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-native_src := \
- application.cpp \
- controller_mesh.cpp \
- display_view.cpp \
- elbow_model.cpp \
- hwc_callback.cpp \
- reticle.cpp \
- shell_view.cpp \
- surface_flinger_view.cpp \
- texture.cpp \
- vr_window_manager.cpp \
- vr_window_manager_binder.cpp \
- aidl/android/service/vr/IVrWindowManager.aidl
-
-static_libs := \
- libdisplay \
- libbufferhub \
- libbufferhubqueue \
- libeds \
- libdvrgraphics \
- libdvrcommon \
- libhwcomposer-client \
- libsensor \
- libperformance \
- libpdx_default_transport \
- libcutils \
- libvr_manager \
- libvirtualtouchpadclient
-
-shared_libs := \
- android.dvr.composer@1.0 \
- android.hardware.graphics.composer@2.1 \
- libvrhwc \
- libbase \
- libbinder \
- libinput \
- libhardware \
- libhwbinder \
- libsync \
- libutils \
- libgui \
- libEGL \
- libGLESv2 \
- libvulkan \
- libsync \
- libui \
- libhidlbase \
- libhidltransport
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(native_src)
-LOCAL_STATIC_LIBRARIES := $(static_libs)
-LOCAL_SHARED_LIBRARIES := $(shared_libs)
-LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES
-LOCAL_CFLAGS += -DEGL_EGLEXT_PROTOTYPES
-LOCAL_CFLAGS += -DLOG_TAG=\"VrWindowManager\"
-LOCAL_LDLIBS := -llog
-LOCAL_MODULE := vr_wm
-LOCAL_MODULE_TAGS := optional
-LOCAL_INIT_RC := vr_wm.rc
-include $(BUILD_EXECUTABLE)
-
-cmd_src := \
- vr_wm_ctl.cpp \
- aidl/android/service/vr/IVrWindowManager.aidl
-
-static_libs := \
- libcutils
-
-shared_libs := \
- libbase \
- libbinder \
- libutils
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(cmd_src)
-LOCAL_STATIC_LIBRARIES := $(static_libs)
-LOCAL_SHARED_LIBRARIES := $(shared_libs)
-LOCAL_CPPFLAGS += -std=c++11
-LOCAL_CFLAGS += -DLOG_TAG=\"vrwmctl\"
-LOCAL_LDLIBS := -llog
-LOCAL_MODULE := vr_wm_ctl
-LOCAL_MODULE_TAGS := optional
-include $(BUILD_EXECUTABLE)
diff --git a/services/vr/vr_window_manager/composer/Android.bp b/services/vr/vr_window_manager/composer/Android.bp
index 7c8bb86..4349269 100644
--- a/services/vr/vr_window_manager/composer/Android.bp
+++ b/services/vr/vr_window_manager/composer/Android.bp
@@ -13,6 +13,10 @@
static_libs: [
"libhwcomposer-client",
+ "libdisplay",
+ "libpdx_default_transport",
+ "libbufferhub",
+ "libbufferhubqueue",
],
shared_libs: [
diff --git a/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp b/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
index 8b50c01..684d15b 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
+++ b/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
@@ -21,6 +21,8 @@
#include <mutex>
+#include <private/dvr/display_client.h>
+
#include "vr_composer_client.h"
using namespace android::hardware::graphics::common::V1_0;
@@ -238,12 +240,14 @@
}
}
-uint32_t VrHwc::getMaxVirtualDisplayCount() { return 0; }
+uint32_t VrHwc::getMaxVirtualDisplayCount() { return 1; }
Error VrHwc::createVirtualDisplay(uint32_t width, uint32_t height,
PixelFormat* format, Display* outDisplay) {
*format = PixelFormat::RGBA_8888;
- *outDisplay = 0;
+ *outDisplay = display_count_;
+ displays_[display_count_].reset(new HwcDisplay());
+ display_count_++;
return Error::NONE;
}
@@ -354,7 +358,11 @@
return Error::BAD_DISPLAY;
}
- *outType = IComposerClient::DisplayType::PHYSICAL;
+ if (display == kDefaultDisplayId)
+ *outType = IComposerClient::DisplayType::PHYSICAL;
+ else
+ *outType = IComposerClient::DisplayType::VIRTUAL;
+
return Error::NONE;
}
@@ -441,8 +449,8 @@
if (!display_ptr)
return Error::BAD_DISPLAY;
- ALOGE("Virtual display support not implemented");
- return Error::UNSUPPORTED;
+ // TODO(dnicoara): Is it necessary to do anything here?
+ return Error::NONE;
}
Error VrHwc::validateDisplay(
diff --git a/services/vr/vr_window_manager/composer/impl/vr_hwc.h b/services/vr/vr_window_manager/composer/impl/vr_hwc.h
index b869d3e..3c76120 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_hwc.h
+++ b/services/vr/vr_window_manager/composer/impl/vr_hwc.h
@@ -248,6 +248,7 @@
std::mutex mutex_;
std::unordered_map<Display, std::unique_ptr<HwcDisplay>> displays_;
+ Display display_count_ = 2;
Observer* observer_ = nullptr;
diff --git a/services/vr/vr_window_manager/hwc_callback.cpp b/services/vr/vr_window_manager/hwc_callback.cpp
index b755c60..2d2a85c 100644
--- a/services/vr/vr_window_manager/hwc_callback.cpp
+++ b/services/vr/vr_window_manager/hwc_callback.cpp
@@ -41,6 +41,7 @@
base::unique_fd HwcCallback::OnNewFrame(const ComposerView::Frame& display_frame) {
auto& frame = display_frame.layers;
std::vector<HwcLayer> hwc_frame(frame.size());
+
for (size_t i = 0; i < frame.size(); ++i) {
hwc_frame[i] = HwcLayer{
.fence = frame[i].fence,
diff --git a/services/vr/vr_window_manager/shell_view.cpp b/services/vr/vr_window_manager/shell_view.cpp
index 72a2c26..a21e883 100644
--- a/services/vr/vr_window_manager/shell_view.cpp
+++ b/services/vr/vr_window_manager/shell_view.cpp
@@ -5,6 +5,7 @@
#include <android/input.h>
#include <binder/IServiceManager.h>
#include <hardware/hwcomposer2.h>
+#include <inttypes.h>
#include <log/log.h>
#include "controller_mesh.h"
@@ -95,7 +96,8 @@
}
int GetTouchIdForDisplay(uint32_t display) {
- return display == 1 ? VirtualTouchpad::PRIMARY : VirtualTouchpad::VIRTUAL;
+ return display == 1 ? DVR_VIRTUAL_TOUCHPAD_PRIMARY
+ : DVR_VIRTUAL_TOUCHPAD_VIRTUAL;
}
} // namespace
@@ -109,8 +111,9 @@
if (ret)
return ret;
- virtual_touchpad_ = VirtualTouchpadClient::Create();
- const status_t touchpad_status = virtual_touchpad_->Attach();
+ virtual_touchpad_.reset(dvrVirtualTouchpadCreate());
+ const status_t touchpad_status =
+ dvrVirtualTouchpadAttach(virtual_touchpad_.get());
if (touchpad_status != OK) {
ALOGE("Failed to connect to virtual touchpad");
return touchpad_status;
@@ -164,13 +167,11 @@
}
void ShellView::EnableDebug(bool debug) {
- ALOGI("EnableDebug(%d)", (int)debug); // XXX TODO delete
QueueTask(debug ? MainThreadTask::EnableDebugMode
: MainThreadTask::DisableDebugMode);
}
void ShellView::VrMode(bool mode) {
- ALOGI("VrMode(%d)", (int)mode); // XXX TODO delete
QueueTask(mode ? MainThreadTask::EnteringVrMode
: MainThreadTask::ExitingVrMode);
}
@@ -180,6 +181,13 @@
result.appendFormat("initialized = %s\n", initialized_ ? "true" : "false");
result.appendFormat("is_visible = %s\n", is_visible_ ? "true" : "false");
result.appendFormat("debug_mode = %s\n\n", debug_mode_ ? "true" : "false");
+
+ result.append("[displays]\n");
+ result.appendFormat("count = %zu\n", displays_.size());
+ for (size_t i = 0; i < displays_.size(); ++i)
+ result.appendFormat(" display_id = %" PRId32 "\n", displays_[i]->id());
+
+ result.append("\n");
}
void ShellView::OnDrawFrame() {
@@ -419,7 +427,7 @@
}
void ShellView::Touch() {
- if (!virtual_touchpad_.get()) {
+ if (!virtual_touchpad_) {
ALOGE("missing virtual touchpad");
return;
}
@@ -431,8 +439,8 @@
// Device is portrait, but in landscape when in VR.
// Rotate touch input appropriately.
- const android::status_t status = virtual_touchpad_->Touch(
- active_display_->touchpad_id(),
+ const android::status_t status = dvrVirtualTouchpadTouch(
+ virtual_touchpad_.get(), active_display_->touchpad_id(),
1.0f - hit_location.y() / size_.y(), hit_location.x() / size_.x(),
is_touching_ ? 1.0f : 0.0f);
if (status != OK) {
@@ -453,7 +461,7 @@
return true;
}
touchpad_buttons_ = buttons;
- if (!virtual_touchpad_.get()) {
+ if (!virtual_touchpad_) {
ALOGE("missing virtual touchpad");
return false;
}
@@ -461,8 +469,9 @@
if (!active_display_)
return true;
- const android::status_t status = virtual_touchpad_->ButtonState(
- active_display_->touchpad_id(), touchpad_buttons_);
+ const android::status_t status = dvrVirtualTouchpadButtonState(
+ virtual_touchpad_.get(), active_display_->touchpad_id(),
+ touchpad_buttons_);
if (status != OK) {
ALOGE("touchpad button failed: %d %d", touchpad_buttons_, status);
}
diff --git a/services/vr/vr_window_manager/shell_view.h b/services/vr/vr_window_manager/shell_view.h
index c10bd27..856c8b8 100644
--- a/services/vr/vr_window_manager/shell_view.h
+++ b/services/vr/vr_window_manager/shell_view.h
@@ -1,12 +1,12 @@
#ifndef VR_WINDOW_MANAGER_SHELL_VIEW_H_
#define VR_WINDOW_MANAGER_SHELL_VIEW_H_
+#include <dvr/virtual_touchpad_client.h>
#include <private/dvr/graphics/mesh.h>
#include <private/dvr/graphics/shader_program.h>
#include <deque>
-#include "VirtualTouchpadClient.h"
#include "application.h"
#include "display_view.h"
#include "reticle.h"
@@ -53,7 +53,6 @@
DisplayView* FindActiveDisplay(const vec3& position, const quat& quaternion,
vec3* hit_location);
-
// HwcCallback::Client:
base::unique_fd OnFrame(std::unique_ptr<HwcCallback::Frame> frame) override;
DisplayView* FindOrCreateDisplay(uint32_t id);
@@ -64,7 +63,15 @@
std::unique_ptr<SurfaceFlingerView> surface_flinger_view_;
std::unique_ptr<Reticle> reticle_;
- sp<VirtualTouchpad> virtual_touchpad_;
+
+ struct DvrVirtualTouchpadDeleter {
+ void operator()(DvrVirtualTouchpad* p) {
+ dvrVirtualTouchpadDetach(p);
+ dvrVirtualTouchpadDestroy(p);
+ }
+ };
+ std::unique_ptr<DvrVirtualTouchpad, DvrVirtualTouchpadDeleter>
+ virtual_touchpad_;
std::unique_ptr<Mesh<vec3, vec3, vec2>> controller_mesh_;
diff --git a/services/vr/vr_window_manager/surface_flinger_view.cpp b/services/vr/vr_window_manager/surface_flinger_view.cpp
index 2011967..8411806 100644
--- a/services/vr/vr_window_manager/surface_flinger_view.cpp
+++ b/services/vr/vr_window_manager/surface_flinger_view.cpp
@@ -1,6 +1,7 @@
#include "surface_flinger_view.h"
#include <impl/vr_composer_view.h>
+#include <private/dvr/display_client.h>
#include <private/dvr/native_buffer.h>
#include "hwc_callback.h"
@@ -38,7 +39,7 @@
vr_composer_view_->Initialize(GetComposerViewFromIComposer(
vr_hwcomposer_.get()));
- // TODO(dnicoara): Query this from the composer service.
+ // TODO(alexst): Refactor ShellView to account for orientation and change this back.
width_ = 1920;
height_ = 1080;
return true;
diff --git a/vulkan/Android.bp b/vulkan/Android.bp
index 3f077a2..3fd8c51 100644
--- a/vulkan/Android.bp
+++ b/vulkan/Android.bp
@@ -23,7 +23,7 @@
license: "include/vulkan/NOTICE",
}
-cc_library_static {
+cc_library_headers {
name: "vulkan_headers",
export_include_dirs: ["include"],
}
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index b4708b0..86dd001 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -320,6 +320,10 @@
@extension("VK_KHR_shared_presentable_image") define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1
@extension("VK_KHR_shared_presentable_image") define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image"
+// 119
+@extension("VK_KHR_get_surface_capabilities2") define VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION 1
+@extension("VK_KHR_get_surface_capabilities2") define VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME "VK_KHR_get_surface_capabilities2"
+
// 123
@extension("VK_MVK_ios_surface") define VK_MVK_IOS_SURFACE_SPEC_VERSION 1
@extension("VK_MVK_ios_surface") define VK_MVK_IOS_SURFACE_EXTENSION_NAME "VK_MVK_ios_surface"
@@ -1082,6 +1086,14 @@
//@extension("VK_EXT_hdr_metadata") // 106
VK_STRUCTURE_TYPE_HDR_METADATA_EXT = 1000105000,
+ //@extension("VK_KHR_shared_presentable_image") // 111
+ VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR = 1000111000,
+
+ //@extension("VK_KHR_get_surface_capabilities2") // 119
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR = 1000119000,
+ VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR = 1000119001,
+ VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR = 1000119002,
+
//@extension("VK_MVK_ios_surface") // 123
VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK = 1000122000,
@@ -4245,6 +4257,34 @@
f32 maxFrameAverageLightLevel
}
+@extension("VK_KHR_shared_presentable_image") // 111
+class VkSharedPresentSurfaceCapabilitiesKHR {
+ VkStructureType sType
+ const void* pNext
+ VkImageUsageFlags sharedPresentSupportedUsageFlags
+}
+
+@extension("VK_KHR_get_surface_capabilities2") // 119
+class VkPhysicalDeviceSurfaceInfo2KHR {
+ VkStructureType sType
+ const void* pNext
+ VkSurfaceKHR surface
+}
+
+@extension("VK_KHR_get_surface_capabilities2") // 119
+class VkSurfaceCapabilities2KHR {
+ VkStructureType sType
+ void* pNext
+ VkSurfaceCapabilitiesKHR surfaceCapabilities
+}
+
+@extension("VK_KHR_get_surface_capabilities2") // 119
+class VkSurfaceFormat2KHR {
+ VkStructureType sType
+ void* pNext
+ VkSurfaceFormatKHR surfaceFormat
+}
+
@extension("VK_MVK_ios_surface") // 123
class VkIOSSurfaceCreateInfoMVK {
VkStructureType sType
@@ -7418,6 +7458,23 @@
return ?
}
+@extension("VK_KHR_get_surface_capabilities2") // 119
+cmd VkResult vkGetPhysicalDeviceSurfaceCapabilities2KHR(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ VkSurfaceCapabilities2KHR* pSurfaceCapabilities) {
+ return ?
+}
+
+@extension("VK_KHR_get_surface_capabilities2") // 119
+cmd VkResult vkGetPhysicalDeviceSurfaceFormats2KHR(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ u32* pSurfaceFormatCount,
+ VkSurfaceFormat2KHR* pSurfaceFormats) {
+ return ?
+}
+
@extension("VK_MVK_ios_surface") // 123
cmd VkResult vkCreateIOSSurfaceMVK(
VkInstance instance,
diff --git a/vulkan/include/vulkan/vulkan.h b/vulkan/include/vulkan/vulkan.h
index 8bb5448..4b3b8bf 100644
--- a/vulkan/include/vulkan/vulkan.h
+++ b/vulkan/include/vulkan/vulkan.h
@@ -301,6 +301,10 @@
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT = 1000099000,
VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT = 1000099001,
VK_STRUCTURE_TYPE_HDR_METADATA_EXT = 1000105000,
+ VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR = 1000111000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR = 1000119000,
+ VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR = 1000119001,
+ VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR = 1000119002,
VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK = 1000122000,
VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000,
VK_STRUCTURE_TYPE_BEGIN_RANGE = VK_STRUCTURE_TYPE_APPLICATION_INFO,
@@ -3302,14 +3306,14 @@
VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0,
VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT = 1000104001,
VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT = 1000104002,
- VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT = 1000104003,
- VK_COLOR_SPACE_DCI_P3_LINEAR_EXT = 1000104004,
- VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT = 1000104005,
- VK_COLOR_SPACE_BT709_LINEAR_EXT = 1000104006,
- VK_COLOR_SPACE_BT709_NONLINEAR_EXT = 1000104007,
- VK_COLOR_SPACE_BT2020_LINEAR_EXT = 1000104008,
- VK_COLOR_SPACE_BT2020_170M_EXT = 1000104009,
- VK_COLOR_SPACE_BT2020_ST2084_EXT = 1000104010,
+ VK_COLOR_SPACE_DCI_P3_LINEAR_EXT = 1000104003,
+ VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT = 1000104004,
+ VK_COLOR_SPACE_BT709_LINEAR_EXT = 1000104005,
+ VK_COLOR_SPACE_BT709_NONLINEAR_EXT = 1000104006,
+ VK_COLOR_SPACE_BT2020_LINEAR_EXT = 1000104007,
+ VK_COLOR_SPACE_HDR10_ST2084_EXT = 1000104008,
+ VK_COLOR_SPACE_DOLBYVISION_EXT = 1000104009,
+ VK_COLOR_SPACE_HDR10_HLG_EXT = 1000104010,
VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT = 1000104011,
VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT = 1000104012,
VK_COLOR_SPACE_PASS_THROUGH_EXT = 1000104013,
@@ -5766,6 +5770,13 @@
#define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1
#define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image"
+typedef struct VkSharedPresentSurfaceCapabilitiesKHR {
+ VkStructureType sType;
+ void* pNext;
+ VkImageUsageFlags sharedPresentSupportedUsageFlags;
+} VkSharedPresentSurfaceCapabilitiesKHR;
+
+
typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainStatusKHR)(VkDevice device, VkSwapchainKHR swapchain);
#ifndef VK_NO_PROTOTYPES
@@ -5774,6 +5785,46 @@
VkSwapchainKHR swapchain);
#endif
+#define VK_KHR_get_surface_capabilities2 1
+#define VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION 1
+#define VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME "VK_KHR_get_surface_capabilities2"
+
+typedef struct VkPhysicalDeviceSurfaceInfo2KHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkSurfaceKHR surface;
+} VkPhysicalDeviceSurfaceInfo2KHR;
+
+typedef struct VkSurfaceCapabilities2KHR {
+ VkStructureType sType;
+ void* pNext;
+ VkSurfaceCapabilitiesKHR surfaceCapabilities;
+} VkSurfaceCapabilities2KHR;
+
+typedef struct VkSurfaceFormat2KHR {
+ VkStructureType sType;
+ void* pNext;
+ VkSurfaceFormatKHR surfaceFormat;
+} VkSurfaceFormat2KHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2KHR(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ VkSurfaceCapabilities2KHR* pSurfaceCapabilities);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormats2KHR(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ uint32_t* pSurfaceFormatCount,
+ VkSurfaceFormat2KHR* pSurfaceFormats);
+#endif
+
+
#ifdef VK_USE_PLATFORM_IOS_MVK
#define VK_MVK_ios_surface 1
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 524de75..2fe880a 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -64,8 +64,8 @@
"vulkan_loader_data.cpp",
],
- export_static_lib_headers: ["vulkan_headers"],
- static_libs: [
+ export_header_lib_headers: ["vulkan_headers"],
+ header_libs: [
"vulkan_headers",
],
shared_libs: [
diff --git a/vulkan/libvulkan/api_gen.cpp b/vulkan/libvulkan/api_gen.cpp
index 69e38de..54c77f1 100644
--- a/vulkan/libvulkan/api_gen.cpp
+++ b/vulkan/libvulkan/api_gen.cpp
@@ -110,7 +110,7 @@
// clang-format on
-} // anonymous
+} // namespace
bool InitDispatchTable(
VkInstance instance,
@@ -473,7 +473,9 @@
"vkGetPhysicalDeviceQueueFamilyProperties2KHR",
"vkGetPhysicalDeviceSparseImageFormatProperties",
"vkGetPhysicalDeviceSparseImageFormatProperties2KHR",
+ "vkGetPhysicalDeviceSurfaceCapabilities2KHR",
"vkGetPhysicalDeviceSurfaceCapabilitiesKHR",
+ "vkGetPhysicalDeviceSurfaceFormats2KHR",
"vkGetPhysicalDeviceSurfaceFormatsKHR",
"vkGetPhysicalDeviceSurfacePresentModesKHR",
"vkGetPhysicalDeviceSurfaceSupportKHR",
diff --git a/vulkan/libvulkan/api_gen.h b/vulkan/libvulkan/api_gen.h
index 7f8d274..3e50fda 100644
--- a/vulkan/libvulkan/api_gen.h
+++ b/vulkan/libvulkan/api_gen.h
@@ -19,8 +19,8 @@
#ifndef LIBVULKAN_API_GEN_H
#define LIBVULKAN_API_GEN_H
-#include <bitset>
#include <vulkan/vulkan.h>
+#include <bitset>
#include "driver_gen.h"
namespace vulkan {
diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl
index 185121c..5bbe116 100644
--- a/vulkan/libvulkan/code-generator.tmpl
+++ b/vulkan/libvulkan/code-generator.tmpl
@@ -690,6 +690,7 @@
VK_KHR_shared_presentable_image
VK_KHR_surface
VK_KHR_swapchain
+VK_KHR_get_surface_capabilities2
{{end}}
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index b62eec6..dbb217d 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -448,6 +448,7 @@
case ProcHook::KHR_android_surface:
case ProcHook::KHR_surface:
case ProcHook::EXT_swapchain_colorspace:
+ case ProcHook::KHR_get_surface_capabilities2:
hook_extensions_.set(ext_bit);
// return now as these extensions do not require HAL support
return;
@@ -674,13 +675,15 @@
const char* pLayerName,
uint32_t* pPropertyCount,
VkExtensionProperties* pProperties) {
- static const std::array<VkExtensionProperties, 3> loader_extensions = {{
+ static const std::array<VkExtensionProperties, 4> loader_extensions = {{
// WSI extensions
{VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION},
{VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
VK_KHR_ANDROID_SURFACE_SPEC_VERSION},
{VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME,
VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION},
+ {VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME,
+ VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION},
}};
static const VkExtensionProperties loader_debug_report_extension = {
VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION,
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index fc3f87a..82b464e 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -262,6 +262,13 @@
reinterpret_cast<PFN_vkVoidFunction>(checkedGetPastPresentationTimingGOOGLE),
},
{
+ "vkGetPhysicalDeviceSurfaceCapabilities2KHR",
+ ProcHook::INSTANCE,
+ ProcHook::KHR_get_surface_capabilities2,
+ reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceCapabilities2KHR),
+ nullptr,
+ },
+ {
"vkGetPhysicalDeviceSurfaceCapabilitiesKHR",
ProcHook::INSTANCE,
ProcHook::KHR_surface,
@@ -269,6 +276,13 @@
nullptr,
},
{
+ "vkGetPhysicalDeviceSurfaceFormats2KHR",
+ ProcHook::INSTANCE,
+ ProcHook::KHR_get_surface_capabilities2,
+ reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceFormats2KHR),
+ nullptr,
+ },
+ {
"vkGetPhysicalDeviceSurfaceFormatsKHR",
ProcHook::INSTANCE,
ProcHook::KHR_surface,
@@ -348,7 +362,7 @@
// clang-format on
};
-} // anonymous
+} // namespace
const ProcHook* GetProcHook(const char* name) {
const auto& begin = g_proc_hooks;
@@ -372,6 +386,7 @@
if (strcmp(name, "VK_KHR_shared_presentable_image") == 0) return ProcHook::KHR_shared_presentable_image;
if (strcmp(name, "VK_KHR_surface") == 0) return ProcHook::KHR_surface;
if (strcmp(name, "VK_KHR_swapchain") == 0) return ProcHook::KHR_swapchain;
+ if (strcmp(name, "VK_KHR_get_surface_capabilities2") == 0) return ProcHook::KHR_get_surface_capabilities2;
if (strcmp(name, "VK_KHR_get_physical_device_properties2") == 0) return ProcHook::KHR_get_physical_device_properties2;
// clang-format on
return ProcHook::EXTENSION_UNKNOWN;
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index 738da5b..3b26a80 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -19,9 +19,9 @@
#ifndef LIBVULKAN_DRIVER_GEN_H
#define LIBVULKAN_DRIVER_GEN_H
-#include <bitset>
-#include <vulkan/vulkan.h>
#include <vulkan/vk_android_native_buffer.h>
+#include <vulkan/vulkan.h>
+#include <bitset>
namespace vulkan {
namespace driver {
@@ -43,6 +43,7 @@
KHR_shared_presentable_image,
KHR_surface,
KHR_swapchain,
+ KHR_get_surface_capabilities2,
KHR_get_physical_device_properties2,
EXTENSION_CORE, // valid bit
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 7dac99a..5017e14 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -410,8 +410,6 @@
return HAL_DATASPACE_DISPLAY_P3;
case VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT:
return HAL_DATASPACE_V0_SCRGB_LINEAR;
- case VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT:
- return HAL_DATASPACE_V0_SCRGB;
case VK_COLOR_SPACE_DCI_P3_LINEAR_EXT:
return HAL_DATASPACE_DCI_P3_LINEAR;
case VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT:
@@ -420,14 +418,20 @@
return HAL_DATASPACE_V0_SRGB_LINEAR;
case VK_COLOR_SPACE_BT709_NONLINEAR_EXT:
return HAL_DATASPACE_V0_SRGB;
- case VK_COLOR_SPACE_BT2020_170M_EXT:
- return static_cast<android_dataspace>(
- HAL_DATASPACE_STANDARD_BT2020 |
- HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_RANGE_FULL);
- case VK_COLOR_SPACE_BT2020_ST2084_EXT:
+ case VK_COLOR_SPACE_BT2020_LINEAR_EXT:
+ return HAL_DATASPACE_BT2020_LINEAR;
+ case VK_COLOR_SPACE_HDR10_ST2084_EXT:
return static_cast<android_dataspace>(
HAL_DATASPACE_STANDARD_BT2020 | HAL_DATASPACE_TRANSFER_ST2084 |
HAL_DATASPACE_RANGE_FULL);
+ case VK_COLOR_SPACE_DOLBYVISION_EXT:
+ return static_cast<android_dataspace>(
+ HAL_DATASPACE_STANDARD_BT2020 | HAL_DATASPACE_TRANSFER_ST2084 |
+ HAL_DATASPACE_RANGE_FULL);
+ case VK_COLOR_SPACE_HDR10_HLG_EXT:
+ return static_cast<android_dataspace>(
+ HAL_DATASPACE_STANDARD_BT2020 | HAL_DATASPACE_TRANSFER_HLG |
+ HAL_DATASPACE_RANGE_FULL);
case VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT:
return static_cast<android_dataspace>(
HAL_DATASPACE_STANDARD_ADOBE_RGB |
@@ -648,6 +652,72 @@
}
VKAPI_ATTR
+VkResult GetPhysicalDeviceSurfaceCapabilities2KHR(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ VkSurfaceCapabilities2KHR* pSurfaceCapabilities) {
+ VkResult result = GetPhysicalDeviceSurfaceCapabilitiesKHR(
+ physicalDevice, pSurfaceInfo->surface,
+ &pSurfaceCapabilities->surfaceCapabilities);
+
+ VkSurfaceCapabilities2KHR* caps = pSurfaceCapabilities;
+ while (caps->pNext) {
+ caps = reinterpret_cast<VkSurfaceCapabilities2KHR*>(caps->pNext);
+
+ switch (caps->sType) {
+ case VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR: {
+ VkSharedPresentSurfaceCapabilitiesKHR* shared_caps =
+ reinterpret_cast<VkSharedPresentSurfaceCapabilitiesKHR*>(
+ caps);
+ // Claim same set of usage flags are supported for
+ // shared present modes as for other modes.
+ shared_caps->sharedPresentSupportedUsageFlags =
+ pSurfaceCapabilities->surfaceCapabilities
+ .supportedUsageFlags;
+ } break;
+
+ default:
+ // Ignore all other extension structs
+ break;
+ }
+ }
+
+ return result;
+}
+
+VKAPI_ATTR
+VkResult GetPhysicalDeviceSurfaceFormats2KHR(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ uint32_t* pSurfaceFormatCount,
+ VkSurfaceFormat2KHR* pSurfaceFormats) {
+ if (!pSurfaceFormats) {
+ return GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice,
+ pSurfaceInfo->surface,
+ pSurfaceFormatCount, nullptr);
+ } else {
+ // temp vector for forwarding; we'll marshal it into the pSurfaceFormats
+ // after the call.
+ android::Vector<VkSurfaceFormatKHR> surface_formats;
+ surface_formats.resize(*pSurfaceFormatCount);
+ VkResult result = GetPhysicalDeviceSurfaceFormatsKHR(
+ physicalDevice, pSurfaceInfo->surface, pSurfaceFormatCount,
+ &surface_formats.editItemAt(0));
+
+ if (result == VK_SUCCESS || result == VK_INCOMPLETE) {
+ // marshal results individually due to stride difference.
+ // completely ignore any chained extension structs.
+ uint32_t formats_to_marshal = *pSurfaceFormatCount;
+ for (uint32_t i = 0u; i < formats_to_marshal; i++) {
+ pSurfaceFormats[i].surfaceFormat = surface_formats[i];
+ }
+ }
+
+ return result;
+ }
+}
+
+VKAPI_ATTR
VkResult GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice pdev,
VkSurfaceKHR /*surface*/,
uint32_t* count,
diff --git a/vulkan/libvulkan/swapchain.h b/vulkan/libvulkan/swapchain.h
index 976c995..e3cf624 100644
--- a/vulkan/libvulkan/swapchain.h
+++ b/vulkan/libvulkan/swapchain.h
@@ -38,6 +38,8 @@
VKAPI_ATTR VkResult GetPastPresentationTimingGOOGLE(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings);
VKAPI_ATTR VkResult GetSwapchainStatusKHR(VkDevice device, VkSwapchainKHR swapchain);
VKAPI_ATTR void SetHdrMetadataEXT(VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pHdrMetadataEXTs);
+VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities);
+VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats);
// clang-format on
} // namespace driver
diff --git a/vulkan/nulldrv/Android.bp b/vulkan/nulldrv/Android.bp
index ea3b781..3329609 100644
--- a/vulkan/nulldrv/Android.bp
+++ b/vulkan/nulldrv/Android.bp
@@ -42,6 +42,6 @@
"null_driver_gen.cpp",
],
- static_libs: ["vulkan_headers"],
+ header_libs: ["vulkan_headers"],
shared_libs: ["liblog"],
}
diff --git a/vulkan/nulldrv/null_driver_gen.cpp b/vulkan/nulldrv/null_driver_gen.cpp
index 7cbbdb1..25ee65a 100644
--- a/vulkan/nulldrv/null_driver_gen.cpp
+++ b/vulkan/nulldrv/null_driver_gen.cpp
@@ -16,8 +16,8 @@
// WARNING: This file is generated. See ../README.md for instructions.
-#include "null_driver_gen.h"
#include <algorithm>
+#include "null_driver_gen.h"
using namespace null_driver;