Merge changes Ica5f5f5c,Ifb7d2cec,Ia402b4bc,I9c3b6b7e,I36ba19c7, ... into oc-dev
* changes:
libgui: Make IGraphicBufferConsumer a SafeInterface
libbinder: Add vector<Parcelable> to SafeInterface
libbinder: Add sp<NativeHandle> to SafeInterface
libbinder: Support enums in SafeInterface
libbinder: Support sp<Flattenable> in SafeInterface
libbinder: Add int64_t/uint64_t to SafeInterface
libgui: Normalize IGraphicBufferConsumer methods
libgui: Format IGraphicBufferConsumer
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index cc4144a..f5dca47 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -836,7 +836,7 @@
continue;
}
- if (!should_dump_hal_interface(info.interfaceName)) {
+ if (!should_dump_hal_interface(info.interfaceName.c_str())) {
continue;
}
diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk
index be1a434..1d21b3c 100644
--- a/cmds/installd/Android.mk
+++ b/cmds/installd/Android.mk
@@ -24,6 +24,7 @@
LOCAL_CFLAGS += -DART_BASE_ADDRESS_MAX_DELTA=$(LOCAL_LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA)
LOCAL_SRC_FILES := otapreopt.cpp globals.cpp utils.cpp dexopt.cpp
+LOCAL_HEADER_LIBRARIES := dex2oat_headers
LOCAL_SHARED_LIBRARIES := \
libbase \
libcutils \
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 20b960d..3e0f6f0 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -1152,6 +1152,9 @@
}
}
+#if HACK_FOR_37193650
+ extStats->dataSize = extStats->dataSize;
+#else
int extGid = multiuser_get_ext_gid(userId, appId);
if (extGid != -1) {
if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), extGid,
@@ -1166,6 +1169,7 @@
extStats->dataSize += dq.dqb_curspace;
}
}
+#endif
int sharedGid = multiuser_get_shared_gid(userId, appId);
if (sharedGid != -1) {
@@ -1363,6 +1367,17 @@
collectQuotaStats(device, userId, appId, &stats, &extStats);
ATRACE_END();
+#if HACK_FOR_37193650
+ ATRACE_BEGIN("external");
+ for (size_t i = 0; i < packageNames.size(); i++) {
+ const char* pkgname = packageNames[i].c_str();
+ auto extPath = create_data_media_package_path(uuid_, userId, "data", pkgname);
+ calculate_tree_size(extPath, &extStats.dataSize);
+ auto mediaPath = create_data_media_package_path(uuid_, userId, "media", pkgname);
+ calculate_tree_size(mediaPath, &extStats.dataSize);
+ }
+ ATRACE_END();
+#endif
} else {
ATRACE_BEGIN("code");
for (auto codePath : codePaths) {
@@ -1447,6 +1462,12 @@
flags &= ~FLAG_USE_QUOTA;
}
+#if HACK_FOR_37193650
+ if (userId != 0) {
+ flags &= ~FLAG_USE_QUOTA;
+ }
+#endif
+
if (flags & FLAG_USE_QUOTA) {
struct dqblk dq;
@@ -1508,6 +1529,7 @@
for (auto appId : appIds) {
if (appId >= AID_APP_START) {
collectQuotaStats(device, userId, appId, &stats, &extStats);
+
#if MEASURE_DEBUG
// Sleep to make sure we don't lose logs
usleep(1);
@@ -1729,7 +1751,8 @@
const std::unique_ptr<std::string>& packageName, const std::string& instructionSet,
int32_t dexoptNeeded, const std::unique_ptr<std::string>& outputPath, int32_t dexFlags,
const std::string& compilerFilter, const std::unique_ptr<std::string>& uuid,
- const std::unique_ptr<std::string>& sharedLibraries) {
+ const std::unique_ptr<std::string>& sharedLibraries,
+ const std::unique_ptr<std::string>& seInfo) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
if (packageName && *packageName != "*") {
@@ -1744,9 +1767,9 @@
const char* compiler_filter = compilerFilter.c_str();
const char* volume_uuid = uuid ? uuid->c_str() : nullptr;
const char* shared_libraries = sharedLibraries ? sharedLibraries->c_str() : nullptr;
-
+ const char* se_info = seInfo ? seInfo->c_str() : nullptr;
int res = android::installd::dexopt(apk_path, uid, pkgname, instruction_set, dexoptNeeded,
- oat_dir, dexFlags, compiler_filter, volume_uuid, shared_libraries);
+ oat_dir, dexFlags, compiler_filter, volume_uuid, shared_libraries, se_info);
return res ? error(res, "Failed to dexopt") : ok();
}
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index f5b7142..fe8aa14 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -82,7 +82,8 @@
const std::unique_ptr<std::string>& packageName, const std::string& instructionSet,
int32_t dexoptNeeded, const std::unique_ptr<std::string>& outputPath, int32_t dexFlags,
const std::string& compilerFilter, const std::unique_ptr<std::string>& uuid,
- const std::unique_ptr<std::string>& sharedLibraries);
+ const std::unique_ptr<std::string>& sharedLibraries,
+ const std::unique_ptr<std::string>& seInfo);
binder::Status rmdex(const std::string& codePath, const std::string& instructionSet);
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 03ff96e..e738b81 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -50,7 +50,8 @@
@utf8InCpp String instructionSet, int dexoptNeeded,
@nullable @utf8InCpp String outputPath, int dexFlags,
@utf8InCpp String compilerFilter, @nullable @utf8InCpp String uuid,
- @nullable @utf8InCpp String sharedLibraries);
+ @nullable @utf8InCpp String sharedLibraries,
+ @nullable @utf8InCpp String seInfo);
void rmdex(@utf8InCpp String codePath, @utf8InCpp String instructionSet);
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index f7e8d13..63afdcd 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -36,6 +36,7 @@
#include <cutils/sched_policy.h>
#include <log/log.h> // TODO: Move everything to base/logging.
#include <private/android_filesystem_config.h>
+#include <selinux/android.h>
#include <system/thread_defs.h>
#include "dexopt.h"
@@ -1302,17 +1303,9 @@
}
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.
- int32_t cache_gid = multiuser_get_cache_gid(
- multiuser_get_user_id(uid), multiuser_get_app_id(uid));
- // If UID doesn't have a specific cache GID, use UID value
- if (cache_gid == -1) {
- cache_gid = uid;
- }
-
// Create oat file output directory.
- if (prepare_app_cache_dir(dex_dir, "oat", 02711, uid, cache_gid) != 0) {
+ mode_t oat_dir_mode = S_IRWXU | S_IRWXG | S_IXOTH;
+ if (prepare_app_cache_dir(dex_dir, "oat", oat_dir_mode, uid, uid) != 0) {
LOG(ERROR) << "Could not prepare oat dir for secondary dex: " << dex_path;
return false;
}
@@ -1322,7 +1315,7 @@
oat_dir_out->assign(oat_dir);
// Create oat/isa output directory.
- if (prepare_app_cache_dir(*oat_dir_out, instruction_set, 02711, uid, cache_gid) != 0) {
+ if (prepare_app_cache_dir(*oat_dir_out, instruction_set, oat_dir_mode, uid, uid) != 0) {
LOG(ERROR) << "Could not prepare oat/isa dir for secondary dex: " << dex_path;
return false;
}
@@ -1366,12 +1359,15 @@
// Processes the dex_path as a secondary dex files and return true if the path dex file should
// 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 oat_dir_out is assigned the oat dir path where the oat file should be stored.
+// When returning true, the output parameters will be:
+// - is_public_out: whether or not the oat file should not be made public
+// - dexopt_needed_out: valid OatFileAsssitant::DexOptNeeded
+// - oat_dir_out: the oat dir path where the oat file should be stored
+// - dex_path_out: the real path of the dex file
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* oat_dir_out,
- std::string* dex_path_out) {
+ const char* compiler_filter, bool* is_public_out, int* dexopt_needed_out,
+ std::string* oat_dir_out, std::string* dex_path_out) {
int storage_flag;
if ((dexopt_flags & DEXOPT_STORAGE_CE) != 0) {
@@ -1407,7 +1403,8 @@
}
// Check if the path exist. If not, there's nothing to do.
- if (access(dex_path.c_str(), F_OK) != 0) {
+ struct stat dex_path_stat;
+ if (stat(dex_path.c_str(), &dex_path_stat) != 0) {
if (errno == ENOENT) {
// Secondary dex files might be deleted any time by the app.
// Nothing to do if that's the case
@@ -1418,6 +1415,11 @@
}
}
+ // Check if we should make the oat file public.
+ // Note that if the dex file is not public the compiled code cannot be made public.
+ *is_public_out = ((dexopt_flags & DEXOPT_PUBLIC) != 0) &&
+ ((dex_path_stat.st_mode & S_IROTH) != 0);
+
// Prepare the oat directories.
if (!prepare_secondary_dex_oat_dir(dex_path, uid, instruction_set, oat_dir_out)) {
return false;
@@ -1458,14 +1460,14 @@
int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* instruction_set,
int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
- const char* volume_uuid, const char* shared_libraries) {
+ const char* volume_uuid, const char* shared_libraries, const char* se_info) {
CHECK(pkgname != nullptr);
CHECK(pkgname[0] != 0);
if ((dexopt_flags & ~DEXOPT_MASK) != 0) {
LOG_FATAL("dexopt flags contains unknown fields\n");
}
- bool is_public = ((dexopt_flags & DEXOPT_PUBLIC) != 0);
+ bool is_public = (dexopt_flags & DEXOPT_PUBLIC) != 0;
bool vm_safe_mode = (dexopt_flags & DEXOPT_SAFEMODE) != 0;
bool debuggable = (dexopt_flags & DEXOPT_DEBUGGABLE) != 0;
bool boot_complete = (dexopt_flags & DEXOPT_BOOTCOMPLETE) != 0;
@@ -1477,7 +1479,8 @@
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, &dex_real_path)) {
+ instruction_set, compiler_filter, &is_public, &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) {
@@ -1516,6 +1519,19 @@
return -1;
}
+ // Ensure that the oat dir and the compiler artifacts of secondary dex files have the correct
+ // selinux context (we generate them on the fly during the dexopt invocation and they don't
+ // fully inherit their parent context).
+ // Note that for primary apk the oat files are created before, in a separate installd
+ // call which also does the restorecon. TODO(calin): unify the paths.
+ if (is_secondary_dex) {
+ if (selinux_android_restorecon_pkgdir(oat_dir, se_info, uid,
+ SELINUX_ANDROID_RESTORECON_RECURSE)) {
+ LOG(ERROR) << "Failed to restorecon " << oat_dir;
+ return -1;
+ }
+ }
+
// Create a swap file if necessary.
unique_fd swap_fd = maybe_open_dexopt_swap_file(out_oat_path);
@@ -1857,8 +1873,9 @@
atoi(params[6]), // dexopt_flags
params[7], // compiler_filter
parse_null(params[8]), // volume_uuid
- parse_null(params[9])); // shared_libraries
- static_assert(DEXOPT_PARAM_COUNT == 10U, "Unexpected dexopt param count");
+ parse_null(params[9]), // shared_libraries
+ parse_null(params[10])); // se_info
+ static_assert(DEXOPT_PARAM_COUNT == 11U, "Unexpected dexopt param count");
}
} // namespace installd
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index dbf3fae..88144b7 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -60,10 +60,10 @@
int dexopt(const char *apk_path, uid_t uid, const char *pkgName, const char *instruction_set,
int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
- const char* volume_uuid, const char* shared_libraries);
+ const char* volume_uuid, const char* shared_libraries, const char* se_info);
-static constexpr size_t DEXOPT_PARAM_COUNT = 10U;
-static_assert(DEXOPT_PARAM_COUNT == 10U, "Unexpected dexopt param size");
+static constexpr size_t DEXOPT_PARAM_COUNT = 11U;
+static_assert(DEXOPT_PARAM_COUNT == 11U, "Unexpected dexopt param size");
// Helper for the above, converting arguments.
int dexopt(const char* const params[DEXOPT_PARAM_COUNT]);
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 82b8cc2..e8e6b56 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -33,6 +33,7 @@
#include <android-base/strings.h>
#include <cutils/fs.h>
#include <cutils/properties.h>
+#include <dex2oat_return_codes.h>
#include <log/log.h>
#include <private/android_filesystem_config.h>
@@ -576,7 +577,11 @@
}
// If the dexopt failed, we may have a stale boot image from a previous OTA run.
- // Try to delete and retry.
+ // Then regenerate and retry.
+ if (WEXITSTATUS(dexopt_result) !=
+ static_cast<int>(art::dex2oat::ReturnCode::kCreateRuntime)) {
+ return dexopt_result;
+ }
if (!PrepareBootImage(/* force */ true)) {
LOG(ERROR) << "Forced boot image creating failed. Original error return was "
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 49605be..dab3236 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -547,7 +547,7 @@
TEST_F(UtilsTest, CreatePrimaryCurrentProfile) {
std::string expected =
- create_primary_current_profile_package_dir_path(1, "com.example") + "/primary.prof";
+ create_primary_current_profile_package_dir_path(0, "com.example") + "/primary.prof";
EXPECT_EQ(expected,
create_current_profile_path(/*user*/0, "com.example", /*is_secondary*/false));
}
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index dd94da9..5db547e 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -32,6 +32,7 @@
#define MEASURE_DEBUG 0
#define FIXUP_DEBUG 0
+#define HACK_FOR_37193650 1
namespace android {
namespace installd {
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index 420ec3c..4c57361 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -301,7 +301,6 @@
if (!manifest.add(vintf::ManifestHal{
.format = vintf::HalFormat::HIDL,
.name = fqName.package(),
- .impl = {.implLevel = vintf::ImplLevel::GENERIC, .impl = ""},
.transportArch = {transport, arch}
})) {
mErr << "Warning: cannot add hal '" << fqInstanceName << "'" << std::endl;
diff --git a/cmds/service/Android.bp b/cmds/service/Android.bp
index 8cffb3c..b703ed4 100644
--- a/cmds/service/Android.bp
+++ b/cmds/service/Android.bp
@@ -9,5 +9,18 @@
],
cflags: ["-DXP_UNIX"],
- //shared_libs: ["librt"],
+}
+
+cc_binary {
+ name: "vndservice",
+
+ proprietary: true,
+ srcs: ["service.cpp"],
+
+ shared_libs: [
+ "libutils",
+ "libbinder",
+ ],
+
+ cflags: ["-DXP_UNIX", "-DVENDORSERVICES"],
}
diff --git a/cmds/service/service.cpp b/cmds/service/service.cpp
index 428b87c..bc11256 100644
--- a/cmds/service/service.cpp
+++ b/cmds/service/service.cpp
@@ -68,13 +68,6 @@
int main(int argc, char* const argv[])
{
- sp<IServiceManager> sm = defaultServiceManager();
- fflush(stdout);
- if (sm == NULL) {
- aerr << "service: Unable to get default service manager!" << endl;
- return 20;
- }
-
bool wantsUsage = false;
int result = 0;
@@ -95,6 +88,15 @@
break;
}
}
+#ifdef VENDORSERVICES
+ ProcessState::initWithDriver("/dev/vndbinder");
+#endif
+ sp<IServiceManager> sm = defaultServiceManager();
+ fflush(stdout);
+ if (sm == NULL) {
+ aerr << "service: Unable to get default service manager!" << endl;
+ return 20;
+ }
if (optind >= argc) {
wantsUsage = true;
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index 68d39db..39d92a7 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -38,7 +38,7 @@
cc_binary {
name: "vndservicemanager",
defaults: ["servicemanager_flags"],
- proprietary: true,
+ vendor: true,
srcs: [
"service_manager.c",
"binder.c",
@@ -46,6 +46,7 @@
cflags: [
"-DVENDORSERVICEMANAGER=1",
],
- shared_libs: ["libcutils", "libselinux"],
+ shared_libs: ["libcutils"],
+ static_libs: ["libselinux"],
init_rc: ["vndservicemanager.rc"],
}
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index 45bb1d0..1f56a47 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -65,7 +65,11 @@
static bool check_mac_perms(pid_t spid, uid_t uid, const char *tctx, const char *perm, const char *name)
{
char *sctx = NULL;
+#ifdef VENDORSERVICEMANAGER
+ const char *class = "vndservice_manager";
+#else
const char *class = "service_manager";
+#endif
bool allowed;
struct audit_data ad;
diff --git a/cmds/vr/vrscreencap/Android.mk b/cmds/vr/vrscreencap/Android.mk
index bd0b224..804afc9 100644
--- a/cmds/vr/vrscreencap/Android.mk
+++ b/cmds/vr/vrscreencap/Android.mk
@@ -6,6 +6,7 @@
vrscreencap.cpp
LOCAL_STATIC_LIBRARIES := \
+ libbufferhub \
libdisplay \
libimageio \
libpdx_default_transport \
@@ -14,7 +15,8 @@
libcutils \
liblog \
libpng \
- libsync
+ libsync \
+ libui \
LOCAL_MODULE := vrscreencap
diff --git a/data/etc/android.hardware.nfc.hce.xml b/data/etc/android.hardware.nfc.hce.xml
index 10b96b1..95da181 100644
--- a/data/etc/android.hardware.nfc.hce.xml
+++ b/data/etc/android.hardware.nfc.hce.xml
@@ -18,4 +18,5 @@
NFC card emulation -->
<permissions>
<feature name="android.hardware.nfc.hce" />
+ <feature name="android.hardware.nfc.any" />
</permissions>
diff --git a/data/etc/android.hardware.nfc.hcef.xml b/data/etc/android.hardware.nfc.hcef.xml
index 0d03023..b86890d 100644
--- a/data/etc/android.hardware.nfc.hcef.xml
+++ b/data/etc/android.hardware.nfc.hcef.xml
@@ -18,4 +18,5 @@
NFC-F card emulation -->
<permissions>
<feature name="android.hardware.nfc.hcef" />
+ <feature name="android.hardware.nfc.any" />
</permissions>
diff --git a/data/etc/android.hardware.nfc.xml b/data/etc/android.hardware.nfc.xml
index 81c4a84..5201fa2 100644
--- a/data/etc/android.hardware.nfc.xml
+++ b/data/etc/android.hardware.nfc.xml
@@ -18,4 +18,5 @@
using Near-Field Communications (NFC). -->
<permissions>
<feature name="android.hardware.nfc" />
+ <feature name="android.hardware.nfc.any" />
</permissions>
diff --git a/data/etc/android.software.activities_on_secondary_displays.xml b/data/etc/android.software.activities_on_secondary_displays.xml
new file mode 100644
index 0000000..db1bdb5
--- /dev/null
+++ b/data/etc/android.software.activities_on_secondary_displays.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<permissions>
+ <feature name="android.software.activities_on_secondary_displays" />
+</permissions>
diff --git a/data/etc/android.software.autofill.xml b/data/etc/android.software.autofill.xml
new file mode 100644
index 0000000..c510d0c
--- /dev/null
+++ b/data/etc/android.software.autofill.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<permissions>
+ <feature name="android.software.autofill" />
+</permissions>
diff --git a/data/etc/android.software.cts.xml b/data/etc/android.software.cts.xml
new file mode 100644
index 0000000..0414c9a
--- /dev/null
+++ b/data/etc/android.software.cts.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<permissions>
+ <!-- This is Android and fully CTS compatible. Basically this is for CTS tests to use. -->
+ <feature name="android.software.cts" />
+</permissions>
diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml
index b5287ac..0d5d206 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -46,8 +46,10 @@
<feature name="android.software.home_screen" />
<feature name="android.software.input_methods" />
<feature name="android.software.picture_in_picture" />
+ <feature name="android.software.activities_on_secondary_displays" />
<feature name="android.software.print" />
<feature name="android.software.companion_device_setup" />
+ <feature name="android.software.autofill" />
<!-- Feature to specify if the device supports adding device admins. -->
<feature name="android.software.device_admin" />
diff --git a/data/etc/tablet_core_hardware.xml b/data/etc/tablet_core_hardware.xml
index 51ea1ca..9b88648 100644
--- a/data/etc/tablet_core_hardware.xml
+++ b/data/etc/tablet_core_hardware.xml
@@ -46,8 +46,10 @@
<feature name="android.software.home_screen" />
<feature name="android.software.input_methods" />
<feature name="android.software.picture_in_picture" />
+ <feature name="android.software.activities_on_secondary_displays" />
<feature name="android.software.print" />
<feature name="android.software.companion_device_setup" />
+ <feature name="android.software.autofill" />
<!-- Feature to specify if the device supports adding device admins. -->
<feature name="android.software.device_admin" />
diff --git a/include/android/sensor.h b/include/android/sensor.h
index 186f62c..cdb3fff 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -484,8 +484,9 @@
*
* Configure sensor direct report on a direct channel: set rate to value other than
* {@link ASENSOR_DIRECT_RATE_STOP} so that sensor event can be directly
- * written into the shared memory region used for creating the buffer; set rate to
- * {@link ASENSOR_DIRECT_RATE_STOP} will stop the sensor direct report.
+ * written into the shared memory region used for creating the buffer. It returns a positive token
+ * which can be used for identify sensor events from different sensors on success. Calling with rate
+ * {@link ASENSOR_DIRECT_RATE_STOP} will stop direct report of the sensor specified in the channel.
*
* To stop all active sensor direct report configured to a channel, set sensor to NULL and rate to
* {@link ASENSOR_DIRECT_RATE_STOP}.
@@ -513,7 +514,7 @@
* {@link ASensorManager_createSharedMemoryDirectChannel} or
* {@link ASensorManager_createHardwareBufferDirectChannel}.
*
- * \return 0 for success or negative integer for failure.
+ * \return positive token for success or negative error code.
*/
int ASensorManager_configureDirectReport(
ASensorManager* manager, ASensor const* sensor, int channelId, int rate);
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index cf2fa47..5d36526 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -72,6 +72,8 @@
status_t appendFrom(const Parcel *parcel,
size_t start, size_t len);
+ int compareData(const Parcel& other);
+
bool allowFds() const;
bool pushAllowFds(bool allowFds);
void restoreAllowFds(bool lastValue);
diff --git a/include/binder/ProcessState.h b/include/binder/ProcessState.h
index 05e9d09..1ef045d 100644
--- a/include/binder/ProcessState.h
+++ b/include/binder/ProcessState.h
@@ -69,6 +69,8 @@
status_t setThreadPoolMaxThreadCount(size_t maxThreads);
void giveThreadPoolName();
+ String8 getDriverName();
+
private:
friend class IPCThreadState;
@@ -86,6 +88,7 @@
handle_entry* lookupHandleLocked(int32_t handle);
+ String8 mDriverName;
int mDriverFD;
void* mVMStart;
diff --git a/include/gui/DisplayEventReceiver.h b/include/gui/DisplayEventReceiver.h
index cb9b373..9557b4f 100644
--- a/include/gui/DisplayEventReceiver.h
+++ b/include/gui/DisplayEventReceiver.h
@@ -32,9 +32,12 @@
// ----------------------------------------------------------------------------
-class BitTube;
class IDisplayEventConnection;
+namespace gui {
+class BitTube;
+} // namespace gui
+
static inline constexpr uint32_t fourcc(char c1, char c2, char c3, char c4) {
return static_cast<uint32_t>(c1) << 24 |
static_cast<uint32_t>(c2) << 16 |
@@ -108,15 +111,13 @@
* should be destroyed and getEvents() shouldn't be called again.
*/
ssize_t getEvents(Event* events, size_t count);
- static ssize_t getEvents(const sp<BitTube>& dataChannel,
- Event* events, size_t count);
+ static ssize_t getEvents(gui::BitTube* dataChannel, Event* events, size_t count);
/*
* sendEvents write events to the queue and returns how many events were
* written.
*/
- static ssize_t sendEvents(const sp<BitTube>& dataChannel,
- Event const* events, size_t count);
+ static ssize_t sendEvents(gui::BitTube* dataChannel, Event const* events, size_t count);
/*
* setVsyncRate() sets the Event::VSync delivery rate. A value of
@@ -134,7 +135,7 @@
private:
sp<IDisplayEventConnection> mEventConnection;
- sp<BitTube> mDataChannel;
+ std::unique_ptr<gui::BitTube> mDataChannel;
};
// ----------------------------------------------------------------------------
diff --git a/include/gui/FrameTimestamps.h b/include/gui/FrameTimestamps.h
index 92251ed..9716be4 100644
--- a/include/gui/FrameTimestamps.h
+++ b/include/gui/FrameTimestamps.h
@@ -54,8 +54,7 @@
static constexpr auto EVENT_COUNT =
static_cast<size_t>(FrameEvent::EVENT_COUNT);
static_assert(EVENT_COUNT <= 32, "Event count sanity check failed.");
- static constexpr nsecs_t TIMESTAMP_PENDING =
- std::numeric_limits<nsecs_t>::max();
+ static constexpr nsecs_t TIMESTAMP_PENDING = -2;
static inline bool isValidTimestamp(nsecs_t time) {
return time != TIMESTAMP_PENDING;
diff --git a/include/gui/IDisplayEventConnection.h b/include/gui/IDisplayEventConnection.h
index 848368c..d783f74 100644
--- a/include/gui/IDisplayEventConnection.h
+++ b/include/gui/IDisplayEventConnection.h
@@ -14,60 +14,52 @@
* limitations under the License.
*/
-#ifndef ANDROID_GUI_IDISPLAY_EVENT_CONNECTION_H
-#define ANDROID_GUI_IDISPLAY_EVENT_CONNECTION_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
+#pragma once
#include <binder/IInterface.h>
+#include <binder/SafeInterface.h>
+
+#include <utils/Errors.h>
+
+#include <cstdint>
namespace android {
-// ----------------------------------------------------------------------------
+namespace gui {
class BitTube;
+} // namespace gui
-class IDisplayEventConnection : public IInterface
-{
+class IDisplayEventConnection : public IInterface {
public:
-
DECLARE_META_INTERFACE(DisplayEventConnection)
/*
- * getDataChannel() returns a BitTube where to receive the events from
+ * stealReceiveChannel() returns a BitTube to receive events from. Only the receive file
+ * descriptor of outChannel will be initialized, and this effectively "steals" the receive
+ * channel from the remote end (such that the remote end can only use its send channel).
*/
- virtual sp<BitTube> getDataChannel() const = 0;
+ virtual status_t stealReceiveChannel(gui::BitTube* outChannel) = 0;
/*
- * setVsyncRate() sets the vsync event delivery rate. A value of
- * 1 returns every vsync events. A value of 2 returns every other events,
- * etc... a value of 0 returns no event unless requestNextVsync() has
- * been called.
+ * setVsyncRate() sets the vsync event delivery rate. A value of 1 returns every vsync event.
+ * A value of 2 returns every other event, etc. A value of 0 returns no event unless
+ * requestNextVsync() has been called.
*/
- virtual void setVsyncRate(uint32_t count) = 0;
+ virtual status_t setVsyncRate(uint32_t count) = 0;
/*
- * requestNextVsync() schedules the next vsync event. It has no effect
- * if the vsync rate is > 0.
+ * requestNextVsync() schedules the next vsync event. It has no effect if the vsync rate is > 0.
*/
- virtual void requestNextVsync() = 0; // asynchronous
+ virtual void requestNextVsync() = 0; // Asynchronous
};
-// ----------------------------------------------------------------------------
-
-class BnDisplayEventConnection : public BnInterface<IDisplayEventConnection>
-{
+class BnDisplayEventConnection : public SafeBnInterface<IDisplayEventConnection> {
public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
+ BnDisplayEventConnection()
+ : SafeBnInterface<IDisplayEventConnection>("BnDisplayEventConnection") {}
+
+ status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags = 0) override;
};
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GUI_IDISPLAY_EVENT_CONNECTION_H
+} // namespace android
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index 2fbe07a..9870ba0 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -126,6 +126,11 @@
virtual bool authenticateSurfaceTexture(
const sp<IGraphicBufferProducer>& surface) const = 0;
+ /* Returns the frame timestamps supported by SurfaceFlinger.
+ */
+ virtual status_t getSupportedFrameTimestamps(
+ std::vector<FrameEvent>* outSupported) const = 0;
+
/* set display power mode. depending on the mode, it can either trigger
* screen on, off or low power mode and wait for it to complete.
* requires ACCESS_SURFACE_FLINGER permission.
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 88ef010..8b1d106 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -426,6 +426,10 @@
uint64_t mNextFrameNumber = 1;
uint64_t mLastFrameNumber = 0;
+ // Mutable because ANativeWindow::query needs this class const.
+ mutable bool mQueriedSupportedTimestamps;
+ mutable bool mFrameTimestampsSupportsPresent;
+
// A cached copy of the FrameEventHistory maintained by the consumer.
bool mEnableFrameTimestamps = false;
std::unique_ptr<ProducerFrameEventHistory> mFrameEventHistory;
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index 394425a..ec310cf 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -146,6 +146,8 @@
status_t setFlags(const sp<IBinder>& id, uint32_t flags, uint32_t mask);
status_t setTransparentRegionHint(const sp<IBinder>& id, const Region& transparent);
status_t setLayer(const sp<IBinder>& id, int32_t layer);
+ status_t setRelativeLayer(const sp<IBinder>& id,
+ const sp<IBinder>& relativeTo, int32_t layer);
status_t setAlpha(const sp<IBinder>& id, float alpha=1.0f);
status_t setMatrix(const sp<IBinder>& id, float dsdx, float dtdx, float dtdy, float dsdy);
status_t setPosition(const sp<IBinder>& id, float x, float y);
diff --git a/include/gui/SurfaceControl.h b/include/gui/SurfaceControl.h
index 3cff7df..712a323 100644
--- a/include/gui/SurfaceControl.h
+++ b/include/gui/SurfaceControl.h
@@ -62,6 +62,27 @@
status_t setLayerStack(uint32_t layerStack);
status_t setLayer(int32_t layer);
+
+ // Sets a Z order relative to the Surface specified by "relativeTo" but
+ // without becoming a full child of the relative. Z-ordering works exactly
+ // as if it were a child however.
+ //
+ // As a nod to sanity, only non-child surfaces may have a relative Z-order.
+ //
+ // This overrides any previous and is overriden by any future calls
+ // to setLayer.
+ //
+ // If the relative dissapears, the Surface will have no layer and be
+ // invisible, until the next time set(Relative)Layer is called.
+ //
+ // TODO: This is probably a hack. Currently it exists only to work around
+ // some framework usage of the hidden APPLICATION_MEDIA_OVERLAY window type
+ // which allows inserting a window between a SurfaceView and it's main application
+ // window. However, since we are using child windows for the SurfaceView, but not using
+ // child windows elsewhere in O, the WindowManager can't set the layer appropriately.
+ // This is only used by the "TvInputService" and following the port of ViewRootImpl
+ // to child surfaces, we can then port this and remove this method.
+ status_t setRelativeLayer(const sp<IBinder>& relativeTo, int32_t layer);
status_t setPosition(float x, float y);
status_t setSize(uint32_t w, uint32_t h);
status_t hide();
diff --git a/include/media/cas/CasAPI.h b/include/media/cas/CasAPI.h
index 0e88019..67f4511 100644
--- a/include/media/cas/CasAPI.h
+++ b/include/media/cas/CasAPI.h
@@ -81,23 +81,12 @@
virtual status_t setPrivateData(
const CasData &privateData) = 0;
- // Open a session for descrambling a program. The session will receive the
- // ECM stream corresponding to the CA_PID for the program.
- virtual status_t openSession(
- uint16_t program_number,
- CasSessionId *sessionId) = 0;
-
- // Open a session for descrambling an elementary stream inside a program.
- // The session will receive the ECM stream corresponding to the CA_PID for
- // the stream.
- virtual status_t openSession(
- uint16_t program_number,
- uint16_t elementary_PID,
- CasSessionId *sessionId) = 0;
+ // Open a session for descrambling a program, or one or more elementary
+ // streams.
+ virtual status_t openSession(CasSessionId *sessionId) = 0;
// Close a previously opened session.
- virtual status_t closeSession(
- const CasSessionId &sessionId) = 0;
+ virtual status_t closeSession(const CasSessionId &sessionId) = 0;
// Provide the CA private data from a CA_descriptor in the program map
// table to a CasPlugin.
diff --git a/include/media/openmax/OMX_AsString.h b/include/media/openmax/OMX_AsString.h
index 6b21979..56d7cc8 100644
--- a/include/media/openmax/OMX_AsString.h
+++ b/include/media/openmax/OMX_AsString.h
@@ -557,6 +557,7 @@
case OMX_IndexConfigPriority: return "ConfigPriority";
case OMX_IndexConfigOperatingRate: return "ConfigOperatingRate";
case OMX_IndexParamConsumerUsageBits: return "ParamConsumerUsageBits";
+ case OMX_IndexConfigLatency: return "ConfigLatency";
default: return asString((OMX_INDEXTYPE)i, def);
}
}
diff --git a/include/media/openmax/OMX_IndexExt.h b/include/media/openmax/OMX_IndexExt.h
index eccecaa..5a029d0 100644
--- a/include/media/openmax/OMX_IndexExt.h
+++ b/include/media/openmax/OMX_IndexExt.h
@@ -96,6 +96,7 @@
OMX_IndexConfigPriority, /**< reference: OMX_PARAM_U32TYPE */
OMX_IndexConfigOperatingRate, /**< reference: OMX_PARAM_U32TYPE in Q16 format for video and in Hz for audio */
OMX_IndexParamConsumerUsageBits, /**< reference: OMX_PARAM_U32TYPE */
+ OMX_IndexConfigLatency, /**< reference: OMX_PARAM_U32TYPE */
OMX_IndexExtOtherEndUnused,
/* Time configurations */
diff --git a/include/private/gui/BitTube.h b/include/private/gui/BitTube.h
deleted file mode 100644
index 9d65fad..0000000
--- a/include/private/gui/BitTube.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2010 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_GUI_SENSOR_CHANNEL_H
-#define ANDROID_GUI_SENSOR_CHANNEL_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <android/log.h>
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
-
-namespace android {
-// ----------------------------------------------------------------------------
-class Parcel;
-
-class BitTube : public RefBase
-{
-public:
-
- // creates a BitTube with a default (4KB) send buffer
- BitTube();
-
- // creates a BitTube with a a specified send and receive buffer size
- explicit BitTube(size_t bufsize);
-
- explicit BitTube(const Parcel& data);
- virtual ~BitTube();
-
- // check state after construction
- status_t initCheck() const;
-
- // get receive file-descriptor
- int getFd() const;
-
- // get the send file-descriptor.
- int getSendFd() const;
-
- // send objects (sized blobs). All objects are guaranteed to be written or the call fails.
- template <typename T>
- static ssize_t sendObjects(const sp<BitTube>& tube,
- T const* events, size_t count) {
- return sendObjects(tube, events, count, sizeof(T));
- }
-
- // receive objects (sized blobs). If the receiving buffer isn't large enough,
- // excess messages are silently discarded.
- template <typename T>
- static ssize_t recvObjects(const sp<BitTube>& tube,
- T* events, size_t count) {
- return recvObjects(tube, events, count, sizeof(T));
- }
-
- // parcels this BitTube
- status_t writeToParcel(Parcel* reply) const;
-
-private:
- void init(size_t rcvbuf, size_t sndbuf);
-
- // send a message. The write is guaranteed to send the whole message or fail.
- ssize_t write(void const* vaddr, size_t size);
-
- // receive a message. the passed buffer must be at least as large as the
- // write call used to send the message, excess data is silently discarded.
- ssize_t read(void* vaddr, size_t size);
-
- int mSendFd;
- mutable int mReceiveFd;
-
- static ssize_t sendObjects(const sp<BitTube>& tube,
- void const* events, size_t count, size_t objSize);
-
- static ssize_t recvObjects(const sp<BitTube>& tube,
- void* events, size_t count, size_t objSize);
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GUI_SENSOR_CHANNEL_H
diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h
index 20f51a5..307c764 100644
--- a/include/private/gui/LayerState.h
+++ b/include/private/gui/LayerState.h
@@ -58,7 +58,8 @@
eOverrideScalingModeChanged = 0x00000800,
eGeometryAppliesWithResize = 0x00001000,
eReparentChildren = 0x00002000,
- eDetachChildren = 0x00004000
+ eDetachChildren = 0x00004000,
+ eRelativeLayerChanged = 0x00008000
};
layer_state_t()
@@ -104,6 +105,8 @@
sp<IGraphicBufferProducer> barrierGbp;
+ sp<IBinder> relativeLayerHandle;
+
// non POD must be last. see write/read
Region transparentRegion;
};
diff --git a/include/ui/DebugUtils.h b/include/ui/DebugUtils.h
new file mode 100644
index 0000000..8483808
--- /dev/null
+++ b/include/ui/DebugUtils.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <system/graphics.h>
+
+#include <string>
+
+std::string decodeStandard(android_dataspace dataspace);
+std::string decodeTransfer(android_dataspace dataspace);
+std::string decodeRange(android_dataspace dataspace);
+std::string dataspaceDetails(android_dataspace dataspace);
+std::string decodeColorMode(android_color_mode colormode);
diff --git a/include/ui/Gralloc2.h b/include/ui/Gralloc2.h
new file mode 100644
index 0000000..c59d327
--- /dev/null
+++ b/include/ui/Gralloc2.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UI_GRALLOC2_H
+#define ANDROID_UI_GRALLOC2_H
+
+#include <string>
+
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <system/window.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+namespace Gralloc2 {
+
+using hardware::graphics::allocator::V2_0::IAllocator;
+using hardware::graphics::common::V1_0::BufferUsage;
+using hardware::graphics::common::V1_0::PixelFormat;
+using hardware::graphics::mapper::V2_0::BufferDescriptor;
+using hardware::graphics::mapper::V2_0::Error;
+using hardware::graphics::mapper::V2_0::IMapper;
+using hardware::graphics::mapper::V2_0::YCbCrLayout;
+
+// A wrapper to IMapper
+class Mapper {
+public:
+ Mapper();
+
+ // this will be removed and Mapper will be always valid
+ bool valid() const { return (mMapper != nullptr); }
+
+ Error createDescriptor(
+ const IMapper::BufferDescriptorInfo& descriptorInfo,
+ BufferDescriptor* outDescriptor) const;
+
+ // Import a buffer that is from another HAL, another process, or is
+ // cloned.
+ //
+ // The returned handle must be freed with freeBuffer.
+ Error importBuffer(const hardware::hidl_handle& rawHandle,
+ buffer_handle_t* outBufferHandle) const;
+
+ void freeBuffer(buffer_handle_t bufferHandle) const;
+
+ // The ownership of acquireFence is always transferred to the callee, even
+ // on errors.
+ Error lock(buffer_handle_t bufferHandle, uint64_t usage,
+ const IMapper::Rect& accessRegion,
+ int acquireFence, void** outData) const;
+
+ // The ownership of acquireFence is always transferred to the callee, even
+ // on errors.
+ Error lock(buffer_handle_t bufferHandle, uint64_t usage,
+ const IMapper::Rect& accessRegion,
+ int acquireFence, YCbCrLayout* outLayout) const;
+
+ // unlock returns a fence sync object (or -1) and the fence sync object is
+ // owned by the caller
+ int unlock(buffer_handle_t bufferHandle) const;
+
+private:
+ sp<IMapper> mMapper;
+};
+
+// A wrapper to IAllocator
+class Allocator {
+public:
+ // An allocator relies on a mapper, and that mapper must be alive at all
+ // time.
+ Allocator(const Mapper& mapper);
+
+ // this will be removed and Allocator will be always valid
+ bool valid() const { return (mAllocator != nullptr); }
+
+ std::string dumpDebugInfo() const;
+
+ /*
+ * The returned buffers are already imported and must not be imported
+ * again. outBufferHandles must point to a space that can contain at
+ * least "count" buffer_handle_t.
+ */
+ Error allocate(BufferDescriptor descriptor, uint32_t count,
+ uint32_t* outStride, buffer_handle_t* outBufferHandles) const;
+
+ Error allocate(BufferDescriptor descriptor,
+ uint32_t* outStride, buffer_handle_t* outBufferHandle) const
+ {
+ return allocate(descriptor, 1, outStride, outBufferHandle);
+ }
+
+ Error allocate(const IMapper::BufferDescriptorInfo& descriptorInfo, uint32_t count,
+ uint32_t* outStride, buffer_handle_t* outBufferHandles) const
+ {
+ BufferDescriptor descriptor;
+ Error error = mMapper.createDescriptor(descriptorInfo, &descriptor);
+ if (error == Error::NONE) {
+ error = allocate(descriptor, count, outStride, outBufferHandles);
+ }
+ return error;
+ }
+
+ Error allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
+ uint32_t* outStride, buffer_handle_t* outBufferHandle) const
+ {
+ return allocate(descriptorInfo, 1, outStride, outBufferHandle);
+ }
+
+private:
+ const Mapper& mMapper;
+ sp<IAllocator> mAllocator;
+};
+
+} // namespace Gralloc2
+
+} // namespace android
+
+#endif // ANDROID_UI_GRALLOC2_H
diff --git a/include/ui/GrallocAllocator.h b/include/ui/GrallocAllocator.h
deleted file mode 100644
index dd0f9e0..0000000
--- a/include/ui/GrallocAllocator.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_UI_GRALLOC_ALLOCATOR_H
-#define ANDROID_UI_GRALLOC_ALLOCATOR_H
-
-#include <string>
-
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <utils/StrongPointer.h>
-
-namespace android {
-
-namespace Gralloc2 {
-
-using hardware::graphics::allocator::V2_0::Error;
-using hardware::graphics::allocator::V2_0::ProducerUsage;
-using hardware::graphics::allocator::V2_0::ConsumerUsage;
-using hardware::graphics::allocator::V2_0::BufferDescriptor;
-using hardware::graphics::allocator::V2_0::Buffer;
-using hardware::graphics::allocator::V2_0::IAllocator;
-using hardware::graphics::allocator::V2_0::IAllocatorClient;
-using hardware::graphics::common::V1_0::PixelFormat;
-
-// Allocator is a wrapper to IAllocator, a proxy to server-side allocator.
-class Allocator {
-public:
- Allocator();
-
- // this will be removed and Allocator will be always valid
- bool valid() const { return (mAllocator != nullptr); }
-
- std::string dumpDebugInfo() const;
-
- Error createBufferDescriptor(
- const IAllocatorClient::BufferDescriptorInfo& descriptorInfo,
- BufferDescriptor* outDescriptor) const;
- void destroyBufferDescriptor(BufferDescriptor descriptor) const;
-
- Error allocate(BufferDescriptor descriptor, Buffer* outBuffer) const;
- void free(Buffer buffer) const;
-
- Error exportHandle(BufferDescriptor descriptor, Buffer buffer,
- native_handle_t** outBufferHandle) const;
-
-private:
- sp<IAllocator> mAllocator;
- sp<IAllocatorClient> mClient;
-};
-
-} // namespace Gralloc2
-
-} // namespace android
-
-#endif // ANDROID_UI_GRALLOC_ALLOCATOR_H
diff --git a/include/ui/GrallocMapper.h b/include/ui/GrallocMapper.h
deleted file mode 100644
index 5a0d64b..0000000
--- a/include/ui/GrallocMapper.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_UI_GRALLOC_MAPPER_H
-#define ANDROID_UI_GRALLOC_MAPPER_H
-
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <system/window.h>
-
-namespace android {
-
-namespace Gralloc2 {
-
-using hardware::graphics::allocator::V2_0::Error;
-using hardware::graphics::allocator::V2_0::ProducerUsage;
-using hardware::graphics::allocator::V2_0::ConsumerUsage;
-using hardware::graphics::common::V1_0::PixelFormat;
-using hardware::graphics::mapper::V2_0::FlexLayout;
-using hardware::graphics::mapper::V2_0::BackingStore;
-using hardware::graphics::mapper::V2_0::IMapper;
-
-// Mapper is a wrapper to IMapper, a client-side graphics buffer mapper.
-class Mapper {
-public:
- Mapper();
-
- // this will be removed and Mapper will be always valid
- bool valid() const { return (mMapper != nullptr); }
-
- Error retain(buffer_handle_t handle) const;
- void release(buffer_handle_t handle) const;
-
- Error getDimensions(buffer_handle_t handle,
- uint32_t* outWidth, uint32_t* outHeight) const;
- Error getFormat(buffer_handle_t handle, int32_t* outFormat) const;
- Error getLayerCount(buffer_handle_t handle, uint32_t* outLayerCount) const;
- Error getProducerUsage(buffer_handle_t handle,
- uint64_t* outProducerUsage) const;
- Error getConsumerUsage(buffer_handle_t handle,
- uint64_t* outConsumerUsage) const;
- Error getBackingStore(buffer_handle_t handle,
- uint64_t* outBackingStore) const;
- Error getStride(buffer_handle_t handle, uint32_t* outStride) const;
-
- Error lock(buffer_handle_t handle, uint64_t producerUsage,
- uint64_t consumerUsage, const IMapper::Rect& accessRegion,
- int acquireFence, void** outData) const;
- Error lock(buffer_handle_t handle, uint64_t producerUsage,
- uint64_t consumerUsage, const IMapper::Rect& accessRegion,
- int acquireFence, FlexLayout* outLayout) const;
- int unlock(buffer_handle_t handle) const;
-
-private:
- sp<IMapper> mMapper;
-};
-
-} // namespace Gralloc2
-
-} // namespace android
-
-#endif // ANDROID_UI_GRALLOC_MAPPER_H
diff --git a/include/ui/GraphicBufferAllocator.h b/include/ui/GraphicBufferAllocator.h
index e97122b..95eb8fd 100644
--- a/include/ui/GraphicBufferAllocator.h
+++ b/include/ui/GraphicBufferAllocator.h
@@ -96,8 +96,8 @@
GraphicBufferAllocator();
~GraphicBufferAllocator();
- const std::unique_ptr<const Gralloc2::Allocator> mAllocator;
GraphicBufferMapper& mMapper;
+ const std::unique_ptr<const Gralloc2::Allocator> mAllocator;
std::unique_ptr<Gralloc1::Loader> mLoader;
std::unique_ptr<Gralloc1::Device> mDevice;
diff --git a/include/ui/GraphicBufferMapper.h b/include/ui/GraphicBufferMapper.h
index b6d4021..d69f8fc 100644
--- a/include/ui/GraphicBufferMapper.h
+++ b/include/ui/GraphicBufferMapper.h
@@ -47,31 +47,15 @@
public:
static inline GraphicBufferMapper& get() { return getInstance(); }
- // This may NOT work on devices without a valid Gralloc2::Mapper.
- status_t registerBuffer(buffer_handle_t handle);
+ // The imported outHandle must be freed with freeBuffer when no longer
+ // needed. rawHandle is owned by the caller.
+ status_t importBuffer(buffer_handle_t rawHandle,
+ buffer_handle_t* outHandle);
- status_t registerBuffer(const GraphicBuffer* buffer);
+ // This is temporary and will be removed soon
+ status_t importBuffer(const GraphicBuffer* buffer);
- status_t unregisterBuffer(buffer_handle_t handle);
-
- status_t getDimensions(buffer_handle_t handle,
- uint32_t* outWidth, uint32_t* outHeight) const;
-
- status_t getFormat(buffer_handle_t handle, int32_t* outFormat) const;
-
- status_t getLayerCount(buffer_handle_t handle,
- uint32_t* outLayerCount) const;
-
- status_t getProducerUsage(buffer_handle_t handle,
- uint64_t* outProducerUsage) const;
-
- status_t getConsumerUsage(buffer_handle_t handle,
- uint64_t* outConsumerUsage) const;
-
- status_t getBackingStore(buffer_handle_t handle,
- uint64_t* outBackingStore) const;
-
- status_t getStride(buffer_handle_t handle, uint32_t* outStride) const;
+ status_t freeBuffer(buffer_handle_t handle);
status_t lock(buffer_handle_t handle,
uint32_t usage, const Rect& bounds, void** vaddr);
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 3aeff2e..c7a0f43 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -23,6 +23,7 @@
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <utils/SystemClock.h>
+#include <utils/CallStack.h>
#include <private/binder/Static.h>
@@ -136,7 +137,12 @@
unsigned n;
for (n = 0; n < 5; n++){
if (n > 0) {
- ALOGI("Waiting for service %s...", String8(name).string());
+ if (!strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder")) {
+ ALOGI("Waiting for vendor service %s...", String8(name).string());
+ CallStack stack(LOG_TAG);
+ } else {
+ ALOGI("Waiting for service %s...", String8(name).string());
+ }
sleep(1);
}
sp<IBinder> svc = checkService(name);
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index da94305..39bb078 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -553,6 +553,14 @@
return err;
}
+int Parcel::compareData(const Parcel& other) {
+ size_t size = dataSize();
+ if (size != other.dataSize()) {
+ return size < other.dataSize() ? -1 : 1;
+ }
+ return memcmp(data(), other.data(), size);
+}
+
bool Parcel::allowFds() const
{
return mAllowFds;
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 5c4cfe2..9ccf07c 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -317,6 +317,10 @@
androidSetThreadName( makeBinderThreadName().string() );
}
+String8 ProcessState::getDriverName() {
+ return mDriverName;
+}
+
static int open_driver(const char *driver)
{
int fd = open(driver, O_RDWR | O_CLOEXEC);
@@ -346,7 +350,8 @@
}
ProcessState::ProcessState(const char *driver)
- : mDriverFD(open_driver(driver))
+ : mDriverName(String8(driver))
+ , mDriverFD(open_driver(driver))
, mVMStart(MAP_FAILED)
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
@@ -367,6 +372,7 @@
ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
close(mDriverFD);
mDriverFD = -1;
+ mDriverName.clear();
}
}
diff --git a/libs/binder/tests/binderValueTypeTest.cpp b/libs/binder/tests/binderValueTypeTest.cpp
index 1a05a52..c8f4697 100644
--- a/libs/binder/tests/binderValueTypeTest.cpp
+++ b/libs/binder/tests/binderValueTypeTest.cpp
@@ -106,6 +106,6 @@
value_a.swap(value_b);
ASSERT_FALSE(value_b.empty());
ASSERT_TRUE(value_a.empty());
- ASSERT_TRUE(value_a.getInt(&int_x));
+ ASSERT_TRUE(value_b.getInt(&int_x));
ASSERT_EQ(31337, int_x);
}
diff --git a/libs/binder/tests/schd-dbg.cpp b/libs/binder/tests/schd-dbg.cpp
index 2732071..fe9e05a 100644
--- a/libs/binder/tests/schd-dbg.cpp
+++ b/libs/binder/tests/schd-dbg.cpp
@@ -15,6 +15,7 @@
#include <pthread.h>
#include <sys/wait.h>
#include <unistd.h>
+#include <fstream>
using namespace std;
using namespace android;
@@ -41,6 +42,8 @@
#define DUMP_PRICISION 3
+string trace_path = "/sys/kernel/debug/tracing";
+
// the default value
int no_process = 2;
int iterations = 100;
@@ -48,6 +51,23 @@
int no_inherent = 0;
int no_sync = 0;
int verbose = 0;
+int trace;
+
+bool traceIsOn() {
+ fstream file;
+ file.open(trace_path + "/tracing_on", ios::in);
+ char on;
+ file >> on;
+ file.close();
+ return on == '1';
+}
+
+void traceStop() {
+ ofstream file;
+ file.open(trace_path + "/tracing_on", ios::out | ios::trunc);
+ file << '0' << endl;
+ file.close();
+}
// the deadline latency that we are interested in
uint64_t deadline_us = 2500;
@@ -197,13 +217,29 @@
uint64_t m_transactions = 0;
uint64_t m_total_time = 0;
uint64_t m_miss = 0;
-
+ bool tracing;
+ Results(bool _tracing) : tracing(_tracing) {
+ }
+ inline bool miss_deadline(uint64_t nano) {
+ return nano > deadline_us * 1000;
+ }
void add_time(uint64_t nano) {
m_best = min(nano, m_best);
m_worst = max(nano, m_worst);
m_transactions += 1;
m_total_time += nano;
- if (nano > deadline_us * 1000) m_miss++;
+ if (miss_deadline(nano)) m_miss++;
+ if (miss_deadline(nano) && tracing) {
+ // There might be multiple process pair running the test concurrently
+ // each may execute following statements and only the first one actually
+ // stop the trace and any traceStop() afterthen has no effect.
+ traceStop();
+ cout << endl;
+ cout << "deadline triggered: halt & stop trace" << endl;
+ cout << "log:" + trace_path + "/trace" << endl;
+ cout << endl;
+ exit(1);
+ }
}
void dump() {
double best = (double)m_best / 1.0E6;
@@ -212,8 +248,9 @@
// FIXME: libjson?
cout << std::setprecision(DUMP_PRICISION) << "{ \"avg\":" << setw(5) << left
<< average << ", \"wst\":" << setw(5) << left << worst
- << ", \"bst\":" << setw(5) << left << best << ", \"miss\":" << m_miss
- << "}";
+ << ", \"bst\":" << setw(5) << left << best << ", \"miss\":" << setw(5)
+ << left << m_miss << ", \"meetR\":" << setw(3) << left
+ << (1.0 - (double)m_miss / m_transactions) << "}";
}
};
@@ -272,7 +309,7 @@
void worker_fx(int num, int no_process, int iterations, int payload_size,
Pipe p) {
int dummy;
- Results results_other, results_fifo;
+ Results results_other(false), results_fifo(trace);
// Create BinderWorkerService and for go.
ProcessState::self()->startThreadPool();
@@ -389,8 +426,28 @@
}
if (string(argv[i]) == "-v") {
verbose = 1;
- i++;
}
+ // The -trace argument is used like that:
+ //
+ // First start trace with atrace command as usual
+ // >atrace --async_start sched freq
+ //
+ // then use schd-dbg with -trace arguments
+ //./schd-dbg -trace -deadline_us 2500
+ //
+ // This makes schd-dbg to stop trace once it detects a transaction
+ // duration over the deadline. By writing '0' to
+ // /sys/kernel/debug/tracing and halt the process. The tracelog is
+ // then available on /sys/kernel/debug/trace
+ if (string(argv[i]) == "-trace") {
+ trace = 1;
+ }
+ }
+ if (trace && !traceIsOn()) {
+ cout << "trace is not running" << endl;
+ cout << "check " << trace_path + "/tracing_on" << endl;
+ cout << "use atrace --async_start first" << endl;
+ exit(-1);
}
vector<Pipe> pipes;
thread_dump("main");
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 28c2a48..90ab286 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -126,6 +126,10 @@
"android.hidl.token@1.0-utils",
"android.hardware.graphics.bufferqueue@1.0",
],
+
+ export_include_dirs: [
+ "include",
+ ],
}
subdirs = ["tests"]
diff --git a/libs/gui/BitTube.cpp b/libs/gui/BitTube.cpp
index 51a8d67..ef7a6f5 100644
--- a/libs/gui/BitTube.cpp
+++ b/libs/gui/BitTube.cpp
@@ -17,8 +17,8 @@
#include <private/gui/BitTube.h>
#include <stdint.h>
-#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
@@ -27,45 +27,21 @@
#include <binder/Parcel.h>
-
namespace android {
-// ----------------------------------------------------------------------------
+namespace gui {
-// Socket buffer size. The default is typically about 128KB, which is much larger than
-// we really need. So we make it smaller.
+// Socket buffer size. The default is typically about 128KB, which is much larger than we really
+// need. So we make it smaller.
static const size_t DEFAULT_SOCKET_BUFFER_SIZE = 4 * 1024;
-
-BitTube::BitTube()
- : mSendFd(-1), mReceiveFd(-1)
-{
- init(DEFAULT_SOCKET_BUFFER_SIZE, DEFAULT_SOCKET_BUFFER_SIZE);
-}
-
-BitTube::BitTube(size_t bufsize)
- : mSendFd(-1), mReceiveFd(-1)
-{
+BitTube::BitTube(size_t bufsize) {
init(bufsize, bufsize);
}
-BitTube::BitTube(const Parcel& data)
- : mSendFd(-1), mReceiveFd(-1)
-{
- mReceiveFd = dup(data.readFileDescriptor());
- if (mReceiveFd < 0) {
- mReceiveFd = -errno;
- ALOGE("BitTube(Parcel): can't dup filedescriptor (%s)",
- strerror(-mReceiveFd));
- }
-}
+BitTube::BitTube(DefaultSizeType) : BitTube(DEFAULT_SOCKET_BUFFER_SIZE) {}
-BitTube::~BitTube()
-{
- if (mSendFd >= 0)
- close(mSendFd);
-
- if (mReceiveFd >= 0)
- close(mReceiveFd);
+BitTube::BitTube(const Parcel& data) {
+ readFromParcel(&data);
}
void BitTube::init(size_t rcvbuf, size_t sndbuf) {
@@ -74,39 +50,43 @@
size_t size = DEFAULT_SOCKET_BUFFER_SIZE;
setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
- // sine we don't use the "return channel", we keep it small...
+ // since we don't use the "return channel", we keep it small...
setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
fcntl(sockets[0], F_SETFL, O_NONBLOCK);
fcntl(sockets[1], F_SETFL, O_NONBLOCK);
- mReceiveFd = sockets[0];
- mSendFd = sockets[1];
+ mReceiveFd.reset(sockets[0]);
+ mSendFd.reset(sockets[1]);
} else {
- mReceiveFd = -errno;
- ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd));
+ mReceiveFd.reset();
+ ALOGE("BitTube: pipe creation failed (%s)", strerror(errno));
}
}
-status_t BitTube::initCheck() const
-{
+status_t BitTube::initCheck() const {
if (mReceiveFd < 0) {
return status_t(mReceiveFd);
}
return NO_ERROR;
}
-int BitTube::getFd() const
-{
+int BitTube::getFd() const {
return mReceiveFd;
}
-int BitTube::getSendFd() const
-{
+int BitTube::getSendFd() const {
return mSendFd;
}
-ssize_t BitTube::write(void const* vaddr, size_t size)
-{
+base::unique_fd BitTube::moveReceiveFd() {
+ return std::move(mReceiveFd);
+}
+
+void BitTube::setReceiveFd(base::unique_fd&& receiveFd) {
+ mReceiveFd = std::move(receiveFd);
+}
+
+ssize_t BitTube::write(void const* vaddr, size_t size) {
ssize_t err, len;
do {
len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL);
@@ -116,62 +96,66 @@
return err == 0 ? len : -err;
}
-ssize_t BitTube::read(void* vaddr, size_t size)
-{
+ssize_t BitTube::read(void* vaddr, size_t size) {
ssize_t err, len;
do {
len = ::recv(mReceiveFd, vaddr, size, MSG_DONTWAIT);
err = len < 0 ? errno : 0;
} while (err == EINTR);
if (err == EAGAIN || err == EWOULDBLOCK) {
- // EAGAIN means that we have non-blocking I/O but there was
- // no data to be read. Nothing the client should care about.
+ // EAGAIN means that we have non-blocking I/O but there was no data to be read. Nothing the
+ // client should care about.
return 0;
}
return err == 0 ? len : -err;
}
-status_t BitTube::writeToParcel(Parcel* reply) const
-{
- if (mReceiveFd < 0)
- return -EINVAL;
+status_t BitTube::writeToParcel(Parcel* reply) const {
+ if (mReceiveFd < 0) return -EINVAL;
status_t result = reply->writeDupFileDescriptor(mReceiveFd);
- close(mReceiveFd);
- mReceiveFd = -1;
+ mReceiveFd.reset();
return result;
}
+status_t BitTube::readFromParcel(const Parcel* parcel) {
+ mReceiveFd.reset(dup(parcel->readFileDescriptor()));
+ if (mReceiveFd < 0) {
+ mReceiveFd.reset();
+ int error = errno;
+ ALOGE("BitTube::readFromParcel: can't dup file descriptor (%s)", strerror(error));
+ return -error;
+ }
+ return NO_ERROR;
+}
-ssize_t BitTube::sendObjects(const sp<BitTube>& tube,
- void const* events, size_t count, size_t objSize)
-{
+ssize_t BitTube::sendObjects(BitTube* tube, void const* events, size_t count, size_t objSize) {
const char* vaddr = reinterpret_cast<const char*>(events);
- ssize_t size = tube->write(vaddr, count*objSize);
+ ssize_t size = tube->write(vaddr, count * objSize);
// should never happen because of SOCK_SEQPACKET
LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)),
- "BitTube::sendObjects(count=%zu, size=%zu), res=%zd (partial events were sent!)",
- count, objSize, size);
+ "BitTube::sendObjects(count=%zu, size=%zu), res=%zd (partial events were "
+ "sent!)",
+ count, objSize, size);
- //ALOGE_IF(size<0, "error %d sending %d events", size, count);
+ // ALOGE_IF(size<0, "error %d sending %d events", size, count);
return size < 0 ? size : size / static_cast<ssize_t>(objSize);
}
-ssize_t BitTube::recvObjects(const sp<BitTube>& tube,
- void* events, size_t count, size_t objSize)
-{
+ssize_t BitTube::recvObjects(BitTube* tube, void* events, size_t count, size_t objSize) {
char* vaddr = reinterpret_cast<char*>(events);
- ssize_t size = tube->read(vaddr, count*objSize);
+ ssize_t size = tube->read(vaddr, count * objSize);
// should never happen because of SOCK_SEQPACKET
LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)),
- "BitTube::recvObjects(count=%zu, size=%zu), res=%zd (partial events were received!)",
- count, objSize, size);
+ "BitTube::recvObjects(count=%zu, size=%zu), res=%zd (partial events were "
+ "received!)",
+ count, objSize, size);
- //ALOGE_IF(size<0, "error %d receiving %d events", size, count);
+ // ALOGE_IF(size<0, "error %d receiving %d events", size, count);
return size < 0 ? size : size / static_cast<ssize_t>(objSize);
}
-// ----------------------------------------------------------------------------
-}; // namespace android
+} // namespace gui
+} // namespace android
diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp
index 07e07e0..1507d51 100644
--- a/libs/gui/DisplayEventReceiver.cpp
+++ b/libs/gui/DisplayEventReceiver.cpp
@@ -37,7 +37,8 @@
if (sf != NULL) {
mEventConnection = sf->createDisplayEventConnection();
if (mEventConnection != NULL) {
- mDataChannel = mEventConnection->getDataChannel();
+ mDataChannel = std::make_unique<gui::BitTube>();
+ mEventConnection->stealReceiveChannel(mDataChannel.get());
}
}
}
@@ -80,19 +81,19 @@
ssize_t DisplayEventReceiver::getEvents(DisplayEventReceiver::Event* events,
size_t count) {
- return DisplayEventReceiver::getEvents(mDataChannel, events, count);
+ return DisplayEventReceiver::getEvents(mDataChannel.get(), events, count);
}
-ssize_t DisplayEventReceiver::getEvents(const sp<BitTube>& dataChannel,
+ssize_t DisplayEventReceiver::getEvents(gui::BitTube* dataChannel,
Event* events, size_t count)
{
- return BitTube::recvObjects(dataChannel, events, count);
+ return gui::BitTube::recvObjects(dataChannel, events, count);
}
-ssize_t DisplayEventReceiver::sendEvents(const sp<BitTube>& dataChannel,
+ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel,
Event const* events, size_t count)
{
- return BitTube::sendObjects(dataChannel, events, count);
+ return gui::BitTube::sendObjects(dataChannel, events, count);
}
// ---------------------------------------------------------------------------
diff --git a/libs/gui/IDisplayEventConnection.cpp b/libs/gui/IDisplayEventConnection.cpp
index e5c3c48..c0e246f 100644
--- a/libs/gui/IDisplayEventConnection.cpp
+++ b/libs/gui/IDisplayEventConnection.cpp
@@ -14,89 +14,67 @@
* limitations under the License.
*/
-#include <stdint.h>
-
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
-
-#include <binder/Parcel.h>
-
#include <gui/IDisplayEventConnection.h>
#include <private/gui/BitTube.h>
namespace android {
-// ----------------------------------------------------------------------------
-enum {
- GET_DATA_CHANNEL = IBinder::FIRST_CALL_TRANSACTION,
+namespace { // Anonymous
+
+enum class Tag : uint32_t {
+ STEAL_RECEIVE_CHANNEL = IBinder::FIRST_CALL_TRANSACTION,
SET_VSYNC_RATE,
- REQUEST_NEXT_VSYNC
+ REQUEST_NEXT_VSYNC,
+ LAST = REQUEST_NEXT_VSYNC,
};
-class BpDisplayEventConnection : public BpInterface<IDisplayEventConnection>
-{
+} // Anonymous namespace
+
+class BpDisplayEventConnection : public SafeBpInterface<IDisplayEventConnection> {
public:
explicit BpDisplayEventConnection(const sp<IBinder>& impl)
- : BpInterface<IDisplayEventConnection>(impl)
- {
+ : SafeBpInterface<IDisplayEventConnection>(impl, "BpDisplayEventConnection") {}
+
+ ~BpDisplayEventConnection() override;
+
+ status_t stealReceiveChannel(gui::BitTube* outChannel) override {
+ return callRemote<decltype(
+ &IDisplayEventConnection::stealReceiveChannel)>(Tag::STEAL_RECEIVE_CHANNEL,
+ outChannel);
}
- virtual ~BpDisplayEventConnection();
-
- virtual sp<BitTube> getDataChannel() const
- {
- Parcel data, reply;
- data.writeInterfaceToken(IDisplayEventConnection::getInterfaceDescriptor());
- remote()->transact(GET_DATA_CHANNEL, data, &reply);
- return new BitTube(reply);
+ status_t setVsyncRate(uint32_t count) override {
+ return callRemote<decltype(&IDisplayEventConnection::setVsyncRate)>(Tag::SET_VSYNC_RATE,
+ count);
}
- virtual void setVsyncRate(uint32_t count) {
- Parcel data, reply;
- data.writeInterfaceToken(IDisplayEventConnection::getInterfaceDescriptor());
- data.writeUint32(count);
- remote()->transact(SET_VSYNC_RATE, data, &reply);
- }
-
- virtual void requestNextVsync() {
- Parcel data, reply;
- data.writeInterfaceToken(IDisplayEventConnection::getInterfaceDescriptor());
- remote()->transact(REQUEST_NEXT_VSYNC, data, &reply, IBinder::FLAG_ONEWAY);
+ void requestNextVsync() override {
+ callRemoteAsync<decltype(&IDisplayEventConnection::requestNextVsync)>(
+ Tag::REQUEST_NEXT_VSYNC);
}
};
-// Out-of-line virtual method definition to trigger vtable emission in this
-// translation unit (see clang warning -Wweak-vtables)
-BpDisplayEventConnection::~BpDisplayEventConnection() {}
+// Out-of-line virtual method definition to trigger vtable emission in this translation unit (see
+// clang warning -Wweak-vtables)
+BpDisplayEventConnection::~BpDisplayEventConnection() = default;
IMPLEMENT_META_INTERFACE(DisplayEventConnection, "android.gui.DisplayEventConnection");
-// ----------------------------------------------------------------------------
-
-status_t BnDisplayEventConnection::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- switch(code) {
- case GET_DATA_CHANNEL: {
- CHECK_INTERFACE(IDisplayEventConnection, data, reply);
- sp<BitTube> channel(getDataChannel());
- channel->writeToParcel(reply);
- return NO_ERROR;
- }
- case SET_VSYNC_RATE: {
- CHECK_INTERFACE(IDisplayEventConnection, data, reply);
- setVsyncRate(data.readUint32());
- return NO_ERROR;
- }
- case REQUEST_NEXT_VSYNC: {
- CHECK_INTERFACE(IDisplayEventConnection, data, reply);
- requestNextVsync();
- return NO_ERROR;
- }
+status_t BnDisplayEventConnection::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags) {
+ if (code < IBinder::FIRST_CALL_TRANSACTION || code > static_cast<uint32_t>(Tag::LAST)) {
+ return BBinder::onTransact(code, data, reply, flags);
}
- return BBinder::onTransact(code, data, reply, flags);
+ auto tag = static_cast<Tag>(code);
+ switch (tag) {
+ case Tag::STEAL_RECEIVE_CHANNEL:
+ return callLocal(data, reply, &IDisplayEventConnection::stealReceiveChannel);
+ case Tag::SET_VSYNC_RATE:
+ return callLocal(data, reply, &IDisplayEventConnection::setVsyncRate);
+ case Tag::REQUEST_NEXT_VSYNC:
+ return callLocalAsync(data, reply, &IDisplayEventConnection::requestNextVsync);
+ }
}
-// ----------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 5a32d05..4d2692f 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -166,6 +166,50 @@
return result != 0;
}
+ virtual status_t getSupportedFrameTimestamps(
+ std::vector<FrameEvent>* outSupported) const {
+ if (!outSupported) {
+ return UNEXPECTED_NULL;
+ }
+ outSupported->clear();
+
+ Parcel data, reply;
+
+ status_t err = data.writeInterfaceToken(
+ ISurfaceComposer::getInterfaceDescriptor());
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ err = remote()->transact(
+ BnSurfaceComposer::GET_SUPPORTED_FRAME_TIMESTAMPS,
+ data, &reply);
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ int32_t result = 0;
+ err = reply.readInt32(&result);
+ if (err != NO_ERROR) {
+ return err;
+ }
+ if (result != NO_ERROR) {
+ return result;
+ }
+
+ std::vector<int32_t> supported;
+ err = reply.readInt32Vector(&supported);
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ outSupported->reserve(supported.size());
+ for (int32_t s : supported) {
+ outSupported->push_back(static_cast<FrameEvent>(s));
+ }
+ return NO_ERROR;
+ }
+
virtual sp<IDisplayEventConnection> createDisplayEventConnection()
{
Parcel data, reply;
@@ -536,6 +580,25 @@
reply->writeInt32(result);
return NO_ERROR;
}
+ case GET_SUPPORTED_FRAME_TIMESTAMPS: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ std::vector<FrameEvent> supportedTimestamps;
+ status_t result = getSupportedFrameTimestamps(&supportedTimestamps);
+ status_t err = reply->writeInt32(result);
+ if (err != NO_ERROR) {
+ return err;
+ }
+ if (result != NO_ERROR) {
+ return result;
+ }
+
+ std::vector<int32_t> supported;
+ supported.reserve(supportedTimestamps.size());
+ for (FrameEvent s : supportedTimestamps) {
+ supported.push_back(static_cast<int32_t>(s));
+ }
+ return reply->writeInt32Vector(supported);
+ }
case CREATE_DISPLAY_EVENT_CONNECTION: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IDisplayEventConnection> connection(createDisplayEventConnection());
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 2461cba..9b06e63 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -44,6 +44,7 @@
output.writeUint64(frameNumber);
output.writeInt32(overrideScalingMode);
output.writeStrongBinder(IInterface::asBinder(barrierGbp));
+ output.writeStrongBinder(relativeLayerHandle);
output.write(transparentRegion);
return NO_ERROR;
}
@@ -75,6 +76,7 @@
overrideScalingMode = input.readInt32();
barrierGbp =
interface_cast<IGraphicBufferProducer>(input.readStrongBinder());
+ relativeLayerHandle = input.readStrongBinder();
input.read(transparentRegion);
return NO_ERROR;
}
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 1149b89..a6d9e66 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -52,6 +52,8 @@
mAutoRefresh(false),
mSharedBufferSlot(BufferItem::INVALID_BUFFER_SLOT),
mSharedBufferHasBeenQueued(false),
+ mQueriedSupportedTimestamps(false),
+ mFrameTimestampsSupportsPresent(false),
mEnableFrameTimestamps(false),
mFrameEventHistory(std::make_unique<ProducerFrameEventHistory>())
{
@@ -209,8 +211,8 @@
bool checkForDisplayPresent = (outDisplayPresentTime != nullptr) &&
!e->hasDisplayPresentInfo();
- // LastRefreshStart, DequeueReady, and Release are never
- // available for the last frame.
+ // LastRefreshStart, DequeueReady, and Release are never available for the
+ // last frame.
bool checkForLastRefreshStart = (outLastRefreshStartTime != nullptr) &&
!e->hasLastRefreshStartInfo() &&
(e->frameNumber != lastFrameNumber);
@@ -227,14 +229,26 @@
static void getFrameTimestamp(nsecs_t *dst, const nsecs_t& src) {
if (dst != nullptr) {
- *dst = FrameEvents::isValidTimestamp(src) ? src : 0;
+ // We always get valid timestamps for these eventually.
+ *dst = (src == FrameEvents::TIMESTAMP_PENDING) ?
+ NATIVE_WINDOW_TIMESTAMP_PENDING : src;
}
}
-static void getFrameTimestampFence(nsecs_t *dst, const std::shared_ptr<FenceTime>& src) {
+static void getFrameTimestampFence(nsecs_t *dst,
+ const std::shared_ptr<FenceTime>& src, bool fenceShouldBeKnown) {
if (dst != nullptr) {
+ if (!fenceShouldBeKnown) {
+ *dst = NATIVE_WINDOW_TIMESTAMP_PENDING;
+ return;
+ }
+
nsecs_t signalTime = src->getSignalTime();
- *dst = Fence::isValidTimestamp(signalTime) ? signalTime : 0;
+ *dst = (signalTime == Fence::SIGNAL_TIME_PENDING) ?
+ NATIVE_WINDOW_TIMESTAMP_PENDING :
+ (signalTime == Fence::SIGNAL_TIME_INVALID) ?
+ NATIVE_WINDOW_TIMESTAMP_INVALID :
+ signalTime;
}
}
@@ -252,6 +266,12 @@
return INVALID_OPERATION;
}
+ // Verify the requested timestamps are supported.
+ querySupportedTimestampsLocked();
+ if (outDisplayPresentTime != nullptr && !mFrameTimestampsSupportsPresent) {
+ return BAD_VALUE;
+ }
+
FrameEvents* events = mFrameEventHistory->getFrame(frameNumber);
if (events == nullptr) {
// If the entry isn't available in the producer, it's definitely not
@@ -282,12 +302,15 @@
getFrameTimestamp(outLastRefreshStartTime, events->lastRefreshStartTime);
getFrameTimestamp(outDequeueReadyTime, events->dequeueReadyTime);
- getFrameTimestampFence(outAcquireTime, events->acquireFence);
- getFrameTimestampFence(
- outGpuCompositionDoneTime, events->gpuCompositionDoneFence);
- getFrameTimestampFence(
- outDisplayPresentTime, events->displayPresentFence);
- getFrameTimestampFence(outReleaseTime, events->releaseFence);
+ getFrameTimestampFence(outAcquireTime, events->acquireFence,
+ events->hasAcquireInfo());
+ getFrameTimestampFence(outGpuCompositionDoneTime,
+ events->gpuCompositionDoneFence,
+ events->hasGpuCompositionDoneInfo());
+ getFrameTimestampFence(outDisplayPresentTime, events->displayPresentFence,
+ events->hasDisplayPresentInfo());
+ getFrameTimestampFence(outReleaseTime, events->releaseFence,
+ events->hasReleaseInfo());
return NO_ERROR;
}
@@ -739,6 +762,29 @@
return err;
}
+void Surface::querySupportedTimestampsLocked() const {
+ // mMutex must be locked when calling this method.
+
+ if (mQueriedSupportedTimestamps) {
+ return;
+ }
+ mQueriedSupportedTimestamps = true;
+
+ std::vector<FrameEvent> supportedFrameTimestamps;
+ status_t err = composerService()->getSupportedFrameTimestamps(
+ &supportedFrameTimestamps);
+
+ if (err != NO_ERROR) {
+ return;
+ }
+
+ for (auto sft : supportedFrameTimestamps) {
+ if (sft == FrameEvent::DISPLAY_PRESENT) {
+ mFrameTimestampsSupportsPresent = true;
+ }
+ }
+}
+
int Surface::query(int what, int* value) const {
ATRACE_CALL();
ALOGV("Surface::query");
@@ -800,6 +846,11 @@
static_cast<int>(durationUs);
return NO_ERROR;
}
+ case NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT: {
+ querySupportedTimestampsLocked();
+ *value = mFrameTimestampsSupportsPresent ? 1 : 0;
+ return NO_ERROR;
+ }
case NATIVE_WINDOW_IS_VALID: {
*value = mGraphicBufferProducer != nullptr ? 1 : 0;
return NO_ERROR;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 56c7586..8c83843 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -149,6 +149,8 @@
uint32_t w, uint32_t h);
status_t setLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
int32_t z);
+ status_t setRelativeLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
+ const sp<IBinder>& relativeTo, int32_t z);
status_t setFlags(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
uint32_t flags, uint32_t mask);
status_t setTransparentRegionHint(
@@ -343,6 +345,20 @@
return NO_ERROR;
}
+status_t Composer::setRelativeLayer(const sp<SurfaceComposerClient>& client,
+ const sp<IBinder>& id, const sp<IBinder>& relativeTo,
+ int32_t z) {
+ Mutex::Autolock _l(mLock);
+ layer_state_t* s = getLayerStateLocked(client, id);
+ if (!s) {
+ return BAD_INDEX;
+ }
+ s->what |= layer_state_t::eRelativeLayerChanged;
+ s->relativeLayerHandle = relativeTo;
+ s->z = z;
+ return NO_ERROR;
+}
+
status_t Composer::setFlags(const sp<SurfaceComposerClient>& client,
const sp<IBinder>& id, uint32_t flags,
uint32_t mask) {
@@ -760,6 +776,11 @@
return getComposer().setLayer(this, id, z);
}
+status_t SurfaceComposerClient::setRelativeLayer(const sp<IBinder>& id,
+ const sp<IBinder>& relativeTo, int32_t z) {
+ return getComposer().setRelativeLayer(this, id, relativeTo, z);
+}
+
status_t SurfaceComposerClient::hide(const sp<IBinder>& id) {
return getComposer().setFlags(this, id,
layer_state_t::eLayerHidden,
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 7a68f11..bf8a815 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -102,11 +102,19 @@
if (err < 0) return err;
return mClient->setLayerStack(mHandle, layerStack);
}
+
status_t SurfaceControl::setLayer(int32_t layer) {
status_t err = validate();
if (err < 0) return err;
return mClient->setLayer(mHandle, layer);
}
+
+status_t SurfaceControl::setRelativeLayer(const sp<IBinder>& relativeTo, int32_t layer) {
+ status_t err = validate();
+ if (err < 0) return err;
+ return mClient->setRelativeLayer(mHandle, relativeTo, layer);
+}
+
status_t SurfaceControl::setPosition(float x, float y) {
status_t err = validate();
if (err < 0) return err;
diff --git a/libs/gui/include/private/gui/BitTube.h b/libs/gui/include/private/gui/BitTube.h
new file mode 100644
index 0000000..13c0162
--- /dev/null
+++ b/libs/gui/include/private/gui/BitTube.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/unique_fd.h>
+#include <binder/Parcelable.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+class Parcel;
+
+namespace gui {
+
+class BitTube : public Parcelable {
+public:
+ // creates an uninitialized BitTube (to unparcel into)
+ BitTube() = default;
+
+ // creates a BitTube with a a specified send and receive buffer size
+ explicit BitTube(size_t bufsize);
+
+ // creates a BitTube with a default (4KB) send buffer
+ struct DefaultSizeType {};
+ static constexpr DefaultSizeType DefaultSize{};
+ explicit BitTube(DefaultSizeType);
+
+ explicit BitTube(const Parcel& data);
+
+ virtual ~BitTube() = default;
+
+ // check state after construction
+ status_t initCheck() const;
+
+ // get receive file-descriptor
+ int getFd() const;
+
+ // get the send file-descriptor.
+ int getSendFd() const;
+
+ // moves the receive file descriptor out of this BitTube
+ base::unique_fd moveReceiveFd();
+
+ // resets this BitTube's receive file descriptor to receiveFd
+ void setReceiveFd(base::unique_fd&& receiveFd);
+
+ // send objects (sized blobs). All objects are guaranteed to be written or the call fails.
+ template <typename T>
+ static ssize_t sendObjects(BitTube* tube, T const* events, size_t count) {
+ return sendObjects(tube, events, count, sizeof(T));
+ }
+
+ // receive objects (sized blobs). If the receiving buffer isn't large enough, excess messages
+ // are silently discarded.
+ template <typename T>
+ static ssize_t recvObjects(BitTube* tube, T* events, size_t count) {
+ return recvObjects(tube, events, count, sizeof(T));
+ }
+
+ // implement the Parcelable protocol. Only parcels the receive file descriptor
+ status_t writeToParcel(Parcel* reply) const;
+ status_t readFromParcel(const Parcel* parcel);
+
+private:
+ void init(size_t rcvbuf, size_t sndbuf);
+
+ // send a message. The write is guaranteed to send the whole message or fail.
+ ssize_t write(void const* vaddr, size_t size);
+
+ // receive a message. the passed buffer must be at least as large as the write call used to send
+ // the message, excess data is silently discarded.
+ ssize_t read(void* vaddr, size_t size);
+
+ base::unique_fd mSendFd;
+ mutable base::unique_fd mReceiveFd;
+
+ static ssize_t sendObjects(BitTube* tube, void const* events, size_t count, size_t objSize);
+
+ static ssize_t recvObjects(BitTube* tube, void* events, size_t count, size_t objSize);
+};
+
+} // namespace gui
+} // namespace android
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index ce11486..cf3d1b2 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -368,6 +368,10 @@
public:
~FakeSurfaceComposer() override {}
+ void setSupportsPresent(bool supportsPresent) {
+ mSupportsPresent = supportsPresent;
+ }
+
sp<ISurfaceComposerClient> createConnection() override { return nullptr; }
sp<ISurfaceComposerClient> createScopedConnection(
const sp<IGraphicBufferProducer>& /* parent */) override {
@@ -391,6 +395,26 @@
const sp<IGraphicBufferProducer>& /*surface*/) const override {
return false;
}
+
+ status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported)
+ const override {
+ *outSupported = {
+ FrameEvent::REQUESTED_PRESENT,
+ FrameEvent::ACQUIRE,
+ FrameEvent::LATCH,
+ FrameEvent::FIRST_REFRESH_START,
+ FrameEvent::LAST_REFRESH_START,
+ FrameEvent::GPU_COMPOSITION_DONE,
+ FrameEvent::DEQUEUE_READY,
+ FrameEvent::RELEASE
+ };
+ if (mSupportsPresent) {
+ outSupported->push_back(
+ FrameEvent::DISPLAY_PRESENT);
+ }
+ return NO_ERROR;
+ }
+
void setPowerMode(const sp<IBinder>& /*display*/, int /*mode*/) override {}
status_t getDisplayConfigs(const sp<IBinder>& /*display*/,
Vector<DisplayInfo>* /*configs*/) override { return NO_ERROR; }
@@ -435,7 +459,6 @@
private:
bool mSupportsPresent{true};
- bool mSupportsRetire{true};
};
class FakeProducerFrameEventHistory : public ProducerFrameEventHistory {
@@ -864,6 +887,28 @@
EXPECT_EQ(4, mFakeConsumer->mGetFrameTimestampsCount);
}
+TEST_F(GetFrameTimestampsTest, QueryPresentSupported) {
+ bool displayPresentSupported = true;
+ mSurface->mFakeSurfaceComposer->setSupportsPresent(displayPresentSupported);
+
+ // Verify supported bits are forwarded.
+ int supportsPresent = -1;
+ mWindow.get()->query(mWindow.get(),
+ NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &supportsPresent);
+ EXPECT_EQ(displayPresentSupported, supportsPresent);
+}
+
+TEST_F(GetFrameTimestampsTest, QueryPresentNotSupported) {
+ bool displayPresentSupported = false;
+ mSurface->mFakeSurfaceComposer->setSupportsPresent(displayPresentSupported);
+
+ // Verify supported bits are forwarded.
+ int supportsPresent = -1;
+ mWindow.get()->query(mWindow.get(),
+ NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &supportsPresent);
+ EXPECT_EQ(displayPresentSupported, supportsPresent);
+}
+
TEST_F(GetFrameTimestampsTest, SnapToNextTickBasic) {
nsecs_t phase = 4000;
nsecs_t interval = 1000;
@@ -1139,8 +1184,8 @@
EXPECT_EQ(mFrames[1].mRefreshes[0].kGpuCompositionDoneTime,
outGpuCompositionDoneTime);
EXPECT_EQ(mFrames[1].mRefreshes[0].kPresentTime, outDisplayPresentTime);
- EXPECT_EQ(0, outDequeueReadyTime);
- EXPECT_EQ(0, outReleaseTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDequeueReadyTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
}
// This test verifies the acquire fence recorded by the consumer is not sent
@@ -1163,7 +1208,7 @@
EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
EXPECT_EQ(NO_ERROR, result);
EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
- EXPECT_EQ(0, outAcquireTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outAcquireTime);
// Signal acquire fences. Verify a sync call still isn't necessary.
mFrames[0].signalQueueFences();
@@ -1192,7 +1237,7 @@
EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
EXPECT_EQ(NO_ERROR, result);
EXPECT_EQ(mFrames[1].kRequestedPresentTime, outRequestedPresentTime);
- EXPECT_EQ(0, outAcquireTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outAcquireTime);
// Signal acquire fences. Verify a sync call still isn't necessary.
mFrames[1].signalQueueFences();
@@ -1228,8 +1273,8 @@
// Verify a request for no timestamps doesn't result in a sync call.
int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
int result = native_window_get_frame_timestamps(mWindow.get(), fId2,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr);
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr);
EXPECT_EQ(NO_ERROR, result);
EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
}
@@ -1265,10 +1310,10 @@
EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
- EXPECT_EQ(0, outGpuCompositionDoneTime);
- EXPECT_EQ(0, outDisplayPresentTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outGpuCompositionDoneTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
- EXPECT_EQ(0, outReleaseTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
// Verify available timestamps are correct for frame 1 again, before any
// fence has been signaled.
@@ -1283,10 +1328,10 @@
EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
- EXPECT_EQ(0, outGpuCompositionDoneTime);
- EXPECT_EQ(0, outDisplayPresentTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outGpuCompositionDoneTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
- EXPECT_EQ(0, outReleaseTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
// Signal the fences for frame 1.
mFrames[0].signalRefreshFences();
@@ -1342,10 +1387,10 @@
EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
- EXPECT_EQ(0, outGpuCompositionDoneTime);
- EXPECT_EQ(0, outDisplayPresentTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
- EXPECT_EQ(0, outReleaseTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
// Signal the fences for frame 1.
mFrames[0].signalRefreshFences();
@@ -1363,7 +1408,7 @@
EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
- EXPECT_EQ(0, outGpuCompositionDoneTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
EXPECT_EQ(mFrames[0].mRefreshes[0].kPresentTime, outDisplayPresentTime);
EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
EXPECT_EQ(mFrames[0].kReleaseTime, outReleaseTime);
@@ -1371,7 +1416,7 @@
// This test verifies that if the certain timestamps can't possibly exist for
// the most recent frame, then a sync call is not done.
-TEST_F(GetFrameTimestampsTest, NoRetireOrReleaseNoSync) {
+TEST_F(GetFrameTimestampsTest, NoReleaseNoSync) {
enableFrameTimestamps();
// Dequeue and queue frame 1.
@@ -1401,10 +1446,10 @@
EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
- EXPECT_EQ(0, outGpuCompositionDoneTime);
- EXPECT_EQ(0, outDisplayPresentTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
- EXPECT_EQ(0, outReleaseTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
mFrames[0].signalRefreshFences();
mFrames[0].signalReleaseFences();
@@ -1425,10 +1470,33 @@
EXPECT_EQ(mFrames[1].kLatchTime, outLatchTime);
EXPECT_EQ(mFrames[1].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
EXPECT_EQ(mFrames[1].mRefreshes[1].kStartTime, outLastRefreshStartTime);
- EXPECT_EQ(0, outGpuCompositionDoneTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
EXPECT_EQ(mFrames[1].mRefreshes[0].kPresentTime, outDisplayPresentTime);
- EXPECT_EQ(0, outDequeueReadyTime);
- EXPECT_EQ(0, outReleaseTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDequeueReadyTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
+}
+
+// This test verifies there are no sync calls for present times
+// when they aren't supported and that an error is returned.
+
+TEST_F(GetFrameTimestampsTest, PresentUnsupportedNoSync) {
+ enableFrameTimestamps();
+ mSurface->mFakeSurfaceComposer->setSupportsPresent(false);
+
+ // Dequeue and queue frame 1.
+ const uint64_t fId1 = getNextFrameId();
+ dequeueAndQueue(0);
+
+ // Verify a query for the Present times do not trigger a sync call if they
+ // are not supported.
+ resetTimestamps();
+ int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
+ int result = native_window_get_frame_timestamps(mWindow.get(), fId1,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ &outDisplayPresentTime, nullptr, nullptr);
+ EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
+ EXPECT_EQ(BAD_VALUE, result);
+ EXPECT_EQ(-1, outDisplayPresentTime);
}
}
diff --git a/libs/hwc2on1adapter/Android.bp b/libs/hwc2on1adapter/Android.bp
index 438d3f5..5d7f660 100644
--- a/libs/hwc2on1adapter/Android.bp
+++ b/libs/hwc2on1adapter/Android.bp
@@ -14,6 +14,7 @@
cc_library_shared {
name: "libhwc2on1adapter",
+ vendor_available: true,
clang: true,
cppflags: [
diff --git a/libs/hwc2on1adapter/HWC2On1Adapter.cpp b/libs/hwc2on1adapter/HWC2On1Adapter.cpp
index e35bfc9..8c6ef69 100644
--- a/libs/hwc2on1adapter/HWC2On1Adapter.cpp
+++ b/libs/hwc2on1adapter/HWC2On1Adapter.cpp
@@ -2246,6 +2246,11 @@
mHwc1SupportsBackgroundColor = true;
}
}
+
+ // Some devices might have HWC1 retire fences that accurately emulate
+ // HWC2 present fences when they are deferred, but it's not very reliable.
+ // To be safe, we indicate PresentFenceIsNotReliable for all HWC1 devices.
+ mCapabilities.insert(Capability::PresentFenceIsNotReliable);
}
HWC2On1Adapter::Display* HWC2On1Adapter::getDisplay(hwc2_display_t id) {
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index 90fb4b6..6c8221d 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -21,7 +21,7 @@
}
ndk_library {
- name: "libnativewindow.ndk",
+ name: "libnativewindow",
symbol_file: "libnativewindow.map.txt",
// Android O
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 63d1ad1..fb67a51 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -186,6 +186,12 @@
* if it is safe (i.e. no crash will occur) to call any method on it.
*/
NATIVE_WINDOW_IS_VALID = 17,
+
+ /*
+ * Returns 1 if NATIVE_WINDOW_GET_FRAME_TIMESTAMPS will return display
+ * present info, 0 if it won't.
+ */
+ NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT = 18,
};
/* Valid operations for the (*perform)() hook.
@@ -305,6 +311,14 @@
*/
static const int64_t NATIVE_WINDOW_TIMESTAMP_AUTO = (-9223372036854775807LL-1);
+/* parameter for NATIVE_WINDOW_GET_FRAME_TIMESTAMPS
+ *
+ * Special timestamp value to indicate the timestamps aren't yet known or
+ * that they are invalid.
+ */
+static const int64_t NATIVE_WINDOW_TIMESTAMP_PENDING = -2;
+static const int64_t NATIVE_WINDOW_TIMESTAMP_INVALID = -1;
+
struct ANativeWindow
{
#ifdef __cplusplus
diff --git a/libs/sensor/ISensorServer.cpp b/libs/sensor/ISensorServer.cpp
index f41f187..74186df 100644
--- a/libs/sensor/ISensorServer.cpp
+++ b/libs/sensor/ISensorServer.cpp
@@ -40,6 +40,7 @@
ENABLE_DATA_INJECTION,
GET_DYNAMIC_SENSOR_LIST,
CREATE_SENSOR_DIRECT_CONNECTION,
+ SET_OPERATION_PARAMETER,
};
class BpSensorServer : public BpInterface<ISensorServer>
@@ -117,6 +118,23 @@
remote()->transact(CREATE_SENSOR_DIRECT_CONNECTION, data, &reply);
return interface_cast<ISensorEventConnection>(reply.readStrongBinder());
}
+
+ virtual int setOperationParameter(
+ int32_t type, const Vector<float> &floats, const Vector<int32_t> &ints) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor());
+ data.writeInt32(type);
+ data.writeUint32(static_cast<uint32_t>(floats.size()));
+ for (auto i : floats) {
+ data.writeFloat(i);
+ }
+ data.writeUint32(static_cast<uint32_t>(ints.size()));
+ for (auto i : ints) {
+ data.writeInt32(i);
+ }
+ remote()->transact(SET_OPERATION_PARAMETER, data, &reply);
+ return reply.readInt32();
+ }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -183,6 +201,26 @@
reply->writeStrongBinder(IInterface::asBinder(ch));
return NO_ERROR;
}
+ case SET_OPERATION_PARAMETER: {
+ CHECK_INTERFACE(ISensorServer, data, reply);
+ int32_t type;
+ Vector<float> floats;
+ Vector<int32_t> ints;
+
+ type = data.readInt32();
+ floats.resize(data.readUint32());
+ for (auto &i : floats) {
+ i = data.readFloat();
+ }
+ ints.resize(data.readUint32());
+ for (auto &i : ints) {
+ i = data.readInt32();
+ }
+
+ int32_t ret = setOperationParameter(type, floats, ints);
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ }
}
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/sensor/SensorManager.cpp b/libs/sensor/SensorManager.cpp
index d6d3304..3fbc5eb 100644
--- a/libs/sensor/SensorManager.cpp
+++ b/libs/sensor/SensorManager.cpp
@@ -304,5 +304,14 @@
return ret;
}
+int SensorManager::setOperationParameter(
+ int type, const Vector<float> &floats, const Vector<int32_t> &ints) {
+ Mutex::Autolock _l(mLock);
+ if (assertStateLocked() != NO_ERROR) {
+ return NO_INIT;
+ }
+ return mSensorServer->setOperationParameter(type, floats, ints);
+}
+
// ----------------------------------------------------------------------------
}; // namespace android
diff --git a/libs/sensor/include/sensor/ISensorServer.h b/libs/sensor/include/sensor/ISensorServer.h
index f922307..8d50062 100644
--- a/libs/sensor/include/sensor/ISensorServer.h
+++ b/libs/sensor/include/sensor/ISensorServer.h
@@ -50,6 +50,9 @@
virtual sp<ISensorEventConnection> createSensorDirectConnection(const String16& opPackageName,
uint32_t size, int32_t type, int32_t format, const native_handle_t *resource) = 0;
+
+ virtual int setOperationParameter(
+ int32_t type, const Vector<float> &floats, const Vector<int32_t> &ints) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/libs/sensor/include/sensor/SensorManager.h b/libs/sensor/include/sensor/SensorManager.h
index 92c9823..5fc85d3 100644
--- a/libs/sensor/include/sensor/SensorManager.h
+++ b/libs/sensor/include/sensor/SensorManager.h
@@ -64,6 +64,7 @@
int createDirectChannel(size_t size, int channelType, const native_handle_t *channelData);
void destroyDirectChannel(int channelNativeHandle);
int configureDirectChannel(int channelNativeHandle, int sensorHandle, int rateLevel);
+ int setOperationParameter(int type, const Vector<float> &floats, const Vector<int32_t> &ints);
private:
// DeathRecipient interface
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 80fb064..ba37391 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -45,13 +45,13 @@
srcs: [
"ColorSpace.cpp",
+ "DebugUtils.cpp",
"Fence.cpp",
"FenceTime.cpp",
"FrameStats.cpp",
"Gralloc1.cpp",
"Gralloc1On0Adapter.cpp",
- "GrallocAllocator.cpp",
- "GrallocMapper.cpp",
+ "Gralloc2.cpp",
"GraphicBuffer.cpp",
"GraphicBufferAllocator.cpp",
"GraphicBufferMapper.cpp",
@@ -66,6 +66,9 @@
shared_libs: [
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.configstore@1.0",
+ "android.hardware.configstore-utils",
+ "libbase",
"libnativeloader",
"libcutils",
"libhardware",
diff --git a/libs/ui/DebugUtils.cpp b/libs/ui/DebugUtils.cpp
new file mode 100644
index 0000000..882bd7c
--- /dev/null
+++ b/libs/ui/DebugUtils.cpp
@@ -0,0 +1,187 @@
+/*
+ * Copyright 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 <ui/DebugUtils.h>
+
+#include <android-base/stringprintf.h>
+#include <string>
+
+std::string decodeStandard(android_dataspace dataspace) {
+ const uint32_t dataspaceSelect = (dataspace & HAL_DATASPACE_STANDARD_MASK);
+ switch (dataspaceSelect) {
+ case HAL_DATASPACE_STANDARD_BT709:
+ return std::string("BT709");
+
+ case HAL_DATASPACE_STANDARD_BT601_625:
+ return std::string("BT601_625");
+
+ case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
+ return std::string("BT601_625_UNADJUSTED");
+
+ case HAL_DATASPACE_STANDARD_BT601_525:
+ return std::string("BT601_525");
+
+ case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
+ return std::string("BT601_525_UNADJUSTED");
+
+ case HAL_DATASPACE_STANDARD_BT2020:
+ return std::string("BT2020");
+
+ case HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE:
+ return std::string("BT2020 (constant luminance)");
+
+ case HAL_DATASPACE_STANDARD_BT470M:
+ return std::string("BT470M");
+
+ case HAL_DATASPACE_STANDARD_FILM:
+ return std::string("FILM");
+
+ case HAL_DATASPACE_STANDARD_DCI_P3:
+ return std::string("DCI-P3");
+
+ case HAL_DATASPACE_STANDARD_ADOBE_RGB:
+ return std::string("AdobeRGB");
+
+ case 0:
+ switch (dataspace & 0xffff) {
+ case HAL_DATASPACE_JFIF:
+ return std::string("(deprecated) JFIF (BT601_625, SMPTE_170M Full range)");
+
+ case HAL_DATASPACE_BT601_625:
+ return std::string("(deprecated) BT601_625 (BT601_625, SMPTE_170M Limited "
+ "range)");
+
+ case HAL_DATASPACE_BT601_525:
+ return std::string("(deprecated) BT601_525 (BT601_525, SMPTE_170M Limited "
+ "range)");
+
+ case HAL_DATASPACE_SRGB_LINEAR:
+ return std::string("(deprecated) SRGB Linear Full range");
+
+ case HAL_DATASPACE_SRGB:
+ return std::string("(deprecated) sRGB");
+
+ case HAL_DATASPACE_V0_BT709:
+ return std::string("(deprecated) BT709 (BT709, SMPTE_170M Limited range)");
+
+ case HAL_DATASPACE_ARBITRARY:
+ return std::string("ARBITRARY");
+
+ case HAL_DATASPACE_UNKNOWN:
+ // Fallthrough
+ default:
+ return android::base::StringPrintf("Unknown deprecated dataspace code %d",
+ dataspaceSelect);
+ }
+ }
+
+ return android::base::StringPrintf("Unknown dataspace code %d", dataspaceSelect);
+}
+
+std::string decodeTransfer(android_dataspace dataspace) {
+ const uint32_t dataspaceTransfer = (dataspace & HAL_DATASPACE_TRANSFER_MASK);
+ switch (dataspaceTransfer) {
+ case HAL_DATASPACE_TRANSFER_UNSPECIFIED:
+ return std::string("Unspecified");
+
+ case HAL_DATASPACE_TRANSFER_LINEAR:
+ return std::string("Linear");
+
+ case HAL_DATASPACE_TRANSFER_SRGB:
+ return std::string("sRGB");
+
+ case HAL_DATASPACE_TRANSFER_SMPTE_170M:
+ return std::string("SMPTE_170M");
+
+ case HAL_DATASPACE_TRANSFER_GAMMA2_2:
+ return std::string("gamma 2.2");
+
+ case HAL_DATASPACE_TRANSFER_GAMMA2_6:
+ return std::string("gamma 2.6");
+
+ case HAL_DATASPACE_TRANSFER_GAMMA2_8:
+ return std::string("gamma 2.8");
+
+ case HAL_DATASPACE_TRANSFER_ST2084:
+ return std::string("SMPTE 2084");
+
+ case HAL_DATASPACE_TRANSFER_HLG:
+ return std::string("STD-B67");
+ }
+
+ return android::base::StringPrintf("Unknown dataspace transfer %d", dataspaceTransfer);
+}
+
+std::string decodeRange(android_dataspace dataspace) {
+ const uint32_t dataspaceRange = (dataspace & HAL_DATASPACE_RANGE_MASK);
+ switch (dataspaceRange) {
+ case HAL_DATASPACE_RANGE_UNSPECIFIED:
+ return std::string("Range Unspecified");
+
+ case HAL_DATASPACE_RANGE_FULL:
+ return std::string("Full range");
+
+ case HAL_DATASPACE_RANGE_LIMITED:
+ return std::string("Limited range");
+
+ case HAL_DATASPACE_RANGE_EXTENDED:
+ return std::string("Extended range");
+ }
+
+ return android::base::StringPrintf("Unknown dataspace range %d", dataspaceRange);
+}
+
+std::string dataspaceDetails(android_dataspace dataspace) {
+ return android::base::StringPrintf("%s %s %s", decodeStandard(dataspace).c_str(),
+ decodeTransfer(dataspace).c_str(),
+ decodeRange(dataspace).c_str());
+}
+
+std::string decodeColorMode(android_color_mode colorMode) {
+ switch (colorMode) {
+ case HAL_COLOR_MODE_NATIVE:
+ return std::string("HAL_COLOR_MODE_NATIVE");
+
+ case HAL_COLOR_MODE_STANDARD_BT601_625:
+ return std::string("HAL_COLOR_MODE_BT601_625");
+
+ case HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED:
+ return std::string("HAL_COLOR_MODE_BT601_625_UNADJUSTED");
+
+ case HAL_COLOR_MODE_STANDARD_BT601_525:
+ return std::string("HAL_COLOR_MODE_BT601_525");
+
+ case HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED:
+ return std::string("HAL_COLOR_MODE_BT601_525_UNADJUSTED");
+
+ case HAL_COLOR_MODE_STANDARD_BT709:
+ return std::string("HAL_COLOR_MODE_BT709");
+
+ case HAL_COLOR_MODE_DCI_P3:
+ return std::string("HAL_COLOR_MODE_DCI_P3");
+
+ case HAL_COLOR_MODE_SRGB:
+ return std::string("HAL_COLOR_MODE_SRGB");
+
+ case HAL_COLOR_MODE_ADOBE_RGB:
+ return std::string("HAL_COLOR_MODE_ADOBE_RGB");
+
+ case HAL_COLOR_MODE_DISPLAY_P3:
+ return std::string("HAL_COLOR_MODE_DISPLAY_P3");
+ }
+
+ return android::base::StringPrintf("Unknown color mode %d", colorMode);
+}
diff --git a/libs/ui/Gralloc1On0Adapter.cpp b/libs/ui/Gralloc1On0Adapter.cpp
index bd7c6a1..9ee9838 100644
--- a/libs/ui/Gralloc1On0Adapter.cpp
+++ b/libs/ui/Gralloc1On0Adapter.cpp
@@ -20,6 +20,9 @@
#include <ui/Gralloc1On0Adapter.h>
+#include <algorithm>
+#include <array>
+
#include <grallocusage/GrallocUsageConversion.h>
#include <hardware/gralloc.h>
@@ -67,13 +70,18 @@
void Gralloc1On0Adapter::doGetCapabilities(uint32_t* outCount,
int32_t* outCapabilities)
{
+ constexpr std::array<int32_t, 2> supportedCapabilities = {{
+ GRALLOC1_CAPABILITY_ON_ADAPTER,
+ GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE,
+ }};
+
if (outCapabilities == nullptr) {
- *outCount = 1;
- return;
- }
- if (*outCount >= 1) {
- *outCapabilities = GRALLOC1_CAPABILITY_ON_ADAPTER;
- *outCount = 1;
+ *outCount = supportedCapabilities.size();
+ } else {
+ *outCount = std::min(*outCount, static_cast<uint32_t>(
+ supportedCapabilities.size()));
+ std::copy_n(supportedCapabilities.begin(),
+ *outCount, outCapabilities);
}
}
@@ -325,6 +333,9 @@
if (result != 0) {
ALOGE("gralloc0 unregister failed: %d", result);
}
+
+ native_handle_close(handle);
+ native_handle_delete(const_cast<native_handle_t*>(handle));
}
mBuffers.erase(handle);
diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp
new file mode 100644
index 0000000..75f5686
--- /dev/null
+++ b/libs/ui/Gralloc2.cpp
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Gralloc2"
+
+#include <ui/Gralloc2.h>
+
+#include <log/log.h>
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wzero-length-array"
+#include <sync/sync.h>
+#pragma clang diagnostic pop
+
+namespace android {
+
+namespace Gralloc2 {
+
+static constexpr Error kTransactionError = Error::NO_RESOURCES;
+
+Mapper::Mapper()
+{
+ mMapper = IMapper::getService();
+ if (mMapper != nullptr && mMapper->isRemote()) {
+ LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode");
+ }
+}
+
+Error Mapper::createDescriptor(
+ const IMapper::BufferDescriptorInfo& descriptorInfo,
+ BufferDescriptor* outDescriptor) const
+{
+ Error error;
+ auto ret = mMapper->createDescriptor(descriptorInfo,
+ [&](const auto& tmpError, const auto& tmpDescriptor)
+ {
+ error = tmpError;
+ if (error != Error::NONE) {
+ return;
+ }
+
+ *outDescriptor = tmpDescriptor;
+ });
+
+ return (ret.isOk()) ? error : kTransactionError;
+}
+
+Error Mapper::importBuffer(const hardware::hidl_handle& rawHandle,
+ buffer_handle_t* outBufferHandle) const
+{
+ Error error;
+ auto ret = mMapper->importBuffer(rawHandle,
+ [&](const auto& tmpError, const auto& tmpBuffer)
+ {
+ error = tmpError;
+ if (error != Error::NONE) {
+ return;
+ }
+
+ *outBufferHandle = static_cast<buffer_handle_t>(tmpBuffer);
+ });
+
+ return (ret.isOk()) ? error : kTransactionError;
+}
+
+void Mapper::freeBuffer(buffer_handle_t bufferHandle) const
+{
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
+ auto ret = mMapper->freeBuffer(buffer);
+
+ auto error = (ret.isOk()) ? static_cast<Error>(ret) : kTransactionError;
+ ALOGE_IF(error != Error::NONE, "freeBuffer(%p) failed with %d",
+ buffer, error);
+}
+
+Error Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage,
+ const IMapper::Rect& accessRegion,
+ int acquireFence, void** outData) const
+{
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+ // put acquireFence in a hidl_handle
+ hardware::hidl_handle acquireFenceHandle;
+ NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+ if (acquireFence >= 0) {
+ auto h = native_handle_init(acquireFenceStorage, 1, 0);
+ h->data[0] = acquireFence;
+ acquireFenceHandle = h;
+ }
+
+ Error error;
+ auto ret = mMapper->lock(buffer, usage, accessRegion, acquireFenceHandle,
+ [&](const auto& tmpError, const auto& tmpData)
+ {
+ error = tmpError;
+ if (error != Error::NONE) {
+ return;
+ }
+
+ *outData = tmpData;
+ });
+
+ // we own acquireFence even on errors
+ if (acquireFence >= 0) {
+ close(acquireFence);
+ }
+
+ return (ret.isOk()) ? error : kTransactionError;
+}
+
+Error Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage,
+ const IMapper::Rect& accessRegion,
+ int acquireFence, YCbCrLayout* outLayout) const
+{
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+ // put acquireFence in a hidl_handle
+ hardware::hidl_handle acquireFenceHandle;
+ NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+ if (acquireFence >= 0) {
+ auto h = native_handle_init(acquireFenceStorage, 1, 0);
+ h->data[0] = acquireFence;
+ acquireFenceHandle = h;
+ }
+
+ Error error;
+ auto ret = mMapper->lockYCbCr(buffer, usage, accessRegion,
+ acquireFenceHandle,
+ [&](const auto& tmpError, const auto& tmpLayout)
+ {
+ error = tmpError;
+ if (error != Error::NONE) {
+ return;
+ }
+
+ *outLayout = tmpLayout;
+ });
+
+ // we own acquireFence even on errors
+ if (acquireFence >= 0) {
+ close(acquireFence);
+ }
+
+ return (ret.isOk()) ? error : kTransactionError;
+}
+
+int Mapper::unlock(buffer_handle_t bufferHandle) const
+{
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+ int releaseFence = -1;
+ Error error;
+ auto ret = mMapper->unlock(buffer,
+ [&](const auto& tmpError, const auto& tmpReleaseFence)
+ {
+ error = tmpError;
+ if (error != Error::NONE) {
+ return;
+ }
+
+ auto fenceHandle = tmpReleaseFence.getNativeHandle();
+ if (fenceHandle && fenceHandle->numFds == 1) {
+ int fd = dup(fenceHandle->data[0]);
+ if (fd >= 0) {
+ releaseFence = fd;
+ } else {
+ ALOGD("failed to dup unlock release fence");
+ sync_wait(fenceHandle->data[0], -1);
+ }
+ }
+ });
+
+ if (!ret.isOk()) {
+ error = kTransactionError;
+ }
+
+ if (error != Error::NONE) {
+ ALOGE("unlock(%p) failed with %d", buffer, error);
+ }
+
+ return releaseFence;
+}
+
+Allocator::Allocator(const Mapper& mapper)
+ : mMapper(mapper)
+{
+ if (mMapper.valid()) {
+ mAllocator = IAllocator::getService();
+ }
+}
+
+std::string Allocator::dumpDebugInfo() const
+{
+ std::string debugInfo;
+
+ mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) {
+ debugInfo = tmpDebugInfo.c_str();
+ });
+
+ return debugInfo;
+}
+
+Error Allocator::allocate(BufferDescriptor descriptor, uint32_t count,
+ uint32_t* outStride, buffer_handle_t* outBufferHandles) const
+{
+ Error error;
+ auto ret = mAllocator->allocate(descriptor, count,
+ [&](const auto& tmpError, const auto& tmpStride,
+ const auto& tmpBuffers) {
+ error = tmpError;
+ if (tmpError != Error::NONE) {
+ return;
+ }
+
+ // import buffers
+ for (uint32_t i = 0; i < count; i++) {
+ error = mMapper.importBuffer(tmpBuffers[i],
+ &outBufferHandles[i]);
+ if (error != Error::NONE) {
+ for (uint32_t j = 0; j < i; j++) {
+ mMapper.freeBuffer(outBufferHandles[j]);
+ outBufferHandles[j] = nullptr;
+ }
+ return;
+ }
+ }
+
+ *outStride = tmpStride;
+ });
+
+ return (ret.isOk()) ? error : kTransactionError;
+}
+
+} // namespace Gralloc2
+
+} // namespace android
diff --git a/libs/ui/GrallocAllocator.cpp b/libs/ui/GrallocAllocator.cpp
deleted file mode 100644
index 7af55e7..0000000
--- a/libs/ui/GrallocAllocator.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "GrallocAllocator"
-
-#include <ui/GrallocAllocator.h>
-
-#include <log/log.h>
-
-namespace android {
-
-namespace Gralloc2 {
-
-// assume NO_RESOURCES when Status::isOk returns false
-constexpr Error kDefaultError = Error::NO_RESOURCES;
-
-Allocator::Allocator()
-{
- mAllocator = IAllocator::getService();
- if (mAllocator != nullptr) {
- mAllocator->createClient(
- [&](const auto& tmpError, const auto& tmpClient) {
- if (tmpError == Error::NONE) {
- mClient = tmpClient;
- }
- });
- if (mClient == nullptr) {
- mAllocator.clear();
- }
- }
-}
-
-std::string Allocator::dumpDebugInfo() const
-{
- std::string info;
-
- mAllocator->dumpDebugInfo([&](const auto& tmpInfo) {
- info = tmpInfo.c_str();
- });
-
- return info;
-}
-
-Error Allocator::createBufferDescriptor(
- const IAllocatorClient::BufferDescriptorInfo& descriptorInfo,
- BufferDescriptor* outDescriptor) const
-{
- Error error = kDefaultError;
- mClient->createDescriptor(descriptorInfo,
- [&](const auto& tmpError, const auto& tmpDescriptor) {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
-
- *outDescriptor = tmpDescriptor;
- });
-
- return error;
-}
-
-void Allocator::destroyBufferDescriptor(BufferDescriptor descriptor) const
-{
- mClient->destroyDescriptor(descriptor);
-}
-
-Error Allocator::allocate(BufferDescriptor descriptor,
- Buffer* outBuffer) const
-{
- hardware::hidl_vec<BufferDescriptor> descriptors;
- descriptors.setToExternal(&descriptor, 1);
-
- Error error = kDefaultError;
- auto status = mClient->allocate(descriptors,
- [&](const auto& tmpError, const auto& tmpBuffers) {
- error = tmpError;
- if (tmpError != Error::NONE) {
- return;
- }
-
- *outBuffer = tmpBuffers[0];
- });
-
- return error;
-}
-
-void Allocator::free(Buffer buffer) const
-{
- mClient->free(buffer);
-}
-
-Error Allocator::exportHandle(BufferDescriptor descriptor, Buffer buffer,
- native_handle_t** outBufferHandle) const
-{
- Error error = kDefaultError;
- auto status = mClient->exportHandle(descriptor, buffer,
- [&](const auto& tmpError, const auto& tmpBufferHandle) {
- error = tmpError;
- if (tmpError != Error::NONE) {
- return;
- }
-
- *outBufferHandle = native_handle_clone(tmpBufferHandle);
- if (!*outBufferHandle) {
- error = Error::NO_RESOURCES;
- }
- });
-
- return error;
-}
-
-} // namespace Gralloc2
-
-} // namespace android
diff --git a/libs/ui/GrallocMapper.cpp b/libs/ui/GrallocMapper.cpp
deleted file mode 100644
index 8095247..0000000
--- a/libs/ui/GrallocMapper.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "GrallocMapper"
-
-#include <ui/GrallocMapper.h>
-
-#include <log/log.h>
-
-namespace android {
-
-namespace Gralloc2 {
-
-static constexpr Error kDefaultError = Error::NO_RESOURCES;
-
-Mapper::Mapper()
-{
- mMapper = IMapper::getService();
- if (mMapper != nullptr && mMapper->isRemote()) {
- LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode");
- }
-}
-
-Error Mapper::retain(buffer_handle_t handle) const
-{
- auto ret = mMapper->retain(handle);
- return (ret.isOk()) ? static_cast<Error>(ret) : kDefaultError;
-}
-
-void Mapper::release(buffer_handle_t handle) const
-{
- auto ret = mMapper->release(handle);
-
- auto error = (ret.isOk()) ? static_cast<Error>(ret) : kDefaultError;
- ALOGE_IF(error != Error::NONE,
- "release(%p) failed with %d", handle, error);
-}
-
-Error Mapper::getDimensions(buffer_handle_t handle,
- uint32_t* outWidth, uint32_t* outHeight) const
-{
- Error error = kDefaultError;
- mMapper->getDimensions(handle,
- [&](const auto& tmpError, const auto& tmpWidth,
- const auto& tmpHeight)
- {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
-
- *outWidth = tmpWidth;
- *outHeight = tmpHeight;
- });
-
- return error;
-}
-
-Error Mapper::getFormat(buffer_handle_t handle, int32_t* outFormat) const
-{
- Error error = kDefaultError;
- mMapper->getFormat(handle,
- [&](const auto& tmpError, const auto& tmpFormat)
- {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
-
- *outFormat = static_cast<int32_t>(tmpFormat);
- });
-
- return error;
-}
-
-Error Mapper::getLayerCount(buffer_handle_t handle,
- uint32_t* outLayerCount) const
-{
- Error error = kDefaultError;
- mMapper->getLayerCount(handle,
- [&](const auto& tmpError, const auto& tmpLayerCount)
- {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
-
- *outLayerCount = tmpLayerCount;
- });
-
- return error;
-}
-
-Error Mapper::getProducerUsage(buffer_handle_t handle,
- uint64_t* outProducerUsage) const
-{
- Error error = kDefaultError;
- mMapper->getProducerUsageMask(handle,
- [&](const auto& tmpError, const auto& tmpProducerUsage)
- {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
-
- *outProducerUsage = tmpProducerUsage;
- });
-
- return error;
-}
-
-Error Mapper::getConsumerUsage(buffer_handle_t handle,
- uint64_t* outConsumerUsage) const
-{
- Error error = kDefaultError;
- mMapper->getConsumerUsageMask(handle,
- [&](const auto& tmpError, const auto& tmpConsumerUsage)
- {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
-
- *outConsumerUsage = tmpConsumerUsage;
- });
-
- return error;
-}
-
-Error Mapper::getBackingStore(buffer_handle_t handle,
- uint64_t* outBackingStore) const
-{
- Error error = kDefaultError;
- mMapper->getBackingStore(handle,
- [&](const auto& tmpError, const auto& tmpStore)
- {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
-
- *outBackingStore = tmpStore;
- });
-
- return error;
-}
-
-Error Mapper::getStride(buffer_handle_t handle, uint32_t* outStride) const
-{
- Error error = kDefaultError;
- mMapper->getStride(handle,
- [&](const auto& tmpError, const auto& tmpStride)
- {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
-
- *outStride = tmpStride;
- });
-
- return error;
-}
-
-Error Mapper::lock(buffer_handle_t handle,
- uint64_t producerUsage,
- uint64_t consumerUsage,
- const IMapper::Rect& accessRegion,
- int acquireFence, void** outData) const
-{
- hardware::hidl_handle acquireFenceHandle;
-
- NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
- if (acquireFence >= 0) {
- auto h = native_handle_init(acquireFenceStorage, 1, 0);
- h->data[0] = acquireFence;
- acquireFenceHandle = h;
- }
-
- Error error = kDefaultError;
- mMapper->lock(handle, producerUsage, consumerUsage,
- accessRegion, acquireFenceHandle,
- [&](const auto& tmpError, const auto& tmpData)
- {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
-
- *outData = tmpData;
- });
-
- if (error == Error::NONE && acquireFence >= 0) {
- close(acquireFence);
- }
-
- return error;
-}
-
-Error Mapper::lock(buffer_handle_t handle,
- uint64_t producerUsage,
- uint64_t consumerUsage,
- const IMapper::Rect& accessRegion,
- int acquireFence, FlexLayout* outLayout) const
-{
- hardware::hidl_handle acquireFenceHandle;
-
- NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
- if (acquireFence >= 0) {
- auto h = native_handle_init(acquireFenceStorage, 1, 0);
- h->data[0] = acquireFence;
- acquireFenceHandle = h;
- }
-
- Error error = kDefaultError;
- mMapper->lockFlex(handle, producerUsage, consumerUsage,
- accessRegion, acquireFenceHandle,
- [&](const auto& tmpError, const auto& tmpLayout)
- {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
-
- *outLayout = tmpLayout;
- });
-
- if (error == Error::NONE && acquireFence >= 0) {
- close(acquireFence);
- }
-
- return error;
-}
-
-int Mapper::unlock(buffer_handle_t handle) const
-{
- int releaseFence = -1;
-
- Error error = kDefaultError;
- mMapper->unlock(handle,
- [&](const auto& tmpError, const auto& tmpReleaseFence)
- {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
-
- auto fenceHandle = tmpReleaseFence.getNativeHandle();
- if (fenceHandle && fenceHandle->numFds == 1) {
- int fd = dup(fenceHandle->data[0]);
- if (fd >= 0) {
- releaseFence = fd;
- } else {
- error = Error::NO_RESOURCES;
- }
- } else {
- releaseFence = -1;
- }
- });
-
- if (error != Error::NONE) {
- ALOGE("unlock(%p) failed with %d", handle, error);
- releaseFence = -1;
- }
-
- return releaseFence;
-}
-
-} // namespace Gralloc2
-
-} // namespace android
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index d21758d..eb5c7b6 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -22,7 +22,7 @@
#include <grallocusage/GrallocUsageConversion.h>
-#include <ui/GrallocMapper.h>
+#include <ui/Gralloc2.h>
#include <ui/GraphicBufferAllocator.h>
#include <ui/GraphicBufferMapper.h>
@@ -104,11 +104,7 @@
void GraphicBuffer::free_handle()
{
if (mOwner == ownHandle) {
- mBufferMapper.unregisterBuffer(handle);
- if (!mBufferMapper.getGrallocMapper().valid()) {
- native_handle_close(handle);
- native_handle_delete(const_cast<native_handle*>(handle));
- }
+ mBufferMapper.freeBuffer(handle);
} else if (mOwner == ownData) {
GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
allocator.free(handle);
@@ -217,7 +213,7 @@
mOwner = (method == WRAP_HANDLE) ? ownNone : ownHandle;
if (method == TAKE_UNREGISTERED_HANDLE) {
- status_t err = mBufferMapper.registerBuffer(this);
+ status_t err = mBufferMapper.importBuffer(this);
if (err != NO_ERROR) {
// clean up cloned handle
if (clone) {
@@ -451,7 +447,7 @@
mOwner = ownHandle;
if (handle != 0) {
- status_t err = mBufferMapper.registerBuffer(this);
+ status_t err = mBufferMapper.importBuffer(this);
if (err != NO_ERROR) {
width = height = stride = format = layerCount = usage = 0;
handle = NULL;
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index 3f18bbc..1f6c537 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -22,13 +22,14 @@
#include <stdio.h>
+#include <grallocusage/GrallocUsageConversion.h>
+
#include <log/log.h>
#include <utils/Singleton.h>
#include <utils/String8.h>
#include <utils/Trace.h>
-#include <ui/GrallocAllocator.h>
-#include <ui/GrallocMapper.h>
+#include <ui/Gralloc2.h>
#include <ui/GraphicBufferMapper.h>
namespace android {
@@ -41,8 +42,9 @@
GraphicBufferAllocator::alloc_rec_t> GraphicBufferAllocator::sAllocList;
GraphicBufferAllocator::GraphicBufferAllocator()
- : mAllocator(std::make_unique<Gralloc2::Allocator>()),
- mMapper(GraphicBufferMapper::getInstance())
+ : mMapper(GraphicBufferMapper::getInstance()),
+ mAllocator(std::make_unique<Gralloc2::Allocator>(
+ mMapper.getGrallocMapper()))
{
if (!mAllocator->valid()) {
mLoader = std::make_unique<Gralloc1::Loader>();
@@ -102,109 +104,6 @@
ALOGD("%s", s.string());
}
-namespace {
-
-class HalBuffer {
-public:
- HalBuffer(const Gralloc2::Allocator* allocator,
- uint32_t width, uint32_t height,
- PixelFormat format, uint32_t layerCount, uint64_t producerUsage,
- uint64_t consumerUsage)
- : mAllocator(allocator), mBufferValid(false)
- {
- Gralloc2::IAllocatorClient::BufferDescriptorInfo info = {};
- info.width = width;
- info.height = height;
- info.format = static_cast<Gralloc2::PixelFormat>(format);
- info.layerCount = layerCount;
- info.producerUsageMask = producerUsage;
- info.consumerUsageMask = consumerUsage;
-
- Gralloc2::BufferDescriptor descriptor;
- auto error = mAllocator->createBufferDescriptor(info, &descriptor);
- if (error != Gralloc2::Error::NONE) {
- ALOGE("Failed to create desc (%u x %u) layerCount %u format %d producerUsage %" PRIx64
- " consumerUsage %" PRIx64 ": %d",
- width, height, layerCount, format, producerUsage,
- consumerUsage, error);
- return;
- }
-
- error = mAllocator->allocate(descriptor, &mBuffer);
- if (error == Gralloc2::Error::NOT_SHARED) {
- error = Gralloc2::Error::NONE;
- }
-
- if (error != Gralloc2::Error::NONE) {
- ALOGE("Failed to allocate (%u x %u) layerCount %u format %d producerUsage %" PRIx64
- " consumerUsage %" PRIx64 ": %d",
- width, height, layerCount, format, producerUsage,
- consumerUsage, error);
- mAllocator->destroyBufferDescriptor(descriptor);
- return;
- }
-
- error = mAllocator->exportHandle(descriptor, mBuffer, &mHandle);
- if (error != Gralloc2::Error::NONE) {
- ALOGE("Failed to export handle");
- mAllocator->free(mBuffer);
- mAllocator->destroyBufferDescriptor(descriptor);
- return;
- }
-
- mAllocator->destroyBufferDescriptor(descriptor);
-
- mBufferValid = true;
- }
-
- ~HalBuffer()
- {
- if (mBufferValid) {
- if (mHandle) {
- native_handle_close(mHandle);
- native_handle_delete(mHandle);
- }
-
- mAllocator->free(mBuffer);
- }
- }
-
- bool exportHandle(GraphicBufferMapper& mapper,
- buffer_handle_t* handle, uint32_t* stride)
- {
- if (!mBufferValid) {
- return false;
- }
-
- if (mapper.registerBuffer(mHandle)) {
- return false;
- }
-
- *handle = mHandle;
-
- auto error = mapper.getGrallocMapper().getStride(mHandle, stride);
- if (error != Gralloc2::Error::NONE) {
- ALOGW("Failed to get stride from buffer: %d", error);
- *stride = 0;
- }
-
- mHandle = nullptr;
- mAllocator->free(mBuffer);
- mBufferValid = false;
-
- return true;
- }
-
-private:
- const Gralloc2::Allocator* mAllocator;
-
- bool mBufferValid;
- Gralloc2::Buffer mBuffer;
- native_handle_t* mHandle;
-};
-
-} // namespace
-
status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height,
PixelFormat format, uint32_t layerCount, uint64_t producerUsage,
uint64_t consumerUsage, buffer_handle_t* handle, uint32_t* stride,
@@ -223,12 +122,18 @@
gralloc1_error_t error;
if (mAllocator->valid()) {
- HalBuffer buffer(mAllocator.get(), width, height, format, layerCount,
- producerUsage, consumerUsage);
- if (!buffer.exportHandle(mMapper, handle, stride)) {
+ Gralloc2::IMapper::BufferDescriptorInfo info = {};
+ info.width = width;
+ info.height = height;
+ info.layerCount = layerCount;
+ info.format = static_cast<Gralloc2::PixelFormat>(format);
+ info.usage = static_cast<uint64_t>(android_convertGralloc1To0Usage(
+ producerUsage, consumerUsage));
+ error = static_cast<gralloc1_error_t>(mAllocator->allocate(info,
+ stride, handle));
+ if (error != GRALLOC1_ERROR_NONE) {
return NO_MEMORY;
}
- error = GRALLOC1_ERROR_NONE;
} else {
auto descriptor = mDevice->createDescriptor();
error = descriptor->setDimensions(width, height);
@@ -310,8 +215,7 @@
gralloc1_error_t error;
if (mAllocator->valid()) {
- error = static_cast<gralloc1_error_t>(
- mMapper.unregisterBuffer(handle));
+ error = static_cast<gralloc1_error_t>(mMapper.freeBuffer(handle));
} else {
error = mDevice->release(handle);
}
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index 656472f..87519bf 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -20,6 +20,8 @@
#include <ui/GraphicBufferMapper.h>
+#include <grallocusage/GrallocUsageConversion.h>
+
// We would eliminate the non-conforming zero-length array, but we can't since
// this is effectively included from the Linux kernel
#pragma clang diagnostic push
@@ -30,7 +32,7 @@
#include <utils/Log.h>
#include <utils/Trace.h>
-#include <ui/GrallocMapper.h>
+#include <ui/Gralloc2.h>
#include <ui/GraphicBuffer.h>
#include <system/graphics.h>
@@ -49,63 +51,84 @@
}
}
-
-
-status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
+status_t GraphicBufferMapper::importBuffer(buffer_handle_t rawHandle,
+ buffer_handle_t* outHandle)
{
ATRACE_CALL();
+ Gralloc2::Error error;
+ if (mMapper->valid()) {
+ error = mMapper->importBuffer(hardware::hidl_handle(rawHandle),
+ outHandle);
+ } else {
+ error = Gralloc2::Error::UNSUPPORTED;
+ }
+
+ ALOGW_IF(error != Gralloc2::Error::NONE, "importBuffer(%p) failed: %d",
+ rawHandle, error);
+
+ return static_cast<status_t>(error);
+}
+
+status_t GraphicBufferMapper::importBuffer(const GraphicBuffer* buffer)
+{
+ ATRACE_CALL();
+
+ ANativeWindowBuffer* nativeBuffer = buffer->getNativeBuffer();
+ buffer_handle_t rawHandle = nativeBuffer->handle;
+
gralloc1_error_t error;
if (mMapper->valid()) {
- error = static_cast<gralloc1_error_t>(mMapper->retain(handle));
+ buffer_handle_t importedHandle;
+ error = static_cast<gralloc1_error_t>(mMapper->importBuffer(
+ hardware::hidl_handle(rawHandle), &importedHandle));
+ if (error == GRALLOC1_ERROR_NONE) {
+ nativeBuffer->handle = importedHandle;
+ }
} else {
- // This always returns GRALLOC1_BAD_HANDLE when handle is from a
- // remote process and mDevice is backed by Gralloc1On0Adapter.
- error = mDevice->retain(handle);
- if (error == GRALLOC1_ERROR_BAD_HANDLE &&
- mDevice->hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {
- ALOGE("registerBuffer by handle is not supported with "
- "Gralloc1On0Adapter");
+ native_handle_t* clonedHandle = native_handle_clone(rawHandle);
+ if (clonedHandle) {
+ nativeBuffer->handle = clonedHandle;
+ error = mDevice->retain(buffer);
+ if (error != GRALLOC1_ERROR_NONE) {
+ nativeBuffer->handle = rawHandle;
+ native_handle_close(clonedHandle);
+ native_handle_delete(clonedHandle);
+ }
+ } else {
+ error = GRALLOC1_ERROR_NO_RESOURCES;
}
}
- ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",
- handle, error);
-
- return error;
-}
-
-status_t GraphicBufferMapper::registerBuffer(const GraphicBuffer* buffer)
-{
- ATRACE_CALL();
-
- gralloc1_error_t error;
- if (mMapper->valid()) {
- error = static_cast<gralloc1_error_t>(
- mMapper->retain(buffer->getNativeBuffer()->handle));
- } else {
- error = mDevice->retain(buffer);
+ // the raw handle is owned by GraphicBuffer and is now replaced
+ if (error == GRALLOC1_ERROR_NONE) {
+ native_handle_close(rawHandle);
+ native_handle_delete(const_cast<native_handle_t*>(rawHandle));
}
- ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",
- buffer->getNativeBuffer()->handle, error);
+ ALOGW_IF(error != GRALLOC1_ERROR_NONE, "importBuffer(%p) failed: %d",
+ rawHandle, error);
return error;
}
-status_t GraphicBufferMapper::unregisterBuffer(buffer_handle_t handle)
+status_t GraphicBufferMapper::freeBuffer(buffer_handle_t handle)
{
ATRACE_CALL();
gralloc1_error_t error;
if (mMapper->valid()) {
- mMapper->release(handle);
+ mMapper->freeBuffer(handle);
error = GRALLOC1_ERROR_NONE;
} else {
error = mDevice->release(handle);
+ if (!mDevice->hasCapability(GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE)) {
+ native_handle_close(handle);
+ native_handle_delete(const_cast<native_handle_t*>(handle));
+ }
}
- ALOGW_IF(error != GRALLOC1_ERROR_NONE, "unregisterBuffer(%p): failed %d",
+ ALOGW_IF(error != GRALLOC1_ERROR_NONE, "freeBuffer(%p): failed %d",
handle, error);
return error;
@@ -120,138 +143,13 @@
return outRect;
}
-
-status_t GraphicBufferMapper::getDimensions(buffer_handle_t handle,
- uint32_t* outWidth, uint32_t* outHeight) const
-{
- ATRACE_CALL();
-
- gralloc1_error_t error;
- if (mMapper->valid()) {
- mMapper->getDimensions(handle, outWidth, outHeight);
- error = GRALLOC1_ERROR_NONE;
- } else {
- error = mDevice->getDimensions(handle, outWidth, outHeight);
- }
-
- ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getDimensions(%p, ...): failed %d",
- handle, error);
-
- return error;
-}
-
-status_t GraphicBufferMapper::getFormat(buffer_handle_t handle,
- int32_t* outFormat) const
-{
- ATRACE_CALL();
-
- gralloc1_error_t error;
- if (mMapper->valid()) {
- mMapper->getFormat(handle, outFormat);
- error = GRALLOC1_ERROR_NONE;
- } else {
- error = mDevice->getFormat(handle, outFormat);
- }
-
- ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getFormat(%p, ...): failed %d",
- handle, error);
-
- return error;
-}
-
-status_t GraphicBufferMapper::getLayerCount(buffer_handle_t handle,
- uint32_t* outLayerCount) const
-{
- ATRACE_CALL();
-
- gralloc1_error_t error;
- if (mMapper->valid()) {
- mMapper->getLayerCount(handle, outLayerCount);
- error = GRALLOC1_ERROR_NONE;
- } else {
- error = mDevice->getLayerCount(handle, outLayerCount);
- }
-
- ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getLayerCount(%p, ...): failed %d",
- handle, error);
-
- return error;
-}
-
-status_t GraphicBufferMapper::getProducerUsage(buffer_handle_t handle,
- uint64_t* outProducerUsage) const
-{
- ATRACE_CALL();
-
- gralloc1_error_t error;
- if (mMapper->valid()) {
- mMapper->getProducerUsage(handle, outProducerUsage);
- error = GRALLOC1_ERROR_NONE;
- } else {
- error = mDevice->getProducerUsage(handle, outProducerUsage);
- }
-
- ALOGW_IF(error != GRALLOC1_ERROR_NONE,
- "getProducerUsage(%p, ...): failed %d", handle, error);
-
- return error;
-}
-
-status_t GraphicBufferMapper::getConsumerUsage(buffer_handle_t handle,
- uint64_t* outConsumerUsage) const
-{
- ATRACE_CALL();
-
- gralloc1_error_t error;
- if (mMapper->valid()) {
- mMapper->getConsumerUsage(handle, outConsumerUsage);
- error = GRALLOC1_ERROR_NONE;
- } else {
- error = mDevice->getConsumerUsage(handle, outConsumerUsage);
- }
-
- ALOGW_IF(error != GRALLOC1_ERROR_NONE,
- "getConsumerUsage(%p, ...): failed %d", handle, error);
-
- return error;
-}
-
-status_t GraphicBufferMapper::getBackingStore(buffer_handle_t handle,
- uint64_t* outBackingStore) const
-{
- ATRACE_CALL();
-
- gralloc1_error_t error;
- if (mMapper->valid()) {
- mMapper->getBackingStore(handle, outBackingStore);
- error = GRALLOC1_ERROR_NONE;
- } else {
- error = mDevice->getBackingStore(handle, outBackingStore);
- }
-
- ALOGW_IF(error != GRALLOC1_ERROR_NONE,
- "getBackingStore(%p, ...): failed %d", handle, error);
-
- return error;
-}
-
-status_t GraphicBufferMapper::getStride(buffer_handle_t handle,
- uint32_t* outStride) const
-{
- ATRACE_CALL();
-
- gralloc1_error_t error;
- if (mMapper->valid()) {
- mMapper->getStride(handle, outStride);
- error = GRALLOC1_ERROR_NONE;
- } else {
- error = mDevice->getStride(handle, outStride);
- }
-
- ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getStride(%p, ...): failed %d",
- handle, error);
-
- return error;
+static inline Gralloc2::IMapper::Rect asGralloc2Rect(const Rect& rect) {
+ Gralloc2::IMapper::Rect outRect{};
+ outRect.left = rect.left;
+ outRect.top = rect.top;
+ outRect.width = rect.width();
+ outRect.height = rect.height();
+ return outRect;
}
status_t GraphicBufferMapper::lock(buffer_handle_t handle, uint32_t usage,
@@ -289,15 +187,15 @@
{
ATRACE_CALL();
- gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);
gralloc1_error_t error;
if (mMapper->valid()) {
- const Gralloc2::IMapper::Rect& accessRect =
- *reinterpret_cast<Gralloc2::IMapper::Rect*>(&accessRegion);
- error = static_cast<gralloc1_error_t>(mMapper->lock(
- handle, producerUsage, consumerUsage, accessRect,
- fenceFd, vaddr));
+ const uint64_t usage =
+ static_cast<uint64_t>(android_convertGralloc1To0Usage(
+ producerUsage, consumerUsage));
+ error = static_cast<gralloc1_error_t>(mMapper->lock(handle,
+ usage, asGralloc2Rect(bounds), fenceFd, vaddr));
} else {
+ gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);
sp<Fence> fence = new Fence(fenceFd);
error = mDevice->lock(handle,
static_cast<gralloc1_producer_usage_t>(producerUsage),
@@ -346,22 +244,19 @@
gralloc1_error_t error;
if (mMapper->valid()) {
- const Gralloc2::IMapper::Rect& accessRect =
- *reinterpret_cast<Gralloc2::IMapper::Rect*>(&accessRegion);
- Gralloc2::FlexLayout layout{};
- error = static_cast<gralloc1_error_t>(mMapper->lock(
- handle, usage, usage, accessRect, fenceFd, &layout));
-
+ Gralloc2::YCbCrLayout layout;
+ error = static_cast<gralloc1_error_t>(mMapper->lock(handle, usage,
+ asGralloc2Rect(bounds), fenceFd, &layout));
if (error == GRALLOC1_ERROR_NONE) {
- planes.resize(layout.planes.size());
- memcpy(planes.data(), layout.planes.data(),
- sizeof(planes[0]) * planes.size());
-
- flexLayout.format = static_cast<android_flex_format_t>(
- layout.format);
- flexLayout.num_planes = static_cast<uint32_t>(planes.size());
- flexLayout.planes = planes.data();
+ ycbcr->y = layout.y;
+ ycbcr->cb = layout.cb;
+ ycbcr->cr = layout.cr;
+ ycbcr->ystride = static_cast<size_t>(layout.yStride);
+ ycbcr->cstride = static_cast<size_t>(layout.cStride);
+ ycbcr->chroma_step = static_cast<size_t>(layout.chromaStep);
}
+
+ return error;
} else {
sp<Fence> fence = new Fence(fenceFd);
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index b55c212..6733505 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -25,9 +25,3 @@
shared_libs: ["libui"],
srcs: ["colorspace_test.cpp"],
}
-
-cc_test {
- name: "Gralloc1Mapper_test",
- shared_libs: ["libui", "libutils"],
- srcs: ["Gralloc1Mapper_test.cpp"],
-}
diff --git a/libs/ui/tests/Gralloc1Mapper_test.cpp b/libs/ui/tests/Gralloc1Mapper_test.cpp
deleted file mode 100644
index b7c9f0f..0000000
--- a/libs/ui/tests/Gralloc1Mapper_test.cpp
+++ /dev/null
@@ -1,105 +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.
- */
-
-#define LOG_TAG "Gralloc1Mapper_test"
-//#define LOG_NDEBUG 0
-
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#include <ui/GraphicBuffer.h>
-#include <ui/GraphicBufferMapper.h>
-#include <utils/Errors.h>
-
-#include <gtest/gtest.h>
-
-using namespace android;
-
-class Gralloc1MapperTest : public ::testing::Test
-{
-public:
- ~Gralloc1MapperTest() override = default;
-
-protected:
- void SetUp() override {
- buffer = new GraphicBuffer(4, 8, HAL_PIXEL_FORMAT_RGBA_8888, 1,
- GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN,
- GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN, "Gralloc1MapperTest");
- ASSERT_NE(nullptr, buffer.get());
-
- handle = static_cast<buffer_handle_t>(buffer->handle);
-
- mapper = &GraphicBufferMapper::get();
- }
-
- sp<GraphicBuffer> buffer;
- buffer_handle_t handle;
- GraphicBufferMapper* mapper;
-};
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getDimensions) {
- uint32_t width = 0;
- uint32_t height = 0;
- status_t err = mapper->getDimensions(handle, &width, &height);
- ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
- EXPECT_EQ(4U, width);
- EXPECT_EQ(8U, height);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getFormat) {
- int32_t value = 0;
- status_t err = mapper->getFormat(handle, &value);
- ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
- EXPECT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, value);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getLayerCount) {
- uint32_t value = 0;
- status_t err = mapper->getLayerCount(handle, &value);
- if (err != GRALLOC1_ERROR_UNSUPPORTED) {
- EXPECT_EQ(1U, value);
- }
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getProducerUsage) {
- uint64_t value = 0;
- status_t err = mapper->getProducerUsage(handle, &value);
- ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
- EXPECT_EQ(GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN, value);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getConsumerUsage) {
- uint64_t value = 0;
- status_t err = mapper->getConsumerUsage(handle, &value);
- ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
- EXPECT_EQ(GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN, value);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getBackingStore) {
- uint64_t value = 0;
- status_t err = mapper->getBackingStore(handle, &value);
- ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getStride) {
- uint32_t value = 0;
- status_t err = mapper->getStride(handle, &value);
- ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
- // The stride should be at least the width of the buffer.
- EXPECT_LE(4U, value);
-}
diff --git a/libs/vr/libbufferhub/buffer_hub_client.cpp b/libs/vr/libbufferhub/buffer_hub_client.cpp
index 2749fd1..a1f952e 100644
--- a/libs/vr/libbufferhub/buffer_hub_client.cpp
+++ b/libs/vr/libbufferhub/buffer_hub_client.cpp
@@ -20,6 +20,7 @@
namespace {
+// TODO(hendrikw): These flags can not be hard coded.
constexpr int kUncachedBlobUsageFlags = GRALLOC_USAGE_SW_READ_RARELY |
GRALLOC_USAGE_SW_WRITE_RARELY |
GRALLOC_USAGE_PRIVATE_UNCACHED;
@@ -110,6 +111,7 @@
int BufferHubBuffer::GetBlobReadWritePointer(size_t size, void** addr) {
int width = static_cast<int>(size);
int height = 1;
+ // TODO(hendrikw): These flags can not be hard coded.
constexpr int usage = GRALLOC_USAGE_SW_READ_RARELY |
GRALLOC_USAGE_SW_WRITE_RARELY |
GRALLOC_USAGE_PRIVATE_UNCACHED;
@@ -196,18 +198,27 @@
InvokeRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(ignore));
}
-BufferProducer::BufferProducer(int width, int height, int format, int usage,
+BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
+ uint32_t usage, size_t metadata_size,
+ size_t slice_count)
+ : BufferProducer(width, height, format, usage, usage, metadata_size,
+ slice_count) {}
+
+BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage,
size_t metadata_size, size_t slice_count)
: BASE(BufferHubRPC::kClientPath) {
ATRACE_NAME("BufferProducer::BufferProducer");
ALOGD_IF(TRACE,
- "BufferProducer::BufferProducer: fd=%d width=%d height=%d format=%d "
- "usage=%d, metadata_size=%zu, slice_count=%zu",
- event_fd(), width, height, format, usage, metadata_size,
- slice_count);
+ "BufferProducer::BufferProducer: fd=%d width=%u height=%u format=%u "
+ "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64
+ " metadata_size=%zu slice_count=%zu",
+ event_fd(), width, height, format, producer_usage, consumer_usage,
+ metadata_size, slice_count);
auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
- width, height, format, usage, metadata_size, slice_count);
+ width, height, format, producer_usage, consumer_usage, metadata_size,
+ slice_count);
if (!status) {
ALOGE(
"BufferProducer::BufferProducer: Failed to create producer buffer: %s",
@@ -226,21 +237,29 @@
}
BufferProducer::BufferProducer(const std::string& name, int user_id,
- int group_id, int width, int height, int format,
- int usage, size_t meta_size_bytes,
+ int group_id, uint32_t width, uint32_t height,
+ uint32_t format, uint32_t usage,
+ size_t meta_size_bytes, size_t slice_count)
+ : BufferProducer(name, user_id, group_id, width, height, format, usage,
+ usage, meta_size_bytes, slice_count) {}
+
+BufferProducer::BufferProducer(const std::string& name, int user_id,
+ int group_id, uint32_t width, uint32_t height,
+ uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage, size_t meta_size_bytes,
size_t slice_count)
: BASE(BufferHubRPC::kClientPath) {
ATRACE_NAME("BufferProducer::BufferProducer");
ALOGD_IF(TRACE,
"BufferProducer::BufferProducer: fd=%d name=%s user_id=%d "
- "group_id=%d width=%d height=%d format=%d usage=%d, "
- "meta_size_bytes=%zu, slice_count=%zu",
+ "group_id=%d width=%u height=%u format=%u producer_usage=%" PRIx64
+ " consumer_usage=%" PRIx64 " meta_size_bytes=%zu slice_count=%zu",
event_fd(), name.c_str(), user_id, group_id, width, height, format,
- usage, meta_size_bytes, slice_count);
+ producer_usage, consumer_usage, meta_size_bytes, slice_count);
auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
- name, user_id, group_id, width, height, format, usage, meta_size_bytes,
- slice_count);
+ name, user_id, group_id, width, height, format, producer_usage,
+ consumer_usage, meta_size_bytes, slice_count);
if (!status) {
ALOGE(
"BufferProducer::BufferProducer: Failed to create/get persistent "
@@ -260,18 +279,25 @@
}
}
-BufferProducer::BufferProducer(int usage, size_t size)
+BufferProducer::BufferProducer(uint32_t usage, size_t size)
+ : BufferProducer(usage, usage, size) {}
+
+BufferProducer::BufferProducer(uint64_t producer_usage, uint64_t consumer_usage,
+ size_t size)
: BASE(BufferHubRPC::kClientPath) {
ATRACE_NAME("BufferProducer::BufferProducer");
- ALOGD_IF(TRACE, "BufferProducer::BufferProducer: usage=%d size=%zu", usage,
- size);
+ ALOGD_IF(TRACE,
+ "BufferProducer::BufferProducer: producer_usage=%" PRIx64
+ " consumer_usage=%" PRIx64 " size=%zu",
+ producer_usage, consumer_usage, size);
const int width = static_cast<int>(size);
const int height = 1;
const int format = HAL_PIXEL_FORMAT_BLOB;
const size_t meta_size_bytes = 0;
const size_t slice_count = 1;
auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
- width, height, format, usage, meta_size_bytes, slice_count);
+ width, height, format, producer_usage, consumer_usage, meta_size_bytes,
+ slice_count);
if (!status) {
ALOGE("BufferProducer::BufferProducer: Failed to create blob: %s",
status.GetErrorMessage().c_str());
@@ -289,21 +315,27 @@
}
BufferProducer::BufferProducer(const std::string& name, int user_id,
- int group_id, int usage, size_t size)
+ int group_id, uint32_t usage, size_t size)
+ : BufferProducer(name, user_id, group_id, usage, usage, size) {}
+
+BufferProducer::BufferProducer(const std::string& name, int user_id,
+ int group_id, uint64_t producer_usage,
+ uint64_t consumer_usage, size_t size)
: BASE(BufferHubRPC::kClientPath) {
ATRACE_NAME("BufferProducer::BufferProducer");
ALOGD_IF(TRACE,
"BufferProducer::BufferProducer: name=%s user_id=%d group=%d "
- "usage=%d size=%zu",
- name.c_str(), user_id, group_id, usage, size);
+ "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64 " size=%zu",
+ name.c_str(), user_id, group_id, producer_usage, consumer_usage,
+ size);
const int width = static_cast<int>(size);
const int height = 1;
const int format = HAL_PIXEL_FORMAT_BLOB;
const size_t meta_size_bytes = 0;
const size_t slice_count = 1;
auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
- name, user_id, group_id, width, height, format, usage, meta_size_bytes,
- slice_count);
+ name, user_id, group_id, width, height, format, producer_usage,
+ consumer_usage, meta_size_bytes, slice_count);
if (!status) {
ALOGE(
"BufferProducer::BufferProducer: Failed to create persistent "
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 aacc385..c772ed3 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
@@ -94,9 +94,12 @@
}
IonBuffer* buffer() { return &slices_[0]; }
+ const IonBuffer* buffer() const { return &slices_[0]; }
+
// If index is greater than or equal to slice_count(), the result is
// undefined.
IonBuffer* slice(size_t index) { return &slices_[index]; }
+ const IonBuffer* slice(size_t index) const { return &slices_[index]; }
int slice_count() const { return static_cast<int>(slices_.size()); }
int id() const { return id_; }
@@ -104,11 +107,14 @@
// The following methods return settings of the first buffer. Currently,
// it is only possible to create multi-buffer BufferHubBuffers with the same
// settings.
- int width() const { return slices_[0].width(); }
- int height() const { return slices_[0].height(); }
- int stride() const { return slices_[0].stride(); }
- int format() const { return slices_[0].format(); }
- int usage() const { return slices_[0].usage(); }
+ uint32_t width() const { return slices_[0].width(); }
+ uint32_t height() const { return slices_[0].height(); }
+ uint32_t stride() const { return slices_[0].stride(); }
+ uint32_t format() const { return slices_[0].format(); }
+ uint32_t usage() const { return slices_[0].usage(); }
+ uint32_t layer_count() const { return slices_[0].layer_count(); }
+ uint64_t producer_usage() const { return slices_[0].producer_usage(); }
+ uint64_t consumer_usage() const { return slices_[0].consumer_usage(); }
protected:
explicit BufferHubBuffer(LocalChannelHandle channel);
@@ -171,9 +177,8 @@
int Post(const LocalHandle& ready_fence) {
return Post(ready_fence, nullptr, 0);
}
- template <
- typename Meta,
- typename = typename std::enable_if<!std::is_void<Meta>::value>::type>
+ template <typename Meta, typename = typename std::enable_if<
+ !std::is_void<Meta>::value>::type>
int Post(const LocalHandle& ready_fence, const Meta& meta) {
return Post(ready_fence, &meta, sizeof(meta));
}
@@ -216,8 +221,12 @@
// arguments as the constructors.
// Constructs a buffer with the given geometry and parameters.
- BufferProducer(int width, int height, int format, int usage,
- size_t metadata_size = 0, size_t slice_count = 1);
+ BufferProducer(uint32_t width, uint32_t height, uint32_t format,
+ uint32_t usage, size_t metadata_size = 0,
+ size_t slice_count = 1);
+ BufferProducer(uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage,
+ size_t metadata_size, size_t slice_count);
// Constructs a persistent buffer with the given geometry and parameters and
// binds it to |name| in one shot. If a persistent buffer with the same name
@@ -231,16 +240,24 @@
// created and cannot be changed. A user or group id of -1 disables checks for
// that respective id. A user or group id of 0 is substituted with the
// effective user or group id of the calling process.
- BufferProducer(const std::string& name, int user_id, int group_id, int width,
- int height, int format, int usage, size_t metadata_size = 0,
+ BufferProducer(const std::string& name, int user_id, int group_id,
+ uint32_t width, uint32_t height, uint32_t format,
+ uint32_t usage, size_t metadata_size = 0,
size_t slice_count = 1);
+ BufferProducer(const std::string& name, int user_id, int group_id,
+ uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage,
+ size_t metadata_size, size_t slice_count);
// Constructs a blob (flat) buffer with the given usage flags.
- BufferProducer(int usage, size_t size);
+ BufferProducer(uint32_t usage, size_t size);
+ BufferProducer(uint64_t producer_usage, uint64_t consumer_usage, size_t size);
// Constructs a persistent blob (flat) buffer and binds it to |name|.
- BufferProducer(const std::string& name, int user_id, int group_id, int usage,
- size_t size);
+ BufferProducer(const std::string& name, int user_id, int group_id,
+ uint32_t usage, size_t size);
+ BufferProducer(const std::string& name, int user_id, int group_id,
+ uint64_t producer_usage, uint64_t consumer_usage, size_t size);
// Constructs a channel to persistent buffer by name only. The buffer must
// have been previously created or made persistent.
diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
index ed11551..b6302f1 100644
--- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
+++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
@@ -24,7 +24,8 @@
width_(buffer.width()),
height_(buffer.height()),
format_(buffer.format()),
- usage_(buffer.usage()) {
+ producer_usage_(buffer.producer_usage()),
+ consumer_usage_(buffer.consumer_usage()) {
// Populate the fd and int vectors: native_handle->data[] is an array of fds
// followed by an array of opaque ints.
const int fd_count = buffer.handle()->numFds;
@@ -37,6 +38,7 @@
}
}
NativeBufferHandle(NativeBufferHandle&& other) = default;
+ NativeBufferHandle& operator=(NativeBufferHandle&& other) = default;
// Imports the native handle into the given IonBuffer instance.
int Import(IonBuffer* buffer) {
@@ -46,9 +48,10 @@
for (const auto& fd : fds_)
fd_ints.push_back(fd.Get());
- const int ret = buffer->Import(fd_ints.data(), fd_ints.size(),
- opaque_ints_.data(), opaque_ints_.size(),
- width_, height_, stride_, format_, usage_);
+ const int ret =
+ buffer->Import(fd_ints.data(), fd_ints.size(), opaque_ints_.data(),
+ opaque_ints_.size(), width_, height_, stride_, format_,
+ producer_usage_, consumer_usage_);
if (ret < 0)
return ret;
@@ -68,24 +71,32 @@
private:
int id_;
- int stride_;
- int width_;
- int height_;
- int format_;
- int usage_;
+ uint32_t stride_;
+ uint32_t width_;
+ uint32_t height_;
+ uint32_t format_;
+ uint64_t producer_usage_;
+ uint64_t consumer_usage_;
std::vector<int> opaque_ints_;
std::vector<FileHandleType> fds_;
- void Clear() { id_ = stride_ = width_ = height_ = format_ = usage_ = -1; }
+ void Clear() {
+ id_ = -1;
+ stride_ = width_ = height_ = format_ = producer_usage_ = consumer_usage_ =
+ 0;
+ }
PDX_SERIALIZABLE_MEMBERS(NativeBufferHandle<FileHandleType>, id_, stride_,
- width_, height_, format_, usage_, opaque_ints_,
- fds_);
+ width_, height_, format_, producer_usage_,
+ consumer_usage_, opaque_ints_, fds_);
NativeBufferHandle(const NativeBufferHandle&) = delete;
void operator=(const NativeBufferHandle&) = delete;
};
+using BorrowedNativeBufferHandle = NativeBufferHandle<pdx::BorrowedHandle>;
+using LocalNativeBufferHandle = NativeBufferHandle<pdx::LocalHandle>;
+
template <typename FileHandleType>
class FenceHandle {
public:
@@ -119,6 +130,31 @@
using LocalFence = FenceHandle<pdx::LocalHandle>;
using BorrowedFence = FenceHandle<pdx::BorrowedHandle>;
+struct QueueInfo {
+ size_t meta_size_bytes;
+ int id;
+
+ private:
+ PDX_SERIALIZABLE_MEMBERS(QueueInfo, meta_size_bytes, id);
+};
+
+struct UsagePolicy {
+ uint64_t producer_set_mask;
+ uint64_t producer_clear_mask;
+ uint64_t producer_deny_set_mask;
+ uint64_t producer_deny_clear_mask;
+ uint64_t consumer_set_mask;
+ uint64_t consumer_clear_mask;
+ uint64_t consumer_deny_set_mask;
+ uint64_t consumer_deny_clear_mask;
+
+ private:
+ PDX_SERIALIZABLE_MEMBERS(UsagePolicy, producer_set_mask, producer_clear_mask,
+ producer_deny_set_mask, producer_deny_clear_mask,
+ consumer_set_mask, consumer_clear_mask,
+ consumer_deny_set_mask, consumer_deny_clear_mask);
+};
+
// BufferHub Service RPC interface. Defines the endpoints, op codes, and method
// type signatures supported by bufferhubd.
struct BufferHubRPC {
@@ -151,6 +187,7 @@
kOpConsumerSetIgnore,
kOpCreateProducerQueue,
kOpCreateConsumerQueue,
+ kOpGetQueueInfo,
kOpProducerQueueAllocateBuffers,
kOpProducerQueueDetachBuffer,
kOpConsumerQueueImportBuffers,
@@ -164,46 +201,49 @@
// Methods.
PDX_REMOTE_METHOD(CreateBuffer, kOpCreateBuffer,
- int(int width, int height, int format, int usage,
- size_t meta_size_bytes, size_t slice_count));
+ void(uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage,
+ size_t meta_size_bytes, size_t slice_count));
PDX_REMOTE_METHOD(CreatePersistentBuffer, kOpCreatePersistentBuffer,
- int(const std::string& name, int user_id, int group_id,
- int width, int height, int format, int usage,
- size_t meta_size_bytes, size_t slice_count));
+ void(const std::string& name, int user_id, int group_id,
+ uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage,
+ size_t meta_size_bytes, size_t slice_count));
PDX_REMOTE_METHOD(GetPersistentBuffer, kOpGetPersistentBuffer,
- int(const std::string& name));
+ void(const std::string& name));
PDX_REMOTE_METHOD(GetBuffer, kOpGetBuffer,
NativeBufferHandle<LocalHandle>(unsigned index));
PDX_REMOTE_METHOD(GetBuffers, kOpGetBuffers,
std::vector<NativeBufferHandle<LocalHandle>>(Void));
PDX_REMOTE_METHOD(NewConsumer, kOpNewConsumer, LocalChannelHandle(Void));
PDX_REMOTE_METHOD(ProducerMakePersistent, kOpProducerMakePersistent,
- int(const std::string& name, int user_id, int group_id));
+ void(const std::string& name, int user_id, int group_id));
PDX_REMOTE_METHOD(ProducerRemovePersistence, kOpProducerRemovePersistence,
- int(Void));
+ void(Void));
PDX_REMOTE_METHOD(ProducerPost, kOpProducerPost,
- int(LocalFence acquire_fence, MetaData));
+ void(LocalFence acquire_fence, MetaData));
PDX_REMOTE_METHOD(ProducerGain, kOpProducerGain, LocalFence(Void));
PDX_REMOTE_METHOD(ConsumerAcquire, kOpConsumerAcquire,
std::pair<LocalFence, MetaData>(std::size_t metadata_size));
PDX_REMOTE_METHOD(ConsumerRelease, kOpConsumerRelease,
- int(LocalFence release_fence));
- PDX_REMOTE_METHOD(ConsumerSetIgnore, kOpConsumerSetIgnore, int(bool ignore));
+ void(LocalFence release_fence));
+ PDX_REMOTE_METHOD(ConsumerSetIgnore, kOpConsumerSetIgnore, void(bool ignore));
// Buffer Queue Methods.
PDX_REMOTE_METHOD(CreateProducerQueue, kOpCreateProducerQueue,
- int(size_t meta_size_bytes, int usage_set_mask,
- int usage_clear_mask, int usage_deny_set_mask,
- int usage_deny_clear_mask));
+ QueueInfo(size_t meta_size_bytes,
+ const UsagePolicy& usage_policy));
PDX_REMOTE_METHOD(CreateConsumerQueue, kOpCreateConsumerQueue,
- std::pair<LocalChannelHandle, size_t>(Void));
+ LocalChannelHandle(Void));
+ PDX_REMOTE_METHOD(GetQueueInfo, kOpGetQueueInfo, QueueInfo(Void));
PDX_REMOTE_METHOD(ProducerQueueAllocateBuffers,
kOpProducerQueueAllocateBuffers,
std::vector<std::pair<LocalChannelHandle, size_t>>(
- int width, int height, int format, int usage,
+ uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage,
size_t slice_count, size_t buffer_count));
PDX_REMOTE_METHOD(ProducerQueueDetachBuffer, kOpProducerQueueDetachBuffer,
- int(size_t slot));
+ void(size_t slot));
PDX_REMOTE_METHOD(ConsumerQueueImportBuffers, kOpConsumerQueueImportBuffers,
std::vector<std::pair<LocalChannelHandle, size_t>>(Void));
};
diff --git a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
index e449cbd..e167a17 100644
--- a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
@@ -12,11 +12,20 @@
class IonBuffer {
public:
IonBuffer();
- IonBuffer(int width, int height, int format, int usage);
- IonBuffer(buffer_handle_t handle, int width, int height, int stride,
- int format, int usage);
- IonBuffer(buffer_handle_t handle, int width, int height, int layer_count,
- int stride, int layer_stride, int format, int usage);
+ IonBuffer(uint32_t width, uint32_t height, uint32_t format, uint32_t usage);
+ IonBuffer(uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage);
+ IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint32_t usage);
+ IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage);
+ IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t layer_count, uint32_t stride, uint32_t layer_stride,
+ uint32_t format, uint32_t usage);
+ IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t layer_count, uint32_t stride, uint32_t layer_stride,
+ uint32_t format, uint64_t producer_usage, uint64_t consumer_usage);
~IonBuffer();
IonBuffer(IonBuffer&& other);
@@ -30,25 +39,36 @@
// previous native handle if necessary. Returns 0 on success or a negative
// errno code otherwise. If allocation fails the previous native handle is
// left intact.
- int Alloc(int width, int height, int format, int usage);
+ int Alloc(uint32_t width, uint32_t height, uint32_t format, uint32_t usage);
+ int Alloc(uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage);
// Resets the underlying native handle and parameters, freeing the previous
// native handle if necessary.
- void Reset(buffer_handle_t handle, int width, int height, int stride,
- int format, int usage);
+ void Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint32_t usage);
+ void Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage);
// Like Reset but also registers the native handle, which is necessary for
// native handles received over IPC. Returns 0 on success or a negative errno
// code otherwise. If import fails the previous native handle is left intact.
- int Import(buffer_handle_t handle, int width, int height, int stride,
- int format, int usage);
+ int Import(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint32_t usage);
+ int Import(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage);
// Like Reset but imports a native handle from raw fd and int arrays. Returns
// 0 on success or a negative errno code otherwise. If import fails the
// previous native handle is left intact.
int Import(const int* fd_array, int fd_count, const int* int_array,
- int int_count, int width, int height, int stride, int format,
- int usage);
+ int int_count, uint32_t width, uint32_t height, uint32_t stride,
+ uint32_t format, uint32_t usage);
+ int Import(const int* fd_array, int fd_count, const int* int_array,
+ int int_count, uint32_t width, uint32_t height, uint32_t stride,
+ uint32_t format, uint64_t producer_usage, uint64_t consumer_usage);
// Duplicates the native handle underlying |other| and then imports it. This
// is useful for creating multiple, independent views of the same Ion/Gralloc
@@ -56,29 +76,38 @@
// duplication or import fail the previous native handle is left intact.
int Duplicate(const IonBuffer* other);
- int Lock(int usage, int x, int y, int width, int height, void** address);
- int LockYUV(int usage, int x, int y, int width, int height,
+ int Lock(uint32_t usage, int x, int y, int width, int height, void** address);
+ int LockYUV(uint32_t usage, int x, int y, int width, int height,
struct android_ycbcr* yuv);
int Unlock();
- 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; }
+
+ const sp<GraphicBuffer>& buffer() const { return buffer_; }
+ buffer_handle_t handle() const {
+ return buffer_.get() ? buffer_->handle : nullptr;
+ }
+ uint32_t width() const { return buffer_.get() ? buffer_->getWidth() : 0; }
+ uint32_t height() const { return buffer_.get() ? buffer_->getHeight() : 0; }
+ uint32_t layer_count() const {
+ return buffer_.get() ? buffer_->getLayerCount() : 0;
+ }
+ uint32_t stride() const { return buffer_.get() ? buffer_->getStride() : 0; }
+ uint32_t layer_stride() const { return 0; }
+ uint32_t format() const {
+ return buffer_.get() ? buffer_->getPixelFormat() : 0;
+ }
+ uint64_t producer_usage() const { return producer_usage_; }
+ uint64_t consumer_usage() const { return consumer_usage_; }
+ uint32_t usage() const { return buffer_.get() ? buffer_->getUsage() : 0; }
private:
sp<GraphicBuffer> buffer_;
+ // GraphicBuffer doesn't expose these separately. Keep these values cached for
+ // BufferHub to check policy against. Clients that import these buffers won't
+ // get the full picture, which is okay.
+ uint64_t producer_usage_;
+ uint64_t consumer_usage_;
+
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 e5a56c1..df9ae81 100644
--- a/libs/vr/libbufferhub/ion_buffer.cpp
+++ b/libs/vr/libbufferhub/ion_buffer.cpp
@@ -6,40 +6,59 @@
#include <mutex>
+namespace {
+
+constexpr uint32_t kDefaultGraphicBufferLayerCount = 1;
+
+} // anonymous namespace
+
namespace android {
namespace dvr {
IonBuffer::IonBuffer() : IonBuffer(nullptr, 0, 0, 0, 0, 0, 0, 0) {}
-IonBuffer::IonBuffer(int width, int height, int format, int usage)
+IonBuffer::IonBuffer(uint32_t width, uint32_t height, uint32_t format,
+ uint32_t usage)
+ : IonBuffer(width, height, format, usage, usage) {}
+
+IonBuffer::IonBuffer(uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage)
: IonBuffer() {
- Alloc(width, height, format, usage);
+ Alloc(width, height, format, producer_usage, consumer_usage);
}
-IonBuffer::IonBuffer(buffer_handle_t handle, int width, int height, int stride,
- int format, int usage)
+IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint32_t usage)
: IonBuffer(handle, width, height, 1, stride, 0, format, usage) {}
+IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t layer_count, uint32_t stride,
+ uint32_t layer_stride, uint32_t format, uint32_t usage)
+ : IonBuffer(handle, width, height, layer_count, stride, layer_stride,
+ format, usage, usage) {}
-IonBuffer::IonBuffer(buffer_handle_t handle, int width, int height,
- int layer_count, int stride, int layer_stride, int format,
- int usage)
+IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t layer_count, uint32_t stride,
+ uint32_t layer_stride, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage)
: 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);
+ "IonBuffer::IonBuffer: handle=%p width=%u height=%u layer_count=%u "
+ "stride=%u layer stride=%u format=%u producer_usage=%" PRIx64
+ " consumer_usage=%" PRIx64,
+ handle, width, height, layer_count, stride, layer_stride, format,
+ producer_usage, consumer_usage);
if (handle != 0) {
- Import(handle, width, height, stride, format, usage);
+ Import(handle, width, height, stride, format, producer_usage,
+ consumer_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());
+ "IonBuffer::~IonBuffer: handle=%p width=%u height=%u stride=%u "
+ "format=%u usage=%x",
+ handle(), width(), height(), stride(), format(), usage());
FreeHandle();
}
@@ -62,55 +81,101 @@
if (buffer_.get()) {
// GraphicBuffer unregisters and cleans up the handle if needed
buffer_ = nullptr;
+ producer_usage_ = 0;
+ consumer_usage_ = 0;
}
}
-int IonBuffer::Alloc(int width, int height, int format, int usage) {
- ALOGD_IF(TRACE, "IonBuffer::Alloc: width=%d height=%d format=%d usage=%d",
- width, height, format, usage);
+int IonBuffer::Alloc(uint32_t width, uint32_t height, uint32_t format,
+ uint32_t usage) {
+ return Alloc(width, height, format, usage, usage);
+}
- buffer_ = new GraphicBuffer(width, height, format, usage);
- if (buffer_->initCheck() != OK) {
+int IonBuffer::Alloc(uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage) {
+ ALOGD_IF(
+ TRACE,
+ "IonBuffer::Alloc: width=%u height=%u format=%u producer_usage=%" PRIx64
+ " consumer_usage=%" PRIx64,
+ width, height, format, producer_usage, consumer_usage);
+
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(width, height, format, kDefaultGraphicBufferLayerCount,
+ producer_usage, consumer_usage);
+ if (buffer->initCheck() != OK) {
ALOGE("IonBuffer::Aloc: Failed to allocate buffer");
+ return -EINVAL;
+ } else {
+ buffer_ = buffer;
+ producer_usage_ = producer_usage;
+ consumer_usage_ = consumer_usage;
+ return 0;
}
- return 0;
}
-void IonBuffer::Reset(buffer_handle_t handle, int width, int height, int stride,
- int format, int usage) {
+void IonBuffer::Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint32_t usage) {
+ Reset(handle, width, height, stride, format, usage, usage);
+}
+
+void IonBuffer::Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage) {
ALOGD_IF(TRACE,
- "IonBuffer::Reset: handle=%p width=%d height=%d stride=%d format=%d "
- "usage=%d",
- handle, width, height, stride, format, usage);
- Import(handle, width, height, stride, format, usage);
+ "IonBuffer::Reset: handle=%p width=%u height=%u stride=%u format=%u "
+ "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64,
+ handle, width, height, stride, format, producer_usage,
+ consumer_usage);
+ Import(handle, width, height, stride, format, producer_usage, consumer_usage);
}
-int IonBuffer::Import(buffer_handle_t handle, int width, int height, int stride,
- int format, int usage) {
+int IonBuffer::Import(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint32_t usage) {
+ return Import(handle, width, height, stride, format, usage, usage);
+}
+
+int IonBuffer::Import(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage) {
ATRACE_NAME("IonBuffer::Import1");
ALOGD_IF(
TRACE,
- "IonBuffer::Import: handle=%p width=%d height=%d stride=%d format=%d "
- "usage=%d",
- handle, width, height, stride, format, usage);
+ "IonBuffer::Import: handle=%p width=%u height=%u stride=%u format=%u "
+ "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64,
+ handle, width, height, stride, format, producer_usage, consumer_usage);
FreeHandle();
- buffer_ = new GraphicBuffer(handle, GraphicBuffer::TAKE_UNREGISTERED_HANDLE,
- width, height, format, 1, usage, stride);
- if (buffer_->initCheck() != OK) {
+ sp<GraphicBuffer> buffer = new GraphicBuffer(
+ handle, GraphicBuffer::TAKE_UNREGISTERED_HANDLE, width, height, format,
+ kDefaultGraphicBufferLayerCount, producer_usage, consumer_usage, stride);
+ if (buffer->initCheck() != OK) {
ALOGE("IonBuffer::Import: Failed to import buffer");
return -EINVAL;
+ } else {
+ buffer_ = buffer;
+ producer_usage_ = producer_usage;
+ consumer_usage_ = consumer_usage;
+ return 0;
}
- return 0;
}
int IonBuffer::Import(const int* fd_array, int fd_count, const int* int_array,
- int int_count, int width, int height, int stride,
- int format, int usage) {
+ int int_count, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint32_t usage) {
+ return Import(fd_array, fd_count, int_array, int_count, width, height, stride,
+ format, usage, usage);
+}
+
+int IonBuffer::Import(const int* fd_array, int fd_count, const int* int_array,
+ int int_count, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage) {
ATRACE_NAME("IonBuffer::Import2");
ALOGD_IF(TRACE,
- "IonBuffer::Import: fd_count=%d int_count=%d width=%d height=%d "
- "stride=%d format=%d usage=%d",
- fd_count, int_count, width, height, stride, format, usage);
+ "IonBuffer::Import: fd_count=%d int_count=%d width=%u height=%u "
+ "stride=%u format=%u producer_usage=%" PRIx64
+ " consumer_usage=%" PRIx64,
+ fd_count, int_count, width, height, stride, format, producer_usage,
+ consumer_usage);
if (fd_count < 0 || int_count < 0) {
ALOGE("IonBuffer::Import: invalid arguments.");
@@ -128,7 +193,8 @@
memcpy(handle->data, fd_array, sizeof(int) * fd_count);
memcpy(handle->data + fd_count, int_array, sizeof(int) * int_count);
- int ret = Import(handle, width, height, stride, format, usage);
+ const int ret = Import(handle, width, height, stride, format, producer_usage,
+ consumer_usage);
if (ret < 0) {
ALOGE("IonBuffer::Import: failed to import raw native handle: %s",
strerror(-ret));
@@ -163,8 +229,9 @@
memcpy(handle->data + fd_count, other->handle()->data + fd_count,
sizeof(int) * int_count);
- const int ret = Import(handle, other->width(), other->height(),
- other->stride(), other->format(), other->usage());
+ const int ret =
+ Import(handle, other->width(), other->height(), other->stride(),
+ other->format(), other->producer_usage(), other->consumer_usage());
if (ret < 0) {
ALOGE("IonBuffer::Duplicate: Failed to import duplicate native handle: %s",
strerror(-ret));
@@ -175,7 +242,7 @@
return ret;
}
-int IonBuffer::Lock(int usage, int x, int y, int width, int height,
+int IonBuffer::Lock(uint32_t usage, int x, int y, int width, int height,
void** address) {
ATRACE_NAME("IonBuffer::Lock");
ALOGD_IF(TRACE,
@@ -183,23 +250,23 @@
"address=%p",
handle(), usage, x, y, width, height, address);
- status_t err = buffer_->lock(usage, Rect(x, y, x + width, y + height),
- address);
+ 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,
+int IonBuffer::LockYUV(uint32_t usage, int x, int y, int width, int height,
struct android_ycbcr* yuv) {
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);
- status_t err = buffer_->lockYCbCr(usage, Rect(x, y, x + width, y + height),
- yuv);
+ status_t err =
+ buffer_->lockYCbCr(usage, Rect(x, y, x + width, y + height), yuv);
if (err != NO_ERROR)
return -EINVAL;
else
@@ -216,5 +283,5 @@
else
return 0;
}
-} // namespace dvr
-} // namespace android
+} // namespace dvr
+} // namespace android
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index 031401a..b431d2f 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -11,34 +11,36 @@
#include <pdx/file_handle.h>
#include <private/dvr/bufferhub_rpc.h>
+using android::pdx::ErrorStatus;
+using android::pdx::LocalChannelHandle;
+using android::pdx::Status;
+
namespace android {
namespace dvr {
-BufferHubQueue::BufferHubQueue(LocalChannelHandle channel_handle,
- size_t meta_size)
+BufferHubQueue::BufferHubQueue(LocalChannelHandle channel_handle)
: Client{pdx::default_transport::ClientChannel::Create(
std::move(channel_handle))},
- meta_size_(meta_size),
- meta_buffer_tmp_(meta_size ? new uint8_t[meta_size] : nullptr),
+ meta_size_(0),
buffers_(BufferHubQueue::kMaxQueueCapacity),
epollhup_pending_(BufferHubQueue::kMaxQueueCapacity, false),
available_buffers_(BufferHubQueue::kMaxQueueCapacity),
fences_(BufferHubQueue::kMaxQueueCapacity),
- capacity_(0) {
+ capacity_(0),
+ id_(-1) {
Initialize();
}
-BufferHubQueue::BufferHubQueue(const std::string& endpoint_path,
- size_t meta_size)
+BufferHubQueue::BufferHubQueue(const std::string& endpoint_path)
: Client{pdx::default_transport::ClientChannelFactory::Create(
endpoint_path)},
- meta_size_(meta_size),
- meta_buffer_tmp_(meta_size ? new uint8_t[meta_size] : nullptr),
+ meta_size_(0),
buffers_(BufferHubQueue::kMaxQueueCapacity),
epollhup_pending_(BufferHubQueue::kMaxQueueCapacity, false),
available_buffers_(BufferHubQueue::kMaxQueueCapacity),
fences_(BufferHubQueue::kMaxQueueCapacity),
- capacity_(0) {
+ capacity_(0),
+ id_(-1) {
Initialize();
}
@@ -55,26 +57,47 @@
BufferHubQueue::kEpollQueueEventIndex)}};
ret = epoll_fd_.Control(EPOLL_CTL_ADD, event_fd(), &event);
if (ret < 0) {
- ALOGE("Failed to register ConsumerQueue into epoll event: %s",
+ ALOGE("BufferHubQueue::Initialize: Failed to add event fd to epoll set: %s",
strerror(-ret));
}
}
-std::unique_ptr<ConsumerQueue> BufferHubQueue::CreateConsumerQueue() {
- Status<std::pair<LocalChannelHandle, size_t>> status =
- InvokeRemoteMethod<BufferHubRPC::CreateConsumerQueue>();
-
+Status<void> BufferHubQueue::ImportQueue() {
+ auto status = InvokeRemoteMethod<BufferHubRPC::GetQueueInfo>();
if (!status) {
- ALOGE("Cannot create ConsumerQueue: %s", status.GetErrorMessage().c_str());
+ ALOGE("BufferHubQueue::ImportQueue: Failed to import queue: %s",
+ status.GetErrorMessage().c_str());
+ return ErrorStatus(status.error());
+ } else {
+ SetupQueue(status.get().meta_size_bytes, status.get().id);
+ return {};
+ }
+}
+
+void BufferHubQueue::SetupQueue(size_t meta_size_bytes, int id) {
+ meta_size_ = meta_size_bytes;
+ id_ = id;
+ meta_buffer_tmp_.reset(meta_size_ > 0 ? new uint8_t[meta_size_] : nullptr);
+}
+
+std::unique_ptr<ConsumerQueue> BufferHubQueue::CreateConsumerQueue() {
+ if (auto status = CreateConsumerQueueHandle())
+ return std::unique_ptr<ConsumerQueue>(new ConsumerQueue(status.take()));
+ else
return nullptr;
+}
+
+Status<LocalChannelHandle> BufferHubQueue::CreateConsumerQueueHandle() {
+ auto status = InvokeRemoteMethod<BufferHubRPC::CreateConsumerQueue>();
+ if (!status) {
+ ALOGE(
+ "BufferHubQueue::CreateConsumerQueue: Failed to create consumer queue: "
+ "%s",
+ status.GetErrorMessage().c_str());
+ return ErrorStatus(status.error());
}
- auto return_value = status.take();
-
- ALOGD_IF(TRACE, "BufferHubQueue::CreateConsumerQueue: meta_size_bytes=%zu",
- return_value.second);
- return ConsumerQueue::Create(std::move(return_value.first),
- return_value.second);
+ return status;
}
bool BufferHubQueue::WaitForBuffers(int timeout) {
@@ -89,7 +112,8 @@
}
if (ret < 0 && ret != -EINTR) {
- ALOGE("Failed to wait for buffers: %s", strerror(-ret));
+ ALOGE("BufferHubQueue::WaitForBuffers: Failed to wait for buffers: %s",
+ strerror(-ret));
return false;
}
@@ -108,7 +132,8 @@
} else if (is_queue_event_index(index)) {
HandleQueueEvent(events[i]);
} else {
- ALOGW("Unknown event index: %" PRId64, index);
+ ALOGW("BufferHubQueue::WaitForBuffers: Unknown event index: %" PRId64,
+ index);
}
}
}
@@ -134,7 +159,8 @@
if (events & EPOLLIN) {
int ret = OnBufferReady(buffer, &fences_[slot]);
if (ret < 0) {
- ALOGE("Failed to set buffer ready: %s", strerror(-ret));
+ ALOGE("BufferHubQueue::HandleBufferEvent: Failed to set buffer ready: %s",
+ strerror(-ret));
return;
}
Enqueue(buffer, slot);
@@ -144,8 +170,8 @@
// epoll FD is cleaned up when the replacement consumer client is imported,
// we shouldn't detach again if |epollhub_pending_[slot]| is set.
ALOGW(
- "Receives EPOLLHUP at slot: %zu, buffer event fd: %d, EPOLLHUP "
- "pending: %d",
+ "BufferHubQueue::HandleBufferEvent: Received EPOLLHUP at slot: %zu, "
+ "buffer event fd: %d, EPOLLHUP pending: %d",
slot, buffer->event_fd(), int{epollhup_pending_[slot]});
if (epollhup_pending_[slot]) {
epollhup_pending_[slot] = false;
@@ -153,7 +179,10 @@
DetachBuffer(slot);
}
} else {
- ALOGW("Unknown event, slot=%zu, epoll events=%d", slot, events);
+ ALOGW(
+ "BufferHubQueue::HandleBufferEvent: Unknown event, slot=%zu, epoll "
+ "events=%d",
+ slot, events);
}
}
@@ -169,12 +198,13 @@
if (events & EPOLLIN) {
// Note that after buffer imports, if |count()| still returns 0, epoll
// wait will be tried again to acquire the newly imported buffer.
- int ret = OnBufferAllocated();
- if (ret < 0) {
- ALOGE("Failed to import buffer: %s", strerror(-ret));
+ auto buffer_status = OnBufferAllocated();
+ if (!buffer_status) {
+ ALOGE("BufferHubQueue::HandleQueueEvent: Failed to import buffer: %s",
+ buffer_status.GetErrorMessage().c_str());
}
} else {
- ALOGW("Unknown epoll events=%d", events);
+ ALOGW("BufferHubQueue::HandleQueueEvent: Unknown epoll events=%d", events);
}
}
@@ -233,7 +263,7 @@
void BufferHubQueue::Enqueue(std::shared_ptr<BufferHubBuffer> buf,
size_t slot) {
if (count() == capacity_) {
- ALOGE("Buffer queue is full!");
+ ALOGE("BufferHubQueue::Enqueue: Buffer queue is full!");
return;
}
@@ -274,7 +304,7 @@
available_buffers_.PopFront();
if (!buf) {
- ALOGE("Dequeue: Buffer to be dequeued is nullptr");
+ ALOGE("BufferHubQueue::Dequeue: Buffer to be dequeued is nullptr");
return nullptr;
}
@@ -287,30 +317,57 @@
}
ProducerQueue::ProducerQueue(size_t meta_size)
- : ProducerQueue(meta_size, 0, 0, 0, 0) {}
+ : ProducerQueue(meta_size, 0, 0, 0, 0, 0, 0, 0, 0) {}
-ProducerQueue::ProducerQueue(LocalChannelHandle handle, size_t meta_size)
- : BASE(std::move(handle), meta_size) {}
+ProducerQueue::ProducerQueue(LocalChannelHandle handle)
+ : BASE(std::move(handle)) {
+ auto status = ImportQueue();
+ if (!status) {
+ ALOGE("ProducerQueue::ProducerQueue: Failed to import queue: %s",
+ status.GetErrorMessage().c_str());
+ Close(-status.error());
+ }
+}
-ProducerQueue::ProducerQueue(size_t meta_size, int usage_set_mask,
- int usage_clear_mask, int usage_deny_set_mask,
- int usage_deny_clear_mask)
- : BASE(BufferHubRPC::kClientPath, meta_size) {
+ProducerQueue::ProducerQueue(size_t meta_size, uint64_t producer_usage_set_mask,
+ uint64_t producer_usage_clear_mask,
+ uint64_t producer_usage_deny_set_mask,
+ uint64_t producer_usage_deny_clear_mask,
+ uint64_t consumer_usage_set_mask,
+ uint64_t consumer_usage_clear_mask,
+ uint64_t consumer_usage_deny_set_mask,
+ uint64_t consumer_usage_deny_clear_mask)
+ : BASE(BufferHubRPC::kClientPath) {
auto status = InvokeRemoteMethod<BufferHubRPC::CreateProducerQueue>(
- meta_size_, usage_set_mask, usage_clear_mask, usage_deny_set_mask,
- usage_deny_clear_mask);
+ meta_size,
+ UsagePolicy{producer_usage_set_mask, producer_usage_clear_mask,
+ producer_usage_deny_set_mask, producer_usage_deny_clear_mask,
+ consumer_usage_set_mask, consumer_usage_clear_mask,
+ consumer_usage_deny_set_mask,
+ consumer_usage_deny_clear_mask});
if (!status) {
ALOGE("ProducerQueue::ProducerQueue: Failed to create producer queue: %s",
status.GetErrorMessage().c_str());
Close(-status.error());
return;
}
+
+ SetupQueue(status.get().meta_size_bytes, status.get().id);
}
-int ProducerQueue::AllocateBuffer(int width, int height, int format, int usage,
+int ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
+ uint32_t format, uint32_t usage,
size_t slice_count, size_t* out_slot) {
+ return AllocateBuffer(width, height, format, usage, usage, slice_count,
+ out_slot);
+}
+
+int ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
+ uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage, size_t slice_count,
+ size_t* out_slot) {
if (out_slot == nullptr) {
- ALOGE("Parameter out_slot cannot be null.");
+ ALOGE("ProducerQueue::AllocateBuffer: Parameter out_slot cannot be null.");
return -EINVAL;
}
@@ -324,7 +381,8 @@
Status<std::vector<std::pair<LocalChannelHandle, size_t>>> status =
InvokeRemoteMethod<BufferHubRPC::ProducerQueueAllocateBuffers>(
- width, height, format, usage, slice_count, kBufferCount);
+ width, height, format, producer_usage, consumer_usage, slice_count,
+ kBufferCount);
if (!status) {
ALOGE(
"ProducerQueue::AllocateBuffer failed to create producer buffer "
@@ -362,7 +420,7 @@
}
int ProducerQueue::DetachBuffer(size_t slot) {
- Status<int> status =
+ auto status =
InvokeRemoteMethod<BufferHubRPC::ProducerQueueDetachBuffer>(slot);
if (!status) {
ALOGE(
@@ -378,7 +436,9 @@
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);
+ ALOGE(
+ "ProducerQueue::Dequeue: invalid parameter, slot=%p, release_fence=%p",
+ slot, release_fence);
return nullptr;
}
@@ -392,21 +452,27 @@
return buffer->Gain(release_fence);
}
-ConsumerQueue::ConsumerQueue(LocalChannelHandle handle, size_t meta_size)
- : BASE(std::move(handle), meta_size) {
- // TODO(b/34387835) Import consumer queue in case the ProducerQueue we are
+ConsumerQueue::ConsumerQueue(LocalChannelHandle handle)
+ : BufferHubQueue(std::move(handle)) {
+ auto status = ImportQueue();
+ if (!status) {
+ ALOGE("ConsumerQueue::ConsumerQueue: Failed to import queue: %s",
+ status.GetErrorMessage().c_str());
+ Close(-status.error());
+ }
+
+ // TODO(b/34387835) Import buffers in case the ProducerQueue we are
// based on was not empty.
}
-int ConsumerQueue::ImportBuffers() {
- Status<std::vector<std::pair<LocalChannelHandle, size_t>>> status =
- InvokeRemoteMethod<BufferHubRPC::ConsumerQueueImportBuffers>();
+Status<size_t> ConsumerQueue::ImportBuffers() {
+ auto status = InvokeRemoteMethod<BufferHubRPC::ConsumerQueueImportBuffers>();
if (!status) {
ALOGE(
"ConsumerQueue::ImportBuffers failed to import consumer buffer through "
"BufferBub, error: %s",
status.GetErrorMessage().c_str());
- return -status.error();
+ return ErrorStatus(status.error());
}
int last_error = 0;
@@ -431,7 +497,10 @@
}
}
- return imported_buffers > 0 ? imported_buffers : last_error;
+ if (imported_buffers > 0)
+ return {imported_buffers};
+ else
+ return ErrorStatus(-last_error);
}
int ConsumerQueue::AddBuffer(const std::shared_ptr<BufferConsumer>& buf,
@@ -445,15 +514,17 @@
LocalHandle* acquire_fence) {
if (meta_size != meta_size_) {
ALOGE(
- "metadata size (%zu) for the dequeuing buffer does not match metadata "
- "size (%zu) for the queue.",
+ "ConsumerQueue::Dequeue: Metadata size (%zu) for the dequeuing buffer "
+ "does not match metadata size (%zu) for the queue.",
meta_size, meta_size_);
return nullptr;
}
if (slot == nullptr || meta == nullptr || acquire_fence == nullptr) {
- ALOGE("invalid parameter, slot=%p, meta=%p, acquire_fence=%p", slot, meta,
- acquire_fence);
+ ALOGE(
+ "ConsumerQueue::Dequeue: Invalid parameter, slot=%p, meta=%p, "
+ "acquire_fence=%p",
+ slot, meta, acquire_fence);
return nullptr;
}
@@ -467,15 +538,19 @@
return buffer->Acquire(acquire_fence, meta_buffer_tmp_.get(), meta_size_);
}
-int ConsumerQueue::OnBufferAllocated() {
- const int ret = ImportBuffers();
- if (ret == 0) {
- ALOGW("No new buffer can be imported on buffer allocated event.");
- } else if (ret < 0) {
- ALOGE("Failed to import buffers on buffer allocated event.");
+Status<void> ConsumerQueue::OnBufferAllocated() {
+ auto status = ImportBuffers();
+ if (!status) {
+ ALOGE("ConsumerQueue::OnBufferAllocated: Failed to import buffers: %s",
+ status.GetErrorMessage().c_str());
+ return ErrorStatus(status.error());
+ } else if (status.get() == 0) {
+ ALOGW("ConsumerQueue::OnBufferAllocated: No new buffers allocated!");
+ return ErrorStatus(ENOBUFS);
+ } else {
+ ALOGD_IF(TRACE, "Imported %zu consumer buffers.", status.get());
+ return {};
}
- ALOGD_IF(TRACE, "Imported %d consumer buffers.", ret);
- return ret;
}
} // namespace dvr
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
index 3fe7642..ebd7da0 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
@@ -38,22 +38,8 @@
}
const auto& buffer_producer = core_->buffers_[slot].mBufferProducer;
+ sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
- // Create new GraphicBuffer based on the newly created |buffer_producer|. Here
- // we have to cast |buffer_handle_t| to |native_handle_t|, it's OK because
- // internally, GraphicBuffer is still an |ANativeWindowBuffer| and |handle|
- // is still type of |buffer_handle_t| and bears const property.
- sp<GraphicBuffer> graphic_buffer(new GraphicBuffer(
- buffer_producer->width(), buffer_producer->height(),
- buffer_producer->format(),
- 1, /* layer count */
- buffer_producer->usage(),
- buffer_producer->stride(),
- const_cast<native_handle_t*>(buffer_producer->buffer()->handle()),
- false));
-
- LOG_ALWAYS_FATAL_IF(NO_ERROR != graphic_buffer->initCheck(),
- "Failed to init GraphicBuffer.");
core_->buffers_[slot].mGraphicBuffer = graphic_buffer;
core_->buffers_[slot].mRequestBufferCalled = true;
@@ -155,9 +141,9 @@
if (!buffer_producer)
return NO_MEMORY;
- if (static_cast<int>(width) == buffer_producer->width() &&
- static_cast<int>(height) == buffer_producer->height() &&
- static_cast<int>(format) == buffer_producer->format()) {
+ if (width == buffer_producer->width() &&
+ height == buffer_producer->height() &&
+ static_cast<uint32_t>(format) == buffer_producer->format()) {
// The producer queue returns a buffer producer matches the request.
break;
}
@@ -165,8 +151,8 @@
// Needs reallocation.
// TODO(jwcai) Consider use VLOG instead if we find this log is not useful.
ALOGI(
- "dequeueBuffer: requested buffer (w=%u, h=%u, format=%d) is different "
- "from the buffer returned at slot: %zu (w=%d, h=%d, format=%d). Need "
+ "dequeueBuffer: requested buffer (w=%u, h=%u, format=%u) is different "
+ "from the buffer returned at slot: %zu (w=%u, h=%u, format=%u). Need "
"re-allocattion.",
width, height, format, slot, buffer_producer->width(),
buffer_producer->height(), buffer_producer->format());
@@ -322,7 +308,7 @@
output->width = buffer_producer->width();
output->height = buffer_producer->height();
- output->transformHint = 0; // default value, we don't use it yet.
+ output->transformHint = 0; // default value, we don't use it yet.
// |numPendingBuffers| counts of the number of buffers that has been enqueued
// by the producer but not yet acquired by the consumer. Due to the nature
@@ -456,7 +442,7 @@
return NO_ERROR;
}
-status_t BufferHubQueueProducer::disconnect(int api, DisconnectMode mode) {
+status_t BufferHubQueueProducer::disconnect(int api, DisconnectMode /*mode*/) {
// Consumer interaction are actually handled by buffer hub, and we need
// to maintain consumer operations here. We only need to perform basic input
// parameter checks here.
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 a020dca..255793f 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
@@ -4,6 +4,7 @@
#include <gui/BufferQueueDefs.h>
#include <pdx/client.h>
+#include <pdx/status.h>
#include <private/dvr/buffer_hub_client.h>
#include <private/dvr/epoll_file_descriptor.h>
#include <private/dvr/ring_buffer.h>
@@ -41,6 +42,9 @@
// Return the default buffer format of this buffer queue.
int32_t default_format() const { return default_format_; }
+ // Create a new consumer in handle form for immediate transport over RPC.
+ Status<LocalChannelHandle> CreateConsumerQueueHandle();
+
// Return the number of buffers avaiable for dequeue.
size_t count() const { return available_buffers_.GetSize(); }
@@ -51,7 +55,7 @@
size_t metadata_size() const { return meta_size_; }
// Return whether the buffer queue is alrady full.
- bool is_full() const { return available_buffers_.IsFull(); }
+ bool is_full() const { return available_buffers_.IsFull(); }
explicit operator bool() const { return epoll_fd_.IsValid(); }
@@ -83,9 +87,18 @@
// timeout.
static constexpr int kNoTimeOut = -1;
+ int id() const { return id_; }
+
protected:
- BufferHubQueue(LocalChannelHandle channel, size_t meta_size);
- BufferHubQueue(const std::string& endpoint_path, size_t meta_size);
+ BufferHubQueue(LocalChannelHandle channel);
+ BufferHubQueue(const std::string& endpoint_path);
+
+ // Imports the queue parameters by querying BufferHub for the parameters for
+ // this channel.
+ Status<void> ImportQueue();
+
+ // Sets up the queue with the given parameters.
+ void SetupQueue(size_t meta_size_bytes_, int id);
// Called by ProducerQueue::AddBuffer and ConsumerQueue::AddBuffer only. to
// register a buffer for epoll and internal bookkeeping.
@@ -112,7 +125,7 @@
LocalHandle* fence) = 0;
// Called when a buffer is allocated remotely.
- virtual int OnBufferAllocated() = 0;
+ virtual Status<void> OnBufferAllocated() { return {}; }
// Data members to handle arbitrary metadata passed through BufferHub. It is
// fair to enforce that all buffers in the same queue share the same metadata
@@ -235,6 +248,9 @@
// Epoll fd used to wait for BufferHub events.
EpollFileDescriptor epoll_fd_;
+ // Global id for the queue that is consistent across processes.
+ int id_;
+
BufferHubQueue(const BufferHubQueue&) = delete;
void operator=(BufferHubQueue&) = delete;
};
@@ -258,18 +274,32 @@
// |usage_deny_clear_mask| shall not conflict with each other. Such
// configuration will be treated as invalid input on creation.
template <typename Meta>
- static std::unique_ptr<ProducerQueue> Create(int usage_set_mask,
- int usage_clear_mask,
- int usage_deny_set_mask,
- int usage_deny_clear_mask) {
+ static std::unique_ptr<ProducerQueue> Create(uint32_t usage_set_mask,
+ uint32_t usage_clear_mask,
+ uint32_t usage_deny_set_mask,
+ uint32_t usage_deny_clear_mask) {
return BASE::Create(sizeof(Meta), usage_set_mask, usage_clear_mask,
- usage_deny_set_mask, usage_deny_clear_mask);
+ usage_deny_set_mask, usage_deny_clear_mask,
+ usage_set_mask, usage_clear_mask, usage_deny_set_mask,
+ usage_deny_clear_mask);
+ }
+ template <typename Meta>
+ static std::unique_ptr<ProducerQueue> Create(
+ uint64_t producer_usage_set_mask, uint64_t producer_usage_clear_mask,
+ uint64_t producer_usage_deny_set_mask,
+ uint64_t producer_usage_deny_clear_mask, uint64_t consumer_usage_set_mask,
+ uint64_t consumer_usage_clear_mask, uint64_t consumer_usage_deny_set_mask,
+ uint64_t consumer_usage_deny_clear_mask) {
+ return BASE::Create(sizeof(Meta), producer_usage_set_mask,
+ producer_usage_clear_mask, producer_usage_deny_set_mask,
+ producer_usage_deny_clear_mask, consumer_usage_set_mask,
+ consumer_usage_clear_mask, consumer_usage_deny_set_mask,
+ consumer_usage_deny_clear_mask);
}
// Import a |ProducerQueue| from a channel handle.
- template <typename Meta>
static std::unique_ptr<ProducerQueue> Import(LocalChannelHandle handle) {
- return BASE::Create(std::move(handle), sizeof(Meta));
+ return BASE::Create(std::move(handle));
}
// Get a buffer producer. Note that the method doesn't check whether the
@@ -286,7 +316,10 @@
// use (i.e. in |Gain|'ed mode).
// Returns Zero on success and negative error code when buffer allocation
// fails.
- int AllocateBuffer(int width, int height, int format, int usage,
+ int AllocateBuffer(uint32_t width, uint32_t height, uint32_t format,
+ uint32_t usage, size_t slice_count, size_t* out_slot);
+ int AllocateBuffer(uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage,
size_t slice_count, size_t* out_slot);
// Add a producer buffer to populate the queue. Once added, a producer buffer
@@ -311,18 +344,21 @@
// static template methods inherited from ClientBase, which take the same
// arguments as the constructors.
explicit ProducerQueue(size_t meta_size);
- ProducerQueue(LocalChannelHandle handle, size_t meta_size);
- ProducerQueue(size_t meta_size, int usage_set_mask, int usage_clear_mask,
- int usage_deny_set_mask, int usage_deny_clear_mask);
+ ProducerQueue(LocalChannelHandle handle);
+ ProducerQueue(size_t meta_size, uint64_t producer_usage_set_mask,
+ uint64_t producer_usage_clear_mask,
+ uint64_t producer_usage_deny_set_mask,
+ uint64_t producer_usage_deny_clear_mask,
+ uint64_t consumer_usage_set_mask,
+ uint64_t consumer_usage_clear_mask,
+ uint64_t consumer_usage_deny_set_mask,
+ uint64_t consumer_usage_deny_clear_mask);
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; }
};
-class ConsumerQueue : public pdx::ClientBase<ConsumerQueue, BufferHubQueue> {
+class ConsumerQueue : public BufferHubQueue {
public:
// Get a buffer consumer. Note that the method doesn't check whether the
// buffer slot has a valid buffer that has been imported already. When no
@@ -333,10 +369,14 @@
BufferHubQueue::GetBuffer(slot));
}
+ // Import a |ConsumerQueue| from a channel handle.
+ static std::unique_ptr<ConsumerQueue> Import(LocalChannelHandle handle) {
+ return std::unique_ptr<ConsumerQueue>(new ConsumerQueue(std::move(handle)));
+ }
+
// Import newly created buffers from the service side.
- // Returns number of buffers successfully imported; or negative error code
- // when buffer import fails.
- int ImportBuffers();
+ // Returns number of buffers successfully imported or an error.
+ Status<size_t> ImportBuffers();
// Dequeue a consumer buffer to read. The returned buffer in |Acquired|'ed
// mode, and caller should call Releasse() once it's done writing to release
@@ -353,10 +393,11 @@
std::shared_ptr<BufferConsumer> Dequeue(int timeout, size_t* slot, void* meta,
size_t meta_size,
LocalHandle* acquire_fence);
- private:
- friend BASE;
- ConsumerQueue(LocalChannelHandle handle, size_t meta_size);
+ private:
+ friend BufferHubQueue;
+
+ ConsumerQueue(LocalChannelHandle handle);
// Add a consumer buffer to populate the queue. Once added, a consumer buffer
// is NOT available to use until the producer side |Post| it. |WaitForBuffers|
@@ -367,7 +408,7 @@
int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
LocalHandle* acquire_fence) override;
- int OnBufferAllocated() override;
+ Status<void> OnBufferAllocated() override;
};
} // namespace dvr
@@ -381,6 +422,7 @@
struct DvrWriteBufferQueue {
std::shared_ptr<android::dvr::ProducerQueue> producer_queue_;
+ ANativeWindow* native_window_{nullptr};
};
struct DvrReadBufferQueue {
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
index 811543d..171577d 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
@@ -22,16 +22,20 @@
class BufferHubQueueTest : public ::testing::Test {
public:
template <typename Meta>
- void CreateQueues(int usage_set_mask = 0, int usage_clear_mask = 0,
+ bool CreateQueues(int usage_set_mask = 0, int usage_clear_mask = 0,
int usage_deny_set_mask = 0,
int usage_deny_clear_mask = 0) {
producer_queue_ =
ProducerQueue::Create<Meta>(usage_set_mask, usage_clear_mask,
usage_deny_set_mask, usage_deny_clear_mask);
- ASSERT_NE(nullptr, producer_queue_);
+ if (!producer_queue_)
+ return false;
consumer_queue_ = producer_queue_->CreateConsumerQueue();
- ASSERT_NE(nullptr, consumer_queue_);
+ if (!consumer_queue_)
+ return false;
+
+ return true;
}
void AllocateBuffer() {
@@ -51,7 +55,7 @@
TEST_F(BufferHubQueueTest, TestDequeue) {
const size_t nb_dequeue_times = 16;
- CreateQueues<size_t>();
+ ASSERT_TRUE(CreateQueues<size_t>());
// Allocate only one buffer.
AllocateBuffer();
@@ -77,7 +81,7 @@
size_t slot;
uint64_t seq;
- CreateQueues<uint64_t>();
+ ASSERT_TRUE(CreateQueues<uint64_t>());
for (size_t i = 0; i < nb_buffer; i++) {
AllocateBuffer();
@@ -127,7 +131,7 @@
};
TEST_F(BufferHubQueueTest, TestMetadata) {
- CreateQueues<TestMetadata>();
+ ASSERT_TRUE(CreateQueues<TestMetadata>());
AllocateBuffer();
std::vector<TestMetadata> ms = {
@@ -149,7 +153,7 @@
}
TEST_F(BufferHubQueueTest, TestMetadataMismatch) {
- CreateQueues<int64_t>();
+ ASSERT_TRUE(CreateQueues<int64_t>());
AllocateBuffer();
int64_t mi = 3;
@@ -166,7 +170,7 @@
}
TEST_F(BufferHubQueueTest, TestEnqueue) {
- CreateQueues<int64_t>();
+ ASSERT_TRUE(CreateQueues<int64_t>());
AllocateBuffer();
size_t slot;
@@ -181,7 +185,7 @@
}
TEST_F(BufferHubQueueTest, TestAllocateBuffer) {
- CreateQueues<int64_t>();
+ ASSERT_TRUE(CreateQueues<int64_t>());
size_t s1;
AllocateBuffer();
@@ -227,7 +231,7 @@
TEST_F(BufferHubQueueTest, TestUsageSetMask) {
const int set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
- CreateQueues<int64_t>(set_mask, 0, 0, 0);
+ ASSERT_TRUE(CreateQueues<int64_t>(set_mask, 0, 0, 0));
// When allocation, leave out |set_mask| from usage bits on purpose.
size_t slot;
@@ -243,7 +247,7 @@
TEST_F(BufferHubQueueTest, TestUsageClearMask) {
const int clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
- CreateQueues<int64_t>(0, clear_mask, 0, 0);
+ ASSERT_TRUE(CreateQueues<int64_t>(0, clear_mask, 0, 0));
// When allocation, add |clear_mask| into usage bits on purpose.
size_t slot;
@@ -259,7 +263,7 @@
TEST_F(BufferHubQueueTest, TestUsageDenySetMask) {
const int deny_set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
- CreateQueues<int64_t>(0, 0, deny_set_mask, 0);
+ ASSERT_TRUE(CreateQueues<int64_t>(0, 0, deny_set_mask, 0));
// Now that |deny_set_mask| is illegal, allocation without those bits should
// be able to succeed.
@@ -278,7 +282,7 @@
TEST_F(BufferHubQueueTest, TestUsageDenyClearMask) {
const int deny_clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
- CreateQueues<int64_t>(0, 0, 0, deny_clear_mask);
+ ASSERT_TRUE(CreateQueues<int64_t>(0, 0, 0, deny_clear_mask));
// Now that clearing |deny_clear_mask| is illegal (i.e. setting these bits are
// mandatory), allocation with those bits should be able to succeed.
diff --git a/libs/vr/libdisplay/display_client.cpp b/libs/vr/libdisplay/display_client.cpp
index 9952e59..ef50a0f 100644
--- a/libs/vr/libdisplay/display_client.cpp
+++ b/libs/vr/libdisplay/display_client.cpp
@@ -160,8 +160,7 @@
return nullptr;
}
- producer_queue_ =
- ProducerQueue::Import<DisplaySurfaceMetadata>(status.take());
+ producer_queue_ = ProducerQueue::Import(status.take());
}
return producer_queue_;
}
@@ -217,7 +216,8 @@
return 0;
}
-pdx::Status<void> DisplayClient::SetViewerParams(const ViewerParams& viewer_params) {
+pdx::Status<void> DisplayClient::SetViewerParams(
+ const ViewerParams& viewer_params) {
auto status = InvokeRemoteMethod<DisplayRPC::SetViewerParams>(viewer_params);
if (!status) {
ALOGE("DisplayClient::SetViewerParams: Failed to set viewer params: %s",
@@ -253,16 +253,20 @@
return DisplaySurfaceClient::Create(width, height, format, usage, flags);
}
-std::unique_ptr<BufferConsumer> DisplayClient::GetPoseBuffer() {
- auto status = InvokeRemoteMethod<DisplayRPC::GetPoseBuffer>();
+std::unique_ptr<IonBuffer> DisplayClient::GetNamedBuffer(
+ const std::string& name) {
+ auto status = InvokeRemoteMethod<DisplayRPC::GetNamedBuffer>(name);
if (!status) {
ALOGE(
- "DisplayClient::GetPoseBuffer: Failed to get pose buffer %s",
- status.GetErrorMessage().c_str());
+ "DisplayClient::GetNamedBuffer: Failed to get pose buffer. name=%s, "
+ "error=%s",
+ name.c_str(), status.GetErrorMessage().c_str());
return nullptr;
}
- return BufferConsumer::Import(std::move(status));
+ auto ion_buffer = std::make_unique<IonBuffer>();
+ status.take().Import(ion_buffer.get());
+ return ion_buffer;
}
bool DisplayClient::IsVrAppRunning() {
diff --git a/libs/vr/libdisplay/display_manager_client_impl.cpp b/libs/vr/libdisplay/display_manager_client_impl.cpp
index 7993fce..44b3c4b 100644
--- a/libs/vr/libdisplay/display_manager_client_impl.cpp
+++ b/libs/vr/libdisplay/display_manager_client_impl.cpp
@@ -31,19 +31,22 @@
return 0;
}
-std::unique_ptr<BufferProducer> DisplayManagerClient::SetupPoseBuffer(
- size_t extended_region_size, int usage) {
- auto status = InvokeRemoteMethod<DisplayManagerRPC::SetupPoseBuffer>(
- extended_region_size, usage);
+std::unique_ptr<IonBuffer> DisplayManagerClient::SetupNamedBuffer(
+ const std::string& name, size_t size, uint64_t producer_usage,
+ uint64_t consumer_usage) {
+ auto status = InvokeRemoteMethod<DisplayManagerRPC::SetupNamedBuffer>(
+ name, size, producer_usage, consumer_usage);
if (!status) {
ALOGE(
- "DisplayManagerClient::SetupPoseBuffer: Failed to create the pose "
- "buffer %s",
- status.GetErrorMessage().c_str());
+ "DisplayManagerClient::SetupNamedBuffer: Failed to create the named "
+ "buffer: name=%s, error=%s",
+ name.c_str(), status.GetErrorMessage().c_str());
return {};
}
- return BufferProducer::Import(std::move(status));
+ auto ion_buffer = std::make_unique<IonBuffer>();
+ status.take().Import(ion_buffer.get());
+ return ion_buffer;
}
} // namespace dvr
diff --git a/libs/vr/libdisplay/include/private/dvr/display_client.h b/libs/vr/libdisplay/include/private/dvr/display_client.h
index 378f67c..fec2ea5 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_client.h
@@ -108,7 +108,7 @@
std::unique_ptr<DisplaySurfaceClient> CreateDisplaySurface(
int width, int height, int format, int usage, int flags);
- std::unique_ptr<BufferConsumer> GetPoseBuffer();
+ std::unique_ptr<IonBuffer> GetNamedBuffer(const std::string& name);
// Temporary query for current VR status. Will be removed later.
bool IsVrAppRunning();
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 144cd3b..b0a7d13 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
@@ -17,8 +17,10 @@
int GetSurfaceList(std::vector<DisplaySurfaceInfo>* surface_list);
- std::unique_ptr<BufferProducer> SetupPoseBuffer(size_t extended_region_size,
- int usage);
+ std::unique_ptr<IonBuffer> SetupNamedBuffer(const std::string& name,
+ size_t size,
+ uint64_t producer_usage,
+ uint64_t consumer_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 ac08650..c12b090 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_rpc.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_rpc.h
@@ -9,6 +9,7 @@
#include <pdx/rpc/remote_method.h>
#include <pdx/rpc/serializable.h>
#include <pdx/rpc/variant.h>
+#include <private/dvr/bufferhub_rpc.h>
#include <private/dvr/display_types.h>
namespace android {
@@ -218,7 +219,7 @@
kOpCreateVideoMeshSurface,
kOpVideoMeshSurfaceCreateProducerQueue,
kOpSetViewerParams,
- kOpGetPoseBuffer,
+ kOpGetNamedBuffer,
kOpIsVrAppRunning,
};
@@ -247,8 +248,8 @@
LocalChannelHandle(Void));
PDX_REMOTE_METHOD(SetViewerParams, kOpSetViewerParams,
void(const ViewerParams& viewer_params));
- PDX_REMOTE_METHOD(GetPoseBuffer, kOpGetPoseBuffer,
- LocalChannelHandle(Void));
+ PDX_REMOTE_METHOD(GetNamedBuffer, kOpGetNamedBuffer,
+ LocalNativeBufferHandle(const std::string& name));
PDX_REMOTE_METHOD(IsVrAppRunning, kOpIsVrAppRunning, int(Void));
};
@@ -260,7 +261,7 @@
enum {
kOpGetSurfaceList = 0,
kOpUpdateSurfaces,
- kOpSetupPoseBuffer,
+ kOpSetupNamedBuffer,
};
// Aliases.
@@ -273,8 +274,11 @@
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));
+ PDX_REMOTE_METHOD(SetupNamedBuffer, kOpSetupNamedBuffer,
+ LocalNativeBufferHandle(const std::string& name,
+ size_t size,
+ uint64_t producer_usage,
+ uint64_t consumer_usage));
};
struct ScreenshotData {
diff --git a/libs/vr/libdisplay/video_mesh_surface_client.cpp b/libs/vr/libdisplay/video_mesh_surface_client.cpp
index 04cc194..a2307e5 100644
--- a/libs/vr/libdisplay/video_mesh_surface_client.cpp
+++ b/libs/vr/libdisplay/video_mesh_surface_client.cpp
@@ -30,8 +30,7 @@
return nullptr;
}
- producer_queue_ =
- ProducerQueue::Import<VideoMeshSurfaceBufferMetadata>(status.take());
+ producer_queue_ = ProducerQueue::Import(status.take());
}
return producer_queue_;
}
diff --git a/libs/vr/libdvr/Android.mk b/libs/vr/libdvr/Android.mk
index 3c6934b..1050283 100644
--- a/libs/vr/libdvr/Android.mk
+++ b/libs/vr/libdvr/Android.mk
@@ -49,7 +49,6 @@
LOCAL_SHARED_LIBRARIES := \
android.hardware.graphics.bufferqueue@1.0 \
android.hidl.token@1.0-utils \
- libandroid_runtime \
libbase \
libnativewindow \
diff --git a/libs/vr/libdvr/display_manager_client.cpp b/libs/vr/libdvr/display_manager_client.cpp
index 7cbfc21..8d84f7b 100644
--- a/libs/vr/libdvr/display_manager_client.cpp
+++ b/libs/vr/libdvr/display_manager_client.cpp
@@ -42,14 +42,16 @@
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));
+DvrBuffer* dvrDisplayManagerSetupNamedBuffer(DvrDisplayManagerClient* client,
+ const char* name, size_t size,
+ uint64_t producer_usage,
+ uint64_t consumer_usage) {
+ // TODO(hendrikw): When we move to gralloc1, pass both producer_usage and
+ // consumer_usage down.
+ auto ion_buffer = client->client->SetupNamedBuffer(name, size, producer_usage,
+ consumer_usage);
+ if (ion_buffer) {
+ return CreateDvrBufferFromIonBuffer(std::move(ion_buffer));
}
return nullptr;
}
@@ -109,8 +111,8 @@
}
int dvrDisplayManagerClientGetSurfaceBuffers(
- DvrDisplayManagerClient* client, int surface_id,
- DvrDisplayManagerClientSurfaceBuffers** surface_buffers) {
+ DvrDisplayManagerClient* /* client */, int /* surface_id */,
+ DvrDisplayManagerClientSurfaceBuffers** /* surface_buffers */) {
// TODO(jwcai, hendrikw) Remove this after we replacing
// dvrDisplayManagerClientGetSurfaceBuffers is dvr_api.
return -1;
diff --git a/libs/vr/libdvr/dvr_api.cpp b/libs/vr/libdvr/dvr_api.cpp
index f786c29..b91de8f 100644
--- a/libs/vr/libdvr/dvr_api.cpp
+++ b/libs/vr/libdvr/dvr_api.cpp
@@ -31,8 +31,8 @@
dvrDisplayManagerClientGetSurfaceList;
dvr_api->display_manager_client_surface_list_destroy =
dvrDisplayManagerClientSurfaceListDestroy;
- dvr_api->display_manager_setup_pose_buffer =
- dvrDisplayManagerSetupPoseBuffer;
+ dvr_api->display_manager_setup_named_buffer =
+ dvrDisplayManagerSetupNamedBuffer;
dvr_api->display_manager_client_surface_list_get_size =
dvrDisplayManagerClientSurfaceListGetSize;
dvr_api->display_manager_client_surface_list_get_surface_id =
@@ -48,7 +48,6 @@
// dvr_buffer.h
dvr_api->write_buffer_destroy = dvrWriteBufferDestroy;
- dvr_api->write_buffer_get_blob_fds = dvrWriteBufferGetBlobFds;
dvr_api->write_buffer_get_ahardwarebuffer =
dvrWriteBufferGetAHardwareBuffer;
dvr_api->write_buffer_post = dvrWriteBufferPost;
@@ -56,11 +55,12 @@
dvr_api->write_buffer_gain_async = dvrWriteBufferGainAsync;
dvr_api->read_buffer_destroy = dvrReadBufferDestroy;
- dvr_api->read_buffer_get_blob_fds = dvrReadBufferGetBlobFds;
dvr_api->read_buffer_get_ahardwarebuffer = dvrReadBufferGetAHardwareBuffer;
dvr_api->read_buffer_acquire = dvrReadBufferAcquire;
dvr_api->read_buffer_release = dvrReadBufferRelease;
dvr_api->read_buffer_release_async = dvrReadBufferReleaseAsync;
+ dvr_api->buffer_destroy = dvrBufferDestroy;
+ dvr_api->buffer_get_ahardwarebuffer = dvrBufferGetAHardwareBuffer;
// dvr_buffer_queue.h
dvr_api->write_buffer_queue_destroy = dvrWriteBufferQueueDestroy;
@@ -77,7 +77,7 @@
dvr_api->read_buffer_queue_dequeue = dvrReadBufferQueueDequeue;
// dvr_surface.h
- dvr_api->get_pose_buffer = dvrGetPoseBuffer;
+ dvr_api->get_named_buffer = dvrGetNamedBuffer;
dvr_api->surface_create = dvrSurfaceCreate;
dvr_api->surface_get_write_buffer_queue = dvrSurfaceGetWriteBufferQueue;
@@ -108,6 +108,7 @@
dvr_api->hwc_frame_get_display_id = dvrHwcFrameGetDisplayId;
dvr_api->hwc_frame_get_display_width = dvrHwcFrameGetDisplayWidth;
dvr_api->hwc_frame_get_display_height = dvrHwcFrameGetDisplayHeight;
+ dvr_api->hwc_frame_get_display_removed = dvrHwcFrameGetDisplayRemoved;
dvr_api->hwc_frame_get_layer_count = dvrHwcFrameGetLayerCount;
dvr_api->hwc_frame_get_layer_id = dvrHwcFrameGetLayerId;
dvr_api->hwc_frame_get_layer_buffer = dvrHwcFrameGetLayerBuffer;
diff --git a/libs/vr/libdvr/dvr_buffer.cpp b/libs/vr/libdvr/dvr_buffer.cpp
index 25128a6..0942b3d 100644
--- a/libs/vr/libdvr/dvr_buffer.cpp
+++ b/libs/vr/libdvr/dvr_buffer.cpp
@@ -6,13 +6,15 @@
using namespace android;
struct DvrWriteBuffer {
- std::shared_ptr<dvr::BufferProducer> write_buffer_;
- sp<GraphicBuffer> graphic_buffer_;
+ std::shared_ptr<dvr::BufferProducer> write_buffer;
};
struct DvrReadBuffer {
- std::shared_ptr<dvr::BufferConsumer> read_buffer_;
- sp<GraphicBuffer> graphic_buffer_;
+ std::shared_ptr<dvr::BufferConsumer> read_buffer;
+};
+
+struct DvrBuffer {
+ std::shared_ptr<dvr::IonBuffer> buffer;
};
namespace android {
@@ -20,16 +22,23 @@
DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
const std::shared_ptr<dvr::BufferProducer>& buffer_producer) {
- DvrWriteBuffer* write_buffer = new DvrWriteBuffer;
- write_buffer->write_buffer_ = std::move(buffer_producer);
- return write_buffer;
+ if (!buffer_producer)
+ return nullptr;
+ return new DvrWriteBuffer{std::move(buffer_producer)};
}
DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
const std::shared_ptr<dvr::BufferConsumer>& buffer_consumer) {
- DvrReadBuffer* read_buffer = new DvrReadBuffer;
- read_buffer->read_buffer_ = std::move(buffer_consumer);
- return read_buffer;
+ if (!buffer_consumer)
+ return nullptr;
+ return new DvrReadBuffer{std::move(buffer_consumer)};
+}
+
+DvrBuffer* CreateDvrBufferFromIonBuffer(
+ const std::shared_ptr<IonBuffer>& ion_buffer) {
+ if (!ion_buffer)
+ return nullptr;
+ return new DvrBuffer{std::move(ion_buffer)};
}
} // namespace dvr
@@ -49,79 +58,82 @@
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);
+void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer) {
+ delete write_buffer;
}
-int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* client,
+int dvrWriteBufferGetId(DvrWriteBuffer* write_buffer) {
+ return write_buffer->write_buffer->id();
+}
+
+int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* write_buffer,
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());
+ *hardware_buffer = reinterpret_cast<AHardwareBuffer*>(
+ write_buffer->write_buffer->buffer()->buffer().get());
return 0;
}
-int dvrWriteBufferPost(DvrWriteBuffer* client, int ready_fence_fd,
+int dvrWriteBufferPost(DvrWriteBuffer* write_buffer, 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();
+ int result = write_buffer->write_buffer->Post(fence, meta, meta_size_bytes);
return result;
}
-int dvrWriteBufferGain(DvrWriteBuffer* client, int* release_fence_fd) {
+int dvrWriteBufferGain(DvrWriteBuffer* write_buffer, int* release_fence_fd) {
pdx::LocalHandle release_fence;
- int result = client->write_buffer_->Gain(&release_fence);
+ int result = write_buffer->write_buffer->Gain(&release_fence);
*release_fence_fd = release_fence.Release();
return result;
}
-int dvrWriteBufferGainAsync(DvrWriteBuffer* client) {
- return client->write_buffer_->GainAsync();
+int dvrWriteBufferGainAsync(DvrWriteBuffer* write_buffer) {
+ return write_buffer->write_buffer->GainAsync();
}
-void dvrReadBufferDestroy(DvrReadBuffer* client) { delete client; }
+void dvrReadBufferDestroy(DvrReadBuffer* read_buffer) { delete read_buffer; }
-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 dvrReadBufferGetId(DvrReadBuffer* read_buffer) {
+ return read_buffer->read_buffer->id();
}
-int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* client,
+int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* read_buffer,
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());
+ *hardware_buffer = reinterpret_cast<AHardwareBuffer*>(
+ read_buffer->read_buffer->buffer()->buffer().get());
return 0;
}
-int dvrReadBufferAcquire(DvrReadBuffer* client, int* ready_fence_fd, void* meta,
- size_t meta_size_bytes) {
+int dvrReadBufferAcquire(DvrReadBuffer* read_buffer, 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);
+ read_buffer->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) {
+int dvrReadBufferRelease(DvrReadBuffer* read_buffer, int release_fence_fd) {
pdx::LocalHandle fence(release_fence_fd);
- int result = client->read_buffer_->Release(fence);
- fence.Release();
+ int result = read_buffer->read_buffer->Release(fence);
return result;
}
-int dvrReadBufferReleaseAsync(DvrReadBuffer* client) {
- return client->read_buffer_->ReleaseAsync();
+int dvrReadBufferReleaseAsync(DvrReadBuffer* read_buffer) {
+ return read_buffer->read_buffer->ReleaseAsync();
+}
+
+void dvrBufferDestroy(DvrBuffer* buffer) { delete buffer; }
+
+int dvrBufferGetAHardwareBuffer(DvrBuffer* buffer,
+ AHardwareBuffer** hardware_buffer) {
+ if (!hardware_buffer) {
+ return -EINVAL;
+ }
+
+ *hardware_buffer =
+ reinterpret_cast<AHardwareBuffer*>(buffer->buffer->buffer().get());
+ return 0;
}
} // extern "C"
diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp
index 4ce0b22..dfde21d 100644
--- a/libs/vr/libdvr/dvr_buffer_queue.cpp
+++ b/libs/vr/libdvr/dvr_buffer_queue.cpp
@@ -1,11 +1,10 @@
#include "include/dvr/dvr_buffer_queue.h"
+#include <android/native_window.h>
#include <gui/Surface.h>
#include <private/dvr/buffer_hub_queue_client.h>
#include <private/dvr/buffer_hub_queue_producer.h>
-#include <android_runtime/android_view_Surface.h>
-
#define CHECK_PARAM(param) \
LOG_ALWAYS_FATAL_IF(param == nullptr, "%s: " #param "cannot be NULL.", \
__FUNCTION__)
@@ -15,6 +14,9 @@
extern "C" {
void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue) {
+ if (write_queue != nullptr && write_queue->native_window_ != nullptr) {
+ ANativeWindow_release(write_queue->native_window_);
+ }
delete write_queue;
}
@@ -23,16 +25,30 @@
return write_queue->producer_queue_->capacity();
}
-jobject dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
- JNIEnv* env) {
- CHECK_PARAM(env);
+int dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
+ ANativeWindow** out_window) {
CHECK_PARAM(write_queue);
+ CHECK_PARAM(out_window);
- std::shared_ptr<dvr::BufferHubQueueCore> core =
- dvr::BufferHubQueueCore::Create(write_queue->producer_queue_);
+ // Lazy creation of |native_window_|.
+ if (write_queue->native_window_ == nullptr) {
+ std::shared_ptr<dvr::BufferHubQueueCore> core =
+ dvr::BufferHubQueueCore::Create(write_queue->producer_queue_);
+ if (core == nullptr) {
+ ALOGE(
+ "dvrWriteBufferQueueGetExternalSurface: Failed to create native "
+ "window.");
+ return -ENOMEM;
+ }
- return android_view_Surface_createFromIGraphicBufferProducer(
- env, new dvr::BufferHubQueueProducer(core));
+ sp<IGraphicBufferProducer> gbp = new dvr::BufferHubQueueProducer(core);
+ sp<Surface> surface = new Surface(gbp, true);
+ write_queue->native_window_ = static_cast<ANativeWindow*>(surface.get());
+ ANativeWindow_acquire(write_queue->native_window_);
+ }
+
+ *out_window = write_queue->native_window_;
+ return 0;
}
int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue,
diff --git a/libs/vr/libdvr/dvr_hardware_composer_client.cpp b/libs/vr/libdvr/dvr_hardware_composer_client.cpp
index e5665e1..39c2a90 100644
--- a/libs/vr/libdvr/dvr_hardware_composer_client.cpp
+++ b/libs/vr/libdvr/dvr_hardware_composer_client.cpp
@@ -84,7 +84,7 @@
delete frame;
}
-Display dvrHwcFrameGetDisplayId(DvrHwcFrame* frame) {
+DvrHwcDisplay dvrHwcFrameGetDisplayId(DvrHwcFrame* frame) {
return frame->frame.display_id;
}
@@ -104,7 +104,7 @@
return frame->frame.layers.size();
}
-Layer dvrHwcFrameGetLayerId(DvrHwcFrame* frame, size_t layer_index) {
+DvrHwcLayer dvrHwcFrameGetLayerId(DvrHwcFrame* frame, size_t layer_index) {
return frame->frame.layers[layer_index].id;
}
@@ -120,8 +120,9 @@
return frame->frame.layers[layer_index].fence->dup();
}
-Recti dvrHwcFrameGetLayerDisplayFrame(DvrHwcFrame* frame, size_t layer_index) {
- return Recti{
+DvrHwcRecti dvrHwcFrameGetLayerDisplayFrame(DvrHwcFrame* frame,
+ size_t layer_index) {
+ return DvrHwcRecti{
frame->frame.layers[layer_index].display_frame.left,
frame->frame.layers[layer_index].display_frame.top,
frame->frame.layers[layer_index].display_frame.right,
@@ -129,8 +130,8 @@
};
}
-Rectf dvrHwcFrameGetLayerCrop(DvrHwcFrame* frame, size_t layer_index) {
- return Rectf{
+DvrHwcRectf dvrHwcFrameGetLayerCrop(DvrHwcFrame* frame, size_t layer_index) {
+ return DvrHwcRectf{
frame->frame.layers[layer_index].crop.left,
frame->frame.layers[layer_index].crop.top,
frame->frame.layers[layer_index].crop.right,
@@ -138,8 +139,10 @@
};
}
-BlendMode dvrHwcFrameGetLayerBlendMode(DvrHwcFrame* frame, size_t layer_index) {
- return static_cast<BlendMode>(frame->frame.layers[layer_index].blend_mode);
+DvrHwcBlendMode dvrHwcFrameGetLayerBlendMode(DvrHwcFrame* frame,
+ size_t layer_index) {
+ return static_cast<DvrHwcBlendMode>(
+ frame->frame.layers[layer_index].blend_mode);
}
float dvrHwcFrameGetLayerAlpha(DvrHwcFrame* frame, size_t layer_index) {
diff --git a/libs/vr/libdvr/dvr_surface.cpp b/libs/vr/libdvr/dvr_surface.cpp
index a3cbba5..a04ed50 100644
--- a/libs/vr/libdvr/dvr_surface.cpp
+++ b/libs/vr/libdvr/dvr_surface.cpp
@@ -58,14 +58,25 @@
return 0;
}
-int dvrGetPoseBuffer(DvrReadBuffer** pose_buffer) {
+int dvrGetNamedBuffer(const char* name, DvrBuffer** out_buffer) {
auto client = android::dvr::DisplayClient::Create();
if (!client) {
- ALOGE("Failed to create display client!");
+ ALOGE("dvrGetNamedBuffer: Failed to create display client!");
return -ECOMM;
}
- *pose_buffer = CreateDvrReadBufferFromBufferConsumer(client->GetPoseBuffer());
+ if (out_buffer == nullptr || name == nullptr) {
+ ALOGE("dvrGetNamedBuffer: Invalid inputs: name=%p, out_buffer=%p.", name,
+ out_buffer);
+ return -EINVAL;
+ }
+
+ auto named_buffer = client->GetNamedBuffer(name);
+ if (!named_buffer) {
+ ALOGE("dvrGetNamedBuffer: Failed to find named buffer: %s.", name);
+ return -EINVAL;
+ }
+ *out_buffer = CreateDvrBufferFromIonBuffer(std::move(named_buffer));
return 0;
}
diff --git a/libs/vr/libdvr/include/dvr/display_manager_client.h b/libs/vr/libdvr/include/dvr/display_manager_client.h
index 0928d43..4e1f227 100644
--- a/libs/vr/libdvr/include/dvr/display_manager_client.h
+++ b/libs/vr/libdvr/include/dvr/display_manager_client.h
@@ -14,15 +14,16 @@
DvrDisplayManagerClientSurfaceList;
typedef struct DvrDisplayManagerClientSurfaceBuffers
DvrDisplayManagerClientSurfaceBuffers;
-typedef struct DvrWriteBuffer DvrWriteBuffer;
+typedef struct DvrBuffer DvrBuffer;
DvrDisplayManagerClient* dvrDisplayManagerClientCreate();
void dvrDisplayManagerClientDestroy(DvrDisplayManagerClient* client);
-DvrWriteBuffer* dvrDisplayManagerSetupPoseBuffer(
- DvrDisplayManagerClient* client, size_t extended_region_size,
- uint64_t usage0, uint64_t usage1);
+DvrBuffer* dvrDisplayManagerSetupNamedBuffer(DvrDisplayManagerClient* client,
+ const char* name, size_t size,
+ uint64_t producer_usage,
+ uint64_t consumer_usage);
// 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
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index 053382f..7dc6a30 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -6,12 +6,13 @@
#include <stdint.h>
#include <dvr/dvr_hardware_composer_defs.h>
-#include <jni.h>
#ifdef __cplusplus
extern "C" {
#endif
+typedef struct ANativeWindow ANativeWindow;
+
typedef struct DvrPoseAsync DvrPoseAsync;
typedef struct DvrDisplayManagerClient DvrDisplayManagerClient;
@@ -29,6 +30,7 @@
typedef struct DvrWriteBuffer DvrWriteBuffer;
typedef struct DvrReadBuffer DvrReadBuffer;
+typedef struct DvrBuffer DvrBuffer;
typedef struct AHardwareBuffer AHardwareBuffer;
typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
@@ -42,9 +44,9 @@
DvrDisplayManagerClientSurfaceList** surface_list);
typedef void (*DvrDisplayManagerClientSurfaceListDestroyPtr)(
DvrDisplayManagerClientSurfaceList* surface_list);
-typedef DvrWriteBuffer* (*DvrDisplayManagerSetupPoseBufferPtr)(
- DvrDisplayManagerClient* client, size_t extended_region_size,
- uint64_t usage0, uint64_t usage1);
+typedef DvrBuffer* (*DvrDisplayManagerSetupNamedBufferPtr)(
+ DvrDisplayManagerClient* client, const char* name, size_t size,
+ uint64_t producer_usage, uint64_t consumer_usage);
typedef size_t (*DvrDisplayManagerClientSurfaceListGetSizePtr)(
DvrDisplayManagerClientSurfaceList* surface_list);
typedef int (*DvrDisplayManagerClientSurfaceListGetSurfaceIdPtr)(
@@ -61,9 +63,6 @@
// dvr_buffer.h
typedef void (*DvrWriteBufferDestroyPtr)(DvrWriteBuffer* client);
-typedef void (*DvrWriteBufferGetBlobFdsPtr)(DvrWriteBuffer* client, int* fds,
- size_t* fds_count,
- size_t max_fds_count);
typedef int (*DvrWriteBufferGetAHardwareBufferPtr)(
DvrWriteBuffer* client, AHardwareBuffer** hardware_buffer);
typedef int (*DvrWriteBufferPostPtr)(DvrWriteBuffer* client, int ready_fence_fd,
@@ -73,9 +72,6 @@
typedef int (*DvrWriteBufferGainAsyncPtr)(DvrWriteBuffer* client);
typedef void (*DvrReadBufferDestroyPtr)(DvrReadBuffer* client);
-typedef void (*DvrReadBufferGetBlobFdsPtr)(DvrReadBuffer* client, int* fds,
- size_t* fds_count,
- size_t max_fds_count);
typedef int (*DvrReadBufferGetAHardwareBufferPtr)(
DvrReadBuffer* client, AHardwareBuffer** hardware_buffer);
typedef int (*DvrReadBufferAcquirePtr)(DvrReadBuffer* client,
@@ -84,13 +80,16 @@
typedef int (*DvrReadBufferReleasePtr)(DvrReadBuffer* client,
int release_fence_fd);
typedef int (*DvrReadBufferReleaseAsyncPtr)(DvrReadBuffer* client);
+typedef void (*DvrBufferDestroy)(DvrBuffer* buffer);
+typedef int (*DvrBufferGetAHardwareBuffer)(DvrBuffer* buffer,
+ AHardwareBuffer** hardware_buffer);
// dvr_buffer_queue.h
typedef void (*DvrWriteBufferQueueDestroyPtr)(DvrWriteBufferQueue* write_queue);
typedef size_t (*DvrWriteBufferQueueGetCapacityPtr)(
DvrWriteBufferQueue* write_queue);
-typedef jobject (*DvrWriteBufferQueueGetExternalSurfacePtr)(
- DvrWriteBufferQueue* write_queue, JNIEnv* env);
+typedef int (*DvrWriteBufferQueueGetExternalSurfacePtr)(
+ DvrWriteBufferQueue* write_queue, ANativeWindow** out_window);
typedef int (*DvrWriteBufferQueueCreateReadQueuePtr)(
DvrWriteBufferQueue* write_queue, DvrReadBufferQueue** out_read_queue);
typedef int (*DvrWriteBufferQueueDequeuePtr)(DvrWriteBufferQueue* write_queue,
@@ -109,7 +108,7 @@
size_t meta_size_bytes);
// dvr_surface.h
-typedef int (*DvrGetPoseBufferPtr)(DvrReadBuffer** pose_buffer);
+typedef int (*DvrGetNamedBufferPtr)(const char* name, DvrBuffer** out_buffer);
typedef int (*DvrSurfaceCreatePtr)(int width, int height, int format,
uint64_t usage0, uint64_t usage1, int flags,
DvrSurface** out_surface);
@@ -148,27 +147,28 @@
// dvr_hardware_composer_client.h
typedef struct DvrHwcClient DvrHwcClient;
typedef struct DvrHwcFrame DvrHwcFrame;
-typedef int(*DvrHwcOnFrameCallback)(void* client_state, DvrHwcFrame* frame);
+typedef int (*DvrHwcOnFrameCallback)(void* client_state, DvrHwcFrame* frame);
typedef DvrHwcClient* (*DvrHwcClientCreatePtr)(DvrHwcOnFrameCallback callback,
void* client_state);
typedef void (*DvrHwcClientDestroyPtr)(DvrHwcClient* client);
typedef void (*DvrHwcFrameDestroyPtr)(DvrHwcFrame* frame);
-typedef Display (*DvrHwcFrameGetDisplayIdPtr)(DvrHwcFrame* frame);
+typedef DvrHwcDisplay (*DvrHwcFrameGetDisplayIdPtr)(DvrHwcFrame* frame);
typedef int32_t (*DvrHwcFrameGetDisplayWidthPtr)(DvrHwcFrame* frame);
typedef int32_t (*DvrHwcFrameGetDisplayHeightPtr)(DvrHwcFrame* frame);
typedef bool (*DvrHwcFrameGetDisplayRemovedPtr)(DvrHwcFrame* frame);
typedef size_t (*DvrHwcFrameGetLayerCountPtr)(DvrHwcFrame* frame);
-typedef Layer (*DvrHwcFrameGetLayerIdPtr)(DvrHwcFrame* frame, size_t layer_index);
+typedef DvrHwcLayer (*DvrHwcFrameGetLayerIdPtr)(DvrHwcFrame* frame,
+ size_t layer_index);
typedef AHardwareBuffer* (*DvrHwcFrameGetLayerBufferPtr)(DvrHwcFrame* frame,
size_t layer_index);
typedef int (*DvrHwcFrameGetLayerFencePtr)(DvrHwcFrame* frame,
size_t layer_index);
-typedef Recti (*DvrHwcFrameGetLayerDisplayFramePtr)(DvrHwcFrame* frame,
- size_t layer_index);
-typedef Rectf (*DvrHwcFrameGetLayerCropPtr)(DvrHwcFrame* frame,
- size_t layer_index);
-typedef BlendMode (*DvrHwcFrameGetLayerBlendModePtr)(DvrHwcFrame* frame,
- size_t layer_index);
+typedef DvrHwcRecti (*DvrHwcFrameGetLayerDisplayFramePtr)(DvrHwcFrame* frame,
+ size_t layer_index);
+typedef DvrHwcRectf (*DvrHwcFrameGetLayerCropPtr)(DvrHwcFrame* frame,
+ size_t layer_index);
+typedef DvrHwcBlendMode (*DvrHwcFrameGetLayerBlendModePtr)(DvrHwcFrame* frame,
+ size_t layer_index);
typedef float (*DvrHwcFrameGetLayerAlphaPtr)(DvrHwcFrame* frame,
size_t layer_index);
typedef uint32_t (*DvrHwcFrameGetLayerTypePtr)(DvrHwcFrame* frame,
@@ -184,7 +184,7 @@
display_manager_client_get_surface_list;
DvrDisplayManagerClientSurfaceListDestroyPtr
display_manager_client_surface_list_destroy;
- DvrDisplayManagerSetupPoseBufferPtr display_manager_setup_pose_buffer;
+ DvrDisplayManagerSetupNamedBufferPtr display_manager_setup_named_buffer;
DvrDisplayManagerClientSurfaceListGetSizePtr
display_manager_client_surface_list_get_size;
DvrDisplayManagerClientSurfaceListGetSurfaceIdPtr
@@ -200,7 +200,6 @@
// Write buffer
DvrWriteBufferDestroyPtr write_buffer_destroy;
- DvrWriteBufferGetBlobFdsPtr write_buffer_get_blob_fds;
DvrWriteBufferGetAHardwareBufferPtr write_buffer_get_ahardwarebuffer;
DvrWriteBufferPostPtr write_buffer_post;
DvrWriteBufferGainPtr write_buffer_gain;
@@ -208,11 +207,12 @@
// Read buffer
DvrReadBufferDestroyPtr read_buffer_destroy;
- DvrReadBufferGetBlobFdsPtr read_buffer_get_blob_fds;
DvrReadBufferGetAHardwareBufferPtr read_buffer_get_ahardwarebuffer;
DvrReadBufferAcquirePtr read_buffer_acquire;
DvrReadBufferReleasePtr read_buffer_release;
DvrReadBufferReleaseAsyncPtr read_buffer_release_async;
+ DvrBufferDestroy buffer_destroy;
+ DvrBufferGetAHardwareBuffer buffer_get_ahardwarebuffer;
// Write buffer queue
DvrWriteBufferQueueDestroyPtr write_buffer_queue_destroy;
@@ -234,7 +234,7 @@
DvrVSyncClientGetSchedInfoPtr vsync_client_get_sched_info;
// Display surface
- DvrGetPoseBufferPtr get_pose_buffer;
+ DvrGetNamedBufferPtr get_named_buffer;
DvrSurfaceCreatePtr surface_create;
DvrSurfaceGetWriteBufferQueuePtr surface_get_write_buffer_queue;
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer.h b/libs/vr/libdvr/include/dvr/dvr_buffer.h
index bbfbb00..6c9c4d3 100644
--- a/libs/vr/libdvr/include/dvr/dvr_buffer.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer.h
@@ -1,9 +1,9 @@
#ifndef ANDROID_DVR_BUFFER_H_
#define ANDROID_DVR_BUFFER_H_
-#include <memory>
#include <stdbool.h>
#include <stdint.h>
+#include <memory>
#ifdef __cplusplus
extern "C" {
@@ -11,29 +11,33 @@
typedef struct DvrWriteBuffer DvrWriteBuffer;
typedef struct DvrReadBuffer DvrReadBuffer;
+typedef struct DvrBuffer DvrBuffer;
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,
+void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer);
+int dvrWriteBufferGetId(DvrWriteBuffer* write_buffer);
+int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* write_buffer,
AHardwareBuffer** hardware_buffer);
-int dvrWriteBufferPost(DvrWriteBuffer* client, int ready_fence_fd,
+int dvrWriteBufferPost(DvrWriteBuffer* write_buffer, int ready_fence_fd,
const void* meta, size_t meta_size_bytes);
-int dvrWriteBufferGain(DvrWriteBuffer* client, int* release_fence_fd);
-int dvrWriteBufferGainAsync(DvrWriteBuffer* client);
+int dvrWriteBufferGain(DvrWriteBuffer* write_buffer, int* release_fence_fd);
+int dvrWriteBufferGainAsync(DvrWriteBuffer* write_buffer);
// Read buffer
-void dvrReadBufferDestroy(DvrReadBuffer* client);
-void dvrReadBufferGetBlobFds(DvrReadBuffer* client, int* fds, size_t* fds_count,
- size_t max_fds_count);
-int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* client,
+void dvrReadBufferDestroy(DvrReadBuffer* read_buffer);
+int dvrReadBufferGetId(DvrReadBuffer* read_buffer);
+int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* read_buffer,
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);
+int dvrReadBufferAcquire(DvrReadBuffer* read_buffer, int* ready_fence_fd,
+ void* meta, size_t meta_size_bytes);
+int dvrReadBufferRelease(DvrReadBuffer* read_buffer, int release_fence_fd);
+int dvrReadBufferReleaseAsync(DvrReadBuffer* read_buffer);
+
+// Buffer
+void dvrBufferDestroy(DvrBuffer* buffer);
+int dvrBufferGetAHardwareBuffer(DvrBuffer* buffer,
+ AHardwareBuffer** hardware_buffer);
#ifdef __cplusplus
} // extern "C"
@@ -44,11 +48,14 @@
class BufferProducer;
class BufferConsumer;
+class IonBuffer;
DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
const std::shared_ptr<BufferProducer>& buffer_producer);
DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
const std::shared_ptr<BufferConsumer>& buffer_consumer);
+DvrBuffer* CreateDvrBufferFromIonBuffer(
+ const std::shared_ptr<IonBuffer>& ion_buffer);
} // namespace dvr
} // namespace android
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
index 80c9779..ba39513 100644
--- a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
@@ -2,12 +2,13 @@
#define ANDROID_DVR_BUFFER_QUEUE_H_
#include <dvr/dvr_buffer.h>
-#include <jni.h>
#ifdef __cplusplus
extern "C" {
#endif
+typedef struct ANativeWindow ANativeWindow;
+
typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
typedef struct DvrReadBufferQueue DvrReadBufferQueue;
@@ -15,10 +16,12 @@
void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue);
size_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue);
-// Returns ANativeWindow in the form of jobject. Can be casted to ANativeWindow
-// using ANativeWindow_fromSurface NDK API.
-jobject dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
- JNIEnv* env);
+// Returns ANativeWindow. Can be casted to a Java Surface using
+// ANativeWindow_toSurface NDK API. Note that this method does not acquire an
+// additional reference to the ANativeWindow returned, don't call
+// ANativeWindow_release on it.
+int dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
+ ANativeWindow** out_window);
int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue,
DvrReadBufferQueue** out_read_queue);
diff --git a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h
index 692864d..2d28aa3 100644
--- a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h
+++ b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h
@@ -29,7 +29,7 @@
// Called to free the frame information.
void dvrHwcFrameDestroy(DvrHwcFrame* frame);
-Display dvrHwcFrameGetDisplayId(DvrHwcFrame* frame);
+DvrHwcDisplay dvrHwcFrameGetDisplayId(DvrHwcFrame* frame);
int32_t dvrHwcFrameGetDisplayWidth(DvrHwcFrame* frame);
@@ -43,7 +43,7 @@
// @return Number of layers in the frame.
size_t dvrHwcFrameGetLayerCount(DvrHwcFrame* frame);
-Layer dvrHwcFrameGetLayerId(DvrHwcFrame* frame, size_t layer_index);
+DvrHwcLayer dvrHwcFrameGetLayerId(DvrHwcFrame* frame, size_t layer_index);
// Return the graphic buffer associated with the layer at |layer_index| in
// |frame|.
@@ -58,11 +58,13 @@
// @return Fence FD. Caller owns the FD and is responsible for closing it.
int dvrHwcFrameGetLayerFence(DvrHwcFrame* frame, size_t layer_index);
-Recti dvrHwcFrameGetLayerDisplayFrame(DvrHwcFrame* frame, size_t layer_index);
+DvrHwcRecti dvrHwcFrameGetLayerDisplayFrame(DvrHwcFrame* frame,
+ size_t layer_index);
-Rectf dvrHwcFrameGetLayerCrop(DvrHwcFrame* frame, size_t layer_index);
+DvrHwcRectf dvrHwcFrameGetLayerCrop(DvrHwcFrame* frame, size_t layer_index);
-BlendMode dvrHwcFrameGetLayerBlendMode(DvrHwcFrame* frame, size_t layer_index);
+DvrHwcBlendMode dvrHwcFrameGetLayerBlendMode(DvrHwcFrame* frame,
+ size_t layer_index);
float dvrHwcFrameGetLayerAlpha(DvrHwcFrame* frame, size_t layer_index);
diff --git a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_defs.h b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_defs.h
index 546ed7b..36c30f9 100644
--- a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_defs.h
+++ b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_defs.h
@@ -10,33 +10,33 @@
// NOTE: These definitions must match the ones in
// //hardware/libhardware/include/hardware/hwcomposer2.h. They are used by the
// client side which does not have access to hwc2 headers.
-enum BlendMode {
- BLEND_MODE_INVALID = 0,
- BLEND_MODE_NONE = 1,
- BLEND_MODE_PREMULTIPLIED = 2,
- BLEND_MODE_COVERAGE = 3,
+enum DvrHwcBlendMode {
+ DVR_HWC_BLEND_MODE_INVALID = 0,
+ DVR_HWC_BLEND_MODE_NONE = 1,
+ DVR_HWC_BLEND_MODE_PREMULTIPLIED = 2,
+ DVR_HWC_BLEND_MODE_COVERAGE = 3,
};
-enum Composition {
- COMPOSITION_INVALID = 0,
- COMPOSITION_CLIENT = 1,
- COMPOSITION_DEVICE = 2,
- COMPOSITION_SOLID_COLOR = 3,
- COMPOSITION_CURSOR = 4,
- COMPOSITION_SIDEBAND = 5,
+enum DvrHwcComposition {
+ DVR_HWC_COMPOSITION_INVALID = 0,
+ DVR_HWC_COMPOSITION_CLIENT = 1,
+ DVR_HWC_COMPOSITION_DEVICE = 2,
+ DVR_HWC_COMPOSITION_SOLID_COLOR = 3,
+ DVR_HWC_COMPOSITION_CURSOR = 4,
+ DVR_HWC_COMPOSITION_SIDEBAND = 5,
};
-typedef uint64_t Display;
-typedef uint64_t Layer;
+typedef uint64_t DvrHwcDisplay;
+typedef uint64_t DvrHwcLayer;
-struct Recti {
+struct DvrHwcRecti {
int32_t left;
int32_t top;
int32_t right;
int32_t bottom;
};
-struct Rectf {
+struct DvrHwcRectf {
float left;
float top;
float right;
diff --git a/libs/vr/libdvr/include/dvr/dvr_surface.h b/libs/vr/libdvr/include/dvr/dvr_surface.h
index 2712f24..e5228d6 100644
--- a/libs/vr/libdvr/include/dvr/dvr_surface.h
+++ b/libs/vr/libdvr/include/dvr/dvr_surface.h
@@ -12,7 +12,7 @@
typedef struct DvrSurfaceParameter DvrSurfaceParameter;
// Get a pointer to the global pose buffer.
-int dvrGetPoseBuffer(DvrReadBuffer** pose_buffer);
+int dvrGetNamedBuffer(const char* name, DvrBuffer** out_buffer);
int dvrSurfaceCreate(int width, int height, int format, uint64_t usage0,
uint64_t usage1, int flags, DvrSurface** out_surface);
diff --git a/libs/vr/libdvr/tests/Android.mk b/libs/vr/libdvr/tests/Android.mk
index 158d58f..29cdc13 100644
--- a/libs/vr/libdvr/tests/Android.mk
+++ b/libs/vr/libdvr/tests/Android.mk
@@ -9,6 +9,7 @@
libhardware \
libui \
libutils \
+ libnativewindow \
static_libraries := \
libdvr \
@@ -16,14 +17,18 @@
libbufferhub \
libchrome \
libdvrcommon \
+ libdisplay \
libpdx_default_transport \
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := dvr_buffer_queue-test.cpp
+LOCAL_SRC_FILES := \
+ dvr_buffer_queue-test.cpp \
+ dvr_named_buffer-test.cpp \
+
LOCAL_STATIC_LIBRARIES := $(static_libraries)
LOCAL_SHARED_LIBRARIES := $(shared_libraries)
LOCAL_EXPORT_C_INCLUDE_DIRS := ${LOCAL_C_INCLUDES}
-LOCAL_CFLAGS := -DLOG_TAG=\"dvr_buffer_queue-test\" -DTRACE=0 -O0 -g
-LOCAL_MODULE := dvr_buffer_queue-test
+LOCAL_CFLAGS := -DLOG_TAG=\"dvr_api-test\" -DTRACE=0 -O0 -g
+LOCAL_MODULE := dvr_api-test
LOCAL_MODULE_TAGS := optional
include $(BUILD_NATIVE_TEST)
diff --git a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
index f344a24..1c9eadd 100644
--- a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
@@ -1,4 +1,5 @@
#include <dvr/dvr_buffer_queue.h>
+#include <gui/Surface.h>
#include <private/dvr/buffer_hub_queue_client.h>
#include <base/logging.h>
@@ -143,6 +144,17 @@
dvrReadBufferQueueDestroy(read_queue);
}
+TEST_F(DvrBufferQueueTest, TestGetExternalSurface) {
+ ANativeWindow* window = nullptr;
+ int ret = dvrWriteBufferQueueGetExternalSurface(write_queue_, &window);
+
+ ASSERT_EQ(0, ret);
+ ASSERT_NE(nullptr, window);
+
+ sp<Surface> surface = static_cast<Surface*>(window);
+ ASSERT_TRUE(Surface::isValid(surface));
+}
+
} // namespace
} // namespace dvr
diff --git a/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
new file mode 100644
index 0000000..cd3285f
--- /dev/null
+++ b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
@@ -0,0 +1,122 @@
+#include <android/hardware_buffer.h>
+#include <dvr/display_manager_client.h>
+#include <dvr/dvr_buffer.h>
+#include <dvr/dvr_surface.h>
+#include <system/graphics.h>
+
+#include <base/logging.h>
+#include <gtest/gtest.h>
+
+namespace android {
+namespace dvr {
+
+namespace {
+
+class DvrNamedBufferTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ client_ = dvrDisplayManagerClientCreate();
+ ASSERT_NE(nullptr, client_);
+ }
+
+ void TearDown() override {
+ if (client_ != nullptr) {
+ dvrDisplayManagerClientDestroy(client_);
+ client_ = nullptr;
+ }
+ }
+
+ DvrDisplayManagerClient* client_ = nullptr;
+};
+
+TEST_F(DvrNamedBufferTest, TestNamedBuffersSameName) {
+ const char* buffer_name = "same_name";
+ DvrBuffer* buffer1 =
+ dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, 0);
+ ASSERT_NE(nullptr, buffer1);
+
+ DvrBuffer* buffer2 =
+ dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, 0);
+ ASSERT_NE(nullptr, buffer2);
+
+ AHardwareBuffer* hardware_buffer1 = nullptr;
+ int e1 = dvrBufferGetAHardwareBuffer(buffer1, &hardware_buffer1);
+ ASSERT_EQ(0, e1);
+
+ AHardwareBuffer* hardware_buffer2 = nullptr;
+ int e2 = dvrBufferGetAHardwareBuffer(buffer2, &hardware_buffer2);
+ ASSERT_EQ(0, e2);
+ ASSERT_NE(nullptr, hardware_buffer1);
+
+ AHardwareBuffer_Desc desc1 = {};
+ AHardwareBuffer_describe(hardware_buffer1, &desc1);
+ AHardwareBuffer_Desc desc2 = {};
+ AHardwareBuffer_describe(hardware_buffer2, &desc2);
+ ASSERT_EQ(desc1.width, 10u);
+ ASSERT_EQ(desc1.height, 1u);
+ ASSERT_EQ(desc1.layers, 1u);
+ ASSERT_EQ(desc1.format, HAL_PIXEL_FORMAT_BLOB);
+ ASSERT_EQ(desc1.usage0, 0u);
+ ASSERT_EQ(desc1.usage1, 0u);
+ ASSERT_EQ(desc2.width, 10u);
+ ASSERT_EQ(desc2.height, 1u);
+ ASSERT_EQ(desc2.layers, 1u);
+ ASSERT_EQ(desc2.format, HAL_PIXEL_FORMAT_BLOB);
+ ASSERT_EQ(desc2.usage0, 0u);
+ ASSERT_EQ(desc2.usage1, 0u);
+
+ dvrBufferDestroy(buffer1);
+ dvrBufferDestroy(buffer2);
+
+ DvrBuffer* buffer3 = nullptr;
+ int e3 = dvrGetNamedBuffer(buffer_name, &buffer3);
+ ASSERT_NE(nullptr, buffer3);
+ ASSERT_EQ(0, e3);
+
+ AHardwareBuffer* hardware_buffer3 = nullptr;
+ int e4 = dvrBufferGetAHardwareBuffer(buffer2, &hardware_buffer3);
+ ASSERT_EQ(0, e4);
+ ASSERT_NE(nullptr, hardware_buffer3);
+
+ AHardwareBuffer_Desc desc3 = {};
+ AHardwareBuffer_describe(hardware_buffer3, &desc3);
+ ASSERT_EQ(desc3.width, 10u);
+ ASSERT_EQ(desc3.height, 1u);
+ ASSERT_EQ(desc3.layers, 1u);
+ ASSERT_EQ(desc3.format, HAL_PIXEL_FORMAT_BLOB);
+ ASSERT_EQ(desc3.usage0, 0u);
+ ASSERT_EQ(desc3.usage1, 0u);
+
+ dvrBufferDestroy(buffer3);
+}
+
+TEST_F(DvrNamedBufferTest, TestMultipleNamedBuffers) {
+ const char* buffer_name1 = "test1";
+ const char* buffer_name2 = "test2";
+ DvrBuffer* setup_buffer1 =
+ dvrDisplayManagerSetupNamedBuffer(client_, buffer_name1, 10, 0, 0);
+ ASSERT_NE(nullptr, setup_buffer1);
+ dvrBufferDestroy(setup_buffer1);
+
+ DvrBuffer* setup_buffer2 =
+ dvrDisplayManagerSetupNamedBuffer(client_, buffer_name2, 10, 0, 0);
+ ASSERT_NE(nullptr, setup_buffer2);
+ dvrBufferDestroy(setup_buffer2);
+
+ DvrBuffer* buffer1 = nullptr;
+ int e1 = dvrGetNamedBuffer(buffer_name1, &buffer1);
+ ASSERT_NE(nullptr, buffer1);
+ ASSERT_EQ(0, e1);
+ dvrBufferDestroy(buffer1);
+
+ DvrBuffer* buffer2 = nullptr;
+ int e2 = dvrGetNamedBuffer(buffer_name2, &buffer2);
+ ASSERT_NE(nullptr, buffer2);
+ ASSERT_EQ(0, e2);
+ dvrBufferDestroy(buffer2);
+}
+
+} // namespace
+
+} // namespace dvr
+} // namespace android
diff --git a/libs/vr/libpdx/private/pdx/rpc/serialization.h b/libs/vr/libpdx/private/pdx/rpc/serialization.h
index 9a012ed..f12aef1 100644
--- a/libs/vr/libpdx/private/pdx/rpc/serialization.h
+++ b/libs/vr/libpdx/private/pdx/rpc/serialization.h
@@ -247,7 +247,7 @@
inline std::size_t GetSerializedSize(const EmptyVariant&);
template <typename... Types>
inline std::size_t GetSerializedSize(const Variant<Types...>&);
-template <typename T, typename Enabled>
+template <typename T, typename Enabled = EnableIfHasSerializableMembers<T>>
inline constexpr std::size_t GetSerializedSize(const T&);
template <typename T>
inline constexpr std::size_t GetSerializedSize(const PointerWrapper<T>&);
@@ -293,7 +293,7 @@
}
// Overload for structs/classes with SerializableMembers defined.
-template <typename T, typename Enabled = EnableIfHasSerializableMembers<T>>
+template <typename T, typename Enabled>
inline constexpr std::size_t GetSerializedSize(const T& value) {
return SerializableTraits<T>::GetSerializedSize(value);
}
@@ -836,7 +836,7 @@
inline void SerializeObject(const EmptyVariant&, MessageWriter*, void*&);
template <typename... Types>
inline void SerializeObject(const Variant<Types...>&, MessageWriter*, void*&);
-template <typename T, typename Enabled>
+template <typename T, typename Enabled = EnableIfHasSerializableMembers<T>>
inline void SerializeObject(const T&, MessageWriter*, void*&);
template <typename T>
inline void SerializeObject(const PointerWrapper<T>&, MessageWriter*, void*&);
@@ -887,7 +887,7 @@
}
// Overload for serializable structure/class types.
-template <typename T, typename Enabled = EnableIfHasSerializableMembers<T>>
+template <typename T, typename Enabled>
inline void SerializeObject(const T& value, MessageWriter* writer,
void*& buffer) {
SerializableTraits<T>::SerializeObject(value, writer, buffer);
@@ -1379,7 +1379,7 @@
}
// Forward declarations for nested definitions.
-template <typename T, typename Enabled>
+template <typename T, typename Enabled = EnableIfHasSerializableMembers<T>>
inline ErrorType DeserializeObject(T*, MessageReader*, const void*&,
const void*&);
template <typename T>
@@ -1438,7 +1438,7 @@
const void*&);
// Deserializes a Serializable type.
-template <typename T, typename Enable = EnableIfHasSerializableMembers<T>>
+template <typename T, typename Enable>
inline ErrorType DeserializeObject(T* value, MessageReader* reader,
const void*& start, const void*& end) {
return SerializableTraits<T>::DeserializeObject(value, reader, start, end);
diff --git a/libs/vr/libpdx/private/pdx/rpc/variant.h b/libs/vr/libpdx/private/pdx/rpc/variant.h
index 09789e5..cb44a51 100644
--- a/libs/vr/libpdx/private/pdx/rpc/variant.h
+++ b/libs/vr/libpdx/private/pdx/rpc/variant.h
@@ -39,15 +39,11 @@
template <typename... Types>
struct HasType : std::false_type {};
template <typename T, typename U>
-struct HasType<T, U> : std::is_same<T, U> {};
+struct HasType<T, U> : std::is_same<std::decay_t<T>, std::decay_t<U>> {};
template <typename T, typename First, typename... Rest>
struct HasType<T, First, Rest...>
- : std::integral_constant<
- bool, std::is_same<T, First>::value || HasType<T, Rest...>::value> {};
-
-template <typename T, typename... Types>
-using HasTypeIgnoreRef =
- HasType<typename std::remove_reference<T>::type, Types...>;
+ : std::integral_constant<bool, HasType<T, First>::value ||
+ HasType<T, Rest...>::value> {};
// Defines set operations on a set of Types...
template <typename... Types>
@@ -59,8 +55,8 @@
struct IsSubset<T> : HasType<T, Types...> {};
template <typename First, typename... Rest>
struct IsSubset<First, Rest...>
- : std::integral_constant<
- bool, IsSubset<First>::value && IsSubset<Rest...>::value> {};
+ : std::integral_constant<bool, IsSubset<First>::value &&
+ IsSubset<Rest...>::value> {};
};
// Determines the number of elements of Types... that are constructible from
@@ -80,18 +76,18 @@
// Enable if T is an element of Types...
template <typename R, typename T, typename... Types>
using EnableIfElement =
- typename std::enable_if<HasTypeIgnoreRef<T, Types...>::value, R>::type;
+ typename std::enable_if<HasType<T, Types...>::value, R>::type;
// Enable if T is not an element of Types...
template <typename R, typename T, typename... Types>
using EnableIfNotElement =
- typename std::enable_if<!HasTypeIgnoreRef<T, Types...>::value, R>::type;
+ typename std::enable_if<!HasType<T, Types...>::value, R>::type;
// Enable if T is convertible to an element of Types... T is considered
// convertible IIF a single element of Types... is assignable from T and T is
// not a direct element of Types...
template <typename R, typename T, typename... Types>
using EnableIfConvertible =
- typename std::enable_if<!HasTypeIgnoreRef<T, Types...>::value &&
+ typename std::enable_if<!HasType<T, Types...>::value &&
ConstructibleCount<T, Types...>::value == 1,
R>::type;
@@ -102,7 +98,7 @@
// in conversion.
template <typename R, typename T, typename... Types>
using EnableIfAssignable =
- typename std::enable_if<HasTypeIgnoreRef<T, Types...>::value ||
+ typename std::enable_if<HasType<T, Types...>::value ||
ConstructibleCount<T, Types...>::value == 1,
R>::type;
@@ -362,15 +358,13 @@
template <typename T>
using TypeTag = detail::TypeTag<T>;
template <typename T>
- using TypeTagIgnoreRef = TypeTag<typename std::remove_reference<T>::type>;
+ using DecayedTypeTag = TypeTag<std::decay_t<T>>;
template <std::size_t I>
using TypeForIndex = detail::TypeForIndex<I, Types...>;
template <std::size_t I>
using TypeTagForIndex = detail::TypeTagForIndex<I, Types...>;
template <typename T>
using HasType = detail::HasType<T, Types...>;
- template <typename T>
- using HasTypeIgnoreRef = detail::HasTypeIgnoreRef<T, Types...>;
template <typename R, typename T>
using EnableIfElement = detail::EnableIfElement<R, T, Types...>;
template <typename R, typename T>
@@ -381,13 +375,12 @@
struct Direct {};
struct Convert {};
template <typename T>
- using SelectConstructor =
- detail::Select<HasTypeIgnoreRef<T>::value, Direct, Convert>;
+ using SelectConstructor = detail::Select<HasType<T>::value, Direct, Convert>;
// Constructs by type tag when T is an direct element of Types...
template <typename T>
explicit Variant(T&& value, Direct)
- : value_(0, &index_, TypeTagIgnoreRef<T>{}, std::forward<T>(value)) {}
+ : value_(0, &index_, DecayedTypeTag<T>{}, std::forward<T>(value)) {}
// Conversion constructor when T is not a direct element of Types...
template <typename T>
explicit Variant(T&& value, Convert)
@@ -421,7 +414,7 @@
// convertible to multiple elements of Types.
template <typename T>
EnableIfElement<Variant&, T> operator=(T&& value) {
- Assign(TypeTagIgnoreRef<T>{}, std::forward<T>(value));
+ Assign(DecayedTypeTag<T>{}, std::forward<T>(value));
return *this;
}
@@ -487,7 +480,7 @@
template <typename T>
constexpr std::int32_t index_of() const {
static_assert(HasType<T>::value, "T is not an element type of Variant.");
- return value_.template index(TypeTag<T>{});
+ return value_.template index(DecayedTypeTag<T>{});
}
// Returns the index of the active type. If the Variant is empty -1 is
@@ -509,14 +502,14 @@
template <typename T>
T* get() {
if (is<T>())
- return &value_.template get(TypeTag<T>{});
+ return &value_.template get(DecayedTypeTag<T>{});
else
return nullptr;
}
template <typename T>
const T* get() const {
if (is<T>())
- return &value_.template get(TypeTag<T>{});
+ return &value_.template get(DecayedTypeTag<T>{});
else
return nullptr;
}
@@ -537,7 +530,7 @@
private:
std::int32_t index_ = kEmptyIndex;
- detail::Union<Types...> value_;
+ detail::Union<std::decay_t<Types>...> value_;
// Constructs an element from the given arguments and sets the Variant to the
// resulting type.
diff --git a/libs/vr/libpdx/thread_local_buffer_tests.cpp b/libs/vr/libpdx/thread_local_buffer_tests.cpp
index 1747d79..6cdaf10 100644
--- a/libs/vr/libpdx/thread_local_buffer_tests.cpp
+++ b/libs/vr/libpdx/thread_local_buffer_tests.cpp
@@ -89,13 +89,13 @@
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, DISABLED_InitialValue) {
+TEST(ThreadLocalBufferTest, InitialValue) {
struct TypeTagX;
using SendSlotX = ThreadLocalSlot<TypeTagX, kSendBufferIndex>;
auto value1 = ThreadLocalBufferTest::GetSlotValue<SendSlotX>();
+ MessageBuffer<SendSlotX>::GetBuffer();
auto value2 = ThreadLocalBufferTest::GetSlotValue<SendSlotX>();
EXPECT_EQ(0U, value1);
diff --git a/libs/vr/libpdx/variant_tests.cpp b/libs/vr/libpdx/variant_tests.cpp
index c30c055..325f33f 100644
--- a/libs/vr/libpdx/variant_tests.cpp
+++ b/libs/vr/libpdx/variant_tests.cpp
@@ -368,6 +368,13 @@
}
{
+ TestType<int> i(1);
+ Variant<int, bool, float> v(i.get());
+ ASSERT_TRUE(v.is<int>());
+ EXPECT_EQ(1, std::get<int>(v));
+ }
+
+ {
TestType<bool> b(true);
Variant<int, bool, float> v(b.take());
ASSERT_TRUE(v.is<bool>());
@@ -375,6 +382,13 @@
}
{
+ TestType<bool> b(true);
+ Variant<int, bool, float> v(b.get());
+ ASSERT_TRUE(v.is<bool>());
+ EXPECT_EQ(true, std::get<bool>(v));
+ }
+
+ {
Variant<const char*> c("test");
Variant<std::string> s(c);
ASSERT_TRUE(s.is<std::string>());
@@ -1060,8 +1074,8 @@
EXPECT_FALSE((detail::HasType<char, int, float, bool>::value));
EXPECT_FALSE(detail::HasType<>::value);
- EXPECT_TRUE((detail::HasTypeIgnoreRef<int&, int, float, bool>::value));
- EXPECT_FALSE((detail::HasTypeIgnoreRef<char&, int, float, bool>::value));
+ EXPECT_TRUE((detail::HasType<int&, int, float, bool>::value));
+ EXPECT_FALSE((detail::HasType<char&, int, float, bool>::value));
}
TEST(Variant, Set) {
diff --git a/libs/vr/libpdx_uds/client_channel.cpp b/libs/vr/libpdx_uds/client_channel.cpp
index 4cbdb94..924335f 100644
--- a/libs/vr/libpdx_uds/client_channel.cpp
+++ b/libs/vr/libpdx_uds/client_channel.cpp
@@ -67,7 +67,7 @@
ResponseHeader<LocalHandle> response;
};
-Status<void> ReadAndDiscardData(int socket_fd, size_t size) {
+Status<void> ReadAndDiscardData(const BorrowedHandle& socket_fd, size_t size) {
while (size > 0) {
// If there is more data to read in the message than the buffers provided
// by the caller, read and discard the extra data from the socket.
@@ -83,9 +83,10 @@
return ErrorStatus(EIO);
}
-Status<void> SendRequest(int socket_fd, TransactionState* transaction_state,
- int opcode, const iovec* send_vector,
- size_t send_count, size_t max_recv_len) {
+Status<void> SendRequest(const BorrowedHandle& socket_fd,
+ TransactionState* transaction_state, int opcode,
+ const iovec* send_vector, size_t send_count,
+ size_t max_recv_len) {
size_t send_len = CountVectorSize(send_vector, send_count);
InitRequest(&transaction_state->request, opcode, send_len, max_recv_len,
false);
@@ -95,7 +96,8 @@
return status;
}
-Status<void> ReceiveResponse(int socket_fd, TransactionState* transaction_state,
+Status<void> ReceiveResponse(const BorrowedHandle& socket_fd,
+ TransactionState* transaction_state,
const iovec* receive_vector, size_t receive_count,
size_t max_recv_len) {
auto status = ReceiveData(socket_fd, &transaction_state->response);
@@ -164,7 +166,7 @@
InitRequest(&request, opcode, length, 0, true);
memcpy(request.impulse_payload.data(), buffer, length);
- return SendData(channel_handle_.value(), request);
+ return SendData(BorrowedHandle{channel_handle_.value()}, request);
}
Status<int> ClientChannel::SendAndReceive(void* transaction_state, int opcode,
@@ -182,11 +184,11 @@
auto* state = static_cast<TransactionState*>(transaction_state);
size_t max_recv_len = CountVectorSize(receive_vector, receive_count);
- auto status = SendRequest(channel_handle_.value(), state, opcode, send_vector,
- send_count, max_recv_len);
+ auto status = SendRequest(BorrowedHandle{channel_handle_.value()}, state,
+ opcode, send_vector, send_count, max_recv_len);
if (status) {
- status = ReceiveResponse(channel_handle_.value(), state, receive_vector,
- receive_count, max_recv_len);
+ status = ReceiveResponse(BorrowedHandle{channel_handle_.value()}, state,
+ receive_vector, receive_count, max_recv_len);
}
if (!result.PropagateError(status)) {
const int return_code = state->response.ret_code;
diff --git a/libs/vr/libpdx_uds/client_channel_factory.cpp b/libs/vr/libpdx_uds/client_channel_factory.cpp
index f059453..323236d 100644
--- a/libs/vr/libpdx_uds/client_channel_factory.cpp
+++ b/libs/vr/libpdx_uds/client_channel_factory.cpp
@@ -111,11 +111,11 @@
remote.sun_path);
RequestHeader<BorrowedHandle> request;
InitRequest(&request, opcodes::CHANNEL_OPEN, 0, 0, false);
- status = SendData(socket_fd.Get(), request);
+ status = SendData(socket_fd.Borrow(), request);
if (!status)
return ErrorStatus(status.error());
ResponseHeader<LocalHandle> response;
- status = ReceiveData(socket_fd.Get(), &response);
+ status = ReceiveData(socket_fd.Borrow(), &response);
if (!status)
return ErrorStatus(status.error());
int ref = response.ret_code;
diff --git a/libs/vr/libpdx_uds/ipc_helper.cpp b/libs/vr/libpdx_uds/ipc_helper.cpp
index fe5c986..d604f62 100644
--- a/libs/vr/libpdx_uds/ipc_helper.cpp
+++ b/libs/vr/libpdx_uds/ipc_helper.cpp
@@ -26,18 +26,19 @@
uint32_t fd_count{0};
};
-Status<void> SendPayload::Send(int socket_fd) {
+Status<void> SendPayload::Send(const BorrowedHandle& socket_fd) {
return Send(socket_fd, nullptr);
}
-Status<void> SendPayload::Send(int socket_fd, const ucred* cred) {
+Status<void> SendPayload::Send(const BorrowedHandle& socket_fd,
+ const ucred* cred) {
MessagePreamble preamble;
preamble.magic = kMagicPreamble;
preamble.data_size = buffer_.size();
preamble.fd_count = file_handles_.size();
- ssize_t ret =
- RETRY_EINTR(send(socket_fd, &preamble, sizeof(preamble), MSG_NOSIGNAL));
+ ssize_t ret = RETRY_EINTR(
+ send(socket_fd.Get(), &preamble, sizeof(preamble), MSG_NOSIGNAL));
if (ret < 0)
return ErrorStatus(errno);
if (ret != sizeof(preamble))
@@ -71,7 +72,7 @@
}
}
- ret = RETRY_EINTR(sendmsg(socket_fd, &msg, MSG_NOSIGNAL));
+ ret = RETRY_EINTR(sendmsg(socket_fd.Get(), &msg, MSG_NOSIGNAL));
if (ret < 0)
return ErrorStatus(errno);
if (static_cast<size_t>(ret) != buffer_.size())
@@ -125,14 +126,15 @@
return ErrorStatus{EOPNOTSUPP};
}
-Status<void> ReceivePayload::Receive(int socket_fd) {
+Status<void> ReceivePayload::Receive(const BorrowedHandle& socket_fd) {
return Receive(socket_fd, nullptr);
}
-Status<void> ReceivePayload::Receive(int socket_fd, ucred* cred) {
+Status<void> ReceivePayload::Receive(const BorrowedHandle& socket_fd,
+ ucred* cred) {
MessagePreamble preamble;
- ssize_t ret =
- RETRY_EINTR(recv(socket_fd, &preamble, sizeof(preamble), MSG_WAITALL));
+ ssize_t ret = RETRY_EINTR(
+ recv(socket_fd.Get(), &preamble, sizeof(preamble), MSG_WAITALL));
if (ret < 0)
return ErrorStatus(errno);
else if (ret == 0)
@@ -157,7 +159,7 @@
msg.msg_control = alloca(msg.msg_controllen);
}
- ret = RETRY_EINTR(recvmsg(socket_fd, &msg, MSG_WAITALL));
+ ret = RETRY_EINTR(recvmsg(socket_fd.Get(), &msg, MSG_WAITALL));
if (ret < 0)
return ErrorStatus(errno);
else if (ret == 0)
@@ -219,8 +221,10 @@
return false;
}
-Status<void> SendData(int socket_fd, const void* data, size_t size) {
- ssize_t size_written = RETRY_EINTR(send(socket_fd, data, size, MSG_NOSIGNAL));
+Status<void> SendData(const BorrowedHandle& socket_fd, const void* data,
+ size_t size) {
+ ssize_t size_written =
+ RETRY_EINTR(send(socket_fd.Get(), data, size, MSG_NOSIGNAL));
if (size_written < 0)
return ErrorStatus(errno);
if (static_cast<size_t>(size_written) != size)
@@ -228,11 +232,13 @@
return {};
}
-Status<void> SendDataVector(int socket_fd, const iovec* data, size_t count) {
+Status<void> SendDataVector(const BorrowedHandle& socket_fd, const iovec* data,
+ size_t count) {
msghdr msg = {};
msg.msg_iov = const_cast<iovec*>(data);
msg.msg_iovlen = count;
- ssize_t size_written = RETRY_EINTR(sendmsg(socket_fd, &msg, MSG_NOSIGNAL));
+ ssize_t size_written =
+ RETRY_EINTR(sendmsg(socket_fd.Get(), &msg, MSG_NOSIGNAL));
if (size_written < 0)
return ErrorStatus(errno);
if (static_cast<size_t>(size_written) != CountVectorSize(data, count))
@@ -240,8 +246,10 @@
return {};
}
-Status<void> ReceiveData(int socket_fd, void* data, size_t size) {
- ssize_t size_read = RETRY_EINTR(recv(socket_fd, data, size, MSG_WAITALL));
+Status<void> ReceiveData(const BorrowedHandle& socket_fd, void* data,
+ size_t size) {
+ ssize_t size_read =
+ RETRY_EINTR(recv(socket_fd.Get(), data, size, MSG_WAITALL));
if (size_read < 0)
return ErrorStatus(errno);
else if (size_read == 0)
@@ -251,11 +259,12 @@
return {};
}
-Status<void> ReceiveDataVector(int socket_fd, const iovec* data, size_t count) {
+Status<void> ReceiveDataVector(const BorrowedHandle& socket_fd,
+ const iovec* data, size_t count) {
msghdr msg = {};
msg.msg_iov = const_cast<iovec*>(data);
msg.msg_iovlen = count;
- ssize_t size_read = RETRY_EINTR(recvmsg(socket_fd, &msg, MSG_WAITALL));
+ ssize_t size_read = RETRY_EINTR(recvmsg(socket_fd.Get(), &msg, MSG_WAITALL));
if (size_read < 0)
return ErrorStatus(errno);
else if (size_read == 0)
diff --git a/libs/vr/libpdx_uds/private/uds/ipc_helper.h b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
index 80530bf..82950a2 100644
--- a/libs/vr/libpdx_uds/private/uds/ipc_helper.h
+++ b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
@@ -25,8 +25,8 @@
class SendPayload : public MessageWriter, public OutputResourceMapper {
public:
- Status<void> Send(int socket_fd);
- Status<void> Send(int socket_fd, const ucred* cred);
+ Status<void> Send(const BorrowedHandle& socket_fd);
+ Status<void> Send(const BorrowedHandle& socket_fd, const ucred* cred);
// MessageWriter
void* GetNextWriteBufferSection(size_t size) override;
@@ -50,8 +50,8 @@
class ReceivePayload : public MessageReader, public InputResourceMapper {
public:
- Status<void> Receive(int socket_fd);
- Status<void> Receive(int socket_fd, ucred* cred);
+ Status<void> Receive(const BorrowedHandle& socket_fd);
+ Status<void> Receive(const BorrowedHandle& socket_fd, ucred* cred);
// MessageReader
BufferSection GetNextReadBufferSection() override;
@@ -111,25 +111,27 @@
};
template <typename T>
-inline Status<void> SendData(int socket_fd, const T& data) {
+inline Status<void> SendData(const BorrowedHandle& socket_fd, const T& data) {
SendPayload payload;
rpc::Serialize(data, &payload);
return payload.Send(socket_fd);
}
template <typename FileHandleType>
-inline Status<void> SendData(int socket_fd,
+inline Status<void> SendData(const BorrowedHandle& socket_fd,
const RequestHeader<FileHandleType>& request) {
SendPayload payload;
rpc::Serialize(request, &payload);
return payload.Send(socket_fd, &request.cred);
}
-Status<void> SendData(int socket_fd, const void* data, size_t size);
-Status<void> SendDataVector(int socket_fd, const iovec* data, size_t count);
+Status<void> SendData(const BorrowedHandle& socket_fd, const void* data,
+ size_t size);
+Status<void> SendDataVector(const BorrowedHandle& socket_fd, const iovec* data,
+ size_t count);
template <typename T>
-inline Status<void> ReceiveData(int socket_fd, T* data) {
+inline Status<void> ReceiveData(const BorrowedHandle& socket_fd, T* data) {
ReceivePayload payload;
Status<void> status = payload.Receive(socket_fd);
if (status && rpc::Deserialize(data, &payload) != rpc::ErrorCode::NO_ERROR)
@@ -138,7 +140,7 @@
}
template <typename FileHandleType>
-inline Status<void> ReceiveData(int socket_fd,
+inline Status<void> ReceiveData(const BorrowedHandle& socket_fd,
RequestHeader<FileHandleType>* request) {
ReceivePayload payload;
Status<void> status = payload.Receive(socket_fd, &request->cred);
@@ -147,8 +149,10 @@
return status;
}
-Status<void> ReceiveData(int socket_fd, void* data, size_t size);
-Status<void> ReceiveDataVector(int socket_fd, const iovec* data, size_t count);
+Status<void> ReceiveData(const BorrowedHandle& socket_fd, void* data,
+ size_t size);
+Status<void> ReceiveDataVector(const BorrowedHandle& socket_fd,
+ const iovec* data, size_t count);
size_t CountVectorSize(const iovec* data, size_t count);
void InitRequest(android::pdx::uds::RequestHeader<BorrowedHandle>* request,
diff --git a/libs/vr/libpdx_uds/private/uds/service_endpoint.h b/libs/vr/libpdx_uds/private/uds/service_endpoint.h
index 2b24f62..f747abc 100644
--- a/libs/vr/libpdx_uds/private/uds/service_endpoint.h
+++ b/libs/vr/libpdx_uds/private/uds/service_endpoint.h
@@ -117,18 +117,20 @@
return next_message_id_.fetch_add(1, std::memory_order_relaxed);
}
- void BuildCloseMessage(int channel_id, Message* message);
+ void BuildCloseMessage(int32_t channel_id, Message* message);
Status<void> AcceptConnection(Message* message);
- Status<void> ReceiveMessageForChannel(int channel_id, Message* message);
+ Status<void> ReceiveMessageForChannel(const BorrowedHandle& channel_fd,
+ Message* message);
Status<void> OnNewChannel(LocalHandle channel_fd);
- Status<ChannelData*> OnNewChannelLocked(LocalHandle channel_fd,
- Channel* channel_state);
- Status<void> CloseChannelLocked(int channel_id);
- Status<void> ReenableEpollEvent(int fd);
- Channel* GetChannelState(int channel_id);
- int GetChannelSocketFd(int channel_id);
- int GetChannelEventFd(int channel_id);
+ Status<std::pair<int32_t, ChannelData*>> OnNewChannelLocked(
+ LocalHandle channel_fd, Channel* channel_state);
+ Status<void> CloseChannelLocked(int32_t channel_id);
+ Status<void> ReenableEpollEvent(const BorrowedHandle& channel_fd);
+ Channel* GetChannelState(int32_t channel_id);
+ BorrowedHandle GetChannelSocketFd(int32_t channel_id);
+ BorrowedHandle GetChannelEventFd(int32_t channel_id);
+ int32_t GetChannelId(const BorrowedHandle& channel_fd);
std::string endpoint_path_;
bool is_blocking_;
@@ -137,7 +139,9 @@
LocalHandle epoll_fd_;
mutable std::mutex channel_mutex_;
- std::map<int, ChannelData> channels_;
+ std::map<int32_t, ChannelData> channels_;
+ std::map<int, int32_t> channel_fd_to_id_;
+ int32_t last_channel_id_{0};
Service* service_{nullptr};
std::atomic<uint32_t> next_message_id_;
diff --git a/libs/vr/libpdx_uds/service_endpoint.cpp b/libs/vr/libpdx_uds/service_endpoint.cpp
index 6f32867..65fd59f 100644
--- a/libs/vr/libpdx_uds/service_endpoint.cpp
+++ b/libs/vr/libpdx_uds/service_endpoint.cpp
@@ -220,9 +220,11 @@
return ErrorStatus(errno);
}
- auto status = ReceiveMessageForChannel(channel_fd.Get(), message);
+ // Borrow the channel handle before we pass (move) it into OnNewChannel().
+ BorrowedHandle borrowed_channel_handle = channel_fd.Borrow();
+ auto status = OnNewChannel(std::move(channel_fd));
if (status)
- status = OnNewChannel(std::move(channel_fd));
+ status = ReceiveMessageForChannel(borrowed_channel_handle, message);
return status;
}
@@ -247,7 +249,7 @@
return status;
}
-Status<Endpoint::ChannelData*> Endpoint::OnNewChannelLocked(
+Status<std::pair<int32_t, Endpoint::ChannelData*>> Endpoint::OnNewChannelLocked(
LocalHandle channel_fd, Channel* channel_state) {
epoll_event event;
event.events = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT;
@@ -259,19 +261,28 @@
return ErrorStatus(errno);
}
ChannelData channel_data;
- const int channel_id = channel_fd.Get();
channel_data.event_set.AddDataFd(channel_fd);
channel_data.data_fd = std::move(channel_fd);
channel_data.channel_state = channel_state;
- auto pair = channels_.emplace(channel_id, std::move(channel_data));
- return &pair.first->second;
+ for (;;) {
+ // Try new channel IDs until we find one which is not already in the map.
+ if (last_channel_id_++ == std::numeric_limits<int32_t>::max())
+ last_channel_id_ = 1;
+ auto iter = channels_.lower_bound(last_channel_id_);
+ if (iter == channels_.end() || iter->first != last_channel_id_) {
+ channel_fd_to_id_.emplace(channel_data.data_fd.Get(), last_channel_id_);
+ iter = channels_.emplace_hint(iter, last_channel_id_,
+ std::move(channel_data));
+ return std::make_pair(last_channel_id_, &iter->second);
+ }
+ }
}
-Status<void> Endpoint::ReenableEpollEvent(int fd) {
+Status<void> Endpoint::ReenableEpollEvent(const BorrowedHandle& fd) {
epoll_event event;
event.events = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT;
- event.data.fd = fd;
- if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_MOD, fd, &event) < 0) {
+ event.data.fd = fd.Get();
+ if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_MOD, fd.Get(), &event) < 0) {
ALOGE(
"Endpoint::ReenableEpollEvent: Failed to re-enable channel to "
"endpoint: %s\n",
@@ -286,16 +297,17 @@
return CloseChannelLocked(channel_id);
}
-Status<void> Endpoint::CloseChannelLocked(int channel_id) {
+Status<void> Endpoint::CloseChannelLocked(int32_t channel_id) {
ALOGD_IF(TRACE, "Endpoint::CloseChannelLocked: channel_id=%d", channel_id);
- auto channel_data = channels_.find(channel_id);
- if (channel_data == channels_.end())
+ auto iter = channels_.find(channel_id);
+ if (iter == channels_.end())
return ErrorStatus{EINVAL};
+ int channel_fd = iter->second.data_fd.Get();
Status<void> status;
epoll_event dummy; // See BUGS in man 2 epoll_ctl.
- if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_DEL, channel_id, &dummy) < 0) {
+ if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_DEL, channel_fd, &dummy) < 0) {
status.SetError(errno);
ALOGE(
"Endpoint::CloseChannelLocked: Failed to remove channel from endpoint: "
@@ -305,7 +317,8 @@
status.SetValue();
}
- channels_.erase(channel_data);
+ channel_fd_to_id_.erase(channel_fd);
+ channels_.erase(iter);
return status;
}
@@ -348,10 +361,10 @@
}
std::lock_guard<std::mutex> autolock(channel_mutex_);
- *channel_id = local_socket.Get();
auto channel_data = OnNewChannelLocked(std::move(local_socket), channel);
if (!channel_data)
return channel_data.error_status();
+ *channel_id = channel_data.get().first;
// Flags are ignored for now.
// TODO(xiaohuit): Implement those.
@@ -359,7 +372,7 @@
auto* state = static_cast<MessageState*>(message->GetState());
Status<ChannelReference> ref = state->PushChannelHandle(
remote_socket.Borrow(),
- channel_data.get()->event_set.event_fd().Borrow());
+ channel_data.get().second->event_set.event_fd().Borrow());
if (!ref)
return ref.error_status();
state->sockets_to_close.push_back(std::move(remote_socket));
@@ -373,32 +386,42 @@
return ErrorStatus(EFAULT);
}
-Channel* Endpoint::GetChannelState(int channel_id) {
+Channel* Endpoint::GetChannelState(int32_t channel_id) {
std::lock_guard<std::mutex> autolock(channel_mutex_);
auto channel_data = channels_.find(channel_id);
return (channel_data != channels_.end()) ? channel_data->second.channel_state
: nullptr;
}
-int Endpoint::GetChannelSocketFd(int channel_id) {
+BorrowedHandle Endpoint::GetChannelSocketFd(int32_t channel_id) {
std::lock_guard<std::mutex> autolock(channel_mutex_);
+ BorrowedHandle handle;
auto channel_data = channels_.find(channel_id);
- return (channel_data != channels_.end()) ? channel_data->second.data_fd.Get()
- : -1;
+ if (channel_data != channels_.end())
+ handle = channel_data->second.data_fd.Borrow();
+ return handle;
}
-int Endpoint::GetChannelEventFd(int channel_id) {
+BorrowedHandle Endpoint::GetChannelEventFd(int32_t channel_id) {
std::lock_guard<std::mutex> autolock(channel_mutex_);
+ BorrowedHandle handle;
auto channel_data = channels_.find(channel_id);
- return (channel_data != channels_.end())
- ? channel_data->second.event_set.event_fd().Get()
- : -1;
+ if (channel_data != channels_.end())
+ handle = channel_data->second.event_set.event_fd().Borrow();
+ return handle;
}
-Status<void> Endpoint::ReceiveMessageForChannel(int channel_id,
- Message* message) {
+int32_t Endpoint::GetChannelId(const BorrowedHandle& channel_fd) {
+ std::lock_guard<std::mutex> autolock(channel_mutex_);
+ auto iter = channel_fd_to_id_.find(channel_fd.Get());
+ return (iter != channel_fd_to_id_.end()) ? iter->second : -1;
+}
+
+Status<void> Endpoint::ReceiveMessageForChannel(
+ const BorrowedHandle& channel_fd, Message* message) {
RequestHeader<LocalHandle> request;
- auto status = ReceiveData(channel_id, &request);
+ int32_t channel_id = GetChannelId(channel_fd);
+ auto status = ReceiveData(channel_fd.Borrow(), &request);
if (!status) {
if (status.error() == ESHUTDOWN) {
BuildCloseMessage(channel_id, message);
@@ -434,12 +457,12 @@
state->request = std::move(request);
if (request.send_len > 0 && !request.is_impulse) {
state->request_data.resize(request.send_len);
- status = ReceiveData(channel_id, state->request_data.data(),
+ status = ReceiveData(channel_fd, state->request_data.data(),
state->request_data.size());
}
if (status && request.is_impulse)
- status = ReenableEpollEvent(channel_id);
+ status = ReenableEpollEvent(channel_fd);
if (!status) {
if (status.error() == ESHUTDOWN) {
@@ -454,7 +477,7 @@
return status;
}
-void Endpoint::BuildCloseMessage(int channel_id, Message* message) {
+void Endpoint::BuildCloseMessage(int32_t channel_id, Message* message) {
ALOGD_IF(TRACE, "Endpoint::BuildCloseMessage: channel_id=%d", channel_id);
MessageInfo info;
info.pid = -1;
@@ -496,22 +519,22 @@
auto status = AcceptConnection(message);
if (!status)
return status;
- return ReenableEpollEvent(socket_fd_.Get());
+ return ReenableEpollEvent(socket_fd_.Borrow());
}
- int channel_id = event.data.fd;
+ BorrowedHandle channel_fd{event.data.fd};
if (event.events & (EPOLLRDHUP | EPOLLHUP)) {
- BuildCloseMessage(channel_id, message);
+ BuildCloseMessage(GetChannelId(channel_fd), message);
return {};
}
- return ReceiveMessageForChannel(channel_id, message);
+ return ReceiveMessageForChannel(channel_fd, message);
}
Status<void> Endpoint::MessageReply(Message* message, int return_code) {
- const int channel_id = message->GetChannelId();
- const int channel_socket = GetChannelSocketFd(channel_id);
- if (channel_socket < 0)
+ const int32_t channel_id = message->GetChannelId();
+ auto channel_socket = GetChannelSocketFd(channel_id);
+ if (!channel_socket)
return ErrorStatus{EBADF};
auto* state = static_cast<MessageState*>(message->GetState());
@@ -524,8 +547,7 @@
return CloseChannel(channel_id);
} else {
// Reply with the event fd.
- auto push_status = state->PushFileHandle(
- BorrowedHandle{GetChannelEventFd(channel_socket)});
+ auto push_status = state->PushFileHandle(GetChannelEventFd(channel_id));
state->response_data.clear(); // Just in case...
if (!push_status)
return push_status.error_status();
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index 3f79a7b..632978b 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -47,7 +47,7 @@
]
sharedLibraries = [
- "android.dvr.composer@1.0",
+ "android.frameworks.vr.composer@1.0",
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.composer@2.1",
"libbinder",
@@ -76,7 +76,7 @@
cflags: [
"-DLOG_TAG=\"vr_flinger\"",
"-DTRACE=0",
- "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
+ "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
"-DGL_GLEXT_PROTOTYPES",
"-DEGL_EGLEXT_PROTOTYPES",
],
diff --git a/libs/vr/libvrflinger/display_manager_service.cpp b/libs/vr/libvrflinger/display_manager_service.cpp
index 49b6f09..99f93bf 100644
--- a/libs/vr/libvrflinger/display_manager_service.cpp
+++ b/libs/vr/libvrflinger/display_manager_service.cpp
@@ -2,7 +2,9 @@
#include <pdx/channel_handle.h>
#include <pdx/default_transport/service_endpoint.h>
+#include <private/android_filesystem_config.h>
#include <private/dvr/display_rpc.h>
+#include <private/dvr/trusted_uids.h>
#include <sys/poll.h>
#include <array>
@@ -82,9 +84,9 @@
*this, &DisplayManagerService::OnUpdateSurfaces, message);
return {};
- case DisplayManagerRPC::SetupPoseBuffer::Opcode:
- DispatchRemoteMethod<DisplayManagerRPC::SetupPoseBuffer>(
- *this, &DisplayManagerService::OnSetupPoseBuffer, message);
+ case DisplayManagerRPC::SetupNamedBuffer::Opcode:
+ DispatchRemoteMethod<DisplayManagerRPC::SetupNamedBuffer>(
+ *this, &DisplayManagerService::OnSetupNamedBuffer, message);
return {};
default:
@@ -188,9 +190,20 @@
return 0;
}
-pdx::BorrowedChannelHandle DisplayManagerService::OnSetupPoseBuffer(
- pdx::Message& /*message*/, size_t extended_region_size, int usage) {
- return display_service_->SetupPoseBuffer(extended_region_size, usage);
+pdx::Status<BorrowedNativeBufferHandle>
+DisplayManagerService::OnSetupNamedBuffer(pdx::Message& message,
+ const std::string& name, size_t size,
+ uint64_t producer_usage,
+ uint64_t consumer_usage) {
+ if (message.GetEffectiveUserId() != AID_ROOT &&
+ !IsTrustedUid(message.GetEffectiveUserId())) {
+ // Only trusted users can setup named buffers.
+ ALOGE("DisplayService::SetupNamedBuffer: Called by untrusted user: uid=%d.",
+ message.GetEffectiveUserId());
+ return {};
+ }
+ return display_service_->SetupNamedBuffer(name, size, producer_usage,
+ consumer_usage);
}
void DisplayManagerService::OnDisplaySurfaceChange() {
diff --git a/libs/vr/libvrflinger/display_manager_service.h b/libs/vr/libvrflinger/display_manager_service.h
index 80324fd..7b037de 100644
--- a/libs/vr/libvrflinger/display_manager_service.h
+++ b/libs/vr/libvrflinger/display_manager_service.h
@@ -54,9 +54,9 @@
int OnUpdateSurfaces(pdx::Message& message,
const std::map<int, DisplaySurfaceAttributes>& updates);
- pdx::BorrowedChannelHandle OnSetupPoseBuffer(pdx::Message& message,
- size_t extended_region_size,
- int usage);
+ pdx::Status<BorrowedNativeBufferHandle> OnSetupNamedBuffer(
+ pdx::Message& message, const std::string& name, size_t size,
+ uint64_t producer_usage, uint64_t consumer_usage);
// Called by the display service to indicate changes to display surfaces that
// the display manager should evaluate.
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index 3750ea3..8cf9d64 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -1,5 +1,6 @@
#include "display_service.h"
+#include <unistd.h>
#include <vector>
#include <pdx/default_transport/service_endpoint.h>
@@ -18,20 +19,10 @@
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 {
-DisplayService::DisplayService()
- : DisplayService(nullptr) {}
+DisplayService::DisplayService() : DisplayService(nullptr) {}
DisplayService::DisplayService(Hwc2::Composer* hidl)
: BASE("DisplayService", Endpoint::Create(DisplayRPC::kClientPath)),
@@ -89,9 +80,9 @@
*this, &DisplayService::OnSetViewerParams, message);
return {};
- case DisplayRPC::GetPoseBuffer::Opcode:
- DispatchRemoteMethod<DisplayRPC::GetPoseBuffer>(
- *this, &DisplayService::OnGetPoseBuffer, message);
+ case DisplayRPC::GetNamedBuffer::Opcode:
+ DispatchRemoteMethod<DisplayRPC::GetNamedBuffer>(
+ *this, &DisplayService::OnGetNamedBuffer, message);
return {};
case DisplayRPC::IsVrAppRunning::Opcode:
@@ -254,13 +245,14 @@
compositor->UpdateHeadMountMetrics(head_mount_metrics);
}
-pdx::LocalChannelHandle DisplayService::OnGetPoseBuffer(pdx::Message& message) {
- if (pose_buffer_) {
- return pose_buffer_->CreateConsumer().take();
+pdx::Status<BorrowedNativeBufferHandle> DisplayService::OnGetNamedBuffer(
+ pdx::Message& /* message */, const std::string& name) {
+ auto named_buffer = named_buffers_.find(name);
+ if (named_buffer != named_buffers_.end()) {
+ return {BorrowedNativeBufferHandle(*named_buffer->second, 0)};
}
- pdx::rpc::RemoteMethodError(message, EAGAIN);
- return {};
+ return pdx::ErrorStatus(EINVAL);
}
// Calls the message handler for the DisplaySurface associated with this
@@ -334,16 +326,22 @@
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);
+pdx::Status<BorrowedNativeBufferHandle> DisplayService::SetupNamedBuffer(
+ const std::string& name, size_t size, int producer_usage,
+ int consumer_usage) {
+ auto named_buffer = named_buffers_.find(name);
+ if (named_buffer == named_buffers_.end()) {
+ // TODO(hendrikw): Update BufferProducer to take producer_usage and
+ // consumer_usage flags.
+ auto ion_buffer = std::make_unique<IonBuffer>(
+ static_cast<int>(size), 1, HAL_PIXEL_FORMAT_BLOB,
+ producer_usage | consumer_usage);
+ named_buffer =
+ named_buffers_.insert(std::make_pair(name, std::move(ion_buffer)))
+ .first;
}
- return pose_buffer_->GetChannelHandle().Borrow();
+ return {BorrowedNativeBufferHandle(*named_buffer->second, 0)};
}
void DisplayService::OnHardwareComposerRefresh() {
@@ -361,11 +359,12 @@
}
int DisplayService::IsVrAppRunning(pdx::Message& message) {
- bool visible = true;
- ForEachDisplaySurface([&visible](const std::shared_ptr<DisplaySurface>& surface) {
- if (surface->client_z_order() == 0 && !surface->IsVisible())
- visible = false;
- });
+ bool visible = false;
+ ForEachDisplaySurface(
+ [&visible](const std::shared_ptr<DisplaySurface>& surface) {
+ if (surface->client_z_order() == 0 && surface->IsVisible())
+ visible = true;
+ });
REPLY_SUCCESS_RETURN(message, visible, 0);
}
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index da80a84..db89064 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -3,6 +3,7 @@
#include <pdx/service.h>
#include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/bufferhub_rpc.h>
#include <private/dvr/display_rpc.h>
#include <private/dvr/late_latch.h>
@@ -38,8 +39,9 @@
// any change to client/manager attributes that affect visibility or z order.
void UpdateActiveDisplaySurfaces();
- pdx::BorrowedChannelHandle SetupPoseBuffer(size_t extended_region_size,
- int usage);
+ pdx::Status<BorrowedNativeBufferHandle> SetupNamedBuffer(
+ const std::string& name, size_t size, int producer_usage,
+ int consumer_usage);
template <class A>
void ForEachDisplaySurface(A action) const {
@@ -85,7 +87,8 @@
void OnSetViewerParams(pdx::Message& message,
const ViewerParams& view_params);
- pdx::LocalChannelHandle OnGetPoseBuffer(pdx::Message& message);
+ pdx::Status<BorrowedNativeBufferHandle> OnGetNamedBuffer(
+ pdx::Message& message, const std::string& name);
// Temporary query for current VR status. Will be removed later.
int IsVrAppRunning(pdx::Message& message);
@@ -102,7 +105,7 @@
HardwareComposer hardware_composer_;
DisplayConfigurationUpdateNotifier update_notifier_;
- std::unique_ptr<BufferProducer> pose_buffer_;
+ std::unordered_map<std::string, std::unique_ptr<IonBuffer>> named_buffers_;
};
} // namespace dvr
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 542bbd9..6602d78 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -1416,7 +1416,7 @@
void Layer::Prepare() {
int right, bottom;
- buffer_handle_t handle;
+ sp<GraphicBuffer> handle;
if (surface_) {
// Only update the acquired buffer when one is either available or this is
@@ -1465,14 +1465,14 @@
}
right = acquired_buffer_.buffer()->width();
bottom = acquired_buffer_.buffer()->height();
- handle = acquired_buffer_.buffer()->native_handle();
+ handle = acquired_buffer_.buffer()->buffer()->buffer();
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();
+ handle = direct_buffer_->buffer();
acquire_fence_fd_.Close();
}
diff --git a/libs/vr/libvrsensor/include/private/dvr/latency_model.h b/libs/vr/libvrsensor/include/private/dvr/latency_model.h
index 1bb3c4f..40b4638 100644
--- a/libs/vr/libvrsensor/include/private/dvr/latency_model.h
+++ b/libs/vr/libvrsensor/include/private/dvr/latency_model.h
@@ -6,23 +6,21 @@
namespace android {
namespace dvr {
-// This class holds a rolling average of the sensor latency.
+// This class models the latency from sensors. It will look at the first
+// window_size measurements and return their average after that.
class LatencyModel {
public:
- LatencyModel(size_t window_size, double weight_mass_in_window);
+ LatencyModel(size_t window_size);
~LatencyModel() = default;
void AddLatency(int64_t latency_ns);
- int64_t CurrentLatencyEstimate() const {
- return static_cast<int64_t>(rolling_average_);
- }
+ int64_t CurrentLatencyEstimate() const { return latency_; }
private:
- // The rolling average of the latencies.
- double rolling_average_ = 0;
-
- // The alpha parameter for an exponential moving average.
- double alpha_;
+ size_t window_size_;
+ int64_t latency_sum_ = 0;
+ size_t num_summed_ = 0;
+ int64_t latency_ = 0;
};
} // namespace dvr
diff --git a/libs/vr/libvrsensor/latency_model.cpp b/libs/vr/libvrsensor/latency_model.cpp
index 8233889..d3a4521 100644
--- a/libs/vr/libvrsensor/latency_model.cpp
+++ b/libs/vr/libvrsensor/latency_model.cpp
@@ -5,28 +5,19 @@
namespace android {
namespace dvr {
-LatencyModel::LatencyModel(size_t window_size, double weight_mass_in_window) {
- // Compute an alpha so the weight of the last window_size measurements is
- // weight_mass_in_window of the total weights.
-
- // The weight in a series of k measurements:
- // alpha + (1 + (1 - alpha) + (1 - alpha)^2 + ... (1 - alpha)^k-1)
- // = alpha x (1 - (1 - alpha) ^ k) / alpha
- // = 1 - (1 - alpha) ^ k
- // weight_mass_in_window = 1 - (1 - alpha) ^ k / lim_k->inf (1 - alpha) ^ k
- // weight_mass_in_window = 1 - (1 - alpha) ^ k / 1
- // 1 - weight_mass_in_window = (1 - alpha) ^ k
- // log(1 - weight_mass_in_window) = k * log(1 - alpha)
- // 10 ^ (log(1 - weight_mass_in_window) / k) = 1 - alpha
- // alpha = 1 - 10 ^ (log(1 - weight_mass_in_window) / k)
- // alpha = 1 - 10 ^ (log(1 - weight_mass_in_window) / window_size)
-
- alpha_ = 1 - std::pow(10.0, std::log10(1 - weight_mass_in_window) /
- static_cast<double>(window_size));
-}
+LatencyModel::LatencyModel(size_t window_size) : window_size_(window_size) {}
void LatencyModel::AddLatency(int64_t latency_ns) {
- rolling_average_ = latency_ns * alpha_ + rolling_average_ * (1 - alpha_);
+ // Not enough samples yet?
+ if (num_summed_ < window_size_) {
+ // Accumulate.
+ latency_sum_ += latency_ns;
+
+ // Have enough samples for latency estimate?
+ if (++num_summed_ == window_size_) {
+ latency_ = latency_sum_ / window_size_;
+ }
+ }
}
} // namespace dvr
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index bf831a7..d0996f0 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -627,19 +627,21 @@
#ifndef EGL_ANDROID_get_frame_timestamps
#define EGL_ANDROID_get_frame_timestamps 1
-#define EGL_TIMESTAMPS_ANDROID 0x314D
-#define EGL_COMPOSITE_DEADLINE_ANDROID 0x314E
-#define EGL_COMPOSITE_INTERVAL_ANDROID 0x314F
-#define EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3150
-#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3151
-#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3152
-#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3153
-#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3154
-#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3155
-#define EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3156
-#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3157
-#define EGL_DEQUEUE_READY_TIME_ANDROID 0x3158
-#define EGL_READS_DONE_TIME_ANDROID 0x3159
+#define EGL_TIMESTAMPS_ANDROID 0x3430
+#define EGL_COMPOSITE_DEADLINE_ANDROID 0x3431
+#define EGL_COMPOSITE_INTERVAL_ANDROID 0x3432
+#define EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3433
+#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3434
+#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3435
+#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3436
+#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3437
+#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3438
+#define EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3439
+#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x343A
+#define EGL_DEQUEUE_READY_TIME_ANDROID 0x343B
+#define EGL_READS_DONE_TIME_ANDROID 0x343C
+#define EGL_TIMESTAMP_PENDING_ANDROID EGL_CAST(EGLnsecsANDROID, -2)
+#define EGL_TIMESTAMP_INVALID_ANDROID EGL_CAST(EGLnsecsANDROID, -1)
#ifdef EGL_EGLEXT_PROTOTYPES
EGLAPI EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId);
EGLAPI EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface, EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values);
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 6a62e8d..a895e63 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -23,28 +23,28 @@
// The headers modules are in frameworks/native/opengl/Android.bp.
ndk_library {
- name: "libEGL.ndk",
+ name: "libEGL",
symbol_file: "libEGL.map.txt",
first_version: "9",
unversioned_until: "current",
}
ndk_library {
- name: "libGLESv1_CM.ndk",
+ name: "libGLESv1_CM",
symbol_file: "libGLESv1_CM.map.txt",
first_version: "9",
unversioned_until: "current",
}
ndk_library {
- name: "libGLESv2.ndk",
+ name: "libGLESv2",
symbol_file: "libGLESv2.map.txt",
first_version: "9",
unversioned_until: "current",
}
ndk_library {
- name: "libGLESv3.ndk",
+ name: "libGLESv3",
symbol_file: "libGLESv3.map.txt",
first_version: "18",
unversioned_until: "current",
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 683e6ca..7d20ba1 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -33,6 +33,10 @@
#include "egl_trace.h"
#include "egldefs.h"
+extern "C" {
+ android_namespace_t* android_get_exported_namespace(const char*);
+}
+
// ----------------------------------------------------------------------------
namespace android {
// ----------------------------------------------------------------------------
@@ -106,6 +110,11 @@
return dlopen(path, mode);
}
+static void* do_android_dlopen_ext(const char* path, int mode, const android_dlextinfo* info) {
+ ATRACE_CALL();
+ return android_dlopen_ext(path, mode, info);
+}
+
// ----------------------------------------------------------------------------
Loader::driver_t::driver_t(void* gles)
@@ -414,6 +423,27 @@
}
const char* const driver_absolute_path = absolutePath.c_str();
+ // Try to load drivers from the 'sphal' namespace, if it exist. Fall back to
+ // the original routine when the namespace does not exist or the load from
+ // the namespace fails.
+ // See /system/core/rootdir/etc/ld.config.txt for the configuration of the
+ // sphal namespace.
+ android_namespace_t* sphal_namespace = android_get_exported_namespace("sphal");
+ if (sphal_namespace != NULL) {
+ const android_dlextinfo dlextinfo = {
+ .flags = ANDROID_DLEXT_USE_NAMESPACE,
+ .library_namespace = sphal_namespace,
+ };
+ void* dso = do_android_dlopen_ext(driver_absolute_path, RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+ if (dso) {
+ ALOGD("loaded %s from sphal namespace", driver_absolute_path);
+ return dso;
+ }
+ else {
+ ALOGW("failed to load %s from sphal namespace: %s", driver_absolute_path, dlerror());
+ }
+ }
+
void* dso = do_dlopen(driver_absolute_path, RTLD_NOW | RTLD_LOCAL);
if (dso == 0) {
const char* err = dlerror();
@@ -426,11 +456,6 @@
return dso;
}
-static void* do_android_dlopen_ext(const char* path, int mode, const android_dlextinfo* info) {
- ATRACE_CALL();
- return android_dlopen_ext(path, mode, info);
-}
-
static const char* HAL_SUBNAME_KEY_PROPERTIES[2] = {
"ro.hardware.egl",
"ro.board.platform",
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index b00d401..0807d1f 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -2166,10 +2166,15 @@
case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID:
- case EGL_DISPLAY_PRESENT_TIME_ANDROID:
case EGL_DEQUEUE_READY_TIME_ANDROID:
case EGL_READS_DONE_TIME_ANDROID:
return EGL_TRUE;
+ case EGL_DISPLAY_PRESENT_TIME_ANDROID: {
+ int value = 0;
+ window->query(window,
+ NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &value);
+ return value == 0 ? EGL_FALSE : EGL_TRUE;
+ }
default:
return EGL_FALSE;
}
diff --git a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
index 61b9b66..b8a9add 100644
--- a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
+++ b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
@@ -28,7 +28,7 @@
Version
- Version 1, January 13, 2017
+ Version 8, April 11, 2017
Number
@@ -81,19 +81,21 @@
New Tokens
- EGL_TIMESTAMPS_ANDROID 0x314D
- EGL_COMPOSITE_DEADLINE_ANDROID 0x314E
- EGL_COMPOSITE_INTERVAL_ANDROID 0x314F
- EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3150
- EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3151
- EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3152
- EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3153
- EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3154
- EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3155
- EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3156
- EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3157
- EGL_DEQUEUE_READY_TIME_ANDROID 0x3158
- EGL_READS_DONE_TIME_ANDROID 0x3159
+ EGL_TIMESTAMPS_ANDROID 0x3430
+ EGL_COMPOSITE_DEADLINE_ANDROID 0x3431
+ EGL_COMPOSITE_INTERVAL_ANDROID 0x3432
+ EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3433
+ EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3434
+ EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3435
+ EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3436
+ EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3437
+ EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3438
+ EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3439
+ EGL_DISPLAY_PRESENT_TIME_ANDROID 0x343A
+ EGL_DEQUEUE_READY_TIME_ANDROID 0x343B
+ EGL_READS_DONE_TIME_ANDROID 0x343C
+ EGL_TIMESTAMP_PENDING_ANDROID -2
+ EGL_TIMESTAMP_INVALID_ANDROID -1
Add to the list of supported tokens for eglSurfaceAttrib in section 3.5.6
"Surface Attributes", page 43:
@@ -155,10 +157,12 @@
limited history of timestamp data. If a query is made for a frame whose
timestamp history no longer exists then EGL_BAD_ACCESS is generated. If
timestamp collection has not been enabled for the surface then
- EGL_BAD_SURFACE is generated. Timestamps for events that will not occur or
- have not yet occurred will be zero. Timestamp queries that are not
- supported will generate an EGL_BAD_PARAMETER error. If any error is
- generated the function will return EGL_FALSE.
+ EGL_BAD_SURFACE is generated. Timestamps for events that might still occur
+ will have the value EGL_TIMESTAMP_PENDING_ANDROID. Timestamps for events
+ that did not occur will have the value EGL_TIMESTAMP_INVALID_ANDROID.
+ Otherwise, the timestamp will be valid and indicate the event has occured.
+ Timestamp queries that are not supported will generate an EGL_BAD_PARAMETER
+ error. If any error is generated the function will return EGL_FALSE.
The application can poll for the timestamp of particular events by calling
eglGetFrameTimestamps over and over without needing to call any other EGL
@@ -222,6 +226,12 @@
Revision History
+#8 (Brian Anderson, April 11, 2017)
+ - Use reserved enumerant values.
+
+#7 (Brian Anderson, March 21, 2017)
+ - Differentiate between pending events and events that did not occur.
+
#6 (Brian Anderson, March 16, 2017)
- Remove DISPLAY_RETIRE_TIME_ANDROID.
diff --git a/opengl/specs/README b/opengl/specs/README
index e922740..cba4453 100644
--- a/opengl/specs/README
+++ b/opengl/specs/README
@@ -4,8 +4,14 @@
The table below tracks usage of EGL enumerant values that have been reserved
for use by Android extensions.
+See https://github.com/KhronosGroup/EGL-Registry/blob/master/api/egl.xml
+for a list of all enumarant values currently reserved and registered with
+Khronos.
+
Value Extension
----------------- ----------------------------------
+================ ==================================
+0x3140 - 0x314F Reserved block
+================ ==================================
0x3140 EGL_NATIVE_BUFFER_ANDROID (EGL_ANDROID_image_native_buffer)
0x3141 EGL_PLATFORM_ANDROID_KHR (KHR_platform_android)
0x3142 EGL_RECORDABLE_ANDROID (EGL_ANDROID_recordable)
@@ -18,17 +24,23 @@
0x314A EGL_IMAGE_CROP_RIGHT_ANDROID (EGL_ANDROID_image_crop)
0x314B EGL_IMAGE_CROP_BOTTOM_ANDROID (EGL_ANDROID_image_crop)
0x314C EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID (EGL_ANDROID_front_buffer_auto_refresh)
-0x314D EGL_TIMESTAMPS_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x314E EGL_COMPOSITE_DEADLINE_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x314F EGL_COMPOSITE_INTERVAL_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3150 EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3151 EGL_REQUESTED_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3152 EGL_RENDERING_COMPLETE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3153 EGL_COMPOSITION_LATCH_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3154 EGL_FIRST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3155 EGL_LAST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3156 EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3157 EGL_DISPLAY_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3158 EGL_DEQUEUE_READY_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3159 EGL_READS_DONE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x315A - 0x315F (unused)
+0x314D - 0x314F (unused)
+
+ Value Extension
+================ ==================================
+0x3430 - 0x343F Reserved block
+================ ==================================
+0x3430 EGL_TIMESTAMPS_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3431 EGL_COMPOSITE_DEADLINE_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3432 EGL_COMPOSITE_INTERVAL_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3433 EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3434 EGL_REQUESTED_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3435 EGL_RENDERING_COMPLETE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3436 EGL_COMPOSITION_LATCH_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3437 EGL_FIRST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3438 EGL_LAST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3439 EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x343A EGL_DISPLAY_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x343B EGL_DEQUEUE_READY_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x343C EGL_READS_DONE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x343D - 0x343F (unused)
diff --git a/opengl/tests/EGLTest/Android.mk b/opengl/tests/EGLTest/Android.mk
index b772450..5620496 100644
--- a/opengl/tests/EGLTest/Android.mk
+++ b/opengl/tests/EGLTest/Android.mk
@@ -12,12 +12,17 @@
EGL_test.cpp \
LOCAL_SHARED_LIBRARIES := \
+ android.hardware.configstore@1.0 \
+ android.hardware.configstore-utils \
libEGL \
libcutils \
libbinder \
+ libhidlbase \
+ libhidltransport \
libutils \
libgui \
libbase \
+ liblog \
LOCAL_C_INCLUDES := \
bionic/libc/private \
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
index 1b3086b..94de5af 100644
--- a/opengl/tests/EGLTest/EGL_test.cpp
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -16,6 +16,9 @@
#include <gtest/gtest.h>
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+
+#include <configstore/Utils.h>
#include <utils/String8.h>
#include <EGL/egl.h>
@@ -25,10 +28,31 @@
#include <gui/IGraphicBufferConsumer.h>
#include <gui/BufferQueue.h>
+#define PIXEL_FORMAT_FLOAT "EGL_EXT_pixel_format_float"
+
+bool hasEglPixelFormatFloat() {
+ EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
+ size_t cropExtLen = strlen(PIXEL_FORMAT_FLOAT);
+ size_t extsLen = strlen(exts);
+ bool equal = !strcmp(PIXEL_FORMAT_FLOAT, exts);
+ bool atStart = !strncmp(PIXEL_FORMAT_FLOAT " ", exts, cropExtLen + 1);
+ bool atEnd = (cropExtLen + 1) < extsLen &&
+ !strcmp(" " PIXEL_FORMAT_FLOAT, exts + extsLen - (cropExtLen + 1));
+ bool inMiddle = strstr(exts, " " PIXEL_FORMAT_FLOAT " ");
+ return equal || atStart || atEnd || inMiddle;
+}
+
namespace android {
#define EGL_UNSIGNED_TRUE static_cast<EGLBoolean>(EGL_TRUE)
+// retrieve wide-color setting from configstore
+using namespace android::hardware::configstore;
+
+static bool hasWideColorDisplay =
+ getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
+
class EGLTest : public ::testing::Test {
protected:
EGLDisplay mEglDisplay;
@@ -169,5 +193,75 @@
EXPECT_GE(components[3], 8);
}
+TEST_F(EGLTest, EGLConfigFP16) {
+ EGLint numConfigs;
+ EGLConfig config;
+ EGLBoolean success;
+ if (!hasWideColorDisplay) {
+ // skip this test if device does not have wide-color display
+ return;
+ }
+
+ ASSERT_TRUE(hasEglPixelFormatFloat());
+
+ EGLint attrs[] = {EGL_SURFACE_TYPE,
+ EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE,
+ EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE,
+ 16,
+ EGL_GREEN_SIZE,
+ 16,
+ EGL_BLUE_SIZE,
+ 16,
+ EGL_ALPHA_SIZE,
+ 16,
+ EGL_COLOR_COMPONENT_TYPE_EXT,
+ EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
+ EGL_NONE};
+ success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ ASSERT_EQ(1, numConfigs);
+
+ EGLint components[4];
+
+ success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+ EXPECT_GE(components[0], 16);
+ EXPECT_GE(components[1], 16);
+ EXPECT_GE(components[2], 16);
+ EXPECT_GE(components[3], 16);
+
+ struct DummyConsumer : public BnConsumerListener {
+ void onFrameAvailable(const BufferItem& /* item */) override {}
+ void onBuffersReleased() override {}
+ void onSidebandStreamChanged() override {}
+ };
+
+ // Create a EGLSurface
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ consumer->consumerConnect(new DummyConsumer, false);
+ sp<Surface> mSTC = new Surface(producer);
+ sp<ANativeWindow> mANW = mSTC;
+
+ EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_SURFACE, eglSurface);
+
+ EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
+}
}
diff --git a/services/schedulerservice/Android.bp b/services/schedulerservice/Android.bp
new file mode 100644
index 0000000..1f1340c
--- /dev/null
+++ b/services/schedulerservice/Android.bp
@@ -0,0 +1,25 @@
+cc_library_shared {
+ name: "libschedulerservicehidl",
+ srcs: [
+ "SchedulingPolicyService.cpp",
+ ],
+ shared_libs: [
+ "libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
+ "libmediautils",
+ "liblog",
+ "libutils",
+ "android.hidl.base@1.0",
+ "android.frameworks.schedulerservice@1.0",
+ ],
+ header_libs: [
+ "libcutils_headers",
+ ],
+ export_include_dirs: [
+ "include/"
+ ],
+ local_include_dirs: [
+ "include/schedulerservice/",
+ ],
+}
diff --git a/services/schedulerservice/SchedulingPolicyService.cpp b/services/schedulerservice/SchedulingPolicyService.cpp
new file mode 100644
index 0000000..1f6ed57
--- /dev/null
+++ b/services/schedulerservice/SchedulingPolicyService.cpp
@@ -0,0 +1,64 @@
+/*
+ * 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 "schedulerservicehidl"
+
+#include "SchedulingPolicyService.h"
+
+#include <log/log.h>
+#include <hwbinder/IPCThreadState.h>
+#include <mediautils/SchedulingPolicyService.h>
+
+namespace android {
+namespace frameworks {
+namespace schedulerservice {
+namespace V1_0 {
+namespace implementation {
+
+bool SchedulingPolicyService::isAllowed() {
+ // TODO(b/37291237)
+ return true;
+}
+
+Return<bool> SchedulingPolicyService::requestPriority(int32_t pid, int32_t tid, int32_t priority) {
+ if (priority < static_cast<int32_t>(Priority::MIN) ||
+ priority > static_cast<int32_t>(Priority::MAX)) {
+ return false;
+ }
+
+ if (!isAllowed()) {
+ return false;
+ }
+
+ // TODO(b/37226359): decouple from and remove AIDL service
+ // this should always be allowed since we are in system_server.
+ int value = ::android::requestPriority(pid, tid, priority, false /* isForApp */);
+ return value == 0 /* success */;
+}
+
+Return<int32_t> SchedulingPolicyService::getMaxAllowedPriority() {
+ if (!isAllowed()) {
+ return 0;
+ }
+
+ // TODO(b/37226359): decouple from and remove AIDL service
+ return 3;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace schedulerservice
+} // namespace frameworks
+} // namespace android
diff --git a/services/schedulerservice/include/schedulerservice/SchedulingPolicyService.h b/services/schedulerservice/include/schedulerservice/SchedulingPolicyService.h
new file mode 100644
index 0000000..7d1c478
--- /dev/null
+++ b/services/schedulerservice/include/schedulerservice/SchedulingPolicyService.h
@@ -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.
+ */
+#pragma once
+
+#include <android/frameworks/schedulerservice/1.0/ISchedulingPolicyService.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace frameworks {
+namespace schedulerservice {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::frameworks::schedulerservice::V1_0::ISchedulingPolicyService;
+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 SchedulingPolicyService : public ISchedulingPolicyService {
+ Return<bool> requestPriority(int32_t pid, int32_t tid, int32_t priority) override;
+ Return<int32_t> getMaxAllowedPriority() override;
+private:
+ bool isAllowed();
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace schedulerservice
+} // namespace frameworks
+} // namespace android
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 8fc4921..4d76272 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -13,23 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-#include <cutils/properties.h>
-
#include <binder/AppOpsManager.h>
#include <binder/BinderService.h>
#include <binder/IServiceManager.h>
#include <binder/PermissionCache.h>
-
#include <cutils/ashmem.h>
-#include <sensor/SensorEventQueue.h>
-
+#include <cutils/properties.h>
#include <hardware/sensors.h>
#include <hardware_legacy/power.h>
-
#include <openssl/digest.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>
+#include <sensor/SensorEventQueue.h>
+#include <utils/SystemClock.h>
#include "BatteryService.h"
#include "CorrectedGyroSensor.h"
@@ -77,7 +73,8 @@
#define SENSOR_SERVICE_SCHED_FIFO_PRIORITY 10
// Permissions.
-static const String16 sDump("android.permission.DUMP");
+static const String16 sDumpPermission("android.permission.DUMP");
+static const String16 sLocationHardwarePermission("android.permission.LOCATION_HARDWARE");
SensorService::SensorService()
: mInitCheck(NO_INIT), mSocketBufferSize(SOCKET_BUFFER_SIZE_NON_BATCHED),
@@ -319,7 +316,7 @@
status_t SensorService::dump(int fd, const Vector<String16>& args) {
String8 result;
- if (!PermissionCache::checkCallingPermission(sDump)) {
+ if (!PermissionCache::checkCallingPermission(sDumpPermission)) {
result.appendFormat("Permission Denial: can't dump SensorService from pid=%d, uid=%d\n",
IPCThreadState::self()->getCallingPid(),
IPCThreadState::self()->getCallingUid());
@@ -1032,6 +1029,84 @@
return conn;
}
+int SensorService::setOperationParameter(
+ int32_t type, const Vector<float> &floats, const Vector<int32_t> &ints) {
+ Mutex::Autolock _l(mLock);
+
+ // check permission
+ int32_t uid;
+ bool hasPermission = checkCallingPermission(sLocationHardwarePermission, nullptr, &uid);
+ if (!hasPermission || (uid != 1000 && uid != 0)) {
+ return PERMISSION_DENIED;
+ }
+
+ bool isFloat = true;
+ size_t expectSize = INT32_MAX;
+ switch (type) {
+ case AINFO_LOCAL_GEOMAGNETIC_FIELD:
+ isFloat = true;
+ expectSize = 3;
+ break;
+ case AINFO_LOCAL_GRAVITY:
+ isFloat = true;
+ expectSize = 1;
+ break;
+ case AINFO_DOCK_STATE:
+ case AINFO_HIGH_PERFORMANCE_MODE:
+ case AINFO_MAGNETIC_FIELD_CALIBRATION:
+ isFloat = false;
+ expectSize = 1;
+ break;
+ default:
+ return BAD_VALUE;
+ }
+
+ // three events: first one is begin tag, last one is end tag, the one in the middle
+ // is the payload.
+ sensors_event_t event[3];
+ int64_t timestamp = elapsedRealtimeNano();
+ for (sensors_event_t* i = event; i < event + 3; i++) {
+ *i = (sensors_event_t) {
+ .version = sizeof(sensors_event_t),
+ .sensor = 0,
+ .type = SENSOR_TYPE_ADDITIONAL_INFO,
+ .timestamp = timestamp++,
+ .additional_info = (additional_info_event_t) {
+ .serial = 0
+ }
+ };
+ }
+
+ event[0].additional_info.type = AINFO_BEGIN;
+ event[1].additional_info.type = type;
+ event[2].additional_info.type = AINFO_END;
+
+ if (isFloat) {
+ if (floats.size() != expectSize) {
+ return BAD_VALUE;
+ }
+ for (size_t i = 0; i < expectSize; ++i) {
+ event[1].additional_info.data_float[i] = floats[i];
+ }
+ } else {
+ if (ints.size() != expectSize) {
+ return BAD_VALUE;
+ }
+ for (size_t i = 0; i < expectSize; ++i) {
+ event[1].additional_info.data_int32[i] = ints[i];
+ }
+ }
+
+ SensorDevice& dev(SensorDevice::getInstance());
+ for (sensors_event_t* i = event; i < event + 3; i++) {
+ int ret = dev.injectSensorData(i);
+ if (ret != NO_ERROR) {
+ return ret;
+ }
+ }
+ return NO_ERROR;
+}
+
status_t SensorService::resetToNormalMode() {
Mutex::Autolock _l(mLock);
return resetToNormalModeLocked();
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index d0be121..2a9d6e8 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -158,6 +158,8 @@
virtual int isDataInjectionEnabled();
virtual sp<ISensorEventConnection> createSensorDirectConnection(const String16& opPackageName,
uint32_t size, int32_t type, int32_t format, const native_handle *resource);
+ virtual int setOperationParameter(
+ int32_t type, const Vector<float> &floats, const Vector<int32_t> &ints);
virtual status_t dump(int fd, const Vector<String16>& args);
String8 getSensorName(int handle) const;
diff --git a/services/sensorservice/hidl/DirectReportChannel.cpp b/services/sensorservice/hidl/DirectReportChannel.cpp
index 773ce8c..adc4675 100644
--- a/services/sensorservice/hidl/DirectReportChannel.cpp
+++ b/services/sensorservice/hidl/DirectReportChannel.cpp
@@ -31,10 +31,13 @@
}
// Methods from ::android::frameworks::sensorservice::V1_0::IDirectReportChannel follow.
-Return<Result> DirectReportChannel::configure(int32_t sensorHandle, RateLevel rate) {
+Return<void> DirectReportChannel::configure(int32_t sensorHandle, RateLevel rate,
+ configure_cb _hidl_cb) {
int token = mManager.configureDirectChannel(mId,
static_cast<int>(sensorHandle), static_cast<int>(rate));
- return token <= 0 ? convertResult(token) : Result::OK;
+ _hidl_cb(token <= 0 ? 0 : token,
+ token <= 0 ? convertResult(token) : Result::OK);
+ return Void();
}
diff --git a/services/sensorservice/hidl/DirectReportChannel.h b/services/sensorservice/hidl/DirectReportChannel.h
index 9134944..dd67827 100644
--- a/services/sensorservice/hidl/DirectReportChannel.h
+++ b/services/sensorservice/hidl/DirectReportChannel.h
@@ -47,7 +47,8 @@
~DirectReportChannel();
// Methods from ::android::frameworks::sensorservice::V1_0::IDirectReportChannel follow.
- Return<Result> configure(int32_t sensorHandle, RateLevel rate) override;
+ Return<void> configure(int32_t sensorHandle, RateLevel rate,
+ configure_cb _hidl_cb) override;
private:
::android::SensorManager& mManager;
diff --git a/services/sensorservice/hidl/EventQueue.cpp b/services/sensorservice/hidl/EventQueue.cpp
index 86d365c..c0365e5 100644
--- a/services/sensorservice/hidl/EventQueue.cpp
+++ b/services/sensorservice/hidl/EventQueue.cpp
@@ -39,7 +39,8 @@
while ((actual = internalQueue->read(&event, 1 /* count */)) > 0) {
internalQueue->sendAck(&event, actual);
- mCallback->onEvent(convertEvent(event));
+ Return<void> ret = mCallback->onEvent(convertEvent(event));
+ (void)ret.isOk(); // ignored
}
return 1; // continue to receive callbacks
diff --git a/services/sensorservice/hidl/SensorManager.cpp b/services/sensorservice/hidl/SensorManager.cpp
index 0743fc3..06ff95c 100644
--- a/services/sensorservice/hidl/SensorManager.cpp
+++ b/services/sensorservice/hidl/SensorManager.cpp
@@ -22,12 +22,14 @@
#include "SensorManager.h"
+#include <sched.h>
+
+#include <thread>
+
#include "EventQueue.h"
#include "DirectReportChannel.h"
#include "utils.h"
-#include <thread>
-
namespace android {
namespace frameworks {
namespace sensorservice {
@@ -131,6 +133,14 @@
std::condition_variable looperSet;
std::thread{[&mutex = mLooperMutex, &looper = mLooper, &looperSet] {
+
+ struct sched_param p = {0};
+ p.sched_priority = 10;
+ if (sched_setscheduler(0 /* current thread*/, SCHED_FIFO, &p) != 0) {
+ LOG(WARNING) << "Could not use SCHED_FIFO for looper thread: "
+ << strerror(errno);
+ }
+
std::unique_lock<std::mutex> lock(mutex);
looper = Looper::prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS /* opts */);
lock.unlock();
diff --git a/services/sensorservice/hidl/utils.cpp b/services/sensorservice/hidl/utils.cpp
index b540525..2f9e922 100644
--- a/services/sensorservice/hidl/utils.cpp
+++ b/services/sensorservice/hidl/utils.cpp
@@ -63,6 +63,8 @@
return Result::NO_MEMORY;
case NO_INIT:
return Result::NO_INIT;
+ case PERMISSION_DENIED:
+ return Result::PERMISSION_DENIED;
case BAD_VALUE:
return Result::BAD_VALUE;
case INVALID_OPERATION:
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index ebf72bc..7bb20ba 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -74,7 +74,7 @@
libvrflinger
LOCAL_SHARED_LIBRARIES := \
- android.dvr.composer@1.0 \
+ android.frameworks.vr.composer@1.0 \
android.hardware.graphics.allocator@2.0 \
android.hardware.graphics.composer@2.1 \
android.hardware.configstore@1.0 \
@@ -133,10 +133,15 @@
main_surfaceflinger.cpp
LOCAL_SHARED_LIBRARIES := \
+ android.hardware.configstore@1.0 \
+ android.hardware.configstore-utils \
+ android.hardware.graphics.allocator@2.0 \
libsurfaceflinger \
libcutils \
liblog \
libbinder \
+ libhidlbase \
+ libhidltransport \
libutils \
libui \
libgui \
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index c3b48ca..b5ffc60 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -80,6 +80,7 @@
uint32_t DisplayDevice::sPrimaryDisplayOrientation = 0;
+// clang-format off
DisplayDevice::DisplayDevice(
const sp<SurfaceFlinger>& flinger,
DisplayType type,
@@ -91,7 +92,8 @@
const wp<IBinder>& displayToken,
const sp<DisplaySurface>& displaySurface,
const sp<IGraphicBufferProducer>& producer,
- EGLConfig config)
+ EGLConfig config,
+ bool supportWideColor)
: lastCompositionHadVisibleLayers(false),
mFlinger(flinger),
mType(type),
@@ -113,12 +115,16 @@
mPowerMode(HWC_POWER_MODE_OFF),
mActiveConfig(0)
{
+ // clang-format on
Surface* surface;
mNativeWindow = surface = new Surface(producer, false);
ANativeWindow* const window = mNativeWindow.get();
#ifdef USE_HWC2
mActiveColorMode = static_cast<android_color_mode_t>(-1);
+ mDisplayHasWideColor = supportWideColor;
+#else
+ (void) supportWideColor;
#endif
/*
* Create our display's surface
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index caa7adc..e2852a7 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -83,6 +83,7 @@
NO_LAYER_STACK = 0xFFFFFFFF,
};
+ // clang-format off
DisplayDevice(
const sp<SurfaceFlinger>& flinger,
DisplayType type,
@@ -94,7 +95,9 @@
const wp<IBinder>& displayToken,
const sp<DisplaySurface>& displaySurface,
const sp<IGraphicBufferProducer>& producer,
- EGLConfig config);
+ EGLConfig config,
+ bool supportWideColor);
+ // clang-format on
~DisplayDevice();
@@ -146,6 +149,7 @@
status_t beginFrame(bool mustRecompose) const;
#ifdef USE_HWC2
status_t prepareFrame(HWComposer& hwc);
+ bool getWideColorSupport() const { return mDisplayHasWideColor; }
#else
status_t prepareFrame(const HWComposer& hwc) const;
#endif
@@ -264,6 +268,11 @@
#ifdef USE_HWC2
// current active color mode
android_color_mode_t mActiveColorMode;
+
+ // Need to know if display is wide-color capable or not.
+ // Initialized by SurfaceFlinger when the DisplayDevice is created.
+ // Fed to RenderEngine during composition.
+ bool mDisplayHasWideColor;
#endif
};
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index d9bddb5..262ab62 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -17,7 +17,6 @@
#undef LOG_TAG
#define LOG_TAG "HwcComposer"
-#include <android/dvr/composer/1.0/IVrComposerClient.h>
#include <inttypes.h>
#include <log/log.h>
#include <gui/BufferQueue.h>
@@ -26,7 +25,6 @@
namespace android {
-using dvr::composer::V1_0::IVrComposerClient;
using hardware::Return;
using hardware::hidl_vec;
using hardware::hidl_handle;
@@ -124,6 +122,41 @@
endCommand();
}
+void Composer::CommandWriter::setClientTargetMetadata(
+ const IVrComposerClient::BufferMetadata& metadata)
+{
+ constexpr uint16_t kSetClientTargetMetadataLength = 7;
+ beginCommand(
+ static_cast<IComposerClient::Command>(
+ IVrComposerClient::VrCommand::SET_CLIENT_TARGET_METADATA),
+ kSetClientTargetMetadataLength);
+ writeBufferMetadata(metadata);
+ endCommand();
+}
+
+void Composer::CommandWriter::setLayerBufferMetadata(
+ const IVrComposerClient::BufferMetadata& metadata)
+{
+ constexpr uint16_t kSetLayerBufferMetadataLength = 7;
+ beginCommand(
+ static_cast<IComposerClient::Command>(
+ IVrComposerClient::VrCommand::SET_LAYER_BUFFER_METADATA),
+ kSetLayerBufferMetadataLength);
+ writeBufferMetadata(metadata);
+ endCommand();
+}
+
+void Composer::CommandWriter::writeBufferMetadata(
+ const IVrComposerClient::BufferMetadata& metadata)
+{
+ write(metadata.width);
+ write(metadata.height);
+ write(metadata.stride);
+ write(metadata.layerCount);
+ writeSigned(static_cast<int32_t>(metadata.format));
+ write64(metadata.usage);
+}
+
Composer::Composer(bool useVrComposer)
: mWriter(kWriterInitialSize),
mIsUsingVrComposer(useVrComposer)
@@ -426,12 +459,29 @@
}
Error Composer::setClientTarget(Display display, uint32_t slot,
- const native_handle_t* target,
+ const sp<GraphicBuffer>& target,
int acquireFence, Dataspace dataspace,
const std::vector<IComposerClient::Rect>& damage)
{
mWriter.selectDisplay(display);
- mWriter.setClientTarget(slot, target, acquireFence, dataspace, damage);
+ if (mIsUsingVrComposer && target.get()) {
+ IVrComposerClient::BufferMetadata metadata = {
+ .width = target->getWidth(),
+ .height = target->getHeight(),
+ .stride = target->getStride(),
+ .layerCount = target->getLayerCount(),
+ .format = static_cast<PixelFormat>(target->getPixelFormat()),
+ .usage = target->getUsage(),
+ };
+ mWriter.setClientTargetMetadata(metadata);
+ }
+
+ const native_handle_t* handle = nullptr;
+ if (target.get()) {
+ handle = target->getNativeBuffer()->handle;
+ }
+
+ mWriter.setClientTarget(slot, handle, acquireFence, dataspace, damage);
return Error::NONE;
}
@@ -502,11 +552,28 @@
}
Error Composer::setLayerBuffer(Display display, Layer layer,
- uint32_t slot, const native_handle_t* buffer, int acquireFence)
+ uint32_t slot, const sp<GraphicBuffer>& buffer, int acquireFence)
{
mWriter.selectDisplay(display);
mWriter.selectLayer(layer);
- mWriter.setLayerBuffer(slot, buffer, acquireFence);
+ if (mIsUsingVrComposer && buffer.get()) {
+ IVrComposerClient::BufferMetadata metadata = {
+ .width = buffer->getWidth(),
+ .height = buffer->getHeight(),
+ .stride = buffer->getStride(),
+ .layerCount = buffer->getLayerCount(),
+ .format = static_cast<PixelFormat>(buffer->getPixelFormat()),
+ .usage = buffer->getUsage(),
+ };
+ mWriter.setLayerBufferMetadata(metadata);
+ }
+
+ const native_handle_t* handle = nullptr;
+ if (buffer.get()) {
+ handle = buffer->getNativeBuffer()->handle;
+ }
+
+ mWriter.setLayerBuffer(slot, handle, acquireFence);
return Error::NONE;
}
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 18af9dd..37b7766 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -23,6 +23,7 @@
#include <utility>
#include <vector>
+#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
#include <android/hardware/graphics/composer/2.1/IComposer.h>
#include <utils/StrongPointer.h>
#include <IComposerCommandBuffer.h>
@@ -31,6 +32,8 @@
namespace Hwc2 {
+using android::frameworks::vr::composer::V1_0::IVrComposerClient;
+
using android::hardware::graphics::common::V1_0::ColorMode;
using android::hardware::graphics::common::V1_0::ColorTransform;
using android::hardware::graphics::common::V1_0::Dataspace;
@@ -179,7 +182,7 @@
* When target is not nullptr, the cache is updated with the new target.
*/
Error setClientTarget(Display display, uint32_t slot,
- const native_handle_t* target,
+ const sp<GraphicBuffer>& target,
int acquireFence, Dataspace dataspace,
const std::vector<IComposerClient::Rect>& damage);
Error setColorMode(Display display, ColorMode mode);
@@ -199,7 +202,7 @@
int32_t x, int32_t y);
/* see setClientTarget for the purpose of slot */
Error setLayerBuffer(Display display, Layer layer, uint32_t slot,
- const native_handle_t* buffer, int acquireFence);
+ const sp<GraphicBuffer>& buffer, int acquireFence);
Error setLayerSurfaceDamage(Display display, Layer layer,
const std::vector<IComposerClient::Rect>& damage);
Error setLayerBlendMode(Display display, Layer layer,
@@ -232,6 +235,14 @@
~CommandWriter() override;
void setLayerInfo(uint32_t type, uint32_t appId);
+ void setClientTargetMetadata(
+ const IVrComposerClient::BufferMetadata& metadata);
+ void setLayerBufferMetadata(
+ const IVrComposerClient::BufferMetadata& metadata);
+
+ private:
+ void writeBufferMetadata(
+ const IVrComposerClient::BufferMetadata& metadata);
};
// Many public functions above simply write a command into the command
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index e49e734..8270c39 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -244,7 +244,7 @@
ALOGE("Failed to get display by id");
return Error::BadDisplay;
}
- (*outDisplay)->setVirtual();
+ (*outDisplay)->setConnected(true);
return Error::None;
}
@@ -531,15 +531,28 @@
: mDevice(device),
mId(id),
mIsConnected(false),
- mIsVirtual(false)
+ mType(DisplayType::Invalid)
{
ALOGV("Created display %" PRIu64, id);
+
+#ifdef BYPASS_IHWC
+ int32_t intError = mDevice.mGetDisplayType(mDevice.mHwcDevice, mId,
+ reinterpret_cast<int32_t *>(&mType));
+#else
+ auto intError = mDevice.mComposer->getDisplayType(mId,
+ reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(&mType));
+#endif
+ auto error = static_cast<Error>(intError);
+ if (error != Error::None) {
+ ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d)",
+ id, to_string(error).c_str(), intError);
+ }
}
Display::~Display()
{
ALOGV("Destroyed display %" PRIu64, mId);
- if (mIsVirtual) {
+ if (mType == DisplayType::Virtual) {
mDevice.destroyVirtualDisplay(mId);
}
}
@@ -802,21 +815,7 @@
Error Display::getType(DisplayType* outType) const
{
-#ifdef BYPASS_IHWC
- int32_t intType = 0;
- int32_t intError = mDevice.mGetDisplayType(mDevice.mHwcDevice, mId,
- &intType);
-#else
- Hwc2::IComposerClient::DisplayType intType =
- Hwc2::IComposerClient::DisplayType::INVALID;
- auto intError = mDevice.mComposer->getDisplayType(mId, &intType);
-#endif
- auto error = static_cast<Error>(intError);
- if (error != Error::None) {
- return error;
- }
-
- *outType = static_cast<DisplayType>(intType);
+ *outType = mType;
return Error::None;
}
@@ -961,14 +960,19 @@
return static_cast<Error>(intError);
}
-Error Display::setClientTarget(uint32_t slot, buffer_handle_t target,
+Error Display::setClientTarget(uint32_t slot, const sp<GraphicBuffer>& target,
const sp<Fence>& acquireFence, android_dataspace_t dataspace)
{
// TODO: Properly encode client target surface damage
int32_t fenceFd = acquireFence->dup();
#ifdef BYPASS_IHWC
(void) slot;
- int32_t intError = mDevice.mSetClientTarget(mDevice.mHwcDevice, mId, target,
+ buffer_handle_t handle = nullptr;
+ if (target.get() && target->getNativeBuffer()) {
+ handle = target->getNativeBuffer()->handle;
+ }
+
+ int32_t intError = mDevice.mSetClientTarget(mDevice.mHwcDevice, mId, handle,
fenceFd, static_cast<int32_t>(dataspace), {0, nullptr});
#else
auto intError = mDevice.mComposer->setClientTarget(mId, slot, target,
@@ -1195,14 +1199,19 @@
return static_cast<Error>(intError);
}
-Error Layer::setBuffer(uint32_t slot, buffer_handle_t buffer,
+Error Layer::setBuffer(uint32_t slot, const sp<GraphicBuffer>& buffer,
const sp<Fence>& acquireFence)
{
int32_t fenceFd = acquireFence->dup();
#ifdef BYPASS_IHWC
(void) slot;
+ buffer_handle_t handle = nullptr;
+ if (buffer.get() && buffer->getNativeBuffer()) {
+ handle = buffer->getNativeBuffer()->handle;
+ }
+
int32_t intError = mDevice.mSetLayerBuffer(mDevice.mHwcDevice, mDisplayId,
- mId, buffer, fenceFd);
+ mId, handle, fenceFd);
#else
auto intError = mDevice.mComposer->setLayerBuffer(mDisplayId,
mId, slot, buffer, fenceFd);
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 4419dc1..643b1e0 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -329,7 +329,7 @@
[[clang::warn_unused_result]] Error setActiveConfig(
const std::shared_ptr<const Config>& config);
[[clang::warn_unused_result]] Error setClientTarget(
- uint32_t slot, buffer_handle_t target,
+ uint32_t slot, const android::sp<android::GraphicBuffer>& target,
const android::sp<android::Fence>& acquireFence,
android_dataspace_t dataspace);
[[clang::warn_unused_result]] Error setColorMode(android_color_mode_t mode);
@@ -352,12 +352,6 @@
private:
// For use by Device
- // Virtual displays are always connected
- void setVirtual() {
- mIsVirtual = true;
- mIsConnected = true;
- }
-
void setConnected(bool connected) { mIsConnected = connected; }
int32_t getAttribute(hwc2_config_t configId, Attribute attribute);
void loadConfig(hwc2_config_t configId);
@@ -375,7 +369,7 @@
Device& mDevice;
hwc2_display_t mId;
bool mIsConnected;
- bool mIsVirtual;
+ DisplayType mType;
std::unordered_map<hwc2_layer_t, std::weak_ptr<Layer>> mLayers;
std::unordered_map<hwc2_config_t, std::shared_ptr<const Config>> mConfigs;
};
@@ -392,7 +386,7 @@
[[clang::warn_unused_result]] Error setCursorPosition(int32_t x, int32_t y);
[[clang::warn_unused_result]] Error setBuffer(uint32_t slot,
- buffer_handle_t buffer,
+ const android::sp<android::GraphicBuffer>& buffer,
const android::sp<android::Fence>& acquireFence);
[[clang::warn_unused_result]] Error setSurfaceDamage(
const android::Region& damage);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 09434f6..40979c9 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -206,7 +206,7 @@
}
disp = DisplayDevice::DISPLAY_EXTERNAL;
}
- mEventHandler->onHotplugReceived(disp,
+ mEventHandler->onHotplugReceived(this, disp,
connected == HWC2::Connection::Connected);
}
@@ -465,12 +465,7 @@
ALOGV("setClientTarget for display %d", displayId);
auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
- buffer_handle_t handle = nullptr;
- if ((target != nullptr) && target->getNativeBuffer()) {
- handle = target->getNativeBuffer()->handle;
- }
- auto error = hwcDisplay->setClientTarget(slot, handle,
- acquireFence, dataspace);
+ auto error = hwcDisplay->setClientTarget(slot, target, acquireFence, dataspace);
if (error != HWC2::Error::None) {
ALOGE("Failed to set client target for display %d: %s (%d)", displayId,
to_string(error).c_str(), static_cast<int32_t>(error));
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 81f1619..78d0307 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -70,7 +70,7 @@
friend class HWComposer;
virtual void onVSyncReceived(
HWComposer* composer, int32_t disp, nsecs_t timestamp) = 0;
- virtual void onHotplugReceived(int32_t disp, bool connected) = 0;
+ virtual void onHotplugReceived(HWComposer* composer, int32_t disp, bool connected) = 0;
virtual void onInvalidateReceived(HWComposer* composer) = 0;
protected:
virtual ~EventHandler() {}
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
index 5b5f1cf..dcb2913 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
@@ -315,7 +315,7 @@
queryDisplayProperties(disp);
// Do not teardown or recreate the primary display
if (disp != HWC_DISPLAY_PRIMARY) {
- mEventHandler.onHotplugReceived(disp, bool(connected));
+ mEventHandler.onHotplugReceived(this, disp, bool(connected));
}
}
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
index f64d69a..4bc63bb 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
@@ -62,7 +62,7 @@
friend class HWComposer;
virtual void onVSyncReceived(
HWComposer* composer, int32_t disp, nsecs_t timestamp) = 0;
- virtual void onHotplugReceived(int disp, bool connected) = 0;
+ virtual void onHotplugReceived(HWComposer* composer, int disp, bool connected) = 0;
virtual void onInvalidateReceived(HWComposer* composer) = 0;
protected:
virtual ~EventHandler() {}
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index 486bce4..a9bb2ba 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -21,7 +21,6 @@
#include <cutils/compiler.h>
-#include <private/gui/BitTube.h>
#include <gui/IDisplayEventConnection.h>
#include <gui/DisplayEventReceiver.h>
@@ -389,7 +388,7 @@
EventThread::Connection::Connection(
const sp<EventThread>& eventThread)
- : count(-1), mEventThread(eventThread), mChannel(new BitTube())
+ : count(-1), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize)
{
}
@@ -403,12 +402,14 @@
mEventThread->registerDisplayEventConnection(this);
}
-sp<BitTube> EventThread::Connection::getDataChannel() const {
- return mChannel;
+status_t EventThread::Connection::stealReceiveChannel(gui::BitTube* outChannel) {
+ outChannel->setReceiveFd(mChannel.moveReceiveFd());
+ return NO_ERROR;
}
-void EventThread::Connection::setVsyncRate(uint32_t count) {
+status_t EventThread::Connection::setVsyncRate(uint32_t count) {
mEventThread->setVsyncRate(count, this);
+ return NO_ERROR;
}
void EventThread::Connection::requestNextVsync() {
@@ -417,7 +418,7 @@
status_t EventThread::Connection::postEvent(
const DisplayEventReceiver::Event& event) {
- ssize_t size = DisplayEventReceiver::sendEvents(mChannel, &event, 1);
+ ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
return size < 0 ? status_t(size) : status_t(NO_ERROR);
}
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index 3f1d0bb..6a59fbb 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -20,6 +20,7 @@
#include <stdint.h>
#include <sys/types.h>
+#include <private/gui/BitTube.h>
#include <gui/DisplayEventReceiver.h>
#include <gui/IDisplayEventConnection.h>
@@ -68,11 +69,11 @@
private:
virtual ~Connection();
virtual void onFirstRef();
- virtual sp<BitTube> getDataChannel() const;
- virtual void setVsyncRate(uint32_t count);
- virtual void requestNextVsync(); // asynchronous
+ status_t stealReceiveChannel(gui::BitTube* outChannel) override;
+ status_t setVsyncRate(uint32_t count) override;
+ void requestNextVsync() override; // asynchronous
sp<EventThread> const mEventThread;
- sp<BitTube> const mChannel;
+ gui::BitTube mChannel;
};
public:
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 16d8160..027fae6 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -852,18 +852,12 @@
}
uint32_t hwcSlot = 0;
- buffer_handle_t hwcHandle = nullptr;
- {
- sp<GraphicBuffer> hwcBuffer;
- hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer,
- &hwcSlot, &hwcBuffer);
- if (hwcBuffer != nullptr) {
- hwcHandle = hwcBuffer->handle;
- }
- }
+ sp<GraphicBuffer> hwcBuffer;
+ hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer,
+ &hwcSlot, &hwcBuffer);
auto acquireFence = mSurfaceFlingerConsumer->getCurrentFence();
- error = hwcLayer->setBuffer(hwcSlot, hwcHandle, acquireFence);
+ error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence);
if (error != HWC2::Error::None) {
ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(),
mActiveBuffer->handle, to_string(error).c_str(),
@@ -1011,6 +1005,9 @@
return inverse(tr);
}
+/*
+ * onDraw will draw the current layer onto the presentable buffer
+ */
void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
bool useIdentityTransform) const
{
@@ -1172,6 +1169,9 @@
RenderEngine& engine(mFlinger->getRenderEngine());
engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), getAlpha());
+#ifdef USE_HWC2
+ engine.setSourceDataSpace(mCurrentState.dataSpace);
+#endif
engine.drawMesh(mMesh);
engine.disableBlending();
}
@@ -1713,10 +1713,55 @@
mCurrentState.sequence++;
mCurrentState.z = z;
mCurrentState.modified = true;
+
+ // Discard all relative layering.
+ if (mCurrentState.zOrderRelativeOf != nullptr) {
+ sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
+ if (strongRelative != nullptr) {
+ strongRelative->removeZOrderRelative(this);
+ }
+ mCurrentState.zOrderRelativeOf = nullptr;
+ }
setTransactionFlags(eTransactionNeeded);
return true;
}
+void Layer::removeZOrderRelative(const wp<Layer>& relative) {
+ mCurrentState.zOrderRelatives.remove(relative);
+ mCurrentState.sequence++;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+}
+
+void Layer::addZOrderRelative(const wp<Layer>& relative) {
+ mCurrentState.zOrderRelatives.add(relative);
+ mCurrentState.modified = true;
+ mCurrentState.sequence++;
+ setTransactionFlags(eTransactionNeeded);
+}
+
+bool Layer::setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t z) {
+ sp<Handle> handle = static_cast<Handle*>(relativeToHandle.get());
+ if (handle == nullptr) {
+ return false;
+ }
+ sp<Layer> relative = handle->owner.promote();
+ if (relative == nullptr) {
+ return false;
+ }
+
+ mCurrentState.sequence++;
+ mCurrentState.modified = true;
+ mCurrentState.z = z;
+
+ mCurrentState.zOrderRelativeOf = relative;
+ relative->addZOrderRelative(this);
+
+ setTransactionFlags(eTransactionNeeded);
+
+ return true;
+}
+
bool Layer::setSize(uint32_t w, uint32_t h) {
if (mCurrentState.requested.w == w && mCurrentState.requested.h == h)
return false;
@@ -2500,40 +2545,70 @@
return mDrawingState.z;
}
+LayerVector Layer::makeTraversalList() {
+ if (mDrawingState.zOrderRelatives.size() == 0) {
+ return mDrawingChildren;
+ }
+ LayerVector traverse;
+
+ for (const wp<Layer>& weakRelative : mDrawingState.zOrderRelatives) {
+ sp<Layer> strongRelative = weakRelative.promote();
+ if (strongRelative != nullptr) {
+ traverse.add(strongRelative);
+ } else {
+ // We need to erase from current state instead of drawing
+ // state so we don't overwrite when copying
+ // the current state to the drawing state.
+ mCurrentState.zOrderRelatives.remove(weakRelative);
+ }
+ }
+
+ for (const sp<Layer>& child : mDrawingChildren) {
+ traverse.add(child);
+ }
+
+ return traverse;
+}
+
/**
- * Negatively signed children are before 'this' in Z-order.
+ * Negatively signed relatives are before 'this' in Z-order.
*/
void Layer::traverseInZOrder(const std::function<void(Layer*)>& exec) {
+ LayerVector list = makeTraversalList();
+
size_t i = 0;
- for (; i < mDrawingChildren.size(); i++) {
- const auto& child = mDrawingChildren[i];
- if (child->getZ() >= 0)
+ for (; i < list.size(); i++) {
+ const auto& relative = list[i];
+ if (relative->getZ() >= 0) {
break;
- child->traverseInZOrder(exec);
+ }
+ relative->traverseInZOrder(exec);
}
exec(this);
- for (; i < mDrawingChildren.size(); i++) {
- const auto& child = mDrawingChildren[i];
- child->traverseInZOrder(exec);
+ for (; i < list.size(); i++) {
+ const auto& relative = list[i];
+ relative->traverseInZOrder(exec);
}
}
/**
- * Positively signed children are before 'this' in reverse Z-order.
+ * Positively signed relatives are before 'this' in reverse Z-order.
*/
void Layer::traverseInReverseZOrder(const std::function<void(Layer*)>& exec) {
+ LayerVector list = makeTraversalList();
+
int32_t i = 0;
- for (i = mDrawingChildren.size()-1; i>=0; i--) {
- const auto& child = mDrawingChildren[i];
- if (child->getZ() < 0) {
+ for (i = list.size()-1; i>=0; i--) {
+ const auto& relative = list[i];
+ if (relative->getZ() < 0) {
break;
}
- child->traverseInReverseZOrder(exec);
+ relative->traverseInReverseZOrder(exec);
}
exec(this);
for (; i>=0; i--) {
- const auto& child = mDrawingChildren[i];
- child->traverseInReverseZOrder(exec);
+ const auto& relative = list[i];
+ relative->traverseInReverseZOrder(exec);
}
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index e21be8b..a5224ec 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -151,6 +151,12 @@
uint32_t appId;
uint32_t type;
+
+ // If non-null, a Surface this Surface's Z-order is interpreted relative to.
+ wp<Layer> zOrderRelativeOf;
+
+ // A list of surfaces whose Z-order is interpreted relative to ours.
+ SortedVector<wp<Layer>> zOrderRelatives;
};
// -----------------------------------------------------------------------
@@ -173,6 +179,8 @@
bool setFinalCrop(const Rect& crop, bool immediate);
bool setLayer(int32_t z);
+ bool setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ);
+
bool setSize(uint32_t w, uint32_t h);
#ifdef USE_HWC2
bool setAlpha(float alpha);
@@ -549,6 +557,10 @@
void setParent(const sp<Layer>& layer);
+ LayerVector makeTraversalList();
+ void addZOrderRelative(const wp<Layer>& relative);
+ void removeZOrderRelative(const wp<Layer>& relative);
+
// -----------------------------------------------------------------------
class SyncPoint
diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp
index 7ba6ad3..90e6395 100644
--- a/services/surfaceflinger/LayerVector.cpp
+++ b/services/surfaceflinger/LayerVector.cpp
@@ -42,13 +42,21 @@
void LayerVector::traverseInZOrder(const std::function<void(Layer*)>& consume) const {
for (size_t i = 0; i < size(); i++) {
- (*this)[i]->traverseInZOrder(consume);
+ const auto& layer = (*this)[i];
+ if (layer->getDrawingState().zOrderRelativeOf != nullptr) {
+ continue;
+ }
+ layer->traverseInZOrder(consume);
}
}
void LayerVector::traverseInReverseZOrder(const std::function<void(Layer*)>& consume) const {
for (auto i = static_cast<int64_t>(size()) - 1; i >= 0; i--) {
- (*this)[i]->traverseInReverseZOrder(consume);
+ const auto& layer = (*this)[i];
+ if (layer->getDrawingState().zOrderRelativeOf != nullptr) {
+ continue;
+ }
+ layer->traverseInReverseZOrder(consume);
}
}
} // namespace android
diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index debea58..bca3430 100644
--- a/services/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
@@ -25,7 +25,6 @@
#include <utils/Log.h>
#include <gui/IDisplayEventConnection.h>
-#include <private/gui/BitTube.h>
#include "MessageQueue.h"
#include "EventThread.h"
@@ -94,8 +93,8 @@
{
mEventThread = eventThread;
mEvents = eventThread->createEventConnection();
- mEventTube = mEvents->getDataChannel();
- mLooper->addFd(mEventTube->getFd(), 0, Looper::EVENT_INPUT,
+ mEvents->stealReceiveChannel(&mEventTube);
+ mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT,
MessageQueue::cb_eventReceiver, this);
}
@@ -150,7 +149,7 @@
int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {
ssize_t n;
DisplayEventReceiver::Event buffer[8];
- while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {
+ while ((n = DisplayEventReceiver::getEvents(&mEventTube, buffer, 8)) > 0) {
for (int i=0 ; i<n ; i++) {
if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
mHandler->dispatchInvalidate();
diff --git a/services/surfaceflinger/MessageQueue.h b/services/surfaceflinger/MessageQueue.h
index aed0aa9..85a33c8 100644
--- a/services/surfaceflinger/MessageQueue.h
+++ b/services/surfaceflinger/MessageQueue.h
@@ -25,6 +25,7 @@
#include <utils/Timers.h>
#include <utils/Looper.h>
+#include <private/gui/BitTube.h>
#include <gui/DisplayEventReceiver.h>
#include "Barrier.h"
@@ -81,7 +82,7 @@
sp<Looper> mLooper;
sp<EventThread> mEventThread;
sp<IDisplayEventConnection> mEvents;
- sp<BitTube> mEventTube;
+ gui::BitTube mEventTube;
sp<Handler> mHandler;
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 406e611..04fe182 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -14,11 +14,16 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "RenderEngine"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
+#include <ui/ColorSpace.h>
+#include <ui/DebugUtils.h>
#include <ui/Rect.h>
#include <utils/String8.h>
@@ -35,6 +40,73 @@
#include "Mesh.h"
#include "Texture.h"
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <configstore/Utils.h>
+
+#include <fstream>
+
+// ---------------------------------------------------------------------------
+#ifdef USE_HWC2
+bool checkGlError(const char* op, int lineNumber) {
+ bool errorFound = false;
+ GLint error = glGetError();
+ while (error != GL_NO_ERROR) {
+ errorFound = true;
+ error = glGetError();
+ ALOGV("after %s() (line # %d) glError (0x%x)\n", op, lineNumber, error);
+ }
+ return errorFound;
+}
+
+static constexpr bool outputDebugPPMs = false;
+
+void writePPM(const char* basename, GLuint width, GLuint height) {
+ ALOGV("writePPM #%s: %d x %d", basename, width, height);
+
+ std::vector<GLubyte> pixels(width * height * 4);
+ std::vector<GLubyte> outBuffer(width * height * 3);
+
+ // TODO(courtneygo): We can now have float formats, need
+ // to remove this code or update to support.
+ // Make returned pixels fit in uint32_t, one byte per component
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
+ if (checkGlError(__FUNCTION__, __LINE__)) {
+ return;
+ }
+
+ std::string filename(basename);
+ filename.append(".ppm");
+ std::ofstream file(filename.c_str(), std::ios::binary);
+ if (!file.is_open()) {
+ ALOGE("Unable to open file: %s", filename.c_str());
+ ALOGE("You may need to do: \"adb shell setenforce 0\" to enable "
+ "surfaceflinger to write debug images");
+ return;
+ }
+
+ file << "P6\n";
+ file << width << "\n";
+ file << height << "\n";
+ file << 255 << "\n";
+
+ auto ptr = reinterpret_cast<char*>(pixels.data());
+ auto outPtr = reinterpret_cast<char*>(outBuffer.data());
+ for (int y = height - 1; y >= 0; y--) {
+ char* data = ptr + y * width * sizeof(uint32_t);
+
+ for (GLuint x = 0; x < width; x++) {
+ // Only copy R, G and B components
+ outPtr[0] = data[0];
+ outPtr[1] = data[1];
+ outPtr[2] = data[2];
+ data += sizeof(uint32_t);
+ outPtr += 3;
+ }
+ }
+ file.write(reinterpret_cast<char*>(outBuffer.data()), outBuffer.size());
+}
+#endif
+
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
@@ -59,6 +131,28 @@
GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData);
//mColorBlindnessCorrection = M;
+
+#ifdef USE_HWC2
+ // retrieve wide-color and hdr settings from configstore
+ using namespace android::hardware::configstore;
+ using namespace android::hardware::configstore::V1_0;
+
+ mPlatformHasWideColor =
+ getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
+ if (mPlatformHasWideColor) {
+ // Compute sRGB to DisplayP3 color transform
+ // NOTE: For now, we are limiting wide-color support to
+ // Display-P3 only.
+ mat3 srgbToP3 = ColorSpace::DisplayP3().getXYZtoRGB() * ColorSpace::sRGB().getRGBtoXYZ();
+
+ // color transform needs to be transposed and expanded to 4x4
+ // to be what the shader wants
+ // mat has an initializer that expands mat3 to mat4, but
+ // not an assignment operator
+ mat4 gamutTransform(transpose(srgbToP3));
+ mSrgbToDisplayP3 = gamutTransform;
+ }
+#endif
}
GLES20RenderEngine::~GLES20RenderEngine() {
@@ -170,6 +264,42 @@
}
}
+#ifdef USE_HWC2
+void GLES20RenderEngine::setColorMode(android_color_mode mode) {
+ ALOGV("setColorMode: %s (0x%x)", decodeColorMode(mode).c_str(), mode);
+
+ if (mColorMode == mode) return;
+
+ if (!mPlatformHasWideColor || !mDisplayHasWideColor || mode == HAL_COLOR_MODE_SRGB ||
+ mode == HAL_COLOR_MODE_NATIVE) {
+ // We are returning back to our default color_mode
+ mUseWideColor = false;
+ mWideColorFrameCount = 0;
+ } else {
+ mUseWideColor = true;
+ }
+
+ mColorMode = mode;
+}
+
+void GLES20RenderEngine::setSourceDataSpace(android_dataspace source) {
+ if (source == HAL_DATASPACE_UNKNOWN) {
+ // Treat UNKNOWN as SRGB
+ source = HAL_DATASPACE_V0_SRGB;
+ }
+ mDataSpace = source;
+}
+
+void GLES20RenderEngine::setWideColor(bool hasWideColor) {
+ ALOGV("setWideColor: %s", hasWideColor ? "true" : "false");
+ mDisplayHasWideColor = hasWideColor;
+}
+
+bool GLES20RenderEngine::usesWideColor() {
+ return mUseWideColor;
+}
+#endif
+
void GLES20RenderEngine::setupLayerTexturing(const Texture& texture) {
GLuint target = texture.getTextureTarget();
glBindTexture(target, texture.getTextureName());
@@ -242,8 +372,6 @@
void GLES20RenderEngine::drawMesh(const Mesh& mesh) {
- ProgramCache::getInstance().useProgram(mState);
-
if (mesh.getTexCoordsSize()) {
glEnableVertexAttribArray(Program::texCoords);
glVertexAttribPointer(Program::texCoords,
@@ -259,7 +387,32 @@
mesh.getByteStride(),
mesh.getPositions());
+#ifdef USE_HWC2
+ if (usesWideColor()) {
+ Description wideColorState = mState;
+ if (mDataSpace != HAL_DATASPACE_DISPLAY_P3) {
+ wideColorState.setColorMatrix(mState.getColorMatrix() * mSrgbToDisplayP3);
+ ALOGV("drawMesh: gamut transform applied");
+ }
+ ProgramCache::getInstance().useProgram(wideColorState);
+
+ glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
+
+ if (outputDebugPPMs) {
+ std::ostringstream out;
+ out << "/data/texture_out" << mWideColorFrameCount++;
+ writePPM(out.str().c_str(), mVpWidth, mVpHeight);
+ }
+ } else {
+ ProgramCache::getInstance().useProgram(mState);
+
+ glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
+ }
+#else
+ ProgramCache::getInstance().useProgram(mState);
+
glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
+#endif
if (mesh.getTexCoordsSize()) {
glDisableVertexAttribArray(Program::texCoords);
@@ -268,6 +421,13 @@
void GLES20RenderEngine::dump(String8& result) {
RenderEngine::dump(result);
+#ifdef USE_HWC2
+ if (usesWideColor()) {
+ result.append("Wide-color: On\n");
+ } else {
+ result.append("Wide-color: Off\n");
+ }
+#endif
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index 7c3f9b5..19cbb60 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -72,6 +72,27 @@
virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque,
float alpha) override;
virtual void setupDimLayerBlending(float alpha) override;
+
+ // Color management related functions and state
+ void setColorMode(android_color_mode mode);
+ void setSourceDataSpace(android_dataspace source);
+ void setWideColor(bool hasWideColor);
+ bool usesWideColor();
+
+ // Current color mode of display using the render engine
+ android_color_mode mColorMode = HAL_COLOR_MODE_NATIVE;
+
+ // Current dataspace of layer being rendered
+ android_dataspace mDataSpace = HAL_DATASPACE_V0_SRGB;
+
+ // Indicate if wide-color mode is needed or not
+ bool mPlatformHasWideColor = false;
+ bool mDisplayHasWideColor = false;
+ bool mUseWideColor = false;
+ uint64_t mWideColorFrameCount = 0;
+
+ // Currently only supporting sRGB and DisplayP3 color spaces
+ mat4 mSrgbToDisplayP3;
#else
virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque,
int alpha);
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index d19137b..8b031bc 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -98,6 +98,10 @@
#ifdef USE_HWC2
virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, float alpha) = 0;
virtual void setupDimLayerBlending(float alpha) = 0;
+ virtual void setColorMode(android_color_mode mode) = 0;
+ virtual void setSourceDataSpace(android_dataspace source) = 0;
+ virtual void setWideColor(bool hasWideColor) = 0;
+ virtual bool usesWideColor() = 0;
#else
virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha) = 0;
virtual void setupDimLayerBlending(int alpha) = 0;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 834c1c4..18a7818 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -37,6 +37,7 @@
#include <dvr/vr_flinger.h>
+#include <ui/DebugUtils.h>
#include <ui/DisplayInfo.h>
#include <ui/DisplayStatInfo.h>
@@ -119,6 +120,7 @@
bool SurfaceFlinger::hasSyncFramework;
bool SurfaceFlinger::useVrFlinger;
int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers;
+bool SurfaceFlinger::hasWideColorDisplay;
SurfaceFlinger::SurfaceFlinger()
: BnSurfaceComposer(),
@@ -189,6 +191,9 @@
maxFrameBufferAcquiredBuffers = getInt64< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::maxFrameBufferAcquiredBuffers>(2);
+ hasWideColorDisplay =
+ getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
+
// debugging stuff...
char value[PROPERTY_VALUE_MAX];
@@ -573,6 +578,14 @@
Mutex::Autolock _l(mStateLock);
+ // Inform native graphics APIs whether the present timestamp is supported:
+ if (getHwComposer().hasCapability(
+ HWC2::Capability::PresentFenceIsNotReliable)) {
+ property_set(kTimestampProperty, "0");
+ } else {
+ property_set(kTimestampProperty, "1");
+ }
+
if (useVrFlinger) {
auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) {
mVrFlingerRequestsDisplay = requestDisplay;
@@ -593,7 +606,7 @@
// make the GLContext current so that we can create textures when creating
// Layers (which may happens before we render something)
- getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
+ getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext);
mEventControlThread = new EventControlThread(this);
mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
@@ -646,6 +659,25 @@
return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0;
}
+status_t SurfaceFlinger::getSupportedFrameTimestamps(
+ std::vector<FrameEvent>* outSupported) const {
+ *outSupported = {
+ FrameEvent::REQUESTED_PRESENT,
+ FrameEvent::ACQUIRE,
+ FrameEvent::LATCH,
+ FrameEvent::FIRST_REFRESH_START,
+ FrameEvent::LAST_REFRESH_START,
+ FrameEvent::GPU_COMPOSITION_DONE,
+ FrameEvent::DEQUEUE_READY,
+ FrameEvent::RELEASE,
+ };
+ if (!getHwComposer().hasCapability(
+ HWC2::Capability::PresentFenceIsNotReliable)) {
+ outSupported->push_back(FrameEvent::DISPLAY_PRESENT);
+ }
+ return NO_ERROR;
+}
+
status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
Vector<DisplayInfo>* configs) {
if ((configs == NULL) || (display.get() == NULL)) {
@@ -709,8 +741,11 @@
info.density = density;
// TODO: this needs to go away (currently needed only by webkit)
- sp<const DisplayDevice> hw(getDefaultDisplayDevice());
- info.orientation = hw->getOrientation();
+ {
+ Mutex::Autolock _l(mStateLock);
+ sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
+ info.orientation = hw->getOrientation();
+ }
} else {
// TODO: where should this value come from?
static const int TV_DENSITY = 213;
@@ -767,10 +802,13 @@
ALOGE("%s : display is NULL", __func__);
return BAD_VALUE;
}
+
+ Mutex::Autolock _l(mStateLock);
sp<DisplayDevice> device(getDisplayDevice(display));
if (device != NULL) {
return device->getActiveConfig();
}
+
return BAD_VALUE;
}
@@ -858,6 +896,7 @@
}
android_color_mode_t SurfaceFlinger::getActiveColorMode(const sp<IBinder>& display) {
+ Mutex::Autolock _l(mStateLock);
sp<DisplayDevice> device(getDisplayDevice(display));
if (device != nullptr) {
return device->getActiveColorMode();
@@ -867,13 +906,10 @@
void SurfaceFlinger::setActiveColorModeInternal(const sp<DisplayDevice>& hw,
android_color_mode_t mode) {
- ALOGD("Set active color mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
- this);
int32_t type = hw->getDisplayType();
android_color_mode_t currentMode = hw->getActiveColorMode();
if (mode == currentMode) {
- ALOGD("Screen type=%d is already in color mode=%d", hw->getDisplayType(), mode);
return;
}
@@ -882,6 +918,9 @@
return;
}
+ ALOGD("Set active color mode: %s (%d), type=%d", decodeColorMode(mode).c_str(), mode,
+ hw->getDisplayType());
+
hw->setActiveColorMode(mode);
getHwComposer().setActiveColorMode(type, mode);
}
@@ -902,17 +941,17 @@
mFlinger.getDisplayColorModes(mDisplay, &modes);
bool exists = std::find(std::begin(modes), std::end(modes), mMode) != std::end(modes);
if (mMode < 0 || !exists) {
- ALOGE("Attempt to set invalid active color mode = %d for display %p", mMode,
- mDisplay.get());
+ ALOGE("Attempt to set invalid active color mode %s (%d) for display %p",
+ decodeColorMode(mMode).c_str(), mMode, mDisplay.get());
return true;
}
sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
if (hw == nullptr) {
- ALOGE("Attempt to set active color mode = %d for null display %p",
- mMode, mDisplay.get());
+ ALOGE("Attempt to set active color mode %s (%d) for null display %p",
+ decodeColorMode(mMode).c_str(), mMode, mDisplay.get());
} else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) {
- ALOGW("Attempt to set active color mode= %d for virtual display",
- mMode);
+ ALOGW("Attempt to set active color mode %s %d for virtual display",
+ decodeColorMode(mMode).c_str(), mMode);
} else {
mFlinger.setActiveColorModeInternal(hw, mMode);
}
@@ -1119,35 +1158,60 @@
*compositorTiming = mCompositorTiming;
}
-void SurfaceFlinger::onHotplugReceived(int32_t disp, bool connected) {
+void SurfaceFlinger::createDefaultDisplayDevice() {
+ const int32_t type = DisplayDevice::DISPLAY_PRIMARY;
+ wp<IBinder> token = mBuiltinDisplays[type];
+
+ // All non-virtual displays are currently considered secure.
+ const bool isSecure = true;
+
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer, new GraphicBufferAlloc());
+
+ sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, type, consumer);
+
+ bool hasWideColorModes = false;
+ std::vector<android_color_mode_t> modes = getHwComposer().getColorModes(
+ type);
+ for (android_color_mode_t colorMode : modes) {
+ switch (colorMode) {
+ case HAL_COLOR_MODE_DISPLAY_P3:
+ case HAL_COLOR_MODE_ADOBE_RGB:
+ case HAL_COLOR_MODE_DCI_P3:
+ hasWideColorModes = true;
+ break;
+ default:
+ break;
+ }
+ }
+ sp<DisplayDevice> hw = new DisplayDevice(this, DisplayDevice::DISPLAY_PRIMARY, type, isSecure,
+ token, fbs, producer, mRenderEngine->getEGLConfig(),
+ hasWideColorModes && hasWideColorDisplay);
+ mDisplays.add(token, hw);
+ android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE;
+ if (hasWideColorModes && hasWideColorDisplay) {
+ defaultColorMode = HAL_COLOR_MODE_SRGB;
+ }
+ setActiveColorModeInternal(hw, defaultColorMode);
+}
+
+void SurfaceFlinger::onHotplugReceived(HWComposer* composer, int32_t disp, bool connected) {
ALOGV("onHotplugReceived(%d, %s)", disp, connected ? "true" : "false");
+
+ if (composer->isUsingVrComposer()) {
+ // We handle initializing the primary display device for the VR
+ // window manager hwc explicitly at the time of transition.
+ if (disp != DisplayDevice::DISPLAY_PRIMARY) {
+ ALOGE("External displays are not supported by the vr hardware composer.");
+ }
+ return;
+ }
+
if (disp == DisplayDevice::DISPLAY_PRIMARY) {
Mutex::Autolock lock(mStateLock);
-
- // All non-virtual displays are currently considered secure.
- bool isSecure = true;
-
- int32_t type = DisplayDevice::DISPLAY_PRIMARY;
-
- // When we're using the vr composer, the assumption is that we've
- // already created the IBinder object for the primary display.
- if (!mHwc->isUsingVrComposer()) {
- createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY);
- }
-
- wp<IBinder> token = mBuiltinDisplays[type];
-
- sp<IGraphicBufferProducer> producer;
- sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer,
- new GraphicBufferAlloc());
-
- sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc,
- DisplayDevice::DISPLAY_PRIMARY, consumer);
- sp<DisplayDevice> hw = new DisplayDevice(this,
- DisplayDevice::DISPLAY_PRIMARY, disp, isSecure, token, fbs,
- producer, mRenderEngine->getEGLConfig());
- mDisplays.add(token, hw);
+ createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY);
+ createDefaultDisplayDevice();
} else {
auto type = DisplayDevice::DISPLAY_EXTERNAL;
Mutex::Autolock _l(mStateLock);
@@ -1189,6 +1253,7 @@
}
}
+// Note: it is assumed the caller holds |mStateLock| when this is called
void SurfaceFlinger::resetHwc() {
disableHardwareVsync(true);
clearHwcLayers(mDrawingState.layersSortedByZ);
@@ -1209,36 +1274,46 @@
if (vrFlingerRequestsDisplay == mHwc->isUsingVrComposer()) {
return;
}
+
+ bool vrHwcNewlyInitialized = false;
+
if (vrFlingerRequestsDisplay && !mVrHwc) {
// Construct new HWComposer without holding any locks.
mVrHwc = new HWComposer(true);
+ vrHwcNewlyInitialized = true;
ALOGV("Vr HWC created");
}
- {
- Mutex::Autolock _l(mStateLock);
- if (vrFlingerRequestsDisplay) {
- resetHwc();
+ Mutex::Autolock _l(mStateLock);
- mHwc = mVrHwc;
- mVrFlinger->GrantDisplayOwnership();
- } else {
- mVrFlinger->SeizeDisplayOwnership();
+ if (vrFlingerRequestsDisplay) {
+ resetHwc();
- resetHwc();
+ mHwc = mVrHwc;
+ mVrFlinger->GrantDisplayOwnership();
- mHwc = mRealHwc;
- enableHardwareVsync();
+ if (vrHwcNewlyInitialized) {
+ mVrHwc->setEventHandler(
+ static_cast<HWComposer::EventHandler*>(this));
}
+ } else {
+ mVrFlinger->SeizeDisplayOwnership();
- mVisibleRegionsDirty = true;
- invalidateHwcGeometry();
- android_atomic_or(1, &mRepaintEverything);
- setTransactionFlags(eDisplayTransactionNeeded);
+ resetHwc();
+
+ mHwc = mRealHwc;
+ enableHardwareVsync();
}
- if (mVrHwc) {
- mVrHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));
- }
+
+ mVisibleRegionsDirty = true;
+ invalidateHwcGeometry();
+
+ // Explicitly re-initialize the primary display. This is because some other
+ // parts of this class rely on the primary display always being available.
+ createDefaultDisplayDevice();
+
+ android_atomic_or(1, &mRepaintEverything);
+ setTransactionFlags(eDisplayTransactionNeeded);
}
void SurfaceFlinger::onMessageReceived(int32_t what) {
@@ -1448,7 +1523,8 @@
layer->releasePendingBuffer(dequeueReadyTime);
}
- const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
+ // |mStateLock| not needed as we are on the main thread
+ const sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
if (mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY)) {
@@ -1591,6 +1667,39 @@
}
}
+// pickColorMode translates a given dataspace into the best available color mode.
+// Currently only support sRGB and Display-P3.
+android_color_mode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) {
+ switch (dataSpace) {
+ // treat Unknown as regular SRGB buffer, since that's what the rest of the
+ // system expects.
+ case HAL_DATASPACE_UNKNOWN:
+ case HAL_DATASPACE_SRGB:
+ case HAL_DATASPACE_V0_SRGB:
+ return HAL_COLOR_MODE_SRGB;
+ break;
+
+ case HAL_DATASPACE_DISPLAY_P3:
+ return HAL_COLOR_MODE_DISPLAY_P3;
+ break;
+
+ default:
+ // TODO (courtneygo): Do we want to assert an error here?
+ ALOGE("No color mode mapping for %s (%#x)", dataspaceDetails(dataSpace).c_str(),
+ dataSpace);
+ return HAL_COLOR_MODE_SRGB;
+ break;
+ }
+}
+
+android_dataspace SurfaceFlinger::bestTargetDataSpace(android_dataspace a, android_dataspace b) {
+ // Only support sRGB and Display-P3 right now.
+ if (a == HAL_DATASPACE_DISPLAY_P3 || b == HAL_DATASPACE_DISPLAY_P3) {
+ return HAL_DATASPACE_DISPLAY_P3;
+ }
+ return HAL_DATASPACE_V0_SRGB;
+}
+
void SurfaceFlinger::setUpHWComposer() {
ATRACE_CALL();
ALOGV("setUpHWComposer");
@@ -1661,6 +1770,7 @@
for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
auto& displayDevice = mDisplays[displayId];
const auto hwcId = displayDevice->getHwcDisplayId();
+
if (hwcId < 0) {
continue;
}
@@ -1672,6 +1782,21 @@
for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
layer->setPerFrameData(displayDevice);
}
+
+ if (hasWideColorDisplay) {
+ android_color_mode newColorMode;
+ android_dataspace newDataSpace = HAL_DATASPACE_V0_SRGB;
+
+ for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+ newDataSpace = bestTargetDataSpace(layer->getDataSpace(), newDataSpace);
+ ALOGV("layer: %s, dataspace: %s (%#x), newDataSpace: %s (%#x)",
+ layer->getName().string(), dataspaceDetails(layer->getDataSpace()).c_str(),
+ layer->getDataSpace(), dataspaceDetails(newDataSpace).c_str(), newDataSpace);
+ }
+ newColorMode = pickColorMode(newDataSpace);
+
+ setActiveColorModeInternal(displayDevice, newColorMode);
+ }
}
mPreviousColorMatrix = colorMatrix;
@@ -1747,7 +1872,8 @@
mLastSwapBufferTime = systemTime() - now;
mDebugInSwapBuffers = 0;
- uint32_t flipCount = getDefaultDisplayDevice()->getPageFlipCount();
+ // |mStateLock| not needed as we are on the main thread
+ uint32_t flipCount = getDefaultDisplayDeviceLocked()->getPageFlipCount();
if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
logFrameStats();
}
@@ -1832,7 +1958,7 @@
// Call makeCurrent() on the primary display so we can
// be sure that nothing associated with this display
// is current.
- const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDevice());
+ const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDeviceLocked());
defaultDisplay->makeCurrent(mEGLDisplay, mEGLContext);
sp<DisplayDevice> hw(getDisplayDevice(draw.keyAt(i)));
if (hw != NULL)
@@ -1950,10 +2076,11 @@
const wp<IBinder>& display(curr.keyAt(i));
if (dispSurface != NULL) {
- sp<DisplayDevice> hw = new DisplayDevice(this,
- state.type, hwcId, state.isSecure, display,
- dispSurface, producer,
- mRenderEngine->getEGLConfig());
+ sp<DisplayDevice> hw =
+ new DisplayDevice(this, state.type, hwcId, state.isSecure, display,
+ dispSurface, producer,
+ mRenderEngine->getEGLConfig(),
+ hasWideColorDisplay);
hw->setLayerStack(state.layerStack);
hw->setProjection(state.orientation,
state.viewport, state.frame);
@@ -2021,7 +2148,7 @@
// could be null when this layer is using a layerStack
// that is not visible on any display. Also can occur at
// screen off/on times.
- disp = getDefaultDisplayDevice();
+ disp = getDefaultDisplayDeviceLocked();
}
layer->updateTransformHint(disp);
@@ -2369,11 +2496,17 @@
if (hasClientComposition) {
ALOGV("hasClientComposition");
+#ifdef USE_HWC2
+ mRenderEngine->setColorMode(displayDevice->getActiveColorMode());
+ mRenderEngine->setWideColor(displayDevice->getWideColorSupport());
+#endif
if (!displayDevice->makeCurrent(mEGLDisplay, mEGLContext)) {
ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
displayDevice->getDisplayName().string());
eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- if(!getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext)) {
+
+ // |mStateLock| not needed as we are on the main thread
+ if(!getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext)) {
ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting.");
}
return false;
@@ -2741,6 +2874,11 @@
}
}
}
+ if (what & layer_state_t::eRelativeLayerChanged) {
+ if (layer->setRelativeLayer(s.relativeLayerHandle, s.z)) {
+ flags |= eTransactionNeeded|eTraversalNeeded;
+ }
+ }
if (what & layer_state_t::eSizeChanged) {
if (layer->setSize(s.w, s.h)) {
flags |= eTraversalNeeded;
@@ -3014,7 +3152,6 @@
int currentMode = hw->getPowerMode();
if (mode == currentMode) {
- ALOGD("Screen type=%d is already mode=%d", hw->getDisplayType(), mode);
return;
}
@@ -3171,6 +3308,12 @@
dumpFrameEventsLocked(result);
dumpAll = false;
}
+
+ if ((index < numArgs) && (args[index] == String16("--wide-color"))) {
+ index++;
+ dumpWideColorInfo(result);
+ dumpAll = false;
+ }
}
if (dumpAll) {
@@ -3341,6 +3484,30 @@
result.append("\n");
}
+void SurfaceFlinger::dumpWideColorInfo(String8& result) const {
+ result.appendFormat("hasWideColorDisplay: %d\n", hasWideColorDisplay);
+
+ // TODO: print out if wide-color mode is active or not
+
+ for (size_t d = 0; d < mDisplays.size(); d++) {
+ const sp<const DisplayDevice>& displayDevice(mDisplays[d]);
+ int32_t hwcId = displayDevice->getHwcDisplayId();
+ if (hwcId == DisplayDevice::DISPLAY_ID_INVALID) {
+ continue;
+ }
+
+ result.appendFormat("Display %d color modes:\n", hwcId);
+ std::vector<android_color_mode_t> modes = getHwComposer().getColorModes(hwcId);
+ for (auto&& mode : modes) {
+ result.appendFormat(" %s (%d)\n", decodeColorMode(mode).c_str(), mode);
+ }
+
+ android_color_mode_t currentMode = displayDevice->getActiveColorMode();
+ result.appendFormat(" Current color mode: %s (%d)\n",
+ decodeColorMode(currentMode).c_str(), currentMode);
+ }
+ result.append("\n");
+}
void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
String8& result) const
@@ -3373,6 +3540,9 @@
appendGuiConfigString(result);
result.append("\n");
+ result.append("\nWide-Color information:\n");
+ dumpWideColorInfo(result);
+
colorizer.bold(result);
result.append("Sync configuration: ");
colorizer.reset(result);
@@ -3428,7 +3598,7 @@
colorizer.reset(result);
HWComposer& hwc(getHwComposer());
- sp<const DisplayDevice> hw(getDefaultDisplayDevice());
+ sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
colorizer.bold(result);
result.appendFormat("EGL implementation : %s\n",
@@ -3658,7 +3828,7 @@
return NO_ERROR;
case 1013: {
Mutex::Autolock _l(mStateLock);
- sp<const DisplayDevice> hw(getDefaultDisplayDevice());
+ sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
reply->writeInt32(hw->getPageFlipCount());
return NO_ERROR;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 4ecbddd..e9c0acf 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -151,6 +151,13 @@
// FramebufferSurface
static int64_t maxFrameBufferAcquiredBuffers;
+ // Indicate if platform supports color management on its
+ // wide-color display. This is typically found on devices
+ // with wide gamut (e.g. Display-P3) display.
+ // This also allows devices with wide-color displays that don't
+ // want to support color management to disable color management.
+ static bool hasWideColorDisplay;
+
static char const* getServiceName() ANDROID_API {
return "SurfaceFlinger";
}
@@ -177,8 +184,9 @@
void repaintEverything();
// returns the default Display
- sp<const DisplayDevice> getDefaultDisplayDevice() const {
- return getDisplayDevice(mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]);
+ sp<const DisplayDevice> getDefaultDisplayDevice() {
+ Mutex::Autolock _l(mStateLock);
+ return getDefaultDisplayDeviceLocked();
}
// utility function to delete a texture on the main thread
@@ -220,6 +228,7 @@
enum { LOG_FRAME_STATS_PERIOD = 30*60*60 };
static const size_t MAX_LAYERS = 4096;
+ static constexpr const char* kTimestampProperty = "service.sf.present_timestamp";
// We're reference counted, never destroy SurfaceFlinger directly
virtual ~SurfaceFlinger();
@@ -258,6 +267,8 @@
virtual void bootFinished();
virtual bool authenticateSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer) const;
+ virtual status_t getSupportedFrameTimestamps(
+ std::vector<FrameEvent>* outSupported) const;
virtual sp<IDisplayEventConnection> createDisplayEventConnection();
virtual status_t captureScreen(const sp<IBinder>& display,
const sp<IGraphicBufferProducer>& producer,
@@ -297,7 +308,7 @@
* HWComposer::EventHandler interface
*/
virtual void onVSyncReceived(HWComposer* composer, int type, nsecs_t timestamp);
- virtual void onHotplugReceived(int disp, bool connected);
+ virtual void onHotplugReceived(HWComposer* composer, int disp, bool connected);
virtual void onInvalidateReceived(HWComposer* composer);
/* ------------------------------------------------------------------------
@@ -432,6 +443,12 @@
return mDisplays.valueFor(dpy);
}
+ sp<const DisplayDevice> getDefaultDisplayDeviceLocked() const {
+ return getDisplayDevice(mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]);
+ }
+
+ void createDefaultDisplayDevice();
+
int32_t getDisplayType(const sp<IBinder>& display) {
if (!display.get()) return NAME_NOT_FOUND;
for (int i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; ++i) {
@@ -472,6 +489,12 @@
nsecs_t vsyncPhase, nsecs_t vsyncInterval,
nsecs_t compositeToPresentLatency);
void rebuildLayerStacks();
+
+ // Given a dataSpace, returns the appropriate color_mode to use
+ // to display that dataSpace.
+ android_color_mode pickColorMode(android_dataspace dataSpace);
+ android_dataspace bestTargetDataSpace(android_dataspace a, android_dataspace b);
+
void setUpHWComposer();
void doComposition();
void doDebugFlashRegions();
@@ -522,6 +545,7 @@
void recordBufferingStats(const char* layerName,
std::vector<OccupancyTracker::Segment>&& history);
void dumpBufferingStats(String8& result) const;
+ void dumpWideColorInfo(String8& result) const;
bool isLayerTripleBufferingDisabled() const {
return this->mLayerTripleBufferingDisabled;
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index a6c0b9c..bdaf85d 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -549,6 +549,9 @@
LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
"couldn't create EGLContext");
+ // Inform native graphics APIs that the present timestamp is NOT supported:
+ property_set(kTimestampProperty, "0");
+
// initialize our non-virtual displays
for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
@@ -570,7 +573,7 @@
sp<DisplayDevice> hw = new DisplayDevice(this,
type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
fbs, producer,
- mRenderEngine->getEGLConfig());
+ mRenderEngine->getEGLConfig(), false);
if (i > DisplayDevice::DISPLAY_PRIMARY) {
// FIXME: currently we don't get blank/unblank requests
// for displays other than the main display, so we always
@@ -584,7 +587,7 @@
// make the GLContext current so that we can create textures when creating Layers
// (which may happens before we render something)
- getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
+ getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext);
mEventControlThread = new EventControlThread(this);
mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
@@ -647,6 +650,21 @@
return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0;
}
+status_t SurfaceFlinger::getSupportedFrameTimestamps(
+ std::vector<FrameEvent>* outSupported) const {
+ *outSupported = {
+ FrameEvent::REQUESTED_PRESENT,
+ FrameEvent::ACQUIRE,
+ FrameEvent::LATCH,
+ FrameEvent::FIRST_REFRESH_START,
+ FrameEvent::LAST_REFRESH_START,
+ FrameEvent::GPU_COMPOSITION_DONE,
+ FrameEvent::DEQUEUE_READY,
+ FrameEvent::RELEASE,
+ };
+ return NO_ERROR;
+}
+
status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
Vector<DisplayInfo>* configs) {
if ((configs == NULL) || (display.get() == NULL)) {
@@ -1040,7 +1058,7 @@
*compositorTiming = mCompositorTiming;
}
-void SurfaceFlinger::onHotplugReceived(int type, bool connected) {
+void SurfaceFlinger::onHotplugReceived(HWComposer* /*composer*/, int type, bool connected) {
if (mEventThread == NULL) {
// This is a temporary workaround for b/7145521. A non-null pointer
// does not mean EventThread has finished initializing, so this
@@ -1740,7 +1758,7 @@
state.type, hwcDisplayId,
mHwc->getFormat(hwcDisplayId), state.isSecure,
display, dispSurface, producer,
- mRenderEngine->getEGLConfig());
+ mRenderEngine->getEGLConfig(), false);
hw->setLayerStack(state.layerStack);
hw->setProjection(state.orientation,
state.viewport, state.frame);
@@ -3222,7 +3240,7 @@
colorizer.reset(result);
HWComposer& hwc(getHwComposer());
- sp<const DisplayDevice> hw(getDefaultDisplayDevice());
+ sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
colorizer.bold(result);
result.appendFormat("EGL implementation : %s\n",
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index f151087..d15376e 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -18,17 +18,44 @@
#include <sched.h>
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
#include <cutils/sched_policy.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
+#include <hidl/LegacySupport.h>
+#include <configstore/Utils.h>
#include "GpuService.h"
#include "SurfaceFlinger.h"
using namespace android;
+using android::hardware::graphics::allocator::V2_0::IAllocator;
+using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
+using android::hardware::configstore::getBool;
+using android::hardware::configstore::getBool;
+
+static status_t startGraphicsAllocatorService() {
+ hardware::configureRpcThreadpool( 1 /* maxThreads */,
+ false /* callerWillJoin */);
+ status_t result =
+ hardware::registerPassthroughServiceImplementation<IAllocator>();
+ if (result != OK) {
+ ALOGE("could not start graphics allocator service");
+ return result;
+ }
+
+ return OK;
+}
+
int main(int, char**) {
+ if (getBool<ISurfaceFlingerConfigs,
+ &ISurfaceFlingerConfigs::startGraphicsAllocatorService>(false)) {
+ startGraphicsAllocatorService();
+ }
+
signal(SIGPIPE, SIG_IGN);
// When SF is launched in its own process, limit the number of
// binder threads to 4.
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index a46ba48..441fc7e 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -662,6 +662,49 @@
}
}
+TEST_F(LayerUpdateTest, LayerSetRelativeLayerWorks) {
+ sp<ScreenCapture> sc;
+ {
+ SCOPED_TRACE("before adding relative surface");
+ ScreenCapture::captureScreen(&sc);
+ sc->expectBGColor(24, 24);
+ sc->expectFGColor(75, 75);
+ sc->expectBGColor(145, 145);
+ }
+
+ auto relativeSurfaceControl = mComposerClient->createSurface(
+ String8("Test Surface"), 64, 64, PIXEL_FORMAT_RGBA_8888, 0);
+ fillSurfaceRGBA8(relativeSurfaceControl, 255, 177, 177);
+ waitForPostedBuffers();
+
+ // Now we stack the surface above the foreground surface and make sure it is visible.
+ SurfaceComposerClient::openGlobalTransaction();
+ relativeSurfaceControl->setPosition(64, 64);
+ relativeSurfaceControl->show();
+ relativeSurfaceControl->setRelativeLayer(mFGSurfaceControl->getHandle(), 1);
+ SurfaceComposerClient::closeGlobalTransaction(true);
+
+
+ {
+ SCOPED_TRACE("after adding relative surface");
+ ScreenCapture::captureScreen(&sc);
+ // our relative surface should be visible now.
+ sc->checkPixel(75, 75, 255, 177, 177);
+ }
+
+ // A call to setLayer will override a call to setRelativeLayer
+ SurfaceComposerClient::openGlobalTransaction();
+ relativeSurfaceControl->setLayer(0);
+ SurfaceComposerClient::closeGlobalTransaction();
+
+ {
+ SCOPED_TRACE("after set layer");
+ ScreenCapture::captureScreen(&sc);
+ // now the FG surface should be visible again.
+ sc->expectFGColor(75, 75);
+ }
+}
+
class ChildLayerTest : public LayerUpdateTest {
protected:
void SetUp() override {
diff --git a/services/vr/bufferhubd/Android.mk b/services/vr/bufferhubd/Android.mk
index b3d777e..97f0332 100644
--- a/services/vr/bufferhubd/Android.mk
+++ b/services/vr/bufferhubd/Android.mk
@@ -37,8 +37,6 @@
libui
include $(CLEAR_VARS)
-# Don't strip symbols so we see stack traces in logcat.
-LOCAL_STRIP_MODULE := false
LOCAL_SRC_FILES := $(sourceFiles)
LOCAL_CFLAGS := -DLOG_TAG=\"bufferhubd\"
LOCAL_CFLAGS += -DTRACE=0
diff --git a/services/vr/bufferhubd/buffer_hub.cpp b/services/vr/bufferhubd/buffer_hub.cpp
index de4950e..4b1a522 100644
--- a/services/vr/bufferhubd/buffer_hub.cpp
+++ b/services/vr/bufferhubd/buffer_hub.cpp
@@ -1,5 +1,6 @@
#include "buffer_hub.h"
+#include <inttypes.h>
#include <log/log.h>
#include <poll.h>
#include <utils/Trace.h>
@@ -16,7 +17,9 @@
#include "producer_queue_channel.h"
using android::pdx::Channel;
+using android::pdx::ErrorStatus;
using android::pdx::Message;
+using android::pdx::Status;
using android::pdx::rpc::DispatchRemoteMethod;
using android::pdx::default_transport::Endpoint;
@@ -28,9 +31,7 @@
BufferHubService::~BufferHubService() {}
-bool BufferHubService::IsInitialized() const {
- return BASE::IsInitialized();
-}
+bool BufferHubService::IsInitialized() const { return BASE::IsInitialized(); }
std::string BufferHubService::DumpState(size_t /*max_length*/) {
std::ostringstream stream;
@@ -52,7 +53,7 @@
stream << " ";
stream << std::setw(6) << "Format";
stream << " ";
- stream << std::setw(10) << "Usage";
+ stream << std::setw(21) << "Usage";
stream << " ";
stream << "Name";
stream << std::endl;
@@ -79,7 +80,9 @@
stream << std::setw(6) << info.format;
stream << " ";
stream << "0x" << std::hex << std::setfill('0');
- stream << std::setw(8) << info.usage;
+ stream << std::setw(8) << info.producer_usage;
+ stream << "0x";
+ stream << std::setw(8) << info.consumer_usage;
stream << std::dec << std::setfill(' ');
stream << " ";
stream << info.name;
@@ -137,6 +140,10 @@
stream << " UsageClearMask";
stream << " UsageDenySetMask";
stream << " UsageDenyClearMask";
+ stream << " UsageSetMask";
+ stream << " UsageClearMask";
+ stream << " UsageDenySetMask";
+ stream << " UsageDenyClearMask";
stream << " ";
stream << std::endl;
@@ -150,16 +157,30 @@
stream << std::right << std::setw(12) << info.consumer_count;
stream << std::setw(5) << std::setfill(' ') << "0x";
stream << std::hex << std::setfill('0');
- stream << std::setw(8) << info.usage_set_mask;
+ stream << std::setw(8) << info.usage_policy.producer_set_mask;
stream << std::setw(7) << std::setfill(' ') << "0x";
stream << std::hex << std::setfill('0');
- stream << std::setw(8) << info.usage_clear_mask;
+ stream << std::setw(8) << info.usage_policy.producer_clear_mask;
stream << std::setw(9) << std::setfill(' ') << "0x";
stream << std::hex << std::setfill('0');
- stream << std::setw(8) << info.usage_deny_set_mask;
+ stream << std::setw(8) << info.usage_policy.producer_deny_set_mask;
stream << std::setw(11) << std::setfill(' ') << "0x";
stream << std::hex << std::setfill('0');
- stream << std::setw(8) << info.usage_deny_clear_mask;
+ stream << std::setw(8) << info.usage_policy.producer_deny_clear_mask;
+ stream << std::setw(5) << std::setfill(' ') << "0x";
+ stream << std::hex << std::setfill('0');
+ stream << std::setw(8) << info.usage_policy.consumer_set_mask;
+ stream << std::setw(7) << std::setfill(' ') << "0x";
+ stream << std::hex << std::setfill('0');
+ stream << std::setw(8) << info.usage_policy.consumer_clear_mask;
+ stream << std::setw(9) << std::setfill(' ') << "0x";
+ stream << std::hex << std::setfill('0');
+ stream << std::setw(8) << info.usage_policy.consumer_deny_set_mask;
+ stream << std::setw(11) << std::setfill(' ') << "0x";
+ stream << std::hex << std::setfill('0');
+ stream << std::setw(8) << info.usage_policy.consumer_deny_clear_mask;
+ stream << std::hex << std::setfill('0');
+ stream << std::endl;
}
}
@@ -177,6 +198,7 @@
stream << std::right << std::setw(6) << info.id;
stream << std::right << std::setw(12) << info.capacity;
+ stream << std::endl;
}
}
@@ -235,48 +257,53 @@
buffer->Detach();
}
-int BufferHubService::OnCreateBuffer(Message& message, int width, int height,
- int format, int usage,
- size_t meta_size_bytes,
- size_t slice_count) {
+Status<void> BufferHubService::OnCreateBuffer(Message& message, uint32_t width,
+ uint32_t height, uint32_t format,
+ uint64_t producer_usage,
+ uint64_t consumer_usage,
+ size_t meta_size_bytes,
+ size_t slice_count) {
// Use the producer channel id as the global buffer id.
const int buffer_id = message.GetChannelId();
ALOGD_IF(TRACE,
- "BufferHubService::OnCreateBuffer: buffer_id=%d width=%d height=%d "
- "format=%d usage=%d meta_size_bytes=%zu slice_count=%zu",
- buffer_id, width, height, format, usage, meta_size_bytes,
- slice_count);
+ "BufferHubService::OnCreateBuffer: buffer_id=%d width=%u height=%u "
+ "format=%u producer_usage=%" PRIx64 " consumer_usage=%" PRIx64
+ " meta_size_bytes=%zu slice_count=%zu",
+ buffer_id, width, height, format, producer_usage, consumer_usage,
+ meta_size_bytes, slice_count);
// See if this channel is already attached to a buffer.
if (const auto channel = message.GetChannel<BufferHubChannel>()) {
ALOGE("BufferHubService::OnCreateBuffer: Buffer already created: buffer=%d",
buffer_id);
- return -EALREADY;
+ return ErrorStatus(EALREADY);
}
- int error;
- if (const auto producer_channel =
- ProducerChannel::Create(this, buffer_id, width, height, format, usage,
- meta_size_bytes, slice_count, &error)) {
- message.SetChannel(producer_channel);
- return 0;
+ auto status = ProducerChannel::Create(this, buffer_id, width, height, format,
+ producer_usage, consumer_usage,
+ meta_size_bytes, slice_count);
+ if (status) {
+ message.SetChannel(status.take());
+ return {};
} else {
- ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
- return error;
+ ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer: %s",
+ status.GetErrorMessage().c_str());
+ return status.error_status();
}
}
-int BufferHubService::OnCreatePersistentBuffer(
+Status<void> BufferHubService::OnCreatePersistentBuffer(
Message& message, const std::string& name, int user_id, int group_id,
- int width, int height, int format, int usage, size_t meta_size_bytes,
- size_t slice_count) {
+ uint32_t width, uint32_t height, uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage, size_t meta_size_bytes, size_t slice_count) {
const int channel_id = message.GetChannelId();
ALOGD_IF(TRACE,
"BufferHubService::OnCreatePersistentBuffer: channel_id=%d name=%s "
- "user_id=%d group_id=%d width=%d height=%d format=%d usage=%d "
- "meta_size_bytes=%zu slice_count=%zu",
+ "user_id=%d group_id=%d width=%u height=%u format=%u "
+ "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64
+ " meta_size_bytes=%zu slice_count=%zu",
channel_id, name.c_str(), user_id, group_id, width, height, format,
- usage, meta_size_bytes, slice_count);
+ producer_usage, consumer_usage, meta_size_bytes, slice_count);
// See if this channel is already attached to a buffer.
if (const auto channel = message.GetChannel<BufferHubChannel>()) {
@@ -284,12 +311,11 @@
"BufferHubService::OnCreatePersistentBuffer: Channel already attached "
"to buffer: channel_id=%d buffer_id=%d",
channel_id, channel->buffer_id());
- return -EALREADY;
+ return ErrorStatus(EALREADY);
}
const int euid = message.GetEffectiveUserId();
const int egid = message.GetEffectiveGroupId();
- int error;
if (auto buffer = GetNamedBuffer(name)) {
if (!buffer->CheckAccess(euid, egid)) {
@@ -297,41 +323,45 @@
"BufferHubService::OnCreatePersistentBuffer: Requesting process does "
"not have permission to access named buffer: name=%s euid=%d egid=%d",
name.c_str(), euid, euid);
- return -EPERM;
- } else if (!buffer->CheckParameters(width, height, format, usage,
- meta_size_bytes, slice_count)) {
+ return ErrorStatus(EPERM);
+ } else if (!buffer->CheckParameters(width, height, format, producer_usage,
+ consumer_usage, meta_size_bytes,
+ slice_count)) {
ALOGE(
"BufferHubService::OnCreatePersistentBuffer: Requested an existing "
"buffer with different parameters: name=%s",
name.c_str());
- return -EINVAL;
+ return ErrorStatus(EINVAL);
} else if (!buffer->IsDetached()) {
ALOGE(
"BufferHubService::OnCreatePersistentBuffer: Requesting a persistent "
"buffer that is already attached to a channel: name=%s",
name.c_str());
- return -EINVAL;
+ return ErrorStatus(EINVAL);
} else {
buffer->Attach(channel_id);
message.SetChannel(buffer);
- return 0;
+ return {};
}
- } else if (auto buffer = ProducerChannel::Create(
- this, channel_id, width, height, format, usage,
- meta_size_bytes, slice_count, &error)) {
- const int ret =
- buffer->OnProducerMakePersistent(message, name, user_id, group_id);
- if (!ret)
- message.SetChannel(buffer);
- return ret;
} else {
- ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
- return error;
+ auto status = ProducerChannel::Create(
+ this, channel_id, width, height, format, producer_usage, consumer_usage,
+ meta_size_bytes, slice_count);
+ if (!status) {
+ ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
+ return status.error_status();
+ }
+ auto persistent_buffer = status.take();
+ auto make_persistent_status = persistent_buffer->OnProducerMakePersistent(
+ message, name, user_id, group_id);
+ if (make_persistent_status)
+ message.SetChannel(persistent_buffer);
+ return make_persistent_status;
}
}
-int BufferHubService::OnGetPersistentBuffer(Message& message,
- const std::string& name) {
+Status<void> BufferHubService::OnGetPersistentBuffer(Message& message,
+ const std::string& name) {
const int channel_id = message.GetChannelId();
ALOGD_IF(TRACE,
"BufferHubService::OnGetPersistentBuffer: channel_id=%d name=%s",
@@ -343,7 +373,7 @@
"BufferHubService::OnGetPersistentBuffer: Channel already attached to "
"buffer: channel_id=%d buffer_id=%d",
channel_id, channel->buffer_id());
- return -EALREADY;
+ return ErrorStatus(EALREADY);
}
const int euid = message.GetEffectiveUserId();
@@ -355,28 +385,28 @@
"BufferHubService::OnGetPersistentBuffer: Requesting process does "
"not have permission to access named buffer: name=%s euid=%d egid=%d",
name.c_str(), euid, egid);
- return -EPERM;
+ return ErrorStatus(EPERM);
} else if (!buffer->IsDetached()) {
ALOGE(
"BufferHubService::OnGetPersistentBuffer: Requesting a persistent "
"buffer that is already attached to a channel: name=%s",
name.c_str());
- return -EINVAL;
+ return ErrorStatus(EINVAL);
} else {
buffer->Attach(channel_id);
message.SetChannel(buffer);
- return 0;
+ return {};
}
} else {
ALOGE("BufferHubService::OnGetPersistentBuffer: Buffer \"%s\" not found!",
name.c_str());
- return -ENOENT;
+ return ErrorStatus(ENOENT);
}
}
-int BufferHubService::OnCreateProducerQueue(
- pdx::Message& message, size_t meta_size_bytes, int usage_set_mask,
- int usage_clear_mask, int usage_deny_set_mask, int usage_deny_clear_mask) {
+Status<QueueInfo> BufferHubService::OnCreateProducerQueue(
+ pdx::Message& message, size_t meta_size_bytes,
+ const UsagePolicy& usage_policy) {
// Use the producer channel id as the global queue id.
const int queue_id = message.GetChannelId();
ALOGD_IF(TRACE, "BufferHubService::OnCreateProducerQueue: queue_id=%d",
@@ -386,18 +416,17 @@
if (const auto channel = message.GetChannel<BufferHubChannel>()) {
ALOGE("BufferHubService::OnCreateProducerQueue: already created: queue=%d",
queue_id);
- return -EALREADY;
+ return ErrorStatus(EALREADY);
}
- int error;
- if (const auto producer_channel = ProducerQueueChannel::Create(
- this, queue_id, meta_size_bytes, usage_set_mask, usage_clear_mask,
- usage_deny_set_mask, usage_deny_clear_mask, &error)) {
- message.SetChannel(producer_channel);
- return 0;
+ auto status = ProducerQueueChannel::Create(this, queue_id, meta_size_bytes,
+ usage_policy);
+ if (status) {
+ message.SetChannel(status.take());
+ return {{meta_size_bytes, queue_id}};
} else {
ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
- return error;
+ return status.error_status();
}
}
diff --git a/services/vr/bufferhubd/buffer_hub.h b/services/vr/bufferhubd/buffer_hub.h
index 8a7dca8..4cb1eb9 100644
--- a/services/vr/bufferhubd/buffer_hub.h
+++ b/services/vr/bufferhubd/buffer_hub.h
@@ -7,6 +7,7 @@
#include <hardware/gralloc.h>
#include <pdx/service.h>
+#include <private/dvr/bufferhub_rpc.h>
namespace android {
namespace dvr {
@@ -47,43 +48,40 @@
size_t consumer_count = 0;
// Data field for buffer producer.
- int width = 0;
- int height = 0;
- int format = 0;
- int usage = 0;
+ uint32_t width = 0;
+ uint32_t height = 0;
+ uint32_t format = 0;
+ uint64_t producer_usage = 0;
+ uint64_t consumer_usage = 0;
size_t slice_count = 0;
std::string name;
// Data filed for producer queue.
size_t capacity = 0;
- int usage_set_mask = 0;
- int usage_clear_mask = 0;
- int usage_deny_set_mask = 0;
- int usage_deny_clear_mask = 0;
+ UsagePolicy usage_policy{0, 0, 0, 0, 0, 0, 0, 0};
- BufferInfo(int id, size_t consumer_count, int width, int height, int format,
- int usage, size_t slice_count, const std::string& name)
+ BufferInfo(int id, size_t consumer_count, uint32_t width, uint32_t height,
+ uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage, size_t slice_count,
+ const std::string& name)
: id(id),
type(kProducerType),
consumer_count(consumer_count),
width(width),
height(height),
format(format),
- usage(usage),
+ producer_usage(producer_usage),
+ consumer_usage(consumer_usage),
slice_count(slice_count),
name(name) {}
- BufferInfo(int id, size_t consumer_count, size_t capacity, int usage_set_mask,
- int usage_clear_mask, int usage_deny_set_mask,
- int usage_deny_clear_mask)
+ BufferInfo(int id, size_t consumer_count, size_t capacity,
+ const UsagePolicy& usage_policy)
: id(id),
type(kProducerQueueType),
consumer_count(consumer_count),
capacity(capacity),
- usage_set_mask(usage_set_mask),
- usage_clear_mask(usage_clear_mask),
- usage_deny_set_mask(usage_deny_set_mask),
- usage_deny_clear_mask(usage_deny_clear_mask) {}
+ usage_policy(usage_policy) {}
BufferInfo() {}
};
@@ -161,16 +159,19 @@
std::unordered_map<std::string, std::shared_ptr<ProducerChannel>>
named_buffers_;
- int OnCreateBuffer(pdx::Message& message, int width, int height, int format,
- int usage, size_t meta_size_bytes, size_t slice_count);
- int OnCreatePersistentBuffer(pdx::Message& message, const std::string& name,
- int user_id, int group_id, int width, int height,
- int format, int usage, size_t meta_size_bytes,
- size_t slice_count);
- int OnGetPersistentBuffer(pdx::Message& message, const std::string& name);
- int OnCreateProducerQueue(pdx::Message& message, size_t meta_size_bytes,
- int usage_set_mask, int usage_clear_mask,
- int usage_deny_set_mask, int usage_deny_clear_mask);
+ pdx::Status<void> OnCreateBuffer(pdx::Message& message, uint32_t width, uint32_t height,
+ uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage, size_t meta_size_bytes,
+ size_t slice_count);
+ pdx::Status<void> OnCreatePersistentBuffer(pdx::Message& message, const std::string& name,
+ int user_id, int group_id, uint32_t width,
+ uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage,
+ size_t meta_size_bytes, size_t slice_count);
+ pdx::Status<void> OnGetPersistentBuffer(pdx::Message& message, const std::string& name);
+ pdx::Status<QueueInfo> OnCreateProducerQueue(pdx::Message& message,
+ size_t meta_size_bytes,
+ const UsagePolicy& usage_policy);
BufferHubService(const BufferHubService&) = delete;
void operator=(const BufferHubService&) = delete;
diff --git a/services/vr/bufferhubd/consumer_channel.cpp b/services/vr/bufferhubd/consumer_channel.cpp
index 2264cef..311f5c6 100644
--- a/services/vr/bufferhubd/consumer_channel.cpp
+++ b/services/vr/bufferhubd/consumer_channel.cpp
@@ -8,9 +8,11 @@
#include <private/dvr/bufferhub_rpc.h>
#include "producer_channel.h"
+using android::pdx::ErrorStatus;
using android::pdx::BorrowedHandle;
using android::pdx::Channel;
using android::pdx::Message;
+using android::pdx::Status;
using android::pdx::rpc::DispatchRemoteMethod;
namespace android {
@@ -103,53 +105,53 @@
}
}
-std::pair<BorrowedFence, ConsumerChannel::MetaData>
+Status<std::pair<BorrowedFence, ConsumerChannel::MetaData>>
ConsumerChannel::OnConsumerAcquire(Message& message,
std::size_t metadata_size) {
ATRACE_NAME("ConsumerChannel::OnConsumerAcquire");
auto producer = GetProducer();
if (!producer)
- REPLY_ERROR_RETURN(message, EPIPE, {});
+ return ErrorStatus(EPIPE);
if (ignored_ || handled_) {
ALOGE(
"ConsumerChannel::OnConsumerAcquire: Acquire when not posted: "
"ignored=%d handled=%d channel_id=%d buffer_id=%d",
ignored_, handled_, message.GetChannelId(), producer->buffer_id());
- REPLY_ERROR_RETURN(message, EBUSY, {});
+ return ErrorStatus(EBUSY);
} else {
ClearAvailable();
return producer->OnConsumerAcquire(message, metadata_size);
}
}
-int ConsumerChannel::OnConsumerRelease(Message& message,
- LocalFence release_fence) {
+Status<void> ConsumerChannel::OnConsumerRelease(Message& message,
+ LocalFence release_fence) {
ATRACE_NAME("ConsumerChannel::OnConsumerRelease");
auto producer = GetProducer();
if (!producer)
- return -EPIPE;
+ return ErrorStatus(EPIPE);
if (ignored_ || handled_) {
ALOGE(
"ConsumerChannel::OnConsumerRelease: Release when not acquired: "
"ignored=%d handled=%d channel_id=%d buffer_id=%d",
ignored_, handled_, message.GetChannelId(), producer->buffer_id());
- return -EBUSY;
+ return ErrorStatus(EBUSY);
} else {
ClearAvailable();
- const int ret =
+ auto status =
producer->OnConsumerRelease(message, std::move(release_fence));
- handled_ = ret == 0;
- return ret;
+ handled_ = !!status;
+ return status;
}
}
-int ConsumerChannel::OnConsumerSetIgnore(Message&, bool ignored) {
+Status<void> ConsumerChannel::OnConsumerSetIgnore(Message&, bool ignored) {
ATRACE_NAME("ConsumerChannel::OnConsumerSetIgnore");
auto producer = GetProducer();
if (!producer)
- return -EPIPE;
+ return ErrorStatus(EPIPE);
ignored_ = ignored;
if (ignored_ && !handled_) {
@@ -160,7 +162,7 @@
handled_ = false;
}
- return 0;
+ return {};
}
bool ConsumerChannel::OnProducerPosted() {
diff --git a/services/vr/bufferhubd/consumer_channel.h b/services/vr/bufferhubd/consumer_channel.h
index d2a078f..d84055c 100644
--- a/services/vr/bufferhubd/consumer_channel.h
+++ b/services/vr/bufferhubd/consumer_channel.h
@@ -32,10 +32,11 @@
std::shared_ptr<ProducerChannel> GetProducer() const;
- std::pair<BorrowedFence, MetaData> OnConsumerAcquire(
+ pdx::Status<std::pair<BorrowedFence, MetaData>> OnConsumerAcquire(
Message& message, std::size_t metadata_size);
- int OnConsumerRelease(Message& message, LocalFence release_fence);
- int OnConsumerSetIgnore(Message& message, bool ignore);
+ pdx::Status<void> OnConsumerRelease(Message& message,
+ LocalFence release_fence);
+ pdx::Status<void> OnConsumerSetIgnore(Message& message, bool ignore);
bool handled_; // True if we have processed RELEASE.
bool ignored_; // True if we are ignoring events.
diff --git a/services/vr/bufferhubd/consumer_queue_channel.cpp b/services/vr/bufferhubd/consumer_queue_channel.cpp
index ae87acd..7422751 100644
--- a/services/vr/bufferhubd/consumer_queue_channel.cpp
+++ b/services/vr/bufferhubd/consumer_queue_channel.cpp
@@ -4,7 +4,9 @@
#include "producer_channel.h"
+using android::pdx::ErrorStatus;
using android::pdx::RemoteChannelHandle;
+using android::pdx::Status;
using android::pdx::rpc::DispatchRemoteMethod;
namespace android {
@@ -40,6 +42,11 @@
*producer, &ProducerQueueChannel::OnCreateConsumerQueue, message);
return true;
+ case BufferHubRPC::GetQueueInfo::Opcode:
+ DispatchRemoteMethod<BufferHubRPC::GetQueueInfo>(
+ *producer, &ProducerQueueChannel::OnGetQueueInfo, message);
+ return true;
+
case BufferHubRPC::ConsumerQueueImportBuffers::Opcode:
DispatchRemoteMethod<BufferHubRPC::ConsumerQueueImportBuffers>(
*this, &ConsumerQueueChannel::OnConsumerQueueImportBuffers, message);
@@ -78,7 +85,7 @@
SignalAvailable();
}
-std::vector<std::pair<RemoteChannelHandle, size_t>>
+Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
ConsumerQueueChannel::OnConsumerQueueImportBuffers(Message& message) {
std::vector<std::pair<RemoteChannelHandle, size_t>> buffer_handles;
ATRACE_NAME("ConsumerQueueChannel::OnConsumerQueueImportBuffers");
@@ -101,31 +108,30 @@
continue;
}
- RemoteChannelHandle consumer_handle(
- producer_channel->CreateConsumer(message));
+ auto status = producer_channel->CreateConsumer(message);
// If no buffers are imported successfully, clear available and return an
// error. Otherwise, return all consumer handles already imported
// successfully, but keep available bits on, so that the client can retry
// importing remaining consumer buffers.
- if (!consumer_handle.valid()) {
+ if (!status) {
ALOGE(
- "ConsumerQueueChannel::OnConsumerQueueImportBuffers: imported "
- "consumer handle is invalid.");
+ "ConsumerQueueChannel::OnConsumerQueueImportBuffers: Failed create "
+ "consumer: %s",
+ status.GetErrorMessage().c_str());
if (buffer_handles.empty()) {
ClearAvailable();
- REPLY_ERROR_RETURN(message, EIO, {});
+ return status.error_status();
} else {
- return buffer_handles;
+ return {std::move(buffer_handles)};
}
}
- // Move consumer_handle into buffer_handles.
- buffer_handles.emplace_back(std::move(consumer_handle), producer_slot);
+ buffer_handles.emplace_back(status.take(), producer_slot);
}
ClearAvailable();
- return buffer_handles;
+ return {std::move(buffer_handles)};
}
} // namespace dvr
diff --git a/services/vr/bufferhubd/consumer_queue_channel.h b/services/vr/bufferhubd/consumer_queue_channel.h
index b345595..e1005e4 100644
--- a/services/vr/bufferhubd/consumer_queue_channel.h
+++ b/services/vr/bufferhubd/consumer_queue_channel.h
@@ -36,7 +36,7 @@
// allocated. Clients uses kOpConsumerQueueImportBuffers to import new
// consumer buffers and this handler returns a vector of fd representing
// BufferConsumers that clients can import.
- std::vector<std::pair<RemoteChannelHandle, size_t>>
+ pdx::Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
OnConsumerQueueImportBuffers(Message& message);
private:
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index 903d174..c946a8d 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -13,8 +13,10 @@
#include "consumer_channel.h"
using android::pdx::BorrowedHandle;
+using android::pdx::ErrorStatus;
using android::pdx::Message;
using android::pdx::RemoteChannelHandle;
+using android::pdx::Status;
using android::pdx::rpc::BufferWrapper;
using android::pdx::rpc::DispatchRemoteMethod;
using android::pdx::rpc::WrapBuffer;
@@ -23,7 +25,9 @@
namespace dvr {
ProducerChannel::ProducerChannel(BufferHubService* service, int channel_id,
- int width, int height, int format, int usage,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage,
size_t meta_size_bytes, size_t slice_count,
int* error)
: BufferHubChannel(service, channel_id, channel_id, kProducerType),
@@ -33,7 +37,8 @@
meta_size_bytes_(meta_size_bytes),
meta_(meta_size_bytes ? new uint8_t[meta_size_bytes] : nullptr) {
for (auto& ion_buffer : slices_) {
- const int ret = ion_buffer.Alloc(width, height, format, usage);
+ const int ret =
+ ion_buffer.Alloc(width, height, format, producer_usage, consumer_usage);
if (ret < 0) {
ALOGE("ProducerChannel::ProducerChannel: Failed to allocate buffer: %s",
strerror(-ret));
@@ -46,17 +51,18 @@
*error = 0;
}
-std::shared_ptr<ProducerChannel> ProducerChannel::Create(
- BufferHubService* service, int channel_id, int width, int height,
- int format, int usage, size_t meta_size_bytes, size_t slice_count,
- int* error) {
- std::shared_ptr<ProducerChannel> producer(
- new ProducerChannel(service, channel_id, width, height, format, usage,
- meta_size_bytes, slice_count, error));
- if (*error < 0)
- return nullptr;
+Status<std::shared_ptr<ProducerChannel>> ProducerChannel::Create(
+ BufferHubService* service, int channel_id, uint32_t width, uint32_t height,
+ uint32_t format, uint64_t producer_usage, uint64_t consumer_usage,
+ size_t meta_size_bytes, size_t slice_count) {
+ int error;
+ std::shared_ptr<ProducerChannel> producer(new ProducerChannel(
+ service, channel_id, width, height, format, producer_usage,
+ consumer_usage, meta_size_bytes, slice_count, &error));
+ if (error < 0)
+ return ErrorStatus(-error);
else
- return producer;
+ return {std::move(producer)};
}
ProducerChannel::~ProducerChannel() {
@@ -70,7 +76,8 @@
BufferHubChannel::BufferInfo ProducerChannel::GetBufferInfo() const {
return BufferInfo(buffer_id(), consumer_channels_.size(), slices_[0].width(),
slices_[0].height(), slices_[0].format(),
- slices_[0].usage(), slices_.size(), name_);
+ slices_[0].producer_usage(), slices_[0].consumer_usage(),
+ slices_.size(), name_);
}
void ProducerChannel::HandleImpulse(Message& message) {
@@ -125,28 +132,28 @@
}
}
-NativeBufferHandle<BorrowedHandle> ProducerChannel::OnGetBuffer(
+Status<NativeBufferHandle<BorrowedHandle>> ProducerChannel::OnGetBuffer(
Message& message, unsigned index) {
ATRACE_NAME("ProducerChannel::OnGetBuffer");
ALOGD_IF(TRACE, "ProducerChannel::OnGetBuffer: buffer=%d", buffer_id());
if (index < slices_.size()) {
- return NativeBufferHandle<BorrowedHandle>(slices_[index], buffer_id());
+ return {NativeBufferHandle<BorrowedHandle>(slices_[index], buffer_id())};
} else {
- REPLY_ERROR_RETURN(message, EINVAL, NativeBufferHandle<BorrowedHandle>());
+ return ErrorStatus(EINVAL);
}
}
-std::vector<NativeBufferHandle<BorrowedHandle>> ProducerChannel::OnGetBuffers(
- Message&) {
+Status<std::vector<NativeBufferHandle<BorrowedHandle>>>
+ProducerChannel::OnGetBuffers(Message&) {
ATRACE_NAME("ProducerChannel::OnGetBuffers");
ALOGD_IF(TRACE, "ProducerChannel::OnGetBuffers: buffer_id=%d", buffer_id());
std::vector<NativeBufferHandle<BorrowedHandle>> buffer_handles;
for (const auto& buffer : slices_)
buffer_handles.emplace_back(buffer, buffer_id());
- return buffer_handles;
+ return {std::move(buffer_handles)};
}
-RemoteChannelHandle ProducerChannel::CreateConsumer(Message& message) {
+Status<RemoteChannelHandle> ProducerChannel::CreateConsumer(Message& message) {
ATRACE_NAME("ProducerChannel::CreateConsumer");
ALOGD_IF(TRACE, "ProducerChannel::CreateConsumer: buffer_id=%d", buffer_id());
@@ -154,9 +161,9 @@
auto status = message.PushChannel(0, nullptr, &channel_id);
if (!status) {
ALOGE(
- "ProducerChannel::CreateConsumer: failed to push consumer channel: %s",
+ "ProducerChannel::CreateConsumer: Failed to push consumer channel: %s",
status.GetErrorMessage().c_str());
- return RemoteChannelHandle();
+ return ErrorStatus(ENOMEM);
}
auto consumer = std::make_shared<ConsumerChannel>(
@@ -167,7 +174,7 @@
"ProducerChannel::CreateConsumer: failed to set new consumer channel: "
"%s",
channel_status.GetErrorMessage().c_str());
- return RemoteChannelHandle();
+ return ErrorStatus(ENOMEM);
}
if (!producer_owns_) {
@@ -176,33 +183,27 @@
pending_consumers_++;
}
- return status.take();
+ return {status.take()};
}
-RemoteChannelHandle ProducerChannel::OnNewConsumer(Message& message) {
+Status<RemoteChannelHandle> ProducerChannel::OnNewConsumer(Message& message) {
ATRACE_NAME("ProducerChannel::OnNewConsumer");
ALOGD_IF(TRACE, "ProducerChannel::OnNewConsumer: buffer_id=%d", buffer_id());
-
- RemoteChannelHandle consumer_handle(CreateConsumer(message));
-
- if (consumer_handle.valid())
- return consumer_handle;
- else
- REPLY_ERROR_RETURN(message, ENOMEM, RemoteChannelHandle());
+ return CreateConsumer(message);
}
-int ProducerChannel::OnProducerPost(
+Status<void> ProducerChannel::OnProducerPost(
Message&, LocalFence acquire_fence,
BufferWrapper<std::vector<std::uint8_t>> metadata) {
ATRACE_NAME("ProducerChannel::OnProducerPost");
ALOGD_IF(TRACE, "ProducerChannel::OnProducerPost: buffer_id=%d", buffer_id());
if (!producer_owns_) {
ALOGE("ProducerChannel::OnProducerPost: Not in gained state!");
- return -EBUSY;
+ return ErrorStatus(EBUSY);
}
if (meta_size_bytes_ != metadata.size())
- return -EINVAL;
+ return ErrorStatus(EINVAL);
std::copy(metadata.begin(), metadata.end(), meta_.get());
post_fence_ = std::move(acquire_fence);
@@ -220,29 +221,29 @@
ALOGD_IF(TRACE, "ProducerChannel::OnProducerPost: %d pending consumers",
pending_consumers_);
- return 0;
+ return {};
}
-LocalFence ProducerChannel::OnProducerGain(Message& message) {
+Status<LocalFence> ProducerChannel::OnProducerGain(Message& message) {
ATRACE_NAME("ProducerChannel::OnGain");
ALOGD_IF(TRACE, "ProducerChannel::OnGain: buffer_id=%d", buffer_id());
if (producer_owns_) {
ALOGE("ProducerChanneL::OnGain: Already in gained state: channel=%d",
channel_id());
- REPLY_ERROR_RETURN(message, EALREADY, {});
+ return ErrorStatus(EALREADY);
}
// There are still pending consumers, return busy.
if (pending_consumers_ > 0)
- REPLY_ERROR_RETURN(message, EBUSY, {});
+ return ErrorStatus(EBUSY);
ClearAvailable();
producer_owns_ = true;
post_fence_.close();
- return std::move(returned_fence_);
+ return {std::move(returned_fence_)};
}
-std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>>
+Status<std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>>>
ProducerChannel::OnConsumerAcquire(Message& message,
std::size_t metadata_size) {
ATRACE_NAME("ProducerChannel::OnConsumerAcquire");
@@ -250,26 +251,27 @@
buffer_id());
if (producer_owns_) {
ALOGE("ProducerChannel::OnConsumerAcquire: Not in posted state!");
- REPLY_ERROR_RETURN(message, EBUSY, {});
+ return ErrorStatus(EBUSY);
}
// Return a borrowed fd to avoid unnecessary duplication of the underlying fd.
// Serialization just needs to read the handle.
if (metadata_size == 0)
- return std::make_pair(post_fence_.borrow(),
- WrapBuffer<std::uint8_t>(nullptr, 0));
+ return {std::make_pair(post_fence_.borrow(),
+ WrapBuffer<std::uint8_t>(nullptr, 0))};
else
- return std::make_pair(post_fence_.borrow(),
- WrapBuffer(meta_.get(), meta_size_bytes_));
+ return {std::make_pair(post_fence_.borrow(),
+ WrapBuffer(meta_.get(), meta_size_bytes_))};
}
-int ProducerChannel::OnConsumerRelease(Message&, LocalFence release_fence) {
+Status<void> ProducerChannel::OnConsumerRelease(Message&,
+ LocalFence release_fence) {
ATRACE_NAME("ProducerChannel::OnConsumerRelease");
ALOGD_IF(TRACE, "ProducerChannel::OnConsumerRelease: buffer_id=%d",
buffer_id());
if (producer_owns_) {
ALOGE("ProducerChannel::OnConsumerRelease: Not in acquired state!");
- return -EBUSY;
+ return ErrorStatus(EBUSY);
}
// Attempt to merge the fences if necessary.
@@ -282,7 +284,7 @@
if (!merged_fence) {
ALOGE("ProducerChannel::OnConsumerRelease: Failed to merge fences: %s",
strerror(error));
- return -error;
+ return ErrorStatus(error);
}
returned_fence_ = std::move(merged_fence);
} else {
@@ -291,7 +293,7 @@
}
OnConsumerIgnored();
- return 0;
+ return {};
}
void ProducerChannel::OnConsumerIgnored() {
@@ -302,9 +304,10 @@
buffer_id(), pending_consumers_);
}
-int ProducerChannel::OnProducerMakePersistent(Message& message,
- const std::string& name,
- int user_id, int group_id) {
+Status<void> ProducerChannel::OnProducerMakePersistent(Message& message,
+ const std::string& name,
+ int user_id,
+ int group_id) {
ATRACE_NAME("ProducerChannel::OnProducerMakePersistent");
ALOGD_IF(TRACE,
"ProducerChannel::OnProducerMakePersistent: buffer_id=%d name=%s "
@@ -313,7 +316,7 @@
if (name.empty() || (user_id < 0 && user_id != kNoCheckId) ||
(group_id < 0 && group_id != kNoCheckId)) {
- return -EINVAL;
+ return ErrorStatus(EINVAL);
}
// Try to add this buffer with the requested name.
@@ -331,18 +334,18 @@
owner_user_id_ = user_id;
owner_group_id_ = group_id;
name_ = name;
- return 0;
+ return {};
} else {
// Otherwise a buffer with that name already exists.
- return -EALREADY;
+ return ErrorStatus(EALREADY);
}
}
-int ProducerChannel::OnRemovePersistence(Message&) {
+Status<void> ProducerChannel::OnRemovePersistence(Message&) {
if (service()->RemoveNamedBuffer(*this))
- return 0;
+ return {};
else
- return -ENOENT;
+ return ErrorStatus(ENOENT);
}
void ProducerChannel::AddConsumer(ConsumerChannel* channel) {
@@ -365,12 +368,16 @@
}
// Returns true if the given parameters match the underlying buffer parameters.
-bool ProducerChannel::CheckParameters(int width, int height, int format,
- int usage, size_t meta_size_bytes,
+bool ProducerChannel::CheckParameters(uint32_t width, uint32_t height,
+ uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage,
+ size_t meta_size_bytes,
size_t slice_count) {
return slices_.size() == slice_count && meta_size_bytes == meta_size_bytes_ &&
slices_[0].width() == width && slices_[0].height() == height &&
- slices_[0].format() == format && slices_[0].usage() == usage;
+ slices_[0].format() == format &&
+ slices_[0].producer_usage() == producer_usage &&
+ slices_[0].consumer_usage() == consumer_usage;
}
} // namespace dvr
diff --git a/services/vr/bufferhubd/producer_channel.h b/services/vr/bufferhubd/producer_channel.h
index e7ca459..f04c8a5 100644
--- a/services/vr/bufferhubd/producer_channel.h
+++ b/services/vr/bufferhubd/producer_channel.h
@@ -30,10 +30,10 @@
template <typename T>
using BufferWrapper = pdx::rpc::BufferWrapper<T>;
- static std::shared_ptr<ProducerChannel> Create(
- BufferHubService* service, int channel_id, int width, int height,
- int format, int usage, size_t meta_size_bytes, size_t slice_count,
- int* error);
+ static pdx::Status<std::shared_ptr<ProducerChannel>> Create(
+ BufferHubService* service, int channel_id, uint32_t width,
+ uint32_t height, uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage, size_t meta_size_bytes, size_t slice_count);
~ProducerChannel() override;
@@ -42,17 +42,18 @@
BufferInfo GetBufferInfo() const override;
- NativeBufferHandle<BorrowedHandle> OnGetBuffer(Message& message,
- unsigned index);
- std::vector<NativeBufferHandle<BorrowedHandle>> OnGetBuffers(
+ pdx::Status<NativeBufferHandle<BorrowedHandle>> OnGetBuffer(Message& message,
+ unsigned index);
+ pdx::Status<std::vector<NativeBufferHandle<BorrowedHandle>>> OnGetBuffers(
Message& message);
- RemoteChannelHandle CreateConsumer(Message& message);
- RemoteChannelHandle OnNewConsumer(Message& message);
+ pdx::Status<RemoteChannelHandle> CreateConsumer(Message& message);
+ pdx::Status<RemoteChannelHandle> OnNewConsumer(Message& message);
- std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>> OnConsumerAcquire(
- Message& message, std::size_t metadata_size);
- int OnConsumerRelease(Message& message, LocalFence release_fence);
+ pdx::Status<std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>>>
+ OnConsumerAcquire(Message& message, std::size_t metadata_size);
+ pdx::Status<void> OnConsumerRelease(Message& message,
+ LocalFence release_fence);
void OnConsumerIgnored();
@@ -60,12 +61,14 @@
void RemoveConsumer(ConsumerChannel* channel);
bool CheckAccess(int euid, int egid);
- bool CheckParameters(int width, int height, int format, int usage,
+ bool CheckParameters(uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage,
size_t meta_size_bytes, size_t slice_count);
- int OnProducerMakePersistent(Message& message, const std::string& name,
- int user_id, int group_id);
- int OnRemovePersistence(Message& message);
+ pdx::Status<void> OnProducerMakePersistent(Message& message,
+ const std::string& name,
+ int user_id, int group_id);
+ pdx::Status<void> OnRemovePersistence(Message& message);
private:
std::vector<ConsumerChannel*> consumer_channels_;
@@ -91,13 +94,15 @@
std::string name_;
- ProducerChannel(BufferHubService* service, int channel, int width, int height,
- int format, int usage, size_t meta_size_bytes,
+ ProducerChannel(BufferHubService* service, int channel, uint32_t width,
+ uint32_t height, uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage, size_t meta_size_bytes,
size_t slice_count, int* error);
- int OnProducerPost(Message& message, LocalFence acquire_fence,
- BufferWrapper<std::vector<std::uint8_t>> metadata);
- LocalFence OnProducerGain(Message& message);
+ pdx::Status<void> OnProducerPost(
+ Message& message, LocalFence acquire_fence,
+ BufferWrapper<std::vector<std::uint8_t>> metadata);
+ pdx::Status<LocalFence> OnProducerGain(Message& message);
ProducerChannel(const ProducerChannel&) = delete;
void operator=(const ProducerChannel&) = delete;
diff --git a/services/vr/bufferhubd/producer_queue_channel.cpp b/services/vr/bufferhubd/producer_queue_channel.cpp
index 7952642..dc2a47e 100644
--- a/services/vr/bufferhubd/producer_queue_channel.cpp
+++ b/services/vr/bufferhubd/producer_queue_channel.cpp
@@ -1,24 +1,27 @@
#include "producer_queue_channel.h"
+#include <inttypes.h>
+
#include "consumer_queue_channel.h"
#include "producer_channel.h"
+using android::pdx::ErrorStatus;
+using android::pdx::Message;
+using android::pdx::Status;
using android::pdx::RemoteChannelHandle;
using android::pdx::rpc::DispatchRemoteMethod;
namespace android {
namespace dvr {
-ProducerQueueChannel::ProducerQueueChannel(
- BufferHubService* service, int channel_id, size_t meta_size_bytes,
- int usage_set_mask, int usage_clear_mask, int usage_deny_set_mask,
- int usage_deny_clear_mask, int* error)
+ProducerQueueChannel::ProducerQueueChannel(BufferHubService* service,
+ int channel_id,
+ size_t meta_size_bytes,
+ const UsagePolicy& usage_policy,
+ int* error)
: BufferHubChannel(service, channel_id, channel_id, kProducerQueueType),
meta_size_bytes_(meta_size_bytes),
- usage_set_mask_(usage_set_mask),
- usage_clear_mask_(usage_clear_mask),
- usage_deny_set_mask_(usage_deny_set_mask),
- usage_deny_clear_mask_(usage_deny_clear_mask),
+ usage_policy_(usage_policy),
capacity_(0) {
*error = 0;
}
@@ -26,28 +29,34 @@
ProducerQueueChannel::~ProducerQueueChannel() {}
/* static */
-std::shared_ptr<ProducerQueueChannel> ProducerQueueChannel::Create(
+Status<std::shared_ptr<ProducerQueueChannel>> ProducerQueueChannel::Create(
BufferHubService* service, int channel_id, size_t meta_size_bytes,
- int usage_set_mask, int usage_clear_mask, int usage_deny_set_mask,
- int usage_deny_clear_mask, int* error) {
+ const UsagePolicy& usage_policy) {
// Configuration between |usage_deny_set_mask| and |usage_deny_clear_mask|
// should be mutually exclusive.
- if (usage_deny_set_mask & usage_deny_clear_mask) {
+ if ((usage_policy.producer_deny_set_mask &
+ usage_policy.producer_deny_clear_mask) ||
+ (usage_policy.consumer_deny_set_mask &
+ usage_policy.consumer_deny_clear_mask)) {
ALOGE(
"BufferHubService::OnCreateProducerQueue: illegal usage mask "
- "configuration: usage_deny_set_mask=%d, usage_deny_clear_mask=%d",
- usage_deny_set_mask, usage_deny_clear_mask);
- *error = -EINVAL;
- return nullptr;
+ "configuration: producer_deny_set_mask=%" PRIx64
+ " producer_deny_clear_mask=%" PRIx64 " consumer_deny_set_mask=%" PRIx64
+ " consumer_deny_clear_mask=%" PRIx64,
+ usage_policy.producer_deny_set_mask,
+ usage_policy.producer_deny_clear_mask,
+ usage_policy.consumer_deny_set_mask,
+ usage_policy.consumer_deny_clear_mask);
+ return ErrorStatus(EINVAL);
}
+ int error = 0;
std::shared_ptr<ProducerQueueChannel> producer(new ProducerQueueChannel(
- service, channel_id, meta_size_bytes, usage_set_mask, usage_clear_mask,
- usage_deny_set_mask, usage_deny_clear_mask, error));
- if (*error < 0)
- return nullptr;
+ service, channel_id, meta_size_bytes, usage_policy, &error));
+ if (error < 0)
+ return ErrorStatus(-error);
else
- return producer;
+ return {std::move(producer)};
}
bool ProducerQueueChannel::HandleMessage(Message& message) {
@@ -58,6 +67,11 @@
*this, &ProducerQueueChannel::OnCreateConsumerQueue, message);
return true;
+ case BufferHubRPC::GetQueueInfo::Opcode:
+ DispatchRemoteMethod<BufferHubRPC::GetQueueInfo>(
+ *this, &ProducerQueueChannel::OnGetQueueInfo, message);
+ return true;
+
case BufferHubRPC::ProducerQueueAllocateBuffers::Opcode:
DispatchRemoteMethod<BufferHubRPC::ProducerQueueAllocateBuffers>(
*this, &ProducerQueueChannel::OnProducerQueueAllocateBuffers,
@@ -80,12 +94,11 @@
BufferHubChannel::BufferInfo ProducerQueueChannel::GetBufferInfo() const {
return BufferInfo(channel_id(), consumer_channels_.size(), capacity_,
- usage_set_mask_, usage_clear_mask_, usage_deny_set_mask_,
- usage_deny_clear_mask_);
+ usage_policy_);
}
-std::pair<RemoteChannelHandle, size_t>
-ProducerQueueChannel::OnCreateConsumerQueue(Message& message) {
+Status<RemoteChannelHandle> ProducerQueueChannel::OnCreateConsumerQueue(
+ Message& message) {
ATRACE_NAME("ProducerQueueChannel::OnCreateConsumerQueue");
ALOGD_IF(TRACE, "ProducerQueueChannel::OnCreateConsumerQueue: channel_id=%d",
channel_id());
@@ -97,7 +110,7 @@
"ProducerQueueChannel::OnCreateConsumerQueue: failed to push consumer "
"channel: %s",
status.GetErrorMessage().c_str());
- REPLY_ERROR_RETURN(message, status.error(), {});
+ return ErrorStatus(ENOMEM);
}
const auto channel_status = service()->SetChannel(
@@ -108,18 +121,21 @@
"ProducerQueueChannel::OnCreateConsumerQueue: failed to set new "
"consumer channel: %s",
channel_status.GetErrorMessage().c_str());
- REPLY_ERROR_RETURN(message, channel_status.error(), {});
+ return ErrorStatus(ENOMEM);
}
- return std::make_pair(status.take(), meta_size_bytes_);
+ return {status.take()};
}
-std::vector<std::pair<RemoteChannelHandle, size_t>>
-ProducerQueueChannel::OnProducerQueueAllocateBuffers(Message& message,
- int width, int height,
- int format, int usage,
- size_t slice_count,
- size_t buffer_count) {
+Status<QueueInfo> ProducerQueueChannel::OnGetQueueInfo(Message&) {
+ return {{meta_size_bytes_, buffer_id()}};
+}
+
+Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
+ProducerQueueChannel::OnProducerQueueAllocateBuffers(
+ Message& message, uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage, size_t slice_count,
+ size_t buffer_count) {
ATRACE_NAME("ProducerQueueChannel::OnProducerQueueAllocateBuffers");
ALOGD_IF(TRACE,
"ProducerQueueChannel::OnProducerQueueAllocateBuffers: "
@@ -129,47 +145,76 @@
std::vector<std::pair<RemoteChannelHandle, size_t>> buffer_handles;
// Deny buffer allocation violating preset rules.
- if (usage & usage_deny_set_mask_) {
+ if (producer_usage & usage_policy_.producer_deny_set_mask) {
ALOGE(
- "ProducerQueueChannel::OnProducerQueueAllocateBuffers: usage: %d is "
- "not permitted. Violating usage_deny_set_mask, the following bits "
- "shall not be set: %d.",
- usage, usage_deny_set_mask_);
- REPLY_ERROR_RETURN(message, EINVAL, buffer_handles);
+ "ProducerQueueChannel::OnProducerQueueAllocateBuffers: producer_usage: "
+ "%" PRIx64
+ " is not permitted. Violating producer_deny_set_mask, the following "
+ "bits shall not be set: %" PRIx64 ".",
+ producer_usage, usage_policy_.producer_deny_set_mask);
+ return ErrorStatus(EINVAL);
}
- if (~usage & usage_deny_clear_mask_) {
+ if (consumer_usage & usage_policy_.consumer_deny_set_mask) {
ALOGE(
- "ProducerQueueChannel::OnProducerQueueAllocateBuffers: usage: %d is "
- "not permitted. Violating usage_deny_clear_mask, the following bits "
- "must be set: %d.",
- usage, usage_deny_clear_mask_);
- REPLY_ERROR_RETURN(message, EINVAL, buffer_handles);
+ "ProducerQueueChannel::OnProducerQueueAllocateBuffers: consumer_usage: "
+ "%" PRIx64
+ " is not permitted. Violating consumer_deny_set_mask, the following "
+ "bits shall not be set: %" PRIx64 ".",
+ consumer_usage, usage_policy_.consumer_deny_set_mask);
+ return ErrorStatus(EINVAL);
}
- // Force set mask and clear mask. Note that |usage_set_mask_| takes precedence
- // and will overwrite |usage_clear_mask_|.
- int effective_usage = (usage & ~usage_clear_mask_) | usage_set_mask_;
+ if (~producer_usage & usage_policy_.producer_deny_clear_mask) {
+ ALOGE(
+ "ProducerQueueChannel::OnProducerQueueAllocateBuffers: producer_usage: "
+ "%" PRIx64
+ " is not permitted. Violating producer_deny_clear_mask, the following "
+ "bits must be set: %" PRIx64 ".",
+ producer_usage, usage_policy_.producer_deny_clear_mask);
+ return ErrorStatus(EINVAL);
+ }
+
+ if (~consumer_usage & usage_policy_.consumer_deny_clear_mask) {
+ ALOGE(
+ "ProducerQueueChannel::OnProducerQueueAllocateBuffers: consumer_usage: "
+ "%" PRIx64
+ " is not permitted. Violating consumer_deny_clear_mask, the following "
+ "bits must be set: %" PRIx64 ".",
+ consumer_usage, usage_policy_.consumer_deny_clear_mask);
+ return ErrorStatus(EINVAL);
+ }
+ // Force set mask and clear mask. Note that |usage_policy_.X_set_mask_| takes
+ // precedence and will overwrite |usage_policy_.X_clear_mask|.
+ uint64_t effective_producer_usage =
+ (producer_usage & ~usage_policy_.producer_clear_mask) |
+ usage_policy_.producer_set_mask;
+ uint64_t effective_consumer_usage =
+ (consumer_usage & ~usage_policy_.consumer_clear_mask) |
+ usage_policy_.consumer_set_mask;
for (size_t i = 0; i < buffer_count; i++) {
- auto buffer_handle_slot = AllocateBuffer(message, width, height, format,
- effective_usage, slice_count);
- if (!buffer_handle_slot.first) {
+ auto status =
+ AllocateBuffer(message, width, height, format, effective_producer_usage,
+ effective_consumer_usage, slice_count);
+ if (!status) {
ALOGE(
- "ProducerQueueChannel::OnProducerQueueAllocateBuffers: failed to "
+ "ProducerQueueChannel::OnProducerQueueAllocateBuffers: Failed to "
"allocate new buffer.");
- REPLY_ERROR_RETURN(message, ENOMEM, buffer_handles);
+ return ErrorStatus(status.error());
}
- buffer_handles.emplace_back(std::move(buffer_handle_slot.first),
- buffer_handle_slot.second);
+ buffer_handles.push_back(status.take());
}
- return buffer_handles;
+ return {std::move(buffer_handles)};
}
-std::pair<RemoteChannelHandle, size_t> ProducerQueueChannel::AllocateBuffer(
- Message& message, int width, int height, int format, int usage,
- size_t slice_count) {
+Status<std::pair<RemoteChannelHandle, size_t>>
+ProducerQueueChannel::AllocateBuffer(Message& message, uint32_t width,
+ uint32_t height, uint32_t format,
+ uint64_t producer_usage,
+ uint64_t consumer_usage,
+ size_t slice_count) {
ATRACE_NAME("ProducerQueueChannel::AllocateBuffer");
ALOGD_IF(TRACE,
"ProducerQueueChannel::AllocateBuffer: producer_channel_id=%d",
@@ -177,7 +222,7 @@
if (capacity_ >= BufferHubRPC::kMaxQueueCapacity) {
ALOGE("ProducerQueueChannel::AllocateBuffer: reaches kMaxQueueCapacity.");
- return {};
+ return ErrorStatus(E2BIG);
}
// Here we are creating a new BufferHubBuffer, initialize the producer
@@ -189,25 +234,28 @@
if (!status) {
ALOGE("ProducerQueueChannel::AllocateBuffer: failed to push channel: %s",
status.GetErrorMessage().c_str());
- return {};
+ return ErrorStatus(status.error());
}
ALOGD_IF(TRACE,
- "ProducerQueueChannel::AllocateBuffer: buffer_id=%d width=%d "
- "height=%d format=%d usage=%d slice_count=%zu",
- buffer_id, width, height, format, usage, slice_count);
+ "ProducerQueueChannel::AllocateBuffer: buffer_id=%d width=%u "
+ "height=%u format=%u producer_usage=%" PRIx64
+ " consumer_usage=%" PRIx64 " slice_count=%zu",
+ buffer_id, width, height, format, producer_usage, consumer_usage,
+ slice_count);
auto buffer_handle = status.take();
- int error;
- const auto producer_channel = ProducerChannel::Create(
- service(), buffer_id, width, height, format, usage,
- meta_size_bytes_, slice_count, &error);
- if (!producer_channel) {
+ auto producer_channel_status = ProducerChannel::Create(
+ service(), buffer_id, width, height, format, producer_usage,
+ consumer_usage, meta_size_bytes_, slice_count);
+ if (!producer_channel_status) {
ALOGE(
- "ProducerQueueChannel::AllocateBuffer: Failed to create "
- "BufferHubBuffer producer!!");
- return {};
+ "ProducerQueueChannel::AllocateBuffer: Failed to create producer "
+ "buffer: %s",
+ producer_channel_status.GetErrorMessage().c_str());
+ return ErrorStatus(ENOMEM);
}
+ auto producer_channel = producer_channel_status.take();
ALOGD_IF(
TRACE,
@@ -221,7 +269,7 @@
"ProducerQueueChannel::AllocateBuffer: failed to set producer channel "
"for new BufferHubBuffer: %s",
channel_status.GetErrorMessage().c_str());
- return {};
+ return ErrorStatus(ENOMEM);
}
// Register the newly allocated buffer's channel_id into the first empty
@@ -235,7 +283,7 @@
ALOGE(
"ProducerQueueChannel::AllocateBuffer: Cannot find empty slot for new "
"buffer allocation.");
- return {};
+ return ErrorStatus(E2BIG);
}
buffers_[slot] = producer_channel;
@@ -250,29 +298,29 @@
consumer_channel->RegisterNewBuffer(producer_channel, slot);
}
- return {std::move(buffer_handle), slot};
+ return {{std::move(buffer_handle), slot}};
}
-int ProducerQueueChannel::OnProducerQueueDetachBuffer(Message& /*message*/,
- size_t slot) {
+Status<void> ProducerQueueChannel::OnProducerQueueDetachBuffer(
+ Message& /*message*/, size_t slot) {
if (buffers_[slot].expired()) {
ALOGE(
"ProducerQueueChannel::OnProducerQueueDetachBuffer: trying to detach "
"an invalid buffer producer at slot %zu",
slot);
- return -EINVAL;
+ return ErrorStatus(EINVAL);
}
if (capacity_ == 0) {
ALOGE(
"ProducerQueueChannel::OnProducerQueueDetachBuffer: trying to detach a "
"buffer producer while the queue's capacity is already zero.");
- return -EINVAL;
+ return ErrorStatus(EINVAL);
}
buffers_[slot].reset();
capacity_--;
- return 0;
+ return {};
}
void ProducerQueueChannel::AddConsumer(ConsumerQueueChannel* channel) {
diff --git a/services/vr/bufferhubd/producer_queue_channel.h b/services/vr/bufferhubd/producer_queue_channel.h
index 49611d4..09b0243 100644
--- a/services/vr/bufferhubd/producer_queue_channel.h
+++ b/services/vr/bufferhubd/producer_queue_channel.h
@@ -3,6 +3,7 @@
#include "buffer_hub.h"
+#include <pdx/status.h>
#include <private/dvr/bufferhub_rpc.h>
namespace android {
@@ -10,17 +11,13 @@
class ProducerQueueChannel : public BufferHubChannel {
public:
- using Message = pdx::Message;
- using RemoteChannelHandle = pdx::RemoteChannelHandle;
-
- static std::shared_ptr<ProducerQueueChannel> Create(
+ static pdx::Status<std::shared_ptr<ProducerQueueChannel>> Create(
BufferHubService* service, int channel_id, size_t meta_size_bytes,
- int usage_set_mask, int usage_clear_mask, int usage_deny_set_mask,
- int usage_deny_clear_mask, int* error);
+ const UsagePolicy& usage_policy);
~ProducerQueueChannel() override;
- bool HandleMessage(Message& message) override;
- void HandleImpulse(Message& message) override;
+ bool HandleMessage(pdx::Message& message) override;
+ void HandleImpulse(pdx::Message& message) override;
BufferInfo GetBufferInfo() const override;
@@ -28,38 +25,41 @@
// producer queue.
// Returns a handle for the service channel, as well as the size of the
// metadata associated with the queue.
- std::pair<RemoteChannelHandle, size_t> OnCreateConsumerQueue(
- Message& message);
+ pdx::Status<pdx::RemoteChannelHandle> OnCreateConsumerQueue(
+ pdx::Message& message);
+
+ pdx::Status<QueueInfo> OnGetQueueInfo(pdx::Message& message);
// Allocate a new BufferHubProducer according to the input spec. Client may
// handle this as if a new producer is created through kOpCreateBuffer.
- std::vector<std::pair<RemoteChannelHandle, size_t>>
- OnProducerQueueAllocateBuffers(Message& message, int width, int height,
- int format, int usage, size_t slice_count,
+ pdx::Status<std::vector<std::pair<pdx::RemoteChannelHandle, size_t>>>
+ OnProducerQueueAllocateBuffers(pdx::Message& message, uint32_t width,
+ uint32_t height, uint32_t format,
+ uint64_t producer_usage,
+ uint64_t consumer_usage, size_t slice_count,
size_t buffer_count);
// Detach a BufferHubProducer indicated by |slot|. Note that the buffer must
// be in Gain'ed state for the producer queue to detach.
- int OnProducerQueueDetachBuffer(Message& message, size_t slot);
+ pdx::Status<void> OnProducerQueueDetachBuffer(pdx::Message& message,
+ size_t slot);
void AddConsumer(ConsumerQueueChannel* channel);
void RemoveConsumer(ConsumerQueueChannel* channel);
private:
ProducerQueueChannel(BufferHubService* service, int channel_id,
- size_t meta_size_bytes, int usage_set_mask,
- int usage_clear_mask, int usage_deny_set_mask,
- int usage_deny_clear_mask, int* error);
+ size_t meta_size_bytes, const UsagePolicy& usage_policy,
+ int* error);
// Allocate one single producer buffer by |OnProducerQueueAllocateBuffers|.
// Note that the newly created buffer's file handle will be pushed to client
// and our return type is a RemoteChannelHandle.
- // Returns the remote channdel handle and the slot number for the newly
+ // Returns the remote channel handle and the slot number for the newly
// allocated buffer.
- std::pair<RemoteChannelHandle, size_t> AllocateBuffer(Message& message,
- int width, int height,
- int format, int usage,
- size_t slice_count);
+ pdx::Status<std::pair<pdx::RemoteChannelHandle, size_t>> AllocateBuffer(
+ pdx::Message& message, uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage, size_t slice_count);
// Size of the meta data associated with all the buffers allocated from the
// queue. Now we assume the metadata size is immutable once the queue is
@@ -68,10 +68,7 @@
// A set of variables to control what |usage| bits can this ProducerQueue
// allocate.
- int usage_set_mask_;
- int usage_clear_mask_;
- int usage_deny_set_mask_;
- int usage_deny_clear_mask_;
+ UsagePolicy usage_policy_;
// Provides access to the |channel_id| of all consumer channels associated
// with this producer.
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index 629d65b..b94d333 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -56,7 +56,7 @@
"libvr_hwc-binder",
],
shared_libs: [
- "android.dvr.composer@1.0",
+ "android.frameworks.vr.composer@1.0",
"android.hardware.graphics.composer@2.1",
"libbase",
"libbinder",
diff --git a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.cpp b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.cpp
index 999d71e..15f63fa 100644
--- a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.cpp
+++ b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.cpp
@@ -7,41 +7,6 @@
namespace android {
namespace dvr {
-namespace {
-
-sp<GraphicBuffer> GetBufferFromHandle(native_handle_t* handle) {
- uint32_t width = 0, height = 0, stride = 0, layer_count = 1;
- uint64_t producer_usage = 0, consumer_usage = 0;
- int32_t format = 0;
-
- GraphicBufferMapper& mapper = GraphicBufferMapper::get();
- // Need to register |handle| otherwise we can't read its properties.
- if (mapper.registerBuffer(handle) != OK) {
- ALOGE("Failed to register buffer");
- return nullptr;
- }
-
- if (mapper.getDimensions(handle, &width, &height) ||
- mapper.getStride(handle, &stride) ||
- mapper.getFormat(handle, &format) ||
- mapper.getProducerUsage(handle, &producer_usage) ||
- mapper.getConsumerUsage(handle, &consumer_usage)) {
- ALOGE("Failed to read handle properties");
- return nullptr;
- }
-
- // This will only succeed if gralloc has GRALLOC1_CAPABILITY_LAYERED_BUFFERS
- // capability. Otherwise assume a count of 1.
- mapper.getLayerCount(handle, &layer_count);
-
- sp<GraphicBuffer> buffer = new GraphicBuffer(handle,
- GraphicBuffer::TAKE_HANDLE, width, height, format, layer_count,
- producer_usage, consumer_usage, stride);
-
- return buffer;
-}
-
-} // namespace
ParcelableComposerLayer::ParcelableComposerLayer() {}
@@ -54,7 +19,7 @@
status_t ret = parcel->writeUint64(layer_.id);
if (ret != OK) return ret;
- ret = parcel->writeNativeHandle(layer_.buffer->getNativeBuffer()->handle);
+ ret = parcel->write(*layer_.buffer);
if (ret != OK) return ret;
ret = parcel->writeBool(layer_.fence->isValid());
@@ -108,11 +73,12 @@
status_t ret = parcel->readUint64(&layer_.id);
if (ret != OK) return ret;
- native_handle* handle = parcel->readNativeHandle();
- if (!handle) return BAD_VALUE;
-
- layer_.buffer = GetBufferFromHandle(handle);
- if (!layer_.buffer.get()) return BAD_VALUE;
+ layer_.buffer = new GraphicBuffer();
+ ret = parcel->read(*layer_.buffer);
+ if (ret != OK) {
+ layer_.buffer.clear();
+ return ret;
+ }
bool has_fence = 0;
ret = parcel->readBool(&has_fence);
diff --git a/services/vr/sensord/Android.mk b/services/vr/sensord/Android.mk
index ba0821b..638c9a8 100644
--- a/services/vr/sensord/Android.mk
+++ b/services/vr/sensord/Android.mk
@@ -51,8 +51,6 @@
-DTRACE=0
include $(CLEAR_VARS)
-# Don't strip symbols so we see stack traces in logcat.
-LOCAL_STRIP_MODULE := false
LOCAL_SRC_FILES := $(sourceFiles)
LOCAL_CFLAGS := $(cFlags)
LOCAL_STATIC_LIBRARIES := $(staticLibraries)
diff --git a/services/vr/sensord/pose_service.cpp b/services/vr/sensord/pose_service.cpp
index 7534732..e3f8171 100644
--- a/services/vr/sensord/pose_service.cpp
+++ b/services/vr/sensord/pose_service.cpp
@@ -65,8 +65,7 @@
static constexpr int kDatasetIdLength = 36;
static constexpr char kDatasetIdChars[] = "0123456789abcdef-";
-static constexpr int kLatencyWindowSize = 100;
-static constexpr double kLatencyWindowMass = 0.5;
+static constexpr int kLatencyWindowSize = 200;
// These are the flags used by BufferProducer::CreatePersistentUncachedBlob,
// plus PRIVATE_ADSP_HEAP to allow access from the DSP.
@@ -115,7 +114,7 @@
photon_timestamp_(0),
// Will be updated by external service, but start with a non-zero value:
display_period_ns_(16000000),
- sensor_latency_(kLatencyWindowSize, kLatencyWindowMass) {
+ sensor_latency_(kLatencyWindowSize) {
last_known_pose_ = {
.orientation = {1.0f, 0.0f, 0.0f, 0.0f},
.translation = {0.0f, 0.0f, 0.0f, 0.0f},
diff --git a/services/vr/virtual_touchpad/main.cpp b/services/vr/virtual_touchpad/main.cpp
index 68f1d70..55ac9bf 100644
--- a/services/vr/virtual_touchpad/main.cpp
+++ b/services/vr/virtual_touchpad/main.cpp
@@ -8,8 +8,9 @@
int main() {
ALOGI("Starting");
- android::dvr::VirtualTouchpadService touchpad_service(
- std::move(android::dvr::VirtualTouchpadEvdev::Create()));
+ android::sp<android::dvr::VirtualTouchpadService> touchpad_service =
+ new android::dvr::VirtualTouchpadService(
+ android::dvr::VirtualTouchpadEvdev::Create());
signal(SIGPIPE, SIG_IGN);
android::sp<android::ProcessState> ps(android::ProcessState::self());
@@ -19,8 +20,8 @@
android::sp<android::IServiceManager> sm(android::defaultServiceManager());
const android::status_t service_status =
- sm->addService(android::String16(touchpad_service.SERVICE_NAME()),
- &touchpad_service, false /*allowIsolated*/);
+ sm->addService(android::String16(touchpad_service->SERVICE_NAME()),
+ touchpad_service, false /*allowIsolated*/);
if (service_status != android::OK) {
ALOGE("virtual touchpad service not added: %d",
static_cast<int>(service_status));
diff --git a/services/vr/vr_window_manager/Android.bp b/services/vr/vr_window_manager/Android.bp
index 0406331..669426b 100644
--- a/services/vr/vr_window_manager/Android.bp
+++ b/services/vr/vr_window_manager/Android.bp
@@ -47,7 +47,7 @@
]
shared_libs = [
- "android.dvr.composer@1.0",
+ "android.frameworks.vr.composer@1.0",
"android.hardware.graphics.composer@2.1",
"libvrhwc",
"libbase",
diff --git a/services/vr/vr_window_manager/application.cpp b/services/vr/vr_window_manager/application.cpp
index b2f02e5..8b4460a 100644
--- a/services/vr/vr_window_manager/application.cpp
+++ b/services/vr/vr_window_manager/application.cpp
@@ -206,8 +206,9 @@
if (fade_value_ > 1.0f)
fade_value_ = 1.0f;
- controller_position_ = elbow_model_.Update(delta, last_pose_.GetRotation(),
- controller_orientation_, false);
+ controller_position_ =
+ elbow_model_.Update(delta, last_pose_.GetRotation(),
+ controller_orientation_, should_recenter_);
dvrBeginRenderFrameEds(graphics_context_, pose.orientation,
pose.translation);
@@ -233,6 +234,7 @@
OnEndFrame();
dvrPresent(graphics_context_);
+ should_recenter_ = false;
}
}
diff --git a/services/vr/vr_window_manager/application.h b/services/vr/vr_window_manager/application.h
index 4b36ecc..ed99157 100644
--- a/services/vr/vr_window_manager/application.h
+++ b/services/vr/vr_window_manager/application.h
@@ -80,6 +80,9 @@
bool shmem_controller_active_ = false;
uint64_t shmem_controller_buttons_;
+ // Used to center the scene when the shell becomes visible.
+ bool should_recenter_ = true;
+
bool is_visible_ = false;
std::chrono::time_point<std::chrono::system_clock> visibility_button_press_;
bool debug_mode_ = false;
diff --git a/services/vr/vr_window_manager/composer/1.0/Android.bp b/services/vr/vr_window_manager/composer/1.0/Android.bp
deleted file mode 100644
index 58f83f8..0000000
--- a/services/vr/vr_window_manager/composer/1.0/Android.bp
+++ /dev/null
@@ -1,54 +0,0 @@
-// This file is autogenerated by hidl-gen. Do not edit manually.
-
-genrule {
- name: "android.dvr.composer@1.0_genc++",
- tools: ["hidl-gen"],
- cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hidl:system/libhidl/transport -randroid.hardware:hardware/interfaces/ -randroid.dvr:frameworks/native/services/vr/vr_window_manager android.dvr.composer@1.0",
- srcs: [
- "IVrComposerClient.hal",
- ],
- out: [
- "android/dvr/composer/1.0/VrComposerClientAll.cpp",
- ],
-}
-
-genrule {
- name: "android.dvr.composer@1.0_genc++_headers",
- tools: ["hidl-gen"],
- cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hidl:system/libhidl/transport -randroid.hardware:hardware/interfaces/ -randroid.dvr:frameworks/native/services/vr/vr_window_manager android.dvr.composer@1.0",
- srcs: [
- "IVrComposerClient.hal",
- ],
- out: [
- "android/dvr/composer/1.0/IVrComposerClient.h",
- "android/dvr/composer/1.0/IHwVrComposerClient.h",
- "android/dvr/composer/1.0/BnHwVrComposerClient.h",
- "android/dvr/composer/1.0/BpHwVrComposerClient.h",
- "android/dvr/composer/1.0/BsVrComposerClient.h",
- ],
-}
-
-cc_library_shared {
- name: "android.dvr.composer@1.0",
- generated_sources: ["android.dvr.composer@1.0_genc++"],
- generated_headers: ["android.dvr.composer@1.0_genc++_headers"],
- export_generated_headers: ["android.dvr.composer@1.0_genc++_headers"],
- shared_libs: [
- "libhidlbase",
- "libhidltransport",
- "libhwbinder",
- "liblog",
- "libutils",
- "libcutils",
- "android.hardware.graphics.composer@2.1",
- "android.hidl.base@1.0",
- ],
- export_shared_lib_headers: [
- "libhidlbase",
- "libhidltransport",
- "libhwbinder",
- "libutils",
- "android.hardware.graphics.composer@2.1",
- "android.hidl.base@1.0",
- ],
-}
diff --git a/services/vr/vr_window_manager/composer/1.0/IVrComposerClient.hal b/services/vr/vr_window_manager/composer/1.0/IVrComposerClient.hal
deleted file mode 100644
index 230a68a..0000000
--- a/services/vr/vr_window_manager/composer/1.0/IVrComposerClient.hal
+++ /dev/null
@@ -1,49 +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.
- */
-package android.dvr.composer@1.0;
-
-import android.hardware.graphics.composer@2.1::IComposerClient;
-
-interface IVrComposerClient
- extends android.hardware.graphics.composer@2.1::IComposerClient {
- /*
- * Used to annotate the layer with additional information, which will be
- * used to describe the content of the layer (ie: notification, permission,
- * etc) which allows VR window manager to treat certain layer types
- * specially.
- *
- * @param display is the display on which the layer was created.
- * @param layer is the layer affected by the change.
- * @param layer_type the type of the layer as described by the window
- * manager.
- * @param application_id the application id the layer belongs to.
- * @return error is NONE upon success. Otherwise,
- * BAD_DISPLAY when an invalid display handle was passed in.
- * BAD_LAYER when an invalid layer handle was passed in.
- *
- * setLayerInfo(Display display,
- * Layer layer,
- * uint32_t layer_type,
- * uint32_t application_id)
- * generates(Error error);
- */
-
- enum VrCommand : int32_t {
- OPCODE_SHIFT = android.hardware.graphics.composer@2.1::IComposerClient.Command:OPCODE_SHIFT,
-
- SET_LAYER_INFO = 0x800 << OPCODE_SHIFT,
- };
-};
diff --git a/services/vr/vr_window_manager/composer/Android.bp b/services/vr/vr_window_manager/composer/Android.bp
index f28818a..1998749 100644
--- a/services/vr/vr_window_manager/composer/Android.bp
+++ b/services/vr/vr_window_manager/composer/Android.bp
@@ -1,7 +1,3 @@
-subdirs = [
- "1.0",
-]
-
cc_library_shared {
name: "libvrhwc",
@@ -14,13 +10,13 @@
static_libs: [
"libhwcomposer-client",
"libdisplay",
- "libpdx_default_transport",
- "libbufferhub",
"libbufferhubqueue",
+ "libbufferhub",
+ "libpdx_default_transport",
],
shared_libs: [
- "android.dvr.composer@1.0",
+ "android.frameworks.vr.composer@1.0",
"android.hardware.graphics.composer@2.1",
"libbase",
"libcutils",
@@ -39,6 +35,7 @@
],
export_shared_lib_headers: [
+ "android.frameworks.vr.composer@1.0",
"android.hardware.graphics.composer@2.1",
],
diff --git a/services/vr/vr_window_manager/composer/impl/vr_composer_client.cpp b/services/vr/vr_window_manager/composer/impl/vr_composer_client.cpp
index 367acb7..e0bdf1c 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_composer_client.cpp
+++ b/services/vr/vr_window_manager/composer/impl/vr_composer_client.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include <android/dvr/composer/1.0/IVrComposerClient.h>
+#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
#include <hardware/gralloc.h>
#include <hardware/gralloc1.h>
#include <log/log.h>
@@ -26,7 +26,7 @@
namespace dvr {
using android::hardware::graphics::common::V1_0::PixelFormat;
-using android::dvr::composer::V1_0::IVrComposerClient;
+using android::frameworks::vr::composer::V1_0::IVrComposerClient;
VrComposerClient::VrComposerClient(dvr::VrHwc& hal)
: ComposerClient(hal), mVrHal(hal) {}
@@ -50,6 +50,10 @@
switch (vrCommand) {
case IVrComposerClient::VrCommand::SET_LAYER_INFO:
return parseSetLayerInfo(length);
+ case IVrComposerClient::VrCommand::SET_CLIENT_TARGET_METADATA:
+ return parseSetClientTargetMetadata(length);
+ case IVrComposerClient::VrCommand::SET_LAYER_BUFFER_METADATA:
+ return parseSetLayerBufferMetadata(length);
default:
return CommandReader::parseCommand(command, length);
}
@@ -68,5 +72,43 @@
return true;
}
+bool VrComposerClient::VrCommandReader::parseSetClientTargetMetadata(
+ uint16_t length) {
+ if (length != 7)
+ return false;
+
+ auto err = mVrHal.setClientTargetMetadata(mDisplay, readBufferMetadata());
+ if (err != Error::NONE)
+ mWriter.setError(getCommandLoc(), err);
+
+ return true;
+}
+
+bool VrComposerClient::VrCommandReader::parseSetLayerBufferMetadata(
+ uint16_t length) {
+ if (length != 7)
+ return false;
+
+ auto err = mVrHal.setLayerBufferMetadata(mDisplay, mLayer,
+ readBufferMetadata());
+ if (err != Error::NONE)
+ mWriter.setError(getCommandLoc(), err);
+
+ return true;
+}
+
+IVrComposerClient::BufferMetadata
+VrComposerClient::VrCommandReader::readBufferMetadata() {
+ IVrComposerClient::BufferMetadata metadata = {
+ .width = read(),
+ .height = read(),
+ .stride = read(),
+ .layerCount = read(),
+ .format = static_cast<PixelFormat>(readSigned()),
+ .usage = read64(),
+ };
+ return metadata;
+}
+
} // namespace dvr
} // namespace android
diff --git a/services/vr/vr_window_manager/composer/impl/vr_composer_client.h b/services/vr/vr_window_manager/composer/impl/vr_composer_client.h
index 8f0c562..8d601ab 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_composer_client.h
+++ b/services/vr/vr_window_manager/composer/impl/vr_composer_client.h
@@ -17,6 +17,7 @@
#ifndef VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_COMPOSER_CLIENT_H_
#define VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_COMPOSER_CLIENT_H_
+#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
#include <ComposerClient.h>
#include <IComposerCommandBuffer.h>
@@ -44,6 +45,10 @@
private:
bool parseSetLayerInfo(uint16_t length);
+ bool parseSetClientTargetMetadata(uint16_t length);
+ bool parseSetLayerBufferMetadata(uint16_t length);
+
+ IVrComposerClient::BufferMetadata readBufferMetadata();
VrComposerClient& mVrClient;
android::dvr::VrHwc& mVrHal;
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 d142729..5efc482 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
+++ b/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
@@ -16,8 +16,6 @@
#include "vr_hwc.h"
#include <ui/Fence.h>
-#include <ui/GraphicBuffer.h>
-#include <ui/GraphicBufferMapper.h>
#include <mutex>
@@ -43,41 +41,19 @@
const Display kDefaultDisplayId = 1;
const Config kDefaultConfigId = 1;
-sp<GraphicBuffer> GetBufferFromHandle(const native_handle_t* handle) {
- uint32_t width = 0, height = 0, stride = 0, layer_count = 1;
- uint64_t producer_usage = 0, consumer_usage = 0;
- int32_t format = 0;
+sp<GraphicBuffer> CreateGraphicBuffer(
+ const native_handle_t* handle,
+ const IVrComposerClient::BufferMetadata& metadata) {
+ sp<GraphicBuffer> buffer = new GraphicBuffer(
+ handle, GraphicBuffer::CLONE_HANDLE, metadata.width, metadata.height,
+ static_cast<int32_t>(metadata.format), metadata.layerCount,
+ metadata.usage, metadata.usage, metadata.stride);
+ if (buffer->initCheck() != OK) {
+ ALOGE("Failed to create graphic buffer");
+ return nullptr;
+ }
- GraphicBufferMapper& mapper = GraphicBufferMapper::get();
- // Need to register |handle| otherwise we can't read its properties.
- if (mapper.registerBuffer(handle) != OK) {
- ALOGE("Failed to register buffer");
- return nullptr;
- }
-
- if (mapper.getDimensions(handle, &width, &height) ||
- mapper.getStride(handle, &stride) ||
- mapper.getFormat(handle, &format) ||
- mapper.getProducerUsage(handle, &producer_usage) ||
- mapper.getConsumerUsage(handle, &consumer_usage)) {
- ALOGE("Failed to read handle properties");
- return nullptr;
- }
-
- // This will only succeed if gralloc has GRALLOC1_CAPABILITY_LAYERED_BUFFERS
- // capability. Otherwise assume a count of 1.
- mapper.getLayerCount(handle, &layer_count);
-
- // NOTE: Can't re-use |handle| since we don't own it.
- sp<GraphicBuffer> buffer = new GraphicBuffer(handle,
- GraphicBuffer::CLONE_HANDLE, width, height, format, layer_count,
- producer_usage, consumer_usage, stride);
- if (buffer->initCheck() != OK) {
- ALOGE("Failed to register cloned buffer");
- return nullptr;
- }
-
- return buffer;
+ return buffer;
}
void GetPrimaryDisplaySize(int32_t* width, int32_t* height) {
@@ -115,12 +91,17 @@
bool HwcDisplay::SetClientTarget(const native_handle_t* handle,
base::unique_fd fence) {
if (handle)
- buffer_ = GetBufferFromHandle(handle);
+ buffer_ = CreateGraphicBuffer(handle, buffer_metadata_);
fence_ = new Fence(fence.release());
return true;
}
+void HwcDisplay::SetClientTargetMetadata(
+ const IVrComposerClient::BufferMetadata& metadata) {
+ buffer_metadata_ = metadata;
+}
+
HwcLayer* HwcDisplay::CreateLayer() {
uint64_t layer_id = layer_ids_++;
layers_.push_back(HwcLayer(layer_id));
@@ -217,19 +198,14 @@
queued_client_target = true;
} else {
if (!layer.info.buffer.get() || !layer.info.fence.get()) {
- ALOGE("Layer requested without valid buffer");
- return Error::BAD_LAYER;
+ ALOGV("Layer requested without valid buffer");
+ continue;
}
frame.push_back(layer.info);
}
}
- if (frame.empty()) {
- ALOGE("Requested frame with no layers");
- return Error::BAD_LAYER;
- }
-
out_frames->swap(frame);
return Error::NONE;
}
@@ -564,7 +540,8 @@
if (!hwc_layer)
return Error::BAD_LAYER;
- hwc_layer->info.buffer = GetBufferFromHandle(buffer);
+ hwc_layer->info.buffer = CreateGraphicBuffer(
+ buffer, hwc_layer->buffer_metadata);
hwc_layer->info.fence = new Fence(fence.release());
return Error::NONE;
@@ -730,6 +707,35 @@
return Error::NONE;
}
+Error VrHwc::setClientTargetMetadata(
+ Display display, const IVrComposerClient::BufferMetadata& metadata) {
+ std::lock_guard<std::mutex> guard(mutex_);
+ auto display_ptr = FindDisplay(display);
+ if (!display_ptr)
+ return Error::BAD_DISPLAY;
+
+ display_ptr->SetClientTargetMetadata(metadata);
+
+ return Error::NONE;
+}
+
+Error VrHwc::setLayerBufferMetadata(
+ Display display, Layer layer,
+ const IVrComposerClient::BufferMetadata& metadata) {
+ std::lock_guard<std::mutex> guard(mutex_);
+ auto display_ptr = FindDisplay(display);
+ if (!display_ptr)
+ return Error::BAD_DISPLAY;
+
+ HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
+ if (!hwc_layer)
+ return Error::BAD_LAYER;
+
+ hwc_layer->buffer_metadata = metadata;
+
+ return Error::NONE;
+}
+
Return<void> VrHwc::getCapabilities(getCapabilities_cb hidl_cb) {
hidl_cb(hidl_vec<Capability>());
return Void();
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 bfca9a6..3da2fb8 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_hwc.h
+++ b/services/vr/vr_window_manager/composer/impl/vr_hwc.h
@@ -17,6 +17,7 @@
#define VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_HWC_H_
#include <android-base/unique_fd.h>
+#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
#include <android/hardware/graphics/composer/2.1/IComposer.h>
#include <ComposerBase.h>
#include <ui/Fence.h>
@@ -26,6 +27,7 @@
#include <mutex>
#include <unordered_map>
+using namespace android::frameworks::vr::composer::V1_0;
using namespace android::hardware::graphics::common::V1_0;
using namespace android::hardware::graphics::composer::V2_1;
@@ -38,7 +40,6 @@
namespace android {
class Fence;
-class GraphicBuffer;
namespace dvr {
@@ -105,6 +106,7 @@
Composition composition_type;
uint32_t z_order;
ComposerView::ComposerLayer info;
+ IVrComposerClient::BufferMetadata buffer_metadata;
};
class HwcDisplay {
@@ -120,6 +122,8 @@
HwcLayer* GetLayer(Layer id);
bool SetClientTarget(const native_handle_t* handle, base::unique_fd fence);
+ void SetClientTargetMetadata(
+ const IVrComposerClient::BufferMetadata& metadata);
void GetChangedCompositionTypes(
std::vector<Layer>* layer_ids,
@@ -131,8 +135,8 @@
private:
// The client target buffer and the associated fence.
- // TODO(dnicoara): Replace this with a list of ComposerView::ComposerLayer.
sp<GraphicBuffer> buffer_;
+ IVrComposerClient::BufferMetadata buffer_metadata_;
sp<Fence> fence_;
// List of currently active layers.
@@ -159,6 +163,11 @@
Error setLayerInfo(Display display, Layer layer, uint32_t type,
uint32_t appId);
+ Error setClientTargetMetadata(
+ Display display, const IVrComposerClient::BufferMetadata& metadata);
+ Error setLayerBufferMetadata(
+ Display display, Layer layer,
+ const IVrComposerClient::BufferMetadata& metadata);
// ComposerBase
void removeClient() override;
diff --git a/services/vr/vr_window_manager/display_view.cpp b/services/vr/vr_window_manager/display_view.cpp
index 52984b7..88768a0 100644
--- a/services/vr/vr_window_manager/display_view.cpp
+++ b/services/vr/vr_window_manager/display_view.cpp
@@ -219,6 +219,11 @@
visibility = ViewMode::Hidden;
current_vr_app_ = app;
}
+ } else if ((use_2dmode_ || !is_vr_active) && app != 0 &&
+ visibility == ViewMode::Hidden) {
+ // This is the case for the VR app launching a 2D intent of itself on some
+ // display.
+ visibility = ViewMode::App;
} else if (!current_vr_app_) {
// The VR app is running.
current_vr_app_ = app;
diff --git a/services/vr/vr_window_manager/shell_view.cpp b/services/vr/vr_window_manager/shell_view.cpp
index 850f604..2b53cd6 100644
--- a/services/vr/vr_window_manager/shell_view.cpp
+++ b/services/vr/vr_window_manager/shell_view.cpp
@@ -327,7 +327,6 @@
// Position the quad horizontally aligned in the direction the user
// is facing, effectively taking out head roll.
displays_[0]->Recenter(GetHorizontallyAlignedMatrixFromPose(last_pose_));
- should_recenter_ = false;
}
for (auto& display : displays_) {
diff --git a/services/vr/vr_window_manager/shell_view.h b/services/vr/vr_window_manager/shell_view.h
index be2ae58..d90e833 100644
--- a/services/vr/vr_window_manager/shell_view.h
+++ b/services/vr/vr_window_manager/shell_view.h
@@ -84,9 +84,6 @@
bool is_touching_ = false;
int touchpad_buttons_ = 0;
- // Used to center the scene when the shell becomes visible.
- bool should_recenter_ = true;
-
std::mutex display_frame_mutex_;
std::vector<std::unique_ptr<DisplayView>> displays_;
diff --git a/services/vr/vr_window_manager/vr_window_manager.cpp b/services/vr/vr_window_manager/vr_window_manager.cpp
index 6636dc5..9d7afe3 100644
--- a/services/vr/vr_window_manager/vr_window_manager.cpp
+++ b/services/vr/vr_window_manager/vr_window_manager.cpp
@@ -20,20 +20,20 @@
LOG_ALWAYS_FATAL_IF(app_status != 0, "failed to initialize: %d", app_status);
// Create vr_wm_binder.
- android::service::vr::VrWindowManagerBinder vr_wm_binder(app);
- const int status = vr_wm_binder.Initialize();
+ android::sp<android::service::vr::VrWindowManagerBinder> vr_wm_binder =
+ new android::service::vr::VrWindowManagerBinder(app);
+ const int status = vr_wm_binder->Initialize();
LOG_ALWAYS_FATAL_IF(status != 0, "initialization failed: %d", status);
android::sp<android::IServiceManager> sm(android::defaultServiceManager());
- const android::status_t vr_wm_binder_status =
- sm->addService(
- android::service::vr::VrWindowManagerBinder::SERVICE_NAME(),
- &vr_wm_binder, false /*allowIsolated*/);
+ const android::status_t vr_wm_binder_status = sm->addService(
+ android::service::vr::VrWindowManagerBinder::SERVICE_NAME(),
+ vr_wm_binder, false /*allowIsolated*/);
LOG_ALWAYS_FATAL_IF(vr_wm_binder_status != android::OK,
"vr_wm_binder service not added: %d",
static_cast<int>(vr_wm_binder_status));
- app.SetControllerDataProvider(&vr_wm_binder);
+ app.SetControllerDataProvider(vr_wm_binder.get());
android::hardware::ProcessState::self()->startThreadPool();
diff --git a/vulkan/Android.bp b/vulkan/Android.bp
index 3fd8c51..91c270e 100644
--- a/vulkan/Android.bp
+++ b/vulkan/Android.bp
@@ -26,6 +26,7 @@
cc_library_headers {
name: "vulkan_headers",
export_include_dirs: ["include"],
+ vendor_available: true,
}
subdirs = [
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 9444da5..6149894 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -14,7 +14,7 @@
// Headers module is in frameworks/native/vulkan/Android.bp.
ndk_library {
- name: "libvulkan.ndk",
+ name: "libvulkan",
symbol_file: "libvulkan.map.txt",
first_version: "24",
unversioned_until: "current",
@@ -78,6 +78,7 @@
"libutils",
"libcutils",
"libz",
+ "libnativewindow",
],
static_libs: ["libgrallocusage"],
}
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 5fbf5f5..f2cd8e6 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -34,6 +34,11 @@
#include "driver.h"
#include "stubhal.h"
+// TODO(b/37049319) Get this from a header once one exists
+extern "C" {
+android_namespace_t* android_get_exported_namespace(const char*);
+}
+
// Set to true to enable exposing unratified extensions for development
static const bool kEnableUnratifiedExtensions = false;
@@ -150,14 +155,12 @@
"ro.board.platform",
}};
-int LoadUpdatedDriver(const hw_module_t** module) {
+int LoadDriver(android_namespace_t* library_namespace,
+ const hwvulkan_module_t** module) {
const android_dlextinfo dlextinfo = {
.flags = ANDROID_DLEXT_USE_NAMESPACE,
- .library_namespace = android::GraphicsEnv::getInstance().getDriverNamespace(),
+ .library_namespace = library_namespace,
};
- if (!dlextinfo.library_namespace)
- return -ENOENT;
-
void* so = nullptr;
char prop[PROPERTY_VALUE_MAX];
for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
@@ -171,7 +174,7 @@
if (!so)
return -ENOENT;
- hw_module_t* hmi = static_cast<hw_module_t*>(dlsym(so, HAL_MODULE_INFO_SYM_AS_STR));
+ auto hmi = static_cast<hw_module_t*>(dlsym(so, HAL_MODULE_INFO_SYM_AS_STR));
if (!hmi) {
ALOGE("couldn't find symbol '%s' in HAL library: %s", HAL_MODULE_INFO_SYM_AS_STR, dlerror());
dlclose(so);
@@ -183,11 +186,24 @@
return -EINVAL;
}
hmi->dso = so;
- *module = hmi;
- ALOGD("loaded updated driver");
+ *module = reinterpret_cast<const hwvulkan_module_t*>(hmi);
return 0;
}
+int LoadBuiltinDriver(const hwvulkan_module_t** module) {
+ auto ns = android_get_exported_namespace("sphal");
+ if (!ns)
+ return -ENOENT;
+ return LoadDriver(ns, module);
+}
+
+int LoadUpdatedDriver(const hwvulkan_module_t** module) {
+ auto ns = android::GraphicsEnv::getInstance().getDriverNamespace();
+ if (!ns)
+ return -ENOENT;
+ return LoadDriver(ns, module);
+}
+
bool Hal::Open() {
ALOG_ASSERT(!hal_.dev_, "OpenHAL called more than once");
@@ -197,9 +213,21 @@
int result;
const hwvulkan_module_t* module = nullptr;
- result = LoadUpdatedDriver(reinterpret_cast<const hw_module_t**>(&module));
+ result = LoadUpdatedDriver(&module);
if (result == -ENOENT) {
- result = hw_get_module(HWVULKAN_HARDWARE_MODULE_ID, reinterpret_cast<const hw_module_t**>(&module));
+ result = LoadBuiltinDriver(&module);
+ if (result != 0) {
+ // -ENOENT means the sphal namespace doesn't exist, not that there
+ // is a problem with the driver.
+ ALOGW_IF(
+ result != -ENOENT,
+ "Failed to load Vulkan driver into sphal namespace. This "
+ "usually means the driver has forbidden library dependencies."
+ "Please fix, this will soon stop working.");
+ result =
+ hw_get_module(HWVULKAN_HARDWARE_MODULE_ID,
+ reinterpret_cast<const hw_module_t**>(&module));
+ }
}
if (result != 0) {
ALOGV("unable to load Vulkan HAL, using stub HAL (result=%d)", result);
@@ -789,9 +817,6 @@
loader_extensions.push_back({
VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION});
- loader_extensions.push_back({
- VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME,
- VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION});
if (kEnableUnratifiedExtensions) {
// conditionally add shared_presentable_image if supportable
@@ -804,6 +829,16 @@
}
}
+ // conditionally add VK_GOOGLE_display_timing if present timestamps are
+ // supported by the driver:
+ char timestamp_property[PROPERTY_VALUE_MAX];
+ property_get("service.sf.present_timestamp", timestamp_property, "1");
+ if (strcmp(timestamp_property, "1") == 0) {
+ loader_extensions.push_back({
+ VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME,
+ VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION});
+ }
+
// enumerate our extensions first
if (!pLayerName && pProperties) {
uint32_t count = std::min(
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 3b785e6..caa2674 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -114,14 +114,34 @@
: vals_{qp->presentID, qp->desiredPresentTime, 0, 0, 0},
native_frame_id_(nativeFrameId) {}
bool ready() const {
- return (timestamp_desired_present_time_ &&
- timestamp_actual_present_time_ &&
- timestamp_render_complete_time_ &&
- timestamp_composition_latch_time_);
+ return (timestamp_desired_present_time_ !=
+ NATIVE_WINDOW_TIMESTAMP_PENDING &&
+ timestamp_actual_present_time_ !=
+ NATIVE_WINDOW_TIMESTAMP_PENDING &&
+ timestamp_render_complete_time_ !=
+ NATIVE_WINDOW_TIMESTAMP_PENDING &&
+ timestamp_composition_latch_time_ !=
+ NATIVE_WINDOW_TIMESTAMP_PENDING);
}
- void calculate(uint64_t rdur) {
- vals_.actualPresentTime = timestamp_actual_present_time_;
- uint64_t margin = (timestamp_composition_latch_time_ -
+ void calculate(int64_t rdur) {
+ bool anyTimestampInvalid =
+ (timestamp_actual_present_time_ ==
+ NATIVE_WINDOW_TIMESTAMP_INVALID) ||
+ (timestamp_render_complete_time_ ==
+ NATIVE_WINDOW_TIMESTAMP_INVALID) ||
+ (timestamp_composition_latch_time_ ==
+ NATIVE_WINDOW_TIMESTAMP_INVALID);
+ if (anyTimestampInvalid) {
+ ALOGE("Unexpectedly received invalid timestamp.");
+ vals_.actualPresentTime = 0;
+ vals_.earliestPresentTime = 0;
+ vals_.presentMargin = 0;
+ return;
+ }
+
+ vals_.actualPresentTime =
+ static_cast<uint64_t>(timestamp_actual_present_time_);
+ int64_t margin = (timestamp_composition_latch_time_ -
timestamp_render_complete_time_);
// Calculate vals_.earliestPresentTime, and potentially adjust
// vals_.presentMargin. The initial value of vals_.earliestPresentTime
@@ -132,14 +152,14 @@
// it did (per the extension specification). If for some reason, we
// can do this subtraction repeatedly, we do, since
// vals_.earliestPresentTime really is supposed to be the "earliest".
- uint64_t early_time = vals_.actualPresentTime;
+ int64_t early_time = timestamp_actual_present_time_;
while ((margin > rdur) &&
((early_time - rdur) > timestamp_composition_latch_time_)) {
early_time -= rdur;
margin -= rdur;
}
- vals_.earliestPresentTime = early_time;
- vals_.presentMargin = margin;
+ vals_.earliestPresentTime = static_cast<uint64_t>(early_time);
+ vals_.presentMargin = static_cast<uint64_t>(margin);
}
void get_values(VkPastPresentationTimingGOOGLE* values) const {
*values = vals_;
@@ -149,10 +169,11 @@
VkPastPresentationTimingGOOGLE vals_ { 0, 0, 0, 0, 0 };
uint64_t native_frame_id_ { 0 };
- uint64_t timestamp_desired_present_time_ { 0 };
- uint64_t timestamp_actual_present_time_ { 0 };
- uint64_t timestamp_render_complete_time_ { 0 };
- uint64_t timestamp_composition_latch_time_ { 0 };
+ int64_t timestamp_desired_present_time_{ NATIVE_WINDOW_TIMESTAMP_PENDING };
+ int64_t timestamp_actual_present_time_ { NATIVE_WINDOW_TIMESTAMP_PENDING };
+ int64_t timestamp_render_complete_time_ { NATIVE_WINDOW_TIMESTAMP_PENDING };
+ int64_t timestamp_composition_latch_time_
+ { NATIVE_WINDOW_TIMESTAMP_PENDING };
};
// ----------------------------------------------------------------------------
@@ -187,18 +208,16 @@
shared(present_mode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR ||
present_mode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR) {
ANativeWindow* window = surface.window.get();
- int64_t rdur;
native_window_get_refresh_cycle_duration(
window,
- &rdur);
- refresh_duration = static_cast<uint64_t>(rdur);
+ &refresh_duration);
}
Surface& surface;
uint32_t num_images;
bool mailbox_mode;
bool frame_timestamps_enabled;
- uint64_t refresh_duration;
+ int64_t refresh_duration;
bool shared;
struct Image {
@@ -327,14 +346,10 @@
// Record the timestamp(s) we received, and then see if this TimingInfo
// is ready to be reported to the user:
- ti.timestamp_desired_present_time_ =
- static_cast<uint64_t>(desired_present_time);
- ti.timestamp_actual_present_time_ =
- static_cast<uint64_t>(actual_present_time);
- ti.timestamp_render_complete_time_ =
- static_cast<uint64_t>(render_complete_time);
- ti.timestamp_composition_latch_time_ =
- static_cast<uint64_t>(composition_latch_time);
+ ti.timestamp_desired_present_time_ = desired_present_time;
+ ti.timestamp_actual_present_time_ = actual_present_time;
+ ti.timestamp_render_complete_time_ = render_complete_time;
+ ti.timestamp_composition_latch_time_ = composition_latch_time;
if (ti.ready()) {
// The TimingInfo has received enough timestamps, and should now
@@ -1494,7 +1509,8 @@
Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
VkResult result = VK_SUCCESS;
- pDisplayTimingProperties->refreshDuration = swapchain.refresh_duration;
+ pDisplayTimingProperties->refreshDuration =
+ static_cast<uint64_t>(swapchain.refresh_duration);
return result;
}