Merge "VR: Remove HIDL VR Composer from service/vr/vr_window_manager" into oc-dev
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 5421a75..5dad511 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1062,13 +1062,9 @@
RunCommand("WIFI NETWORKS", {"wpa_cli", "IFNAME=wlan0", "list_networks"},
CommandOptions::WithTimeout(20).Build());
- DumpFile("INTERRUPTS (1)", "/proc/interrupts");
-
RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
CommandOptions::WithTimeout(10).Build());
- DumpFile("INTERRUPTS (2)", "/proc/interrupts");
-
RunCommand("SYSTEM PROPERTIES", {"getprop"});
RunCommand("VOLD DUMP", {"vdc", "dump"});
@@ -1152,6 +1148,13 @@
RunDumpsys("APP PROVIDERS", {"activity", "provider", "all"});
+ printf("========================================================\n");
+ printf("== Dropbox crashes\n");
+ printf("========================================================\n");
+
+ RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
+ RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
+
// DumpModemLogs adds the modem logs if available to the bugreport.
// Do this at the end to allow for sufficient time for the modem logs to be
// collected.
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index c604ca0..20b960d 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -88,6 +88,7 @@
static constexpr int FLAG_FREE_CACHE_V2 = 1 << 13;
static constexpr int FLAG_FREE_CACHE_V2_DEFY_QUOTA = 1 << 14;
static constexpr int FLAG_FREE_CACHE_NOOP = 1 << 15;
+static constexpr int FLAG_FORCE = 1 << 16;
namespace {
@@ -600,6 +601,113 @@
return res;
}
+static gid_t get_cache_gid(uid_t uid) {
+ int32_t gid = multiuser_get_cache_gid(multiuser_get_user_id(uid), multiuser_get_app_id(uid));
+ return (gid != -1) ? gid : uid;
+}
+
+binder::Status InstalldNativeService::fixupAppData(const std::unique_ptr<std::string>& uuid,
+ int32_t flags) {
+ ENFORCE_UID(AID_SYSTEM);
+ CHECK_ARGUMENT_UUID(uuid);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
+
+ const char* uuid_ = uuid ? uuid->c_str() : nullptr;
+ for (auto user : get_known_users(uuid_)) {
+ ATRACE_BEGIN("fixup user");
+ FTS* fts;
+ FTSENT* p;
+ char *argv[] = {
+ (char*) create_data_user_ce_path(uuid_, user).c_str(),
+ (char*) create_data_user_de_path(uuid_, user).c_str(),
+ nullptr
+ };
+ if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) {
+ return error("Failed to fts_open");
+ }
+ while ((p = fts_read(fts)) != nullptr) {
+ if (p->fts_info == FTS_D && p->fts_level == 1) {
+ // Track down inodes of cache directories
+ uint64_t raw = 0;
+ ino_t inode_cache = 0;
+ ino_t inode_code_cache = 0;
+ if (getxattr(p->fts_path, kXattrInodeCache, &raw, sizeof(raw)) == sizeof(raw)) {
+ inode_cache = raw;
+ }
+ if (getxattr(p->fts_path, kXattrInodeCodeCache, &raw, sizeof(raw)) == sizeof(raw)) {
+ inode_code_cache = raw;
+ }
+
+ // Figure out expected GID of each child
+ FTSENT* child = fts_children(fts, 0);
+ while (child != nullptr) {
+ if ((child->fts_statp->st_ino == inode_cache)
+ || (child->fts_statp->st_ino == inode_code_cache)
+ || !strcmp(child->fts_name, "cache")
+ || !strcmp(child->fts_name, "code_cache")) {
+ child->fts_number = get_cache_gid(p->fts_statp->st_uid);
+ } else {
+ child->fts_number = p->fts_statp->st_uid;
+ }
+ child = child->fts_link;
+ }
+ } else if (p->fts_level >= 2) {
+ if (p->fts_level > 2) {
+ // Inherit GID from parent once we're deeper into tree
+ p->fts_number = p->fts_parent->fts_number;
+ }
+
+ uid_t uid = p->fts_parent->fts_statp->st_uid;
+ gid_t cache_gid = get_cache_gid(uid);
+ gid_t expected = p->fts_number;
+ gid_t actual = p->fts_statp->st_gid;
+ if (actual == expected) {
+#if FIXUP_DEBUG
+ LOG(DEBUG) << "Ignoring " << p->fts_path << " with expected GID " << expected;
+#endif
+ if (!(flags & FLAG_FORCE)) {
+ fts_set(fts, p, FTS_SKIP);
+ }
+ } else if ((actual == uid) || (actual == cache_gid)) {
+ // Only consider fixing up when current GID belongs to app
+ if (p->fts_info != FTS_D) {
+ LOG(INFO) << "Fixing " << p->fts_path << " with unexpected GID " << actual
+ << " instead of " << expected;
+ }
+ switch (p->fts_info) {
+ case FTS_DP:
+ // If we're moving towards cache GID, we need to set S_ISGID
+ if (expected == cache_gid) {
+ if (chmod(p->fts_path, 02771) != 0) {
+ PLOG(WARNING) << "Failed to chmod " << p->fts_path;
+ }
+ }
+ // Intentional fall through to also set GID
+ case FTS_F:
+ if (chown(p->fts_path, -1, expected) != 0) {
+ PLOG(WARNING) << "Failed to chown " << p->fts_path;
+ }
+ break;
+ case FTS_SL:
+ case FTS_SLNONE:
+ if (lchown(p->fts_path, -1, expected) != 0) {
+ PLOG(WARNING) << "Failed to chown " << p->fts_path;
+ }
+ break;
+ }
+ } else {
+ // Ignore all other GID transitions, since they're kinda shady
+ LOG(WARNING) << "Ignoring " << p->fts_path << " with unexpected GID " << actual
+ << " instead of " << expected;
+ }
+ }
+ }
+ fts_close(fts);
+ ATRACE_END();
+ }
+ return ok();
+}
+
binder::Status InstalldNativeService::moveCompleteApp(const std::unique_ptr<std::string>& fromUuid,
const std::unique_ptr<std::string>& toUuid, const std::string& packageName,
const std::string& dataAppName, int32_t appId, const std::string& seInfo,
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 7ad8687..f5b7142 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -58,6 +58,8 @@
binder::Status destroyAppData(const std::unique_ptr<std::string>& uuid,
const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode);
+ binder::Status fixupAppData(const std::unique_ptr<std::string>& uuid, int32_t flags);
+
binder::Status getAppSize(const std::unique_ptr<std::string>& uuid,
const std::vector<std::string>& packageNames, int32_t userId, int32_t flags,
int32_t appId, const std::vector<int64_t>& ceDataInodes,
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 4195a01..03ff96e 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -32,6 +32,8 @@
void destroyAppData(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
int userId, int flags, long ceDataInode);
+ void fixupAppData(@nullable @utf8InCpp String uuid, int flags);
+
long[] getAppSize(@nullable @utf8InCpp String uuid, in @utf8InCpp String[] packageNames,
int userId, int flags, int appId, in long[] ceDataInodes,
in @utf8InCpp String[] codePaths);
diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp
index b5b080d..630c1f3 100644
--- a/cmds/installd/tests/Android.bp
+++ b/cmds/installd/tests/Android.bp
@@ -33,3 +33,22 @@
"libdiskusage",
],
}
+
+cc_test {
+ name: "installd_service_test",
+ clang: true,
+ srcs: ["installd_service_test.cpp"],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "libcutils",
+ "liblog",
+ "liblogwrap",
+ "libselinux",
+ "libutils",
+ ],
+ static_libs: [
+ "libinstalld",
+ "libdiskusage",
+ ],
+}
diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp
new file mode 100644
index 0000000..4a1f333
--- /dev/null
+++ b/cmds/installd/tests/installd_service_test.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/statvfs.h>
+#include <sys/xattr.h>
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <cutils/properties.h>
+#include <gtest/gtest.h>
+
+#include "InstalldNativeService.h"
+#include "globals.h"
+#include "utils.h"
+
+using android::base::StringPrintf;
+
+namespace android {
+namespace installd {
+
+constexpr const char* kTestUuid = "TEST";
+
+static constexpr int FLAG_FORCE = 1 << 16;
+
+int get_property(const char *key, char *value, const char *default_value) {
+ return property_get(key, value, default_value);
+}
+
+bool calculate_oat_file_path(char path[PKG_PATH_MAX] ATTRIBUTE_UNUSED,
+ const char *oat_dir ATTRIBUTE_UNUSED,
+ const char *apk_path ATTRIBUTE_UNUSED,
+ const char *instruction_set ATTRIBUTE_UNUSED) {
+ return false;
+}
+
+bool calculate_odex_file_path(char path[PKG_PATH_MAX] ATTRIBUTE_UNUSED,
+ const char *apk_path ATTRIBUTE_UNUSED,
+ const char *instruction_set ATTRIBUTE_UNUSED) {
+ return false;
+}
+
+bool create_cache_path(char path[PKG_PATH_MAX] ATTRIBUTE_UNUSED,
+ const char *src ATTRIBUTE_UNUSED,
+ const char *instruction_set ATTRIBUTE_UNUSED) {
+ return false;
+}
+
+static void mkdir(const char* path, uid_t owner, gid_t group, mode_t mode) {
+ const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
+ ::mkdir(fullPath, mode);
+ ::chown(fullPath, owner, group);
+ ::chmod(fullPath, mode);
+}
+
+static void touch(const char* path, uid_t owner, gid_t group, mode_t mode) {
+ int fd = ::open(StringPrintf("/data/local/tmp/user/0/%s", path).c_str(),
+ O_RDWR | O_CREAT, mode);
+ ::fchown(fd, owner, group);
+ ::fchmod(fd, mode);
+ ::close(fd);
+}
+
+static int stat_gid(const char* path) {
+ struct stat buf;
+ ::stat(StringPrintf("/data/local/tmp/user/0/%s", path).c_str(), &buf);
+ return buf.st_gid;
+}
+
+static int stat_mode(const char* path) {
+ struct stat buf;
+ ::stat(StringPrintf("/data/local/tmp/user/0/%s", path).c_str(), &buf);
+ return buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISGID);
+}
+
+class ServiceTest : public testing::Test {
+protected:
+ InstalldNativeService* service;
+ std::unique_ptr<std::string> testUuid;
+
+ virtual void SetUp() {
+ setenv("ANDROID_LOG_TAGS", "*:v", 1);
+ android::base::InitLogging(nullptr);
+
+ service = new InstalldNativeService();
+ testUuid = std::make_unique<std::string>();
+ *testUuid = std::string(kTestUuid);
+ system("mkdir -p /data/local/tmp/user/0");
+ }
+
+ virtual void TearDown() {
+ delete service;
+ system("rm -rf /data/local/tmp/user");
+ }
+};
+
+TEST_F(ServiceTest, FixupAppData_Upgrade) {
+ LOG(INFO) << "FixupAppData_Upgrade";
+
+ mkdir("com.example", 10000, 10000, 0700);
+ mkdir("com.example/normal", 10000, 10000, 0700);
+ mkdir("com.example/cache", 10000, 10000, 0700);
+ touch("com.example/cache/file", 10000, 10000, 0700);
+
+ service->fixupAppData(testUuid, 0);
+
+ EXPECT_EQ(10000, stat_gid("com.example/normal"));
+ EXPECT_EQ(20000, stat_gid("com.example/cache"));
+ EXPECT_EQ(20000, stat_gid("com.example/cache/file"));
+
+ EXPECT_EQ(0700, stat_mode("com.example/normal"));
+ EXPECT_EQ(02771, stat_mode("com.example/cache"));
+ EXPECT_EQ(0700, stat_mode("com.example/cache/file"));
+}
+
+TEST_F(ServiceTest, FixupAppData_Moved) {
+ LOG(INFO) << "FixupAppData_Moved";
+
+ mkdir("com.example", 10000, 10000, 0700);
+ mkdir("com.example/foo", 10000, 10000, 0700);
+ touch("com.example/foo/file", 10000, 20000, 0700);
+ mkdir("com.example/bar", 10000, 20000, 0700);
+ touch("com.example/bar/file", 10000, 20000, 0700);
+
+ service->fixupAppData(testUuid, 0);
+
+ EXPECT_EQ(10000, stat_gid("com.example/foo"));
+ EXPECT_EQ(20000, stat_gid("com.example/foo/file"));
+ EXPECT_EQ(10000, stat_gid("com.example/bar"));
+ EXPECT_EQ(10000, stat_gid("com.example/bar/file"));
+
+ service->fixupAppData(testUuid, FLAG_FORCE);
+
+ EXPECT_EQ(10000, stat_gid("com.example/foo"));
+ EXPECT_EQ(10000, stat_gid("com.example/foo/file"));
+ EXPECT_EQ(10000, stat_gid("com.example/bar"));
+ EXPECT_EQ(10000, stat_gid("com.example/bar/file"));
+}
+
+} // namespace installd
+} // namespace android
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 24c0b45..c792082 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -1047,18 +1047,18 @@
while ((p = fts_read(fts)) != NULL) {
switch (p->fts_info) {
case FTS_DP:
- if (chmod(p->fts_accpath, target_mode) != 0) {
+ if (chmod(p->fts_path, target_mode) != 0) {
PLOG(WARNING) << "Failed to chmod " << p->fts_path;
}
// Intentional fall through to also set GID
case FTS_F:
- if (chown(p->fts_accpath, -1, gid) != 0) {
+ if (chown(p->fts_path, -1, gid) != 0) {
PLOG(WARNING) << "Failed to chown " << p->fts_path;
}
break;
case FTS_SL:
case FTS_SLNONE:
- if (lchown(p->fts_accpath, -1, gid) != 0) {
+ if (lchown(p->fts_path, -1, gid) != 0) {
PLOG(WARNING) << "Failed to chown " << p->fts_path;
}
break;
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 7ebfea2..dd94da9 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -31,6 +31,7 @@
#include <installd_constants.h>
#define MEASURE_DEBUG 0
+#define FIXUP_DEBUG 0
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/include/gui/GLConsumer.h b/include/gui/GLConsumer.h
index 51d7666..2cf6162 100644
--- a/include/gui/GLConsumer.h
+++ b/include/gui/GLConsumer.h
@@ -23,6 +23,7 @@
#include <gui/BufferQueueDefs.h>
#include <gui/ConsumerBase.h>
+#include <ui/FenceTime.h>
#include <ui/GraphicBuffer.h>
#include <utils/String8.h>
diff --git a/include/gui/IConsumerListener.h b/include/gui/IConsumerListener.h
index a3c7d64..c082882 100644
--- a/include/gui/IConsumerListener.h
+++ b/include/gui/IConsumerListener.h
@@ -14,103 +14,84 @@
* limitations under the License.
*/
-#ifndef ANDROID_GUI_ICONSUMERLISTENER_H
-#define ANDROID_GUI_ICONSUMERLISTENER_H
+#pragma once
-#include <stdint.h>
-#include <sys/types.h>
+#include <binder/IInterface.h>
+#include <binder/SafeInterface.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-
-#include <gui/FrameTimestamps.h>
+#include <cstdint>
namespace android {
-// ----------------------------------------------------------------------------
class BufferItem;
+class FrameEventHistoryDelta;
+struct NewFrameEventsEntry;
-// ConsumerListener is the interface through which the BufferQueue notifies
-// the consumer of events that the consumer may wish to react to. Because
-// the consumer will generally have a mutex that is locked during calls from
-// the consumer to the BufferQueue, these calls from the BufferQueue to the
+// ConsumerListener is the interface through which the BufferQueue notifies the consumer of events
+// that the consumer may wish to react to. Because the consumer will generally have a mutex that is
+// locked during calls from the consumer to the BufferQueue, these calls from the BufferQueue to the
// consumer *MUST* be called only when the BufferQueue mutex is NOT locked.
class ConsumerListener : public virtual RefBase {
public:
- ConsumerListener() { }
+ ConsumerListener() {}
virtual ~ConsumerListener();
// onDisconnect is called when a producer disconnects from the BufferQueue.
virtual void onDisconnect() {} /* Asynchronous */
- // onFrameAvailable is called from queueBuffer each time an additional
- // frame becomes available for consumption. This means that frames that
- // are queued while in asynchronous mode only trigger the callback if no
- // previous frames are pending. Frames queued while in synchronous mode
- // always trigger the callback. The item passed to the callback will contain
- // all of the information about the queued frame except for its
- // GraphicBuffer pointer, which will always be null (except if the consumer
- // is SurfaceFlinger).
+ // onFrameAvailable is called from queueBuffer each time an additional frame becomes available
+ // for consumption. This means that frames that are queued while in asynchronous mode only
+ // trigger the callback if no previous frames are pending. Frames queued while in synchronous
+ // mode always trigger the callback. The item passed to the callback will contain all of the
+ // information about the queued frame except for its GraphicBuffer pointer, which will always be
+ // null (except if the consumer is SurfaceFlinger).
//
- // This is called without any lock held and can be called concurrently
- // by multiple threads.
+ // This is called without any lock held and can be called concurrently by multiple threads.
virtual void onFrameAvailable(const BufferItem& item) = 0; /* Asynchronous */
- // onFrameReplaced is called from queueBuffer if the frame being queued is
- // replacing an existing slot in the queue. Any call to queueBuffer that
- // doesn't call onFrameAvailable will call this callback instead. The item
- // passed to the callback will contain all of the information about the
- // queued frame except for its GraphicBuffer pointer, which will always be
- // null.
+ // onFrameReplaced is called from queueBuffer if the frame being queued is replacing an existing
+ // slot in the queue. Any call to queueBuffer that doesn't call onFrameAvailable will call this
+ // callback instead. The item passed to the callback will contain all of the information about
+ // the queued frame except for its GraphicBuffer pointer, which will always be null.
//
- // This is called without any lock held and can be called concurrently
- // by multiple threads.
+ // This is called without any lock held and can be called concurrently by multiple threads.
virtual void onFrameReplaced(const BufferItem& /* item */) {} /* Asynchronous */
- // onBuffersReleased is called to notify the buffer consumer that the
- // BufferQueue has released its references to one or more GraphicBuffers
- // contained in its slots. The buffer consumer should then call
- // BufferQueue::getReleasedBuffers to retrieve the list of buffers
+ // onBuffersReleased is called to notify the buffer consumer that the BufferQueue has released
+ // its references to one or more GraphicBuffers contained in its slots. The buffer consumer
+ // should then call BufferQueue::getReleasedBuffers to retrieve the list of buffers.
//
- // This is called without any lock held and can be called concurrently
- // by multiple threads.
+ // This is called without any lock held and can be called concurrently by multiple threads.
virtual void onBuffersReleased() = 0; /* Asynchronous */
- // onSidebandStreamChanged is called to notify the buffer consumer that the
- // BufferQueue's sideband buffer stream has changed. This is called when a
- // stream is first attached and when it is either detached or replaced by a
- // different stream.
+ // onSidebandStreamChanged is called to notify the buffer consumer that the BufferQueue's
+ // sideband buffer stream has changed. This is called when a stream is first attached and when
+ // it is either detached or replaced by a different stream.
virtual void onSidebandStreamChanged() = 0; /* Asynchronous */
- // Notifies the consumer of any new producer-side timestamps and
- // returns the combined frame history that hasn't already been retrieved.
- virtual void addAndGetFrameTimestamps(
- const NewFrameEventsEntry* /*newTimestamps*/,
- FrameEventHistoryDelta* /*outDelta*/) {}
+ // Notifies the consumer of any new producer-side timestamps and returns the combined frame
+ // history that hasn't already been retrieved.
+ //
+ // WARNING: This method can only be called when the BufferQueue is in the consumer's process.
+ virtual void addAndGetFrameTimestamps(const NewFrameEventsEntry* /*newTimestamps*/,
+ FrameEventHistoryDelta* /*outDelta*/) {}
};
-
-class IConsumerListener : public ConsumerListener, public IInterface
-{
+class IConsumerListener : public ConsumerListener, public IInterface {
public:
DECLARE_META_INTERFACE(ConsumerListener)
};
-// ----------------------------------------------------------------------------
-
-class BnConsumerListener : public BnInterface<IConsumerListener>
-{
+class BnConsumerListener : public SafeBnInterface<IConsumerListener> {
public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
+ BnConsumerListener() : SafeBnInterface<IConsumerListener>("BnConsumerListener") {}
+
+ status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags = 0) override;
};
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GUI_ICONSUMERLISTENER_H
+} // namespace android
diff --git a/include/gui/ISurfaceComposerClient.h b/include/gui/ISurfaceComposerClient.h
index a680bc6..2c613ea 100644
--- a/include/gui/ISurfaceComposerClient.h
+++ b/include/gui/ISurfaceComposerClient.h
@@ -29,14 +29,6 @@
public:
DECLARE_META_INTERFACE(SurfaceComposerClient)
- enum class Tag : uint32_t {
- CreateSurface = IBinder::FIRST_CALL_TRANSACTION,
- DestroySurface,
- ClearLayerFrameStats,
- GetLayerFrameStats,
- Last,
- };
-
// flags for createSurface()
enum { // (keep in sync with Surface.java)
eHidden = 0x00000004,
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/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index 040d1e7..af1d8be 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -72,30 +72,69 @@
USAGE_CURSOR = GRALLOC_USAGE_CURSOR,
};
+ static sp<GraphicBuffer> from(ANativeWindowBuffer *);
+
+
+ // Create a GraphicBuffer to be unflatten'ed into or be reallocated.
GraphicBuffer();
- // creates w * h buffer
- GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
- uint32_t inUsage, std::string requestorName = "<Unknown>");
-
- // creates w * h buffer with a layer count using gralloc1
+ // Create a GraphicBuffer by allocating and managing a buffer internally.
+ // This function is privileged. See reallocate for details.
GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
uint32_t inLayerCount, uint64_t inProducerUsage,
uint64_t inConsumerUsage, std::string requestorName = "<Unknown>");
- // create a buffer from an existing handle
+ // Create a GraphicBuffer from an existing handle.
+ enum HandleWrapMethod : uint8_t {
+ // Wrap and use the handle directly. It assumes the handle has been
+ // registered and never fails. The handle must have a longer lifetime
+ // than this wrapping GraphicBuffer.
+ //
+ // This can be used when, for example, you want to wrap a handle that
+ // is already managed by another GraphicBuffer.
+ WRAP_HANDLE,
+
+ // Take ownership of the handle and use it directly. It assumes the
+ // handle has been registered and never fails.
+ //
+ // This can be used to manage an already registered handle with
+ // GraphicBuffer.
+ TAKE_HANDLE,
+
+ // Take onwership of an unregistered handle and use it directly. It
+ // can fail when the buffer does not register. There is no ownership
+ // transfer on failures.
+ //
+ // This can be used to, for example, create a GraphicBuffer from a
+ // handle returned by Parcel::readNativeHandle.
+ TAKE_UNREGISTERED_HANDLE,
+
+ // Make a clone of the handle and use the cloned handle. It can fail
+ // when cloning fails or when the buffer does not register. There is
+ // never ownership transfer.
+ //
+ // This can be used to create a GraphicBuffer from a handle that
+ // cannot be used directly, such as one from hidl_handle.
+ CLONE_HANDLE,
+ };
+ GraphicBuffer(const native_handle_t* handle, HandleWrapMethod method,
+ uint32_t width, uint32_t height,
+ PixelFormat format, uint32_t layerCount,
+ uint64_t producerUsage, uint64_t consumerUsage, uint32_t stride);
+
+ // These functions are deprecated because they do not distinguish producer
+ // and consumer usages.
+ GraphicBuffer(const native_handle_t* handle, HandleWrapMethod method,
+ uint32_t width, uint32_t height,
+ PixelFormat format, uint32_t layerCount,
+ uint32_t usage, uint32_t stride)
+ : GraphicBuffer(handle, method, width, height, format, layerCount,
+ usage, usage, stride) {}
GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
uint32_t inLayerCount, uint32_t inUsage, uint32_t inStride,
native_handle_t* inHandle, bool keepOwnership);
-
- // create a buffer from an existing handle using gralloc1
GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
- uint32_t inLayerCount, uint32_t inProducerUsage,
- uint32_t inConsumerUsage, uint32_t inStride,
- native_handle_t* inHandle, bool keepOwnership);
-
- // create a buffer from an existing ANativeWindowBuffer
- GraphicBuffer(ANativeWindowBuffer* buffer, bool keepOwnership);
+ uint32_t inUsage, std::string requestorName = "<Unknown>");
// return status
status_t initCheck() const;
@@ -114,6 +153,9 @@
mGenerationNumber = generation;
}
+ // This function is privileged. It requires access to the allocator
+ // device or service, which usually involves adding suitable selinux
+ // rules.
status_t reallocate(uint32_t inWidth, uint32_t inHeight,
PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage);
@@ -175,19 +217,21 @@
GraphicBuffer& operator = (const GraphicBuffer& rhs);
const GraphicBuffer& operator = (const GraphicBuffer& rhs) const;
- status_t initSize(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
- uint32_t inLayerCount, uint64_t inProducerUsage,
- uint64_t inConsumerUsage, std::string requestorName);
+ status_t initWithSize(uint32_t inWidth, uint32_t inHeight,
+ PixelFormat inFormat, uint32_t inLayerCount,
+ uint64_t inProducerUsage, uint64_t inConsumerUsage,
+ std::string requestorName);
+
+ status_t initWithHandle(const native_handle_t* handle,
+ HandleWrapMethod method, uint32_t width, uint32_t height,
+ PixelFormat format, uint32_t layerCount,
+ uint64_t producerUsage, uint64_t consumerUsage, uint32_t stride);
void free_handle();
GraphicBufferMapper& mBufferMapper;
ssize_t mInitCheck;
- // If we're wrapping another buffer then this reference will make sure it
- // doesn't get freed.
- sp<ANativeWindowBuffer> mWrappedBuffer;
-
uint64_t mId;
// Stores the generation number of this buffer. If this number does not
diff --git a/libs/binder/include/binder/SafeInterface.h b/libs/binder/include/binder/SafeInterface.h
index 0e723c5..44c1352 100644
--- a/libs/binder/include/binder/SafeInterface.h
+++ b/libs/binder/include/binder/SafeInterface.h
@@ -45,6 +45,16 @@
return callParcel("writeBool", [&]() { return parcel->writeBool(b); });
}
template <typename T>
+ typename std::enable_if<std::is_base_of<Flattenable<T>, T>::value, status_t>::type read(
+ const Parcel& parcel, T* t) const {
+ return callParcel("read(Flattenable)", [&]() { return parcel.read(*t); });
+ }
+ template <typename T>
+ typename std::enable_if<std::is_base_of<Flattenable<T>, T>::value, status_t>::type write(
+ Parcel* parcel, const T& t) const {
+ return callParcel("write(Flattenable)", [&]() { return parcel->write(t); });
+ }
+ template <typename T>
typename std::enable_if<std::is_base_of<LightFlattenable<T>, T>::value, status_t>::type read(
const Parcel& parcel, T* t) const {
return callParcel("read(LightFlattenable)", [&]() { return parcel.read(*t); });
diff --git a/libs/binder/tests/binderSafeInterfaceTest.cpp b/libs/binder/tests/binderSafeInterfaceTest.cpp
index ac2f4d5..d1f63a7 100644
--- a/libs/binder/tests/binderSafeInterfaceTest.cpp
+++ b/libs/binder/tests/binderSafeInterfaceTest.cpp
@@ -65,6 +65,25 @@
uint8_t mPadding[4] = {}; // Avoids a warning from -Wpadded
};
+struct TestFlattenable : Flattenable<TestFlattenable> {
+ TestFlattenable() = default;
+ explicit TestFlattenable(int32_t v) : value(v) {}
+
+ // Flattenable protocol
+ size_t getFlattenedSize() const { return sizeof(value); }
+ size_t getFdCount() const { return 0; }
+ status_t flatten(void*& buffer, size_t& size, int*& /*fds*/, size_t& /*count*/) const {
+ FlattenableUtils::write(buffer, size, value);
+ return NO_ERROR;
+ }
+ status_t unflatten(void const*& buffer, size_t& size, int const*& /*fds*/, size_t& /*count*/) {
+ FlattenableUtils::read(buffer, size, value);
+ return NO_ERROR;
+ }
+
+ int32_t value = 0;
+};
+
struct TestLightFlattenable : LightFlattenablePod<TestLightFlattenable> {
TestLightFlattenable() = default;
explicit TestLightFlattenable(int32_t v) : value(v) {}
@@ -142,6 +161,7 @@
SetDeathToken = IBinder::FIRST_CALL_TRANSACTION,
ReturnsNoMemory,
LogicalNot,
+ IncrementFlattenable,
IncrementLightFlattenable,
IncrementNoCopyNoMove,
ToUpper,
@@ -161,6 +181,7 @@
// These are ordered according to their corresponding methods in SafeInterface::ParcelHandler
virtual status_t logicalNot(bool a, bool* notA) const = 0;
+ virtual status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const = 0;
virtual status_t increment(const TestLightFlattenable& a,
TestLightFlattenable* aPlusOne) const = 0;
virtual status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const = 0;
@@ -192,6 +213,12 @@
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
return callRemote<decltype(&ISafeInterfaceTest::logicalNot)>(Tag::LogicalNot, a, notA);
}
+ status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const override {
+ using Signature =
+ status_t (ISafeInterfaceTest::*)(const TestFlattenable&, TestFlattenable*) const;
+ ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+ return callRemote<Signature>(Tag::IncrementFlattenable, a, aPlusOne);
+ }
status_t increment(const TestLightFlattenable& a,
TestLightFlattenable* aPlusOne) const override {
using Signature = status_t (ISafeInterfaceTest::*)(const TestLightFlattenable&,
@@ -263,6 +290,11 @@
*notA = !a;
return NO_ERROR;
}
+ status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const override {
+ ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+ aPlusOne->value = a.value + 1;
+ return NO_ERROR;
+ }
status_t increment(const TestLightFlattenable& a,
TestLightFlattenable* aPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
@@ -317,6 +349,11 @@
case ISafeInterfaceTest::Tag::LogicalNot: {
return callLocal(data, reply, &ISafeInterfaceTest::logicalNot);
}
+ case ISafeInterfaceTest::Tag::IncrementFlattenable: {
+ using Signature = status_t (ISafeInterfaceTest::*)(const TestFlattenable& a,
+ TestFlattenable* aPlusOne) const;
+ return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
+ }
case ISafeInterfaceTest::Tag::IncrementLightFlattenable: {
using Signature =
status_t (ISafeInterfaceTest::*)(const TestLightFlattenable& a,
@@ -428,6 +465,14 @@
ASSERT_EQ(!b, notB);
}
+TEST_F(SafeInterfaceTest, TestIncrementFlattenable) {
+ const TestFlattenable a{1};
+ TestFlattenable aPlusOne{0};
+ status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
+ ASSERT_EQ(NO_ERROR, result);
+ ASSERT_EQ(a.value + 1, aPlusOne.value);
+}
+
TEST_F(SafeInterfaceTest, TestIncrementLightFlattenable) {
const TestLightFlattenable a{1};
TestLightFlattenable aPlusOne{0};
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 5fc6abe..28c2a48 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -117,6 +117,7 @@
"android.hidl.token@1.0-utils",
"android.hardware.graphics.bufferqueue@1.0",
"android.hardware.configstore@1.0",
+ "android.hardware.configstore-utils",
],
export_shared_lib_headers: [
@@ -125,8 +126,6 @@
"android.hidl.token@1.0-utils",
"android.hardware.graphics.bufferqueue@1.0",
],
-
- header_libs: ["android.hardware.configstore-utils"],
}
subdirs = ["tests"]
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 27ced61..aef231a 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -951,7 +951,11 @@
// Call back without the main BufferQueue lock held, but with the callback
// lock held so we can ensure that callbacks occur in order
- {
+
+ int connectedApi;
+ sp<Fence> lastQueuedFence;
+
+ { // scope for the lock
Mutex::Autolock lock(mCallbackMutex);
while (callbackTicket != mCurrentCallbackTicket) {
mCallbackCondition.wait(mCallbackMutex);
@@ -963,20 +967,24 @@
frameReplacedListener->onFrameReplaced(item);
}
+ connectedApi = mCore->mConnectedApi;
+ lastQueuedFence = std::move(mLastQueueBufferFence);
+
+ mLastQueueBufferFence = std::move(acquireFence);
+ mLastQueuedCrop = item.mCrop;
+ mLastQueuedTransform = item.mTransform;
+
++mCurrentCallbackTicket;
mCallbackCondition.broadcast();
}
// Wait without lock held
- if (mCore->mConnectedApi == NATIVE_WINDOW_API_EGL) {
+ if (connectedApi == NATIVE_WINDOW_API_EGL) {
// Waiting here allows for two full buffers to be queued but not a
// third. In the event that frames take varying time, this makes a
// small trade-off in favor of latency rather than throughput.
- mLastQueueBufferFence->waitForever("Throttling EGL Production");
+ lastQueuedFence->waitForever("Throttling EGL Production");
}
- mLastQueueBufferFence = std::move(acquireFence);
- mLastQueuedCrop = item.mCrop;
- mLastQueuedTransform = item.mTransform;
// Update and get FrameEventHistory.
nsecs_t postedTime = systemTime(SYSTEM_TIME_MONOTONIC);
diff --git a/libs/gui/IConsumerListener.cpp b/libs/gui/IConsumerListener.cpp
index 8cadc4d..85ac304 100644
--- a/libs/gui/IConsumerListener.cpp
+++ b/libs/gui/IConsumerListener.cpp
@@ -14,98 +14,86 @@
* limitations under the License.
*/
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-
#include <gui/IConsumerListener.h>
+
#include <gui/BufferItem.h>
-// ---------------------------------------------------------------------------
namespace android {
-// ---------------------------------------------------------------------------
-enum {
+namespace { // Anonymous
+
+enum class Tag : uint32_t {
ON_DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
ON_FRAME_AVAILABLE,
- ON_BUFFER_RELEASED,
+ ON_FRAME_REPLACED,
+ ON_BUFFERS_RELEASED,
ON_SIDEBAND_STREAM_CHANGED,
- GET_FRAME_TIMESTAMPS
+ LAST = ON_SIDEBAND_STREAM_CHANGED,
};
-class BpConsumerListener : public BpInterface<IConsumerListener>
-{
+} // Anonymous namespace
+
+class BpConsumerListener : public SafeBpInterface<IConsumerListener> {
public:
explicit BpConsumerListener(const sp<IBinder>& impl)
- : BpInterface<IConsumerListener>(impl) {
+ : SafeBpInterface<IConsumerListener>(impl, "BpConsumerListener") {}
+
+ ~BpConsumerListener() override;
+
+ void onDisconnect() override {
+ callRemoteAsync<decltype(&IConsumerListener::onDisconnect)>(Tag::ON_DISCONNECT);
}
- virtual ~BpConsumerListener();
-
- virtual void onDisconnect() {
- Parcel data, reply;
- data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor());
- remote()->transact(ON_DISCONNECT, data, &reply, IBinder::FLAG_ONEWAY);
+ void onFrameAvailable(const BufferItem& item) override {
+ callRemoteAsync<decltype(&IConsumerListener::onFrameAvailable)>(Tag::ON_FRAME_AVAILABLE,
+ item);
}
- virtual void onFrameAvailable(const BufferItem& item) {
- Parcel data, reply;
- data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor());
- data.write(item);
- remote()->transact(ON_FRAME_AVAILABLE, data, &reply, IBinder::FLAG_ONEWAY);
+ void onFrameReplaced(const BufferItem& item) override {
+ callRemoteAsync<decltype(&IConsumerListener::onFrameReplaced)>(Tag::ON_FRAME_REPLACED,
+ item);
}
- virtual void onBuffersReleased() {
- Parcel data, reply;
- data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor());
- remote()->transact(ON_BUFFER_RELEASED, data, &reply, IBinder::FLAG_ONEWAY);
+ void onBuffersReleased() override {
+ callRemoteAsync<decltype(&IConsumerListener::onBuffersReleased)>(Tag::ON_BUFFERS_RELEASED);
}
- virtual void onSidebandStreamChanged() {
- Parcel data, reply;
- data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor());
- remote()->transact(ON_SIDEBAND_STREAM_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
+ void onSidebandStreamChanged() override {
+ callRemoteAsync<decltype(&IConsumerListener::onSidebandStreamChanged)>(
+ Tag::ON_SIDEBAND_STREAM_CHANGED);
+ }
+
+ void addAndGetFrameTimestamps(const NewFrameEventsEntry* /*newTimestamps*/,
+ FrameEventHistoryDelta* /*outDelta*/) override {
+ LOG_ALWAYS_FATAL("IConsumerListener::addAndGetFrameTimestamps cannot be proxied");
}
};
-// Out-of-line virtual method definition to trigger vtable emission in this
-// translation unit (see clang warning -Wweak-vtables)
-BpConsumerListener::~BpConsumerListener() {}
+// Out-of-line virtual method definitions to trigger vtable emission in this translation unit (see
+// clang warning -Wweak-vtables)
+BpConsumerListener::~BpConsumerListener() = default;
+ConsumerListener::~ConsumerListener() = default;
IMPLEMENT_META_INTERFACE(ConsumerListener, "android.gui.IConsumerListener");
-// ----------------------------------------------------------------------
-
-status_t BnConsumerListener::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- switch(code) {
- case ON_DISCONNECT: {
- CHECK_INTERFACE(IConsumerListener, data, reply);
- onDisconnect();
- return NO_ERROR; }
- case ON_FRAME_AVAILABLE: {
- CHECK_INTERFACE(IConsumerListener, data, reply);
- BufferItem item;
- data.read(item);
- onFrameAvailable(item);
- return NO_ERROR; }
- case ON_BUFFER_RELEASED: {
- CHECK_INTERFACE(IConsumerListener, data, reply);
- onBuffersReleased();
- return NO_ERROR; }
- case ON_SIDEBAND_STREAM_CHANGED: {
- CHECK_INTERFACE(IConsumerListener, data, reply);
- onSidebandStreamChanged();
- return NO_ERROR; }
+status_t BnConsumerListener::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::ON_DISCONNECT:
+ return callLocalAsync(data, reply, &IConsumerListener::onDisconnect);
+ case Tag::ON_FRAME_AVAILABLE:
+ return callLocalAsync(data, reply, &IConsumerListener::onFrameAvailable);
+ case Tag::ON_FRAME_REPLACED:
+ return callLocalAsync(data, reply, &IConsumerListener::onFrameReplaced);
+ case Tag::ON_BUFFERS_RELEASED:
+ return callLocalAsync(data, reply, &IConsumerListener::onBuffersReleased);
+ case Tag::ON_SIDEBAND_STREAM_CHANGED:
+ return callLocalAsync(data, reply, &IConsumerListener::onSidebandStreamChanged);
+ }
}
-ConsumerListener::~ConsumerListener() = default;
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-// ---------------------------------------------------------------------------
+} // namespace android
diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp
index 2d2146b..679f44b 100644
--- a/libs/gui/ISurfaceComposerClient.cpp
+++ b/libs/gui/ISurfaceComposerClient.cpp
@@ -17,24 +17,28 @@
// tag as surfaceflinger
#define LOG_TAG "SurfaceFlinger"
-#include <stdint.h>
-#include <stdio.h>
-#include <sys/types.h>
+#include <gui/ISurfaceComposerClient.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/Parcel.h>
+#include <gui/IGraphicBufferProducer.h>
+
#include <binder/SafeInterface.h>
#include <ui/FrameStats.h>
-#include <ui/Point.h>
-#include <ui/Rect.h>
-
-#include <gui/IGraphicBufferProducer.h>
-#include <gui/ISurfaceComposerClient.h>
namespace android {
+namespace { // Anonymous
+
+enum class Tag : uint32_t {
+ CREATE_SURFACE = IBinder::FIRST_CALL_TRANSACTION,
+ DESTROY_SURFACE,
+ CLEAR_LAYER_FRAME_STATS,
+ GET_LAYER_FRAME_STATS,
+ LAST = GET_LAYER_FRAME_STATS,
+};
+
+} // Anonymous namespace
+
class BpSurfaceComposerClient : public SafeBpInterface<ISurfaceComposerClient> {
public:
explicit BpSurfaceComposerClient(const sp<IBinder>& impl)
@@ -46,7 +50,7 @@
uint32_t flags, const sp<IBinder>& parent, uint32_t windowType,
uint32_t ownerUid, sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp) override {
- return callRemote<decltype(&ISurfaceComposerClient::createSurface)>(Tag::CreateSurface,
+ return callRemote<decltype(&ISurfaceComposerClient::createSurface)>(Tag::CREATE_SURFACE,
name, width, height,
format, flags, parent,
windowType, ownerUid,
@@ -54,18 +58,19 @@
}
status_t destroySurface(const sp<IBinder>& handle) override {
- return callRemote<decltype(&ISurfaceComposerClient::destroySurface)>(Tag::DestroySurface,
+ return callRemote<decltype(&ISurfaceComposerClient::destroySurface)>(Tag::DESTROY_SURFACE,
handle);
}
status_t clearLayerFrameStats(const sp<IBinder>& handle) const override {
return callRemote<decltype(
- &ISurfaceComposerClient::clearLayerFrameStats)>(Tag::ClearLayerFrameStats, handle);
+ &ISurfaceComposerClient::clearLayerFrameStats)>(Tag::CLEAR_LAYER_FRAME_STATS,
+ handle);
}
status_t getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const override {
return callRemote<decltype(
- &ISurfaceComposerClient::getLayerFrameStats)>(Tag::GetLayerFrameStats, handle,
+ &ISurfaceComposerClient::getLayerFrameStats)>(Tag::GET_LAYER_FRAME_STATS, handle,
outStats);
}
};
@@ -80,26 +85,19 @@
status_t BnSurfaceComposerClient::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)) {
+ if (code < IBinder::FIRST_CALL_TRANSACTION || code > static_cast<uint32_t>(Tag::LAST)) {
return BBinder::onTransact(code, data, reply, flags);
}
auto tag = static_cast<Tag>(code);
switch (tag) {
- case Tag::CreateSurface: {
+ case Tag::CREATE_SURFACE:
return callLocal(data, reply, &ISurfaceComposerClient::createSurface);
- }
- case Tag::DestroySurface: {
+ case Tag::DESTROY_SURFACE:
return callLocal(data, reply, &ISurfaceComposerClient::destroySurface);
- }
- case Tag::ClearLayerFrameStats: {
+ case Tag::CLEAR_LAYER_FRAME_STATS:
return callLocal(data, reply, &ISurfaceComposerClient::clearLayerFrameStats);
- }
- case Tag::GetLayerFrameStats: {
+ case Tag::GET_LAYER_FRAME_STATS:
return callLocal(data, reply, &ISurfaceComposerClient::getLayerFrameStats);
- }
- case Tag::Last:
- // Should not be possible because of the check at the beginning of the method
- return BBinder::onTransact(code, data, reply, flags);
}
}
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index 3a99147..192bfc8 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -27,6 +27,8 @@
],
shared_libs: [
+ "android.hardware.configstore@1.0",
+ "android.hardware.configstore-utils",
"liblog",
"libEGL",
"libGLESv1_CM",
@@ -34,6 +36,8 @@
"libbinder",
"libcutils",
"libgui",
+ "libhidlbase",
+ "libhidltransport",
"libui",
"libutils",
"libnativewindow"
diff --git a/libs/gui/tests/CpuConsumer_test.cpp b/libs/gui/tests/CpuConsumer_test.cpp
index 9c2e838..5848c74 100644
--- a/libs/gui/tests/CpuConsumer_test.cpp
+++ b/libs/gui/tests/CpuConsumer_test.cpp
@@ -490,7 +490,7 @@
ASSERT_TRUE(anb != NULL);
- sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+ sp<GraphicBuffer> buf(GraphicBuffer::from(anb));
*stride = buf->getStride();
uint8_t* img = NULL;
diff --git a/libs/gui/tests/FillBuffer.cpp b/libs/gui/tests/FillBuffer.cpp
index 079962c..ccd674f 100644
--- a/libs/gui/tests/FillBuffer.cpp
+++ b/libs/gui/tests/FillBuffer.cpp
@@ -95,7 +95,7 @@
&anb));
ASSERT_TRUE(anb != NULL);
- sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+ sp<GraphicBuffer> buf(GraphicBuffer::from(anb));
uint8_t* img = NULL;
ASSERT_EQ(NO_ERROR, buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN,
diff --git a/libs/gui/tests/SurfaceTextureFBO_test.cpp b/libs/gui/tests/SurfaceTextureFBO_test.cpp
index 0606839..0134273 100644
--- a/libs/gui/tests/SurfaceTextureFBO_test.cpp
+++ b/libs/gui/tests/SurfaceTextureFBO_test.cpp
@@ -41,7 +41,7 @@
&anb));
ASSERT_TRUE(anb != NULL);
- sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+ sp<GraphicBuffer> buf(GraphicBuffer::from(anb));
// Fill the buffer with green
uint8_t* img = NULL;
@@ -65,7 +65,7 @@
&anb));
ASSERT_TRUE(anb != NULL);
- buf = new GraphicBuffer(anb, false);
+ buf = GraphicBuffer::from(anb);
// Fill the buffer with red
ASSERT_EQ(NO_ERROR, buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN,
diff --git a/libs/gui/tests/SurfaceTextureGL_test.cpp b/libs/gui/tests/SurfaceTextureGL_test.cpp
index 308bd7d..c6745d0 100644
--- a/libs/gui/tests/SurfaceTextureGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureGL_test.cpp
@@ -42,7 +42,7 @@
&anb));
ASSERT_TRUE(anb != NULL);
- sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+ sp<GraphicBuffer> buf(GraphicBuffer::from(anb));
// Fill the buffer with the a checkerboard pattern
uint8_t* img = NULL;
@@ -92,7 +92,7 @@
&anb));
ASSERT_TRUE(anb != NULL);
- sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+ sp<GraphicBuffer> buf(GraphicBuffer::from(anb));
// Fill the buffer with the a checkerboard pattern
uint8_t* img = NULL;
@@ -157,7 +157,7 @@
&anb));
ASSERT_TRUE(anb != NULL);
- sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+ sp<GraphicBuffer> buf(GraphicBuffer::from(anb));
uint8_t* img = NULL;
buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
@@ -238,7 +238,7 @@
return false;
}
- sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+ sp<GraphicBuffer> buf(GraphicBuffer::from(anb));
const int yuvTexOffsetY = 0;
int stride = buf->getStride();
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 3932b92..ce11486 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -18,7 +18,9 @@
#include <gtest/gtest.h>
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <binder/ProcessState.h>
+#include <configstore/Utils.h>
#include <cutils/properties.h>
#include <gui/BufferItemConsumer.h>
#include <gui/IDisplayEventConnection.h>
@@ -35,6 +37,12 @@
namespace android {
using namespace std::chrono_literals;
+// retrieve wide-color and hdr settings from configstore
+using namespace android::hardware::configstore;
+using namespace android::hardware::configstore::V1_0;
+
+static bool hasWideColorDisplay =
+ getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
class FakeSurfaceComposer;
class FakeProducerFrameEventHistory;
@@ -271,17 +279,19 @@
bool supported;
surface->getWideColorSupport(&supported);
- // TODO(courtneygo): How can we know what device we are on to
- // verify that this is correct?
- char product[PROPERTY_VALUE_MAX] = "0";
- property_get("ro.build.product", product, "0");
- std::cerr << "[ ] product = " << product << std::endl;
-
- if (strcmp("marlin", product) == 0 || strcmp("sailfish", product) == 0) {
- ASSERT_EQ(true, supported);
- } else {
- ASSERT_EQ(false, supported);
- }
+ // NOTE: This test assumes that device that supports
+ // wide-color (as indicated by BoardConfig) must also
+ // have a wide-color primary display.
+ // That assumption allows this test to cover devices
+ // that advertised a wide-color color mode without
+ // actually supporting wide-color to pass this test
+ // as well as the case of a device that does support
+ // wide-color (via BoardConfig) and has a wide-color
+ // primary display.
+ // NOT covered at this time is a device that supports
+ // wide color in the BoardConfig but does not support
+ // a wide-color color mode on the primary display.
+ ASSERT_EQ(hasWideColorDisplay, supported);
}
TEST_F(SurfaceTest, DynamicSetBufferCount) {
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..310d25e 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -45,6 +45,7 @@
srcs: [
"ColorSpace.cpp",
+ "DebugUtils.cpp",
"Fence.cpp",
"FenceTime.cpp",
"FrameStats.cpp",
@@ -66,6 +67,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/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 6e84730..d21758d 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -39,6 +39,10 @@
return id;
}
+sp<GraphicBuffer> GraphicBuffer::from(ANativeWindowBuffer* anwb) {
+ return static_cast<GraphicBuffer *>(anwb);
+}
+
GraphicBuffer::GraphicBuffer()
: BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
@@ -52,86 +56,42 @@
handle = NULL;
}
+// deprecated
GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
PixelFormat inFormat, uint32_t inUsage, std::string requestorName)
- : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
- mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
+ : GraphicBuffer(inWidth, inHeight, inFormat, 1, inUsage, inUsage,
+ requestorName)
{
- width =
- height =
- stride =
- format =
- usage = 0;
- layerCount = 0;
- handle = NULL;
- mInitCheck = initSize(inWidth, inHeight, inFormat, 1, inUsage, inUsage,
- std::move(requestorName));
}
GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
PixelFormat inFormat, uint32_t inLayerCount, uint64_t producerUsage,
uint64_t consumerUsage, std::string requestorName)
- : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
- mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
+ : GraphicBuffer()
{
- width =
- height =
- stride =
- format =
- usage = 0;
- layerCount = 0;
- handle = NULL;
- mInitCheck = initSize(inWidth, inHeight, inFormat, inLayerCount,
+ mInitCheck = initWithSize(inWidth, inHeight, inFormat, inLayerCount,
producerUsage, consumerUsage, std::move(requestorName));
}
+// deprecated
GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage,
uint32_t inStride, native_handle_t* inHandle, bool keepOwnership)
- : BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
- mBufferMapper(GraphicBufferMapper::get()),
- mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
+ : GraphicBuffer(inHandle, keepOwnership ? TAKE_HANDLE : WRAP_HANDLE,
+ inWidth, inHeight, inFormat, inLayerCount, inUsage, inUsage,
+ inStride)
{
- width = static_cast<int>(inWidth);
- height = static_cast<int>(inHeight);
- stride = static_cast<int>(inStride);
- format = inFormat;
- layerCount = inLayerCount;
- usage = static_cast<int>(inUsage);
- handle = inHandle;
}
-GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
- PixelFormat inFormat, uint32_t inLayerCount, uint32_t inProducerUsage,
- uint32_t inConsumerUsage, uint32_t inStride,
- native_handle_t* inHandle, bool keepOwnership)
- : BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
- mBufferMapper(GraphicBufferMapper::get()),
- mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
+GraphicBuffer::GraphicBuffer(const native_handle_t* handle,
+ HandleWrapMethod method, uint32_t width, uint32_t height,
+ PixelFormat format, uint32_t layerCount,
+ uint64_t producerUsage, uint64_t consumerUsage,
+ uint32_t stride)
+ : GraphicBuffer()
{
- width = static_cast<int>(inWidth);
- height = static_cast<int>(inHeight);
- stride = static_cast<int>(inStride);
- format = inFormat;
- layerCount = inLayerCount;
- usage = android_convertGralloc1To0Usage(inProducerUsage, inConsumerUsage);
- handle = inHandle;
-}
-
-
-GraphicBuffer::GraphicBuffer(ANativeWindowBuffer* buffer, bool keepOwnership)
- : BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
- mBufferMapper(GraphicBufferMapper::get()),
- mInitCheck(NO_ERROR), mWrappedBuffer(buffer), mId(getUniqueId()),
- mGenerationNumber(0)
-{
- width = buffer->width;
- height = buffer->height;
- stride = buffer->stride;
- format = buffer->format;
- layerCount = buffer->layerCount;
- usage = buffer->usage;
- handle = buffer->handle;
+ mInitCheck = initWithHandle(handle, method, width, height, format,
+ layerCount, producerUsage, consumerUsage, stride);
}
GraphicBuffer::~GraphicBuffer()
@@ -154,7 +114,6 @@
allocator.free(handle);
}
handle = NULL;
- mWrappedBuffer = 0;
}
status_t GraphicBuffer::initCheck() const {
@@ -192,8 +151,8 @@
allocator.free(handle);
handle = 0;
}
- return initSize(inWidth, inHeight, inFormat, inLayerCount, inUsage, inUsage,
- "[Reallocation]");
+ return initWithSize(inWidth, inHeight, inFormat, inLayerCount,
+ inUsage, inUsage, "[Reallocation]");
}
bool GraphicBuffer::needsReallocation(uint32_t inWidth, uint32_t inHeight,
@@ -207,7 +166,7 @@
return false;
}
-status_t GraphicBuffer::initSize(uint32_t inWidth, uint32_t inHeight,
+status_t GraphicBuffer::initWithSize(uint32_t inWidth, uint32_t inHeight,
PixelFormat inFormat, uint32_t inLayerCount, uint64_t inProducerUsage,
uint64_t inConsumerUsage, std::string requestorName)
{
@@ -227,6 +186,54 @@
return err;
}
+status_t GraphicBuffer::initWithHandle(const native_handle_t* handle,
+ HandleWrapMethod method, uint32_t width, uint32_t height,
+ PixelFormat format, uint32_t layerCount,
+ uint64_t producerUsage, uint64_t consumerUsage,
+ uint32_t stride)
+{
+ native_handle_t* clone = nullptr;
+
+ if (method == CLONE_HANDLE) {
+ clone = native_handle_clone(handle);
+ if (!clone) {
+ return NO_MEMORY;
+ }
+
+ handle = clone;
+ method = TAKE_UNREGISTERED_HANDLE;
+ }
+
+ ANativeWindowBuffer::width = static_cast<int>(width);
+ ANativeWindowBuffer::height = static_cast<int>(height);
+ ANativeWindowBuffer::stride = static_cast<int>(stride);
+ ANativeWindowBuffer::format = format;
+ ANativeWindowBuffer::usage =
+ android_convertGralloc1To0Usage(producerUsage, consumerUsage);
+
+ ANativeWindowBuffer::layerCount = layerCount;
+ ANativeWindowBuffer::handle = handle;
+
+ mOwner = (method == WRAP_HANDLE) ? ownNone : ownHandle;
+
+ if (method == TAKE_UNREGISTERED_HANDLE) {
+ status_t err = mBufferMapper.registerBuffer(this);
+ if (err != NO_ERROR) {
+ // clean up cloned handle
+ if (clone) {
+ native_handle_close(clone);
+ native_handle_delete(clone);
+ }
+
+ initWithHandle(nullptr, WRAP_HANDLE, 0, 0, 0, 0, 0, 0, 0);
+
+ return err;
+ }
+ }
+
+ return NO_ERROR;
+}
+
status_t GraphicBuffer::lock(uint32_t inUsage, void** vaddr)
{
const Rect lockBounds(width, height);
diff --git a/libs/vr/libbufferhub/ion_buffer.cpp b/libs/vr/libbufferhub/ion_buffer.cpp
index 3fb3f3c..e5a56c1 100644
--- a/libs/vr/libbufferhub/ion_buffer.cpp
+++ b/libs/vr/libbufferhub/ion_buffer.cpp
@@ -1,5 +1,4 @@
#include <private/dvr/ion_buffer.h>
-#include <ui/GraphicBufferMapper.h>
#include <log/log.h>
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
@@ -70,10 +69,9 @@
ALOGD_IF(TRACE, "IonBuffer::Alloc: width=%d height=%d format=%d usage=%d",
width, height, format, usage);
- GraphicBufferMapper& mapper = GraphicBufferMapper::get();
buffer_ = new GraphicBuffer(width, height, format, usage);
- if (mapper.registerBuffer(buffer_.get()) != OK) {
- ALOGE("IonBuffer::Aloc: Failed to register buffer");
+ if (buffer_->initCheck() != OK) {
+ ALOGE("IonBuffer::Aloc: Failed to allocate buffer");
}
return 0;
}
@@ -96,11 +94,10 @@
"usage=%d",
handle, width, height, stride, format, usage);
FreeHandle();
- GraphicBufferMapper& mapper = GraphicBufferMapper::get();
- buffer_ = new GraphicBuffer(width, height, format, 1, usage,
- stride, (native_handle_t*)handle, true);
- if (mapper.registerBuffer(buffer_.get()) != OK) {
- ALOGE("IonBuffer::Import: Failed to register cloned buffer");
+ buffer_ = new GraphicBuffer(handle, GraphicBuffer::TAKE_UNREGISTERED_HANDLE,
+ width, height, format, 1, usage, stride);
+ if (buffer_->initCheck() != OK) {
+ ALOGE("IonBuffer::Import: Failed to import buffer");
return -EINVAL;
}
return 0;
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_core.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_core.cpp
index a108042..a826a69 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_core.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_core.cpp
@@ -50,27 +50,7 @@
LOG_ALWAYS_FATAL_IF(buffer_producer == nullptr,
"Failed to get buffer producer at slot: %zu", slot);
- // Allocating a new buffer, |buffers_[slot]| should be in initial state.
- LOG_ALWAYS_FATAL_IF(buffers_[slot].mGraphicBuffer != nullptr,
- "AllocateBuffer: slot %zu is not empty.", slot);
-
- // 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.");
buffers_[slot].mBufferProducer = buffer_producer;
- buffers_[slot].mGraphicBuffer = graphic_buffer;
return NO_ERROR;
}
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
index ddf7fd2..3fe7642 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
@@ -8,7 +8,7 @@
BufferHubQueueProducer::BufferHubQueueProducer(
const std::shared_ptr<BufferHubQueueCore>& core)
- : core_(core), req_buffer_count_(kInvalidBufferCount) {}
+ : core_(core) {}
status_t BufferHubQueueProducer::requestBuffer(int slot,
sp<GraphicBuffer>* buf) {
@@ -16,18 +16,48 @@
std::unique_lock<std::mutex> lock(core_->mutex_);
- if (slot < 0 || slot >= req_buffer_count_) {
+ if (core_->connected_api_ == BufferHubQueueCore::kNoConnectedApi) {
+ ALOGE("requestBuffer: BufferHubQueueProducer has no connected producer");
+ return NO_INIT;
+ }
+
+ if (slot < 0 || slot >= max_buffer_count_) {
ALOGE("requestBuffer: slot index %d out of range [0, %d)", slot,
- req_buffer_count_);
+ max_buffer_count_);
return BAD_VALUE;
} else if (!core_->buffers_[slot].mBufferState.isDequeued()) {
ALOGE("requestBuffer: slot %d is not owned by the producer (state = %s)",
slot, core_->buffers_[slot].mBufferState.string());
return BAD_VALUE;
+ } else if (core_->buffers_[slot].mGraphicBuffer != nullptr) {
+ ALOGE("requestBuffer: slot %d is not empty.", slot);
+ return BAD_VALUE;
+ } else if (core_->buffers_[slot].mBufferProducer == nullptr) {
+ ALOGE("requestBuffer: slot %d is not dequeued.", slot);
+ return BAD_VALUE;
}
+ const auto& buffer_producer = core_->buffers_[slot].mBufferProducer;
+
+ // 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;
- *buf = core_->buffers_[slot].mGraphicBuffer;
+
+ *buf = graphic_buffer;
return NO_ERROR;
}
@@ -46,30 +76,68 @@
return BAD_VALUE;
}
- req_buffer_count_ = max_dequeued_buffers;
+ // The new dequeued_buffers count should not be violated by the number
+ // of currently dequeued buffers.
+ int dequeued_count = 0;
+ for (const auto& buf : core_->buffers_) {
+ if (buf.mBufferState.isDequeued()) {
+ dequeued_count++;
+ }
+ }
+ if (dequeued_count > max_dequeued_buffers) {
+ ALOGE(
+ "setMaxDequeuedBufferCount: the requested dequeued_buffers"
+ "count (%d) exceeds the current dequeued buffer count (%d)",
+ max_dequeued_buffers, dequeued_count);
+ return BAD_VALUE;
+ }
+
+ max_dequeued_buffer_count_ = max_dequeued_buffers;
return NO_ERROR;
}
-status_t BufferHubQueueProducer::setAsyncMode(bool /* async */) {
- ALOGE("BufferHubQueueProducer::setAsyncMode not implemented.");
- return INVALID_OPERATION;
+status_t BufferHubQueueProducer::setAsyncMode(bool async) {
+ if (async) {
+ // TODO(b/36724099) BufferHubQueue's consumer end always acquires the buffer
+ // automatically and behaves differently from IGraphicBufferConsumer. Thus,
+ // android::BufferQueue's async mode (a.k.a. allocating an additional buffer
+ // to prevent dequeueBuffer from being blocking) technically does not apply
+ // here.
+ //
+ // In Daydream, non-blocking producer side dequeue is guaranteed by careful
+ // buffer consumer implementations. In another word, BufferHubQueue based
+ // dequeueBuffer should never block whether setAsyncMode(true) is set or
+ // not.
+ //
+ // See: IGraphicBufferProducer::setAsyncMode and
+ // BufferQueueProducer::setAsyncMode for more about original implementation.
+ ALOGW(
+ "BufferHubQueueProducer::setAsyncMode: BufferHubQueue should always be "
+ "asynchronous. This call makes no effact.");
+ return NO_ERROR;
+ }
+ return NO_ERROR;
}
-status_t BufferHubQueueProducer::dequeueBuffer(int* out_slot,
- sp<Fence>* out_fence,
- uint32_t width, uint32_t height,
- PixelFormat format,
- uint32_t usage,
- FrameEventHistoryDelta* /* outTimestamps */) {
+status_t BufferHubQueueProducer::dequeueBuffer(
+ int* out_slot, sp<Fence>* out_fence, uint32_t width, uint32_t height,
+ PixelFormat format, uint32_t usage,
+ FrameEventHistoryDelta* /* out_timestamps */) {
ALOGD_IF(TRACE, "dequeueBuffer: w=%u, h=%u, format=%d, usage=%u", width,
height, format, usage);
status_t ret;
std::unique_lock<std::mutex> lock(core_->mutex_);
- if (static_cast<int32_t>(core_->producer_->capacity()) < req_buffer_count_) {
+ if (core_->connected_api_ == BufferHubQueueCore::kNoConnectedApi) {
+ ALOGE("dequeueBuffer: BufferQueue has no connected producer");
+ return NO_INIT;
+ }
+
+ if (static_cast<int32_t>(core_->producer_->capacity()) <
+ max_dequeued_buffer_count_) {
// Lazy allocation. When the capacity of |core_->producer_| has not reach
- // |req_buffer_count_|, allocate new buffer.
+ // |max_dequeued_buffer_count_|, allocate new buffer.
// TODO(jwcai) To save memory, the really reasonable thing to do is to go
// over existing slots and find first existing one to dequeue.
ret = core_->AllocateBuffer(width, height, format, usage, 1);
@@ -126,8 +194,8 @@
// BufferHubQueue).
// TODO(jwcai) Clean this up, make mBufferState compatible with BufferHub's
// model.
- LOG_ALWAYS_FATAL_IF(!core_->buffers_[slot].mBufferState.isFree() &&
- !core_->buffers_[slot].mBufferState.isQueued(),
+ LOG_ALWAYS_FATAL_IF((!core_->buffers_[slot].mBufferState.isFree() &&
+ !core_->buffers_[slot].mBufferState.isQueued()),
"dequeueBuffer: slot %zu is not free or queued.", slot);
core_->buffers_[slot].mBufferState.freeQueued();
@@ -170,22 +238,39 @@
status_t BufferHubQueueProducer::queueBuffer(int slot,
const QueueBufferInput& input,
- QueueBufferOutput* /* output */) {
+ QueueBufferOutput* output) {
ALOGD_IF(TRACE, "queueBuffer: slot %d", slot);
+ if (output == nullptr) {
+ return BAD_VALUE;
+ }
+
int64_t timestamp;
+ int scaling_mode;
sp<Fence> fence;
+ Rect crop(Rect::EMPTY_RECT);
// TODO(jwcai) The following attributes are ignored.
bool is_auto_timestamp;
android_dataspace data_space;
- Rect crop(Rect::EMPTY_RECT);
- int scaling_mode;
uint32_t transform;
input.deflate(×tamp, &is_auto_timestamp, &data_space, &crop,
&scaling_mode, &transform, &fence);
+ // Check input scaling mode is valid.
+ switch (scaling_mode) {
+ case NATIVE_WINDOW_SCALING_MODE_FREEZE:
+ case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
+ case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
+ case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
+ break;
+ default:
+ ALOGE("queueBuffer: unknown scaling mode %d", scaling_mode);
+ return BAD_VALUE;
+ }
+
+ // Check input fence is valid.
if (fence == nullptr) {
ALOGE("queueBuffer: fence is NULL");
return BAD_VALUE;
@@ -194,25 +279,61 @@
status_t ret;
std::unique_lock<std::mutex> lock(core_->mutex_);
- if (slot < 0 || slot >= req_buffer_count_) {
+ if (core_->connected_api_ == BufferHubQueueCore::kNoConnectedApi) {
+ ALOGE("queueBuffer: BufferQueue has no connected producer");
+ return NO_INIT;
+ }
+
+ if (slot < 0 || slot >= max_buffer_count_) {
ALOGE("queueBuffer: slot index %d out of range [0, %d)", slot,
- req_buffer_count_);
+ max_buffer_count_);
return BAD_VALUE;
} else if (!core_->buffers_[slot].mBufferState.isDequeued()) {
ALOGE("queueBuffer: slot %d is not owned by the producer (state = %s)",
slot, core_->buffers_[slot].mBufferState.string());
return BAD_VALUE;
+ } else if ((!core_->buffers_[slot].mRequestBufferCalled ||
+ core_->buffers_[slot].mGraphicBuffer == nullptr)) {
+ ALOGE(
+ "queueBuffer: slot %d is not requested (mRequestBufferCalled=%d, "
+ "mGraphicBuffer=%p)",
+ slot, core_->buffers_[slot].mRequestBufferCalled,
+ core_->buffers_[slot].mGraphicBuffer.get());
+ return BAD_VALUE;
}
// Post the buffer producer with timestamp in the metadata.
- auto buffer_producer = core_->buffers_[slot].mBufferProducer;
+ const auto& buffer_producer = core_->buffers_[slot].mBufferProducer;
+
+ // Check input crop is not out of boundary of current buffer.
+ Rect buffer_rect(buffer_producer->width(), buffer_producer->height());
+ Rect cropped_rect(Rect::EMPTY_RECT);
+ crop.intersect(buffer_rect, &cropped_rect);
+ if (cropped_rect != crop) {
+ ALOGE("queueBuffer: slot %d has out-of-boundary crop.", slot);
+ return BAD_VALUE;
+ }
+
LocalHandle fence_fd(fence->isValid() ? fence->dup() : -1);
BufferHubQueueCore::BufferMetadata meta_data = {.timestamp = timestamp};
buffer_producer->Post(fence_fd, &meta_data, sizeof(meta_data));
core_->buffers_[slot].mBufferState.queue();
- // TODO(jwcai) check how to fill in output properly.
+ output->width = buffer_producer->width();
+ output->height = buffer_producer->height();
+ 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
+ // of BufferHubQueue design, this is hard to trace from the producer's client
+ // side, but it's safe to assume it's zero.
+ output->numPendingBuffers = 0;
+
+ // Note that we are not setting nextFrameNumber here as it seems to be only
+ // used by surface flinger. See more at b/22802885, ag/791760.
+ output->nextFrameNumber = 0;
+
return NO_ERROR;
}
@@ -222,15 +343,20 @@
std::unique_lock<std::mutex> lock(core_->mutex_);
- if (slot < 0 || slot >= req_buffer_count_) {
+ if (core_->connected_api_ == BufferHubQueueCore::kNoConnectedApi) {
+ ALOGE("cancelBuffer: BufferQueue has no connected producer");
+ return NO_INIT;
+ }
+
+ if (slot < 0 || slot >= max_buffer_count_) {
ALOGE("cancelBuffer: slot index %d out of range [0, %d)", slot,
- req_buffer_count_);
+ max_buffer_count_);
return BAD_VALUE;
} else if (!core_->buffers_[slot].mBufferState.isDequeued()) {
ALOGE("cancelBuffer: slot %d is not owned by the producer (state = %s)",
slot, core_->buffers_[slot].mBufferState.string());
return BAD_VALUE;
- } else if (fence == NULL) {
+ } else if (fence == nullptr) {
ALOGE("cancelBuffer: fence is NULL");
return BAD_VALUE;
}
@@ -249,7 +375,7 @@
std::unique_lock<std::mutex> lock(core_->mutex_);
- if (out_value == NULL) {
+ if (out_value == nullptr) {
ALOGE("query: out_value was NULL");
return BAD_VALUE;
}
@@ -262,15 +388,30 @@
case NATIVE_WINDOW_BUFFER_AGE:
value = 0;
break;
+ case NATIVE_WINDOW_WIDTH:
+ value = core_->producer_->default_width();
+ break;
+ case NATIVE_WINDOW_HEIGHT:
+ value = core_->producer_->default_height();
+ break;
+ case NATIVE_WINDOW_FORMAT:
+ value = core_->producer_->default_format();
+ break;
+ case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
+ // BufferHubQueue is always operating in async mode, thus semantically
+ // consumer can never be running behind. See BufferQueueCore.cpp core
+ // for more information about the original meaning of this flag.
+ value = 0;
+ break;
+ case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
+ // TODO(jwcai) This is currently not implement as we don't need
+ // IGraphicBufferConsumer parity.
+ value = 0;
+ break;
// The following queries are currently considered as unsupported.
// TODO(jwcai) Need to carefully check the whether they should be
// supported after all.
- case NATIVE_WINDOW_WIDTH:
- case NATIVE_WINDOW_HEIGHT:
- case NATIVE_WINDOW_FORMAT:
case NATIVE_WINDOW_STICKY_TRANSFORM:
- case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
- case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
case NATIVE_WINDOW_DEFAULT_DATASPACE:
default:
return BAD_VALUE;
@@ -282,24 +423,58 @@
}
status_t BufferHubQueueProducer::connect(
- const sp<IProducerListener>& /* listener */, int /* api */,
- bool /* producer_controlled_by_app */, QueueBufferOutput* /* output */) {
+ const sp<IProducerListener>& /* listener */, int api,
+ bool /* producer_controlled_by_app */, QueueBufferOutput* output) {
// Consumer interaction are actually handled by buffer hub, and we need
- // to maintain consumer operations here. Hence |connect| is a NO-OP.
+ // to maintain consumer operations here. We only need to perform basic input
+ // parameter checks here.
ALOGD_IF(TRACE, __FUNCTION__);
+
+ if (output == nullptr) {
+ return BAD_VALUE;
+ }
+
+ std::unique_lock<std::mutex> lock(core_->mutex_);
+
+ if (core_->connected_api_ != BufferHubQueueCore::kNoConnectedApi) {
+ return BAD_VALUE;
+ }
+
+ switch (api) {
+ case NATIVE_WINDOW_API_EGL:
+ case NATIVE_WINDOW_API_CPU:
+ case NATIVE_WINDOW_API_MEDIA:
+ case NATIVE_WINDOW_API_CAMERA:
+ core_->connected_api_ = api;
+ // TODO(jwcai) Fill output.
+ break;
+ default:
+ ALOGE("BufferHubQueueProducer::connect: unknow API %d", api);
+ return BAD_VALUE;
+ }
+
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. Hence |disconnect| is a NO-OP.
+ // to maintain consumer operations here. We only need to perform basic input
+ // parameter checks here.
ALOGD_IF(TRACE, __FUNCTION__);
+
+ std::unique_lock<std::mutex> lock(core_->mutex_);
+
+ if (api != core_->connected_api_) {
+ return BAD_VALUE;
+ }
+
+ core_->connected_api_ = BufferHubQueueCore::kNoConnectedApi;
return NO_ERROR;
}
status_t BufferHubQueueProducer::setSidebandStream(
const sp<NativeHandle>& stream) {
- if (stream != NULL) {
+ if (stream != nullptr) {
// TODO(jwcai) Investigate how is is used, maybe use BufferHubBuffer's
// metadata.
ALOGE("SidebandStream is not currently supported.");
@@ -314,7 +489,7 @@
uint32_t /* usage */) {
// TODO(jwcai) |allocateBuffers| aims to preallocate up to the maximum number
// of buffers permitted by the current BufferQueue configuration (aka
- // |req_buffer_count_|).
+ // |max_buffer_count_|).
ALOGE("BufferHubQueueProducer::allocateBuffers not implemented.");
}
@@ -343,6 +518,7 @@
status_t BufferHubQueueProducer::setSharedBufferMode(
bool /* shared_buffer_mode */) {
ALOGE("BufferHubQueueProducer::setSharedBufferMode not implemented.");
+ // TODO(b/36373181) Front buffer mode for buffer hub queue as ANativeWindow.
return INVALID_OPERATION;
}
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 f786356..a020dca 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
@@ -32,6 +32,15 @@
// a new consumer queue client or nullptr on failure.
std::unique_ptr<ConsumerQueue> CreateConsumerQueue();
+ // Return the default buffer width of this buffer queue.
+ size_t default_width() const { return default_width_; }
+
+ // Return the default buffer height of this buffer queue.
+ size_t default_height() const { return default_height_; }
+
+ // Return the default buffer format of this buffer queue.
+ int32_t default_format() const { return default_format_; }
+
// Return the number of buffers avaiable for dequeue.
size_t count() const { return available_buffers_.GetSize(); }
@@ -169,6 +178,18 @@
void operator=(BufferInfo&) = delete;
};
+ // Default buffer width that can be set to override the buffer width when a
+ // width and height of 0 are specified in AllocateBuffer.
+ size_t default_width_{1};
+
+ // Default buffer height that can be set to override the buffer height when a
+ // width and height of 0 are specified in AllocateBuffer.
+ size_t default_height_{1};
+
+ // Default buffer format that can be set to override the buffer format when it
+ // isn't specified in AllocateBuffer.
+ int32_t default_format_{PIXEL_FORMAT_RGBA_8888};
+
// Buffer queue:
// |buffers_| tracks all |BufferHubBuffer|s created by this |BufferHubQueue|.
std::vector<std::shared_ptr<BufferHubBuffer>> buffers_;
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_core.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_core.h
index ba0c0c5..e353187 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_core.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_core.h
@@ -17,6 +17,8 @@
friend class BufferHubQueueProducer;
public:
+ static constexpr int kNoConnectedApi = -1;
+
// Create a BufferHubQueueCore instance by creating a new producer queue.
static std::shared_ptr<BufferHubQueueCore> Create();
@@ -87,6 +89,9 @@
// Mutex for thread safety.
std::mutex mutex_;
+ // Connect client API, should be one of the NATIVE_WINDOW_API_* flags.
+ int connected_api_{kNoConnectedApi};
+
// |buffers_| stores the buffers that have been dequeued from
// |dvr::BufferHubQueue|, It is initialized to invalid buffers, and gets
// filled in with the result of |Dequeue|.
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
index 5b1a7e0..43e5ce3 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
@@ -103,13 +103,15 @@
private:
using LocalHandle = pdx::LocalHandle;
- static constexpr int kInvalidBufferCount = -1;
-
// |core_| holds the actually buffer slots.
std::shared_ptr<BufferHubQueueCore> core_;
- // |req_buffer_count_| sets the capacity of the underlying buffer queue.
- int32_t req_buffer_count_;
+ // |max_buffer_count_| sets the capacity of the underlying buffer queue.
+ int32_t max_buffer_count_{BufferHubQueue::kMaxQueueCapacity};
+
+ // |max_dequeued_buffer_count_| set the maximum number of buffers that can
+ // be dequeued at the same momment.
+ int32_t max_dequeued_buffer_count_{1};
};
} // namespace dvr
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
index 5bb121a..64034e8 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
@@ -1,7 +1,9 @@
#include <private/dvr/buffer_hub_queue_producer.h>
#include <base/logging.h>
+#include <gui/IProducerListener.h>
#include <gui/Surface.h>
+
#include <gtest/gtest.h>
namespace android {
@@ -9,12 +11,500 @@
namespace {
-class BufferHubQueueProducerTest : public ::testing::Test {};
+// Default dimensions before setDefaultBufferSize is called by the consumer.
+constexpr uint32_t kDefaultWidth = 1;
+constexpr uint32_t kDefaultHeight = 1;
-TEST_F(BufferHubQueueProducerTest, TempTestBufferHubQueueProducer) {
- auto core = BufferHubQueueCore::Create();
- sp<BufferHubQueueProducer> producer = new BufferHubQueueProducer(core);
- sp<Surface> surface = new Surface(producer, true);
+// Default format before setDefaultBufferFormat is called by the consumer.
+constexpr PixelFormat kDefaultFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+constexpr int kDefaultConsumerUsageBits = 0;
+
+// Default transform hint before setTransformHint is called by the consumer.
+constexpr uint32_t kDefaultTransformHint = 0;
+
+constexpr int kTestApi = NATIVE_WINDOW_API_CPU;
+constexpr int kTestApiOther = NATIVE_WINDOW_API_EGL;
+constexpr int kTestApiInvalid = 0xDEADBEEF;
+constexpr int kTestProducerUsageBits = 0;
+constexpr bool kTestControlledByApp = true;
+
+// Builder pattern to slightly vary *almost* correct input
+// -- avoids copying and pasting
+struct QueueBufferInputBuilder {
+ IGraphicBufferProducer::QueueBufferInput build() {
+ return IGraphicBufferProducer::QueueBufferInput(
+ mTimestamp, mIsAutoTimestamp, mDataSpace, mCrop, mScalingMode,
+ mTransform, mFence);
+ }
+
+ QueueBufferInputBuilder& setTimestamp(int64_t timestamp) {
+ this->mTimestamp = timestamp;
+ return *this;
+ }
+
+ QueueBufferInputBuilder& setIsAutoTimestamp(bool isAutoTimestamp) {
+ this->mIsAutoTimestamp = isAutoTimestamp;
+ return *this;
+ }
+
+ QueueBufferInputBuilder& setDataSpace(android_dataspace dataSpace) {
+ this->mDataSpace = dataSpace;
+ return *this;
+ }
+
+ QueueBufferInputBuilder& setCrop(Rect crop) {
+ this->mCrop = crop;
+ return *this;
+ }
+
+ QueueBufferInputBuilder& setScalingMode(int scalingMode) {
+ this->mScalingMode = scalingMode;
+ return *this;
+ }
+
+ QueueBufferInputBuilder& setTransform(uint32_t transform) {
+ this->mTransform = transform;
+ return *this;
+ }
+
+ QueueBufferInputBuilder& setFence(sp<Fence> fence) {
+ this->mFence = fence;
+ return *this;
+ }
+
+ private:
+ int64_t mTimestamp{1384888611};
+ bool mIsAutoTimestamp{false};
+ android_dataspace mDataSpace{HAL_DATASPACE_UNKNOWN};
+ Rect mCrop{Rect(kDefaultWidth, kDefaultHeight)};
+ int mScalingMode{0};
+ uint32_t mTransform{0};
+ sp<Fence> mFence{Fence::NO_FENCE};
+};
+
+// This is a test that covers our implementation of bufferhubqueue-based
+// IGraphicBufferProducer.
+class BufferHubQueueProducerTest : public ::testing::Test {
+ protected:
+ virtual void SetUp() {
+ const ::testing::TestInfo* const testInfo =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ ALOGD_IF(TRACE, "Begin test: %s.%s", testInfo->test_case_name(),
+ testInfo->name());
+
+ auto core = BufferHubQueueCore::Create();
+ mProducer = new BufferHubQueueProducer(core);
+ ASSERT_TRUE(mProducer != nullptr);
+ mSurface = new Surface(mProducer, true);
+ ASSERT_TRUE(mSurface != nullptr);
+ }
+
+ // Connect to a producer in a 'correct' fashion.
+ void ConnectProducer() {
+ IGraphicBufferProducer::QueueBufferOutput output;
+ // Can connect the first time.
+ ASSERT_EQ(NO_ERROR, mProducer->connect(kDummyListener, kTestApi,
+ kTestControlledByApp, &output));
+ }
+
+ // Dequeue a buffer in a 'correct' fashion.
+ // Precondition: Producer is connected.
+ void DequeueBuffer(int* outSlot) {
+ sp<Fence> fence;
+ ASSERT_NO_FATAL_FAILURE(DequeueBuffer(outSlot, &fence));
+ }
+
+ void DequeueBuffer(int* outSlot, sp<Fence>* outFence) {
+ ASSERT_NE(nullptr, outSlot);
+ ASSERT_NE(nullptr, outFence);
+
+ int ret = mProducer->dequeueBuffer(outSlot, outFence, kDefaultWidth,
+ kDefaultHeight, kDefaultFormat,
+ kTestProducerUsageBits, nullptr);
+ // BUFFER_NEEDS_REALLOCATION can be either on or off.
+ ASSERT_EQ(0, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION & ret);
+
+ // Slot number should be in boundary.
+ ASSERT_LE(0, *outSlot);
+ ASSERT_GT(BufferQueueDefs::NUM_BUFFER_SLOTS, *outSlot);
+ }
+
+ // Create a generic "valid" input for queueBuffer
+ // -- uses the default buffer format, width, etc.
+ static IGraphicBufferProducer::QueueBufferInput CreateBufferInput() {
+ return QueueBufferInputBuilder().build();
+ }
+
+ const sp<IProducerListener> kDummyListener{new DummyProducerListener};
+
+ sp<BufferHubQueueProducer> mProducer;
+ sp<Surface> mSurface;
+};
+
+TEST_F(BufferHubQueueProducerTest, ConnectFirst_ReturnsError) {
+ IGraphicBufferProducer::QueueBufferOutput output;
+
+ // NULL output returns BAD_VALUE
+ EXPECT_EQ(BAD_VALUE, mProducer->connect(kDummyListener, kTestApi,
+ kTestControlledByApp, nullptr));
+
+ // Invalid API returns bad value
+ EXPECT_EQ(BAD_VALUE, mProducer->connect(kDummyListener, kTestApiInvalid,
+ kTestControlledByApp, &output));
+}
+
+TEST_F(BufferHubQueueProducerTest, ConnectAgain_ReturnsError) {
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+
+ // Can't connect when there is already a producer connected.
+ IGraphicBufferProducer::QueueBufferOutput output;
+ EXPECT_EQ(BAD_VALUE, mProducer->connect(kDummyListener, kTestApi,
+ kTestControlledByApp, &output));
+}
+
+TEST_F(BufferHubQueueProducerTest, Disconnect_Succeeds) {
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+
+ ASSERT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
+}
+
+TEST_F(BufferHubQueueProducerTest, Disconnect_ReturnsError) {
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+
+ // Must disconnect with same API number
+ EXPECT_EQ(BAD_VALUE, mProducer->disconnect(kTestApiOther));
+ // API must not be out of range
+ EXPECT_EQ(BAD_VALUE, mProducer->disconnect(kTestApiInvalid));
+}
+
+TEST_F(BufferHubQueueProducerTest, Query_Succeeds) {
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+
+ int32_t value = -1;
+ EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_WIDTH, &value));
+ EXPECT_EQ(kDefaultWidth, static_cast<uint32_t>(value));
+
+ EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_HEIGHT, &value));
+ EXPECT_EQ(kDefaultHeight, static_cast<uint32_t>(value));
+
+ EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_FORMAT, &value));
+ EXPECT_EQ(kDefaultFormat, value);
+
+ EXPECT_EQ(NO_ERROR,
+ mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &value));
+ EXPECT_LE(0, value);
+ EXPECT_GE(BufferQueueDefs::NUM_BUFFER_SLOTS, static_cast<size_t>(value));
+
+ EXPECT_EQ(NO_ERROR,
+ mProducer->query(NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value));
+ EXPECT_FALSE(value); // Can't run behind when we haven't touched the queue
+
+ EXPECT_EQ(NO_ERROR,
+ mProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &value));
+ EXPECT_EQ(kDefaultConsumerUsageBits, value);
+}
+
+TEST_F(BufferHubQueueProducerTest, Query_ReturnsError) {
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+
+ // One past the end of the last 'query' enum value. Update this if we add more
+ // enums.
+ const int NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE = NATIVE_WINDOW_BUFFER_AGE + 1;
+
+ int value;
+ // What was out of range
+ EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/ -1, &value));
+ EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/ 0xDEADBEEF, &value));
+ EXPECT_EQ(BAD_VALUE,
+ mProducer->query(NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE, &value));
+
+ // Some enums from window.h are 'invalid'
+ EXPECT_EQ(BAD_VALUE,
+ mProducer->query(NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, &value));
+ EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_CONCRETE_TYPE, &value));
+ EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_WIDTH, &value));
+ EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_HEIGHT, &value));
+ EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_TRANSFORM_HINT, &value));
+
+ // Value was NULL
+ EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_FORMAT, /*value*/ NULL));
+}
+
+TEST_F(BufferHubQueueProducerTest, Queue_Succeeds) {
+ int slot = -1;
+
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+ ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
+
+ // Request the buffer (pre-requisite for queueing)
+ sp<GraphicBuffer> buffer;
+ ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
+
+ // A generic "valid" input
+ IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
+ IGraphicBufferProducer::QueueBufferOutput output;
+
+ // Queue the buffer back into the BQ
+ ASSERT_EQ(NO_ERROR, mProducer->queueBuffer(slot, input, &output));
+
+ EXPECT_EQ(kDefaultWidth, output.width);
+ EXPECT_EQ(kDefaultHeight, output.height);
+ EXPECT_EQ(kDefaultTransformHint, output.transformHint);
+
+ // BufferHubQueue delivers buffers to consumer immediately.
+ EXPECT_EQ(0u, output.numPendingBuffers);
+
+ // Note that BufferHubQueue doesn't support nextFrameNumber as it seems to
+ // be a SurfaceFlinger specific optimization.
+ EXPECT_EQ(0u, output.nextFrameNumber);
+
+ // Buffer was not in the dequeued state
+ EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
+}
+
+// Test invalid slot number
+TEST_F(BufferHubQueueProducerTest, QueueInvalidSlot_ReturnsError) {
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+
+ // A generic "valid" input
+ IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
+ IGraphicBufferProducer::QueueBufferOutput output;
+
+ EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/ -1, input, &output));
+ EXPECT_EQ(BAD_VALUE,
+ mProducer->queueBuffer(/*slot*/ 0xDEADBEEF, input, &output));
+ EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(BufferQueueDefs::NUM_BUFFER_SLOTS,
+ input, &output));
+}
+
+// Slot was not in the dequeued state (all slots start out in Free state)
+TEST_F(BufferHubQueueProducerTest, QueueNotDequeued_ReturnsError) {
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+
+ IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
+ IGraphicBufferProducer::QueueBufferOutput output;
+
+ EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/ 0, input, &output));
+}
+
+// Slot was enqueued without requesting a buffer
+TEST_F(BufferHubQueueProducerTest, QueueNotRequested_ReturnsError) {
+ int slot = -1;
+
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+ ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
+
+ IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
+ IGraphicBufferProducer::QueueBufferOutput output;
+
+ EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
+}
+
+// Test when fence was NULL
+TEST_F(BufferHubQueueProducerTest, QueueNoFence_ReturnsError) {
+ int slot = -1;
+
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+ ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
+
+ sp<GraphicBuffer> buffer;
+ ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
+
+ sp<Fence> nullFence = NULL;
+
+ IGraphicBufferProducer::QueueBufferInput input =
+ QueueBufferInputBuilder().setFence(nullFence).build();
+ IGraphicBufferProducer::QueueBufferOutput output;
+
+ EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
+}
+
+// Test scaling mode was invalid
+TEST_F(BufferHubQueueProducerTest, QueueTestInvalidScalingMode_ReturnsError) {
+ int slot = -1;
+
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+ ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
+
+ sp<GraphicBuffer> buffer;
+ ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
+
+ IGraphicBufferProducer::QueueBufferInput input =
+ QueueBufferInputBuilder().setScalingMode(-1).build();
+ IGraphicBufferProducer::QueueBufferOutput output;
+
+ EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
+
+ input = QueueBufferInputBuilder().setScalingMode(0xDEADBEEF).build();
+
+ EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
+}
+
+// Test crop rect is out of bounds of the buffer dimensions
+TEST_F(BufferHubQueueProducerTest, QueueCropOutOfBounds_ReturnsError) {
+ int slot = -1;
+
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+ ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
+
+ sp<GraphicBuffer> buffer;
+ ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
+
+ IGraphicBufferProducer::QueueBufferInput input =
+ QueueBufferInputBuilder()
+ .setCrop(Rect(kDefaultWidth + 1, kDefaultHeight + 1))
+ .build();
+ IGraphicBufferProducer::QueueBufferOutput output;
+
+ EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
+}
+
+TEST_F(BufferHubQueueProducerTest, CancelBuffer_Succeeds) {
+ int slot = -1;
+ sp<Fence> fence;
+
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+ ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot, &fence));
+
+ // Should be able to cancel buffer after a dequeue.
+ EXPECT_EQ(NO_ERROR, mProducer->cancelBuffer(slot, fence));
+}
+
+TEST_F(BufferHubQueueProducerTest, SetMaxDequeuedBufferCount_Succeeds) {
+ return;
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+
+ int minUndequeuedBuffers;
+ ASSERT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+ &minUndequeuedBuffers));
+
+ const int minBuffers = 1;
+ const int maxBuffers =
+ BufferQueueDefs::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
+
+ ASSERT_EQ(NO_ERROR, mProducer->setAsyncMode(false))
+ << "async mode: " << false;
+ ASSERT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(minBuffers))
+ << "bufferCount: " << minBuffers;
+
+ // Should now be able to dequeue up to minBuffers times
+ // Should now be able to dequeue up to maxBuffers times
+ int slot = -1;
+ for (int i = 0; i < minBuffers; ++i) {
+ ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
+ }
+
+ ASSERT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(maxBuffers));
+
+ // queue the first buffer to enable max dequeued buffer count checking
+ IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
+ IGraphicBufferProducer::QueueBufferOutput output;
+ sp<GraphicBuffer> buffer;
+ ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
+ ASSERT_EQ(NO_ERROR, mProducer->queueBuffer(slot, input, &output));
+
+ sp<Fence> fence;
+ for (int i = 0; i < maxBuffers; ++i) {
+ ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot, &fence));
+ }
+
+ // Cancel a buffer, so we can decrease the buffer count
+ ASSERT_EQ(NO_ERROR, mProducer->cancelBuffer(slot, fence));
+
+ // Should now be able to decrease the max dequeued count by 1
+ ASSERT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(maxBuffers - 1));
+}
+
+TEST_F(BufferHubQueueProducerTest, SetMaxDequeuedBufferCount_Fails) {
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+
+ int minUndequeuedBuffers;
+ ASSERT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+ &minUndequeuedBuffers));
+
+ const int minBuffers = 1;
+ const int maxBuffers =
+ BufferQueueDefs::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
+
+ ASSERT_EQ(NO_ERROR, mProducer->setAsyncMode(false))
+ << "async mode: " << false;
+ // Buffer count was out of range
+ EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(0))
+ << "bufferCount: " << 0;
+ EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(maxBuffers + 1))
+ << "bufferCount: " << maxBuffers + 1;
+
+ // Set max dequeue count to 2
+ ASSERT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(2));
+ // Dequeue 2 buffers
+ int slot = -1;
+ sp<Fence> fence;
+ for (int i = 0; i < 2; i++) {
+ ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+ (mProducer->dequeueBuffer(
+ &slot, &fence, kDefaultWidth, kDefaultHeight,
+ kDefaultFormat, kTestProducerUsageBits, nullptr)))
+ << "slot: " << slot;
+ }
+
+ // Client has too many buffers dequeued
+ EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(1))
+ << "bufferCount: " << minBuffers;
+}
+
+TEST_F(BufferHubQueueProducerTest,
+ DisconnectedProducerReturnsError_dequeueBuffer) {
+ int slot = -1;
+ sp<Fence> fence;
+
+ ASSERT_EQ(NO_INIT, mProducer->dequeueBuffer(&slot, &fence, kDefaultWidth,
+ kDefaultHeight, kDefaultFormat,
+ kTestProducerUsageBits, nullptr));
+}
+
+TEST_F(BufferHubQueueProducerTest,
+ DisconnectedProducerReturnsError_requestBuffer) {
+ int slot = -1;
+ sp<GraphicBuffer> buffer;
+
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+ ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
+
+ // Shouldn't be able to request buffer after disconnect.
+ ASSERT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
+ ASSERT_EQ(NO_INIT, mProducer->requestBuffer(slot, &buffer));
+}
+
+TEST_F(BufferHubQueueProducerTest,
+ DisconnectedProducerReturnsError_queueBuffer) {
+ int slot = -1;
+ sp<GraphicBuffer> buffer;
+
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+ ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
+ ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
+
+ // A generic "valid" input
+ IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
+ IGraphicBufferProducer::QueueBufferOutput output;
+
+ // Shouldn't be able to queue buffer after disconnect.
+ ASSERT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
+ ASSERT_EQ(NO_INIT, mProducer->queueBuffer(slot, input, &output));
+}
+
+TEST_F(BufferHubQueueProducerTest,
+ DisconnectedProducerReturnsError_cancelBuffer) {
+ int slot = -1;
+ sp<GraphicBuffer> buffer;
+
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+ ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
+ ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
+
+ // Shouldn't be able to cancel buffer after disconnect.
+ ASSERT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
+ ASSERT_EQ(NO_INIT, mProducer->cancelBuffer(slot, Fence::NO_FENCE));
}
} // namespace
diff --git a/libs/vr/libpdx/client.cpp b/libs/vr/libpdx/client.cpp
index c318628..bfa2d87 100644
--- a/libs/vr/libpdx/client.cpp
+++ b/libs/vr/libpdx/client.cpp
@@ -4,7 +4,6 @@
#include <log/log.h>
#include <pdx/trace.h>
-#include "errno_guard.h"
namespace android {
namespace pdx {
@@ -84,7 +83,6 @@
Status<void> Client::SendImpulse(int opcode) {
PDX_TRACE_NAME("Client::SendImpulse");
- ErrnoGuard errno_guard;
auto status = CheckReconnect();
if (!status)
@@ -98,7 +96,6 @@
Status<void> Client::SendImpulse(int opcode, const void* buffer,
size_t length) {
PDX_TRACE_NAME("Client::SendImpulse");
- ErrnoGuard errno_guard;
auto status = CheckReconnect();
if (!status)
@@ -110,7 +107,6 @@
}
void Client::Close(int error) {
- ErrnoGuard errno_guard;
channel_.reset();
// Normalize error codes to negative integer space.
error_ = error <= 0 ? error : -error;
@@ -228,37 +224,38 @@
CheckDisconnect(*ret);
}
-FileReference Transaction::PushFileHandle(const LocalHandle& handle) {
- return client_.CheckReconnect() && EnsureStateAllocated()
- ? client_.GetChannel()->PushFileHandle(state_, handle)
- : -1;
+Status<FileReference> Transaction::PushFileHandle(const LocalHandle& handle) {
+ if (client_.CheckReconnect() && EnsureStateAllocated())
+ return client_.GetChannel()->PushFileHandle(state_, handle);
+ return ErrorStatus{ESHUTDOWN};
}
-FileReference Transaction::PushFileHandle(const BorrowedHandle& handle) {
- return client_.CheckReconnect() && EnsureStateAllocated()
- ? client_.GetChannel()->PushFileHandle(state_, handle)
- : -1;
+Status<FileReference> Transaction::PushFileHandle(
+ const BorrowedHandle& handle) {
+ if (client_.CheckReconnect() && EnsureStateAllocated())
+ return client_.GetChannel()->PushFileHandle(state_, handle);
+ return ErrorStatus{ESHUTDOWN};
}
-FileReference Transaction::PushFileHandle(const RemoteHandle& handle) {
+Status<FileReference> Transaction::PushFileHandle(const RemoteHandle& handle) {
return handle.Get();
}
-ChannelReference Transaction::PushChannelHandle(
+Status<ChannelReference> Transaction::PushChannelHandle(
const LocalChannelHandle& handle) {
- return client_.CheckReconnect() && EnsureStateAllocated()
- ? client_.GetChannel()->PushChannelHandle(state_, handle)
- : -1;
+ if (client_.CheckReconnect() && EnsureStateAllocated())
+ return client_.GetChannel()->PushChannelHandle(state_, handle);
+ return ErrorStatus{ESHUTDOWN};
}
-ChannelReference Transaction::PushChannelHandle(
+Status<ChannelReference> Transaction::PushChannelHandle(
const BorrowedChannelHandle& handle) {
- return client_.CheckReconnect() && EnsureStateAllocated()
- ? client_.GetChannel()->PushChannelHandle(state_, handle)
- : -1;
+ if (client_.CheckReconnect() && EnsureStateAllocated())
+ return client_.GetChannel()->PushChannelHandle(state_, handle);
+ return ErrorStatus{ESHUTDOWN};
}
-ChannelReference Transaction::PushChannelHandle(
+Status<ChannelReference> Transaction::PushChannelHandle(
const RemoteChannelHandle& handle) {
return handle.value();
}
diff --git a/libs/vr/libpdx/client_tests.cpp b/libs/vr/libpdx/client_tests.cpp
index f1fb6d1..99ccc69 100644
--- a/libs/vr/libpdx/client_tests.cpp
+++ b/libs/vr/libpdx/client_tests.cpp
@@ -518,28 +518,29 @@
EXPECT_CALL(*mock_channel(),
PushFileHandle(kTransactionState, A<const LocalHandle&>()))
.WillOnce(Return(1));
- EXPECT_EQ(1, transaction_.PushFileHandle(LocalHandle{-1}));
+ EXPECT_EQ(1, transaction_.PushFileHandle(LocalHandle{-1}).get());
EXPECT_CALL(*mock_channel(),
PushFileHandle(kTransactionState, A<const BorrowedHandle&>()))
.WillOnce(Return(2));
- EXPECT_EQ(2, transaction_.PushFileHandle(BorrowedHandle{-1}));
+ EXPECT_EQ(2, transaction_.PushFileHandle(BorrowedHandle{-1}).get());
- EXPECT_EQ(3, transaction_.PushFileHandle(RemoteHandle{3}));
+ EXPECT_EQ(3, transaction_.PushFileHandle(RemoteHandle{3}).get());
EXPECT_CALL(
*mock_channel(),
PushChannelHandle(kTransactionState, A<const LocalChannelHandle&>()))
.WillOnce(Return(11));
- EXPECT_EQ(11, transaction_.PushChannelHandle(LocalChannelHandle{nullptr, 1}));
+ EXPECT_EQ(
+ 11, transaction_.PushChannelHandle(LocalChannelHandle{nullptr, 1}).get());
EXPECT_CALL(
*mock_channel(),
PushChannelHandle(kTransactionState, A<const BorrowedChannelHandle&>()))
.WillOnce(Return(12));
- EXPECT_EQ(12, transaction_.PushChannelHandle(BorrowedChannelHandle{2}));
+ EXPECT_EQ(12, transaction_.PushChannelHandle(BorrowedChannelHandle{2}).get());
- EXPECT_EQ(13, transaction_.PushChannelHandle(RemoteChannelHandle{13}));
+ EXPECT_EQ(13, transaction_.PushChannelHandle(RemoteChannelHandle{13}).get());
}
TEST_F(ClientTransactionTest, GetHandle) {
diff --git a/libs/vr/libpdx/errno_guard.h b/libs/vr/libpdx/errno_guard.h
deleted file mode 100644
index fc7dfdf..0000000
--- a/libs/vr/libpdx/errno_guard.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef ANDROID_PDX_ERRNO_GUARD_H_
-#define ANDROID_PDX_ERRNO_GUARD_H_
-
-#include <errno.h>
-
-namespace android {
-namespace pdx {
-
-// Automatically saves and restores the system errno for API implementations to
-// prevent internal use errno from affecting API callers.
-class ErrnoGuard {
- public:
- ErrnoGuard() : saved_errno_(errno) {}
- ~ErrnoGuard() { errno = saved_errno_; }
-
- int saved_errno() const { return saved_errno_; }
-
- private:
- int saved_errno_;
-
- ErrnoGuard(const ErrnoGuard&) = delete;
- void operator=(const ErrnoGuard&) = delete;
-};
-
-// Checks |return_code| and returns either it or the negated system errno based
-// on the return code value.
-inline int ReturnCodeOrError(int return_code) {
- return return_code < 0 ? -errno : return_code;
-}
-
-} // namespace pdx
-} // namespace android
-
-#endif // ANDROID_PDX_ERRNO_GUARD_H_
diff --git a/libs/vr/libpdx/private/pdx/client.h b/libs/vr/libpdx/private/pdx/client.h
index a590087..656de7e 100644
--- a/libs/vr/libpdx/private/pdx/client.h
+++ b/libs/vr/libpdx/private/pdx/client.h
@@ -253,13 +253,14 @@
}
// OutputResourceMapper
- FileReference PushFileHandle(const LocalHandle& handle) override;
- FileReference PushFileHandle(const BorrowedHandle& handle) override;
- FileReference PushFileHandle(const RemoteHandle& handle) override;
- ChannelReference PushChannelHandle(const LocalChannelHandle& handle) override;
- ChannelReference PushChannelHandle(
+ Status<FileReference> PushFileHandle(const LocalHandle& handle) override;
+ Status<FileReference> PushFileHandle(const BorrowedHandle& handle) override;
+ Status<FileReference> PushFileHandle(const RemoteHandle& handle) override;
+ Status<ChannelReference> PushChannelHandle(
+ const LocalChannelHandle& handle) override;
+ Status<ChannelReference> PushChannelHandle(
const BorrowedChannelHandle& handle) override;
- ChannelReference PushChannelHandle(
+ Status<ChannelReference> PushChannelHandle(
const RemoteChannelHandle& handle) override;
// InputResourceMapper
diff --git a/libs/vr/libpdx/private/pdx/message_writer.h b/libs/vr/libpdx/private/pdx/message_writer.h
index 0cb6e40..4a101d6 100644
--- a/libs/vr/libpdx/private/pdx/message_writer.h
+++ b/libs/vr/libpdx/private/pdx/message_writer.h
@@ -3,20 +3,22 @@
#include <pdx/channel_handle.h>
#include <pdx/file_handle.h>
+#include <pdx/status.h>
namespace android {
namespace pdx {
class OutputResourceMapper {
public:
- virtual FileReference PushFileHandle(const LocalHandle& handle) = 0;
- virtual FileReference PushFileHandle(const BorrowedHandle& handle) = 0;
- virtual FileReference PushFileHandle(const RemoteHandle& handle) = 0;
- virtual ChannelReference PushChannelHandle(
+ virtual Status<FileReference> PushFileHandle(const LocalHandle& handle) = 0;
+ virtual Status<FileReference> PushFileHandle(
+ const BorrowedHandle& handle) = 0;
+ virtual Status<FileReference> PushFileHandle(const RemoteHandle& handle) = 0;
+ virtual Status<ChannelReference> PushChannelHandle(
const LocalChannelHandle& handle) = 0;
- virtual ChannelReference PushChannelHandle(
+ virtual Status<ChannelReference> PushChannelHandle(
const BorrowedChannelHandle& handle) = 0;
- virtual ChannelReference PushChannelHandle(
+ virtual Status<ChannelReference> PushChannelHandle(
const RemoteChannelHandle& handle) = 0;
protected:
diff --git a/libs/vr/libpdx/private/pdx/mock_message_writer.h b/libs/vr/libpdx/private/pdx/mock_message_writer.h
index 3c513d7..e06e5bb 100644
--- a/libs/vr/libpdx/private/pdx/mock_message_writer.h
+++ b/libs/vr/libpdx/private/pdx/mock_message_writer.h
@@ -9,15 +9,18 @@
class MockOutputResourceMapper : public OutputResourceMapper {
public:
- MOCK_METHOD1(PushFileHandle, FileReference(const LocalHandle& handle));
- MOCK_METHOD1(PushFileHandle, FileReference(const BorrowedHandle& handle));
- MOCK_METHOD1(PushFileHandle, FileReference(const RemoteHandle& handle));
+ MOCK_METHOD1(PushFileHandle,
+ Status<FileReference>(const LocalHandle& handle));
+ MOCK_METHOD1(PushFileHandle,
+ Status<FileReference>(const BorrowedHandle& handle));
+ MOCK_METHOD1(PushFileHandle,
+ Status<FileReference>(const RemoteHandle& handle));
MOCK_METHOD1(PushChannelHandle,
- ChannelReference(const LocalChannelHandle& handle));
+ Status<ChannelReference>(const LocalChannelHandle& handle));
MOCK_METHOD1(PushChannelHandle,
- ChannelReference(const BorrowedChannelHandle& handle));
+ Status<ChannelReference>(const BorrowedChannelHandle& handle));
MOCK_METHOD1(PushChannelHandle,
- ChannelReference(const RemoteChannelHandle& handle));
+ Status<ChannelReference>(const RemoteChannelHandle& handle));
};
class MockMessageWriter : public MessageWriter {
diff --git a/libs/vr/libpdx/private/pdx/mock_service_endpoint.h b/libs/vr/libpdx/private/pdx/mock_service_endpoint.h
index ead74d5..e741d4a 100644
--- a/libs/vr/libpdx/private/pdx/mock_service_endpoint.h
+++ b/libs/vr/libpdx/private/pdx/mock_service_endpoint.h
@@ -10,46 +10,54 @@
class MockEndpoint : public Endpoint {
public:
MOCK_CONST_METHOD0(GetIpcTag, uint32_t());
- MOCK_METHOD1(SetService, int(Service* service));
- MOCK_METHOD2(SetChannel, int(int channel_id, Channel* channel));
- MOCK_METHOD1(CloseChannel, int(int channel_id));
+ MOCK_METHOD1(SetService, Status<void>(Service* service));
+ MOCK_METHOD2(SetChannel, Status<void>(int channel_id, Channel* channel));
+ MOCK_METHOD1(CloseChannel, Status<void>(int channel_id));
MOCK_METHOD3(ModifyChannelEvents,
- int(int channel_id, int clear_mask, int set_mask));
+ Status<void>(int channel_id, int clear_mask, int set_mask));
MOCK_METHOD4(PushChannel,
Status<RemoteChannelHandle>(Message* message, int flags,
Channel* channel, int* channel_id));
MOCK_METHOD3(CheckChannel,
Status<int>(const Message* message, ChannelReference ref,
Channel** channel));
- MOCK_METHOD1(DefaultHandleMessage, int(const MessageInfo& info));
- MOCK_METHOD1(MessageReceive, int(Message* message));
- MOCK_METHOD2(MessageReply, int(Message* message, int return_code));
- MOCK_METHOD2(MessageReplyFd, int(Message* message, unsigned int push_fd));
+ MOCK_METHOD1(MessageReceive, Status<void>(Message* message));
+ MOCK_METHOD2(MessageReply, Status<void>(Message* message, int return_code));
+ MOCK_METHOD2(MessageReplyFd,
+ Status<void>(Message* message, unsigned int push_fd));
MOCK_METHOD2(MessageReplyChannelHandle,
- int(Message* message, const LocalChannelHandle& handle));
+ Status<void>(Message* message,
+ const LocalChannelHandle& handle));
MOCK_METHOD2(MessageReplyChannelHandle,
- int(Message* message, const BorrowedChannelHandle& handle));
+ Status<void>(Message* message,
+ const BorrowedChannelHandle& handle));
MOCK_METHOD2(MessageReplyChannelHandle,
- int(Message* message, const RemoteChannelHandle& handle));
- MOCK_METHOD3(ReadMessageData, ssize_t(Message* message, const iovec* vector,
- size_t vector_length));
- MOCK_METHOD3(WriteMessageData, ssize_t(Message* message, const iovec* vector,
- size_t vector_length));
+ Status<void>(Message* message,
+ const RemoteChannelHandle& handle));
+ MOCK_METHOD3(ReadMessageData,
+ Status<size_t>(Message* message, const iovec* vector,
+ size_t vector_length));
+ MOCK_METHOD3(WriteMessageData,
+ Status<size_t>(Message* message, const iovec* vector,
+ size_t vector_length));
MOCK_METHOD2(PushFileHandle,
- FileReference(Message* message, const LocalHandle& handle));
+ Status<FileReference>(Message* message,
+ const LocalHandle& handle));
MOCK_METHOD2(PushFileHandle,
- FileReference(Message* message, const BorrowedHandle& handle));
+ Status<FileReference>(Message* message,
+ const BorrowedHandle& handle));
MOCK_METHOD2(PushFileHandle,
- FileReference(Message* message, const RemoteHandle& handle));
+ Status<FileReference>(Message* message,
+ const RemoteHandle& handle));
MOCK_METHOD2(PushChannelHandle,
- ChannelReference(Message* message,
- const LocalChannelHandle& handle));
+ Status<ChannelReference>(Message* message,
+ const LocalChannelHandle& handle));
MOCK_METHOD2(PushChannelHandle,
- ChannelReference(Message* message,
- const BorrowedChannelHandle& handle));
+ Status<ChannelReference>(Message* message,
+ const BorrowedChannelHandle& handle));
MOCK_METHOD2(PushChannelHandle,
- ChannelReference(Message* message,
- const RemoteChannelHandle& handle));
+ Status<ChannelReference>(Message* message,
+ const RemoteChannelHandle& handle));
MOCK_CONST_METHOD2(GetFileHandle,
LocalHandle(Message* message, FileReference ref));
MOCK_CONST_METHOD2(GetChannelHandle,
@@ -57,7 +65,7 @@
ChannelReference ref));
MOCK_METHOD0(AllocateMessageState, void*());
MOCK_METHOD1(FreeMessageState, void(void* state));
- MOCK_METHOD0(Cancel, int());
+ MOCK_METHOD0(Cancel, Status<void>());
};
} // namespace pdx
diff --git a/libs/vr/libpdx/private/pdx/rpc/remote_method.h b/libs/vr/libpdx/private/pdx/rpc/remote_method.h
index 3eca9e5..505c63b 100644
--- a/libs/vr/libpdx/private/pdx/rpc/remote_method.h
+++ b/libs/vr/libpdx/private/pdx/rpc/remote_method.h
@@ -121,9 +121,9 @@
// either during dispatch of the remote method handler or at a later time if the
// message is moved for delayed response.
inline void RemoteMethodError(Message& message, int error_code) {
- const int ret = message.ReplyError(error_code);
- ALOGE_IF(ret < 0, "RemoteMethodError: Failed to reply to message: %s",
- strerror(-ret));
+ const auto status = message.ReplyError(error_code);
+ ALOGE_IF(!status, "RemoteMethodError: Failed to reply to message: %s",
+ status.GetErrorMessage().c_str());
}
// Returns a value from a remote method to the client. The usual method to
@@ -135,9 +135,9 @@
template <typename RemoteMethodType, typename Return>
EnableIfDirectReturn<typename RemoteMethodType::Return> RemoteMethodReturn(
Message& message, const Return& return_value) {
- const int ret = message.Reply(return_value);
- ALOGE_IF(ret < 0, "RemoteMethodReturn: Failed to reply to message: %s",
- strerror(-ret));
+ const auto status = message.Reply(return_value);
+ ALOGE_IF(!status, "RemoteMethodReturn: Failed to reply to message: %s",
+ status.GetErrorMessage().c_str());
}
// Overload for non-direct return types.
@@ -148,14 +148,10 @@
rpc::ServicePayload<ReplyBuffer> payload(message);
MakeArgumentEncoder<Signature>(&payload).EncodeReturn(return_value);
- int ret;
- auto size = message.Write(payload.Data(), payload.Size());
- if (size < static_cast<decltype(size)>(payload.Size()))
- ret = message.ReplyError(EIO);
- else
- ret = message.Reply(0);
- ALOGE_IF(ret < 0, "RemoteMethodReturn: Failed to reply to message: %s",
- strerror(-ret));
+ auto ret = message.WriteAll(payload.Data(), payload.Size());
+ auto status = message.Reply(ret);
+ ALOGE_IF(!status, "RemoteMethodReturn: Failed to reply to message: %s",
+ status.GetErrorMessage().c_str());
}
// Overload for Status<void> return types.
@@ -189,13 +185,13 @@
rpc::ServicePayload<ReceiveBuffer> payload(message);
payload.Resize(max_capacity);
- auto size = message.Read(payload.Data(), payload.Size());
- if (size < 0) {
- RemoteMethodError(message, -size);
+ Status<size_t> read_status = message.Read(payload.Data(), payload.Size());
+ if (!read_status) {
+ RemoteMethodError(message, read_status.error());
return;
}
- payload.Resize(size);
+ payload.Resize(read_status.get());
ErrorType error;
auto decoder = MakeArgumentDecoder<Signature>(&payload);
@@ -225,13 +221,13 @@
rpc::ServicePayload<ReceiveBuffer> payload(message);
payload.Resize(max_capacity);
- auto size = message.Read(payload.Data(), payload.Size());
- if (size < 0) {
- RemoteMethodError(message, -size);
+ Status<size_t> read_status = message.Read(payload.Data(), payload.Size());
+ if (!read_status) {
+ RemoteMethodError(message, read_status.error());
return;
}
- payload.Resize(size);
+ payload.Resize(read_status.get());
ErrorType error;
auto decoder = MakeArgumentDecoder<Signature>(&payload);
@@ -265,13 +261,13 @@
rpc::ServicePayload<ReceiveBuffer> payload(message);
payload.Resize(max_capacity);
- auto size = message.Read(payload.Data(), payload.Size());
- if (size < 0) {
- RemoteMethodError(message, -size);
+ Status<size_t> read_status = message.Read(payload.Data(), payload.Size());
+ if (!read_status) {
+ RemoteMethodError(message, read_status.error());
return;
}
- payload.Resize(size);
+ payload.Resize(read_status.get());
ErrorType error;
auto decoder = MakeArgumentDecoder<Signature>(&payload);
diff --git a/libs/vr/libpdx/private/pdx/rpc/serialization.h b/libs/vr/libpdx/private/pdx/rpc/serialization.h
index fccd028..9a012ed 100644
--- a/libs/vr/libpdx/private/pdx/rpc/serialization.h
+++ b/libs/vr/libpdx/private/pdx/rpc/serialization.h
@@ -905,8 +905,9 @@
inline void SerializeObject(const FileHandle<Mode>& fd, MessageWriter* writer,
void*& buffer) {
SerializeType(fd, buffer);
- const FileReference value =
+ const Status<FileReference> status =
writer->GetOutputResourceMapper()->PushFileHandle(fd);
+ FileReference value = status ? status.get() : -status.error();
SerializeRaw(value, buffer);
}
@@ -915,8 +916,9 @@
inline void SerializeObject(const ChannelHandle<Mode>& handle,
MessageWriter* writer, void*& buffer) {
SerializeType(handle, buffer);
- const ChannelReference value =
+ const Status<ChannelReference> status =
writer->GetOutputResourceMapper()->PushChannelHandle(handle);
+ ChannelReference value = status ? status.get() : -status.error();
SerializeRaw(value, buffer);
}
diff --git a/libs/vr/libpdx/private/pdx/service.h b/libs/vr/libpdx/private/pdx/service.h
index 175cedf..0d30614 100644
--- a/libs/vr/libpdx/private/pdx/service.h
+++ b/libs/vr/libpdx/private/pdx/service.h
@@ -98,29 +98,62 @@
/*
* Read/write payload, in either single buffer or iovec form.
*/
- ssize_t ReadVector(const iovec* vector, size_t vector_length);
- ssize_t Read(void* buffer, size_t length);
- ssize_t WriteVector(const iovec* vector, size_t vector_length);
- ssize_t Write(const void* buffer, size_t length);
+ Status<size_t> ReadVector(const iovec* vector, size_t vector_length);
+ Status<size_t> Read(void* buffer, size_t length);
+ Status<size_t> WriteVector(const iovec* vector, size_t vector_length);
+ Status<size_t> Write(const void* buffer, size_t length);
template <size_t N>
- inline ssize_t ReadVector(const iovec (&vector)[N]) {
+ inline Status<size_t> ReadVector(const iovec (&vector)[N]) {
return ReadVector(vector, N);
}
template <size_t N>
- inline ssize_t WriteVector(const iovec (&vector)[N]) {
+ inline Status<size_t> WriteVector(const iovec (&vector)[N]) {
return WriteVector(vector, N);
}
+ // Helper functions to read/write all requested bytes, and return EIO if not
+ // all were read/written.
+ Status<void> ReadVectorAll(const iovec* vector, size_t vector_length);
+ Status<void> WriteVectorAll(const iovec* vector, size_t vector_length);
+
+ inline Status<void> ReadAll(void* buffer, size_t length) {
+ Status<size_t> status = Read(buffer, length);
+ if (status && status.get() < length)
+ status.SetError(EIO);
+ Status<void> ret;
+ ret.PropagateError(status);
+ return ret;
+ }
+ inline Status<void> WriteAll(const void* buffer, size_t length) {
+ Status<size_t> status = Write(buffer, length);
+ if (status && status.get() < length)
+ status.SetError(EIO);
+ Status<void> ret;
+ ret.PropagateError(status);
+ return ret;
+ }
+
+ template <size_t N>
+ inline Status<void> ReadVectorAll(const iovec (&vector)[N]) {
+ return ReadVectorAll(vector, N);
+ }
+
+ template <size_t N>
+ inline Status<void> WriteVectorAll(const iovec (&vector)[N]) {
+ return WriteVectorAll(vector, N);
+ }
+
// OutputResourceMapper
- FileReference PushFileHandle(const LocalHandle& handle) override;
- FileReference PushFileHandle(const BorrowedHandle& handle) override;
- FileReference PushFileHandle(const RemoteHandle& handle) override;
- ChannelReference PushChannelHandle(const LocalChannelHandle& handle) override;
- ChannelReference PushChannelHandle(
+ Status<FileReference> PushFileHandle(const LocalHandle& handle) override;
+ Status<FileReference> PushFileHandle(const BorrowedHandle& handle) override;
+ Status<FileReference> PushFileHandle(const RemoteHandle& handle) override;
+ Status<ChannelReference> PushChannelHandle(
+ const LocalChannelHandle& handle) override;
+ Status<ChannelReference> PushChannelHandle(
const BorrowedChannelHandle& handle) override;
- ChannelReference PushChannelHandle(
+ Status<ChannelReference> PushChannelHandle(
const RemoteChannelHandle& handle) override;
// InputResourceMapper
@@ -131,25 +164,29 @@
/*
* Various ways to reply to a message.
*/
- int Reply(int return_code);
- int ReplyError(unsigned error);
- int ReplyFileDescriptor(unsigned int fd);
- int Reply(const LocalHandle& handle);
- int Reply(const BorrowedHandle& handle);
- int Reply(const RemoteHandle& handle);
- int Reply(const LocalChannelHandle& handle);
- int Reply(const BorrowedChannelHandle& handle);
- int Reply(const RemoteChannelHandle& handle);
+ Status<void> Reply(int return_code);
+ Status<void> ReplyError(unsigned int error);
+ Status<void> ReplyFileDescriptor(unsigned int fd);
+ Status<void> Reply(const LocalHandle& handle);
+ Status<void> Reply(const BorrowedHandle& handle);
+ Status<void> Reply(const RemoteHandle& handle);
+ Status<void> Reply(const LocalChannelHandle& handle);
+ Status<void> Reply(const BorrowedChannelHandle& handle);
+ Status<void> Reply(const RemoteChannelHandle& handle);
template <typename T>
- inline int Reply(const Status<T>& status) {
+ inline Status<void> Reply(const Status<T>& status) {
return status ? Reply(status.get()) : ReplyError(status.error());
}
+ inline Status<void> Reply(const Status<void>& status) {
+ return status ? Reply(0) : ReplyError(status.error());
+ }
+
/*
* Update the channel event bits with the given clear and set masks.
*/
- int ModifyChannelEvents(int clear_mask, int set_mask);
+ Status<void> ModifyChannelEvents(int clear_mask, int set_mask);
/*
* Create a new channel and push it as a file descriptor to the client. See
@@ -264,7 +301,7 @@
* these in multi-threaded services.
*/
std::shared_ptr<Channel> GetChannel() const;
- void SetChannel(const std::shared_ptr<Channel>& channnel);
+ Status<void> SetChannel(const std::shared_ptr<Channel>& channnel);
/*
* Get the Channel object for the channel associated with this message,
@@ -355,7 +392,8 @@
* the Channel object until the channel is closed or another call replaces
* the current value.
*/
- int SetChannel(int channel_id, const std::shared_ptr<Channel>& channel);
+ Status<void> SetChannel(int channel_id,
+ const std::shared_ptr<Channel>& channel);
/*
* Get the channel context for the given channel id. This method should be
@@ -404,7 +442,7 @@
*
* OnChannelClosed is not called in response to this method call.
*/
- int CloseChannel(int channel_id);
+ Status<void> CloseChannel(int channel_id);
/*
* Update the event bits for the given channel (given by id), using the
@@ -413,7 +451,8 @@
* This is useful for asynchronously signaling events that clients may be
* waiting for using select/poll/epoll.
*/
- int ModifyChannelEvents(int channel_id, int clear_mask, int set_mask);
+ Status<void> ModifyChannelEvents(int channel_id, int clear_mask,
+ int set_mask);
/*
* Create a new channel and push it as a file descriptor to the process
@@ -478,7 +517,7 @@
* The default implementation simply calls defaultHandleMessage().
* Subclasses should call the same for any unrecognized message opcodes.
*/
- virtual int HandleMessage(Message& message);
+ virtual Status<void> HandleMessage(Message& message);
/*
* Handle an asynchronous message. Subclasses override this to receive
@@ -496,9 +535,9 @@
* Provides default handling of CHANNEL_OPEN and CHANNEL_CLOSE, calling
* OnChannelOpen() and OnChannelClose(), respectively.
*
- * For all other message opcodes, this method replies with -ENOTSUP.
+ * For all other message opcodes, this method replies with ENOTSUP.
*/
- int DefaultHandleMessage(Message& message);
+ Status<void> DefaultHandleMessage(Message& message);
/*
* Called when system properties have changed. Subclasses should implement
@@ -515,7 +554,7 @@
* Cancels the endpoint, unblocking any receiver threads waiting in
* ReceiveAndDispatch().
*/
- int Cancel();
+ Status<void> Cancel();
/*
* Iterator type for Channel map iterators.
@@ -564,14 +603,14 @@
* If the endpoint is in blocking mode this call blocks until a message is
* received, a signal is delivered to this thread, or the service is canceled.
* If the endpoint is in non-blocking mode and a message is not pending this
- * call returns immediately with -ETIMEDOUT.
+ * call returns immediately with ETIMEDOUT.
*/
- int ReceiveAndDispatch();
+ Status<void> ReceiveAndDispatch();
private:
friend class Message;
- bool HandleSystemMessage(Message& message);
+ Status<void> HandleSystemMessage(Message& message);
Service(const Service&);
void operator=(const Service&) = delete;
@@ -639,28 +678,28 @@
#define REPLY_ERROR(message, error, error_label) \
do { \
- int __ret = message.ReplyError(error); \
- CHECK_ERROR(__ret < 0, error_label, \
+ auto __status = message.ReplyError(error); \
+ CHECK_ERROR(!__status, error_label, \
PDX_ERROR_PREFIX " Failed to reply to message because: %s\n", \
- strerror(-__ret)); \
+ __status.GetErrorMessage().c_str()); \
goto error_label; \
} while (0)
#define REPLY_ERROR_RETURN(message, error, ...) \
do { \
- int __ret = message.ReplyError(error); \
- ALOGE_IF(__ret < 0, \
+ auto __status = message.ReplyError(error); \
+ ALOGE_IF(!__status, \
PDX_ERROR_PREFIX " Failed to reply to message because: %s", \
- strerror(-__ret)); \
+ __status.GetErrorMessage().c_str()); \
return __VA_ARGS__; \
} while (0)
#define REPLY_MESSAGE(message, message_return_code, error_label) \
do { \
- int __ret = message.Reply(message_return_code); \
- CHECK_ERROR(__ret < 0, error_label, \
+ auto __status = message.Reply(message_return_code); \
+ CHECK_ERROR(!__status, error_label, \
PDX_ERROR_PREFIX " Failed to reply to message because: %s\n", \
- strerror(-__ret)); \
+ __status.GetErrorMessage().c_str()); \
goto error_label; \
} while (0)
@@ -669,10 +708,10 @@
#define REPLY_MESSAGE_RETURN(message, message_return_code, ...) \
do { \
- int __ret = message.Reply(message_return_code); \
- ALOGE_IF(__ret < 0, \
+ auto __status = message.Reply(message_return_code); \
+ ALOGE_IF(!__status, \
PDX_ERROR_PREFIX " Failed to reply to message because: %s", \
- strerror(-__ret)); \
+ __status.GetErrorMessage().c_str()); \
return __VA_ARGS__; \
} while (0)
@@ -681,19 +720,19 @@
#define REPLY_FD(message, push_fd, error_label) \
do { \
- int __ret = message.ReplyFileDescriptor(push_fd); \
- CHECK_ERROR(__ret < 0, error_label, \
+ auto __status = message.ReplyFileDescriptor(push_fd); \
+ CHECK_ERROR(!__status, error_label, \
PDX_ERROR_PREFIX " Failed to reply to message because: %s\n", \
- strerror(-__ret)); \
+ __status.GetErrorMessage().c_str()); \
goto error_label; \
} while (0)
#define REPLY_FD_RETURN(message, push_fd, ...) \
do { \
- int __ret = message.ReplyFileDescriptor(push_fd); \
- ALOGE_IF(__ret < 0, \
+ auto __status = message.ReplyFileDescriptor(push_fd); \
+ ALOGE_IF(__status < 0, \
PDX_ERROR_PREFIX " Failed to reply to message because: %s", \
- strerror(-__ret)); \
+ __status.GetErrorMessage().c_str()); \
return __VA_ARGS__; \
} while (0)
diff --git a/libs/vr/libpdx/private/pdx/service_endpoint.h b/libs/vr/libpdx/private/pdx/service_endpoint.h
index 613be7c..28bd6bc 100644
--- a/libs/vr/libpdx/private/pdx/service_endpoint.h
+++ b/libs/vr/libpdx/private/pdx/service_endpoint.h
@@ -44,20 +44,20 @@
// Associates a Service instance with an endpoint by setting the service
// context pointer to the address of the Service. Only one Service may be
// associated with a given endpoint.
- virtual int SetService(Service* service) = 0;
+ virtual Status<void> SetService(Service* service) = 0;
// Set the channel context for the given channel.
- virtual int SetChannel(int channel_id, Channel* channel) = 0;
+ virtual Status<void> SetChannel(int channel_id, Channel* channel) = 0;
// Close a channel, signaling the client file object and freeing the channel
// id. Once closed, the client side of the channel always returns the error
// ESHUTDOWN and signals the poll/epoll events POLLHUP and POLLFREE.
- virtual int CloseChannel(int channel_id) = 0;
+ virtual Status<void> CloseChannel(int channel_id) = 0;
// Update the event bits for the given channel (given by id), using the
// given clear and set masks.
- virtual int ModifyChannelEvents(int channel_id, int clear_mask,
- int set_mask) = 0;
+ virtual Status<void> ModifyChannelEvents(int channel_id, int clear_mask,
+ int set_mask) = 0;
// Create a new channel and push it as a file descriptor to the process
// sending the |message|. |flags| may be set to O_NONBLOCK and/or
@@ -77,54 +77,49 @@
virtual Status<int> CheckChannel(const Message* message, ChannelReference ref,
Channel** channel) = 0;
- // The default message handler. It is important that all messages
- // (eventually) get a reply. This method should be called for any unrecognized
- // opcodes or otherwise unhandled messages to prevent erroneous requests from
- // blocking indefinitely.
- virtual int DefaultHandleMessage(const MessageInfo& info) = 0;
-
// Receives a message on the given endpoint file descriptor.
- virtual int MessageReceive(Message* message) = 0;
+ virtual Status<void> MessageReceive(Message* message) = 0;
// Replies to the message with a return code.
- virtual int MessageReply(Message* message, int return_code) = 0;
+ virtual Status<void> MessageReply(Message* message, int return_code) = 0;
// Replies to the message with a file descriptor.
- virtual int MessageReplyFd(Message* message, unsigned int push_fd) = 0;
+ virtual Status<void> MessageReplyFd(Message* message,
+ unsigned int push_fd) = 0;
// Replies to the message with a local channel handle.
- virtual int MessageReplyChannelHandle(Message* message,
- const LocalChannelHandle& handle) = 0;
+ virtual Status<void> MessageReplyChannelHandle(
+ Message* message, const LocalChannelHandle& handle) = 0;
// Replies to the message with a borrowed local channel handle.
- virtual int MessageReplyChannelHandle(
+ virtual Status<void> MessageReplyChannelHandle(
Message* message, const BorrowedChannelHandle& handle) = 0;
// Replies to the message with a remote channel handle.
- virtual int MessageReplyChannelHandle(Message* message,
- const RemoteChannelHandle& handle) = 0;
+ virtual Status<void> MessageReplyChannelHandle(
+ Message* message, const RemoteChannelHandle& handle) = 0;
// Reads message data into an array of memory buffers.
- virtual ssize_t ReadMessageData(Message* message, const iovec* vector,
- size_t vector_length) = 0;
+ virtual Status<size_t> ReadMessageData(Message* message, const iovec* vector,
+ size_t vector_length) = 0;
// Sends reply data for message.
- virtual ssize_t WriteMessageData(Message* message, const iovec* vector,
- size_t vector_length) = 0;
+ virtual Status<size_t> WriteMessageData(Message* message, const iovec* vector,
+ size_t vector_length) = 0;
// Records a file descriptor into the message buffer and returns the remapped
// reference to be sent to the remote process.
- virtual FileReference PushFileHandle(Message* message,
- const LocalHandle& handle) = 0;
- virtual FileReference PushFileHandle(Message* message,
- const BorrowedHandle& handle) = 0;
- virtual FileReference PushFileHandle(Message* message,
- const RemoteHandle& handle) = 0;
- virtual ChannelReference PushChannelHandle(
+ virtual Status<FileReference> PushFileHandle(Message* message,
+ const LocalHandle& handle) = 0;
+ virtual Status<FileReference> PushFileHandle(
+ Message* message, const BorrowedHandle& handle) = 0;
+ virtual Status<FileReference> PushFileHandle(Message* message,
+ const RemoteHandle& handle) = 0;
+ virtual Status<ChannelReference> PushChannelHandle(
Message* message, const LocalChannelHandle& handle) = 0;
- virtual ChannelReference PushChannelHandle(
+ virtual Status<ChannelReference> PushChannelHandle(
Message* message, const BorrowedChannelHandle& handle) = 0;
- virtual ChannelReference PushChannelHandle(
+ virtual Status<ChannelReference> PushChannelHandle(
Message* message, const RemoteChannelHandle& handle) = 0;
// Obtains a file descriptor/channel handle from a message for the given
@@ -140,7 +135,7 @@
// Cancels the endpoint, unblocking any receiver threads waiting for a
// message.
- virtual int Cancel() = 0;
+ virtual Status<void> Cancel() = 0;
};
} // namespace pdx
diff --git a/libs/vr/libpdx/private/pdx/status.h b/libs/vr/libpdx/private/pdx/status.h
index ca2832c..067fe25 100644
--- a/libs/vr/libpdx/private/pdx/status.h
+++ b/libs/vr/libpdx/private/pdx/status.h
@@ -103,6 +103,17 @@
// is not empty nor containing a valid value).
int error() const { return std::max(error_, 0); }
+ // Returns the error code as ErrorStatus object. This is a helper method
+ // to aid in propagation of error codes between Status<T> of different types
+ // as in the following example:
+ // Status<int> foo() {
+ // Status<void> status = bar();
+ // if(!status)
+ // return status.error_status();
+ // return 12;
+ // }
+ inline ErrorStatus error_status() const { return ErrorStatus{error()}; }
+
// Returns the error message associated with error code stored in the object.
// The message is the same as the string returned by strerror(status.error()).
// Can be called only when an error is actually stored (that is, the object
@@ -142,6 +153,7 @@
bool empty() const { return false; }
explicit operator bool() const { return ok(); }
int error() const { return std::max(error_, 0); }
+ inline ErrorStatus error_status() const { return ErrorStatus{error()}; }
std::string GetErrorMessage() const {
std::string message;
if (error_ > 0)
diff --git a/libs/vr/libpdx/private/pdx/utility.h b/libs/vr/libpdx/private/pdx/utility.h
index c8c717c..305c3b8 100644
--- a/libs/vr/libpdx/private/pdx/utility.h
+++ b/libs/vr/libpdx/private/pdx/utility.h
@@ -150,29 +150,29 @@
class NoOpOutputResourceMapper : public OutputResourceMapper {
public:
- FileReference PushFileHandle(const LocalHandle& handle) override {
+ Status<FileReference> PushFileHandle(const LocalHandle& handle) override {
return handle.Get();
}
- FileReference PushFileHandle(const BorrowedHandle& handle) override {
+ Status<FileReference> PushFileHandle(const BorrowedHandle& handle) override {
return handle.Get();
}
- FileReference PushFileHandle(const RemoteHandle& handle) override {
+ Status<FileReference> PushFileHandle(const RemoteHandle& handle) override {
return handle.Get();
}
- ChannelReference PushChannelHandle(
+ Status<ChannelReference> PushChannelHandle(
const LocalChannelHandle& handle) override {
return handle.value();
}
- ChannelReference PushChannelHandle(
+ Status<ChannelReference> PushChannelHandle(
const BorrowedChannelHandle& handle) override {
return handle.value();
}
- ChannelReference PushChannelHandle(
+ Status<ChannelReference> PushChannelHandle(
const RemoteChannelHandle& handle) override {
return handle.value();
}
@@ -278,7 +278,7 @@
OutputResourceMapper* GetOutputResourceMapper() override { return this; }
// OutputResourceMapper
- FileReference PushFileHandle(const LocalHandle& handle) override {
+ Status<FileReference> PushFileHandle(const LocalHandle& handle) override {
if (handle) {
const int ref = file_handles_.size();
file_handles_.push_back(handle.Get());
@@ -288,7 +288,7 @@
}
}
- FileReference PushFileHandle(const BorrowedHandle& handle) override {
+ Status<FileReference> PushFileHandle(const BorrowedHandle& handle) override {
if (handle) {
const int ref = file_handles_.size();
file_handles_.push_back(handle.Get());
@@ -298,11 +298,11 @@
}
}
- FileReference PushFileHandle(const RemoteHandle& handle) override {
+ Status<FileReference> PushFileHandle(const RemoteHandle& handle) override {
return handle.Get();
}
- ChannelReference PushChannelHandle(
+ Status<ChannelReference> PushChannelHandle(
const LocalChannelHandle& handle) override {
if (handle) {
const int ref = file_handles_.size();
@@ -313,7 +313,7 @@
}
}
- ChannelReference PushChannelHandle(
+ Status<ChannelReference> PushChannelHandle(
const BorrowedChannelHandle& handle) override {
if (handle) {
const int ref = file_handles_.size();
@@ -324,7 +324,7 @@
}
}
- ChannelReference PushChannelHandle(
+ Status<ChannelReference> PushChannelHandle(
const RemoteChannelHandle& handle) override {
return handle.value();
}
diff --git a/libs/vr/libpdx/service.cpp b/libs/vr/libpdx/service.cpp
index daf9af8..fab4770 100644
--- a/libs/vr/libpdx/service.cpp
+++ b/libs/vr/libpdx/service.cpp
@@ -9,7 +9,6 @@
#include <cstdint>
#include <pdx/trace.h>
-#include "errno_guard.h"
#define TRACE 0
@@ -60,7 +59,7 @@
"ERROR: Service \"%s\" failed to reply to message: op=%d pid=%d "
"cid=%d\n",
svc->name_.c_str(), info_.op, info_.pid, info_.cid);
- svc->endpoint()->DefaultHandleMessage(info_);
+ svc->DefaultHandleMessage(*this);
}
svc->endpoint()->FreeMessageState(state_);
}
@@ -77,112 +76,138 @@
return ImpulseBegin() + (IsImpulse() ? GetSendLength() : 0);
}
-ssize_t Message::ReadVector(const struct iovec* vector, size_t vector_length) {
+Status<size_t> Message::ReadVector(const struct iovec* vector,
+ size_t vector_length) {
PDX_TRACE_NAME("Message::ReadVector");
if (auto svc = service_.lock()) {
- ErrnoGuard errno_guard;
- const ssize_t ret =
- svc->endpoint()->ReadMessageData(this, vector, vector_length);
- return ReturnCodeOrError(ret);
+ return svc->endpoint()->ReadMessageData(this, vector, vector_length);
} else {
- return -ESHUTDOWN;
+ return ErrorStatus{ESHUTDOWN};
}
}
-ssize_t Message::Read(void* buffer, size_t length) {
+Status<void> Message::ReadVectorAll(const struct iovec* vector,
+ size_t vector_length) {
+ PDX_TRACE_NAME("Message::ReadVectorAll");
+ if (auto svc = service_.lock()) {
+ const auto status =
+ svc->endpoint()->ReadMessageData(this, vector, vector_length);
+ if (!status)
+ return status.error_status();
+ size_t size_to_read = 0;
+ for (size_t i = 0; i < vector_length; i++)
+ size_to_read += vector[i].iov_len;
+ if (status.get() < size_to_read)
+ return ErrorStatus{EIO};
+ return {};
+ } else {
+ return ErrorStatus{ESHUTDOWN};
+ }
+}
+
+Status<size_t> Message::Read(void* buffer, size_t length) {
PDX_TRACE_NAME("Message::Read");
if (auto svc = service_.lock()) {
- ErrnoGuard errno_guard;
const struct iovec vector = {buffer, length};
- const ssize_t ret = svc->endpoint()->ReadMessageData(this, &vector, 1);
- return ReturnCodeOrError(ret);
+ return svc->endpoint()->ReadMessageData(this, &vector, 1);
} else {
- return -ESHUTDOWN;
+ return ErrorStatus{ESHUTDOWN};
}
}
-ssize_t Message::WriteVector(const struct iovec* vector, size_t vector_length) {
+Status<size_t> Message::WriteVector(const struct iovec* vector,
+ size_t vector_length) {
PDX_TRACE_NAME("Message::WriteVector");
if (auto svc = service_.lock()) {
- ErrnoGuard errno_guard;
- const ssize_t ret =
- svc->endpoint()->WriteMessageData(this, vector, vector_length);
- return ReturnCodeOrError(ret);
+ return svc->endpoint()->WriteMessageData(this, vector, vector_length);
} else {
- return -ESHUTDOWN;
+ return ErrorStatus{ESHUTDOWN};
}
}
-ssize_t Message::Write(const void* buffer, size_t length) {
+Status<void> Message::WriteVectorAll(const struct iovec* vector,
+ size_t vector_length) {
+ PDX_TRACE_NAME("Message::WriteVector");
+ if (auto svc = service_.lock()) {
+ const auto status =
+ svc->endpoint()->WriteMessageData(this, vector, vector_length);
+ if (!status)
+ return status.error_status();
+ size_t size_to_write = 0;
+ for (size_t i = 0; i < vector_length; i++)
+ size_to_write += vector[i].iov_len;
+ if (status.get() < size_to_write)
+ return ErrorStatus{EIO};
+ return {};
+ } else {
+ return ErrorStatus{ESHUTDOWN};
+ }
+}
+
+Status<size_t> Message::Write(const void* buffer, size_t length) {
PDX_TRACE_NAME("Message::Write");
if (auto svc = service_.lock()) {
- ErrnoGuard errno_guard;
const struct iovec vector = {const_cast<void*>(buffer), length};
- const ssize_t ret = svc->endpoint()->WriteMessageData(this, &vector, 1);
- return ReturnCodeOrError(ret);
+ return svc->endpoint()->WriteMessageData(this, &vector, 1);
} else {
- return -ESHUTDOWN;
+ return ErrorStatus{ESHUTDOWN};
}
}
-FileReference Message::PushFileHandle(const LocalHandle& handle) {
+Status<FileReference> Message::PushFileHandle(const LocalHandle& handle) {
PDX_TRACE_NAME("Message::PushFileHandle");
if (auto svc = service_.lock()) {
- ErrnoGuard errno_guard;
- return ReturnCodeOrError(svc->endpoint()->PushFileHandle(this, handle));
+ return svc->endpoint()->PushFileHandle(this, handle);
} else {
- return -ESHUTDOWN;
+ return ErrorStatus{ESHUTDOWN};
}
}
-FileReference Message::PushFileHandle(const BorrowedHandle& handle) {
+Status<FileReference> Message::PushFileHandle(const BorrowedHandle& handle) {
PDX_TRACE_NAME("Message::PushFileHandle");
if (auto svc = service_.lock()) {
- ErrnoGuard errno_guard;
- return ReturnCodeOrError(svc->endpoint()->PushFileHandle(this, handle));
+ return svc->endpoint()->PushFileHandle(this, handle);
} else {
- return -ESHUTDOWN;
+ return ErrorStatus{ESHUTDOWN};
}
}
-FileReference Message::PushFileHandle(const RemoteHandle& handle) {
+Status<FileReference> Message::PushFileHandle(const RemoteHandle& handle) {
PDX_TRACE_NAME("Message::PushFileHandle");
if (auto svc = service_.lock()) {
- ErrnoGuard errno_guard;
- return ReturnCodeOrError(svc->endpoint()->PushFileHandle(this, handle));
+ return svc->endpoint()->PushFileHandle(this, handle);
} else {
- return -ESHUTDOWN;
+ return ErrorStatus{ESHUTDOWN};
}
}
-ChannelReference Message::PushChannelHandle(const LocalChannelHandle& handle) {
+Status<ChannelReference> Message::PushChannelHandle(
+ const LocalChannelHandle& handle) {
PDX_TRACE_NAME("Message::PushChannelHandle");
if (auto svc = service_.lock()) {
- ErrnoGuard errno_guard;
- return ReturnCodeOrError(svc->endpoint()->PushChannelHandle(this, handle));
+ return svc->endpoint()->PushChannelHandle(this, handle);
} else {
- return -ESHUTDOWN;
+ return ErrorStatus{ESHUTDOWN};
}
}
-ChannelReference Message::PushChannelHandle(
+Status<ChannelReference> Message::PushChannelHandle(
const BorrowedChannelHandle& handle) {
PDX_TRACE_NAME("Message::PushChannelHandle");
if (auto svc = service_.lock()) {
- ErrnoGuard errno_guard;
- return ReturnCodeOrError(svc->endpoint()->PushChannelHandle(this, handle));
+ return svc->endpoint()->PushChannelHandle(this, handle);
} else {
- return -ESHUTDOWN;
+ return ErrorStatus{ESHUTDOWN};
}
}
-ChannelReference Message::PushChannelHandle(const RemoteChannelHandle& handle) {
+Status<ChannelReference> Message::PushChannelHandle(
+ const RemoteChannelHandle& handle) {
PDX_TRACE_NAME("Message::PushChannelHandle");
if (auto svc = service_.lock()) {
- ErrnoGuard errno_guard;
- return ReturnCodeOrError(svc->endpoint()->PushChannelHandle(this, handle));
+ return svc->endpoint()->PushChannelHandle(this, handle);
} else {
- return -ESHUTDOWN;
+ return ErrorStatus{ESHUTDOWN};
}
}
@@ -193,7 +218,6 @@
return false;
if (ref >= 0) {
- ErrnoGuard errno_guard;
*handle = svc->endpoint()->GetFileHandle(this, ref);
if (!handle->IsValid())
return false;
@@ -211,7 +235,6 @@
return false;
if (ref >= 0) {
- ErrnoGuard errno_guard;
*handle = svc->endpoint()->GetChannelHandle(this, ref);
if (!handle->valid())
return false;
@@ -221,141 +244,137 @@
return true;
}
-int Message::Reply(int return_code) {
+Status<void> Message::Reply(int return_code) {
PDX_TRACE_NAME("Message::Reply");
auto svc = service_.lock();
if (!replied_ && svc) {
- ErrnoGuard errno_guard;
- const int ret = svc->endpoint()->MessageReply(this, return_code);
- replied_ = ret == 0;
- return ReturnCodeOrError(ret);
+ const auto ret = svc->endpoint()->MessageReply(this, return_code);
+ replied_ = ret.ok();
+ return ret;
} else {
- return -EINVAL;
+ return ErrorStatus{EINVAL};
}
}
-int Message::ReplyFileDescriptor(unsigned int fd) {
+Status<void> Message::ReplyFileDescriptor(unsigned int fd) {
PDX_TRACE_NAME("Message::ReplyFileDescriptor");
auto svc = service_.lock();
if (!replied_ && svc) {
- ErrnoGuard errno_guard;
- const int ret = svc->endpoint()->MessageReplyFd(this, fd);
- replied_ = ret == 0;
- return ReturnCodeOrError(ret);
+ const auto ret = svc->endpoint()->MessageReplyFd(this, fd);
+ replied_ = ret.ok();
+ return ret;
} else {
- return -EINVAL;
+ return ErrorStatus{EINVAL};
}
}
-int Message::ReplyError(unsigned error) {
+Status<void> Message::ReplyError(unsigned int error) {
PDX_TRACE_NAME("Message::ReplyError");
auto svc = service_.lock();
if (!replied_ && svc) {
- ErrnoGuard errno_guard;
- const int ret = svc->endpoint()->MessageReply(this, -error);
- replied_ = ret == 0;
- return ReturnCodeOrError(ret);
+ const auto ret =
+ svc->endpoint()->MessageReply(this, -static_cast<int>(error));
+ replied_ = ret.ok();
+ return ret;
} else {
- return -EINVAL;
+ return ErrorStatus{EINVAL};
}
}
-int Message::Reply(const LocalHandle& handle) {
+Status<void> Message::Reply(const LocalHandle& handle) {
PDX_TRACE_NAME("Message::ReplyFileHandle");
auto svc = service_.lock();
if (!replied_ && svc) {
- ErrnoGuard errno_guard;
- int ret;
+ Status<void> ret;
if (handle)
ret = svc->endpoint()->MessageReplyFd(this, handle.Get());
else
ret = svc->endpoint()->MessageReply(this, handle.Get());
- replied_ = ret == 0;
- return ReturnCodeOrError(ret);
+ replied_ = ret.ok();
+ return ret;
} else {
- return -EINVAL;
+ return ErrorStatus{EINVAL};
}
}
-int Message::Reply(const BorrowedHandle& handle) {
+Status<void> Message::Reply(const BorrowedHandle& handle) {
PDX_TRACE_NAME("Message::ReplyFileHandle");
auto svc = service_.lock();
if (!replied_ && svc) {
- ErrnoGuard errno_guard;
- int ret;
+ Status<void> ret;
if (handle)
ret = svc->endpoint()->MessageReplyFd(this, handle.Get());
else
ret = svc->endpoint()->MessageReply(this, handle.Get());
- replied_ = ret == 0;
- return ReturnCodeOrError(ret);
+ replied_ = ret.ok();
+ return ret;
} else {
- return -EINVAL;
+ return ErrorStatus{EINVAL};
}
}
-int Message::Reply(const RemoteHandle& handle) {
+Status<void> Message::Reply(const RemoteHandle& handle) {
PDX_TRACE_NAME("Message::ReplyFileHandle");
auto svc = service_.lock();
if (!replied_ && svc) {
- ErrnoGuard errno_guard;
- const int ret = svc->endpoint()->MessageReply(this, handle.Get());
- replied_ = ret == 0;
- return ReturnCodeOrError(ret);
+ Status<void> ret;
+
+ if (handle)
+ ret = svc->endpoint()->MessageReply(this, handle.Get());
+ else
+ ret = svc->endpoint()->MessageReply(this, handle.Get());
+
+ replied_ = ret.ok();
+ return ret;
} else {
- return -EINVAL;
+ return ErrorStatus{EINVAL};
}
}
-int Message::Reply(const LocalChannelHandle& handle) {
+Status<void> Message::Reply(const LocalChannelHandle& handle) {
auto svc = service_.lock();
if (!replied_ && svc) {
- ErrnoGuard errno_guard;
- const int ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
- replied_ = ret == 0;
- return ReturnCodeOrError(ret);
+ const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
+ replied_ = ret.ok();
+ return ret;
} else {
- return -EINVAL;
+ return ErrorStatus{EINVAL};
}
}
-int Message::Reply(const BorrowedChannelHandle& handle) {
+Status<void> Message::Reply(const BorrowedChannelHandle& handle) {
auto svc = service_.lock();
if (!replied_ && svc) {
- ErrnoGuard errno_guard;
- const int ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
- replied_ = ret == 0;
- return ReturnCodeOrError(ret);
+ const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
+ replied_ = ret.ok();
+ return ret;
} else {
- return -EINVAL;
+ return ErrorStatus{EINVAL};
}
}
-int Message::Reply(const RemoteChannelHandle& handle) {
+Status<void> Message::Reply(const RemoteChannelHandle& handle) {
auto svc = service_.lock();
if (!replied_ && svc) {
- ErrnoGuard errno_guard;
- const int ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
- replied_ = ret == 0;
- return ReturnCodeOrError(ret);
+ const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
+ replied_ = ret.ok();
+ return ret;
} else {
- return -EINVAL;
+ return ErrorStatus{EINVAL};
}
}
-int Message::ModifyChannelEvents(int clear_mask, int set_mask) {
+Status<void> Message::ModifyChannelEvents(int clear_mask, int set_mask) {
PDX_TRACE_NAME("Message::ModifyChannelEvents");
if (auto svc = service_.lock()) {
- ErrnoGuard errno_guard;
- const int ret =
- svc->endpoint()->ModifyChannelEvents(info_.cid, clear_mask, set_mask);
- return ReturnCodeOrError(ret);
+ return svc->endpoint()->ModifyChannelEvents(info_.cid, clear_mask,
+ set_mask);
} else {
- return -ESHUTDOWN;
+ return ErrorStatus{ESHUTDOWN};
}
}
@@ -416,11 +435,12 @@
std::shared_ptr<Channel> Message::GetChannel() const { return channel_.lock(); }
-void Message::SetChannel(const std::shared_ptr<Channel>& chan) {
+Status<void> Message::SetChannel(const std::shared_ptr<Channel>& chan) {
channel_ = chan;
-
+ Status<void> status;
if (auto svc = service_.lock())
- svc->SetChannel(info_.cid, chan);
+ status = svc->SetChannel(info_.cid, chan);
+ return status;
}
std::shared_ptr<Service> Message::GetService() const { return service_.lock(); }
@@ -432,16 +452,16 @@
if (!endpoint_)
return;
- const int ret = endpoint_->SetService(this);
- ALOGE_IF(ret < 0, "Failed to set service context because: %s",
- strerror(-ret));
+ const auto status = endpoint_->SetService(this);
+ ALOGE_IF(!status, "Failed to set service context because: %s",
+ status.GetErrorMessage().c_str());
}
Service::~Service() {
if (endpoint_) {
- const int ret = endpoint_->SetService(nullptr);
- ALOGE_IF(ret < 0, "Failed to clear service context because: %s",
- strerror(-ret));
+ const auto status = endpoint_->SetService(nullptr);
+ ALOGE_IF(!status, "Failed to clear service context because: %s",
+ status.GetErrorMessage().c_str());
}
}
@@ -459,32 +479,28 @@
void Service::OnChannelClose(Message& /*message*/,
const std::shared_ptr<Channel>& /*channel*/) {}
-int Service::SetChannel(int channel_id,
- const std::shared_ptr<Channel>& channel) {
+Status<void> Service::SetChannel(int channel_id,
+ const std::shared_ptr<Channel>& channel) {
PDX_TRACE_NAME("Service::SetChannel");
- ErrnoGuard errno_guard;
std::lock_guard<std::mutex> autolock(channels_mutex_);
- const int ret = endpoint_->SetChannel(channel_id, channel.get());
- if (ret == -1) {
+ const auto status = endpoint_->SetChannel(channel_id, channel.get());
+ if (!status) {
ALOGE("%s::SetChannel: Failed to set channel context: %s\n", name_.c_str(),
- strerror(errno));
+ status.GetErrorMessage().c_str());
// It's possible someone mucked with things behind our back by calling the C
// API directly. Since we know the channel id isn't valid, make sure we
// don't have it in the channels map.
- if (errno == ENOENT)
+ if (status.error() == ENOENT)
channels_.erase(channel_id);
-
- return ReturnCodeOrError(ret);
+ } else {
+ if (channel != nullptr)
+ channels_[channel_id] = channel;
+ else
+ channels_.erase(channel_id);
}
-
- if (channel != nullptr)
- channels_[channel_id] = channel;
- else
- channels_.erase(channel_id);
-
- return ret;
+ return status;
}
std::shared_ptr<Channel> Service::GetChannel(int channel_id) const {
@@ -498,21 +514,21 @@
return nullptr;
}
-int Service::CloseChannel(int channel_id) {
+Status<void> Service::CloseChannel(int channel_id) {
PDX_TRACE_NAME("Service::CloseChannel");
- ErrnoGuard errno_guard;
std::lock_guard<std::mutex> autolock(channels_mutex_);
- const int ret = endpoint_->CloseChannel(channel_id);
+ const auto status = endpoint_->CloseChannel(channel_id);
// Always erase the map entry, in case someone mucked with things behind our
// back using the C API directly.
channels_.erase(channel_id);
- return ReturnCodeOrError(ret);
+ return status;
}
-int Service::ModifyChannelEvents(int channel_id, int clear_mask, int set_mask) {
+Status<void> Service::ModifyChannelEvents(int channel_id, int clear_mask,
+ int set_mask) {
PDX_TRACE_NAME("Service::ModifyChannelEvents");
return endpoint_->ModifyChannelEvents(channel_id, clear_mask, set_mask);
}
@@ -521,7 +537,6 @@
Message* message, int flags, const std::shared_ptr<Channel>& channel,
int* channel_id) {
PDX_TRACE_NAME("Service::PushChannel");
- ErrnoGuard errno_guard;
std::lock_guard<std::mutex> autolock(channels_mutex_);
@@ -542,7 +557,6 @@
Status<int> Service::CheckChannel(const Message* message, ChannelReference ref,
std::shared_ptr<Channel>* channel) const {
PDX_TRACE_NAME("Service::CheckChannel");
- ErrnoGuard errno_guard;
// Synchronization to maintain consistency between the kernel's channel
// context pointer and the userspace channels_ map. Other threads may attempt
@@ -565,13 +579,13 @@
std::string Service::DumpState(size_t /*max_length*/) { return ""; }
-int Service::HandleMessage(Message& message) {
+Status<void> Service::HandleMessage(Message& message) {
return DefaultHandleMessage(message);
}
void Service::HandleImpulse(Message& /*impulse*/) {}
-bool Service::HandleSystemMessage(Message& message) {
+Status<void> Service::HandleSystemMessage(Message& message) {
const MessageInfo& info = message.GetInfo();
switch (info.op) {
@@ -579,8 +593,7 @@
ALOGD("%s::OnChannelOpen: pid=%d cid=%d\n", name_.c_str(), info.pid,
info.cid);
message.SetChannel(OnChannelOpen(message));
- message.Reply(0);
- return true;
+ return message.Reply(0);
}
case opcodes::CHANNEL_CLOSE: {
@@ -588,8 +601,7 @@
info.cid);
OnChannelClose(message, Channel::GetFromMessageInfo(info));
message.SetChannel(nullptr);
- message.Reply(0);
- return true;
+ return message.Reply(0);
}
case opcodes::REPORT_SYSPROP_CHANGE:
@@ -597,8 +609,7 @@
info.pid, info.cid);
OnSysPropChange();
android::report_sysprop_change();
- message.Reply(0);
- return true;
+ return message.Reply(0);
case opcodes::DUMP_STATE: {
ALOGD("%s:DUMP_STATE: pid=%d cid=%d\n", name_.c_str(), info.pid,
@@ -607,21 +618,20 @@
const size_t response_size = response.size() < message.GetReceiveLength()
? response.size()
: message.GetReceiveLength();
- const ssize_t bytes_written =
+ const Status<size_t> status =
message.Write(response.data(), response_size);
- if (bytes_written < static_cast<ssize_t>(response_size))
- message.ReplyError(EIO);
+ if (status && status.get() < response_size)
+ return message.ReplyError(EIO);
else
- message.Reply(bytes_written);
- return true;
+ return message.Reply(status);
}
default:
- return false;
+ return ErrorStatus{EOPNOTSUPP};
}
}
-int Service::DefaultHandleMessage(Message& message) {
+Status<void> Service::DefaultHandleMessage(Message& message) {
const MessageInfo& info = message.GetInfo();
ALOGD_IF(TRACE, "Service::DefaultHandleMessage: pid=%d cid=%d op=%d\n",
@@ -632,23 +642,21 @@
case opcodes::CHANNEL_CLOSE:
case opcodes::REPORT_SYSPROP_CHANGE:
case opcodes::DUMP_STATE:
- HandleSystemMessage(message);
- return 0;
+ return HandleSystemMessage(message);
default:
- return message.ReplyError(ENOTSUP);
+ return message.ReplyError(EOPNOTSUPP);
}
}
void Service::OnSysPropChange() {}
-int Service::ReceiveAndDispatch() {
- ErrnoGuard errno_guard;
+Status<void> Service::ReceiveAndDispatch() {
Message message;
- const int ret = endpoint_->MessageReceive(&message);
- if (ret < 0) {
- ALOGE("Failed to receive message: %s\n", strerror(errno));
- return ReturnCodeOrError(ret);
+ const auto status = endpoint_->MessageReceive(&message);
+ if (!status) {
+ ALOGE("Failed to receive message: %s\n", status.GetErrorMessage().c_str());
+ return status;
}
std::shared_ptr<Service> service = message.GetService();
@@ -657,24 +665,20 @@
ALOGE("Service::ReceiveAndDispatch: service context is NULL!!!\n");
// Don't block the sender indefinitely in this error case.
endpoint_->MessageReply(&message, -EINVAL);
- return -EINVAL;
+ return ErrorStatus{EINVAL};
}
if (message.IsImpulse()) {
service->HandleImpulse(message);
- return 0;
+ return {};
} else if (service->HandleSystemMessage(message)) {
- return 0;
+ return {};
} else {
return service->HandleMessage(message);
}
}
-int Service::Cancel() {
- ErrnoGuard errno_guard;
- const int ret = endpoint_->Cancel();
- return ReturnCodeOrError(ret);
-}
+Status<void> Service::Cancel() { return endpoint_->Cancel(); }
} // namespace pdx
} // namespace android
diff --git a/libs/vr/libpdx/service_tests.cpp b/libs/vr/libpdx/service_tests.cpp
index fc0c8db..c7412b7 100644
--- a/libs/vr/libpdx/service_tests.cpp
+++ b/libs/vr/libpdx/service_tests.cpp
@@ -30,7 +30,6 @@
using testing::Ref;
using testing::Return;
using testing::SetArgPointee;
-using testing::SetErrnoAndReturn;
using testing::WithArg;
using testing::WithoutArgs;
using testing::_;
@@ -91,7 +90,7 @@
MOCK_METHOD1(OnChannelOpen, std::shared_ptr<Channel>(Message& message));
MOCK_METHOD2(OnChannelClose,
void(Message& message, const std::shared_ptr<Channel>& channel));
- MOCK_METHOD1(HandleMessage, int(Message& message));
+ MOCK_METHOD1(HandleMessage, Status<void>(Message& message));
MOCK_METHOD1(HandleImpulse, void(Message& impulse));
MOCK_METHOD0(OnSysPropChange, void());
MOCK_METHOD1(DumpState, std::string(size_t max_length));
@@ -101,7 +100,9 @@
public:
ServiceTest() {
auto endpoint = std::make_unique<testing::StrictMock<MockEndpoint>>();
- EXPECT_CALL(*endpoint, SetService(_)).Times(2).WillRepeatedly(Return(0));
+ EXPECT_CALL(*endpoint, SetService(_))
+ .Times(2)
+ .WillRepeatedly(Return(Status<void>{}));
service_ = std::make_shared<MockService>("MockSvc", std::move(endpoint));
}
@@ -134,7 +135,8 @@
}
void ExpectDefaultHandleMessage() {
- EXPECT_CALL(*endpoint(), DefaultHandleMessage(_));
+ EXPECT_CALL(*endpoint(), MessageReply(_, -EOPNOTSUPP))
+ .WillOnce(Return(Status<void>{}));
}
std::shared_ptr<MockService> service_;
@@ -222,10 +224,11 @@
auto channel = std::make_shared<Channel>();
EXPECT_CALL(*service_, OnChannelOpen(Ref(message))).WillOnce(Return(channel));
EXPECT_CALL(*endpoint(), SetChannel(kTestCid, channel.get()))
- .WillOnce(Return(0));
- EXPECT_CALL(*endpoint(), MessageReply(&message, 0)).WillOnce(Return(0));
+ .WillOnce(Return(Status<void>{}));
+ EXPECT_CALL(*endpoint(), MessageReply(&message, 0))
+ .WillOnce(Return(Status<void>{}));
- EXPECT_EQ(0, service_->Service::HandleMessage(message));
+ EXPECT_TRUE(service_->Service::HandleMessage(message));
}
TEST_F(ServiceTest, HandleMessageChannelClose) {
@@ -237,10 +240,12 @@
Message message{info};
EXPECT_CALL(*service_, OnChannelClose(Ref(message), channel));
- EXPECT_CALL(*endpoint(), SetChannel(kTestCid, nullptr)).WillOnce(Return(0));
- EXPECT_CALL(*endpoint(), MessageReply(&message, 0)).WillOnce(Return(0));
+ EXPECT_CALL(*endpoint(), SetChannel(kTestCid, nullptr))
+ .WillOnce(Return(Status<void>{}));
+ EXPECT_CALL(*endpoint(), MessageReply(&message, 0))
+ .WillOnce(Return(Status<void>{}));
- EXPECT_EQ(0, service_->Service::HandleMessage(message));
+ EXPECT_TRUE(service_->Service::HandleMessage(message));
}
TEST_F(ServiceTest, HandleMessageOnSysPropChange) {
@@ -250,9 +255,10 @@
Message message{info};
EXPECT_CALL(*service_, OnSysPropChange());
- EXPECT_CALL(*endpoint(), MessageReply(&message, 0)).WillOnce(Return(0));
+ EXPECT_CALL(*endpoint(), MessageReply(&message, 0))
+ .WillOnce(Return(Status<void>{}));
- EXPECT_EQ(0, service_->Service::HandleMessage(message));
+ EXPECT_TRUE(service_->Service::HandleMessage(message));
}
TEST_F(ServiceTest, HandleMessageOnDumpState) {
@@ -270,9 +276,9 @@
WriteMessageData(&message, IoVecDataMatcher(IoVecData{kReply}), 1))
.WillOnce(Return(kReply.size()));
EXPECT_CALL(*endpoint(), MessageReply(&message, kReply.size()))
- .WillOnce(Return(0));
+ .WillOnce(Return(Status<void>{}));
- EXPECT_EQ(0, service_->Service::HandleMessage(message));
+ EXPECT_TRUE(service_->Service::HandleMessage(message));
}
TEST_F(ServiceTest, HandleMessageOnDumpStateTooLarge) {
@@ -291,9 +297,9 @@
WriteMessageData(&message, IoVecDataMatcher(IoVecData{kActualReply}), 1))
.WillOnce(Return(kActualReply.size()));
EXPECT_CALL(*endpoint(), MessageReply(&message, kActualReply.size()))
- .WillOnce(Return(0));
+ .WillOnce(Return(Status<void>{}));
- EXPECT_EQ(0, service_->Service::HandleMessage(message));
+ EXPECT_TRUE(service_->Service::HandleMessage(message));
}
TEST_F(ServiceTest, HandleMessageOnDumpStateFail) {
@@ -310,9 +316,10 @@
*endpoint(),
WriteMessageData(&message, IoVecDataMatcher(IoVecData{kReply}), 1))
.WillOnce(Return(1));
- EXPECT_CALL(*endpoint(), MessageReply(&message, -EIO)).WillOnce(Return(0));
+ EXPECT_CALL(*endpoint(), MessageReply(&message, -EIO))
+ .WillOnce(Return(Status<void>{}));
- EXPECT_EQ(0, service_->Service::HandleMessage(message));
+ EXPECT_TRUE(service_->Service::HandleMessage(message));
}
TEST_F(ServiceTest, HandleMessageCustom) {
@@ -320,10 +327,10 @@
SetupMessageInfoAndDefaultExpectations(&info, kTestOp);
Message message{info};
- EXPECT_CALL(*endpoint(), MessageReply(&message, -ENOTSUP))
- .WillOnce(Return(0));
+ EXPECT_CALL(*endpoint(), MessageReply(&message, -EOPNOTSUPP))
+ .WillOnce(Return(Status<void>{}));
- EXPECT_EQ(0, service_->Service::HandleMessage(message));
+ EXPECT_TRUE(service_->Service::HandleMessage(message));
}
TEST_F(ServiceTest, ReplyMessageWithoutService) {
@@ -337,7 +344,7 @@
service_.reset();
EXPECT_TRUE(message.IsServiceExpired());
- EXPECT_EQ(-EINVAL, message.Reply(12));
+ EXPECT_EQ(EINVAL, message.Reply(12).error());
}
TEST_F(ServiceTest, ReceiveAndDispatchMessage) {
@@ -345,33 +352,33 @@
SetupMessageInfoAndDefaultExpectations(&info, kTestOp);
ExpectDefaultHandleMessage();
- auto on_receive = [&info](Message* message) {
+ auto on_receive = [&info](Message* message) -> Status<void> {
*message = Message{info};
- return 0;
+ return {};
};
EXPECT_CALL(*endpoint(), MessageReceive(_)).WillOnce(Invoke(on_receive));
- EXPECT_CALL(*service_, HandleMessage(_)).WillOnce(Return(0));
+ EXPECT_CALL(*service_, HandleMessage(_)).WillOnce(Return(Status<void>{}));
- EXPECT_EQ(0, service_->ReceiveAndDispatch());
+ EXPECT_TRUE(service_->ReceiveAndDispatch());
}
TEST_F(ServiceTest, ReceiveAndDispatchImpulse) {
MessageInfo info;
SetupMessageInfoAndDefaultExpectations(&info, kTestOp, true);
- auto on_receive = [&info](Message* message) {
+ auto on_receive = [&info](Message* message) -> Status<void> {
*message = Message{info};
- return 0;
+ return {};
};
EXPECT_CALL(*endpoint(), MessageReceive(_)).WillOnce(Invoke(on_receive));
EXPECT_CALL(*service_, HandleImpulse(_));
- EXPECT_EQ(0, service_->ReceiveAndDispatch());
+ EXPECT_TRUE(service_->ReceiveAndDispatch());
}
TEST_F(ServiceTest, Cancel) {
- EXPECT_CALL(*endpoint(), Cancel()).WillOnce(Return(0));
- EXPECT_EQ(0, service_->Cancel());
+ EXPECT_CALL(*endpoint(), Cancel()).WillOnce(Return(Status<void>{}));
+ EXPECT_TRUE(service_->Cancel());
}
///////////////////////////////////////////////////////////////////////////////
@@ -380,85 +387,85 @@
TEST_F(ServiceMessageTest, Reply) {
EXPECT_CALL(*endpoint(), MessageReply(message_.get(), 12))
- .WillOnce(Return(0));
+ .WillOnce(Return(Status<void>{}));
EXPECT_FALSE(message_->replied());
- EXPECT_EQ(0, message_->Reply(12));
+ EXPECT_TRUE(message_->Reply(12));
EXPECT_TRUE(message_->replied());
- EXPECT_EQ(-EINVAL, message_->Reply(12)); // Already replied.
+ EXPECT_EQ(EINVAL, message_->Reply(12).error()); // Already replied.
}
TEST_F(ServiceMessageTest, ReplyFail) {
EXPECT_CALL(*endpoint(), MessageReply(message_.get(), 12))
- .WillOnce(SetErrnoAndReturn(EIO, -1));
- EXPECT_EQ(-EIO, message_->Reply(12));
+ .WillOnce(Return(ErrorStatus{EIO}));
+ EXPECT_EQ(EIO, message_->Reply(12).error());
ExpectDefaultHandleMessage();
}
TEST_F(ServiceMessageTest, ReplyError) {
EXPECT_CALL(*endpoint(), MessageReply(message_.get(), -12))
- .WillOnce(Return(0));
- EXPECT_EQ(0, message_->ReplyError(12));
+ .WillOnce(Return(Status<void>{}));
+ EXPECT_TRUE(message_->ReplyError(12));
}
TEST_F(ServiceMessageTest, ReplyFileDescriptor) {
EXPECT_CALL(*endpoint(), MessageReplyFd(message_.get(), 5))
- .WillOnce(Return(0));
- EXPECT_EQ(0, message_->ReplyFileDescriptor(5));
+ .WillOnce(Return(Status<void>{}));
+ EXPECT_TRUE(message_->ReplyFileDescriptor(5));
}
TEST_F(ServiceMessageTest, ReplyLocalFileHandle) {
const int kFakeFd = 12345;
LocalHandle handle{kFakeFd};
EXPECT_CALL(*endpoint(), MessageReplyFd(message_.get(), kFakeFd))
- .WillOnce(Return(0));
- EXPECT_EQ(0, message_->Reply(handle));
+ .WillOnce(Return(Status<void>{}));
+ EXPECT_TRUE(message_->Reply(handle));
handle.Release(); // Make sure we do not close the fake file descriptor.
}
TEST_F(ServiceMessageTest, ReplyLocalFileHandleError) {
LocalHandle handle{-EINVAL};
EXPECT_CALL(*endpoint(), MessageReply(message_.get(), -EINVAL))
- .WillOnce(Return(0));
- EXPECT_EQ(0, message_->Reply(handle));
+ .WillOnce(Return(Status<void>{}));
+ EXPECT_TRUE(message_->Reply(handle));
}
TEST_F(ServiceMessageTest, ReplyBorrowedFileHandle) {
const int kFakeFd = 12345;
BorrowedHandle handle{kFakeFd};
EXPECT_CALL(*endpoint(), MessageReplyFd(message_.get(), kFakeFd))
- .WillOnce(Return(0));
- EXPECT_EQ(0, message_->Reply(handle));
+ .WillOnce(Return(Status<void>{}));
+ EXPECT_TRUE(message_->Reply(handle));
}
TEST_F(ServiceMessageTest, ReplyBorrowedFileHandleError) {
BorrowedHandle handle{-EACCES};
EXPECT_CALL(*endpoint(), MessageReply(message_.get(), -EACCES))
- .WillOnce(Return(0));
- EXPECT_EQ(0, message_->Reply(handle));
+ .WillOnce(Return(Status<void>{}));
+ EXPECT_TRUE(message_->Reply(handle));
}
TEST_F(ServiceMessageTest, ReplyRemoteFileHandle) {
RemoteHandle handle{123};
EXPECT_CALL(*endpoint(), MessageReply(message_.get(), handle.Get()))
- .WillOnce(Return(0));
- EXPECT_EQ(0, message_->Reply(handle));
+ .WillOnce(Return(Status<void>{}));
+ EXPECT_TRUE(message_->Reply(handle));
}
TEST_F(ServiceMessageTest, ReplyRemoteFileHandleError) {
RemoteHandle handle{-EIO};
EXPECT_CALL(*endpoint(), MessageReply(message_.get(), -EIO))
- .WillOnce(Return(0));
- EXPECT_EQ(0, message_->Reply(handle));
+ .WillOnce(Return(Status<void>{}));
+ EXPECT_TRUE(message_->Reply(handle));
}
TEST_F(ServiceMessageTest, ReplyLocalChannelHandle) {
LocalChannelHandle handle{nullptr, 12345};
EXPECT_CALL(*endpoint(), MessageReplyChannelHandle(
message_.get(), A<const LocalChannelHandle&>()))
- .WillOnce(Return(0));
- EXPECT_EQ(0, message_->Reply(handle));
+ .WillOnce(Return(Status<void>{}));
+ EXPECT_TRUE(message_->Reply(handle));
}
TEST_F(ServiceMessageTest, ReplyBorrowedChannelHandle) {
@@ -466,30 +473,30 @@
EXPECT_CALL(*endpoint(),
MessageReplyChannelHandle(message_.get(),
A<const BorrowedChannelHandle&>()))
- .WillOnce(Return(0));
- EXPECT_EQ(0, message_->Reply(handle));
+ .WillOnce(Return(Status<void>{}));
+ EXPECT_TRUE(message_->Reply(handle));
}
TEST_F(ServiceMessageTest, ReplyRemoteChannelHandle) {
RemoteChannelHandle handle{12345};
EXPECT_CALL(*endpoint(), MessageReplyChannelHandle(
message_.get(), A<const RemoteChannelHandle&>()))
- .WillOnce(Return(0));
- EXPECT_EQ(0, message_->Reply(handle));
+ .WillOnce(Return(Status<void>{}));
+ EXPECT_TRUE(message_->Reply(handle));
}
TEST_F(ServiceMessageTest, ReplyStatusInt) {
Status<int> status{123};
EXPECT_CALL(*endpoint(), MessageReply(message_.get(), status.get()))
- .WillOnce(Return(0));
- EXPECT_EQ(0, message_->Reply(status));
+ .WillOnce(Return(Status<void>{}));
+ EXPECT_TRUE(message_->Reply(status));
}
TEST_F(ServiceMessageTest, ReplyStatusError) {
Status<int> status{ErrorStatus{EIO}};
EXPECT_CALL(*endpoint(), MessageReply(message_.get(), -status.error()))
- .WillOnce(Return(0));
- EXPECT_EQ(0, message_->Reply(status));
+ .WillOnce(Return(Status<void>{}));
+ EXPECT_TRUE(message_->Reply(status));
}
TEST_F(ServiceMessageTest, Read) {
@@ -500,9 +507,9 @@
*endpoint(),
ReadMessageData(message_.get(), IoVecMatcher(kDataBuffer, kDataSize), 1))
.WillOnce(Return(50))
- .WillOnce(SetErrnoAndReturn(EACCES, -1));
- EXPECT_EQ(50, message_->Read(kDataBuffer, kDataSize));
- EXPECT_EQ(-EACCES, message_->Read(kDataBuffer, kDataSize));
+ .WillOnce(Return(ErrorStatus{EACCES}));
+ EXPECT_EQ(50u, message_->Read(kDataBuffer, kDataSize).get());
+ EXPECT_EQ(EACCES, message_->Read(kDataBuffer, kDataSize).error());
}
TEST_F(ServiceMessageTest, ReadVector) {
@@ -516,10 +523,10 @@
IoVecMatcher(IoVecArray{std::begin(vec), std::end(vec)}), 2))
.WillOnce(Return(30))
.WillOnce(Return(15))
- .WillOnce(SetErrnoAndReturn(EBADF, -1));
- EXPECT_EQ(30, message_->ReadVector(vec, 2));
- EXPECT_EQ(15, message_->ReadVector(vec));
- EXPECT_EQ(-EBADF, message_->ReadVector(vec));
+ .WillOnce(Return(ErrorStatus{EBADF}));
+ EXPECT_EQ(30u, message_->ReadVector(vec, 2).get());
+ EXPECT_EQ(15u, message_->ReadVector(vec).get());
+ EXPECT_EQ(EBADF, message_->ReadVector(vec).error());
}
TEST_F(ServiceMessageTest, Write) {
@@ -530,9 +537,9 @@
*endpoint(),
WriteMessageData(message_.get(), IoVecMatcher(kDataBuffer, kDataSize), 1))
.WillOnce(Return(50))
- .WillOnce(SetErrnoAndReturn(EBADMSG, -1));
- EXPECT_EQ(50, message_->Write(kDataBuffer, kDataSize));
- EXPECT_EQ(-EBADMSG, message_->Write(kDataBuffer, kDataSize));
+ .WillOnce(Return(ErrorStatus{EBADMSG}));
+ EXPECT_EQ(50u, message_->Write(kDataBuffer, kDataSize).get());
+ EXPECT_EQ(EBADMSG, message_->Write(kDataBuffer, kDataSize).error());
}
TEST_F(ServiceMessageTest, WriteVector) {
@@ -546,10 +553,10 @@
IoVecMatcher(IoVecArray{std::begin(vec), std::end(vec)}), 2))
.WillOnce(Return(30))
.WillOnce(Return(15))
- .WillOnce(SetErrnoAndReturn(EIO, -1));
- EXPECT_EQ(30, message_->WriteVector(vec, 2));
- EXPECT_EQ(15, message_->WriteVector(vec));
- EXPECT_EQ(-EIO, message_->WriteVector(vec, 2));
+ .WillOnce(Return(ErrorStatus{EIO}));
+ EXPECT_EQ(30u, message_->WriteVector(vec, 2).get());
+ EXPECT_EQ(15u, message_->WriteVector(vec).get());
+ EXPECT_EQ(EIO, message_->WriteVector(vec, 2).error());
}
TEST_F(ServiceMessageTest, PushLocalFileHandle) {
@@ -560,9 +567,9 @@
PushFileHandle(message_.get(), Matcher<const LocalHandle&>(
FileHandleMatcher(kFakeFd))))
.WillOnce(Return(12))
- .WillOnce(SetErrnoAndReturn(EIO, -1));
- EXPECT_EQ(12, message_->PushFileHandle(handle));
- EXPECT_EQ(-EIO, message_->PushFileHandle(handle));
+ .WillOnce(Return(ErrorStatus{EIO}));
+ EXPECT_EQ(12, message_->PushFileHandle(handle).get());
+ EXPECT_EQ(EIO, message_->PushFileHandle(handle).error());
handle.Release(); // Make sure we do not close the fake file descriptor.
}
@@ -574,9 +581,9 @@
PushFileHandle(message_.get(), Matcher<const BorrowedHandle&>(
FileHandleMatcher(kFakeFd))))
.WillOnce(Return(13))
- .WillOnce(SetErrnoAndReturn(EACCES, -1));
- EXPECT_EQ(13, message_->PushFileHandle(handle));
- EXPECT_EQ(-EACCES, message_->PushFileHandle(handle));
+ .WillOnce(Return(ErrorStatus{EACCES}));
+ EXPECT_EQ(13, message_->PushFileHandle(handle).get());
+ EXPECT_EQ(EACCES, message_->PushFileHandle(handle).error());
}
TEST_F(ServiceMessageTest, PushRemoteFileHandle) {
@@ -587,9 +594,9 @@
PushFileHandle(message_.get(), Matcher<const RemoteHandle&>(
FileHandleMatcher(kFakeFd))))
.WillOnce(Return(kFakeFd))
- .WillOnce(SetErrnoAndReturn(EIO, -1));
- EXPECT_EQ(kFakeFd, message_->PushFileHandle(handle));
- EXPECT_EQ(-EIO, message_->PushFileHandle(handle));
+ .WillOnce(Return(ErrorStatus{EIO}));
+ EXPECT_EQ(kFakeFd, message_->PushFileHandle(handle).get());
+ EXPECT_EQ(EIO, message_->PushFileHandle(handle).error());
}
TEST_F(ServiceMessageTest, PushLocalChannelHandle) {
@@ -600,9 +607,9 @@
Matcher<const LocalChannelHandle&>(
ChannelHandleMatcher(kValue))))
.WillOnce(Return(7))
- .WillOnce(SetErrnoAndReturn(EIO, -1));
- EXPECT_EQ(7, message_->PushChannelHandle(handle));
- EXPECT_EQ(-EIO, message_->PushChannelHandle(handle));
+ .WillOnce(Return(ErrorStatus{EIO}));
+ EXPECT_EQ(7, message_->PushChannelHandle(handle).get());
+ EXPECT_EQ(EIO, message_->PushChannelHandle(handle).error());
}
TEST_F(ServiceMessageTest, PushBorrowedChannelHandle) {
@@ -614,9 +621,9 @@
PushChannelHandle(message_.get(), Matcher<const BorrowedChannelHandle&>(
ChannelHandleMatcher(kValue))))
.WillOnce(Return(8))
- .WillOnce(SetErrnoAndReturn(EIO, -1));
- EXPECT_EQ(8, message_->PushChannelHandle(handle));
- EXPECT_EQ(-EIO, message_->PushChannelHandle(handle));
+ .WillOnce(Return(ErrorStatus{EIO}));
+ EXPECT_EQ(8, message_->PushChannelHandle(handle).get());
+ EXPECT_EQ(EIO, message_->PushChannelHandle(handle).error());
}
TEST_F(ServiceMessageTest, PushRemoteChannelHandle) {
@@ -628,9 +635,9 @@
PushChannelHandle(message_.get(), Matcher<const RemoteChannelHandle&>(
ChannelHandleMatcher(kValue))))
.WillOnce(Return(kValue))
- .WillOnce(SetErrnoAndReturn(EIO, -1));
- EXPECT_EQ(kValue, message_->PushChannelHandle(handle));
- EXPECT_EQ(-EIO, message_->PushChannelHandle(handle));
+ .WillOnce(Return(ErrorStatus{EIO}));
+ EXPECT_EQ(kValue, message_->PushChannelHandle(handle).get());
+ EXPECT_EQ(EIO, message_->PushChannelHandle(handle).error());
}
TEST_F(ServiceMessageTest, GetFileHandle) {
@@ -701,8 +708,8 @@
int kClearMask = 1;
int kSetMask = 2;
EXPECT_CALL(*endpoint(), ModifyChannelEvents(kTestCid, kClearMask, kSetMask))
- .WillOnce(Return(0));
- EXPECT_EQ(0, message_->ModifyChannelEvents(kClearMask, kSetMask));
+ .WillOnce(Return(Status<void>{}));
+ EXPECT_TRUE(message_->ModifyChannelEvents(kClearMask, kSetMask));
}
TEST_F(ServiceMessageTest, PushChannelSameService) {
@@ -733,7 +740,9 @@
TEST_F(ServiceMessageTest, PushChannelDifferentService) {
ExpectDefaultHandleMessage();
auto endpoint2 = std::make_unique<testing::StrictMock<MockEndpoint>>();
- EXPECT_CALL(*endpoint2, SetService(_)).Times(2).WillRepeatedly(Return(0));
+ EXPECT_CALL(*endpoint2, SetService(_))
+ .Times(2)
+ .WillRepeatedly(Return(Status<void>{}));
auto service2 =
std::make_shared<MockService>("MockSvc2", std::move(endpoint2));
@@ -779,7 +788,9 @@
TEST_F(ServiceMessageTest, CheckChannelDifferentService) {
ExpectDefaultHandleMessage();
auto endpoint2 = std::make_unique<testing::StrictMock<MockEndpoint>>();
- EXPECT_CALL(*endpoint2, SetService(_)).Times(2).WillRepeatedly(Return(0));
+ EXPECT_CALL(*endpoint2, SetService(_))
+ .Times(2)
+ .WillRepeatedly(Return(Status<void>{}));
auto service2 =
std::make_shared<MockService>("MockSvc2", std::move(endpoint2));
diff --git a/libs/vr/libpdx_default_transport/Android.bp b/libs/vr/libpdx_default_transport/Android.bp
index 655adb8..8cfa86f 100644
--- a/libs/vr/libpdx_default_transport/Android.bp
+++ b/libs/vr/libpdx_default_transport/Android.bp
@@ -57,6 +57,7 @@
"pdx_benchmarks.cpp",
],
shared_libs: [
+ "libbase",
"libchrome",
"libcutils",
"liblog",
diff --git a/libs/vr/libpdx_default_transport/pdx_benchmarks.cpp b/libs/vr/libpdx_default_transport/pdx_benchmarks.cpp
index de02401..0b658fb 100644
--- a/libs/vr/libpdx_default_transport/pdx_benchmarks.cpp
+++ b/libs/vr/libpdx_default_transport/pdx_benchmarks.cpp
@@ -38,6 +38,7 @@
using android::pdx::Channel;
using android::pdx::ClientBase;
using android::pdx::Endpoint;
+using android::pdx::ErrorStatus;
using android::pdx::Message;
using android::pdx::Service;
using android::pdx::ServiceBase;
@@ -246,7 +247,7 @@
<< message.GetChannelId();
}
- int HandleMessage(Message& message) override {
+ Status<void> HandleMessage(Message& message) override {
ATRACE_NAME("BenchmarkService::HandleMessage");
switch (message.GetOp()) {
@@ -254,30 +255,27 @@
VLOG(1) << "BenchmarkService::HandleMessage: op=nop";
{
ATRACE_NAME("Reply");
- CHECK(message.Reply(0) == 0);
+ CHECK(message.Reply(0));
}
- return 0;
+ return {};
case BenchmarkOps::Write: {
VLOG(1) << "BenchmarkService::HandleMessage: op=write send_length="
<< message.GetSendLength()
<< " receive_length=" << message.GetReceiveLength();
- const ssize_t expected_length =
- static_cast<ssize_t>(message.GetSendLength());
- const ssize_t actual_length =
- expected_length > 0
- ? message.Read(send_buffer.data(), message.GetSendLength())
- : 0;
+ Status<void> status;
+ if (message.GetSendLength())
+ status = message.ReadAll(send_buffer.data(), message.GetSendLength());
{
ATRACE_NAME("Reply");
- if (actual_length < expected_length)
- CHECK(message.ReplyError(EIO) == 0);
+ if (!status)
+ CHECK(message.ReplyError(status.error()));
else
- CHECK(message.Reply(actual_length) == 0);
+ CHECK(message.Reply(message.GetSendLength()));
}
- return 0;
+ return {};
}
case BenchmarkOps::Read: {
@@ -285,22 +283,20 @@
<< message.GetSendLength()
<< " receive_length=" << message.GetReceiveLength();
- const ssize_t expected_length =
- static_cast<ssize_t>(message.GetReceiveLength());
- const ssize_t actual_length =
- expected_length > 0
- ? message.Write(receive_buffer.data(),
- message.GetReceiveLength())
- : 0;
+ Status<void> status;
+ if (message.GetReceiveLength()) {
+ status = message.WriteAll(receive_buffer.data(),
+ message.GetReceiveLength());
+ }
{
ATRACE_NAME("Reply");
- if (actual_length < expected_length)
- CHECK(message.ReplyError(EIO) == 0);
+ if (!status)
+ CHECK(message.ReplyError(status.error()));
else
- CHECK(message.Reply(actual_length) == 0);
+ CHECK(message.Reply(message.GetReceiveLength()));
}
- return 0;
+ return {};
}
case BenchmarkOps::Echo: {
@@ -308,31 +304,28 @@
<< message.GetSendLength()
<< " receive_length=" << message.GetReceiveLength();
- const ssize_t expected_length =
- static_cast<ssize_t>(message.GetSendLength());
- ssize_t actual_length =
- expected_length > 0
- ? message.Read(send_buffer.data(), message.GetSendLength())
- : 0;
+ Status<void> status;
+ if (message.GetSendLength())
+ status = message.ReadAll(send_buffer.data(), message.GetSendLength());
- if (actual_length < expected_length) {
- CHECK(message.ReplyError(EIO) == 0);
- return 0;
+ if (!status) {
+ CHECK(message.ReplyError(status.error()));
+ return {};
}
- actual_length =
- expected_length > 0
- ? message.Write(send_buffer.data(), message.GetSendLength())
- : 0;
+ if (message.GetSendLength()) {
+ status =
+ message.WriteAll(send_buffer.data(), message.GetSendLength());
+ }
{
ATRACE_NAME("Reply");
- if (actual_length < expected_length)
- CHECK(message.ReplyError(EIO) == 0);
+ if (!status)
+ CHECK(message.ReplyError(status.error()));
else
- CHECK(message.Reply(actual_length) == 0);
+ CHECK(message.Reply(message.GetSendLength()));
}
- return 0;
+ return {};
}
case BenchmarkOps::Stats: {
@@ -348,7 +341,7 @@
RemoteMethodReturn<BenchmarkRPC::Stats>(
message, BenchmarkRPC::Stats::Return{receive_time_ns, GetClockNs(),
sched_stats_});
- return 0;
+ return {};
}
case BenchmarkOps::WriteVector:
@@ -358,7 +351,7 @@
DispatchRemoteMethod<BenchmarkRPC::WriteVector>(
*this, &BenchmarkService::OnWriteVector, message, kMaxMessageSize);
- return 0;
+ return {};
case BenchmarkOps::EchoVector:
VLOG(1) << "BenchmarkService::HandleMessage: op=echovec send_length="
@@ -367,11 +360,11 @@
DispatchRemoteMethod<BenchmarkRPC::EchoVector>(
*this, &BenchmarkService::OnEchoVector, message, kMaxMessageSize);
- return 0;
+ return {};
case BenchmarkOps::Quit:
Cancel();
- return -ESHUTDOWN;
+ return ErrorStatus{ESHUTDOWN};
default:
VLOG(1) << "BenchmarkService::HandleMessage: default case; op="
@@ -543,17 +536,17 @@
const std::shared_ptr<BenchmarkService>& local_service) {
SetThreadName("service" + std::to_string(service_id));
- // Read the inital schedstats for this thread from procfs.
+ // Read the initial schedstats for this thread from procfs.
local_service->UpdateSchedStats();
ATRACE_NAME("BenchmarkService::Dispatch");
while (!done) {
- const int ret = local_service->ReceiveAndDispatch();
- if (ret < 0) {
- if (ret != -ESHUTDOWN) {
+ auto ret = local_service->ReceiveAndDispatch();
+ if (!ret) {
+ if (ret.error() != ESHUTDOWN) {
std::cerr << "Error while dispatching message on thread "
<< thread_id << " service " << service_id << ": "
- << strerror(-ret) << std::endl;
+ << ret.GetErrorMessage() << std::endl;
} else {
std::cerr << "Quitting thread " << thread_id << " service "
<< service_id << std::endl;
diff --git a/libs/vr/libpdx_uds/Android.bp b/libs/vr/libpdx_uds/Android.bp
index 09eeaa0..a73ba34 100644
--- a/libs/vr/libpdx_uds/Android.bp
+++ b/libs/vr/libpdx_uds/Android.bp
@@ -20,6 +20,8 @@
"service_endpoint.cpp",
],
static_libs: [
+ "libcutils",
+ "libbase",
"libpdx",
],
}
@@ -41,6 +43,8 @@
"libpdx",
],
shared_libs: [
+ "libbase",
+ "libcutils",
"liblog",
"libutils",
],
diff --git a/libs/vr/libpdx_uds/channel_event_set.cpp b/libs/vr/libpdx_uds/channel_event_set.cpp
index f8baeab..ac4dea9 100644
--- a/libs/vr/libpdx_uds/channel_event_set.cpp
+++ b/libs/vr/libpdx_uds/channel_event_set.cpp
@@ -12,7 +12,7 @@
const int flags = EFD_CLOEXEC | EFD_NONBLOCK;
LocalHandle epoll_fd, event_fd;
- if (!SetupHandle(epoll_create(1), &epoll_fd, "epoll") ||
+ if (!SetupHandle(epoll_create1(EPOLL_CLOEXEC), &epoll_fd, "epoll") ||
!SetupHandle(eventfd(0, flags), &event_fd, "event")) {
return;
}
diff --git a/libs/vr/libpdx_uds/ipc_helper.cpp b/libs/vr/libpdx_uds/ipc_helper.cpp
index ee7299e..fe5c986 100644
--- a/libs/vr/libpdx_uds/ipc_helper.cpp
+++ b/libs/vr/libpdx_uds/ipc_helper.cpp
@@ -87,7 +87,7 @@
OutputResourceMapper* SendPayload::GetOutputResourceMapper() { return this; }
// OutputResourceMapper
-FileReference SendPayload::PushFileHandle(const LocalHandle& handle) {
+Status<FileReference> SendPayload::PushFileHandle(const LocalHandle& handle) {
if (handle) {
const int ref = file_handles_.size();
file_handles_.push_back(handle.Get());
@@ -97,7 +97,8 @@
}
}
-FileReference SendPayload::PushFileHandle(const BorrowedHandle& handle) {
+Status<FileReference> SendPayload::PushFileHandle(
+ const BorrowedHandle& handle) {
if (handle) {
const int ref = file_handles_.size();
file_handles_.push_back(handle.Get());
@@ -107,21 +108,21 @@
}
}
-FileReference SendPayload::PushFileHandle(const RemoteHandle& handle) {
+Status<FileReference> SendPayload::PushFileHandle(const RemoteHandle& handle) {
return handle.Get();
}
-ChannelReference SendPayload::PushChannelHandle(
+Status<ChannelReference> SendPayload::PushChannelHandle(
const LocalChannelHandle& /*handle*/) {
- return -1;
+ return ErrorStatus{EOPNOTSUPP};
}
-ChannelReference SendPayload::PushChannelHandle(
+Status<ChannelReference> SendPayload::PushChannelHandle(
const BorrowedChannelHandle& /*handle*/) {
- return -1;
+ return ErrorStatus{EOPNOTSUPP};
}
-ChannelReference SendPayload::PushChannelHandle(
+Status<ChannelReference> SendPayload::PushChannelHandle(
const RemoteChannelHandle& /*handle*/) {
- return -1;
+ return ErrorStatus{EOPNOTSUPP};
}
Status<void> ReceivePayload::Receive(int socket_fd) {
diff --git a/libs/vr/libpdx_uds/private/uds/ipc_helper.h b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
index 00f3490..80530bf 100644
--- a/libs/vr/libpdx_uds/private/uds/ipc_helper.h
+++ b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
@@ -33,13 +33,14 @@
OutputResourceMapper* GetOutputResourceMapper() override;
// OutputResourceMapper
- FileReference PushFileHandle(const LocalHandle& handle) override;
- FileReference PushFileHandle(const BorrowedHandle& handle) override;
- FileReference PushFileHandle(const RemoteHandle& handle) override;
- ChannelReference PushChannelHandle(const LocalChannelHandle& handle) override;
- ChannelReference PushChannelHandle(
+ Status<FileReference> PushFileHandle(const LocalHandle& handle) override;
+ Status<FileReference> PushFileHandle(const BorrowedHandle& handle) override;
+ Status<FileReference> PushFileHandle(const RemoteHandle& handle) override;
+ Status<ChannelReference> PushChannelHandle(
+ const LocalChannelHandle& handle) override;
+ Status<ChannelReference> PushChannelHandle(
const BorrowedChannelHandle& handle) override;
- ChannelReference PushChannelHandle(
+ Status<ChannelReference> PushChannelHandle(
const RemoteChannelHandle& handle) override;
private:
diff --git a/libs/vr/libpdx_uds/private/uds/service_endpoint.h b/libs/vr/libpdx_uds/private/uds/service_endpoint.h
index 3ec8519..2b24f62 100644
--- a/libs/vr/libpdx_uds/private/uds/service_endpoint.h
+++ b/libs/vr/libpdx_uds/private/uds/service_endpoint.h
@@ -39,41 +39,40 @@
~Endpoint() override = default;
uint32_t GetIpcTag() const override { return kIpcTag; }
- int SetService(Service* service) override;
- int SetChannel(int channel_id, Channel* channel) override;
- int CloseChannel(int channel_id) override;
- int ModifyChannelEvents(int channel_id, int clear_mask,
- int set_mask) override;
+ Status<void> SetService(Service* service) override;
+ Status<void> SetChannel(int channel_id, Channel* channel) override;
+ Status<void> CloseChannel(int channel_id) override;
+ Status<void> ModifyChannelEvents(int channel_id, int clear_mask,
+ int set_mask) override;
Status<RemoteChannelHandle> PushChannel(Message* message, int flags,
Channel* channel,
int* channel_id) override;
Status<int> CheckChannel(const Message* message, ChannelReference ref,
Channel** channel) override;
- int DefaultHandleMessage(const MessageInfo& info) override;
- int MessageReceive(Message* message) override;
- int MessageReply(Message* message, int return_code) override;
- int MessageReplyFd(Message* message, unsigned int push_fd) override;
- int MessageReplyChannelHandle(Message* message,
- const LocalChannelHandle& handle) override;
- int MessageReplyChannelHandle(Message* message,
- const BorrowedChannelHandle& handle) override;
- int MessageReplyChannelHandle(Message* message,
- const RemoteChannelHandle& handle) override;
- ssize_t ReadMessageData(Message* message, const iovec* vector,
- size_t vector_length) override;
- ssize_t WriteMessageData(Message* message, const iovec* vector,
- size_t vector_length) override;
- FileReference PushFileHandle(Message* message,
- const LocalHandle& handle) override;
- FileReference PushFileHandle(Message* message,
- const BorrowedHandle& handle) override;
- FileReference PushFileHandle(Message* message,
- const RemoteHandle& handle) override;
- ChannelReference PushChannelHandle(Message* message,
- const LocalChannelHandle& handle) override;
- ChannelReference PushChannelHandle(
+ Status<void> MessageReceive(Message* message) override;
+ Status<void> MessageReply(Message* message, int return_code) override;
+ Status<void> MessageReplyFd(Message* message, unsigned int push_fd) override;
+ Status<void> MessageReplyChannelHandle(
+ Message* message, const LocalChannelHandle& handle) override;
+ Status<void> MessageReplyChannelHandle(
Message* message, const BorrowedChannelHandle& handle) override;
- ChannelReference PushChannelHandle(
+ Status<void> MessageReplyChannelHandle(
+ Message* message, const RemoteChannelHandle& handle) override;
+ Status<size_t> ReadMessageData(Message* message, const iovec* vector,
+ size_t vector_length) override;
+ Status<size_t> WriteMessageData(Message* message, const iovec* vector,
+ size_t vector_length) override;
+ Status<FileReference> PushFileHandle(Message* message,
+ const LocalHandle& handle) override;
+ Status<FileReference> PushFileHandle(Message* message,
+ const BorrowedHandle& handle) override;
+ Status<FileReference> PushFileHandle(Message* message,
+ const RemoteHandle& handle) override;
+ Status<ChannelReference> PushChannelHandle(
+ Message* message, const LocalChannelHandle& handle) override;
+ Status<ChannelReference> PushChannelHandle(
+ Message* message, const BorrowedChannelHandle& handle) override;
+ Status<ChannelReference> PushChannelHandle(
Message* message, const RemoteChannelHandle& handle) override;
LocalHandle GetFileHandle(Message* message, FileReference ref) const override;
LocalChannelHandle GetChannelHandle(Message* message,
@@ -82,15 +81,22 @@
void* AllocateMessageState() override;
void FreeMessageState(void* state) override;
- int Cancel() override;
+ Status<void> Cancel() override;
// Open an endpoint at the given path.
// Second parameter is unused for UDS, but we have it here for compatibility
// in signature with servicefs::Endpoint::Create().
+ // This method uses |endpoint_path| as a relative path to endpoint socket
+ // created by init process.
static std::unique_ptr<Endpoint> Create(const std::string& endpoint_path,
mode_t /*unused_mode*/ = kDefaultMode,
bool blocking = kDefaultBlocking);
+ // Helper method to create an endpoint at the given UDS socket path. This
+ // method physically creates and binds a socket at that path.
+ static std::unique_ptr<Endpoint> CreateAndBindSocket(
+ const std::string& endpoint_path, bool blocking = kDefaultBlocking);
+
int epoll_fd() const { return epoll_fd_.Get(); }
private:
@@ -101,7 +107,8 @@
};
// This class must be instantiated using Create() static methods above.
- Endpoint(const std::string& endpoint_path, bool blocking);
+ Endpoint(const std::string& endpoint_path, bool blocking,
+ bool use_init_socket_fd = true);
Endpoint(const Endpoint&) = delete;
void operator=(const Endpoint&) = delete;
@@ -117,7 +124,7 @@
Status<void> OnNewChannel(LocalHandle channel_fd);
Status<ChannelData*> OnNewChannelLocked(LocalHandle channel_fd,
Channel* channel_state);
- int CloseChannelLocked(int channel_id);
+ Status<void> CloseChannelLocked(int channel_id);
Status<void> ReenableEpollEvent(int fd);
Channel* GetChannelState(int channel_id);
int GetChannelSocketFd(int channel_id);
diff --git a/libs/vr/libpdx_uds/remote_method_tests.cpp b/libs/vr/libpdx_uds/remote_method_tests.cpp
index 9050500..3109753 100644
--- a/libs/vr/libpdx_uds/remote_method_tests.cpp
+++ b/libs/vr/libpdx_uds/remote_method_tests.cpp
@@ -342,87 +342,87 @@
// Test service that encodes/decodes messages from clients.
class TestService : public ServiceBase<TestService> {
public:
- int HandleMessage(Message& message) override {
+ Status<void> HandleMessage(Message& message) override {
switch (message.GetOp()) {
case TestInterface::Add::Opcode:
DispatchRemoteMethod<TestInterface::Add>(*this, &TestService::OnAdd,
message);
- return 0;
+ return {};
case TestInterface::Foo::Opcode:
DispatchRemoteMethod<TestInterface::Foo>(*this, &TestService::OnFoo,
message);
- return 0;
+ return {};
case TestInterface::Concatenate::Opcode:
DispatchRemoteMethod<TestInterface::Concatenate>(
*this, &TestService::OnConcatenate, message);
- return 0;
+ return {};
case TestInterface::SumVector::Opcode:
DispatchRemoteMethod<TestInterface::SumVector>(
*this, &TestService::OnSumVector, message);
- return 0;
+ return {};
case TestInterface::StringLength::Opcode:
DispatchRemoteMethod<TestInterface::StringLength>(
*this, &TestService::OnStringLength, message);
- return 0;
+ return {};
case TestInterface::SendTestType::Opcode:
DispatchRemoteMethod<TestInterface::SendTestType>(
*this, &TestService::OnSendTestType, message);
- return 0;
+ return {};
case TestInterface::SendVector::Opcode:
DispatchRemoteMethod<TestInterface::SendVector>(
*this, &TestService::OnSendVector, message);
- return 0;
+ return {};
case TestInterface::Rot13::Opcode:
DispatchRemoteMethod<TestInterface::Rot13>(*this, &TestService::OnRot13,
message);
- return 0;
+ return {};
case TestInterface::NoArgs::Opcode:
DispatchRemoteMethod<TestInterface::NoArgs>(
*this, &TestService::OnNoArgs, message);
- return 0;
+ return {};
case TestInterface::SendFile::Opcode:
DispatchRemoteMethod<TestInterface::SendFile>(
*this, &TestService::OnSendFile, message);
- return 0;
+ return {};
case TestInterface::GetFile::Opcode:
DispatchRemoteMethod<TestInterface::GetFile>(
*this, &TestService::OnGetFile, message);
- return 0;
+ return {};
case TestInterface::GetTestFdType::Opcode:
DispatchRemoteMethod<TestInterface::GetTestFdType>(
*this, &TestService::OnGetTestFdType, message);
- return 0;
+ return {};
case TestInterface::OpenFiles::Opcode:
DispatchRemoteMethod<TestInterface::OpenFiles>(
*this, &TestService::OnOpenFiles, message);
- return 0;
+ return {};
case TestInterface::ReadFile::Opcode:
DispatchRemoteMethod<TestInterface::ReadFile>(
*this, &TestService::OnReadFile, message);
- return 0;
+ return {};
case TestInterface::PushChannel::Opcode:
DispatchRemoteMethod<TestInterface::PushChannel>(
*this, &TestService::OnPushChannel, message);
- return 0;
+ return {};
case TestInterface::Positive::Opcode:
DispatchRemoteMethod<TestInterface::Positive>(
*this, &TestService::OnPositive, message);
- return 0;
+ return {};
default:
return Service::DefaultHandleMessage(message);
@@ -433,7 +433,8 @@
friend BASE;
TestService()
- : BASE("TestService", Endpoint::Create(TestInterface::kClientPath)) {}
+ : BASE("TestService",
+ Endpoint::CreateAndBindSocket(TestInterface::kClientPath)) {}
int OnAdd(Message&, int a, int b) { return a + b; }
diff --git a/libs/vr/libpdx_uds/service_dispatcher.cpp b/libs/vr/libpdx_uds/service_dispatcher.cpp
index fa98f26..2c52578 100644
--- a/libs/vr/libpdx_uds/service_dispatcher.cpp
+++ b/libs/vr/libpdx_uds/service_dispatcher.cpp
@@ -30,7 +30,7 @@
return;
}
- epoll_fd_.Reset(epoll_create(1)); // Size arg is ignored, but must be > 0.
+ epoll_fd_.Reset(epoll_create1(EPOLL_CLOEXEC));
if (!epoll_fd_) {
ALOGE("Failed to create epoll fd because: %s\n", strerror(errno));
return;
diff --git a/libs/vr/libpdx_uds/service_endpoint.cpp b/libs/vr/libpdx_uds/service_endpoint.cpp
index 7bf753d..6f32867 100644
--- a/libs/vr/libpdx_uds/service_endpoint.cpp
+++ b/libs/vr/libpdx_uds/service_endpoint.cpp
@@ -7,6 +7,9 @@
#include <sys/un.h>
#include <algorithm> // std::min
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+#include <cutils/sockets.h>
#include <pdx/service.h>
#include <uds/channel_manager.h>
#include <uds/client_channel_factory.h>
@@ -19,6 +22,7 @@
using android::pdx::BorrowedChannelHandle;
using android::pdx::BorrowedHandle;
using android::pdx::ChannelReference;
+using android::pdx::ErrorStatus;
using android::pdx::FileReference;
using android::pdx::LocalChannelHandle;
using android::pdx::LocalHandle;
@@ -51,14 +55,14 @@
return true;
}
- FileReference PushFileHandle(BorrowedHandle handle) {
+ Status<FileReference> PushFileHandle(BorrowedHandle handle) {
if (!handle)
return handle.Get();
response.file_descriptors.push_back(std::move(handle));
return response.file_descriptors.size() - 1;
}
- ChannelReference PushChannelHandle(BorrowedChannelHandle handle) {
+ Status<ChannelReference> PushChannelHandle(BorrowedChannelHandle handle) {
if (!handle)
return handle.value();
@@ -70,14 +74,14 @@
response.channels.push_back(std::move(channel_info));
return response.channels.size() - 1;
} else {
- return -1;
+ return ErrorStatus{EINVAL};
}
}
- ChannelReference PushChannelHandle(BorrowedHandle data_fd,
- BorrowedHandle event_fd) {
+ Status<ChannelReference> PushChannelHandle(BorrowedHandle data_fd,
+ BorrowedHandle event_fd) {
if (!data_fd || !event_fd)
- return -1;
+ return ErrorStatus{EINVAL};
ChannelInfo<BorrowedHandle> channel_info;
channel_info.data_fd = std::move(data_fd);
channel_info.event_fd = std::move(event_fd);
@@ -85,8 +89,8 @@
return response.channels.size() - 1;
}
- ssize_t WriteData(const iovec* vector, size_t vector_length) {
- ssize_t size = 0;
+ Status<size_t> WriteData(const iovec* vector, size_t vector_length) {
+ size_t size = 0;
for (size_t i = 0; i < vector_length; i++) {
const auto* data = reinterpret_cast<const uint8_t*>(vector[i].iov_base);
response_data.insert(response_data.end(), data, data + vector[i].iov_len);
@@ -95,9 +99,9 @@
return size;
}
- ssize_t ReadData(const iovec* vector, size_t vector_length) {
+ Status<size_t> ReadData(const iovec* vector, size_t vector_length) {
size_t size_remaining = request_data.size() - request_data_read_pos;
- ssize_t size = 0;
+ size_t size = 0;
for (size_t i = 0; i < vector_length && size_remaining > 0; i++) {
size_t size_to_copy = std::min(size_remaining, vector[i].iov_len);
memcpy(vector[i].iov_base, request_data.data() + request_data_read_pos,
@@ -123,43 +127,50 @@
namespace pdx {
namespace uds {
-Endpoint::Endpoint(const std::string& endpoint_path, bool blocking)
+Endpoint::Endpoint(const std::string& endpoint_path, bool blocking,
+ bool use_init_socket_fd)
: endpoint_path_{ClientChannelFactory::GetEndpointPath(endpoint_path)},
is_blocking_{blocking} {
- LocalHandle fd{socket(AF_UNIX, SOCK_STREAM, 0)};
- if (!fd) {
- ALOGE("Endpoint::Endpoint: Failed to create socket: %s", strerror(errno));
- return;
- }
+ LocalHandle fd;
+ if (use_init_socket_fd) {
+ // Cut off the /dev/socket/ prefix from the full socket path and use the
+ // resulting "name" to retrieve the file descriptor for the socket created
+ // by the init process.
+ constexpr char prefix[] = "/dev/socket/";
+ CHECK(android::base::StartsWith(endpoint_path_, prefix))
+ << "Endpoint::Endpoint: Socket name '" << endpoint_path_
+ << "' must begin with '" << prefix << "'";
+ std::string socket_name = endpoint_path_.substr(sizeof(prefix) - 1);
+ fd.Reset(android_get_control_socket(socket_name.c_str()));
+ CHECK(fd.IsValid())
+ << "Endpoint::Endpoint: Unable to obtain the control socket fd for '"
+ << socket_name << "'";
+ fcntl(fd.Get(), F_SETFD, FD_CLOEXEC);
+ } else {
+ fd.Reset(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0));
+ CHECK(fd.IsValid()) << "Endpoint::Endpoint: Failed to create socket: "
+ << strerror(errno);
- sockaddr_un local;
- local.sun_family = AF_UNIX;
- strncpy(local.sun_path, endpoint_path_.c_str(), sizeof(local.sun_path));
- local.sun_path[sizeof(local.sun_path) - 1] = '\0';
+ sockaddr_un local;
+ local.sun_family = AF_UNIX;
+ strncpy(local.sun_path, endpoint_path_.c_str(), sizeof(local.sun_path));
+ local.sun_path[sizeof(local.sun_path) - 1] = '\0';
- unlink(local.sun_path);
- if (bind(fd.Get(), (struct sockaddr*)&local, sizeof(local)) == -1) {
- ALOGE("Endpoint::Endpoint: bind error: %s", strerror(errno));
- return;
+ unlink(local.sun_path);
+ int ret =
+ bind(fd.Get(), reinterpret_cast<sockaddr*>(&local), sizeof(local));
+ CHECK_EQ(ret, 0) << "Endpoint::Endpoint: bind error: " << strerror(errno);
}
- if (listen(fd.Get(), kMaxBackLogForSocketListen) == -1) {
- ALOGE("Endpoint::Endpoint: listen error: %s", strerror(errno));
- return;
- }
+ CHECK_EQ(listen(fd.Get(), kMaxBackLogForSocketListen), 0)
+ << "Endpoint::Endpoint: listen error: " << strerror(errno);
cancel_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
- if (!cancel_event_fd_) {
- ALOGE("Endpoint::Endpoint: Failed to create event fd: %s\n",
- strerror(errno));
- return;
- }
+ CHECK(cancel_event_fd_.IsValid())
+ << "Endpoint::Endpoint: Failed to create event fd: " << strerror(errno);
- epoll_fd_.Reset(epoll_create(1)); // Size arg is ignored, but must be > 0.
- if (!epoll_fd_) {
- ALOGE("Endpoint::Endpoint: Failed to create epoll fd: %s\n",
- strerror(errno));
- return;
- }
+ epoll_fd_.Reset(epoll_create1(EPOLL_CLOEXEC));
+ CHECK(epoll_fd_.IsValid())
+ << "Endpoint::Endpoint: Failed to create epoll fd: " << strerror(errno);
epoll_event socket_event;
socket_event.events = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT;
@@ -169,16 +180,16 @@
cancel_event.events = EPOLLIN;
cancel_event.data.fd = cancel_event_fd_.Get();
- if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, fd.Get(), &socket_event) < 0 ||
- epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, cancel_event_fd_.Get(),
- &cancel_event) < 0) {
- ALOGE("Endpoint::Endpoint: Failed to add event fd to epoll fd: %s\n",
- strerror(errno));
- cancel_event_fd_.Close();
- epoll_fd_.Close();
- } else {
- socket_fd_ = std::move(fd);
- }
+ int ret = epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, fd.Get(), &socket_event);
+ CHECK_EQ(ret, 0)
+ << "Endpoint::Endpoint: Failed to add socket fd to epoll fd: "
+ << strerror(errno);
+ ret = epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, cancel_event_fd_.Get(),
+ &cancel_event);
+ CHECK_EQ(ret, 0)
+ << "Endpoint::Endpoint: Failed to add cancel event fd to epoll fd: "
+ << strerror(errno);
+ socket_fd_ = std::move(fd);
}
void* Endpoint::AllocateMessageState() { return new MessageState; }
@@ -190,8 +201,9 @@
Status<void> Endpoint::AcceptConnection(Message* message) {
sockaddr_un remote;
socklen_t addrlen = sizeof(remote);
- LocalHandle channel_fd{
- accept(socket_fd_.Get(), reinterpret_cast<sockaddr*>(&remote), &addrlen)};
+ LocalHandle channel_fd{accept4(socket_fd_.Get(),
+ reinterpret_cast<sockaddr*>(&remote), &addrlen,
+ SOCK_CLOEXEC)};
if (!channel_fd) {
ALOGE("Endpoint::AcceptConnection: failed to accept connection: %s",
strerror(errno));
@@ -214,18 +226,18 @@
return status;
}
-int Endpoint::SetService(Service* service) {
+Status<void> Endpoint::SetService(Service* service) {
service_ = service;
- return 0;
+ return {};
}
-int Endpoint::SetChannel(int channel_id, Channel* channel) {
+Status<void> Endpoint::SetChannel(int channel_id, Channel* channel) {
std::lock_guard<std::mutex> autolock(channel_mutex_);
auto channel_data = channels_.find(channel_id);
if (channel_data == channels_.end())
- return -EINVAL;
+ return ErrorStatus{EINVAL};
channel_data->second.channel_state = channel;
- return 0;
+ return {};
}
Status<void> Endpoint::OnNewChannel(LocalHandle channel_fd) {
@@ -269,44 +281,46 @@
return {};
}
-int Endpoint::CloseChannel(int channel_id) {
+Status<void> Endpoint::CloseChannel(int channel_id) {
std::lock_guard<std::mutex> autolock(channel_mutex_);
return CloseChannelLocked(channel_id);
}
-int Endpoint::CloseChannelLocked(int channel_id) {
+Status<void> Endpoint::CloseChannelLocked(int channel_id) {
ALOGD_IF(TRACE, "Endpoint::CloseChannelLocked: channel_id=%d", channel_id);
auto channel_data = channels_.find(channel_id);
if (channel_data == channels_.end())
- return -EINVAL;
+ return ErrorStatus{EINVAL};
- int ret = 0;
+ 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) {
- ret = -errno;
+ status.SetError(errno);
ALOGE(
"Endpoint::CloseChannelLocked: Failed to remove channel from endpoint: "
"%s\n",
strerror(errno));
+ } else {
+ status.SetValue();
}
channels_.erase(channel_data);
- return ret;
+ return status;
}
-int Endpoint::ModifyChannelEvents(int channel_id, int clear_mask,
- int set_mask) {
+Status<void> Endpoint::ModifyChannelEvents(int channel_id, int clear_mask,
+ int set_mask) {
std::lock_guard<std::mutex> autolock(channel_mutex_);
auto search = channels_.find(channel_id);
if (search != channels_.end()) {
auto& channel_data = search->second;
channel_data.event_set.ModifyEvents(clear_mask, set_mask);
- return 0;
+ return {};
}
- return -EINVAL;
+ return ErrorStatus{EINVAL};
}
Status<RemoteChannelHandle> Endpoint::PushChannel(Message* message,
@@ -314,7 +328,7 @@
Channel* channel,
int* channel_id) {
int channel_pair[2] = {};
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, channel_pair) == -1) {
+ if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, channel_pair) == -1) {
ALOGE("Endpoint::PushChannel: Failed to create a socket pair: %s",
strerror(errno));
return ErrorStatus(errno);
@@ -337,17 +351,19 @@
*channel_id = local_socket.Get();
auto channel_data = OnNewChannelLocked(std::move(local_socket), channel);
if (!channel_data)
- return ErrorStatus(channel_data.error());
+ return channel_data.error_status();
// Flags are ignored for now.
// TODO(xiaohuit): Implement those.
auto* state = static_cast<MessageState*>(message->GetState());
- ChannelReference ref = state->PushChannelHandle(
+ Status<ChannelReference> ref = state->PushChannelHandle(
remote_socket.Borrow(),
channel_data.get()->event_set.event_fd().Borrow());
+ if (!ref)
+ return ref.error_status();
state->sockets_to_close.push_back(std::move(remote_socket));
- return RemoteChannelHandle{ref};
+ return RemoteChannelHandle{ref.get()};
}
Status<int> Endpoint::CheckChannel(const Message* /*message*/,
@@ -357,13 +373,6 @@
return ErrorStatus(EFAULT);
}
-int Endpoint::DefaultHandleMessage(const MessageInfo& /* info */) {
- ALOGE(
- "Endpoint::CheckChannel: Not implemented! Endpoint DefaultHandleMessage "
- "does nothing!");
- return 0;
-}
-
Channel* Endpoint::GetChannelState(int channel_id) {
std::lock_guard<std::mutex> autolock(channel_mutex_);
auto channel_data = channels_.find(channel_id);
@@ -464,7 +473,7 @@
*message = Message{info};
}
-int Endpoint::MessageReceive(Message* message) {
+Status<void> Endpoint::MessageReceive(Message* message) {
// Receive at most one event from the epoll set. This should prevent multiple
// dispatch threads from attempting to handle messages on the same socket at
// the same time.
@@ -474,40 +483,36 @@
if (count < 0) {
ALOGE("Endpoint::MessageReceive: Failed to wait for epoll events: %s\n",
strerror(errno));
- return -errno;
+ return ErrorStatus{errno};
} else if (count == 0) {
- return -ETIMEDOUT;
+ return ErrorStatus{ETIMEDOUT};
}
if (event.data.fd == cancel_event_fd_.Get()) {
- return -ESHUTDOWN;
+ return ErrorStatus{ESHUTDOWN};
}
if (event.data.fd == socket_fd_.Get()) {
auto status = AcceptConnection(message);
if (!status)
- return -status.error();
- status = ReenableEpollEvent(socket_fd_.Get());
- return status ? 0 : -status.error();
+ return status;
+ return ReenableEpollEvent(socket_fd_.Get());
}
int channel_id = event.data.fd;
if (event.events & (EPOLLRDHUP | EPOLLHUP)) {
BuildCloseMessage(channel_id, message);
- return 0;
+ return {};
}
- auto status = ReceiveMessageForChannel(channel_id, message);
- if (!status)
- return -status.error();
- return 0;
+ return ReceiveMessageForChannel(channel_id, message);
}
-int Endpoint::MessageReply(Message* message, int return_code) {
+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)
- return -EBADF;
+ return ErrorStatus{EBADF};
auto* state = static_cast<MessageState*>(message->GetState());
switch (message->GetOp()) {
@@ -515,12 +520,17 @@
return CloseChannel(channel_id);
case opcodes::CHANNEL_OPEN:
- if (return_code < 0)
+ if (return_code < 0) {
return CloseChannel(channel_id);
- // Reply with the event fd.
- return_code = state->PushFileHandle(
- BorrowedHandle{GetChannelEventFd(channel_socket)});
- state->response_data.clear(); // Just in case...
+ } else {
+ // Reply with the event fd.
+ auto push_status = state->PushFileHandle(
+ BorrowedHandle{GetChannelEventFd(channel_socket)});
+ state->response_data.clear(); // Just in case...
+ if (!push_status)
+ return push_status.error_status();
+ return_code = push_status.get();
+ }
break;
}
@@ -535,76 +545,82 @@
if (status)
status = ReenableEpollEvent(channel_socket);
- return status ? 0 : -status.error();
+ return status;
}
-int Endpoint::MessageReplyFd(Message* message, unsigned int push_fd) {
+Status<void> Endpoint::MessageReplyFd(Message* message, unsigned int push_fd) {
auto* state = static_cast<MessageState*>(message->GetState());
auto ref = state->PushFileHandle(BorrowedHandle{static_cast<int>(push_fd)});
- return MessageReply(message, ref);
+ if (!ref)
+ return ref.error_status();
+ return MessageReply(message, ref.get());
}
-int Endpoint::MessageReplyChannelHandle(Message* message,
- const LocalChannelHandle& handle) {
+Status<void> Endpoint::MessageReplyChannelHandle(
+ Message* message, const LocalChannelHandle& handle) {
auto* state = static_cast<MessageState*>(message->GetState());
auto ref = state->PushChannelHandle(handle.Borrow());
- return MessageReply(message, ref);
+ if (!ref)
+ return ref.error_status();
+ return MessageReply(message, ref.get());
}
-int Endpoint::MessageReplyChannelHandle(Message* message,
- const BorrowedChannelHandle& handle) {
+Status<void> Endpoint::MessageReplyChannelHandle(
+ Message* message, const BorrowedChannelHandle& handle) {
auto* state = static_cast<MessageState*>(message->GetState());
auto ref = state->PushChannelHandle(handle.Duplicate());
- return MessageReply(message, ref);
+ if (!ref)
+ return ref.error_status();
+ return MessageReply(message, ref.get());
}
-int Endpoint::MessageReplyChannelHandle(Message* message,
- const RemoteChannelHandle& handle) {
+Status<void> Endpoint::MessageReplyChannelHandle(
+ Message* message, const RemoteChannelHandle& handle) {
return MessageReply(message, handle.value());
}
-ssize_t Endpoint::ReadMessageData(Message* message, const iovec* vector,
- size_t vector_length) {
+Status<size_t> Endpoint::ReadMessageData(Message* message, const iovec* vector,
+ size_t vector_length) {
auto* state = static_cast<MessageState*>(message->GetState());
return state->ReadData(vector, vector_length);
}
-ssize_t Endpoint::WriteMessageData(Message* message, const iovec* vector,
- size_t vector_length) {
+Status<size_t> Endpoint::WriteMessageData(Message* message, const iovec* vector,
+ size_t vector_length) {
auto* state = static_cast<MessageState*>(message->GetState());
return state->WriteData(vector, vector_length);
}
-FileReference Endpoint::PushFileHandle(Message* message,
- const LocalHandle& handle) {
+Status<FileReference> Endpoint::PushFileHandle(Message* message,
+ const LocalHandle& handle) {
auto* state = static_cast<MessageState*>(message->GetState());
return state->PushFileHandle(handle.Borrow());
}
-FileReference Endpoint::PushFileHandle(Message* message,
- const BorrowedHandle& handle) {
+Status<FileReference> Endpoint::PushFileHandle(Message* message,
+ const BorrowedHandle& handle) {
auto* state = static_cast<MessageState*>(message->GetState());
return state->PushFileHandle(handle.Duplicate());
}
-FileReference Endpoint::PushFileHandle(Message* /*message*/,
- const RemoteHandle& handle) {
+Status<FileReference> Endpoint::PushFileHandle(Message* /*message*/,
+ const RemoteHandle& handle) {
return handle.Get();
}
-ChannelReference Endpoint::PushChannelHandle(Message* message,
- const LocalChannelHandle& handle) {
+Status<ChannelReference> Endpoint::PushChannelHandle(
+ Message* message, const LocalChannelHandle& handle) {
auto* state = static_cast<MessageState*>(message->GetState());
return state->PushChannelHandle(handle.Borrow());
}
-ChannelReference Endpoint::PushChannelHandle(
+Status<ChannelReference> Endpoint::PushChannelHandle(
Message* message, const BorrowedChannelHandle& handle) {
auto* state = static_cast<MessageState*>(message->GetState());
return state->PushChannelHandle(handle.Duplicate());
}
-ChannelReference Endpoint::PushChannelHandle(
+Status<ChannelReference> Endpoint::PushChannelHandle(
Message* /*message*/, const RemoteChannelHandle& handle) {
return handle.value();
}
@@ -624,8 +640,10 @@
return handle;
}
-int Endpoint::Cancel() {
- return (eventfd_write(cancel_event_fd_.Get(), 1) < 0) ? -errno : 0;
+Status<void> Endpoint::Cancel() {
+ if (eventfd_write(cancel_event_fd_.Get(), 1) < 0)
+ return ErrorStatus{errno};
+ return {};
}
std::unique_ptr<Endpoint> Endpoint::Create(const std::string& endpoint_path,
@@ -634,6 +652,12 @@
return std::unique_ptr<Endpoint>(new Endpoint(endpoint_path, blocking));
}
+std::unique_ptr<Endpoint> Endpoint::CreateAndBindSocket(
+ const std::string& endpoint_path, bool blocking) {
+ return std::unique_ptr<Endpoint>(
+ new Endpoint(endpoint_path, blocking, false));
+}
+
} // namespace uds
} // namespace pdx
} // namespace android
diff --git a/libs/vr/libpdx_uds/service_framework_tests.cpp b/libs/vr/libpdx_uds/service_framework_tests.cpp
index 9e31e82..2943239 100644
--- a/libs/vr/libpdx_uds/service_framework_tests.cpp
+++ b/libs/vr/libpdx_uds/service_framework_tests.cpp
@@ -119,106 +119,106 @@
}
}
- int HandleMessage(Message& message) override {
+ Status<void> HandleMessage(Message& message) override {
switch (message.GetOp()) {
case TEST_OP_GET_SERVICE_ID:
- REPLY_MESSAGE_RETURN(message, service_id_, 0);
+ REPLY_MESSAGE_RETURN(message, service_id_, {});
// Set the test channel to the TestChannel for the current channel. Other
// messages can use this to perform tests.
case TEST_OP_SET_TEST_CHANNEL:
test_channel_ = message.GetChannel<TestChannel>();
- REPLY_MESSAGE_RETURN(message, 0, 0);
+ REPLY_MESSAGE_RETURN(message, 0, {});
// Return the channel id for the current channel.
case TEST_OP_GET_THIS_CHANNEL_ID:
- REPLY_MESSAGE_RETURN(message, message.GetChannelId(), 0);
+ REPLY_MESSAGE_RETURN(message, message.GetChannelId(), {});
// Return the channel id for the test channel.
case TEST_OP_GET_TEST_CHANNEL_ID:
if (test_channel_)
- REPLY_MESSAGE_RETURN(message, test_channel_->channel_id(), 0);
+ REPLY_MESSAGE_RETURN(message, test_channel_->channel_id(), {});
else
- REPLY_ERROR_RETURN(message, ENOENT, 0);
+ REPLY_ERROR_RETURN(message, ENOENT, {});
// Test check channel feature.
case TEST_OP_CHECK_CHANNEL_ID: {
ChannelReference ref = 0;
- if (message.Read(&ref, sizeof(ref)) < static_cast<ssize_t>(sizeof(ref)))
- REPLY_ERROR_RETURN(message, EIO, 0);
+ if (!message.ReadAll(&ref, sizeof(ref)))
+ REPLY_ERROR_RETURN(message, EIO, {});
const Status<int> ret = message.CheckChannel<TestChannel>(ref, nullptr);
- REPLY_MESSAGE_RETURN(message, ret, 0);
+ REPLY_MESSAGE_RETURN(message, ret, {});
}
case TEST_OP_CHECK_CHANNEL_OBJECT: {
std::shared_ptr<TestChannel> channel;
ChannelReference ref = 0;
- if (message.Read(&ref, sizeof(ref)) < static_cast<ssize_t>(sizeof(ref)))
- REPLY_ERROR_RETURN(message, EIO, 0);
+ if (!message.ReadAll(&ref, sizeof(ref)))
+ REPLY_ERROR_RETURN(message, EIO, {});
const Status<int> ret =
message.CheckChannel<TestChannel>(ref, &channel);
if (!ret)
- REPLY_MESSAGE_RETURN(message, ret, 0);
+ REPLY_MESSAGE_RETURN(message, ret, {});
if (channel != nullptr)
- REPLY_MESSAGE_RETURN(message, channel->channel_id(), 0);
+ REPLY_MESSAGE_RETURN(message, channel->channel_id(), {});
else
- REPLY_ERROR_RETURN(message, ENODATA, 0);
+ REPLY_ERROR_RETURN(message, ENODATA, {});
}
case TEST_OP_CHECK_CHANNEL_FROM_OTHER_SERVICE: {
ChannelReference ref = 0;
- if (message.Read(&ref, sizeof(ref)) < static_cast<ssize_t>(sizeof(ref)))
- REPLY_ERROR_RETURN(message, EIO, 0);
+ if (!message.ReadAll(&ref, sizeof(ref)))
+ REPLY_ERROR_RETURN(message, EIO, {});
const Status<int> ret = message.CheckChannel<TestChannel>(
other_service_.get(), ref, nullptr);
- REPLY_MESSAGE_RETURN(message, ret, 0);
+ REPLY_MESSAGE_RETURN(message, ret, {});
}
case TEST_OP_GET_NEW_CHANNEL: {
auto channel = std::make_shared<TestChannel>(-1);
Status<RemoteChannelHandle> channel_handle =
message.PushChannel(0, channel, &channel->channel_id_);
- REPLY_MESSAGE_RETURN(message, channel_handle, 0);
+ REPLY_MESSAGE_RETURN(message, channel_handle, {});
}
case TEST_OP_GET_NEW_CHANNEL_FROM_OTHER_SERVICE: {
if (!other_service_)
- REPLY_ERROR_RETURN(message, EINVAL, 0);
+ REPLY_ERROR_RETURN(message, EINVAL, {});
auto channel = std::make_shared<TestChannel>(-1);
Status<RemoteChannelHandle> channel_handle = message.PushChannel(
other_service_.get(), 0, channel, &channel->channel_id_);
- REPLY_MESSAGE_RETURN(message, channel_handle, 0);
+ REPLY_MESSAGE_RETURN(message, channel_handle, {});
}
case TEST_OP_GET_THIS_PROCESS_ID:
- REPLY_MESSAGE_RETURN(message, message.GetProcessId(), 0);
+ REPLY_MESSAGE_RETURN(message, message.GetProcessId(), {});
case TEST_OP_GET_THIS_THREAD_ID:
- REPLY_MESSAGE_RETURN(message, message.GetThreadId(), 0);
+ REPLY_MESSAGE_RETURN(message, message.GetThreadId(), {});
case TEST_OP_GET_THIS_EUID:
- REPLY_MESSAGE_RETURN(message, message.GetEffectiveUserId(), 0);
+ REPLY_MESSAGE_RETURN(message, message.GetEffectiveUserId(), {});
case TEST_OP_GET_THIS_EGID:
- REPLY_MESSAGE_RETURN(message, message.GetEffectiveGroupId(), 0);
+ REPLY_MESSAGE_RETURN(message, message.GetEffectiveGroupId(), {});
case TEST_OP_POLLIN_FROM_SERVICE:
REPLY_MESSAGE_RETURN(message, message.ModifyChannelEvents(0, EPOLLIN),
- 0);
+ {});
case TEST_OP_SEND_LARGE_DATA_RETURN_SUM: {
std::array<int, kLargeDataSize> data_array;
- ssize_t size_to_read = data_array.size() * sizeof(int);
- ssize_t read = message.Read(data_array.data(), size_to_read);
- if (read < size_to_read)
- REPLY_ERROR_RETURN(message, EIO, 0);
+ size_t size_to_read = data_array.size() * sizeof(int);
+ if (!message.ReadAll(data_array.data(), size_to_read)) {
+ REPLY_ERROR_RETURN(message, EIO, {});
+ }
int sum = std::accumulate(data_array.begin(), data_array.end(), 0);
- REPLY_MESSAGE_RETURN(message, sum, 0);
+ REPLY_MESSAGE_RETURN(message, sum, {});
}
default:
@@ -245,7 +245,7 @@
TestService(const std::string& name,
const std::shared_ptr<TestService>& other_service, bool blocking)
: BASE(std::string("TestService") + name,
- Endpoint::Create(kTestServicePath + name, blocking)),
+ Endpoint::CreateAndBindSocket(kTestServicePath + name, blocking)),
other_service_(other_service),
service_id_(service_counter_++) {}
@@ -300,7 +300,7 @@
// Returns the channel id of the channel.
int CheckChannelIdArgument(BorrowedChannelHandle channel) {
Transaction trans{*this};
- ChannelReference ref = trans.PushChannelHandle(channel);
+ ChannelReference ref = trans.PushChannelHandle(channel).get();
return ReturnStatusOrError(trans.Send<int>(TEST_OP_CHECK_CHANNEL_ID, &ref,
sizeof(ref), nullptr, 0));
}
@@ -309,7 +309,7 @@
// Returns the channel id of the channel exercising the context pointer.
int CheckChannelObjectArgument(BorrowedChannelHandle channel) {
Transaction trans{*this};
- ChannelReference ref = trans.PushChannelHandle(channel);
+ ChannelReference ref = trans.PushChannelHandle(channel).get();
return ReturnStatusOrError(trans.Send<int>(TEST_OP_CHECK_CHANNEL_OBJECT,
&ref, sizeof(ref), nullptr, 0));
}
@@ -318,7 +318,7 @@
// Returns 0 on success.
int CheckChannelFromOtherService(BorrowedChannelHandle channel) {
Transaction trans{*this};
- ChannelReference ref = trans.PushChannelHandle(channel);
+ ChannelReference ref = trans.PushChannelHandle(channel).get();
return ReturnStatusOrError(
trans.Send<int>(TEST_OP_CHECK_CHANNEL_FROM_OTHER_SERVICE, &ref,
sizeof(ref), nullptr, 0));
diff --git a/libs/vr/libposepredictor/include/polynomial_predictor.h b/libs/vr/libposepredictor/include/polynomial_predictor.h
index 762afd3..4b8d51b 100644
--- a/libs/vr/libposepredictor/include/polynomial_predictor.h
+++ b/libs/vr/libposepredictor/include/polynomial_predictor.h
@@ -19,7 +19,7 @@
public:
PolynomialPosePredictor(real regularization = 1e-9)
: BufferedPredictor(TrainingWindow), regularization_(regularization) {
- static_assert(PolynomialDegree + 1 >= TrainingWindow,
+ static_assert(TrainingWindow >= PolynomialDegree + 1,
"Underconstrained polynomial regressor");
}
diff --git a/libs/vr/libposepredictor/predictor.cpp b/libs/vr/libposepredictor/predictor.cpp
index 4d2eafd..beba156 100644
--- a/libs/vr/libposepredictor/predictor.cpp
+++ b/libs/vr/libposepredictor/predictor.cpp
@@ -5,7 +5,7 @@
namespace posepredictor {
vec3 Predictor::AngularVelocity(const quat& a, const quat& b, real delta_time) {
- const auto delta_q = b.inverse() * a;
+ const auto delta_q = a.inverse() * b;
// Check that delta_q.w() == 1, Eigen doesn't respect this convention. If
// delta_q.w() == -1, we'll get the opposite velocity.
return 2.0 * (delta_q.w() < 0 ? static_cast<vec3>(-delta_q.vec()) : delta_q.vec()) / delta_time;
diff --git a/libs/vr/libvrflinger/display_manager_service.cpp b/libs/vr/libvrflinger/display_manager_service.cpp
index e07901d..49b6f09 100644
--- a/libs/vr/libvrflinger/display_manager_service.cpp
+++ b/libs/vr/libvrflinger/display_manager_service.cpp
@@ -32,12 +32,12 @@
namespace dvr {
void DisplayManager::SetNotificationsPending(bool pending) {
- int ret = service_->ModifyChannelEvents(channel_id_, pending ? 0 : POLLIN,
- pending ? POLLIN : 0);
- ALOGE_IF(ret < 0,
+ auto status = service_->ModifyChannelEvents(channel_id_, pending ? 0 : POLLIN,
+ pending ? POLLIN : 0);
+ ALOGE_IF(!status,
"DisplayManager::SetNotificationPending: Failed to modify channel "
"events: %s",
- strerror(-ret));
+ status.GetErrorMessage().c_str());
}
DisplayManagerService::DisplayManagerService(
@@ -68,24 +68,24 @@
display_manager_ = nullptr;
}
-int DisplayManagerService::HandleMessage(pdx::Message& message) {
+pdx::Status<void> DisplayManagerService::HandleMessage(pdx::Message& message) {
auto channel = std::static_pointer_cast<DisplayManager>(message.GetChannel());
switch (message.GetOp()) {
case DisplayManagerRPC::GetSurfaceList::Opcode:
DispatchRemoteMethod<DisplayManagerRPC::GetSurfaceList>(
*this, &DisplayManagerService::OnGetSurfaceList, message);
- return 0;
+ return {};
case DisplayManagerRPC::UpdateSurfaces::Opcode:
DispatchRemoteMethod<DisplayManagerRPC::UpdateSurfaces>(
*this, &DisplayManagerService::OnUpdateSurfaces, message);
- return 0;
+ return {};
case DisplayManagerRPC::SetupPoseBuffer::Opcode:
DispatchRemoteMethod<DisplayManagerRPC::SetupPoseBuffer>(
*this, &DisplayManagerService::OnSetupPoseBuffer, message);
- return 0;
+ return {};
default:
return Service::DefaultHandleMessage(message);
@@ -189,7 +189,7 @@
}
pdx::BorrowedChannelHandle DisplayManagerService::OnSetupPoseBuffer(
- pdx::Message& message, size_t extended_region_size, int usage) {
+ pdx::Message& /*message*/, size_t extended_region_size, int usage) {
return display_service_->SetupPoseBuffer(extended_region_size, usage);
}
diff --git a/libs/vr/libvrflinger/display_manager_service.h b/libs/vr/libvrflinger/display_manager_service.h
index 19098c2..80324fd 100644
--- a/libs/vr/libvrflinger/display_manager_service.h
+++ b/libs/vr/libvrflinger/display_manager_service.h
@@ -42,7 +42,7 @@
std::shared_ptr<pdx::Channel> OnChannelOpen(pdx::Message& message) override;
void OnChannelClose(pdx::Message& message,
const std::shared_ptr<pdx::Channel>& channel) override;
- int HandleMessage(pdx::Message& message) override;
+ pdx::Status<void> HandleMessage(pdx::Message& message) override;
private:
friend BASE;
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index c079187..3750ea3 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -65,39 +65,39 @@
// First-level dispatch for display service messages. Directly handles messages
// that are independent of the display surface (metrics, creation) and routes
// surface-specific messages to the per-instance handlers.
-int DisplayService::HandleMessage(pdx::Message& message) {
+pdx::Status<void> DisplayService::HandleMessage(pdx::Message& message) {
auto channel = message.GetChannel<SurfaceChannel>();
switch (message.GetOp()) {
case DisplayRPC::GetMetrics::Opcode:
DispatchRemoteMethod<DisplayRPC::GetMetrics>(
*this, &DisplayService::OnGetMetrics, message);
- return 0;
+ return {};
case DisplayRPC::GetEdsCapture::Opcode:
DispatchRemoteMethod<DisplayRPC::GetEdsCapture>(
*this, &DisplayService::OnGetEdsCapture, message);
- return 0;
+ return {};
case DisplayRPC::CreateSurface::Opcode:
DispatchRemoteMethod<DisplayRPC::CreateSurface>(
*this, &DisplayService::OnCreateSurface, message);
- return 0;
+ return {};
case DisplayRPC::SetViewerParams::Opcode:
DispatchRemoteMethod<DisplayRPC::SetViewerParams>(
*this, &DisplayService::OnSetViewerParams, message);
- return 0;
+ return {};
case DisplayRPC::GetPoseBuffer::Opcode:
DispatchRemoteMethod<DisplayRPC::GetPoseBuffer>(
*this, &DisplayService::OnGetPoseBuffer, message);
- return 0;
+ return {};
case DisplayRPC::IsVrAppRunning::Opcode:
DispatchRemoteMethod<DisplayRPC::IsVrAppRunning>(
*this, &DisplayService::IsVrAppRunning, message);
- return 0;
+ return {};
// Direct the surface specific messages to the surface instance.
case DisplayRPC::CreateBufferQueue::Opcode:
@@ -265,7 +265,7 @@
// Calls the message handler for the DisplaySurface associated with this
// channel.
-int DisplayService::HandleSurfaceMessage(pdx::Message& message) {
+pdx::Status<void> DisplayService::HandleSurfaceMessage(pdx::Message& message) {
auto surface = std::static_pointer_cast<SurfaceChannel>(message.GetChannel());
ALOGW_IF(!surface,
"DisplayService::HandleSurfaceMessage: surface is nullptr!");
@@ -273,7 +273,7 @@
if (surface)
return surface->HandleMessage(message);
else
- REPLY_ERROR_RETURN(message, EINVAL, 0);
+ REPLY_ERROR_RETURN(message, EINVAL, {});
}
std::shared_ptr<DisplaySurface> DisplayService::GetDisplaySurface(
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index 8e96172..da80a84 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -27,7 +27,7 @@
void OnChannelClose(pdx::Message& message,
const std::shared_ptr<pdx::Channel>& channel) override;
- int HandleMessage(pdx::Message& message) override;
+ pdx::Status<void> HandleMessage(pdx::Message& message) override;
std::shared_ptr<DisplaySurface> GetDisplaySurface(int surface_id) const;
std::vector<std::shared_ptr<DisplaySurface>> GetDisplaySurfaces() const;
@@ -94,7 +94,7 @@
// the display manager should be notified.
void NotifyDisplayConfigurationUpdate();
- int HandleSurfaceMessage(pdx::Message& message);
+ pdx::Status<void> HandleSurfaceMessage(pdx::Message& message);
DisplayService(const DisplayService&) = delete;
void operator=(const DisplayService&) = delete;
diff --git a/libs/vr/libvrflinger/display_surface.cpp b/libs/vr/libvrflinger/display_surface.cpp
index 66e9925..a7220fe 100644
--- a/libs/vr/libvrflinger/display_surface.cpp
+++ b/libs/vr/libvrflinger/display_surface.cpp
@@ -206,7 +206,7 @@
return !acquired_buffers_.IsEmpty();
}
-int DisplaySurface::HandleMessage(pdx::Message& message) {
+pdx::Status<void> DisplaySurface::HandleMessage(pdx::Message& message) {
switch (message.GetOp()) {
case DisplayRPC::SetAttributes::Opcode:
DispatchRemoteMethod<DisplayRPC::SetAttributes>(
@@ -227,7 +227,7 @@
return SurfaceChannel::HandleMessage(message);
}
- return 0;
+ return {};
}
int DisplaySurface::OnClientSetAttributes(
@@ -301,7 +301,7 @@
pdx::Message& message) {
if (flags_ & DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION) {
ALOGE(
- "DisplaySurface::OnCreateVideoMeshSurface: system distorion is "
+ "DisplaySurface::OnCreateVideoMeshSurface: system distortion is "
"disabled on this display surface, cannot create VideoMeshSurface on "
"top of it.");
REPLY_ERROR_RETURN(message, EINVAL, {});
@@ -309,22 +309,21 @@
int channel_id;
auto status = message.PushChannel(0, nullptr, &channel_id);
-
if (!status) {
ALOGE(
"DisplaySurface::OnCreateVideoMeshSurface: failed to push channel: %s",
status.GetErrorMessage().c_str());
- REPLY_ERROR_RETURN(message, ENOMEM, {});
+ REPLY_ERROR_RETURN(message, status.error(), {});
}
auto surface = std::make_shared<VideoMeshSurface>(service(), channel_id);
- const int ret = service()->SetChannel(channel_id, surface);
- if (ret < 0) {
+ auto channel_status = service()->SetChannel(channel_id, surface);
+ if (!channel_status) {
ALOGE(
"DisplaySurface::OnCreateVideoMeshSurface: failed to set new video "
"mesh surface channel: %s",
- strerror(-ret));
- REPLY_ERROR_RETURN(message, ENOMEM, {});
+ channel_status.GetErrorMessage().c_str());
+ REPLY_ERROR_RETURN(message, channel_status.error(), {});
}
{
diff --git a/libs/vr/libvrflinger/display_surface.h b/libs/vr/libvrflinger/display_surface.h
index d31a3a9..2e4cf75 100644
--- a/libs/vr/libvrflinger/display_surface.h
+++ b/libs/vr/libvrflinger/display_surface.h
@@ -106,7 +106,7 @@
// Dispatches display surface messages to the appropriate handlers. This
// handler runs on the displayd message dispatch thread.
- int HandleMessage(pdx::Message& message) override;
+ pdx::Status<void> HandleMessage(pdx::Message& message) override;
// Sets display surface's client-controlled attributes.
int OnClientSetAttributes(pdx::Message& message,
diff --git a/libs/vr/libvrflinger/screenshot_service.cpp b/libs/vr/libvrflinger/screenshot_service.cpp
index fd1c582..d14d588 100644
--- a/libs/vr/libvrflinger/screenshot_service.cpp
+++ b/libs/vr/libvrflinger/screenshot_service.cpp
@@ -19,17 +19,17 @@
ScreenshotService::~ScreenshotService() { instance_ = nullptr; }
-int ScreenshotService::HandleMessage(pdx::Message& message) {
+pdx::Status<void> ScreenshotService::HandleMessage(pdx::Message& message) {
switch (message.GetOp()) {
case DisplayScreenshotRPC::GetFormat::Opcode:
DispatchRemoteMethod<DisplayScreenshotRPC::GetFormat>(
*this, &ScreenshotService::OnGetFormat, message);
- return 0;
+ return {};
case DisplayScreenshotRPC::TakeScreenshot::Opcode:
DispatchRemoteMethod<DisplayScreenshotRPC::TakeScreenshot>(
*this, &ScreenshotService::OnTakeScreenshot, message);
- return 0;
+ return {};
default:
return Service::HandleMessage(message);
diff --git a/libs/vr/libvrflinger/screenshot_service.h b/libs/vr/libvrflinger/screenshot_service.h
index ec4c527..f59e872 100644
--- a/libs/vr/libvrflinger/screenshot_service.h
+++ b/libs/vr/libvrflinger/screenshot_service.h
@@ -38,7 +38,7 @@
public:
~ScreenshotService();
- int HandleMessage(pdx::Message& message) override;
+ pdx::Status<void> HandleMessage(pdx::Message& message) override;
// Returns true if there is a pending screenshot request.
bool IsScreenshotRequestPending() const {
diff --git a/libs/vr/libvrflinger/surface_channel.cpp b/libs/vr/libvrflinger/surface_channel.cpp
index 8aa220b..263b382 100644
--- a/libs/vr/libvrflinger/surface_channel.cpp
+++ b/libs/vr/libvrflinger/surface_channel.cpp
@@ -7,7 +7,7 @@
namespace android {
namespace dvr {
-int SurfaceChannel::HandleMessage(Message& message) {
+pdx::Status<void> SurfaceChannel::HandleMessage(Message& message) {
switch (message.GetOp()) {
case DisplayRPC::GetMetadataBuffer::Opcode:
DispatchRemoteMethod<DisplayRPC::GetMetadataBuffer>(
@@ -15,7 +15,7 @@
break;
}
- return 0;
+ return {};
}
BorrowedChannelHandle SurfaceChannel::OnGetMetadataBuffer(Message& message) {
diff --git a/libs/vr/libvrflinger/surface_channel.h b/libs/vr/libvrflinger/surface_channel.h
index 870e1a4..bb6b1c5 100644
--- a/libs/vr/libvrflinger/surface_channel.h
+++ b/libs/vr/libvrflinger/surface_channel.h
@@ -33,7 +33,7 @@
// Dispatches surface channel messages to the appropriate handlers. This
// handler runs on the displayd message dispatch thread.
- virtual int HandleMessage(pdx::Message& message);
+ virtual pdx::Status<void> HandleMessage(pdx::Message& message);
protected:
// Contains the surface metadata.
diff --git a/libs/vr/libvrflinger/video_mesh_surface.cpp b/libs/vr/libvrflinger/video_mesh_surface.cpp
index a961a3d..d915a4a 100644
--- a/libs/vr/libvrflinger/video_mesh_surface.cpp
+++ b/libs/vr/libvrflinger/video_mesh_surface.cpp
@@ -14,7 +14,7 @@
VideoMeshSurface::~VideoMeshSurface() {}
-int VideoMeshSurface::HandleMessage(Message& message) {
+pdx::Status<void> VideoMeshSurface::HandleMessage(Message& message) {
ATRACE_NAME("VideoMeshSurface::HandleMessage");
switch (message.GetOp()) {
@@ -27,7 +27,7 @@
return SurfaceChannel::HandleMessage(message);
}
- return 0;
+ return {};
}
std::shared_ptr<ConsumerQueue> VideoMeshSurface::GetConsumerQueue() {
diff --git a/libs/vr/libvrflinger/video_mesh_surface.h b/libs/vr/libvrflinger/video_mesh_surface.h
index 1370793..2c9f3e8 100644
--- a/libs/vr/libvrflinger/video_mesh_surface.h
+++ b/libs/vr/libvrflinger/video_mesh_surface.h
@@ -12,7 +12,7 @@
// VideoMeshSurface takes three inputs: 1) buffers filled by Android system
// components (e.g. MediaCodec or camera stack) other than applications' GL
-// context; 2) a 3D mesh choosen by application to define the shape of the
+// context; 2) a 3D mesh chosen by application to define the shape of the
// surface; 3) a transformation matrix from application to define the rotation,
// position, and scaling of the video surface.
class VideoMeshSurface : public SurfaceChannel {
@@ -33,7 +33,7 @@
}
}
- int HandleMessage(Message& message) override;
+ pdx::Status<void> HandleMessage(Message& message) override;
std::shared_ptr<ConsumerQueue> GetConsumerQueue();
diff --git a/libs/vr/libvrflinger/vsync_service.cpp b/libs/vr/libvrflinger/vsync_service.cpp
index 48fa2c2..612b9b2 100644
--- a/libs/vr/libvrflinger/vsync_service.cpp
+++ b/libs/vr/libvrflinger/vsync_service.cpp
@@ -107,26 +107,26 @@
}
}
-int VSyncService::HandleMessage(pdx::Message& message) {
+pdx::Status<void> VSyncService::HandleMessage(pdx::Message& message) {
switch (message.GetOp()) {
case DisplayVSyncRPC::Wait::Opcode:
AddWaiter(message);
- return 0;
+ return {};
case DisplayVSyncRPC::GetLastTimestamp::Opcode:
DispatchRemoteMethod<DisplayVSyncRPC::GetLastTimestamp>(
*this, &VSyncService::OnGetLastTimestamp, message);
- return 0;
+ return {};
case DisplayVSyncRPC::GetSchedInfo::Opcode:
DispatchRemoteMethod<DisplayVSyncRPC::GetSchedInfo>(
*this, &VSyncService::OnGetSchedInfo, message);
- return 0;
+ return {};
case DisplayVSyncRPC::Acknowledge::Opcode:
DispatchRemoteMethod<DisplayVSyncRPC::Acknowledge>(
*this, &VSyncService::OnAcknowledge, message);
- return 0;
+ return {};
default:
return Service::HandleMessage(message);
diff --git a/libs/vr/libvrflinger/vsync_service.h b/libs/vr/libvrflinger/vsync_service.h
index ba1d4df..1c86d42 100644
--- a/libs/vr/libvrflinger/vsync_service.h
+++ b/libs/vr/libvrflinger/vsync_service.h
@@ -56,7 +56,7 @@
public:
~VSyncService() override;
- int HandleMessage(pdx::Message& message) override;
+ pdx::Status<void> HandleMessage(pdx::Message& message) override;
std::shared_ptr<pdx::Channel> OnChannelOpen(pdx::Message& message) override;
void OnChannelClose(pdx::Message& message,
diff --git a/libs/vr/libvrsensor/Android.bp b/libs/vr/libvrsensor/Android.bp
index 6d48f18..d59182e 100644
--- a/libs/vr/libvrsensor/Android.bp
+++ b/libs/vr/libvrsensor/Android.bp
@@ -15,6 +15,7 @@
sourceFiles = [
"pose_client.cpp",
"sensor_client.cpp",
+ "latency_model.cpp",
]
includeFiles = [
diff --git a/libs/vr/libvrsensor/include/private/dvr/latency_model.h b/libs/vr/libvrsensor/include/private/dvr/latency_model.h
new file mode 100644
index 0000000..1bb3c4f
--- /dev/null
+++ b/libs/vr/libvrsensor/include/private/dvr/latency_model.h
@@ -0,0 +1,31 @@
+#ifndef ANDROID_DVR_LATENCY_MODEL_H_
+#define ANDROID_DVR_LATENCY_MODEL_H_
+
+#include <vector>
+
+namespace android {
+namespace dvr {
+
+// This class holds a rolling average of the sensor latency.
+class LatencyModel {
+ public:
+ LatencyModel(size_t window_size, double weight_mass_in_window);
+ ~LatencyModel() = default;
+
+ void AddLatency(int64_t latency_ns);
+ int64_t CurrentLatencyEstimate() const {
+ return static_cast<int64_t>(rolling_average_);
+ }
+
+ private:
+ // The rolling average of the latencies.
+ double rolling_average_ = 0;
+
+ // The alpha parameter for an exponential moving average.
+ double alpha_;
+};
+
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_DVR_LATENCY_MODEL_H_
diff --git a/libs/vr/libvrsensor/latency_model.cpp b/libs/vr/libvrsensor/latency_model.cpp
new file mode 100644
index 0000000..8233889
--- /dev/null
+++ b/libs/vr/libvrsensor/latency_model.cpp
@@ -0,0 +1,33 @@
+#include <private/dvr/latency_model.h>
+
+#include <cmath>
+
+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));
+}
+
+void LatencyModel::AddLatency(int64_t latency_ns) {
+ rolling_average_ = latency_ns * alpha_ + rolling_average_ * (1 - alpha_);
+}
+
+} // namespace dvr
+} // namespace android
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/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/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 9f0c889..76baa01 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -66,9 +66,6 @@
LOCAL_CFLAGS += -fvisibility=hidden -Werror=format
-LOCAL_HEADER_LIBRARIES := \
- android.hardware.configstore-utils
-
LOCAL_STATIC_LIBRARIES := \
libhwcomposer-command-buffer \
libtrace_proto \
@@ -81,6 +78,7 @@
android.hardware.graphics.allocator@2.0 \
android.hardware.graphics.composer@2.1 \
android.hardware.configstore@1.0 \
+ android.hardware.configstore-utils \
libcutils \
liblog \
libdl \
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index c3b48ca..976455e 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),
@@ -111,8 +113,10 @@
mLayerStack(NO_LAYER_STACK),
mOrientation(),
mPowerMode(HWC_POWER_MODE_OFF),
- mActiveConfig(0)
+ mActiveConfig(0),
+ mDisplayHasWideColor(supportWideColor)
{
+ // clang-format on
Surface* surface;
mNativeWindow = surface = new Surface(producer, false);
ANativeWindow* const window = mNativeWindow.get();
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/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 16d8160..c211c7b 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1011,6 +1011,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 +1175,9 @@
RenderEngine& engine(mFlinger->getRenderEngine());
engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), getAlpha());
+#ifdef USE_HWC2
+ engine.setSourceDataSpace(mCurrentState.dataSpace);
+#endif
engine.drawMesh(mMesh);
engine.disableBlending();
}
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 406e611..413051d 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,71 @@
#include "Mesh.h"
#include "Texture.h"
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <configstore/Utils.h>
+
+#include <fstream>
+
+static constexpr bool outputDebugPPMs = false;
+
+// ---------------------------------------------------------------------------
+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;
+}
+
+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());
+}
+
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
@@ -59,6 +129,26 @@
GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData);
//mColorBlindnessCorrection = M;
+
+ // 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;
+ }
}
GLES20RenderEngine::~GLES20RenderEngine() {
@@ -170,6 +260,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 +368,6 @@
void GLES20RenderEngine::drawMesh(const Mesh& mesh) {
- ProgramCache::getInstance().useProgram(mState);
-
if (mesh.getTexCoordsSize()) {
glEnableVertexAttribArray(Program::texCoords);
glVertexAttribPointer(Program::texCoords,
@@ -259,7 +383,26 @@
mesh.getByteStride(),
mesh.getPositions());
- glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
+ 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());
+ }
if (mesh.getTexCoordsSize()) {
glDisableVertexAttribArray(Program::texCoords);
@@ -268,6 +411,11 @@
void GLES20RenderEngine::dump(String8& result) {
RenderEngine::dump(result);
+ if (usesWideColor()) {
+ result.append("Wide-color: On\n");
+ } else {
+ result.append("Wide-color: Off\n");
+ }
}
// ---------------------------------------------------------------------------
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..26baaae 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];
@@ -867,13 +872,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 +884,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 +907,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);
}
@@ -1144,10 +1149,30 @@
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());
+
+ 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, disp, 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);
} else {
auto type = DisplayDevice::DISPLAY_EXTERNAL;
Mutex::Autolock _l(mStateLock);
@@ -1591,6 +1616,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 +1719,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 +1731,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;
@@ -1950,10 +2024,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);
@@ -2369,6 +2444,10 @@
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());
@@ -3014,7 +3093,6 @@
int currentMode = hw->getPowerMode();
if (mode == currentMode) {
- ALOGD("Screen type=%d is already mode=%d", hw->getDisplayType(), mode);
return;
}
@@ -3171,6 +3249,12 @@
dumpFrameEventsLocked(result);
dumpAll = false;
}
+
+ if ((index < numArgs) && (args[index] == String16("--wide-color"))) {
+ index++;
+ dumpWideColorInfo(result);
+ dumpAll = false;
+ }
}
if (dumpAll) {
@@ -3341,6 +3425,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 +3481,9 @@
appendGuiConfigString(result);
result.append("\n");
+ result.append("\nWide-Color information:\n");
+ dumpWideColorInfo(result);
+
colorizer.bold(result);
result.append("Sync configuration: ");
colorizer.reset(result);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 4ecbddd..46121cf 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";
}
@@ -472,6 +479,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 +535,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.rc b/services/surfaceflinger/surfaceflinger.rc
index 0b482f7..41b6225 100644
--- a/services/surfaceflinger/surfaceflinger.rc
+++ b/services/surfaceflinger/surfaceflinger.rc
@@ -4,3 +4,7 @@
group graphics drmrpc readproc
onrestart restart zygote
writepid /dev/stune/foreground/tasks
+ socket pdx/system/vr/display/client stream 0666 system graphics
+ socket pdx/system/vr/display/manager stream 0660 system graphics
+ socket pdx/system/vr/display/screenshot stream 0660 system graphics
+ socket pdx/system/vr/display/vsync stream 0666 system graphics
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 80efcf8..de4950e 100644
--- a/services/vr/bufferhubd/buffer_hub.cpp
+++ b/services/vr/bufferhubd/buffer_hub.cpp
@@ -189,7 +189,7 @@
channel->HandleImpulse(message);
}
-int BufferHubService::HandleMessage(Message& message) {
+pdx::Status<void> BufferHubService::HandleMessage(Message& message) {
ATRACE_NAME("BufferHubService::HandleMessage");
auto channel = message.GetChannel<BufferHubChannel>();
@@ -207,22 +207,22 @@
case BufferHubRPC::CreateBuffer::Opcode:
DispatchRemoteMethod<BufferHubRPC::CreateBuffer>(
*this, &BufferHubService::OnCreateBuffer, message);
- return 0;
+ return {};
case BufferHubRPC::CreatePersistentBuffer::Opcode:
DispatchRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
*this, &BufferHubService::OnCreatePersistentBuffer, message);
- return 0;
+ return {};
case BufferHubRPC::GetPersistentBuffer::Opcode:
DispatchRemoteMethod<BufferHubRPC::GetPersistentBuffer>(
*this, &BufferHubService::OnGetPersistentBuffer, message);
- return 0;
+ return {};
case BufferHubRPC::CreateProducerQueue::Opcode:
DispatchRemoteMethod<BufferHubRPC::CreateProducerQueue>(
*this, &BufferHubService::OnCreateProducerQueue, message);
- return 0;
+ return {};
default:
return DefaultHandleMessage(message);
@@ -438,11 +438,11 @@
"BufferHubChannel::SignalAvailable: channel_id=%d buffer_id=%d",
channel_id(), buffer_id());
if (!IsDetached()) {
- const int ret = service_->ModifyChannelEvents(channel_id_, 0, POLLIN);
- ALOGE_IF(ret < 0,
+ const auto status = service_->ModifyChannelEvents(channel_id_, 0, POLLIN);
+ ALOGE_IF(!status,
"BufferHubChannel::SignalAvailable: failed to signal availability "
"channel_id=%d: %s",
- channel_id_, strerror(-ret));
+ channel_id_, status.GetErrorMessage().c_str());
} else {
ALOGD_IF(TRACE, "BufferHubChannel::SignalAvailable: detached buffer.");
}
@@ -454,11 +454,11 @@
"BufferHubChannel::ClearAvailable: channel_id=%d buffer_id=%d",
channel_id(), buffer_id());
if (!IsDetached()) {
- const int ret = service_->ModifyChannelEvents(channel_id_, POLLIN, 0);
- ALOGE_IF(ret < 0,
+ const auto status = service_->ModifyChannelEvents(channel_id_, POLLIN, 0);
+ ALOGE_IF(!status,
"BufferHubChannel::ClearAvailable: failed to clear availability "
"channel_id=%d: %s",
- channel_id_, strerror(-ret));
+ channel_id_, status.GetErrorMessage().c_str());
} else {
ALOGD_IF(TRACE, "BufferHubChannel::ClearAvailable: detached buffer.");
}
@@ -469,11 +469,11 @@
ALOGD_IF(TRACE, "BufferHubChannel::Hangup: channel_id=%d buffer_id=%d",
channel_id(), buffer_id());
if (!IsDetached()) {
- const int ret = service_->ModifyChannelEvents(channel_id_, 0, POLLHUP);
+ const auto status = service_->ModifyChannelEvents(channel_id_, 0, POLLHUP);
ALOGE_IF(
- ret < 0,
+ !status,
"BufferHubChannel::Hangup: failed to signal hangup channel_id=%d: %s",
- channel_id_, strerror(-ret));
+ channel_id_, status.GetErrorMessage().c_str());
} else {
ALOGD_IF(TRACE, "BufferHubChannel::Hangup: detached buffer.");
}
diff --git a/services/vr/bufferhubd/buffer_hub.h b/services/vr/bufferhubd/buffer_hub.h
index 28cb468..8a7dca8 100644
--- a/services/vr/bufferhubd/buffer_hub.h
+++ b/services/vr/bufferhubd/buffer_hub.h
@@ -141,7 +141,7 @@
BufferHubService();
~BufferHubService() override;
- int HandleMessage(pdx::Message& message) override;
+ pdx::Status<void> HandleMessage(pdx::Message& message) override;
void HandleImpulse(pdx::Message& message) override;
void OnChannelClose(pdx::Message& message,
diff --git a/services/vr/bufferhubd/bufferhubd.rc b/services/vr/bufferhubd/bufferhubd.rc
index 65b7293..8d57723 100644
--- a/services/vr/bufferhubd/bufferhubd.rc
+++ b/services/vr/bufferhubd/bufferhubd.rc
@@ -3,4 +3,4 @@
user system
group system
writepid /dev/cpuset/tasks
-
+ socket pdx/system/buffer_hub/client stream 0660 system system
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index 43010b0..903d174 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -161,12 +161,12 @@
auto consumer = std::make_shared<ConsumerChannel>(
service(), buffer_id(), channel_id, shared_from_this());
- const int ret = service()->SetChannel(channel_id, consumer);
- if (ret < 0) {
+ const auto channel_status = service()->SetChannel(channel_id, consumer);
+ if (!channel_status) {
ALOGE(
"ProducerChannel::CreateConsumer: failed to set new consumer channel: "
"%s",
- strerror(-ret));
+ channel_status.GetErrorMessage().c_str());
return RemoteChannelHandle();
}
diff --git a/services/vr/bufferhubd/producer_queue_channel.cpp b/services/vr/bufferhubd/producer_queue_channel.cpp
index 08f1e9d..7952642 100644
--- a/services/vr/bufferhubd/producer_queue_channel.cpp
+++ b/services/vr/bufferhubd/producer_queue_channel.cpp
@@ -97,18 +97,18 @@
"ProducerQueueChannel::OnCreateConsumerQueue: failed to push consumer "
"channel: %s",
status.GetErrorMessage().c_str());
- REPLY_ERROR_RETURN(message, ENOMEM, {});
+ REPLY_ERROR_RETURN(message, status.error(), {});
}
- const int ret = service()->SetChannel(
+ const auto channel_status = service()->SetChannel(
channel_id, std::make_shared<ConsumerQueueChannel>(
service(), buffer_id(), channel_id, shared_from_this()));
- if (ret < 0) {
+ if (!channel_status) {
ALOGE(
"ProducerQueueChannel::OnCreateConsumerQueue: failed to set new "
"consumer channel: %s",
- strerror(-ret));
- REPLY_ERROR_RETURN(message, ENOMEM, {});
+ channel_status.GetErrorMessage().c_str());
+ REPLY_ERROR_RETURN(message, channel_status.error(), {});
}
return std::make_pair(status.take(), meta_size_bytes_);
@@ -214,12 +214,13 @@
"ProducerQueueChannel::AllocateBuffer: buffer_id=%d, buffer_handle=%d",
buffer_id, buffer_handle.value());
- const int ret = service()->SetChannel(buffer_id, producer_channel);
- if (ret < 0) {
+ const auto channel_status =
+ service()->SetChannel(buffer_id, producer_channel);
+ if (!channel_status) {
ALOGE(
- "ProducerQueueChannel::AllocateBuffer: failed to set prodcuer channel "
+ "ProducerQueueChannel::AllocateBuffer: failed to set producer channel "
"for new BufferHubBuffer: %s",
- strerror(-ret));
+ channel_status.GetErrorMessage().c_str());
return {};
}
@@ -252,7 +253,7 @@
return {std::move(buffer_handle), slot};
}
-int ProducerQueueChannel::OnProducerQueueDetachBuffer(Message& message,
+int ProducerQueueChannel::OnProducerQueueDetachBuffer(Message& /*message*/,
size_t slot) {
if (buffers_[slot].expired()) {
ALOGE(
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 34e2b7e..999d71e 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
@@ -34,9 +34,9 @@
// capability. Otherwise assume a count of 1.
mapper.getLayerCount(handle, &layer_count);
- sp<GraphicBuffer> buffer = new GraphicBuffer(
- width, height, format, layer_count, producer_usage, consumer_usage,
- stride, handle, true);
+ sp<GraphicBuffer> buffer = new GraphicBuffer(handle,
+ GraphicBuffer::TAKE_HANDLE, width, height, format, layer_count,
+ producer_usage, consumer_usage, stride);
return buffer;
}
diff --git a/services/vr/performanced/performance_service.cpp b/services/vr/performanced/performance_service.cpp
index c99c8d4..955c661 100644
--- a/services/vr/performanced/performance_service.cpp
+++ b/services/vr/performanced/performance_service.cpp
@@ -170,22 +170,22 @@
return task.GetCpuSetPath();
}
-int PerformanceService::HandleMessage(Message& message) {
+pdx::Status<void> PerformanceService::HandleMessage(Message& message) {
switch (message.GetOp()) {
case PerformanceRPC::SetCpuPartition::Opcode:
DispatchRemoteMethod<PerformanceRPC::SetSchedulerClass>(
*this, &PerformanceService::OnSetCpuPartition, message);
- return 0;
+ return {};
case PerformanceRPC::SetSchedulerClass::Opcode:
DispatchRemoteMethod<PerformanceRPC::SetSchedulerClass>(
*this, &PerformanceService::OnSetSchedulerClass, message);
- return 0;
+ return {};
case PerformanceRPC::GetCpuPartition::Opcode:
DispatchRemoteMethod<PerformanceRPC::GetCpuPartition>(
*this, &PerformanceService::OnGetCpuPartition, message);
- return 0;
+ return {};
default:
return Service::HandleMessage(message);
diff --git a/services/vr/performanced/performance_service.h b/services/vr/performanced/performance_service.h
index e32d834..34abba7 100644
--- a/services/vr/performanced/performance_service.h
+++ b/services/vr/performanced/performance_service.h
@@ -17,7 +17,7 @@
// achieve system performance goals.
class PerformanceService : public pdx::ServiceBase<PerformanceService> {
public:
- int HandleMessage(pdx::Message& message) override;
+ pdx::Status<void> HandleMessage(pdx::Message& message) override;
bool IsInitialized() const override;
std::string DumpState(size_t max_length) override;
diff --git a/services/vr/performanced/performanced.rc b/services/vr/performanced/performanced.rc
index 5042982..6283f37 100644
--- a/services/vr/performanced/performanced.rc
+++ b/services/vr/performanced/performanced.rc
@@ -3,3 +3,4 @@
user root
group system readproc
writepid /dev/cpuset/tasks
+ socket pdx/system/performance/client stream 0666 system system
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 2c4fc30..7534732 100644
--- a/services/vr/sensord/pose_service.cpp
+++ b/services/vr/sensord/pose_service.cpp
@@ -65,6 +65,9 @@
static constexpr int kDatasetIdLength = 36;
static constexpr char kDatasetIdChars[] = "0123456789abcdef-";
+static constexpr int kLatencyWindowSize = 100;
+static constexpr double kLatencyWindowMass = 0.5;
+
// These are the flags used by BufferProducer::CreatePersistentUncachedBlob,
// plus PRIVATE_ADSP_HEAP to allow access from the DSP.
static constexpr int kPoseRingBufferFlags =
@@ -111,7 +114,8 @@
vsync_count_(0),
photon_timestamp_(0),
// Will be updated by external service, but start with a non-zero value:
- display_period_ns_(16000000) {
+ display_period_ns_(16000000),
+ sensor_latency_(kLatencyWindowSize, kLatencyWindowMass) {
last_known_pose_ = {
.orientation = {1.0f, 0.0f, 0.0f, 0.0f},
.translation = {0.0f, 0.0f, 0.0f, 0.0f},
@@ -463,10 +467,13 @@
start_from_head_rotation * Vector3d(0.0, kDefaultNeckVerticalOffset,
-kDefaultNeckHorizontalOffset);
- // IMU driver gives timestamps on its own clock, but we need monotonic
- // clock. Subtract 5ms to account for estimated IMU sample latency.
- WriteAsyncPoses(position, start_from_head_rotation,
- pose_state.timestamp_ns + 5000000);
+ // Update the current latency model.
+ sensor_latency_.AddLatency(GetSystemClockNs() - pose_state.timestamp_ns);
+
+ // Update the timestamp with the expected latency.
+ WriteAsyncPoses(
+ position, start_from_head_rotation,
+ pose_state.timestamp_ns + sensor_latency_.CurrentLatencyEstimate());
break;
}
default:
@@ -476,8 +483,8 @@
}
}
-int PoseService::HandleMessage(pdx::Message& msg) {
- int ret = 0;
+pdx::Status<void> PoseService::HandleMessage(pdx::Message& msg) {
+ pdx::Status<void> ret;
const pdx::MessageInfo& info = msg.GetInfo();
switch (info.op) {
case DVR_POSE_NOTIFY_VSYNC: {
@@ -495,21 +502,13 @@
{.iov_base = &right_eye_photon_offset_ns_,
.iov_len = sizeof(right_eye_photon_offset_ns_)},
};
- constexpr int expected_size =
- sizeof(vsync_count_) + sizeof(photon_timestamp_) +
- sizeof(display_period_ns_) + sizeof(right_eye_photon_offset_ns_);
- ret = msg.ReadVector(data, sizeof(data) / sizeof(data[0]));
- if (ret < expected_size) {
- ALOGI("error: msg.Read read too little (%d < %d)", ret, expected_size);
- REPLY_ERROR(msg, EIO, error);
- }
-
- if (!enable_external_pose_) {
+ ret = msg.ReadVectorAll(data);
+ if (ret && !enable_external_pose_) {
mapped_pose_buffer_->vsync_count = vsync_count_;
}
// TODO(jbates, eieio): make this async, no need to reply.
- REPLY_SUCCESS(msg, 0, error);
+ REPLY_MESSAGE(msg, ret, error);
}
case DVR_POSE_POLL: {
ATRACE_NAME("pose_poll");
@@ -535,61 +534,43 @@
Btrace("Pose polled");
- ret = msg.Write(&client_state, sizeof(client_state));
- const int expected_size = sizeof(client_state);
- if (ret < expected_size) {
- ALOGI("error: msg.Write wrote too little (%d < %d)", ret,
- expected_size);
- REPLY_ERROR(msg, EIO, error);
- }
- REPLY_SUCCESS(msg, 0, error);
+ ret = msg.WriteAll(&client_state, sizeof(client_state));
+ REPLY_MESSAGE(msg, ret, error);
}
case DVR_POSE_FREEZE: {
{
std::lock_guard<std::mutex> guard(mutex_);
DvrPoseState frozen_state;
- const int expected_size = sizeof(frozen_state);
- ret = msg.Read(&frozen_state, expected_size);
- if (ret < expected_size) {
- ALOGI("error: msg.Read read too little (%d < %d)", ret,
- expected_size);
- REPLY_ERROR(msg, EIO, error);
+ ret = msg.ReadAll(&frozen_state, sizeof(frozen_state));
+ if (!ret) {
+ REPLY_ERROR(msg, ret.error(), error);
}
frozen_state_ = frozen_state;
}
SetPoseMode(DVR_POSE_MODE_MOCK_FROZEN);
- REPLY_SUCCESS(msg, 0, error);
+ REPLY_MESSAGE(msg, ret, error);
}
case DVR_POSE_SET_MODE: {
int mode;
{
std::lock_guard<std::mutex> guard(mutex_);
- const int expected_size = sizeof(mode);
- ret = msg.Read(&mode, expected_size);
- if (ret < expected_size) {
- ALOGI("error: msg.Read read too little (%d < %d)", ret,
- expected_size);
- REPLY_ERROR(msg, EIO, error);
+ ret = msg.ReadAll(&mode, sizeof(mode));
+ if (!ret) {
+ REPLY_ERROR(msg, ret.error(), error);
}
if (mode < 0 || mode >= DVR_POSE_MODE_COUNT) {
REPLY_ERROR(msg, EINVAL, error);
}
}
SetPoseMode(DvrPoseMode(mode));
- REPLY_SUCCESS(msg, 0, error);
+ REPLY_MESSAGE(msg, ret, error);
}
case DVR_POSE_GET_MODE: {
std::lock_guard<std::mutex> guard(mutex_);
int mode = pose_mode_;
- ret = msg.Write(&mode, sizeof(mode));
- const int expected_size = sizeof(mode);
- if (ret < expected_size) {
- ALOGI("error: msg.Write wrote too little (%d < %d)", ret,
- expected_size);
- REPLY_ERROR(msg, EIO, error);
- }
- REPLY_SUCCESS(msg, 0, error);
+ ret = msg.WriteAll(&mode, sizeof(mode));
+ REPLY_MESSAGE(msg, ret, error);
}
case DVR_POSE_GET_RING_BUFFER: {
std::lock_guard<std::mutex> guard(mutex_);
diff --git a/services/vr/sensord/pose_service.h b/services/vr/sensord/pose_service.h
index 4df5036..7b7adec 100644
--- a/services/vr/sensord/pose_service.h
+++ b/services/vr/sensord/pose_service.h
@@ -11,8 +11,9 @@
#include <dvr/pose_client.h>
#include <pdx/service.h>
#include <private/dvr/buffer_hub_client.h>
-#include <private/dvr/pose_client_internal.h>
#include <private/dvr/dvr_pose_predictor.h>
+#include <private/dvr/latency_model.h>
+#include <private/dvr/pose_client_internal.h>
#include <private/dvr/ring_buffer.h>
#include "sensor_fusion.h"
@@ -27,7 +28,7 @@
~PoseService() override;
bool IsInitialized() const override;
- int HandleMessage(pdx::Message& msg) override;
+ pdx::Status<void> HandleMessage(pdx::Message& msg) override;
std::string DumpState(size_t max_length) override;
// Handle events from the sensor HAL.
@@ -132,6 +133,9 @@
int64_t display_period_ns_;
int64_t right_eye_photon_offset_ns_ = 0;
+ // To model the measurement - arrival latency.
+ LatencyModel sensor_latency_;
+
// Type for controlling pose orientation calculation.
OrientationType device_orientation_type_;
diff --git a/services/vr/sensord/sensor_service.cpp b/services/vr/sensord/sensor_service.cpp
index 1b809b0..a182a26 100644
--- a/services/vr/sensord/sensor_service.cpp
+++ b/services/vr/sensord/sensor_service.cpp
@@ -69,8 +69,8 @@
client->unset_sensor();
}
-int SensorService::HandleMessage(pdx::Message& msg) {
- int ret = 0;
+pdx::Status<void> SensorService::HandleMessage(pdx::Message& msg) {
+ pdx::Status<void> ret;
const pdx::MessageInfo& info = msg.GetInfo();
switch (info.op) {
case DVR_SENSOR_START: {
@@ -82,8 +82,7 @@
if (client->has_sensor())
REPLY_ERROR(msg, EINVAL, error);
int sensor_type;
- if (msg.Read(&sensor_type, sizeof(sensor_type)) <
- (ssize_t)sizeof(sensor_type))
+ if (!msg.ReadAll(&sensor_type, sizeof(sensor_type)))
REPLY_ERROR(msg, EIO, error);
// Find the sensor of the requested type.
@@ -120,10 +119,8 @@
{.iov_base = out_buffer,
.iov_len = num_events * sizeof(sensors_event_t)},
};
- ret = msg.WriteVector(svec, 2);
- int expected_size = sizeof(int) + num_events * sizeof(sensors_event_t);
- if (ret < expected_size) {
- ALOGI("error: msg.WriteVector wrote too little.");
+ ret = msg.WriteVectorAll(svec, 2);
+ if (!ret) {
REPLY_ERROR(msg, EIO, error);
}
REPLY_SUCCESS(msg, 0, error);
diff --git a/services/vr/sensord/sensor_service.h b/services/vr/sensord/sensor_service.h
index c35fada..6ea470b 100644
--- a/services/vr/sensord/sensor_service.h
+++ b/services/vr/sensord/sensor_service.h
@@ -22,7 +22,7 @@
*/
class SensorService : public pdx::ServiceBase<SensorService> {
public:
- int HandleMessage(pdx::Message& msg) override;
+ pdx::Status<void> HandleMessage(pdx::Message& msg) override;
std::shared_ptr<pdx::Channel> OnChannelOpen(pdx::Message& msg) override;
void OnChannelClose(pdx::Message& msg,
const std::shared_ptr<pdx::Channel>& chan) override;
diff --git a/services/vr/sensord/sensord.rc b/services/vr/sensord/sensord.rc
index f8d28fd..36cd377 100644
--- a/services/vr/sensord/sensord.rc
+++ b/services/vr/sensord/sensord.rc
@@ -7,3 +7,5 @@
user system
group system camera sdcard_rw
writepid /dev/cpuset/system/tasks
+ socket pdx/system/vr/sensors/client stream 0666 system system
+ socket pdx/system/vr/pose/client stream 0666 system system
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/impl/vr_hwc.cpp b/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
index 3393ade..d142729 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
+++ b/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
@@ -69,11 +69,10 @@
mapper.getLayerCount(handle, &layer_count);
// NOTE: Can't re-use |handle| since we don't own it.
- sp<GraphicBuffer> buffer = new GraphicBuffer(
- width, height, format, layer_count, producer_usage, consumer_usage,
- stride, native_handle_clone(handle), true);
- // Need to register the cloned buffer otherwise it can't be used later on.
- if (mapper.registerBuffer(buffer.get()) != OK) {
+ 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;
}
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/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index 86dd001..a19fcf1 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -28,7 +28,7 @@
// API version (major.minor.patch)
define VERSION_MAJOR 1
define VERSION_MINOR 0
-define VERSION_PATCH 43
+define VERSION_PATCH 46
// API limits
define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256
@@ -93,7 +93,7 @@
@extension("VK_ANDROID_native_buffer") define VK_ANDROID_NATIVE_BUFFER_NAME "VK_ANDROID_native_buffer"
// 12
-@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_SPEC_VERSION 5
+@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_SPEC_VERSION 6
@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_NAME "VK_EXT_debug_report"
// 13
@@ -250,7 +250,7 @@
// 85
@extension("VK_KHR_incremental_present") define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 1
-@extension("VK_KHR_incremental_present") define VK_KHR_INCREMENTAL_PRESENT_NAME "VK_KHR_incremental_present"
+@extension("VK_KHR_incremental_present") define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present"
// 86
@extension("VK_KHR_descriptor_update_template") define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_SPEC_VERSION 1
@@ -309,8 +309,8 @@
@extension("VK_EXT_discard_rectangles") define VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME "VK_EXT_discard_rectangles"
// 105
-@extension("VK_EXT_swapchain_colorspace") define VK_EXT_SWAPCHAIN_COLORSPACE_SPEC_VERSION 1
-@extension("VK_EXT_swapchain_colorspace") define VK_EXT_SWAPCHAIN_COLORSPACE_COUNTER_EXTENSION_NAME "VK_EXT_swapchain_colorspace"
+@extension("VK_EXT_swapchain_colorspace") define VK_EXT_SWAPCHAIN_COLORSPACE_SPEC_VERSION 2
+@extension("VK_EXT_swapchain_colorspace") define VK_EXT_SWAPCHAIN_COLORSPACE_EXTENSION_NAME "VK_EXT_swapchain_colorspace"
// 106
@extension("VK_EXT_hdr_metadata") define VK_EXT_HDR_METADATA_SPEC_VERSION 1
@@ -1195,19 +1195,20 @@
enum VkColorSpaceKHR {
VK_COLORSPACE_SRGB_NONLINEAR_KHR = 0x00000000,
- //@extension("VK_EXT_swapchain_colorspace")
- VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT = 1000104001,
- VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT = 1000104002,
- VK_COLOR_SPACE_SCRGB_LINEAR_EXT = 1000104003,
- VK_COLOR_SPACE_SCRGB_NONLINEAR_EXT = 1000104004,
- VK_COLOR_SPACE_DCI_P3_LINEAR_EXT = 1000104005,
- VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT = 1000104006,
- VK_COLOR_SPACE_BT709_LINEAR_EXT = 1000104007,
- VK_COLOR_SPACE_BT709_NONLINEAR_EXT = 1000104008,
- VK_COLOR_SPACE_BT2020_LINEAR_EXT = 1000104009,
- VK_COLOR_SPACE_BT2020_NONLINEAR_EXT = 1000104010,
+ //@extension("VK_EXT_swapchain_colorspace") // 105
+ VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT = 1000104001,
+ VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT = 1000104002,
+ VK_COLOR_SPACE_DCI_P3_LINEAR_EXT = 1000104003,
+ VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT = 1000104004,
+ VK_COLOR_SPACE_BT709_LINEAR_EXT = 1000104005,
+ VK_COLOR_SPACE_BT709_NONLINEAR_EXT = 1000104006,
+ VK_COLOR_SPACE_BT2020_LINEAR_EXT = 1000104007,
+ VK_COLOR_SPACE_HDR10_ST2084_EXT = 1000104008,
+ VK_COLOR_SPACE_DOLBYVISION_EXT = 1000104009,
+ VK_COLOR_SPACE_HDR10_HLG_EXT = 1000104010,
VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT = 1000104011,
VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT = 1000104012,
+ VK_COLOR_SPACE_PASS_THROUGH_EXT = 1000104013,
}
@extension("VK_EXT_debug_report") // 12
@@ -1245,6 +1246,9 @@
VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT = 30,
VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT = 31,
VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT = 32,
+
+ //extension("VK_KHR_descriptor_update_template") // 86
+ VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = 1000085000,
}
@extension("VK_EXT_debug_report") // 12
@@ -3735,7 +3739,7 @@
@extension("VK_KHX_device_group_creation") // 71
class VkPhysicalDeviceGroupPropertiesKHX {
VkStructureType sType
- const void* pNext
+ void* pNext
u32 physicalDeviceCount
VkPhysicalDevice[VK_MAX_DEVICE_GROUP_SIZE_KHX] physicalDevices
VkBool32 subsetAllocation
@@ -4223,7 +4227,7 @@
@extension("VK_EXT_discard_rectangles") // 100
class VkPhysicalDeviceDiscardRectanglePropertiesEXT {
VkStructureType sType
- const void* pNext
+ void* pNext
u32 maxDiscardRectangles
}
diff --git a/vulkan/include/vulkan/vulkan.h b/vulkan/include/vulkan/vulkan.h
index 4b3b8bf..67eba86 100644
--- a/vulkan/include/vulkan/vulkan.h
+++ b/vulkan/include/vulkan/vulkan.h
@@ -43,7 +43,7 @@
#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
// Version of this file
-#define VK_HEADER_VERSION 43
+#define VK_HEADER_VERSION 46
#define VK_NULL_HANDLE 0
@@ -4011,6 +4011,30 @@
const VkWriteDescriptorSet* pDescriptorWrites);
#endif
+#define VK_KHR_incremental_present 1
+#define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 1
+#define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present"
+
+typedef struct VkRectLayerKHR {
+ VkOffset2D offset;
+ VkExtent2D extent;
+ uint32_t layer;
+} VkRectLayerKHR;
+
+typedef struct VkPresentRegionKHR {
+ uint32_t rectangleCount;
+ const VkRectLayerKHR* pRectangles;
+} VkPresentRegionKHR;
+
+typedef struct VkPresentRegionsKHR {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t swapchainCount;
+ const VkPresentRegionKHR* pRegions;
+} VkPresentRegionsKHR;
+
+
+
#define VK_KHR_descriptor_update_template 1
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorUpdateTemplateKHR)
@@ -4086,7 +4110,7 @@
#define VK_EXT_debug_report 1
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT)
-#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 5
+#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 6
#define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report"
#define VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT
@@ -4125,6 +4149,7 @@
VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT = 30,
VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT = 31,
VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT = 32,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = 1000085000,
VK_DEBUG_REPORT_OBJECT_TYPE_BEGIN_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
VK_DEBUG_REPORT_OBJECT_TYPE_END_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT,
VK_DEBUG_REPORT_OBJECT_TYPE_RANGE_SIZE_EXT = (VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT - VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT + 1),
@@ -4781,7 +4806,7 @@
typedef struct VkPhysicalDeviceGroupPropertiesKHX {
VkStructureType sType;
- const void* pNext;
+ void* pNext;
uint32_t physicalDeviceCount;
VkPhysicalDevice physicalDevices[VK_MAX_DEVICE_GROUP_SIZE_KHX];
VkBool32 subsetAllocation;
@@ -4906,7 +4931,7 @@
-#ifdef VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHX
#define VK_KHX_external_memory_win32 1
#define VK_KHX_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1
#define VK_KHX_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_KHX_external_memory_win32"
@@ -4949,7 +4974,7 @@
HANDLE handle,
VkMemoryWin32HandlePropertiesKHX* pMemoryWin32HandleProperties);
#endif
-#endif /* VK_USE_PLATFORM_WIN32_KHR */
+#endif /* VK_USE_PLATFORM_WIN32_KHX */
#define VK_KHX_external_memory_fd 1
#define VK_KHX_EXTERNAL_MEMORY_FD_SPEC_VERSION 1
@@ -5139,28 +5164,6 @@
int* pFd);
#endif
-#define VK_KHR_incremental_present 1
-#define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 1
-#define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present"
-
-typedef struct VkRectLayerKHR {
- VkOffset2D offset;
- VkExtent2D extent;
- uint32_t layer;
-} VkRectLayerKHR;
-
-typedef struct VkPresentRegionKHR {
- uint32_t rectangleCount;
- const VkRectLayerKHR* pRectangles;
-} VkPresentRegionKHR;
-
-typedef struct VkPresentRegionsKHR {
- VkStructureType sType;
- const void* pNext;
- uint32_t swapchainCount;
- const VkPresentRegionKHR* pRegions;
-} VkPresentRegionsKHR;
-
#define VK_NVX_device_generated_commands 1
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkObjectTableNVX)
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNVX)
@@ -5705,7 +5708,7 @@
typedef struct VkPhysicalDeviceDiscardRectanglePropertiesEXT {
VkStructureType sType;
- const void* pNext;
+ void* pNext;
uint32_t maxDiscardRectangles;
} VkPhysicalDeviceDiscardRectanglePropertiesEXT;
@@ -5730,9 +5733,10 @@
#endif
#define VK_EXT_swapchain_colorspace 1
-#define VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION 1
+#define VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION 2
#define VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME "VK_EXT_swapchain_colorspace"
+
#define VK_EXT_hdr_metadata 1
#define VK_EXT_HDR_METADATA_SPEC_VERSION 1
#define VK_EXT_HDR_METADATA_EXTENSION_NAME "VK_EXT_hdr_metadata"
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 2fee8a5..3b785e6 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -981,25 +981,9 @@
int gralloc_usage = 0;
if (dispatch.GetSwapchainGrallocUsage2ANDROID) {
uint64_t consumer_usage, producer_usage;
- if (GetData(device).driver_version == 256587285) {
- // HACK workaround for loader/driver mismatch during transition to
- // vkGetSwapchainGrallocUsage2ANDROID.
- typedef VkResult(VKAPI_PTR *
- PFN_vkGetSwapchainGrallocUsage2ANDROID_HACK)(
- VkDevice device, VkFormat format, VkImageUsageFlags imageUsage,
- uint64_t * grallocConsumerUsage,
- uint64_t * grallocProducerUsage);
- auto get_swapchain_gralloc_usage =
- reinterpret_cast<PFN_vkGetSwapchainGrallocUsage2ANDROID_HACK>(
- dispatch.GetSwapchainGrallocUsage2ANDROID);
- result = get_swapchain_gralloc_usage(
- device, create_info->imageFormat, create_info->imageUsage,
- &consumer_usage, &producer_usage);
- } else {
- result = dispatch.GetSwapchainGrallocUsage2ANDROID(
- device, create_info->imageFormat, create_info->imageUsage,
- swapchain_image_usage, &consumer_usage, &producer_usage);
- }
+ result = dispatch.GetSwapchainGrallocUsage2ANDROID(
+ device, create_info->imageFormat, create_info->imageUsage,
+ swapchain_image_usage, &consumer_usage, &producer_usage);
if (result != VK_SUCCESS) {
ALOGE("vkGetSwapchainGrallocUsage2ANDROID failed: %d", result);
return VK_ERROR_SURFACE_LOST_KHR;