Merge "[SurfaceFlinger]Use configStore useContextPriority"
diff --git a/cmds/flatland/GLHelper.cpp b/cmds/flatland/GLHelper.cpp
index dfc3e58..5c04f6c 100644
--- a/cmds/flatland/GLHelper.cpp
+++ b/cmds/flatland/GLHelper.cpp
@@ -25,6 +25,7 @@
namespace android {
GLHelper::GLHelper() :
+ mGraphicBufferAlloc(new GraphicBufferAlloc()),
mDisplay(EGL_NO_DISPLAY),
mContext(EGL_NO_CONTEXT),
mDummySurface(EGL_NO_SURFACE),
@@ -202,7 +203,7 @@
sp<GLConsumer>* glConsumer, EGLSurface* surface) {
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer);
+ BufferQueue::createBufferQueue(&producer, &consumer, mGraphicBufferAlloc);
sp<GLConsumer> glc = new GLConsumer(consumer, name,
GL_TEXTURE_EXTERNAL_OES, false, true);
glc->setDefaultBufferSize(w, h);
diff --git a/cmds/flatland/GLHelper.h b/cmds/flatland/GLHelper.h
index d09463a..7a9e9e3 100644
--- a/cmds/flatland/GLHelper.h
+++ b/cmds/flatland/GLHelper.h
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <gui/GraphicBufferAlloc.h>
#include <gui/GLConsumer.h>
#include <gui/Surface.h>
#include <gui/SurfaceControl.h>
@@ -74,6 +75,8 @@
bool setUpShaders(const ShaderDesc* shaderDescs, size_t numShaders);
+ sp<GraphicBufferAlloc> mGraphicBufferAlloc;
+
EGLDisplay mDisplay;
EGLContext mContext;
EGLSurface mDummySurface;
diff --git a/cmds/flatland/Main.cpp b/cmds/flatland/Main.cpp
index ec1e543..c47b0c8 100644
--- a/cmds/flatland/Main.cpp
+++ b/cmds/flatland/Main.cpp
@@ -16,6 +16,7 @@
#define ATRACE_TAG ATRACE_TAG_ALWAYS
+#include <gui/GraphicBufferAlloc.h>
#include <gui/Surface.h>
#include <gui/SurfaceControl.h>
#include <gui/GLConsumer.h>
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 58b9d2c..a5ac8a4 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -45,10 +45,15 @@
using android::base::StringPrintf;
using android::base::EndsWith;
+using android::base::unique_fd;
namespace android {
namespace installd {
+static unique_fd invalid_unique_fd() {
+ return unique_fd(-1);
+}
+
static const char* parse_null(const char* arg) {
if (strcmp(arg, "!") == 0) {
return nullptr;
@@ -58,7 +63,7 @@
}
static bool clear_profile(const std::string& profile) {
- base::unique_fd ufd(open(profile.c_str(), O_WRONLY | O_NOFOLLOW | O_CLOEXEC));
+ unique_fd ufd(open(profile.c_str(), O_WRONLY | O_NOFOLLOW | O_CLOEXEC));
if (ufd.get() < 0) {
if (errno != ENOENT) {
PLOG(WARNING) << "Could not open profile " << profile;
@@ -467,18 +472,10 @@
}
}
-static void close_all_fds(const std::vector<fd_t>& fds, const char* description) {
- for (size_t i = 0; i < fds.size(); i++) {
- if (close(fds[i]) != 0) {
- PLOG(WARNING) << "Failed to close fd for " << description << " at index " << i;
- }
- }
-}
-
-static fd_t open_profile_dir(const std::string& profile_dir) {
- fd_t profile_dir_fd = TEMP_FAILURE_RETRY(open(profile_dir.c_str(),
- O_PATH | O_CLOEXEC | O_DIRECTORY | O_NOFOLLOW));
- if (profile_dir_fd < 0) {
+static unique_fd open_profile_dir(const std::string& profile_dir) {
+ unique_fd profile_dir_fd(TEMP_FAILURE_RETRY(open(profile_dir.c_str(),
+ O_PATH | O_CLOEXEC | O_DIRECTORY | O_NOFOLLOW)));
+ if (profile_dir_fd.get() < 0) {
// In a multi-user environment, these directories can be created at
// different points and it's possible we'll attempt to open a profile
// dir before it exists.
@@ -489,66 +486,61 @@
return profile_dir_fd;
}
-static fd_t open_primary_profile_file_from_dir(const std::string& profile_dir, mode_t open_mode) {
- fd_t profile_dir_fd = open_profile_dir(profile_dir);
- if (profile_dir_fd < 0) {
- return -1;
+static unique_fd open_primary_profile_file_from_dir(const std::string& profile_dir,
+ mode_t open_mode) {
+ unique_fd profile_dir_fd = open_profile_dir(profile_dir);
+ if (profile_dir_fd.get() < 0) {
+ return invalid_unique_fd();
}
- fd_t profile_fd = -1;
std::string profile_file = create_primary_profile(profile_dir);
-
- profile_fd = TEMP_FAILURE_RETRY(open(profile_file.c_str(), open_mode | O_NOFOLLOW, 0600));
+ unique_fd profile_fd(TEMP_FAILURE_RETRY(open(profile_file.c_str(),
+ open_mode | O_NOFOLLOW, 0600)));
if (profile_fd == -1) {
// It's not an error if the profile file does not exist.
if (errno != ENOENT) {
- PLOG(ERROR) << "Failed to lstat profile_dir: " << profile_dir;
+ PLOG(ERROR) << "Failed to open profile : " << profile_file;
}
}
- // TODO(calin): use AutoCloseFD instead of closing the fd manually.
- if (close(profile_dir_fd) != 0) {
- PLOG(WARNING) << "Could not close profile dir " << profile_dir;
- }
return profile_fd;
}
-static fd_t open_primary_profile_file(userid_t user, const std::string& pkgname) {
+static unique_fd open_primary_profile_file(userid_t user, const std::string& pkgname) {
std::string profile_dir = create_data_user_profile_package_path(user, pkgname);
return open_primary_profile_file_from_dir(profile_dir, O_RDONLY);
}
-static fd_t open_reference_profile(uid_t uid, const std::string& pkgname, bool read_write) {
+static unique_fd open_reference_profile(uid_t uid, const std::string& pkgname, bool read_write) {
std::string reference_profile_dir = create_data_ref_profile_package_path(pkgname);
int flags = read_write ? O_RDWR | O_CREAT : O_RDONLY;
- fd_t fd = open_primary_profile_file_from_dir(reference_profile_dir, flags);
- if (fd < 0) {
- return -1;
+ unique_fd fd = open_primary_profile_file_from_dir(reference_profile_dir, flags);
+ if (fd.get() < 0) {
+ return invalid_unique_fd();
}
if (read_write) {
// Fix the owner.
- if (fchown(fd, uid, uid) < 0) {
- close(fd);
- return -1;
+ if (fchown(fd.get(), uid, uid) < 0) {
+ return invalid_unique_fd();
}
}
return fd;
}
static void open_profile_files(uid_t uid, const std::string& pkgname,
- /*out*/ std::vector<fd_t>* profiles_fd, /*out*/ fd_t* reference_profile_fd) {
+ /*out*/ std::vector<unique_fd>* profiles_fd, /*out*/ unique_fd* reference_profile_fd) {
// Open the reference profile in read-write mode as profman might need to save the merge.
- *reference_profile_fd = open_reference_profile(uid, pkgname, /*read_write*/ true);
- if (*reference_profile_fd < 0) {
+ reference_profile_fd->reset(open_reference_profile(uid, pkgname, /*read_write*/ true));
+ if (reference_profile_fd->get() < 0) {
// We can't access the reference profile file.
return;
}
std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
for (auto user : users) {
- fd_t profile_fd = open_primary_profile_file(user, pkgname);
+ unique_fd profile_fd = open_primary_profile_file(user, pkgname);
// Add to the lists only if both fds are valid.
- if (profile_fd >= 0) {
- profiles_fd->push_back(profile_fd);
+ if (profile_fd.get() >= 0) {
+ profiles_fd->push_back(std::move(profile_fd));
}
}
}
@@ -580,18 +572,19 @@
static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 3;
static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 4;
-static void run_profman_merge(const std::vector<fd_t>& profiles_fd, fd_t reference_profile_fd) {
+static void run_profman_merge(const std::vector<unique_fd>& profiles_fd,
+ const unique_fd& reference_profile_fd) {
static const size_t MAX_INT_LEN = 32;
static const char* PROFMAN_BIN = "/system/bin/profman";
std::vector<std::string> profile_args(profiles_fd.size());
char profile_buf[strlen("--profile-file-fd=") + MAX_INT_LEN];
for (size_t k = 0; k < profiles_fd.size(); k++) {
- sprintf(profile_buf, "--profile-file-fd=%d", profiles_fd[k]);
+ sprintf(profile_buf, "--profile-file-fd=%d", profiles_fd[k].get());
profile_args[k].assign(profile_buf);
}
char reference_profile_arg[strlen("--reference-profile-file-fd=") + MAX_INT_LEN];
- sprintf(reference_profile_arg, "--reference-profile-file-fd=%d", reference_profile_fd);
+ sprintf(reference_profile_arg, "--reference-profile-file-fd=%d", reference_profile_fd.get());
// program name, reference profile fd, the final NULL and the profile fds
const char* argv[3 + profiles_fd.size()];
@@ -615,16 +608,12 @@
// If the return value is true all the current profiles would have been merged into
// the reference profiles accessible with open_reference_profile().
bool analyse_profiles(uid_t uid, const std::string& pkgname) {
- std::vector<fd_t> profiles_fd;
- fd_t reference_profile_fd = -1;
+ std::vector<unique_fd> profiles_fd;
+ unique_fd reference_profile_fd;
open_profile_files(uid, pkgname, &profiles_fd, &reference_profile_fd);
- if (profiles_fd.empty() || (reference_profile_fd == -1)) {
+ if (profiles_fd.empty() || (reference_profile_fd.get() < 0)) {
// Skip profile guided compilation because no profiles were found.
// Or if the reference profile info couldn't be opened.
- close_all_fds(profiles_fd, "profiles_fd");
- if ((reference_profile_fd != - 1) && (close(reference_profile_fd) != 0)) {
- PLOG(WARNING) << "Failed to close fd for reference profile";
- }
return false;
}
@@ -679,10 +668,7 @@
break;
}
}
- close_all_fds(profiles_fd, "profiles_fd");
- if (close(reference_profile_fd) != 0) {
- PLOG(WARNING) << "Failed to close fd for reference profile";
- }
+
if (should_clear_current_profiles) {
clear_current_profiles(pkgname);
}
@@ -692,28 +678,28 @@
return need_to_compile;
}
-static void run_profman_dump(const std::vector<fd_t>& profile_fds,
- fd_t reference_profile_fd,
+static void run_profman_dump(const std::vector<unique_fd>& profile_fds,
+ const unique_fd& reference_profile_fd,
const std::vector<std::string>& dex_locations,
- const std::vector<fd_t>& apk_fds,
- fd_t output_fd) {
+ const std::vector<unique_fd>& apk_fds,
+ const unique_fd& output_fd) {
std::vector<std::string> profman_args;
static const char* PROFMAN_BIN = "/system/bin/profman";
profman_args.push_back(PROFMAN_BIN);
profman_args.push_back("--dump-only");
- profman_args.push_back(StringPrintf("--dump-output-to-fd=%d", output_fd));
+ profman_args.push_back(StringPrintf("--dump-output-to-fd=%d", output_fd.get()));
if (reference_profile_fd != -1) {
profman_args.push_back(StringPrintf("--reference-profile-file-fd=%d",
- reference_profile_fd));
+ reference_profile_fd.get()));
}
- for (fd_t profile_fd : profile_fds) {
- profman_args.push_back(StringPrintf("--profile-file-fd=%d", profile_fd));
+ for (size_t i = 0; i < profile_fds.size(); i++) {
+ profman_args.push_back(StringPrintf("--profile-file-fd=%d", profile_fds[i].get()));
}
for (const std::string& dex_location : dex_locations) {
profman_args.push_back(StringPrintf("--dex-location=%s", dex_location.c_str()));
}
- for (fd_t apk_fd : apk_fds) {
- profman_args.push_back(StringPrintf("--apk-fd=%d", apk_fd));
+ for (size_t i = 0; i < apk_fds.size(); i++) {
+ profman_args.push_back(StringPrintf("--apk-fd=%d", apk_fds[i].get()));
}
const char **argv = new const char*[profman_args.size() + 1];
size_t i = 0;
@@ -739,13 +725,13 @@
}
bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths) {
- std::vector<fd_t> profile_fds;
- fd_t reference_profile_fd = -1;
+ std::vector<unique_fd> profile_fds;
+ unique_fd reference_profile_fd;
std::string out_file_name = StringPrintf("/data/misc/profman/%s.txt", pkgname.c_str());
open_profile_files(uid, pkgname, &profile_fds, &reference_profile_fd);
- const bool has_reference_profile = (reference_profile_fd != -1);
+ const bool has_reference_profile = (reference_profile_fd.get() != -1);
const bool has_profiles = !profile_fds.empty();
if (!has_reference_profile && !has_profiles) {
@@ -753,23 +739,23 @@
return false;
}
- fd_t output_fd = open(out_file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0644);
+ unique_fd output_fd(open(out_file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0644));
if (fchmod(output_fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
ALOGE("installd cannot chmod '%s' dump_profile\n", out_file_name.c_str());
return false;
}
std::vector<std::string> code_full_paths = base::Split(code_paths, ";");
std::vector<std::string> dex_locations;
- std::vector<fd_t> apk_fds;
+ std::vector<unique_fd> apk_fds;
for (const std::string& code_full_path : code_full_paths) {
const char* full_path = code_full_path.c_str();
- fd_t apk_fd = open(full_path, O_RDONLY | O_NOFOLLOW);
+ unique_fd apk_fd(open(full_path, O_RDONLY | O_NOFOLLOW));
if (apk_fd == -1) {
ALOGE("installd cannot open '%s'\n", full_path);
return false;
}
dex_locations.push_back(get_location_from_path(full_path));
- apk_fds.push_back(apk_fd);
+ apk_fds.push_back(std::move(apk_fd));
}
pid_t pid = fork();
@@ -781,11 +767,6 @@
exit(68); /* only get here on exec failure */
}
/* parent */
- close_all_fds(apk_fds, "apk_fds");
- close_all_fds(profile_fds, "profile_fds");
- if (close(reference_profile_fd) != 0) {
- PLOG(WARNING) << "Failed to close fd for reference profile";
- }
int return_code = wait_child(pid);
if (!WIFEXITED(return_code)) {
LOG(WARNING) << "profman failed for package " << pkgname << ": "
@@ -1053,17 +1034,17 @@
// Creates the dexopt swap file if necessary and return its fd.
// Returns -1 if there's no need for a swap or in case of errors.
-base::unique_fd maybe_open_dexopt_swap_file(const char* out_oat_path) {
+unique_fd maybe_open_dexopt_swap_file(const char* out_oat_path) {
if (!ShouldUseSwapFileForDexopt()) {
- return base::unique_fd();
+ return invalid_unique_fd();
}
// Make sure there really is enough space.
char swap_file_name[PKG_PATH_MAX];
strcpy(swap_file_name, out_oat_path);
if (!add_extension_to_file_name(swap_file_name, ".swap")) {
- return base::unique_fd();
+ return invalid_unique_fd();
}
- base::unique_fd swap_fd(open_output_file(
+ unique_fd swap_fd(open_output_file(
swap_file_name, /*recreate*/true, /*permissions*/0600));
if (swap_fd.get() < 0) {
// Could not create swap file. Optimistically go on and hope that we can compile
@@ -1088,8 +1069,9 @@
if (profile_guided && !is_secondary_dex && !is_public && (pkgname[0] != '*')) {
// Open reference profile in read only mode as dex2oat does not get write permissions.
const std::string pkgname_str(pkgname);
+ unique_fd profile_fd = open_reference_profile(uid, pkgname, /*read_write*/ false);
return Dex2oatFileWrapper(
- open_reference_profile(uid, pkgname, /*read_write*/ false),
+ profile_fd.release(),
[pkgname_str]() {
clear_reference_profile(pkgname_str.c_str());
});
@@ -1430,7 +1412,7 @@
}
// Open the input file.
- base::unique_fd input_fd(open(dex_path, O_RDONLY, 0));
+ unique_fd input_fd(open(dex_path, O_RDONLY, 0));
if (input_fd.get() < 0) {
ALOGE("installd cannot open '%s' for input during dexopt\n", dex_path);
return -1;
@@ -1453,7 +1435,7 @@
}
// Create a swap file if necessary.
- base::unique_fd swap_fd = maybe_open_dexopt_swap_file(out_oat_path);
+ unique_fd swap_fd = maybe_open_dexopt_swap_file(out_oat_path);
// Create the app image file if needed.
Dex2oatFileWrapper image_fd =
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index fab4d94..df6d176 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -32,8 +32,6 @@
static constexpr int DEX2OAT_FOR_RELOCATION = 4;
static constexpr int PATCHOAT_FOR_RELOCATION = 5;
-typedef int fd_t;
-
bool clear_reference_profile(const std::string& pkgname);
bool clear_current_profile(const std::string& pkgname, userid_t user);
bool clear_current_profiles(const std::string& pkgname);
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index bd62d85..c95c535 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -23,6 +23,10 @@
#include <gui/IGraphicBufferProducer.h>
#include <gui/IConsumerListener.h>
+// These are only required to keep other parts of the framework with incomplete
+// dependencies building successfully
+#include <gui/IGraphicBufferAlloc.h>
+
namespace android {
class BufferQueue {
@@ -77,9 +81,11 @@
// needed gralloc buffers.
static void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
+ const sp<IGraphicBufferAlloc>& allocator = NULL,
bool consumerIsSurfaceFlinger = false);
- BufferQueue() = delete; // Create through createBufferQueue
+private:
+ BufferQueue(); // Create through createBufferQueue
};
// ----------------------------------------------------------------------------
diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h
index 1e9585c..b1c730a 100644
--- a/include/gui/BufferQueueCore.h
+++ b/include/gui/BufferQueueCore.h
@@ -51,6 +51,7 @@
namespace android {
class IConsumerListener;
+class IGraphicBufferAlloc;
class IProducerListener;
class BufferQueueCore : public virtual RefBase {
@@ -78,8 +79,9 @@
typedef Vector<BufferItem> Fifo;
// BufferQueueCore manages a pool of gralloc memory slots to be used by
- // producers and consumers.
- BufferQueueCore();
+ // producers and consumers. allocator is used to allocate all the needed
+ // gralloc buffers.
+ BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator = NULL);
virtual ~BufferQueueCore();
private:
@@ -141,6 +143,10 @@
void validateConsistencyLocked() const;
#endif
+ // mAllocator is the connection to SurfaceFlinger that is used to allocate
+ // new GraphicBuffer objects.
+ sp<IGraphicBufferAlloc> mAllocator;
+
// mMutex is the mutex used to prevent concurrent access to the member
// variables of BufferQueueCore objects. It must be locked whenever any
// member variable is accessed.
diff --git a/include/gui/GraphicBufferAlloc.h b/include/gui/GraphicBufferAlloc.h
new file mode 100644
index 0000000..54c9829
--- /dev/null
+++ b/include/gui/GraphicBufferAlloc.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_GUI_GRAPHIC_BUFFER_ALLOC_H
+#define ANDROID_GUI_GRAPHIC_BUFFER_ALLOC_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <gui/IGraphicBufferAlloc.h>
+#include <ui/PixelFormat.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+class GraphicBuffer;
+
+/*
+ * Concrete implementation of the IGraphicBufferAlloc interface.
+ *
+ * This can create GraphicBuffer instance across processes. This is mainly used
+ * by surfaceflinger.
+ */
+
+class GraphicBufferAlloc : public BnGraphicBufferAlloc {
+public:
+ GraphicBufferAlloc();
+ virtual ~GraphicBufferAlloc();
+ virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t width,
+ uint32_t height, PixelFormat format, uint32_t layerCount,
+ uint64_t producerUsage, uint64_t consumerUsage,
+ std::string requestorName, status_t* error) override;
+};
+
+
+} // namespace android
+
+#endif // ANDROID_GUI_GRAPHIC_BUFFER_ALLOC_H
diff --git a/include/gui/IGraphicBufferAlloc.h b/include/gui/IGraphicBufferAlloc.h
new file mode 100644
index 0000000..1e578cc
--- /dev/null
+++ b/include/gui/IGraphicBufferAlloc.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_GUI_IGRAPHIC_BUFFER_ALLOC_H
+#define ANDROID_GUI_IGRAPHIC_BUFFER_ALLOC_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/IInterface.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/PixelFormat.h>
+#include <utils/RefBase.h>
+
+#include <string>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class IGraphicBufferAlloc : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(GraphicBufferAlloc)
+
+ /* Create a new GraphicBuffer for the client to use.
+ */
+ virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
+ PixelFormat format, uint32_t layerCount, uint64_t producerUsage,
+ uint64_t consumerUsage, std::string requestorName,
+ status_t* error) = 0;
+
+ sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
+ PixelFormat format, uint32_t layerCount, uint32_t usage,
+ status_t* error) {
+ return createGraphicBuffer(w, h, format, layerCount, usage,
+ usage, "<Unknown>", error);
+ }
+
+ sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
+ PixelFormat format, uint32_t layerCount, uint32_t usage,
+ std::string requestorName, status_t* error) {
+ return createGraphicBuffer(w, h, format, layerCount, usage,
+ usage, requestorName, error);
+ }
+
+ sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
+ PixelFormat format, uint32_t layerCount, uint64_t producerUsage,
+ uint64_t consumerUsage, status_t* error) {
+ return createGraphicBuffer(w, h, format, layerCount, producerUsage,
+ consumerUsage, "<Unknown>", error);
+ }
+};
+
+// ----------------------------------------------------------------------------
+
+class BnGraphicBufferAlloc : public BnInterface<IGraphicBufferAlloc>
+{
+public:
+ virtual status_t onTransact(uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_GUI_IGRAPHIC_BUFFER_ALLOC_H
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index 1112973..9870ba0 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -41,6 +41,7 @@
struct DisplayStatInfo;
class HdrCapabilities;
class IDisplayEventConnection;
+class IGraphicBufferAlloc;
class IGraphicBufferProducer;
class ISurfaceComposerClient;
class Rect;
@@ -88,6 +89,10 @@
virtual sp<ISurfaceComposerClient> createScopedConnection(
const sp<IGraphicBufferProducer>& parent) = 0;
+ /* create a graphic buffer allocator
+ */
+ virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc() = 0;
+
/* return an IDisplayEventConnection */
virtual sp<IDisplayEventConnection> createDisplayEventConnection() = 0;
@@ -200,7 +205,7 @@
// Java by ActivityManagerService.
BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
CREATE_CONNECTION,
- UNUSED, // formerly CREATE_GRAPHIC_BUFFER_ALLOC
+ CREATE_GRAPHIC_BUFFER_ALLOC,
CREATE_DISPLAY_EVENT_CONNECTION,
CREATE_DISPLAY,
DESTROY_DISPLAY,
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 9d2dcb6..a1b4abc 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -70,9 +70,11 @@
"DisplayEventReceiver.cpp",
"FrameTimestamps.cpp",
"GLConsumer.cpp",
+ "GraphicBufferAlloc.cpp",
"GuiConfig.cpp",
"IDisplayEventConnection.cpp",
"IConsumerListener.cpp",
+ "IGraphicBufferAlloc.cpp",
"IGraphicBufferConsumer.cpp",
"IGraphicBufferProducer.cpp",
"IProducerListener.cpp",
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 4151212..13692eb 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -79,13 +79,14 @@
void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
+ const sp<IGraphicBufferAlloc>& allocator,
bool consumerIsSurfaceFlinger) {
LOG_ALWAYS_FATAL_IF(outProducer == NULL,
"BufferQueue: outProducer must not be NULL");
LOG_ALWAYS_FATAL_IF(outConsumer == NULL,
"BufferQueue: outConsumer must not be NULL");
- sp<BufferQueueCore> core(new BufferQueueCore());
+ sp<BufferQueueCore> core(new BufferQueueCore(allocator));
LOG_ALWAYS_FATAL_IF(core == NULL,
"BufferQueue: failed to create BufferQueueCore");
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index 1b8ffd7..9e3fecb 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -33,7 +33,9 @@
#include <gui/BufferItem.h>
#include <gui/BufferQueueCore.h>
+#include <gui/GraphicBufferAlloc.h>
#include <gui/IConsumerListener.h>
+#include <gui/IGraphicBufferAlloc.h>
#include <gui/IProducerListener.h>
#include <gui/ISurfaceComposer.h>
#include <private/gui/ComposerService.h>
@@ -52,7 +54,8 @@
return id | counter++;
}
-BufferQueueCore::BufferQueueCore() :
+BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) :
+ mAllocator(allocator),
mMutex(),
mIsAbandoned(false),
mConsumerControlledByApp(false),
@@ -94,6 +97,30 @@
mLastQueuedSlot(INVALID_BUFFER_SLOT),
mUniqueId(getUniqueId())
{
+ if (allocator == NULL) {
+
+#ifdef HAVE_NO_SURFACE_FLINGER
+ // Without a SurfaceFlinger, allocate in-process. This only makes
+ // sense in systems with static SELinux configurations and no
+ // applications (since applications need dynamic SELinux policy).
+ mAllocator = new GraphicBufferAlloc();
+#else
+ // Run time check for headless, where we also allocate in-process.
+ char value[PROPERTY_VALUE_MAX];
+ property_get("config.headless", value, "0");
+ if (atoi(value) == 1) {
+ mAllocator = new GraphicBufferAlloc();
+ } else {
+ sp<ISurfaceComposer> composer(ComposerService::getComposerService());
+ mAllocator = composer->createGraphicBufferAlloc();
+ }
+#endif // HAVE_NO_SURFACE_FLINGER
+
+ if (mAllocator == NULL) {
+ BQ_LOGE("createGraphicBufferAlloc failed");
+ }
+ }
+
int numStartingBuffers = getMaxBufferCountLocked();
for (int s = 0; s < numStartingBuffers; s++) {
mFreeSlots.insert(s);
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index b92e895..27ced61 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -34,6 +34,7 @@
#include <gui/BufferQueueProducer.h>
#include <gui/GLConsumer.h>
#include <gui/IConsumerListener.h>
+#include <gui/IGraphicBufferAlloc.h>
#include <gui/IProducerListener.h>
#include <utils/Log.h>
@@ -453,7 +454,8 @@
mSlots[found].mBufferState.dequeue();
if ((buffer == NULL) ||
- buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage))
+ buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT,
+ usage))
{
mSlots[found].mAcquireCalled = false;
mSlots[found].mGraphicBuffer = NULL;
@@ -501,13 +503,11 @@
} // Autolock scope
if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
+ status_t error;
BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
- sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
- width, height, format, BQ_LAYER_COUNT, usage, usage,
- {mConsumerName.string(), mConsumerName.size()});
-
- status_t error = graphicBuffer->initCheck();
-
+ sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
+ width, height, format, BQ_LAYER_COUNT, usage,
+ {mConsumerName.string(), mConsumerName.size()}, &error));
{ // Autolock scope
Mutex::Autolock lock(mCore->mMutex);
@@ -1329,12 +1329,11 @@
Vector<sp<GraphicBuffer>> buffers;
for (size_t i = 0; i < newBufferCount; ++i) {
- sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
+ status_t result = NO_ERROR;
+ sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
allocWidth, allocHeight, allocFormat, BQ_LAYER_COUNT,
- allocUsage, allocUsage, {mConsumerName.string(), mConsumerName.size()});
-
- status_t result = graphicBuffer->initCheck();
-
+ allocUsage, {mConsumerName.string(), mConsumerName.size()},
+ &result));
if (result != NO_ERROR) {
BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
" %u, usage %u)", width, height, format, usage);
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index 9d0fa7e..8acdfed 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -30,6 +30,7 @@
#include <cutils/atomic.h>
#include <gui/BufferItem.h>
+#include <gui/IGraphicBufferAlloc.h>
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/ConsumerBase.h>
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index c654f08..55e0d26 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -31,6 +31,7 @@
#include <gui/BufferItem.h>
#include <gui/GLConsumer.h>
+#include <gui/IGraphicBufferAlloc.h>
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
diff --git a/libs/gui/GraphicBufferAlloc.cpp b/libs/gui/GraphicBufferAlloc.cpp
new file mode 100644
index 0000000..cc7d403
--- /dev/null
+++ b/libs/gui/GraphicBufferAlloc.cpp
@@ -0,0 +1,49 @@
+/*
+ **
+ ** Copyright 2012 The Android Open Source Project
+ **
+ ** Licensed under the Apache License Version 2.0(the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing software
+ ** distributed under the License is distributed on an "AS IS" BASIS
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include <gui/GraphicBufferAlloc.h>
+
+#include <log/log.h>
+
+
+namespace android {
+
+GraphicBufferAlloc::GraphicBufferAlloc() = default;
+GraphicBufferAlloc::~GraphicBufferAlloc() = default;
+
+sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t width,
+ uint32_t height, PixelFormat format, uint32_t layerCount,
+ uint64_t producerUsage, uint64_t consumerUsage,
+ std::string requestorName, status_t* error) {
+ sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(
+ width, height, format, layerCount, producerUsage, consumerUsage,
+ std::move(requestorName)));
+ status_t err = graphicBuffer->initCheck();
+ *error = err;
+ if (err != 0 || graphicBuffer->handle == 0) {
+ if (err == NO_MEMORY) {
+ GraphicBuffer::dumpAllocationsToSystemLog();
+ }
+ ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%u, h=%u, lc=%u) failed (%s), handle=%p",
+ width, height, layerCount, strerror(-err),
+ graphicBuffer->handle);
+ graphicBuffer.clear();
+ }
+ return graphicBuffer;
+}
+
+} // namespace android
diff --git a/libs/gui/IGraphicBufferAlloc.cpp b/libs/gui/IGraphicBufferAlloc.cpp
new file mode 100644
index 0000000..21a0dd5
--- /dev/null
+++ b/libs/gui/IGraphicBufferAlloc.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+// tag as surfaceflinger
+#define LOG_TAG "SurfaceFlinger"
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+
+#include <ui/GraphicBuffer.h>
+
+#include <gui/IGraphicBufferAlloc.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+enum {
+ CREATE_GRAPHIC_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+class BpGraphicBufferAlloc : public BpInterface<IGraphicBufferAlloc>
+{
+public:
+ explicit BpGraphicBufferAlloc(const sp<IBinder>& impl)
+ : BpInterface<IGraphicBufferAlloc>(impl)
+ {
+ }
+
+ virtual ~BpGraphicBufferAlloc();
+
+ virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t width,
+ uint32_t height, PixelFormat format, uint32_t layerCount,
+ uint64_t producerUsage, uint64_t consumerUsage,
+ std::string requestorName, status_t* error) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IGraphicBufferAlloc::getInterfaceDescriptor());
+ data.writeUint32(width);
+ data.writeUint32(height);
+ data.writeInt32(static_cast<int32_t>(format));
+ data.writeUint32(layerCount);
+ data.writeUint64(producerUsage);
+ data.writeUint64(consumerUsage);
+ if (requestorName.empty()) {
+ requestorName += "[PID ";
+ requestorName += std::to_string(getpid());
+ requestorName += ']';
+ }
+ data.writeUtf8AsUtf16(requestorName);
+ remote()->transact(CREATE_GRAPHIC_BUFFER, data, &reply);
+ sp<GraphicBuffer> graphicBuffer;
+ status_t result = reply.readInt32();
+ if (result == NO_ERROR) {
+ graphicBuffer = new GraphicBuffer();
+ result = reply.read(*graphicBuffer);
+ if (result != NO_ERROR) {
+ graphicBuffer.clear();
+ }
+ // reply.readStrongBinder();
+ // here we don't even have to read the BufferReference from
+ // the parcel, it'll die with the parcel.
+ }
+ *error = result;
+ return graphicBuffer;
+ }
+};
+
+// Out-of-line virtual method definition to trigger vtable emission in this
+// translation unit (see clang warning -Wweak-vtables)
+BpGraphicBufferAlloc::~BpGraphicBufferAlloc() {}
+
+IMPLEMENT_META_INTERFACE(GraphicBufferAlloc, "android.ui.IGraphicBufferAlloc");
+
+// ----------------------------------------------------------------------
+
+status_t BnGraphicBufferAlloc::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ // codes that don't require permission check
+
+ // BufferReference just keeps a strong reference to a GraphicBuffer until it
+ // is destroyed (that is, until no local or remote process have a reference
+ // to it).
+ class BufferReference : public BBinder {
+ sp<GraphicBuffer> mBuffer;
+ public:
+ explicit BufferReference(const sp<GraphicBuffer>& buffer) : mBuffer(buffer) {}
+ };
+
+
+ switch (code) {
+ case CREATE_GRAPHIC_BUFFER: {
+ CHECK_INTERFACE(IGraphicBufferAlloc, data, reply);
+ uint32_t width = data.readUint32();
+ uint32_t height = data.readUint32();
+ PixelFormat format = static_cast<PixelFormat>(data.readInt32());
+ uint32_t layerCount = data.readUint32();
+ uint64_t producerUsage = data.readUint64();
+ uint64_t consumerUsage = data.readUint64();
+ status_t error = NO_ERROR;
+ std::string requestorName;
+ data.readUtf8FromUtf16(&requestorName);
+ sp<GraphicBuffer> result = createGraphicBuffer(width, height,
+ format, layerCount, producerUsage, consumerUsage,
+ requestorName, &error);
+ reply->writeInt32(error);
+ if (result != 0) {
+ reply->write(*result);
+ // We add a BufferReference to this parcel to make sure the
+ // buffer stays alive until the GraphicBuffer object on
+ // the other side has been created.
+ // This is needed so that the buffer handle can be
+ // registered before the buffer is destroyed on implementations
+ // that do not use file-descriptors to track their buffers.
+ reply->writeStrongBinder( new BufferReference(result) );
+ }
+ return NO_ERROR;
+ }
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+}; // namespace android
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 2516fb8..4d2692f 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -25,6 +25,7 @@
#include <binder/IServiceManager.h>
#include <gui/IDisplayEventConnection.h>
+#include <gui/IGraphicBufferAlloc.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/ISurfaceComposer.h>
#include <gui/ISurfaceComposerClient.h>
@@ -71,6 +72,14 @@
return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
}
+ virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ remote()->transact(BnSurfaceComposer::CREATE_GRAPHIC_BUFFER_ALLOC, data, &reply);
+ return interface_cast<IGraphicBufferAlloc>(reply.readStrongBinder());
+ }
+
virtual void setTransactionState(
const Vector<ComposerState>& state,
const Vector<DisplayState>& displays,
@@ -496,6 +505,12 @@
reply->writeStrongBinder(b);
return NO_ERROR;
}
+ case CREATE_GRAPHIC_BUFFER_ALLOC: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ sp<IBinder> b = IInterface::asBinder(createGraphicBufferAlloc());
+ reply->writeStrongBinder(b);
+ return NO_ERROR;
+ }
case SET_TRANSACTION_STATE: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index be48c11..da6f13d 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -366,6 +366,9 @@
const sp<IGraphicBufferProducer>& /* parent */) override {
return nullptr;
}
+ sp<IGraphicBufferAlloc> createGraphicBufferAlloc() override {
+ return nullptr;
+ }
sp<IDisplayEventConnection> createDisplayEventConnection() override {
return nullptr;
}
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index e25e909..2d9fc93 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -69,7 +69,7 @@
if (err == NO_MEMORY) {
GraphicBuffer::dumpAllocationsToSystemLog();
}
- ALOGE("GraphicBuffer(w=%u, h=%u, lc=%u) failed (%s), handle=%p",
+ ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%u, h=%u, lc=%u) failed (%s), handle=%p",
desc->width, desc->height, desc->layers, strerror(-err), gbuffer->handle);
return err;
}
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index 34c136a..a85d16e 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -69,3 +69,20 @@
int32_t ANativeWindow_unlockAndPost(ANativeWindow* window) {
return window->perform(window, NATIVE_WINDOW_UNLOCK_AND_POST);
}
+
+int32_t ANativeWindow_setBuffersTransform(ANativeWindow* window, int32_t transform) {
+ static_assert(ANATIVEWINDOW_TRANSFORM_MIRROR_HORIZONTAL == NATIVE_WINDOW_TRANSFORM_FLIP_H);
+ static_assert(ANATIVEWINDOW_TRANSFORM_MIRROR_VERTICAL == NATIVE_WINDOW_TRANSFORM_FLIP_V);
+ static_assert(ANATIVEWINDOW_TRANSFORM_ROTATE_90 == NATIVE_WINDOW_TRANSFORM_ROT_90);
+
+ constexpr int32_t kAllTransformBits =
+ ANATIVEWINDOW_TRANSFORM_MIRROR_HORIZONTAL |
+ ANATIVEWINDOW_TRANSFORM_MIRROR_VERTICAL |
+ ANATIVEWINDOW_TRANSFORM_ROTATE_90;
+ if (!window || !getWindowProp(window, NATIVE_WINDOW_IS_VALID))
+ return -EINVAL;
+ if ((transform & ~kAllTransformBits) != 0)
+ return -EINVAL;
+
+ return native_window_set_buffers_transform(window, transform);
+}
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index 9c5f096..2668927 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -34,6 +34,10 @@
clang: true,
+ cppflags: [
+ "-std=c++1z"
+ ],
+
srcs: [
"AHardwareBuffer.cpp",
"ANativeWindow.cpp",
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index 6a46d7f..6cd5df3 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -50,6 +50,25 @@
WINDOW_FORMAT_RGB_565 = AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM,
};
+/**
+ * Transforms that can be applied to buffers as they are displayed to a window.
+ *
+ * Supported transforms are any combination of horizontal mirror, vertical
+ * mirror, and clockwise 90 degree rotation, in that order. Rotations of 180
+ * and 270 degrees are made up of those basic transforms.
+ */
+enum ANativeWindowTransform {
+ ANATIVEWINDOW_TRANSFORM_IDENTITY = 0x00,
+ ANATIVEWINDOW_TRANSFORM_MIRROR_HORIZONTAL = 0x01,
+ ANATIVEWINDOW_TRANSFORM_MIRROR_VERTICAL = 0x02,
+ ANATIVEWINDOW_TRANSFORM_ROTATE_90 = 0x04,
+
+ ANATIVEWINDOW_TRANSFORM_ROTATE_180 = ANATIVEWINDOW_TRANSFORM_MIRROR_HORIZONTAL |
+ ANATIVEWINDOW_TRANSFORM_MIRROR_VERTICAL,
+ ANATIVEWINDOW_TRANSFORM_ROTATE_270 = ANATIVEWINDOW_TRANSFORM_ROTATE_180 |
+ ANATIVEWINDOW_TRANSFORM_ROTATE_90,
+};
+
struct ANativeWindow;
/**
* {@link ANativeWindow} is opaque type that provides access to a native window.
@@ -147,6 +166,19 @@
*/
int32_t ANativeWindow_unlockAndPost(ANativeWindow* window);
+#if __ANDROID_API__ >= __ANDROID_API_O__
+
+/**
+ * Set a transform that will be applied to future buffers posted to the window.
+ *
+ * @param transform combination of {@link ANativeWindowTransform} flags
+ * @return 0 if successful
+ * @return -EINVAL if @param transform is invalid
+ */
+int32_t ANativeWindow_setBuffersTransform(ANativeWindow* window, int32_t transform);
+
+#endif // __ANDROID_API__ >= __ANDROID_API_O__
+
#ifdef __cplusplus
};
#endif
diff --git a/libs/nativewindow/libnativewindow.map.txt b/libs/nativewindow/libnativewindow.map.txt
index dcfabac..b29c888 100644
--- a/libs/nativewindow/libnativewindow.map.txt
+++ b/libs/nativewindow/libnativewindow.map.txt
@@ -20,6 +20,7 @@
ANativeWindow_lock;
ANativeWindow_release;
ANativeWindow_setBuffersGeometry;
+ ANativeWindow_setBuffersTransform;
ANativeWindow_unlockAndPost;
local:
*;
diff --git a/libs/ui/ColorSpace.cpp b/libs/ui/ColorSpace.cpp
index 6a86bb5..49390d9 100644
--- a/libs/ui/ColorSpace.cpp
+++ b/libs/ui/ColorSpace.cpp
@@ -211,8 +211,8 @@
"Display P3",
{{float2{0.680f, 0.320f}, {0.265f, 0.690f}, {0.150f, 0.060f}}},
{0.3127f, 0.3290f},
- std::bind(rcpResponse, _1, 2.4f, 1 / 1.055f, 0.055f / 1.055f, 1 / 12.92f, 0.04045f),
- std::bind(response, _1, 2.4f, 1 / 1.055f, 0.055f / 1.055f, 1 / 12.92f, 0.04045f)
+ std::bind(rcpResponse, _1, 2.4f, 1 / 1.055f, 0.055f / 1.055f, 1 / 12.92f, 0.039f),
+ std::bind(response, _1, 2.4f, 1 / 1.055f, 0.055f / 1.055f, 1 / 12.92f, 0.039f)
};
}
diff --git a/libs/vr/libdisplay/include/private/dvr/vsync_client_api.h b/libs/vr/libdisplay/include/private/dvr/vsync_client_api.h
index 4cdbc71..0ae5cd5 100644
--- a/libs/vr/libdisplay/include/private/dvr/vsync_client_api.h
+++ b/libs/vr/libdisplay/include/private/dvr/vsync_client_api.h
@@ -12,7 +12,7 @@
// The "dvr_vsync_client" structure wraps a client connection to the
// system vsync service. It is used to synchronize application drawing
// with the scanout of the display.
-typedef struct dvr_vsync_client dreamos_vsync_client;
+typedef struct dvr_vsync_client dvr_vsync_client;
// Creates a new client to the system vsync service.
dvr_vsync_client* dvr_vsync_client_create();
@@ -20,22 +20,14 @@
// Destroys the vsync client.
void dvr_vsync_client_destroy(dvr_vsync_client* client);
-// Blocks until the next vsync signal.
-// The timestamp (in ns) is written into |*timestamp_ns| when it is non-NULL.
-// Returns 0 upon success, or -errno.
-int dvr_vsync_client_wait(dvr_vsync_client* client, int64_t* timestamp_ns);
-
-// Returns the file descriptor used to communicate with the vsync service.
-int dvr_vsync_client_get_fd(dvr_vsync_client* client);
-
-// Clears the select/poll/epoll event so that subsequent calls to these
-// will not signal until the next vsync.
-int dvr_vsync_client_acknowledge(dvr_vsync_client* client);
-
-// Gets the timestamp of the last vsync signal in ns. This call has the
-// same side effects on events as acknowledge.
-int dvr_vsync_client_get_last_timestamp(dvr_vsync_client* client,
- int64_t* timestamp_ns);
+// Get the estimated timestamp of the next GPU lens warp preemption event in
+// ns. Also returns the corresponding vsync count that the next lens warp
+// operation will target. This call has the same side effect on events as
+// Acknowledge, which saves an IPC message.
+int dvr_vsync_client_get_sched_info(dvr_vsync_client* client,
+ int64_t* vsync_period_ns,
+ int64_t* next_timestamp_ns,
+ uint32_t* next_vsync_count);
#ifdef __cplusplus
} // extern "C"
diff --git a/libs/vr/libdisplay/vsync_client_api.cpp b/libs/vr/libdisplay/vsync_client_api.cpp
index 56103ed..00af525 100644
--- a/libs/vr/libdisplay/vsync_client_api.cpp
+++ b/libs/vr/libdisplay/vsync_client_api.cpp
@@ -13,22 +13,12 @@
delete static_cast<android::dvr::VSyncClient*>(client);
}
-int dvr_vsync_client_wait(dvr_vsync_client* client, int64_t* timestamp_ns) {
- return static_cast<android::dvr::VSyncClient*>(client)->Wait(timestamp_ns);
-}
-
-int dvr_vsync_client_get_fd(dvr_vsync_client* client) {
- return static_cast<android::dvr::VSyncClient*>(client)->GetFd();
-}
-
-int dvr_vsync_client_acknowledge(dvr_vsync_client* client) {
- return static_cast<android::dvr::VSyncClient*>(client)->Acknowledge();
-}
-
-int dvr_vsync_client_get_last_timestamp(dvr_vsync_client* client,
- int64_t* timestamp_ns) {
- return static_cast<android::dvr::VSyncClient*>(client)->GetLastTimestamp(
- timestamp_ns);
+int dvr_vsync_client_get_sched_info(dvr_vsync_client* client,
+ int64_t* vsync_period_ns,
+ int64_t* next_timestamp_ns,
+ uint32_t* next_vsync_count) {
+ return static_cast<android::dvr::VSyncClient*>(client)->GetSchedInfo(
+ vsync_period_ns, next_timestamp_ns, next_vsync_count);
}
} // extern "C"
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index aa67d41..6a62e8d 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -58,6 +58,8 @@
"-fvisibility=hidden",
],
shared_libs: [
+ // ***** DO NOT ADD NEW DEPENDENCIES HERE *****
+ // In particular, DO NOT add libutils or anything "above" libcutils
"libcutils",
"liblog",
"libdl",
@@ -77,9 +79,11 @@
"-DLOG_TAG=\"libEGL\"",
],
shared_libs: [
- "libutils",
+ // ***** DO NOT ADD NEW DEPENDENCIES HERE *****
+ // In particular, DO NOT add libutils nor anything "above" libui
"libui",
"libnativewindow",
+ "libbacktrace",
],
}
@@ -142,7 +146,6 @@
name: "libGLESv1_CM",
defaults: ["gles_libs_defaults"],
srcs: ["GLES_CM/gl.cpp"],
-
cflags: ["-DLOG_TAG=\"libGLESv1\""],
}
@@ -153,9 +156,6 @@
name: "libGLESv2",
defaults: ["gles_libs_defaults"],
srcs: ["GLES2/gl2.cpp"],
-
- shared_libs: ["libutils"],
-
cflags: ["-DLOG_TAG=\"libGLESv2\""],
}
@@ -166,8 +166,5 @@
name: "libGLESv3",
defaults: ["gles_libs_defaults"],
srcs: ["GLES2/gl2.cpp"],
-
- shared_libs: ["libutils"],
-
cflags: ["-DLOG_TAG=\"libGLESv3\""],
}
diff --git a/opengl/libs/EGL/CallStack.h b/opengl/libs/EGL/CallStack.h
new file mode 100644
index 0000000..0e2a9b3
--- /dev/null
+++ b/opengl/libs/EGL/CallStack.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <log/log.h>
+#include <backtrace/Backtrace.h>
+#include <memory>
+
+class CallStack {
+public:
+ // Create a callstack with the current thread's stack trace.
+ // Immediately dump it to logcat using the given logtag.
+ static void log(const char* logtag) noexcept {
+ std::unique_ptr<Backtrace> backtrace(
+ Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
+ if (backtrace->Unwind(2)) {
+ for (size_t i = 0, c = backtrace->NumFrames(); i < c; i++) {
+ __android_log_print(ANDROID_LOG_DEBUG, logtag, "%s",
+ backtrace->FormatFrameData(i).c_str());
+ }
+ }
+ }
+};
+
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index f44c1ca..f53cf3f 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -24,14 +24,13 @@
#include <log/log.h>
-#include <utils/CallStack.h>
-
#include "../egl_impl.h"
#include "egldefs.h"
#include "egl_tls.h"
#include "egl_display.h"
#include "egl_object.h"
+#include "CallStack.h"
#include "Loader.h"
typedef __eglMustCastToProperFunctionPointerType EGLFuncPointer;
@@ -65,7 +64,7 @@
char value[PROPERTY_VALUE_MAX];
property_get("debug.egl.callstack", value, "0");
if (atoi(value)) {
- CallStack stack(LOG_TAG);
+ CallStack::log(LOG_TAG);
}
}
return 0;
@@ -224,7 +223,7 @@
char value[PROPERTY_VALUE_MAX];
property_get("debug.egl.callstack", value, "0");
if (atoi(value)) {
- CallStack stack(LOG_TAG);
+ CallStack::log(LOG_TAG);
}
}
}
diff --git a/opengl/libs/EGL/egl_tls.cpp b/opengl/libs/EGL/egl_tls.cpp
index ca8684e..8508c5f 100644
--- a/opengl/libs/EGL/egl_tls.cpp
+++ b/opengl/libs/EGL/egl_tls.cpp
@@ -20,8 +20,7 @@
#include <cutils/properties.h>
#include <log/log.h>
-#include <utils/CallStack.h>
-
+#include "CallStack.h"
namespace android {
@@ -74,7 +73,7 @@
char value[PROPERTY_VALUE_MAX];
property_get("debug.egl.callstack", value, "0");
if (atoi(value)) {
- CallStack stack(LOG_TAG);
+ CallStack::log(LOG_TAG);
}
}
tls->error = error;
diff --git a/opengl/libs/EGL/getProcAddress.cpp b/opengl/libs/EGL/getProcAddress.cpp
index 450c402..c05e840 100644
--- a/opengl/libs/EGL/getProcAddress.cpp
+++ b/opengl/libs/EGL/getProcAddress.cpp
@@ -18,7 +18,7 @@
#include <errno.h>
#include <stdlib.h>
-#include <android/log.h>
+#include <log/log.h>
#include "egldefs.h"
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
index c206041..f7fde96 100644
--- a/opengl/libs/GLES2/gl2.cpp
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -19,7 +19,7 @@
#include <string.h>
#include <sys/ioctl.h>
-#include <android/log.h>
+#include <log/log.h>
#include <cutils/properties.h>
#include "../hooks.h"
diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp
index e698fcd..bacd4b4 100644
--- a/opengl/libs/GLES_CM/gl.cpp
+++ b/opengl/libs/GLES_CM/gl.cpp
@@ -19,7 +19,7 @@
#include <string.h>
#include <sys/ioctl.h>
-#include <android/log.h>
+#include <log/log.h>
#include <cutils/properties.h>
#include <GLES/gl.h>
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 92a7794..9a0e94e 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -32,6 +32,7 @@
#include <hardware/hardware.h>
#include <gui/BufferItem.h>
#include <gui/BufferQueue.h>
+#include <gui/GraphicBufferAlloc.h>
#include <gui/Surface.h>
#include <ui/GraphicBuffer.h>
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 51984b7..295b229 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -167,7 +167,7 @@
// Creates a custom BufferQueue for SurfaceFlingerConsumer to use
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer, true);
+ BufferQueue::createBufferQueue(&producer, &consumer, nullptr, true);
mProducer = new MonitoredProducer(producer, mFlinger, this);
mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName, this);
mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 3677c2e..e3a3ff4 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -44,6 +44,7 @@
#include <gui/GuiConfig.h>
#include <gui/IDisplayEventConnection.h>
#include <gui/Surface.h>
+#include <gui/GraphicBufferAlloc.h>
#include <ui/GraphicBufferAllocator.h>
#include <ui/PixelFormat.h>
@@ -325,6 +326,12 @@
return mBuiltinDisplays[id];
}
+sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
+{
+ sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
+ return gba;
+}
+
void SurfaceFlinger::bootFinished()
{
if (mStartBootAnimThread->join() != NO_ERROR) {
@@ -1130,7 +1137,8 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer);
+ BufferQueue::createBufferQueue(&producer, &consumer,
+ new GraphicBufferAlloc());
sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc,
DisplayDevice::DISPLAY_PRIMARY, consumer);
@@ -1891,7 +1899,8 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferProducer> bqProducer;
sp<IGraphicBufferConsumer> bqConsumer;
- BufferQueue::createBufferQueue(&bqProducer, &bqConsumer);
+ BufferQueue::createBufferQueue(&bqProducer, &bqConsumer,
+ new GraphicBufferAlloc());
int32_t hwcId = -1;
if (state.isVirtualDisplay()) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 11d7c6f..bfe0c9c 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -76,6 +76,7 @@
class Client;
class DisplayEventConnection;
class EventThread;
+class IGraphicBufferAlloc;
class Layer;
class LayerDim;
class Surface;
@@ -230,6 +231,7 @@
*/
virtual sp<ISurfaceComposerClient> createConnection();
virtual sp<ISurfaceComposerClient> createScopedConnection(const sp<IGraphicBufferProducer>& gbp);
+ virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc();
virtual sp<IBinder> createDisplay(const String8& displayName, bool secure);
virtual void destroyDisplay(const sp<IBinder>& display);
virtual sp<IBinder> getBuiltInDisplay(int32_t id);
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index f37fa6c..2932fc9 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -42,6 +42,7 @@
#include <gui/GuiConfig.h>
#include <gui/IDisplayEventConnection.h>
#include <gui/Surface.h>
+#include <gui/GraphicBufferAlloc.h>
#include <ui/GraphicBufferAllocator.h>
#include <ui/HdrCapabilities.h>
@@ -298,6 +299,12 @@
return mBuiltinDisplays[id];
}
+sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
+{
+ sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
+ return gba;
+}
+
void SurfaceFlinger::bootFinished()
{
if (mStartBootAnimThread->join() != NO_ERROR) {
@@ -534,7 +541,8 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer);
+ BufferQueue::createBufferQueue(&producer, &consumer,
+ new GraphicBufferAlloc());
sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
consumer);
@@ -1664,7 +1672,8 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferProducer> bqProducer;
sp<IGraphicBufferConsumer> bqConsumer;
- BufferQueue::createBufferQueue(&bqProducer, &bqConsumer);
+ BufferQueue::createBufferQueue(&bqProducer, &bqConsumer,
+ new GraphicBufferAlloc());
int32_t hwcDisplayId = -1;
if (state.isVirtualDisplay()) {
diff --git a/services/vr/virtual_touchpad/EvdevInjector.cpp b/services/vr/virtual_touchpad/EvdevInjector.cpp
index b4c0a52..a4ccdd0 100644
--- a/services/vr/virtual_touchpad/EvdevInjector.cpp
+++ b/services/vr/virtual_touchpad/EvdevInjector.cpp
@@ -308,9 +308,8 @@
}
void EvdevInjector::dumpInternal(String8& result) {
- result.append("[injector]\n");
- result.appendFormat("state = %d\n", static_cast<int>(state_));
- result.appendFormat("error = %d\n\n", error_);
+ result.appendFormat("injector_state = %d\n", static_cast<int>(state_));
+ result.appendFormat("injector_error = %d\n", error_);
}
} // namespace dvr
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
index bc29408..92193d3 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
@@ -18,7 +18,7 @@
// use it to look up device configuration, so it must be unique. Vendor and
// product values must be 0 to indicate an internal device and prevent a
// similar lookup that could conflict with a physical device.
-static const char* const kDeviceName = "vr window manager virtual touchpad";
+static const char* const kDeviceNameFormat = "vr virtual touchpad %d";
static constexpr int16_t kDeviceBusType = BUS_VIRTUAL;
static constexpr int16_t kDeviceVendor = 0;
static constexpr int16_t kDeviceProduct = 0;
@@ -32,122 +32,154 @@
sp<VirtualTouchpad> VirtualTouchpadEvdev::Create() {
VirtualTouchpadEvdev* const touchpad = new VirtualTouchpadEvdev();
+ touchpad->Reset();
return sp<VirtualTouchpad>(touchpad);
}
-status_t VirtualTouchpadEvdev::Attach() {
- if (!injector_) {
- owned_injector_.reset(new EvdevInjector());
- injector_ = owned_injector_.get();
+void VirtualTouchpadEvdev::Reset() {
+ for (auto& touchpad : touchpad_) {
+ if (touchpad.injector) {
+ touchpad.injector->Close();
+ }
+ touchpad.injector = nullptr;
+ touchpad.owned_injector.reset();
+ touchpad.last_device_x = INT32_MIN;
+ touchpad.last_device_y = INT32_MIN;
+ touchpad.touches = 0;
+ touchpad.last_motion_event_buttons = 0;
}
- injector_->ConfigureBegin(kDeviceName, kDeviceBusType, kDeviceVendor,
- kDeviceProduct, kDeviceVersion);
- injector_->ConfigureInputProperty(INPUT_PROP_DIRECT);
- injector_->ConfigureMultiTouchXY(0, 0, kWidth - 1, kHeight - 1);
- injector_->ConfigureAbsSlots(kSlots);
- injector_->ConfigureKey(BTN_TOUCH);
- injector_->ConfigureKey(BTN_BACK);
- injector_->ConfigureEnd();
- return injector_->GetError();
+}
+
+status_t VirtualTouchpadEvdev::Attach() {
+ status_t status = OK;
+ for (int i = 0; i < kTouchpads; ++i) {
+ Touchpad& touchpad = touchpad_[i];
+ if (!touchpad.injector) {
+ touchpad.owned_injector.reset(new EvdevInjector());
+ touchpad.injector = touchpad.owned_injector.get();
+ }
+ String8 DeviceName;
+ DeviceName.appendFormat(kDeviceNameFormat, i);
+ touchpad.injector->ConfigureBegin(DeviceName, kDeviceBusType,
+ kDeviceVendor, kDeviceProduct,
+ kDeviceVersion);
+ touchpad.injector->ConfigureInputProperty(INPUT_PROP_DIRECT);
+ touchpad.injector->ConfigureMultiTouchXY(0, 0, kWidth - 1, kHeight - 1);
+ touchpad.injector->ConfigureAbsSlots(kSlots);
+ touchpad.injector->ConfigureKey(BTN_TOUCH);
+ touchpad.injector->ConfigureKey(BTN_BACK);
+ touchpad.injector->ConfigureEnd();
+ if (const status_t configuration_status = touchpad.injector->GetError()) {
+ status = configuration_status;
+ }
+ }
+ return status;
}
status_t VirtualTouchpadEvdev::Detach() {
- injector_->Close();
- injector_ = nullptr;
- owned_injector_.reset();
- last_device_x_ = INT32_MIN;
- last_device_y_ = INT32_MIN;
- touches_ = 0;
- last_motion_event_buttons_ = 0;
+ Reset();
return OK;
}
-int VirtualTouchpadEvdev::Touch(int touchpad, float x, float y,
+int VirtualTouchpadEvdev::Touch(int touchpad_id, float x, float y,
float pressure) {
- (void)touchpad; // TODO(b/35992608) Support multiple touchpad devices.
+ if (touchpad_id < 0 || touchpad_id >= kTouchpads) {
+ return EINVAL;
+ }
if ((x < 0.0f) || (x >= 1.0f) || (y < 0.0f) || (y >= 1.0f)) {
return EINVAL;
}
int32_t device_x = x * kWidth;
int32_t device_y = y * kHeight;
- touches_ = ((touches_ & 1) << 1) | (pressure > 0);
+ Touchpad& touchpad = touchpad_[touchpad_id];
+ touchpad.touches = ((touchpad.touches & 1) << 1) | (pressure > 0);
ALOGV("(%f,%f) %f -> (%" PRId32 ",%" PRId32 ") %d", x, y, pressure, device_x,
- device_y, touches_);
+ device_y, touchpad.touches);
- if (!injector_) {
+ if (!touchpad.injector) {
return EvdevInjector::ERROR_SEQUENCING;
}
- injector_->ResetError();
- switch (touches_) {
+ touchpad.injector->ResetError();
+ switch (touchpad.touches) {
case 0b00: // Hover continues.
- if (device_x != last_device_x_ || device_y != last_device_y_) {
- injector_->SendMultiTouchXY(0, 0, device_x, device_y);
- injector_->SendSynReport();
+ if (device_x != touchpad.last_device_x ||
+ device_y != touchpad.last_device_y) {
+ touchpad.injector->SendMultiTouchXY(0, 0, device_x, device_y);
+ touchpad.injector->SendSynReport();
}
break;
case 0b01: // Touch begins.
// Press.
- injector_->SendMultiTouchXY(0, 0, device_x, device_y);
- injector_->SendKey(BTN_TOUCH, EvdevInjector::KEY_PRESS);
- injector_->SendSynReport();
+ touchpad.injector->SendMultiTouchXY(0, 0, device_x, device_y);
+ touchpad.injector->SendKey(BTN_TOUCH, EvdevInjector::KEY_PRESS);
+ touchpad.injector->SendSynReport();
break;
case 0b10: // Touch ends.
- injector_->SendKey(BTN_TOUCH, EvdevInjector::KEY_RELEASE);
- injector_->SendMultiTouchLift(0);
- injector_->SendSynReport();
+ touchpad.injector->SendKey(BTN_TOUCH, EvdevInjector::KEY_RELEASE);
+ touchpad.injector->SendMultiTouchLift(0);
+ touchpad.injector->SendSynReport();
break;
case 0b11: // Touch continues.
- if (device_x != last_device_x_ || device_y != last_device_y_) {
- injector_->SendMultiTouchXY(0, 0, device_x, device_y);
- injector_->SendSynReport();
+ if (device_x != touchpad.last_device_x ||
+ device_y != touchpad.last_device_y) {
+ touchpad.injector->SendMultiTouchXY(0, 0, device_x, device_y);
+ touchpad.injector->SendSynReport();
}
break;
}
- last_device_x_ = device_x;
- last_device_y_ = device_y;
+ touchpad.last_device_x = device_x;
+ touchpad.last_device_y = device_y;
- return injector_->GetError();
+ return touchpad.injector->GetError();
}
-int VirtualTouchpadEvdev::ButtonState(int touchpad, int buttons) {
- (void)touchpad; // TODO(b/35992608) Support multiple touchpad devices.
- const int changes = last_motion_event_buttons_ ^ buttons;
+int VirtualTouchpadEvdev::ButtonState(int touchpad_id, int buttons) {
+ if (touchpad_id < 0 || touchpad_id >= kTouchpads) {
+ return EINVAL;
+ }
+ Touchpad& touchpad = touchpad_[touchpad_id];
+ const int changes = touchpad.last_motion_event_buttons ^ buttons;
if (!changes) {
return 0;
}
if (buttons & ~AMOTION_EVENT_BUTTON_BACK) {
return ENOTSUP;
}
- ALOGV("change %X from %X to %X", changes, last_motion_event_buttons_,
+ ALOGV("change %X from %X to %X", changes, touchpad.last_motion_event_buttons,
buttons);
- if (!injector_) {
+ if (!touchpad.injector) {
return EvdevInjector::ERROR_SEQUENCING;
}
- injector_->ResetError();
+ touchpad.injector->ResetError();
if (changes & AMOTION_EVENT_BUTTON_BACK) {
- injector_->SendKey(BTN_BACK, (buttons & AMOTION_EVENT_BUTTON_BACK)
- ? EvdevInjector::KEY_PRESS
- : EvdevInjector::KEY_RELEASE);
- injector_->SendSynReport();
+ touchpad.injector->SendKey(BTN_BACK, (buttons & AMOTION_EVENT_BUTTON_BACK)
+ ? EvdevInjector::KEY_PRESS
+ : EvdevInjector::KEY_RELEASE);
+ touchpad.injector->SendSynReport();
}
- last_motion_event_buttons_ = buttons;
- return injector_->GetError();
+ touchpad.last_motion_event_buttons = buttons;
+ return touchpad.injector->GetError();
}
void VirtualTouchpadEvdev::dumpInternal(String8& result) {
- result.append("[virtual touchpad]\n");
- if (!injector_) {
- result.append("injector = none\n");
- return;
+ for (int i = 0; i < kTouchpads; ++i) {
+ const auto& touchpad = touchpad_[i];
+ result.appendFormat("[virtual touchpad %d]\n", i);
+ if (!touchpad.injector) {
+ result.append("injector = none\n");
+ return;
+ }
+ result.appendFormat("injector = %s\n",
+ touchpad.owned_injector ? "normal" : "test");
+ result.appendFormat("touches = %d\n", touchpad.touches);
+ result.appendFormat("last_position = (%" PRId32 ", %" PRId32 ")\n",
+ touchpad.last_device_x, touchpad.last_device_y);
+ result.appendFormat("last_buttons = 0x%" PRIX32 "\n",
+ touchpad.last_motion_event_buttons);
+ touchpad.injector->dumpInternal(result);
+ result.append("\n");
}
- result.appendFormat("injector = %s\n", owned_injector_ ? "normal" : "test");
- result.appendFormat("touches = %d\n", touches_);
- result.appendFormat("last_position = (%" PRId32 ", %" PRId32 ")\n",
- last_device_x_, last_device_y_);
- result.appendFormat("last_buttons = 0x%" PRIX32 "\n\n",
- last_motion_event_buttons_);
- injector_->dumpInternal(result);
}
} // namespace dvr
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h
index b158cec..dbaca9a 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h
+++ b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h
@@ -3,8 +3,8 @@
#include <memory>
-#include "VirtualTouchpad.h"
#include "EvdevInjector.h"
+#include "VirtualTouchpad.h"
namespace android {
namespace dvr {
@@ -25,31 +25,39 @@
void dumpInternal(String8& result) override;
protected:
+ static constexpr int kTouchpads = 2;
+
VirtualTouchpadEvdev() {}
~VirtualTouchpadEvdev() override {}
+ void Reset();
- // Must be called only between construction and Attach().
- inline void SetEvdevInjectorForTesting(EvdevInjector* injector) {
- injector_ = injector;
+ // Must be called only between construction (or Detach()) and Attach().
+ inline void SetEvdevInjectorForTesting(int touchpad,
+ EvdevInjector* injector) {
+ touchpad_[touchpad].injector = injector;
}
private:
- // Except for testing, the |EvdevInjector| used to inject evdev events.
- std::unique_ptr<EvdevInjector> owned_injector_;
+ // Per-touchpad state.
+ struct Touchpad {
+ // Except for testing, the |EvdevInjector| used to inject evdev events.
+ std::unique_ptr<EvdevInjector> owned_injector;
- // Active pointer to |owned_injector_| or to a testing injector.
- EvdevInjector* injector_ = nullptr;
+ // Active pointer to |owned_injector_| or to a testing injector.
+ EvdevInjector* injector = nullptr;
- // Previous (x, y) position in device space, to suppress redundant events.
- int32_t last_device_x_ = INT32_MIN;
- int32_t last_device_y_ = INT32_MIN;
+ // Previous (x, y) position in device space, to suppress redundant events.
+ int32_t last_device_x;
+ int32_t last_device_y;
- // Records current touch state (0=up 1=down) in bit 0, and previous state
- // in bit 1, to track transitions.
- int touches_ = 0;
+ // Records current touch state (0=up 1=down) in bit 0, and previous state
+ // in bit 1, to track transitions.
+ int touches;
- // Previous injected button state, to detect changes.
- int32_t last_motion_event_buttons_ = 0;
+ // Previous injected button state, to detect changes.
+ int32_t last_motion_event_buttons;
+ };
+ Touchpad touchpad_[kTouchpads];
VirtualTouchpadEvdev(const VirtualTouchpadEvdev&) = delete;
void operator=(const VirtualTouchpadEvdev&) = delete;
diff --git a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp b/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
index b11a983..bc34850 100644
--- a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
+++ b/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
@@ -88,17 +88,24 @@
class EvdevInjectorForTesting : public EvdevInjector {
public:
- EvdevInjectorForTesting(UInput& uinput) { SetUInputForTesting(&uinput); }
+ EvdevInjectorForTesting() { SetUInputForTesting(&record); }
const uinput_user_dev* GetUiDev() const { return GetUiDevForTesting(); }
+ UInputRecorder record;
};
class VirtualTouchpadForTesting : public VirtualTouchpadEvdev {
public:
- static sp<VirtualTouchpad> Create(EvdevInjectorForTesting& injector) {
+ static sp<VirtualTouchpad> Create() { return sp<VirtualTouchpad>(New()); }
+ static VirtualTouchpadForTesting* New() {
VirtualTouchpadForTesting* const touchpad = new VirtualTouchpadForTesting();
- touchpad->SetEvdevInjectorForTesting(&injector);
- return sp<VirtualTouchpad>(touchpad);
+ touchpad->Reset();
+ for (int t = 0; t < kTouchpads; ++t) {
+ touchpad->SetEvdevInjectorForTesting(t, &touchpad->injector[t]);
+ }
+ return touchpad;
}
+ int GetTouchpadCount() const { return kTouchpads; }
+ EvdevInjectorForTesting injector[kTouchpads];
};
void DumpDifference(const char* expect, const char* actual) {
@@ -117,133 +124,169 @@
class VirtualTouchpadTest : public testing::Test {};
TEST_F(VirtualTouchpadTest, Goodness) {
+ sp<VirtualTouchpadForTesting> touchpad(VirtualTouchpadForTesting::New());
UInputRecorder expect;
- UInputRecorder record;
- EvdevInjectorForTesting injector(record);
- sp<VirtualTouchpad> touchpad(VirtualTouchpadForTesting::Create(injector));
status_t touch_status = touchpad->Attach();
EXPECT_EQ(0, touch_status);
// Check some aspects of uinput_user_dev.
- const uinput_user_dev* uidev = injector.GetUiDev();
- for (int i = 0; i < ABS_CNT; ++i) {
- EXPECT_EQ(0, uidev->absmin[i]);
- EXPECT_EQ(0, uidev->absfuzz[i]);
- EXPECT_EQ(0, uidev->absflat[i]);
- if (i != ABS_MT_POSITION_X && i != ABS_MT_POSITION_Y && i != ABS_MT_SLOT) {
- EXPECT_EQ(0, uidev->absmax[i]);
+ const uinput_user_dev* uidev;
+ for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
+ SCOPED_TRACE(t);
+ uidev = touchpad->injector[t].GetUiDev();
+ String8 name;
+ name.appendFormat("vr virtual touchpad %d", t);
+ EXPECT_EQ(name, uidev->name);
+ for (int i = 0; i < ABS_CNT; ++i) {
+ EXPECT_EQ(0, uidev->absmin[i]);
+ EXPECT_EQ(0, uidev->absfuzz[i]);
+ EXPECT_EQ(0, uidev->absflat[i]);
+ if (i != ABS_MT_POSITION_X && i != ABS_MT_POSITION_Y &&
+ i != ABS_MT_SLOT) {
+ EXPECT_EQ(0, uidev->absmax[i]);
+ }
}
}
const int32_t width = 1 + uidev->absmax[ABS_MT_POSITION_X];
const int32_t height = 1 + uidev->absmax[ABS_MT_POSITION_Y];
const int32_t slots = uidev->absmax[ABS_MT_SLOT];
- // Check the system calls performed by initialization.
- // From ConfigureBegin():
- expect.Open();
- // From ConfigureInputProperty(INPUT_PROP_DIRECT):
- expect.IoctlSetInt(UI_SET_PROPBIT, INPUT_PROP_DIRECT);
- // From ConfigureMultiTouchXY(0, 0, kWidth - 1, kHeight - 1):
- expect.IoctlSetInt(UI_SET_EVBIT, EV_ABS);
- expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_POSITION_X);
- expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_POSITION_Y);
- // From ConfigureAbsSlots(kSlots):
- expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_SLOT);
- // From ConfigureKey(BTN_TOUCH):
- expect.IoctlSetInt(UI_SET_EVBIT, EV_KEY);
- expect.IoctlSetInt(UI_SET_KEYBIT, BTN_TOUCH);
- expect.IoctlSetInt(UI_SET_KEYBIT, BTN_BACK);
- // From ConfigureEnd():
- expect.Write(uidev, sizeof(uinput_user_dev));
- expect.IoctlVoid(UI_DEV_CREATE);
- EXPECT_EQ(expect.GetString(), record.GetString());
+ for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
+ SCOPED_TRACE(t);
+ // Check the system calls performed by initialization.
+ expect.Reset();
+ // From ConfigureBegin():
+ expect.Open();
+ // From ConfigureInputProperty(INPUT_PROP_DIRECT):
+ expect.IoctlSetInt(UI_SET_PROPBIT, INPUT_PROP_DIRECT);
+ // From ConfigureMultiTouchXY(0, 0, kWidth - 1, kHeight - 1):
+ expect.IoctlSetInt(UI_SET_EVBIT, EV_ABS);
+ expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_POSITION_X);
+ expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_POSITION_Y);
+ // From ConfigureAbsSlots(kSlots):
+ expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_SLOT);
+ // From ConfigureKey(BTN_TOUCH):
+ expect.IoctlSetInt(UI_SET_EVBIT, EV_KEY);
+ expect.IoctlSetInt(UI_SET_KEYBIT, BTN_TOUCH);
+ expect.IoctlSetInt(UI_SET_KEYBIT, BTN_BACK);
+ // From ConfigureEnd():
+ expect.Write(touchpad->injector[t].GetUiDev(), sizeof(uinput_user_dev));
+ expect.IoctlVoid(UI_DEV_CREATE);
+ EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
+ }
expect.Reset();
- record.Reset();
- touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0, 0, 0);
- EXPECT_EQ(0, touch_status);
expect.WriteInputEvent(EV_ABS, ABS_MT_SLOT, 0);
expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0);
expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0);
expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0);
expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
- EXPECT_EQ(expect.GetString(), record.GetString());
+ for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
+ SCOPED_TRACE(t);
+ touchpad->injector[t].record.Reset();
+ touch_status = touchpad->Touch(t, 0, 0, 0);
+ EXPECT_EQ(0, touch_status);
+ EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
+ }
expect.Reset();
- record.Reset();
- touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0.25f, 0.75f, 0.5f);
- EXPECT_EQ(0, touch_status);
expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0);
expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0.25f * width);
expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0.75f * height);
expect.WriteInputEvent(EV_KEY, BTN_TOUCH, EvdevInjector::KEY_PRESS);
expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
- EXPECT_EQ(expect.GetString(), record.GetString());
+ for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
+ SCOPED_TRACE(t);
+ touchpad->injector[t].record.Reset();
+ touch_status = touchpad->Touch(t, 0.25f, 0.75f, 0.5f);
+ EXPECT_EQ(0, touch_status);
+ EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
+ }
expect.Reset();
- record.Reset();
- touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0.99f, 0.99f, 0.99f);
- EXPECT_EQ(0, touch_status);
expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0);
expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0.99f * width);
expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0.99f * height);
expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
- EXPECT_EQ(expect.GetString(), record.GetString());
+ for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
+ SCOPED_TRACE(t);
+ touchpad->injector[t].record.Reset();
+ touch_status = touchpad->Touch(t, 0.99f, 0.99f, 0.99f);
+ EXPECT_EQ(0, touch_status);
+ EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
+ }
expect.Reset();
- record.Reset();
- touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 1.0f, 1.0f, 1.0f);
- EXPECT_EQ(EINVAL, touch_status);
- EXPECT_EQ(expect.GetString(), record.GetString());
+ for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
+ SCOPED_TRACE(t);
+ touchpad->injector[t].record.Reset();
+ touch_status = touchpad->Touch(t, 1.0f, 1.0f, 1.0f);
+ EXPECT_EQ(EINVAL, touch_status);
+ EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
+ }
expect.Reset();
- record.Reset();
- touch_status =
- touchpad->Touch(VirtualTouchpad::PRIMARY, 0.25f, 0.75f, -0.01f);
- EXPECT_EQ(0, touch_status);
expect.WriteInputEvent(EV_KEY, BTN_TOUCH, EvdevInjector::KEY_RELEASE);
expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, -1);
expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
- EXPECT_EQ(expect.GetString(), record.GetString());
+ for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
+ SCOPED_TRACE(t);
+ touchpad->injector[t].record.Reset();
+ touch_status = touchpad->Touch(t, 0.25f, 0.75f, -0.01f);
+ EXPECT_EQ(0, touch_status);
+ EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
+ }
expect.Reset();
- record.Reset();
- touch_status = touchpad->ButtonState(VirtualTouchpad::PRIMARY,
- AMOTION_EVENT_BUTTON_BACK);
- EXPECT_EQ(0, touch_status);
expect.WriteInputEvent(EV_KEY, BTN_BACK, EvdevInjector::KEY_PRESS);
expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
- EXPECT_EQ(expect.GetString(), record.GetString());
+ for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
+ SCOPED_TRACE(t);
+ touchpad->injector[t].record.Reset();
+ touch_status = touchpad->ButtonState(t, AMOTION_EVENT_BUTTON_BACK);
+ EXPECT_EQ(0, touch_status);
+ EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
+ }
expect.Reset();
- record.Reset();
- touch_status = touchpad->ButtonState(VirtualTouchpad::PRIMARY,
- AMOTION_EVENT_BUTTON_BACK);
- EXPECT_EQ(0, touch_status);
- EXPECT_EQ(expect.GetString(), record.GetString());
+ for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
+ SCOPED_TRACE(t);
+ touchpad->injector[t].record.Reset();
+ touch_status = touchpad->ButtonState(t, AMOTION_EVENT_BUTTON_BACK);
+ EXPECT_EQ(0, touch_status);
+ EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
+ }
expect.Reset();
- record.Reset();
- touch_status = touchpad->ButtonState(VirtualTouchpad::PRIMARY, 0);
- EXPECT_EQ(0, touch_status);
expect.WriteInputEvent(EV_KEY, BTN_BACK, EvdevInjector::KEY_RELEASE);
expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
- EXPECT_EQ(expect.GetString(), record.GetString());
+ for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
+ SCOPED_TRACE(t);
+ touchpad->injector[t].record.Reset();
+ touch_status = touchpad->ButtonState(t, 0);
+ EXPECT_EQ(0, touch_status);
+ EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
+ }
expect.Reset();
- record.Reset();
+ expect.Close();
+ for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
+ SCOPED_TRACE(t);
+ touchpad->injector[t].record.Reset();
+ }
touch_status = touchpad->Detach();
EXPECT_EQ(0, touch_status);
- expect.Close();
- EXPECT_EQ(expect.GetString(), record.GetString());
+ for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
+ SCOPED_TRACE(t);
+ EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString());
+ }
}
TEST_F(VirtualTouchpadTest, Badness) {
+ sp<VirtualTouchpadForTesting> touchpad(VirtualTouchpadForTesting::New());
UInputRecorder expect;
- UInputRecorder record;
- EvdevInjectorForTesting injector(record);
- sp<VirtualTouchpad> touchpad(VirtualTouchpadForTesting::Create(injector));
+ UInputRecorder& record = touchpad->injector[VirtualTouchpad::PRIMARY].record;
status_t touch_status = touchpad->Attach();
EXPECT_EQ(0, touch_status);
@@ -252,11 +295,9 @@
// and should not result in any system calls.
expect.Reset();
record.Reset();
- touch_status =
- touchpad->Touch(VirtualTouchpad::PRIMARY, -0.25f, 0.75f, 1.0f);
+ touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, -0.25f, 0.75f, 1.0f);
EXPECT_NE(OK, touch_status);
- touch_status =
- touchpad->Touch(VirtualTouchpad::PRIMARY, 0.25f, -0.75f, 1.0f);
+ touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0.25f, -0.75f, 1.0f);
EXPECT_NE(OK, touch_status);
touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 1.25f, 0.75f, 1.0f);
EXPECT_NE(OK, touch_status);
diff --git a/services/vr/vr_window_manager/application.cpp b/services/vr/vr_window_manager/application.cpp
index 24087c9..dba797f 100644
--- a/services/vr/vr_window_manager/application.cpp
+++ b/services/vr/vr_window_manager/application.cpp
@@ -294,10 +294,7 @@
bool changed = is_visible_ != visible;
if (changed) {
is_visible_ = visible;
- // TODO (alexst): b/36036583 Disable vr_wm visibility until we figure out
- // why it's always on top. Still make it visible in debug mode.
- if (debug_mode_)
- dvrGraphicsSurfaceSetVisible(graphics_context_, is_visible_);
+ dvrGraphicsSurfaceSetVisible(graphics_context_, is_visible_);
OnVisibilityChanged(is_visible_);
}
}
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 6a78c98..bd801f0 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
+++ b/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
@@ -301,10 +301,10 @@
switch (attribute) {
case IComposerClient::Attribute::WIDTH:
- *outValue = 1920;
+ *outValue = 1080;
break;
case IComposerClient::Attribute::HEIGHT:
- *outValue = 1080;
+ *outValue = 1920;
break;
case IComposerClient::Attribute::VSYNC_PERIOD:
*outValue = 1000 * 1000 * 1000 / 30; // 30fps
diff --git a/services/vr/vr_window_manager/shell_view.cpp b/services/vr/vr_window_manager/shell_view.cpp
index 10588b7..03d582c 100644
--- a/services/vr/vr_window_manager/shell_view.cpp
+++ b/services/vr/vr_window_manager/shell_view.cpp
@@ -15,7 +15,7 @@
namespace {
-constexpr float kLayerScaleFactor = 4.0f;
+constexpr float kLayerScaleFactor = 3.0f;
constexpr unsigned int kVRAppLayerCount = 2;
@@ -131,7 +131,7 @@
m(3, 0) = 0.0f; m(3, 1) = 0.0f; m(3, 2) = 0.0f; m(3, 3) = 1.0f;
// clang-format on
- return m * Eigen::AngleAxisf(M_PI * 0.5f, vec3::UnitZ());
+ return m;
}
// Helper function that applies the crop transform to the texture layer and
@@ -195,27 +195,27 @@
uint32_t vr_app) {
auto& layers = frame.layers();
- // We assume the first two layers are the VR app. In the case of a 2D app,
- // there will be the app + at least one system layer so this is still safe.
- if (layers.size() < kVRAppLayerCount)
+ // TODO(achaulk): Figure out how to identify the current VR app for 2D app
+ // detection.
+
+ size_t index;
+ // Skip all layers that we don't know about.
+ for (index = 0; index < layers.size(); index++) {
+ if (layers[index].type != 0xFFFFFFFF && layers[index].type != 0)
+ break;
+ }
+
+ if (index == layers.size())
return ViewMode::Hidden;
- if (vr_app != layers[0].appid || layers[0].appid == 0 ||
- layers[1].appid != layers[0].appid) {
- if (layers[1].appid != layers[0].appid && layers[0].appid) {
- // This might be a 2D app.
- // If a dim layer exists afterwards it is much more likely that this is
- // actually an app launch artifact.
- for (size_t i = 2; i < layers.size(); i++) {
- if (layers[i].is_extra_layer())
- return ViewMode::Hidden;
- }
- return ViewMode::App;
- }
+ if (layers[index].type != 1) {
+ // We don't have a VR app layer? Abort.
return ViewMode::Hidden;
}
- size_t index = kVRAppLayerCount;
+ // This is the VR app, ignore it.
+ index++;
+
// Now, find a dim layer if it exists.
// If it does, ignore any layers behind it for visibility determination.
for (size_t i = index; i < layers.size(); i++) {
@@ -712,10 +712,12 @@
return;
}
+ // Device is portrait, but in landscape when in VR.
+ // Rotate touch input appropriately.
const android::status_t status = virtual_touchpad_->Touch(
VirtualTouchpad::PRIMARY,
+ 1.0f - hit_location_in_window_coord_.y() / size_.y(),
hit_location_in_window_coord_.x() / size_.x(),
- hit_location_in_window_coord_.y() / size_.y(),
is_touching_ ? 1.0f : 0.0f);
if (status != OK) {
ALOGE("touch failed: %d", status);
diff --git a/services/vr/vr_window_manager/surface_flinger_view.cpp b/services/vr/vr_window_manager/surface_flinger_view.cpp
index 63bc143..2011967 100644
--- a/services/vr/vr_window_manager/surface_flinger_view.cpp
+++ b/services/vr/vr_window_manager/surface_flinger_view.cpp
@@ -54,9 +54,7 @@
size_t start = 0;
// Skip the second layer if it is from the VR app.
if (!debug && skip_first_layer) {
- start = 1;
- if (layers[0].appid && layers[0].appid == layers[1].appid)
- start = 2;
+ start = 2;
}
for (size_t i = start; i < layers.size(); ++i) {
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index a0ae1f3..47404d5 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -903,8 +903,7 @@
int gralloc_usage = 0;
if (dispatch.GetSwapchainGrallocUsage2ANDROID) {
uint64_t consumer_usage, producer_usage;
- uint32_t driver_version = GetData(device).driver_version;
- if (driver_version == 256587285 || driver_version == 96011958) {
+ if (GetData(device).driver_version == 256587285) {
// HACK workaround for loader/driver mismatch during transition to
// vkGetSwapchainGrallocUsage2ANDROID.
typedef VkResult(VKAPI_PTR *